diff --git a/Chopperman.psd b/Chopperman.psd new file mode 100644 index 000000000..050e68187 Binary files /dev/null and b/Chopperman.psd differ diff --git a/README.md b/README.md new file mode 100644 index 000000000..edac4f63d --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +# optc-db.github.io + +The Continuation of the highly loved and apreciated OPTC Database. + +This is a Database for all things One Piece Treasure Cruise, including Stats, Drops, Sockets and a Damage Calculator. + +This project is written in html and js, using angular, bootstrap and jquery. + +It is hosted on github pages, although you can just download it and run a local copy. + +# Team + +* Mondfischer - Took over the Project and responsible for adding features and data +* Zeenigami - Joined shorty after and helps out with data and features (And usually adds the newest Units) +* xfts - The newest member for fact checking and everything concerning translations +* Everyone else on Discord/Reddit/Github etc that reports errors and wrong data + +# Installation + +Just download it and run it in some kind of Live preview or via xampp. Or better yet access it via http://optc-db.github.io + +Keep in mind though that the images are not hosted here, but instead linked from the offical site. So you would need an internet connection to see them. + +# Contact + You can reach us on Discord @Mondfischer and @Zeenigami and on Reddit as Mondfischer and Zee_n1 + + The site also has a google contact form, you can also open an Issue on here. + +# License + + GNU General Public License + + It's also in the Project named LICENSE.md. diff --git a/characters/css/edgy.css b/characters/css/edgy.css index e267634f0..b2a91d43c 100644 --- a/characters/css/edgy.css +++ b/characters/css/edgy.css @@ -131,3 +131,10 @@ a:hover { color: #53dccd; } .pagination > li:hover > a { color: white; } + +@media (max-width: 1024px) { + #rightContainer { + background: #404040; + } + +} diff --git a/characters/css/index.css b/characters/css/index.css index 8cc1bc777..7397aad68 100644 --- a/characters/css/index.css +++ b/characters/css/index.css @@ -1,3 +1,14 @@ +/* +Enable for April First +#rightContainer { +-moz-transform: scale(1, -1); +-webkit-transform: scale(1, -1); +-o-transform: scale(1, -1); +-ms-transform: scale(1, -1); +transform: scale(1, -1); +} +*/ + @font-face { font-family: 'icomoon'; src:url('../../res/icomoon.eot?xewvs9'); @@ -113,16 +124,18 @@ input[type="text"] { height: 73px; } -.STR { background: salmon; } -.QCK { background: lightskyblue; } -.DEX { background: lightgreen; } -.PSY { background: gold; } -.INT { background: orchid; } -.RCV { background: sandybrown; } -.TND { background: peru; } -.BLOCK { background: darkslateblue; } -.BOMB { background: maroon; } -.G { background: orange; } +.STR { background: salmon; } +.QCK { background: lightskyblue; } +.DEX { background: lightgreen; } +.PSY { background: gold; } +.INT { background: orchid; } +.RCV { background: sandybrown; } +.TND { background: peru; } +.BLOCK { background: darkslateblue; } +.BOMB { background: maroon; } +.RAINBOW { background: magenta; } +.G { background: orange; } +.EMPTY { background: #777; } .cell-STR { font-weight: bold; color: red; } .cell-QCK { font-weight: bold; color: blue; } @@ -139,39 +152,69 @@ input[type="text"] { margin-right: 5px; } -.badge-japan + div, .badge-global + div { +.badge-base { + float: left; + position: relative; + top: 2px; + width: 125px; + text-align: center; + margin-right: 5px; +} + +.badge-level1, .badge-level2, .badge-level3, .badge-level4, .badge-level5, .badge-level6 { + float: left; + position: relative; + top: 2px; + width: 200px; + text-align: center; + margin-right: 5px; +} + +.badge-japan + div, .badge-global + div, .badge-base + div, .badge-level1 + div, .badge-level2 + div, .badge-level3 + div, .badge-level4 + div, .badge-level5 + div, .badge-level6 + div { margin-bottom: 2px; } .badge-japan { background: mediumvioletred; } .badge-global { background: rebeccapurple; } +.badge-base { background: darkred; } +.badge-level1 { background: crimson; } +.badge-level2 { background: crimson; } +.badge-level3 { background: crimson; } +.badge-level4 { background: crimson; } +.badge-level5 { background: crimson; } +.badge-level6 { background: crimson; } .stars:before, .stars:after { font-weight: bold; font-family: icomoon; - font-size: 11px; + font-size: 13px; } .filter.stars:not(.active):not(:hover):before { color: #cccccc !important; } -.stars-1:before { color: #40a3da; content: '\e900'; } -.stars-1:after { color: #cccccc; content: '\e900\e900\e900\e900\e900'; } +.stars-1:before { color: #40a3da; content: '\2605'; } +.stars-1:after { color: #cccccc; content: '\2605\2605\2605\2605\2605'; } + +.stars-2:before { color: #acc523; content: '\2605\2605'; } +.stars-2:after { color: #cccccc; content: '\2605\2605\2605\2605'; } -.stars-2:before { color: #acc523; content: '\e900\e900'; } -.stars-2:after { color: #cccccc; content: '\e900\e900\e900\e900'; } +.stars-3:before { color: #f7c118; content: '\2605\2605\2605'; } +.stars-3:after { color: #cccccc; content: '\2605\2605\2605'; } -.stars-3:before { color: #f7c118; content: '\e900\e900\e900'; } -.stars-3:after { color: #cccccc; content: '\e900\e900\e900'; } +.stars-4:before { color: #f28e00; content: '\2605\2605\2605\2605'; } +.stars-4:after { color: #cccccc; content: '\2605\2605'; } -.stars-4:before { color: #f28e00; content: '\e900\e900\e900\e900'; } -.stars-4:after { color: #cccccc; content: '\e900\e900'; } +.stars-5:before { color: #ff0000; content: '\2605\2605\2605\2605\2605'; } +.stars-5:after { color: #cccccc; content: '\2605'; } -.stars-5:before { color: #ff0000; content: '\e900\e900\e900\e900\e900'; } -.stars-5:after { color: #cccccc; content: '\e900'; } +*[class~="stars-5+"]:before { color: #ff1493; content: '\2605\2605\2605\2605\2605\002B'; } + +.stars-6:before { color: #9932cc; content: '\2605\2605\2605\2605\2605\2605'; } + +*[class~="stars-6+"]:before { color: #990000; content: '\2605\2605\2605\2605\2605\2605\002B'; } -.stars-6:before { color: #9932cc; content: '\e900\e900\e900\e900\e900\e900'; } .block-icon:before, .tnd-icon:before { font-style: normal; @@ -315,7 +358,7 @@ input[type="text"] { } #controllers > span:not(.separator) { - width: 14.28%; + width: 9.09090909%; display: inline-block; padding: 2px 0; cursor: pointer; @@ -740,6 +783,14 @@ tr.preview td:nth-child(2) > a:after { text-decoration: underline; } +.clickable, #random-button { + cursor: pointer !important; +} + +#random-button:hover { + text-decoration: underline; +} + .arrow { font-size: 1.5em; bottom: 10px; @@ -842,6 +893,10 @@ unit > a:hover, .clickable:hover { height: 320px; } +.chart-line { + height: 338px !important; +} + /******************* * SLOT THUMBNAILS * *******************/ diff --git a/characters/index.html b/characters/index.html index 2c406572a..b6ce2034f 100644 --- a/characters/index.html +++ b/characters/index.html @@ -4,7 +4,9 @@ - + + + One Piece Treasure Cruise Character Table @@ -83,8 +85,9 @@ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); - ga('create', 'UA-64769042-1', 'auto'); + }) + (window,document,'script','//www.google-analytics.com/analytics.js','ga'); + ga('create', 'UA-73715806-1', 'auto'); ga('send', 'pageview', '/characters'); diff --git a/characters/js/controllers.js b/characters/js/controllers.js index 217224408..4d66c3c98 100644 --- a/characters/js/controllers.js +++ b/characters/js/controllers.js @@ -4,7 +4,7 @@ * Common data * ***************/ -var filters = { custom: [ ], classes: [ ], stars: [ ], cost: [ 1, 55 ] }; +var filters = { custom: [ ], classes: [ ], stars: [ ], cost: [ 1, 99 ] }; /*************** * Controllers * @@ -15,7 +15,10 @@ var app = angular.module('optc'); app.controller('MainCtrl',function($scope, $rootScope, $state, $stateParams, $timeout, $storage, $controller) { var colors = Chart.defaults.global.colours; + //Change Default Chart Colors + Chart.defaults.global.colours = ["#0e91d3", "#F7464A", "#4D5360", "#97BBCD", "#F7464A", "#4D5360", "#4D5360"]; colors = colors.splice(2,0,colors.splice(1,1)[0]); + if (!$rootScope.hasOwnProperty('nightMode')) { $rootScope.nightMode = $storage.get('chars.night', false); @@ -31,6 +34,11 @@ app.controller('MainCtrl',function($scope, $rootScope, $state, $stateParams, $ti }); $controller('DismissalCtrl'); + + $scope.getRandChar = function(){ + var range = parseInt($rootScope.table.data.length) + 1; + return $rootScope.table.data[Math.floor(Math.random() * range)][0]; + }; }); @@ -48,8 +56,8 @@ app.controller('SidebarCtrl',function($scope, $rootScope, $stateParams, $timeout }); $scope.clearFilters = function() { - filters = { custom: [ ], classes: [ ], stars: [ ], cost: [ 1, 55 ] }; - $rootScope.filters = { custom: [ ], classes: [ ], stars: [ ], cost: [ 1, 55 ] }; + filters = { custom: [ ], classes: [ ], stars: [ ], cost: [ 1, 99 ] }; + $rootScope.filters = { custom: [ ], classes: [ ], stars: [ ], cost: [ 1, 99 ] }; }; $scope.onFilterClick = function(e, value) { @@ -139,6 +147,26 @@ app.controller('DetailsCtrl',function($scope, $rootScope, $state, $stateParams, location: location }); }); + + //Super Hack Job to show Karoo as a socket for Vivi + if (family == "Nefertari Vivi"){ + if (!$scope.families.filter(function(e) { return e.uid == 445; }).length>0){ + $scope.families.push({ + uid: 445, + name: units[444].name, + location: {data: ["All Difficulties"], name: "Supersonic Duck Squadron! Fortnight", thumb:445} + }); + } + } + if (family == "Demalo Black"){ + if (!$scope.families.filter(function(e) { return e.uid == 985; }).length>0){ + $scope.families.push({ + uid: 985, + name: units[985].name, + location: {data: ["Ultimate"], name: "Clash!? Impostor Straw Hat Pirates", thumb:989} + }); + } + } }); } @@ -164,9 +192,12 @@ app.controller('DetailsCtrl',function($scope, $rootScope, $state, $stateParams, $('#compare').prop('disabled', false); }; $scope.getPrevious = function() { return $stateParams.previous.concat($scope.id); }; - $scope.isCaptainHybrid = ($scope.details && $scope.details.captain && $scope.details.captain.global); + $scope.isCaptainHybrid = ($scope.details && $scope.details.captain && ($scope.details.captain.global || $scope.details.captain.base)); + $scope.isSailorHybrid = ($scope.details && $scope.details.sailor && $scope.details.sailor.global); $scope.isSpecialHybrid = ($scope.details && $scope.details.special && $scope.details.special.global); $scope.isSpecialStaged = ($scope.details && $scope.details.special && $scope.details.special.constructor == Array); + $scope.isLimitStaged = ($scope.details && $scope.details.limit && $scope.details.limit.constructor == Array); + $scope.isPotentialStaged = ($scope.details && $scope.details.potential && $scope.details.potential.constructor == Array); $scope.$watch('customLevel.level',function(level) { if (isNaN(level) || level < 1 || level > $scope.unit.maxLevel) { @@ -199,14 +230,143 @@ app.controller('DetailsCtrl',function($scope, $rootScope, $state, $stateParams, multiTooltipTemplate: '<%= Math.round(value * { HP: 4000, ATK: 1500, RCV: 550 }[label] / 100) %>' } }; + + if($scope.unit.maxLevel<6) + $scope.showLine = false; + + // radars for Line Graph + if ($scope.unit.incomplete) return; + if ($scope.unit.maxLevel>6){ + $scope.radarHP = { + labels: [1,Math.ceil($scope.unit.maxLevel*0.1) , Math.ceil($scope.unit.maxLevel*0.2), Math.ceil($scope.unit.maxLevel*0.3), Math.ceil($scope.unit.maxLevel*0.4), Math.ceil($scope.unit.maxLevel*0.5), Math.ceil($scope.unit.maxLevel*0.6),Math.ceil($scope.unit.maxLevel*0.7), Math.ceil($scope.unit.maxLevel*0.8), Math.ceil($scope.unit.maxLevel*0.9), $scope.unit.maxLevel], + series: [$scope.unit.name+' HP'], + data: [ + [CharUtils.getStatOfUnit($scope.unit, 'hp', 1), + CharUtils.getStatOfUnit($scope.unit, 'hp', Math.ceil($scope.unit.maxLevel*0.1)), + CharUtils.getStatOfUnit($scope.unit, 'hp', Math.ceil($scope.unit.maxLevel*0.2)), + CharUtils.getStatOfUnit($scope.unit, 'hp', Math.ceil($scope.unit.maxLevel*0.3)), + CharUtils.getStatOfUnit($scope.unit, 'hp', Math.ceil($scope.unit.maxLevel*0.4)), + CharUtils.getStatOfUnit($scope.unit, 'hp', Math.ceil($scope.unit.maxLevel*0.5)), + CharUtils.getStatOfUnit($scope.unit, 'hp', Math.ceil($scope.unit.maxLevel*0.6)), + CharUtils.getStatOfUnit($scope.unit, 'hp', Math.ceil($scope.unit.maxLevel*0.7)), + CharUtils.getStatOfUnit($scope.unit, 'hp', Math.ceil($scope.unit.maxLevel*0.8)), + CharUtils.getStatOfUnit($scope.unit, 'hp', Math.ceil($scope.unit.maxLevel*0.9)), + $scope.unit.maxHP] + ]}; + $scope.radarATK = { + labels: [1,Math.ceil($scope.unit.maxLevel*0.1) , Math.ceil($scope.unit.maxLevel*0.2), Math.ceil($scope.unit.maxLevel*0.3), Math.ceil($scope.unit.maxLevel*0.4), Math.ceil($scope.unit.maxLevel*0.5), Math.ceil($scope.unit.maxLevel*0.6),Math.ceil($scope.unit.maxLevel*0.7), Math.ceil($scope.unit.maxLevel*0.8), Math.ceil($scope.unit.maxLevel*0.9), $scope.unit.maxLevel], + series: [$scope.unit.name+' ATK'], + data: [ + [CharUtils.getStatOfUnit($scope.unit, 'atk', 1), + CharUtils.getStatOfUnit($scope.unit, 'atk', Math.ceil($scope.unit.maxLevel*0.1)), + CharUtils.getStatOfUnit($scope.unit, 'atk', Math.ceil($scope.unit.maxLevel*0.2)), + CharUtils.getStatOfUnit($scope.unit, 'atk', Math.ceil($scope.unit.maxLevel*0.3)), + CharUtils.getStatOfUnit($scope.unit, 'atk', Math.ceil($scope.unit.maxLevel*0.4)), + CharUtils.getStatOfUnit($scope.unit, 'atk', Math.ceil($scope.unit.maxLevel*0.5)), + CharUtils.getStatOfUnit($scope.unit, 'atk', Math.ceil($scope.unit.maxLevel*0.6)), + CharUtils.getStatOfUnit($scope.unit, 'atk', Math.ceil($scope.unit.maxLevel*0.7)), + CharUtils.getStatOfUnit($scope.unit, 'atk', Math.ceil($scope.unit.maxLevel*0.8)), + CharUtils.getStatOfUnit($scope.unit, 'atk', Math.ceil($scope.unit.maxLevel*0.9)), + $scope.unit.maxATK] + ]}; + $scope.radarRCV = { + labels: [1,Math.ceil($scope.unit.maxLevel*0.1) , Math.ceil($scope.unit.maxLevel*0.2), Math.ceil($scope.unit.maxLevel*0.3), Math.ceil($scope.unit.maxLevel*0.4), Math.ceil($scope.unit.maxLevel*0.5), Math.ceil($scope.unit.maxLevel*0.6),Math.ceil($scope.unit.maxLevel*0.7), Math.ceil($scope.unit.maxLevel*0.8), Math.ceil($scope.unit.maxLevel*0.9), $scope.unit.maxLevel], + series: [$scope.unit.name+' RCV'], + data: [ + [CharUtils.getStatOfUnit($scope.unit, 'rcv', 1), + CharUtils.getStatOfUnit($scope.unit, 'rcv', Math.ceil($scope.unit.maxLevel*0.1)), + CharUtils.getStatOfUnit($scope.unit, 'rcv', Math.ceil($scope.unit.maxLevel*0.2)), + CharUtils.getStatOfUnit($scope.unit, 'rcv', Math.ceil($scope.unit.maxLevel*0.3)), + CharUtils.getStatOfUnit($scope.unit, 'rcv', Math.ceil($scope.unit.maxLevel*0.4)), + CharUtils.getStatOfUnit($scope.unit, 'rcv', Math.ceil($scope.unit.maxLevel*0.5)), + CharUtils.getStatOfUnit($scope.unit, 'rcv', Math.ceil($scope.unit.maxLevel*0.6)), + CharUtils.getStatOfUnit($scope.unit, 'rcv', Math.ceil($scope.unit.maxLevel*0.7)), + CharUtils.getStatOfUnit($scope.unit, 'rcv', Math.ceil($scope.unit.maxLevel*0.8)), + CharUtils.getStatOfUnit($scope.unit, 'rcv', Math.ceil($scope.unit.maxLevel*0.9)), + $scope.unit.maxRCV] + ]}; + }else{ + $scope.radarHP = { + labels: ['1',$scope.unit.maxLevel], + series: ['HP'], + data: [ + [CharUtils.getStatOfUnit($scope.unit, 'hp', 1) , $scope.unit.maxHP] + ] + }; + $scope.radarATK = { + labels: ['1',$scope.unit.maxLevel], + series: ['ATK'], + data: [ + [CharUtils.getStatOfUnit($scope.unit, 'atk', 1) , $scope.unit.maxATK] + ] + }; + $scope.radarRCV = { + labels: ['1',$scope.unit.maxLevel], + series: ['RCV'], + data: [ + [CharUtils.getStatOfUnit($scope.unit, 'rcv', 1) , $scope.unit.maxRCV] + ] + }; + } + $scope.$watch('compare',function(compare) { + //Delete old Comparison data $scope.radar.data = $scope.radar.data.slice(0,1); + $scope.radarHP.data = $scope.radarHP.data.slice(0,1); + $scope.radarHP.series = $scope.radarHP.series.slice(0,1); + $scope.radarATK.data = $scope.radarATK.data.slice(0,1); + $scope.radarATK.series = $scope.radarATK.series.slice(0,1); + $scope.radarRCV.data = $scope.radarRCV.data.slice(0,1); + $scope.radarRCV.series = $scope.radarRCV.series.slice(0,1); if (compare) { $scope.radar.data.push([ $scope.compare.maxHP / 4000 * 100, $scope.compare.maxATK / 1500 * 100, Math.max(0, $scope.compare.maxRCV / 550 * 100) ]); + + $scope.radarHP.series.push($scope.compare.name+' HP'); + $scope.radarHP.data.push( + [CharUtils.getStatOfUnit($scope.compare, 'hp', 1), + CharUtils.getStatOfUnit($scope.compare, 'hp', Math.ceil($scope.compare.maxLevel*0.1)), + CharUtils.getStatOfUnit($scope.compare, 'hp', Math.ceil($scope.compare.maxLevel*0.2)), + CharUtils.getStatOfUnit($scope.compare, 'hp', Math.ceil($scope.compare.maxLevel*0.3)), + CharUtils.getStatOfUnit($scope.compare, 'hp', Math.ceil($scope.compare.maxLevel*0.4)), + CharUtils.getStatOfUnit($scope.compare, 'hp', Math.ceil($scope.compare.maxLevel*0.5)), + CharUtils.getStatOfUnit($scope.compare, 'hp', Math.ceil($scope.compare.maxLevel*0.6)), + CharUtils.getStatOfUnit($scope.compare, 'hp', Math.ceil($scope.compare.maxLevel*0.7)), + CharUtils.getStatOfUnit($scope.compare, 'hp', Math.ceil($scope.compare.maxLevel*0.8)), + CharUtils.getStatOfUnit($scope.compare, 'hp', Math.ceil($scope.compare.maxLevel*0.9)), + $scope.compare.maxHP] + ); + $scope.radarATK.series.push($scope.compare.name+' ATK'); + $scope.radarATK.data.push( + [CharUtils.getStatOfUnit($scope.compare, 'atk', 1), + CharUtils.getStatOfUnit($scope.compare, 'atk', Math.ceil($scope.compare.maxLevel*0.1)), + CharUtils.getStatOfUnit($scope.compare, 'atk', Math.ceil($scope.compare.maxLevel*0.2)), + CharUtils.getStatOfUnit($scope.compare, 'atk', Math.ceil($scope.compare.maxLevel*0.3)), + CharUtils.getStatOfUnit($scope.compare, 'atk', Math.ceil($scope.compare.maxLevel*0.4)), + CharUtils.getStatOfUnit($scope.compare, 'atk', Math.ceil($scope.compare.maxLevel*0.5)), + CharUtils.getStatOfUnit($scope.compare, 'atk', Math.ceil($scope.compare.maxLevel*0.6)), + CharUtils.getStatOfUnit($scope.compare, 'atk', Math.ceil($scope.compare.maxLevel*0.7)), + CharUtils.getStatOfUnit($scope.compare, 'atk', Math.ceil($scope.compare.maxLevel*0.8)), + CharUtils.getStatOfUnit($scope.compare, 'atk', Math.ceil($scope.compare.maxLevel*0.9)), + $scope.compare.maxATK] + ); + $scope.radarRCV.series.push($scope.compare.name+' RCV'); + $scope.radarRCV.data.push( + [CharUtils.getStatOfUnit($scope.compare, 'rcv', 1), + CharUtils.getStatOfUnit($scope.compare, 'rcv', Math.ceil($scope.compare.maxLevel*0.1)), + CharUtils.getStatOfUnit($scope.compare, 'rcv', Math.ceil($scope.compare.maxLevel*0.2)), + CharUtils.getStatOfUnit($scope.compare, 'rcv', Math.ceil($scope.compare.maxLevel*0.3)), + CharUtils.getStatOfUnit($scope.compare, 'rcv', Math.ceil($scope.compare.maxLevel*0.4)), + CharUtils.getStatOfUnit($scope.compare, 'rcv', Math.ceil($scope.compare.maxLevel*0.5)), + CharUtils.getStatOfUnit($scope.compare, 'rcv', Math.ceil($scope.compare.maxLevel*0.6)), + CharUtils.getStatOfUnit($scope.compare, 'rcv', Math.ceil($scope.compare.maxLevel*0.7)), + CharUtils.getStatOfUnit($scope.compare, 'rcv', Math.ceil($scope.compare.maxLevel*0.8)), + CharUtils.getStatOfUnit($scope.compare, 'rcv', Math.ceil($scope.compare.maxLevel*0.9)), + $scope.compare.maxRCV] + ); } if (!$scope.$$phase) $scope.$apply(); }); @@ -217,7 +377,7 @@ app.controller('ColumnsCtrl',function($scope, $rootScope, $state, $stateParams, $scope.columns = { 'HP/ATK': false, 'HP/RCV': false, 'ATK/RCV': false, 'ATK/CMB': false, 'CMB': false, 'ATK/cost': false, 'HP/cost': false, 'Minimum cooldown': false, - 'Initial cooldown': false }; + 'Initial cooldown': false,'MAX EXP': false }; var additionalColumns = $storage.get('charColumns', [ ]); diff --git a/characters/js/directives.js b/characters/js/directives.js index 9634da5d1..8ffb675e4 100644 --- a/characters/js/directives.js +++ b/characters/js/directives.js @@ -11,52 +11,52 @@ var app = angular.module('optc'); directives.characterTable = function($rootScope, $timeout, $compile, $storage) { return { - restrict: 'E', - replace: true, - template: '
', - link: function(scope, element, attrs) { - var table = element.dataTable({ - iDisplayLength: $storage.get('unitsPerPage', 10), - stateSave: true, - data: scope.table.data, - columns: scope.table.columns, - rowCallback: function(row, data, index) { - if (!row || row.hasAttribute('loaded')) return; - var $row = $(row); - if (!$row) return; - // lazy thumbnails - $row.find('[data-original]').each(function(n,x) { - x.setAttribute('src',x.getAttribute('data-original')); - x.removeAttribute('data-original'); - }); - // character log checkbox - var id = data[data.length - 1] + 1; - var checkbox = $(''); - $(row.cells[10 + scope.table.additional]).append(checkbox); - // cosmetic fixes - $(row.cells[2]).addClass('cell-' + row.cells[2].textContent); - var n = row.cells.length - 2 - scope.table.additional; - $(row.cells[n]).addClass('stars stars-' + row.cells[n].textContent); - row.cells[n].textContent = ''; - // compile - $compile($(row).contents())($rootScope); - if (window.units[id - 1].preview) $(row).addClass('preview'); - else if (window.units[id - 1].incomplete) $(row).addClass('incomplete'); - row.setAttribute('loaded','true'); - }, - headerCallback : function(header) { - if (header.hasAttribute('loaded')) return; - header.cells[header.cells.length - 1].setAttribute('title', 'Character Log'); - header.setAttribute('loaded',true); - } - }); - scope.table.refresh = function() { - $rootScope.$emit('table.refresh'); - $timeout(function() { element.fnDraw(); }); - }; + restrict: 'E', + replace: true, + template: '
', + link: function(scope, element, attrs) { + var table = element.dataTable({ + iDisplayLength: $storage.get('unitsPerPage', 10), + stateSave: true, + data: scope.table.data, + columns: scope.table.columns, + rowCallback: function(row, data, index) { + if (!row || row.hasAttribute('loaded')) return; + var $row = $(row); + if (!$row) return; + // lazy thumbnails + $row.find('[data-original]').each(function(n,x) { + x.setAttribute('src',x.getAttribute('data-original')); + x.removeAttribute('data-original'); + }); + // character log checkbox + var id = data[data.length - 1] + 1; + var checkbox = $(''); + $(row.cells[10 + scope.table.additional]).append(checkbox); + // cosmetic fixes + $(row.cells[2]).addClass('cell-' + row.cells[2].textContent); + var n = row.cells.length - 2 - scope.table.additional; + $(row.cells[n]).addClass('stars stars-' + row.cells[n].textContent); + row.cells[n].textContent = ''; + // compile + $compile($(row).contents())($rootScope); + if (window.units[id - 1].preview) $(row).addClass('preview'); + else if (window.units[id - 1].incomplete) $(row).addClass('incomplete'); + row.setAttribute('loaded','true'); + }, + headerCallback : function(header) { + if (header.hasAttribute('loaded')) return; + header.cells[header.cells.length - 1].setAttribute('title', 'Character Log'); + header.setAttribute('loaded',true); + } + }); + scope.table.refresh = function() { + $rootScope.$emit('table.refresh'); + $timeout(function() { element.fnDraw(); }); + }; // report link - var link = $('Want to report or request something? Use this form.'); - link.find('a').attr('href', 'https://docs.google.com/forms/d/1jSlwN0Ruyc5bFfxdXlwihqfLdCiELX7HQTabXoCV7hU/viewform?usp=send_form'); + var link = $('Want to report or request something? Join our discord.'); + link.find('a').attr('href', 'https://discord.gg/MRhRrbF'); link.insertAfter($('.dataTables_length')); // pick column link var pick = $(''); - var classes = [ 'Fighter', 'Shooter', 'Slasher', 'Striker', 'Freedom', 'Knowledge', 'Tough', 'Ambition' ]; + var classes = [ 'Fighter', 'Shooter', 'Slasher', 'Striker', 'Free Spirit', 'Cerebral', 'Powerhouse', 'Driven' ]; classes.forEach(function(x,n) { var template = '%s'; @@ -130,6 +131,30 @@ directives.addCaptainOptions = function($timeout, $compile, MATCHER_IDS) { } }; }; + +directives.addSailorOptions = function($timeout, $compile, MATCHER_IDS) { + //TO DO ONCE WE FIND OUT WHAT SAILOR ABILITIES DO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + var TARGET = MATCHER_IDS['sailor.ClassBoostingSailors']; + return { + restrict: 'A', + link: function(scope, element, attrs) { + if (scope.n !== TARGET) return; + var filter = $('
'); + var classes = [ 'Fighter', 'Shooter', 'Slasher', 'Striker', 'Free Spirit', 'Cerebral', 'Powerhouse', 'Driven' ]; + classes.forEach(function(x,n) { + var template = '%s'; + filter.append($(template.replace(/%s/g,x).replace(/%c/,'width-6'))); + }); + element.after(filter); + $compile(filter)(scope); + scope.onSailorClick = function(e,type) { + scope.filters.classSailor = (scope.filters.classSailor == type ? null : type); + }; + } + }; +}; directives.addSpecialOptions = function($timeout, $compile, MATCHER_IDS) { var TARGET = MATCHER_IDS['special.ClassBoostingSpecials']; @@ -138,7 +163,7 @@ directives.addSpecialOptions = function($timeout, $compile, MATCHER_IDS) { link: function(scope, element, attrs) { if (scope.n !== TARGET) return; var filter = $('
'); - var classes = [ 'Fighter', 'Shooter', 'Slasher', 'Striker', 'Freedom', 'Knowledge', 'Tough', 'Ambition' ]; + var classes = [ 'Fighter', 'Shooter', 'Slasher', 'Striker', 'Free Spirit', 'Cerebral', 'Powerhouse', 'Driven' ]; classes.forEach(function(x,n) { var template = '%s'; @@ -163,7 +188,7 @@ directives.addOrbOptions = function($timeout, $compile, MATCHER_IDS) { var filter = $('
' + '
'); var separator = filter.find('.separator'); - [ 'STR', 'DEX', 'QCK', 'PSY', 'INT', 'RCV', 'TND' ].forEach(function(type) { + [ 'STR', 'DEX', 'QCK', 'PSY', 'INT', 'RCV', 'TND', 'BLOCK', 'EMPTY', 'BOMB', 'G' ].forEach(function(type) { var template = '%S'; separator.before($(template.replace(/%s/g,type).replace(/%S/g,type[0]).replace(/%f/g,'ctrlFrom'))); @@ -183,6 +208,29 @@ directives.addOrbOptions = function($timeout, $compile, MATCHER_IDS) { } }; }; + +directives.addDebuffOptions = function($timeout, $compile, MATCHER_IDS) { + var TARGET = MATCHER_IDS['special.DebuffReducingSpecials']; + return { + restrict: 'A', + link: function(scope, element, attrs) { + if (scope.n !== TARGET) return; + var filter = $('
'); + var debuffs = [ 'Bind', 'Despair', 'Silence', 'Paralysis', 'Blindness', 'Poison', 'Anti-Healing', 'Chain Limit' ]; + debuffs.forEach(function(x,n) { + var template = '%s'; + filter.append($(template.replace(/%s/g,x).replace(/%c/,'width-6'))); + }); + element.after(filter); + $compile(filter)(scope); + scope.onDebuffClick = function(e,type) { + console.log(scope.filters.debuffs); + scope.filters.debuffs = (scope.filters.debuffs == type ? null : type); + }; + } + }; +}; directives.goBack = function($state) { return { @@ -206,6 +254,7 @@ directives.evolution = function($state, $stateParams) { templateUrl: 'views/evolution.html', link: function(scope, element, attrs) { scope.goToState = function(id) { + if (!Number.isInteger(id)) return; if (id == parseInt($stateParams.id,10)) return; var previous = $stateParams.previous.concat([ $stateParams.id ]); $state.go('main.search.view',{ id: id, previous: previous }); @@ -242,10 +291,21 @@ directives.compare = function() { source: function(query, callback) { callback(fuse.search(query)); }, templates: { suggestion: function(id) { - var name = units[id].name, url = Utils.getThumbnailUrl(id+1); - if (name.length > 63) name = name.slice(0,60) + '...'; - var thumb = '
'; - return '
' + thumb + '' + name + '
'; + if (Number.isInteger(id)){ + + var name = units[id].name, url = Utils.getThumbnailUrl(id+1); + //var name = units[id].name, url = Utils.getThumbnailUrl(id+1), url2 = Utils.getGlobalThumbnailUrl(id+1); + if (name.length > 63) name = name.slice(0,60) + '...'; + var thumb = '
'; + //var thumb = '
'; + + return '
' + thumb + '' + name + '
'; + } + else{ + var name = 'material', url = Utils.getThumbnailUrl(id); + var thumb = '
'; + return '
' + thumb + '' + name + '
'; + } } }, display: function(id) { @@ -253,7 +313,7 @@ directives.compare = function() { } } ); - + target.bind('typeahead:select',function(e,suggestion) { $(e.currentTarget).prop('disabled', true); scope.compare = window.units[suggestion]; @@ -261,6 +321,8 @@ directives.compare = function() { scope.compareCooldown = window.cooldowns[suggestion]; scope.isCompareCaptainHybrid = (scope.compareDetails && scope.compareDetails.captain && scope.compareDetails.captain.global); + scope.isCompareSailorHybrid = (scope.compareDetails && scope.compareDetails.sailor && + scope.compareDetails.sailor.global); scope.isCompareSpecialHybrid = (scope.compareDetails && scope.compareDetails.special && scope.compareDetails.special.global); scope.isCompareSpecialStaged = (scope.compareDetails && scope.compareDetails.special && @@ -294,6 +356,31 @@ directives.comparison = function() { }; }; +directives.addNames = function($stateParams, $rootScope) { + var name = window.aliases; + return { + restrict: 'E', + replace: true, + template: '
', + link: function(scope, element, attrs) { + var id = $stateParams.id, data = details[id]; + + var currentAliases = name[id]; + if(currentAliases[0]!=''){ + element.append($('Japanese
'+ currentAliases[0] +'
')); + } + if(currentAliases[1]!=''){ + element.append($('French
'+ currentAliases[1] +'
')); + } + if(currentAliases[2]){ + var otherAliases = currentAliases.toString().replace(/(.*?),(.*?),/,""); + element.append($('Others
'+ otherAliases +'
')); + } + } + } +}; + + directives.addTags = function($stateParams, $rootScope) { return { restrict: 'E', @@ -309,6 +396,7 @@ directives.addTags = function($stateParams, $rootScope) { if (flags.rr) element.append($('Rare Recruit only')); if (flags.lrr) element.append($('Limited Rare Recruit only')); if (flags.promo) element.append($('Promo-code only')); + if (flags.shop) element.append($('Rayleigh Shop Unit')); if (flags.special) element.append($('One time only characters')); if (CharUtils.checkFarmable(id, { 'Story Island': true })) element.append($('Story mode only')); @@ -332,6 +420,14 @@ directives.addTags = function($stateParams, $rootScope) { name = name.replace(/iing/,'ying'); element.append($('' + name + '')); } + // sailor effects + if (matcher.target.indexOf('sailor') === 0 && matcher.matcher.test(data[matcher.target]) && !(data[matcher.target] === undefined)) { + name = matcher.name; + if (!/sailor$/.test(name)) name = name.replace(/ers$/,'ing').replace(/s$/,'') + ' sailor'; + else name = name.replace(/s$/,''); + name = name.replace(/iing/,'ying'); + element.append($('' + name + '')); + } // specials if (matcher.target.indexOf('special') === 0 && matcher.matcher.test(data[matcher.target])) { name = matcher.name; @@ -340,6 +436,16 @@ directives.addTags = function($stateParams, $rootScope) { name = name.replace(/iing/,'ying'); element.append($('' + name + '')); } + // limit + if (matcher.target.indexOf('limit') === 0 && matcher.matcher.test(data[matcher.target])) { + name = matcher.name; + if (!/limit$/.test(name)) name = name.replace(/ers$/,'ing').replace(/s$/,'') + ' limit'; + else name = name.replace(/s$/,''); + name = name.replace(/iing/,'ying'); + if (name != "Has Limit Break limit"){ + element.append($('' + name + '')); + } + } }); } }; @@ -356,16 +462,22 @@ directives.addLinks = function($stateParams) { var incomplete = units[id - 1].incomplete; var ul = $('
    '); if (!incomplete && window.flags[id] && window.flags[id].global) { - var link = 'http://onepiece-treasurecruise.com/en/' + (id == '5' ? 'roronoa-zoro' : 'c-' + id); + var link = 'http://onepiece-treasurecruise.com/en/' + (id == '5' ? 'roronoa-zoro' : id == 1254 ? 'maelstrom-spider-squard-whitebeard-pirates-family' : 'c-' + id); ul.append($('
  • Official Guide (English)
  • ')); } if (!incomplete) { - ul.append($('
  • ' + + if (id == 1478){ + ul.append($('
  • ' + 'Official Guide (Japanese)
  • ')); + } + else{ + ul.append($('
  • ' + + 'Official Guide (Japanese)
  • ')); + } } - if (!isNaN(gw[id-1])) { + if (gw[id-1] != null) { ul.append($('
  • ' + - 'GameWith Page (Japanese)
  • ')); + 'GameWith Page (Japanese) | ' +'Google Translate')); } if (ul.children().length > 0) element.append(ul); diff --git a/characters/js/index.js b/characters/js/index.js index d4048341f..c77e4e724 100644 --- a/characters/js/index.js +++ b/characters/js/index.js @@ -12,7 +12,7 @@ Utils.parseUnits(false); var reverseMatcherMap = { }; for (var i=0;i ' + + //return ' ' + '' + data + ''; }; @@ -53,7 +54,8 @@ angular.module('optc') .run(function($rootScope, $timeout, $storage, MATCHER_IDS additionalColumns.forEach(function(x) { var title = x .replace(/Minimum cooldown/,'Min CD') - .replace(/Initial cooldown/,'Max CD'); + .replace(/Initial cooldown/,'Max CD') + .replace(/MAX EXP/,'MAX EXP'); result.splice(result.length-1, 0, { title: title, type: 'num-string' }); }); return result; @@ -67,6 +69,8 @@ angular.module('optc') .run(function($rootScope, $timeout, $storage, MATCHER_IDS if (!tableData.parameters) return true; var id = parseInt(data[0],10), unit = window.units[id - 1]; var flags = window.flags[unit.number + 1] || { }; + var farmableSocket = CharUtils.hasFarmableSocket(unit.number); + /* * * * * Query filters * * * * */ // filter by matchers for (var matcher in tableData.parameters.matchers) { @@ -139,6 +143,9 @@ angular.module('optc') .run(function($rootScope, $timeout, $storage, MATCHER_IDS // special if (filters.nonFarmable.special && !flags.special) return false; if (filters.nonFarmable.special === false && flags.special) return false; + // rayleigh shop + if (filters.nonFarmable.shop && !flags.shop) return false; + if (filters.nonFarmable.shop === false && flags.shop) return false; } } } @@ -148,7 +155,7 @@ angular.module('optc') .run(function($rootScope, $timeout, $storage, MATCHER_IDS if (filters.noFodder && Utils.isFodder(unit)) return false; if (filters.noFortnights && flags.fnonly) return false; if (filters.noRaids && flags.raid) return false; - if (filters.noSpecials && (flags.lrr || flags.promo || flags.special)) return false; + if (filters.noSpecials && (flags.lrr || flags.promo || flags.special || flags.shop )) return false; // filter by server if (filters.server) { if (filters.server == 'Global units' && !flags.global) return false; @@ -156,6 +163,8 @@ angular.module('optc') .run(function($rootScope, $timeout, $storage, MATCHER_IDS } // filter by rr pool if ((filters.rr === 'Not in RR pool' && flags.rr) || (filters.rr === 'In RR pool' && !flags.rr)) return false; + //filter by farmable Sockets + if ((filters.socket === 'No Farmable Sockets' && farmableSocket) || (filters.socket === 'Farmable Sockets' && !farmableSocket)) return false; // filter by active matchers if (filters.custom.length > 0 && !window.details.hasOwnProperty(id)) return false; for (var i=0;i OPTC Character Table - https://optc.github.io/favicon.ico - + https://optc-db.github.io/favicon.ico + diff --git a/characters/views/details.html b/characters/views/details.html index f90cf5b5e..a2f201791 100644 --- a/characters/views/details.html +++ b/characters/views/details.html @@ -121,6 +121,18 @@ + + + + + + + + + @@ -137,12 +149,41 @@
    + Japan +
    + Global +
    + Base Captain Ability +
    + Limit Break Level 1 Captain Ability +
    + Limit Break Level 2 Captain Ability +
    + Limit Break Level 3 Captain Ability +
    + Limit Break Level 4 Captain Ability +
    + Limit Break Level 5 Captain Ability +
    + Limit Break Level 6 Captain Ability +
    +
    + + + + + Sailor Ability + + +
    + +
    Japan -
    +
    Global -
    +
    - + @@ -179,6 +220,60 @@ +
    + + + + + + + + + + + +
    Limit Break + +
    + +
    +
    + Level {{$index + 1}}: + +
    +
    +
    + Japan +
    + Global +
    +
    + +
    Potential Abilties + +
    + +
    +
    + Potential Ability {{$index + 1}}: + {{stage.Name}} +
    +
    +
    +
    +
    +
    +
    +
    +
    + Japan +
    + Global +
    +
    + +
    +
    @@ -202,6 +297,21 @@
    - {{drop.name}} + {{drop.name}} {{drop.data.join(', ')}} @@ -391,7 +501,7 @@
    - {{drop.name}} + {{drop.name}} {{drop.data.join(', ')}} @@ -425,11 +535,17 @@
    {{data.name}} - {{data.location.name}} + {{data.location.name}} {{data.location.data.join(', ')}} + + + + + + diff --git a/characters/views/main.html b/characters/views/main.html index 32b18ba61..68bb9504a 100644 --- a/characters/views/main.html +++ b/characters/views/main.html @@ -10,6 +10,7 @@ Clear + Random Operators @@ -25,6 +26,7 @@
    • type:X: shows only units of type X (STR, DEX, QCK, ...)
    • class:X: shows only units of class X (fighter, slasher, ...)
    • +
      • For Free Spirit units enter free_spirit or just free

    Supported mathematical operators: diff --git a/characters/views/sidebar.html b/characters/views/sidebar.html index 6f617da61..07ad9c611 100644 --- a/characters/views/sidebar.html +++ b/characters/views/sidebar.html @@ -1,104 +1,131 @@ -
    Clear filters
    - -
    - Type filters - {{type}} -
    - -
    - Class filters - {{class}} -
    - -
    - Rarity filters - -
    - - - -
    - Drop filters - {{type}} - {{type}} - {{type}} -
    - -
    - Farmable filters - Fortnight-onlyHide fortnight-only - Raid-onlyHide raid-only - Colosseum-onlyHide Clssm-only -
    - -
    - Non-farmable filters - Limited RR-onlyHide lim. RR-only - Promo-onlyHide promo-only - Special-onlyHide special-only -
    - -
    - Exclusion filters - Hide base formsHide fodder - Hide Boosters and Evolvers -
    - -
    - Captain ability filters - {{filter.name}} -
    - -
    - Special filters - {{filter.name}} -
    - -
    - Character Log filters - Hide units in Character Log - Hide units not in Character Log -
    +
    Clear filters
    + +
    + Type filters + {{type}} +
    + +
    + Class filters + {{class}} +
    + + +
    + Rarity filters + + +
    + + + +
    + Drop filters + {{type}} + {{type}} + {{type}} + {{type}} +
    + +
    + Farmable filters + Story-onlyHide story-only + Fortnight-onlyHide fortnight-only + Raid-onlyHide raid-only + Coliseum-onlyHide Clssm-only +
    + +
    + Non-farmable filters + Limited RR-onlyHide lim. RR-only + Promo-onlyHide promo-only + Special-onlyHide special-only + Ray Shop UnitHide Ray Shop Unit +
    + +
    + Exclusion filters + Hide base formsHide fodder + Hide Boosters and Evolvers +
    + +
    + Captain ability filters + {{filter.name}} +
    + +
    + Special filters + {{filter.name}} +
    + +
    + Sailor ability filters + {{filter.name}} +
    + +
    + Limit Break filters + {{filter.name}} +
    + +
    + Character Log filters + Hide units in Character Log + Hide units not in Character Log +
    \ No newline at end of file diff --git a/common/css/links.css b/common/css/links.css index f1e6bac19..fe701c6a9 100644 --- a/common/css/links.css +++ b/common/css/links.css @@ -6,8 +6,8 @@ #links-button { position: fixed; - right: 20px; - bottom: 5px; + bottom: 20px; + right: 5px; transform: translateX(-50%) translateY(-50%); width: 2em; height: 2em; @@ -167,12 +167,40 @@ transform: translateX(-15em); } +#links-button.active .rotater:nth-child(6) > a { + -webkit-transform: translateX(-18em); + -ms-transform: translateX(-18em); + transform: translateX(-18em); +} + +#links-button.active .rotater:nth-child(7) > a { + -webkit-transform: translateX(-21em); + -ms-transform: translateX(-21em); + transform: translateX(-21em); +} + +#links-button.active .rotater:nth-child(8) > a { + -webkit-transform: translateX(-24em); + -ms-transform: translateX(-24em); + transform: translateX(-24em); +} + +#links-button.active .rotater:nth-child(9) > a { + -webkit-transform: translateY(-4em); + -ms-transform: translateY(-4em); + transform: translateY(-4em); +} + #link-damage > .btn { background: #85C1F5; } #link-characters > .btn { background: #7FCA9F; } #link-drops > .btn { background: #F4BA70; } #link-tally > .btn { background: #E96D63; } #link-report > .btn { background: orchid; } #link-slots > .btn { background: #99cc66; } +#links-home > .btn { background: #939393; } +#link-prob > .btn { background: #DEA5A4; } +#link-turtles > .btn { background: #ce4500; } +#link-es > .btn { background: linear-gradient(#ff0000 30%, #ffff00 30%, #ffff00 70%, #ff0000 30%); } .tip { color: black; } @@ -191,3 +219,6 @@ text-decoration: none !important; } +.top { + left: -1em; +} diff --git a/common/data/abilities.js b/common/data/abilities.js index cbb5140f8..b7ffd4783 100644 --- a/common/data/abilities.js +++ b/common/data/abilities.js @@ -27,11 +27,11 @@ window.abilities = [ }, { - name: 'Silence resistance', + name: 'Despair resistance', levels: [ - [ 10, 'Silence duration reduced by 1 turn' ], - [ 15, 'Silence duration reduced by 2 turns' ], - [ 20, 'Silence duration reduced by 3 turns' ] + [ 10, 'Despair duration reduced by 1 turn' ], + [ 15, 'Despair duration reduced by 2 turns' ], + [ 20, 'Despair duration reduced by 3 turns' ] ] }, @@ -62,7 +62,7 @@ window.abilities = [ levels: [ [ 5, 'Boosted chances (20%) of getting matching orbs' ], [ 10, 'Boosted chances (22.2%) of getting matching orbs' ], - [ 20, 'Boosted chances (25%) of getting matching orbs' ], + [ 20, 'Boosted chances (25%) of getting matching orbs' ] ] }, @@ -71,7 +71,7 @@ window.abilities = [ levels: [ [ 10, 'Poison damage reduced by 20%' ], [ 15, 'Poison damage reduced by 50%' ], - [ 20, 'Poison damage reduced by 100%' ], + [ 20, 'Poison damage reduced by 100%' ] ] }, @@ -79,7 +79,7 @@ window.abilities = [ name: 'Map damage resistance', levels: [ [ 10, 'Map damage reduced by 50%' ], - [ 20, 'Map damage reduced by 100%' ], + [ 20, 'Map damage reduced by 100%' ] ] }, diff --git a/common/data/aliases.js b/common/data/aliases.js index 20b0d058c..dfe68e107 100644 --- a/common/data/aliases.js +++ b/common/data/aliases.js @@ -1,165 +1,1866 @@ window.aliases = { - 4: [ 'G2' ], - 15: [ 'GPU' ], - 16: [ 'Usopp' ], - 63: [ 'Hachi' ], - 207: [ 'Mr. 2 Bonclay' ], - 208: [ 'Mr. 2 Bonclay Bombardier Arabesque' ], - 209: [ 'Nico Robin' ], - 217: [ 'Mistake', 'G3' ], - 221: [ 'Towel Nami' ], - 224: [ 'Sanji' ], - 225: [ 'Sanji' ], - 247: [ 'Chopperman', 'Chopper Man' ], - 248: [ 'Monster Chopper' ], - 249: [ 'Monster Chopper' ], - 260: [ 'Whitebeard' ], - 317: [ 'Califa', 'Calipha', 'Kalipha' ], - 318: [ 'Beautiful Secretary Califa', 'Beautiful Secretary Calipha', 'Beautiful Secretary Kalipha' ], - 334: [ 'Lapahn', 'Lapan', 'Rapan' ], - 335: [ 'Lapahn Adult', 'Lapan Adult', 'Rapan Adult' ], - 383: [ 'Crocodile' ], - 384: [ 'Strikerdile', 'Impactdile' ], - 393: [ 'Kumashi' ], - 394: [ 'Inuppe' ], - 408: [ 'Slasherdile' ], - 409: [ 'Jinbe', 'Jimbei', 'Jinbei' ], - 410: [ 'Jinbe Warlord of the Sea', 'Jimbei Warlord of the Sea', 'Jinbei Warlord of the Sea' ], - 417: [ 'Doffy' ], - 418: [ 'Doffy' ], - 419: [ 'Kimono Sanji' ], - 420: [ 'Kimono Luffy' ], - 421: [ 'Kimono Zoro' ], - 422: [ 'Kimono Nami' ], - 425: [ 'Ryuuma' ], - 432: [ 'Sarkies' ], - 437: [ 'Valentine Perona' ], - 438: [ 'Valentine Perona' ], - 439: [ 'Valentine Vivi' ], - 440: [ 'Valentine Vivi' ], - 444: [ 'Carue', 'Karue' ], - 445: [ 'Captain Karue and the Supersonic Duck Squadron', 'Captain Carue and the Supersonic Duck Squadron' ], - 446: [ 'Blackbeard' ], - 450: [ 'Namur' ], - 451: [ 'One-Hit Namur' ], - 461: [ 'Fugitive Bentham Mr. 2 Bonclay' ], - 462: [ 'Prison Break Expert Mr. 2 Bonclay' ], - 472: [ 'Enel\'s Elect: Red Guard Skypiea Enforcer' ], - 473: [ 'Enel\'s Elect: Blue Guard Skypiea Enforcer' ], - 474: [ 'Enel\'s Elect: Green Guard Skypiea Enforcer' ], - 475: [ 'Enel\'s Elect: Yellow Guard Skypiea Enforcer' ], - 476: [ 'Enel\'s Elect: Black Guard Skypiea Enforcer' ], - 517: [ 'Usoppun' ], - 518: [ 'Usoppun, Pupil of Heracles\'n' ], - 519: [ 'Strong World Luffy', 'SW Luffy' ], - 520: [ 'Strong World Luffy', 'SW Luffy' ], - 521: [ 'Strong World Sanji', 'SW Sanji' ], - 522: [ 'Strong World Sanji', 'SW Sanji' ], - 523: [ 'Strong World Nami', 'SW Nami' ], - 524: [ 'Strong World Nami', 'SW Nami' ], - 525: [ 'Strong World Brook', 'SW Brook' ], - 526: [ 'Strong World Brook', 'SW Brook' ], - 527: [ 'Strong World Chopper', 'SW Chopper' ], - 528: [ 'Strong World Chopper', 'SW Chopper' ], - 529: [ 'Strong World Shanks', 'SW Shanks' ], - 530: [ 'Strong World Shanks', 'SW Shanks' ], - 531: [ 'Sakura Robin' ], - 532: [ 'Sakura Robin' ], - 533: [ 'Sakura Brook' ], - 534: [ 'Sakura Brook' ], - 535: [ 'Sakura Nami' ], - 536: [ 'Sakura Nami' ], - 543: [ 'Wiper' ], - 544: [ 'Wiper, Descendant of Great Warrior Calgara' ], - 545: [ 'Enel' ], - 546: [ 'God Enel' ], - 553: [ 'Strong World Zoro', 'SW Zoro' ], - 554: [ 'Strong World Zoro', 'SW Zoro' ], - 555: [ 'Strong World Usopp', 'SW Usopp' ], - 556: [ 'Strong World Usopp', 'SW Usopp' ], - 557: [ 'Strong World Robin', 'SW Robin' ], - 558: [ 'Strong World Robin', 'SW Robin' ], - 559: [ 'Strong World Franky', 'SW Franky' ], - 560: [ 'Strong World Franky', 'SW Franky' ], - 561: [ 'Strong World Ace', 'SW Ace' ], - 562: [ 'Strong World Ace', 'SW Ace' ], - 567: [ 'Big Pan' ], - 570: [ 'Afro Luffy', 'Afroluffy' ], - 571: [ 'Afro Luffy', 'Afroluffy' ], - 577: [ 'Log Luffy' ], - 578: [ 'Log Luffy' ], - 579: [ 'Log Zoro' ], - 580: [ 'Log Zoro' ], - 583: [ 'Laki' ], - 596: [ 'Log Chopper' ], - 591: [ 'Princess Turtle' ], - 592: [ 'Princess Turtle' ], - 593: [ 'Princess Turtle' ], - 594: [ 'Princess Turtle' ], - 595: [ 'Princess Turtle' ], - 597: [ 'Log Chopper' ], - 602: [ 'Enel, 200 Million Volt Thunder God' ], - 603: [ 'Enel the Lightning Human, 200 Million Volt Thunder God' ], - 604: [ 'Log Sanji' ], - 605: [ 'Log Sanji' ], - 611: [ 'Pudding Pudding' ], - 612: [ 'Log Brook' ], - 613: [ 'Log Brook' ], - 637: [ 'Hachi, Takoyaki Stand Owner' ], - 650: [ 'Log Nami' ], - 651: [ 'Log Nami' ], - 660: [ 'Log Usopp' ], - 661: [ 'Log Usopp' ], - 678: [ 'Log Robin' ], - 679: [ 'Log Robin' ], - 710: [ 'Log Franky' ], - 711: [ 'Log Franky' ], - 725: [ 'Log Vivi' ], - 726: [ 'Log Vivi' ], - 728: [ 'Califa, Cipher Pol No.9', 'Calipha, Cipher Pol No.9', 'Kalipha, Cipher Pol No.9' ], - 729: [ 'Califa Rokushiki, Cipher Pol No.9', 'Calipha Rokushiki, Cipher Pol No.9', 'Kalipha Rokushiki, Cipher Pol No.9' ], - 744: [ 'Log Ace' ], - 745: [ 'Log Ace' ], - 751: [ 'Califa, CP9\'s Dark Justice', 'Calipha, CP9\'s Dark Justice', 'Kalipha, CP9\'s Dark Justice' ], - 752: [ 'Califa, CP9\'s Strongest Generation', 'Calipha, CP9\'s Strongest Generation', 'Kalipha, CP9\'s Strongest Generation' ], - 761: [ 'Halloween Luffy' ], - 762: [ 'Halloween Usopp' ], - 763: [ 'Halloween Franky' ], - 764: [ 'Halloween Nami' ], - 765: [ 'Halloween Chopper' ], - 766: [ 'Halloween Zoro' ], - 767: [ 'Halloween Robin' ], - 768: [ 'Halloween Sanji' ], - 769: [ 'Halloween Brook' ], - 782: [ 'Kimono Tashigi' ], - 783: [ 'Kimono Tashigi' ], - 786: [ 'Dr. Hiruruk' ], - 787: [ 'Dr. Hiruruk, Quack Doctor' ], - 790: [ 'Usopp Pirates' ], - 791: [ 'Usopp Pirates' ], - 792: [ 'Iceberg' ], - 793: [ 'Iceberg, Mayor of W7 and President of Galley-La Company' ], - 799: [ 'Sea Lapahn, Sea Animal Pirates', 'Sea Lapan, Sea Animal Pirates', 'Sea Rapan, Sea Animal Pirates' ], - 801: [ 'Log Bon Clay', 'Log Bonclay' ], - 802: [ 'Log Bon Clay', 'Log Bonclay' ], - 813: [ 'Spider Monkey' ], - 832: [ 'Wiper, Warrior of Shandia' ], - 833: [ 'Berserker Wiper, Warrior of Shandia' ], - 849: [ 'Franky, Tom\'s Workers' ], - 850: [ 'Iceburg, Tom\'s Workers' ], - 866: [ 'Kimono Robin' ], - 867: [ 'Kimono Usopp' ], - 868: [ 'Kimono Chopper' ], - 869: [ 'Doffy' ], - 870: [ 'Doffy' ], - 873: [ 'Senor Pink', 'Senior Pink' ], - 874: [ 'Senor Pink', 'Senior Pink' ], - 877: [ 'Giolla' ], - 878: [ 'Giolla, Donquixote Pirates' ], - 885: [ 'Kimono Jinbe', 'Kimono Jimbei', 'Kimono Jinbei' ], - 886: [ 'Kimono Mr. 1' ], - 887: [ 'Kimono Buggy' ], - 897: [ 'Kimono Crocodile' ], - 898: [ 'Kimono Mr. 3', 'Kimono Galdino' ], - 899: [ 'Kimono Mr. 2', 'Kimono Bonclay', 'Kimono Bon Clay' ] + 1: ['モンキー・D・ルフィ','Monkey D. Luffy'], + 2: ['モンキー・D・ルフィ ゴムゴムの銃(ピストル)','Monkey D. Luffy Gum-Gum Carabine'], + 3: ['モンキー・D・ルフィ ゴムゴムのバズーカ','Monkey D. Luffy Gum-Gum Bazooka'], + 4: ['モンキー・D・ルフィ ギア2','Monkey D. Luffy Gear 2','Monkey D. Luffy', ' G2'], + 5: ['ロロノア・ゾロ','Roronoa Zoro'], + 6: ['ロロノア・ゾロ 三・千・世・界','Roronoa Zoro Moulinet Infernal'], + 7: ['ロロノア・ゾロ 煩悩鳳(ポンドほう)','Roronoa Zoro Calibre'], + 8: ['ロロノア・ゾロ 阿修羅弌霧銀(あしゅらいちぶぎん)','Roronoa Zoro Brume Argentée'], + 9: ['ナミ','Nami'], + 10: ['ナミ トルネード=テンポ','Nami Tornado Tempo'], + 11: ['ナミ 蜃気楼=テンポ','Nami MirageTempo'], + 12: ['ナミ サンダーボルト=テンポ','Nami Fulguro Tempo'], + 13: ['ウソップ','Usopp'], + 14: ['ウソップ タバスコ星','Usopp Etoile Piquante'], + 15: ['ウソップ ゴールデンパウンド','Usopp Usopp-Pilon doré','GPU'], + 16: [ 'そげキング','Sniperking','Usopp'], + 17: ['サンジ','Sanji'], + 18: ['サンジ 整形ショット(パラージュショット)','Sanji Tir esthétique'], + 19: ['料理人サンジ 焼き石シチュー','Chef Sanji Ragoût bouillonnant'], + 20: ['サンジ 悪魔風脚 (ディアブルジャンブ)','Sanji Jambe du diable'], + 21: ['トニートニー・チョッパー','Tony Tony Chopper'], + 22: ['トニートニー・チョッパー 重量強化(ヘビーポイント)','Tony Tony Chopper Weight Boost'], + 23: ['トニートニー・チョッパー 頭脳強化(ブレーンポイント)','Tony Tony Chopper Brain Boost'], + 24: ['トニートニー・チョッパー 腕力強化(アームポイント)','Tony Tony Chopper Arm Boost'], + 25: ['トニートニー・チョッパー 角強化(ホーンポイント)','Tony Tony Chopper Horn Boost'], + 26: ['トニートニー・チョッパー 毛皮強化(ガードポイント)','Tony Tony Chopper Guard Boost'], + 27: ['ヒグマ','Higuma'], + 28: ['近海の主(ヌシ)','Seigneur de la côte'], + 29: ['金棒のアルビダ','Alvida à la Massue'], + 30: ['金棒のアルビダ スベスベの実','Alvida à la Massue Fruit Glisse-Glisse'], + 31: ['コビー','Kobby'], + 32: ['雑用コビー','Kobby le mousse'], + 33: ['ヘルメッポ','Hermep'], + 34: ['雑用ヘルメッポ','Hermep le mousse'], + 35: ['斧手のモーガン','Morgan le Hacheur'], + 36: ['モージ&リッチー','Morge et Richy'], + 37: ['曲芸のカバジ','Cabaji l\'acrobate'], + 38: ['バギー','Baggy'], + 39: ['道化のバギー','Baggy le Clown'], + 40: ['ガイモン','Gaimon'], + 41: ['シャム','Sham'], + 42: ['ブチ','Buchi'], + 43: ['1・2のジャンゴ','Jango l\'hypnotiseur'], + 44: ['ダンシングジャンゴ','Jango le danseur'], + 45: ['キャプテン・クロ','Capitaine Kuro'], + 46: ['百計のクロ','Kuro les pattes de velours'], + 47: ['ヨサク','Yosaku'], + 48: ['ジョニー','Jhonny'], + 49: ['鉄拳のフルボディ','Fullbody au poing d\'acier'], + 50: ['パティ','Patty'], + 51: ['カルネ','Carne'], + 52: ['料理長ゼフ','Zeff le chef'], + 53: ['ギン','Gyn'], + 54: ['鬼人ギン','Gyn le démon enragé'], + 55: ['パール','Pearl'], + 56: ['ファイヤーパール','Fire Pearl'], + 57: ['首領・クリーク','Don Krieg '], + 58: ['首領・クリーク 猛毒ガス弾「M・H・5」','Don Krieg Bombe à gaz toxique MH5'], + 59: ['ネズミ','Nezumi'], + 60: ['モーム','Meuh-Meuh'], + 61: ['チュウ','Smack'], + 62: ['クロオビ','Kuroobi'], + 63: ['はっちゃん','Octy', 'Hachi' ], + 64: ['六刀流のハチ','Octy aux six lames', 'Hatchan'], + 65: ['アーロン','Arlong'], + 66: ['ブチ切れアーロン 鮫(シャ-ク)・ON・歯車(トゥース)','Arlong enragé Squalo Crunch'], + 67: ['たしぎ','Tashigi'], + 68: ['たしぎ 海軍本部少尉','Tashigi Lieutenant-colonel de la Marine'], + 69: ['スモーカー','Smoker'], + 70: ['白猟のスモーカー','Smoker le chasseur blanc'], + 71: ['ミス・ウェンズデー','Miss Wednesday'], + 72: ['ネフェルタリ・ビビ','Vivi Nerfertari'], + 73: ['王女ビビ','Princesse Vivi'], + 74: ['ポートガス・D・エース','Portgas D. Ace'], + 75: ['ポートガス・D・エース 鏡火炎(きょうかえん)','Portgas D. Ace Pyro-miroir'], + 76: ['シャンクス','Shanks'], + 77: ['赤髪のシャンクス','Shanks le Roux'], + 78: ['赤盗人ペンギン','Pingouin chapardeur rouge'], + 79: ['青盗人ペンギン','Pingouin chapardeur bleu'], + 80: ['緑盗人ペンギン','Pingouin chapardeur vert'], + 81: ['黄盗人ペンギン','Pingouin chapardeur jaune'], + 82: ['黒盗人ペンギン','Pingouin chapardeur noir'], + 83: ['虹盗人ペンギン','Pingouin chapardeur arc-en-ciel'], + 84: ['赤海賊ペンギン','Pingouin pirate rouge'], + 85: ['赤海賊ペンギン','Pingouin pirate bleu'], + 86: ['赤海賊ペンギン','Pingouin pirate vert'], + 87: ['赤海賊ペンギン','Pingouin pirate jaune'], + 88: ['赤海賊ペンギン','Pingouin pirate noir'], + 89: ['赤カブトヤドカリ','Bernard-l\'ermite rouge'], + 90: ['赤カブトヤドカリ','Bernard-l\'ermite bleu'], + 91: ['赤カブトヤドカリ','Bernard-l\'ermite vert'], + 92: ['赤カブトヤドカリ','Bernard-l\'ermite jaune'], + 93: ['赤カブトヤドカリ','Bernard-l\'ermite noir'], + 94: ['赤カブトヤドカリ','Bernard-l\'ermite arc-en-ciel'], + 95: ['赤ヨロイガニ','Crabe blindé rouge'], + 96: ['赤ヨロイガニ','Crabe blindé bleu'], + 97: ['赤ヨロイガニ','Crabe blindé vert'], + 98: ['赤ヨロイガニ','Crabe blindé jaune'], + 99: ['赤ヨロイガニ','Crabe blindé noir'], + 100: ['赤しま番竜','Dragon rayé rouge'], + 101: ['赤しま番竜','Dragon rayé bleu'], + 102: ['赤しま番竜','Dragon rayé vert'], + 103: ['赤しま番竜','Dragon rayé jaune'], + 104: ['赤しま番竜','Dragon rayé noir'], + 105: ['赤タカラガメ','Tortue-trésor rouge','Baby Turtle'], + 106: ['赤タカラガメ','Tortue-trésor bleue','Baby Turtle'], + 107: ['赤タカラガメ','Tortue-trésor verte','Baby Turtle'], + 108: ['赤タカラガメ','Tortue-trésor jaune','Baby Turtle'], + 109: ['赤タカラガメ','Tortue-trésor noire','Baby Turtle'], + 110: ['赤ダイミョウガメ','Tortue noble rouge'], + 111: ['赤ダイミョウガメ','Tortue noble bleue'], + 112: ['赤ダイミョウガメ','Tortue noble verte'], + 113: ['赤ダイミョウガメ','Tortue noble jaune'], + 114: ['赤ダイミョウガメ','Tortue noble noire'], + 115: ['タツノコ','Poney marin'], + 116: ['タツノワカ','Poulain marin'], + 117: ['タツノミコト','Cheval marin'], + 118: ['タツノオウ','Étalon marin'], + 119: ['カタナ山賊',''], + 120: ['ピストル山賊',''], + 121: ['格闘隊 雑用 レッドパイレーツ',''], + 122: ['格闘隊 雑用 ブルーパイレーツ',''], + 123: ['格闘隊 雑用 グリーンパイレーツ',''], + 124: ['格闘隊 雑用 イエローパイレーツ',''], + 125: ['格闘隊 雑用 ブラックパイレーツ',''], + 126: ['斬撃隊 雑用 レッドパイレーツ',''], + 127: ['斬撃隊 雑用 ブルーパイレーツ',''], + 128: ['斬撃隊 雑用 グリーンパイレーツ',''], + 129: ['斬撃隊 雑用 イエローパイレーツ',''], + 130: ['斬撃隊 雑用 ブラックパイレーツ',''], + 131: ['突撃隊 雑用 レッドパイレーツ',''], + 132: ['突撃隊 雑用 ブルーパイレーツ',''], + 133: ['突撃隊 雑用 グリーンパイレーツ',''], + 134: ['突撃隊 雑用 イエローパイレーツ',''], + 135: ['突撃隊 雑用 ブラックパイレーツ',''], + 136: ['狙撃隊 雑用 レッドパイレーツ',''], + 137: ['狙撃隊 雑用 ブルーパイレーツ',''], + 138: ['狙撃隊 雑用 グリーンパイレーツ',''], + 139: ['狙撃隊 雑用 イエローパイレーツ',''], + 140: ['狙撃隊 雑用 ブラックパイレーツ',''], + 141: ['砲撃手 雑用',''], + 142: ['格闘隊 隊員 レッドパイレーツ',''], + 143: ['格闘隊 隊員 ブルーパイレーツ',''], + 144: ['格闘隊 隊員 グリーンパイレーツ',''], + 145: ['格闘隊 隊員 イエローパイレーツ',''], + 146: ['格闘隊 隊員 ブラックパイレーツ',''], + 147: ['斬撃隊 隊員 レッドパイレーツ',''], + 148: ['斬撃隊 隊員 ブルーパイレーツ',''], + 149: ['斬撃隊 隊員 グリーンパイレーツ',''], + 150: ['斬撃隊 隊員 イエローパイレーツ',''], + 151: ['斬撃隊 隊員 ブラックパイレーツ',''], + 152: ['突撃隊 隊員 レッドパイレーツ',''], + 153: ['突撃隊 隊員 ブルーパイレーツ',''], + 154: ['突撃隊 隊員 グリーンパイレーツ',''], + 155: ['突撃隊 隊員 イエローパイレーツ',''], + 156: ['突撃隊 隊員 ブラックパイレーツ',''], + 157: ['狙撃隊 隊員 レッドパイレーツ',''], + 158: ['狙撃隊 隊員 ブルーパイレーツ',''], + 159: ['狙撃隊 隊員 グリーンパイレーツ',''], + 160: ['狙撃隊 隊員 イエローパイレーツ',''], + 161: ['狙撃隊 隊員 ブラックパイレーツ',''], + 162: ['砲撃手 腕利き',''], + 163: ['ボディガード・サングラス',''], + 164: ['ボディガード・ヒゲ',''], + 165: ['ナックルごろつき クロネコ海賊団',''], + 166: ['サーベルごろつき クロネコ海賊団',''], + 167: ['ナギナタごろつき クロネコ海賊団',''], + 168: ['ピストルごろつき クロネコ海賊団',''], + 169: ['バズーカごろつき クロネコ海賊団',''], + 170: ['格闘隊 隊長',''], + 171: ['斬撃隊 隊長',''], + 172: ['突撃隊 隊長',''], + 173: ['狙撃隊 隊長',''], + 174: ['遊撃手 凄腕',''], + 175: ['空手使いの魚人 アーロン一味',''], + 176: ['カタナ使いの魚人 アーロン一味',''], + 177: ['ヤリ使いの魚人 アーロン一味',''], + 178: ['銃使いの魚人 アーロン一味',''], + 179: ['ナックル三等兵 海軍',''], + 180: ['サーベル三等兵 海軍',''], + 181: ['ナギナタ三等兵 海軍',''], + 182: ['ピストル三等兵 海軍',''], + 183: ['バズーカ三等兵 海軍',''], + 184: ['ナックル一等兵 海軍',''], + 185: ['サーベル一等兵 海軍',''], + 186: ['ナギナタ一等兵 海軍',''], + 187: ['ピストル一等兵 海軍',''], + 188: ['バズーカ一等兵 海軍',''], + 189: ['赤タイロウガメ',''], + 190: ['青タイロウガメ',''], + 191: ['青タイロウガメ',''], + 192: ['青タイロウガメ',''], + 193: ['青タイロウガメ',''], + 194: ['ナックル少尉 海軍本部',''], + 195: ['サーベル少尉 海軍本部',''], + 196: ['ナギナタ少尉 海軍本部',''], + 197: ['ピストル少尉 海軍本部',''], + 198: ['バズーカ少尉 海軍本部',''], + 199: ['Mr.5 鼻空想砲(ノーズファンシーキャノン)','', 'Mr 5'], + 200: ['Mr.5 そよ風息爆弾(ブリーズ・ブレス・ボム)','', 'Mr 5'], + 201: ['ミス・バレンタイン',''], + 202: ['ミス・バレンタイン 1万キロギロチン',''], + 203: ['Mr.3','','Mr 3'], + 204: ['Mr.3 特大キャンドルサービスセット','', 'Mr 3'], + 205: ['ミス・ゴールデンウィーク',''], + 206: ['ミス・ゴールデンウィーク カラーズトラップ なごみの緑',''], + 207: ['Mr.2・ボン・クレー ','', 'Mr. 2 Bonclay', 'Mr 2 Bonclay' ], + 208: ['Mr.2・ボン・クレー 爆撃白鳥アラベスク(ボンバルディエ)','', 'Mr. 2 Bonclay Bombardier Arabesque', 'Mr 2 Bonclay Bombardier Arabesque' ], + 209: ['ミス・オールサンデー バロックワークス副社長','', 'Nico Robin' ], + 210: ['ニコ・ロビン',''], + 211: ['Mr.9','','Mr 9'], + 212: ['Mr.9 (熱血ナイン根性バット)','','Mr 9 Hot Blooded Bat'], + 213: ['ラブーン',''], + 214: ['ラブーン(ルフィ落書き)',''], + 215: ['大王イカ',''], + 216: ['モンキー・D・ルフィ(ゴムゴムの風船)',''], + 217: ['モンキー・D・ルフィ(ギア3)','', 'Mistake', 'G3','Gear 3' ], + 218: ['ゾロ_刀狼流し(とうろうながし)',''], + 219: ['ロロノア・ゾロ_獅子歌歌(ししソンソン)','','LS Zoro'], + 220: ['ナミ(ファイン=テンポ)',''], + 221: ['ナミ(幸せパンチ)','', 'Towel Nami','TNami' ], + 222: ['ウソップ(ウソップハンマー)',''], + 223: ['ウソップ(衝撃(インパクト))',''], + 224: ['Mr.プリンス(羊肉(ムートン)ショット)','', 'Sanji', 'Mr Prince Mutton Shot'], + 225: ['Mr.プリンス(仔牛肉(ヴォー)ショット)','', 'Sanji', 'Mr Prince Veau Shot' ], + 226: ['ジュラキュール・ミホーク','','Raidhawk', 'Raid Mihawk', 'Hawk' ], + 227: ['鷹の目のミホーク','','Raidhawk', 'Raid Mihawk'], + 228: ['脱獄モーガン',''], + 229: ['寝返りのジャンゴ',''], + 230: ['両鉄拳のフルボディ',''], + 231: ['ヒナ',''], + 232: ['黒檻のヒナ',''], + 233: ['Mr.8','','Mr 8'], + 234: ['Mr.8 イガラッパッパ','','Mr 8'], + 235: ['ミス・マンデー',''], + 236: ['ミス・マンデー カ・イ・リ・キ メリケン',''], + 237: ['ナックルミリオンズ バロックワークス',''], + 238: ['サーベルミリオンズ バロックワークス',''], + 239: ['ナギナタミリオンズ バロックワークス',''], + 240: ['ピストルミリオンズ バロックワークス',''], + 241: ['バズーカミリオンズ バロックワークス',''], + 242: ['ナックルビリオンズ バロックワークス',''], + 243: ['サーベルビリオンズ バロックワークス',''], + 244: ['ナギナタビリオンズ バロックワークス',''], + 245: ['ピストルビリオンズ バロックワークス',''], + 246: ['バズーカビリオンズ バロックワークス',''], + 247: ['チョッパーマン','', 'Chopperman', 'Chopper Man' ], + 248: ['トニートニー・チョッパー 暴走前','', 'Raid Monster Chopper', 'MC' ], + 249: ['トニートニー・チョッパー 暴走後','', 'Raid Monster Chopper', 'MC' ], + 250: ['マルコ',''], + 251: ['不死鳥マルコ',''], + 252: ['ジョズ',''], + 253: ['ダイヤモンド・ジョズ',''], + 254: ['ビスタ',''], + 255: ['花剣のビスタ',''], + 256: ['イゾウ',''], + 257: ['短筒使いのイゾウ',''], + 258: ['ブラメンコ',''], + 259: ['大槌のブラメンコ',''], + 260: ['エドワード・ニューゲート','', 'Whitebeard', 'WB', 'Legend WB', 'Legend Whitebeard', 'Yonko'], + 261: ['白ひげ','','Edward Newgate', 'WB', 'Legend WB', 'Legend Whitebeard', 'Yonko'], + 262: ['特訓コビー',''], + 263: ['曹長コビー',''], + 264: ['特訓ヘルメッポ',''], + 265: ['軍曹ヘルメッポ',''], + 266: ['虹海賊ペンギン',''], + 267: ['虹しま番竜',''], + 268: ['白猟のスモーカー ビローアバイク','','WC Smoker'], + 269: ['格闘隊 武装隊員 レッドパイレーツ',''], + 270: ['格闘隊 武装隊員 ブルーパイレーツ',''], + 271: ['格闘隊 武装隊員 グリーンパイレーツ',''], + 272: ['格闘隊 武装隊員 イエローパイレーツ',''], + 273: ['格闘隊 武装隊員 ブラックパイレーツ',''], + 274: ['斬撃隊 武装隊員 レッドパイレーツ',''], + 275: ['斬撃隊 武装隊員 ブルーパイレーツ',''], + 276: ['斬撃隊 武装隊員 グリーンパイレーツ',''], + 277: ['斬撃隊 武装隊員 イエローパイレーツ',''], + 278: ['斬撃隊 武装隊員 ブラックパイレーツ',''], + 279: ['突撃隊 武装隊員 レッドパイレーツ',''], + 280: ['突撃隊 武装隊員 ブルーパイレーツ',''], + 281: ['突撃隊 武装隊員 グリーンパイレーツ',''], + 282: ['突撃隊 武装隊員 イエローパイレーツ',''], + 283: ['突撃隊 武装隊員 ブラックパイレーツ',''], + 284: ['狙撃隊 武装隊員 レッドパイレーツ',''], + 285: ['狙撃隊 武装隊員 ブルーパイレーツ',''], + 286: ['狙撃隊 武装隊員 グリーンパイレーツ',''], + 287: ['狙撃隊 武装隊員 イエローパイレーツ',''], + 288: ['狙撃隊 武装隊員 ブラックパイレーツ',''], + 289: ['砲撃手 敏腕',''], + 290: ['Mr.13&ミス・フライデー 13日の金曜日(アンラッキーズ)','','Mr 13 and Ms Friday the Unluckies'], + 291: ['ドリー',''], + 292: ['ブロギー',''], + 293: ['トリケラトプス',''], + 294: ['レックス',''], + 295: ['ブロントザウルス',''], + 296: ['おつるさん',''], + 297: ['大参謀つる',''], + 298: ['モモンガ',''], + 299: ['オニグモ',''], + 300: ['赤アーマーロブスター',''], + 301: ['青アーマーロブスター',''], + 302: ['緑アーマーロブスター',''], + 303: ['黄アーマーロブスター',''], + 304: ['黒アーマーロブスター',''], + 305: ['モンキー・D・ガープ','','Raid Garp'], + 306: ['ゲンコツのガープ','','Raid Garp'], + 307: ['トラファルガー・ロー','','Supernova Law'], + 308: ['トラファルガー・ロー ROOMバジル・ホーキンス','','Supernova Law'], + 309: ['バジル・ホーキンス','','Supernova Hawkins'], + 310: ['魔術師バジル・ホーキンス','','Supernova Hawkins'], + 311: ['キラー','','Supernova Killer'], + 312: ['殺戮武人キラー','','Supernova Killer'], + 313: ['ウルージ','','Supernova Urouge'], + 314: ['怪僧ウルージ','','Supernova Urouge'], + 315: ['ベポ',''], + 316: ['武闘家のベポ',''], + 317: ['カリファ','', 'Califa', 'Calipha', 'Kalipha' ], + 318: ['美人秘書カリファ','', 'Beautiful Secretary Califa', 'Beautiful Secretary Calipha', 'Beautiful Secretary Kalipha' ], + 319: ['パウリー',''], + 320: ['パウリー 1番ドック艤装(ぎそう)・マスト職職長',''], + 321: ['ロブ・ルッチ',''], + 322: ['ロブ・ルッチ 1番ドック木びき・木釘職職長',''], + 323: ['カク',''], + 324: ['カク 1番ドック大工職職長',''], + 325: ['ルル',''], + 326: ['ワポル',''], + 327: ['ワポルハウス',''], + 328: ['ドルトン',''], + 329: ['ドルトン 野牛(バイソン)',''], + 330: ['チェス',''], + 331: ['クロマーリモ',''], + 332: ['チェスマーリモ',''], + 333: ['Dr.くれは',''], + 334: ['ラパーン','', 'Lapahn', 'Lapan', 'Rapan' ], + 335: ['ラパーン 成獣','', 'Lapahn Adult', 'Lapan Adult', 'Rapan Adult' ], + 336: ['フランキー',''], + 337: ['解体屋フランキー',''], + 338: ['キウイ',''], + 339: ['モズ',''], + 340: ['クラーケン スルメ',''], + 341: ['クラーケン 北極の怪物',''], + 342: ['赤パワース豚(トーン)','','Pig','Pork'], + 343: ['青パワース豚(トーン)','','Pig','Pork'], + 344: ['緑パワース豚(トーン)','','Pig','Pork'], + 345: ['黄パワース豚(トーン)','','Pig','Pork'], + 346: ['黒パワース豚(トーン)','','Pig','Pork'], + 347: ['ルビーパワース豚(トーン)','','Pig','Pork'], + 348: ['サファイアパワース豚(トーン)','','Pig','Pork'], + 349: ['エメラルドパワース豚(トーン)','','Pig','Pork'], + 350: ['トパーズパワース豚(トーン)','','Pig','Pork'], + 351: ['アメジストパワース豚(トーン)','','Pig','Pork'], + 352: ['ゼファー','','Raid Zephyr'], + 353: ['ゼファー NEO海軍総帥','','Raid Zephyr'], + 354: ['アイン','','Raid Ain'], + 355: ['アイン NEO海軍バイス・アドミラル','','Raid Ain'], + 356: ['ユースタス・キッド','','Supernova Kid','Supernova Kidd', 'Kidd'], + 357: ['キャプテン・キッド','','Supernova Kid','Supernova Kidd', 'Kidd'], + 358: ['スクラッチメン・アプー','','Supernova Apoo'], + 359: ['海鳴り スクラッチメン・アプー','','Supernova Apoo'], + 360: ['X・ドレーク','','Supernova Drake','Supernova X Drake'], + 361: ['赤旗 X・ドレーク','','Supernova Drake', 'Supernova X Drake'], + 362: ['ジュエリー・ボニー','','Supernova Bonney'], + 363: ['大喰らい ジュエリー・ボニー','','Supernova Bonney'], + 364: ['カポネ・ベッジ','','Supernova Capone'], + 365: ['カポネ・ギャング・ベッジ','','Supernova Capone'], + 366: ['シルバーズ・レイリー','', 'Dark King Rayliegh', 'Legend Rayliegh'], + 367: ['冥王レイリー','', 'Silvers Rayleigh', 'Legend Rayliegh'], + 368: ['巨人斬撃隊 レッドパイレーツ',''], + 369: ['巨人射撃隊 ブルーパイレーツ',''], + 370: ['巨人女戦士隊 グリーンパイレーツ',''], + 371: ['巨人格闘隊 イエローパイレーツ',''], + 372: ['巨人突撃隊 ブラックパイレーツ',''], + 373: ['巨人斬撃近衛隊 レッドパイレーツ',''], + 374: ['巨人射撃近衛隊 ブルーパイレーツ',''], + 375: ['巨人女戦士近衛隊 グリーンパイレーツ',''], + 376: ['巨人格闘近衛隊 イエローパイレーツ',''], + 377: ['巨人突撃近衛隊 ブラックパイレーツ',''], + 378: ['海ネコ',''], + 379: ['クンフージュゴン',''], + 380: ['クンフージュゴン 兄弟弟子',''], + 381: ['バナナワニ',''], + 382: ['サンドラ大トカゲ',''], + 383: ['Mr.0 バロックワークス社長','', 'Crocodile', 'Mr 0' ], + 384: ['サー・クロコダイル','', 'Strikerdile', 'Impactdile', 'Mr 0','Mr. 0' ], + 385: ['ホグバック',''], + 386: ['ドクトル・ホグバック',''], + 387: ['シンドリーちゃん',''], + 388: ['ビクトリア・シンドリー',''], + 389: ['エンポリオ・イワンコフ','','Raid Ivankov'], + 390: ['エンポリオ・イワンコフ カマバッカ王国女王【永久欠番】','','Raid Ivankov'], + 391: ['ペローナ',''], + 392: ['ペローナ ゴーストプリンセス',''], + 393: ['クマシー','', 'Kumashi' ], + 394: ['犬ッペ','', 'Inuppe' ], + 395: ['ミス・メリークリスマス',''], + 396: ['ミス・メリークリスマス モグラ人間',''], + 397: ['Mr.4','','Mr 4'], + 398: ['Mr.4と犬銃ラッスー','','Mr 4 and Lassoo the Dog-Gun'], + 399: ['ミス・ダブルフィンガー',''], + 400: ['ミス・ダブルフィンガー 棘(とげ)人間',''], + 401: ['Mr.1','','Mr 1','Daz Bones'], + 402: ['Mr.1 全身刃物人間','','Mr 1','Daz Bones'], + 403: ['レベッカ',''], + 404: ['アブサロム',''], + 405: ['墓場のアブサロム',''], + 406: ['将軍ゾンビ',''], + 407: ['風のジゴロウ',''], + 408: ['サー・クロコダイル 王下七武海','', 'Slasherdile' ], + 409: ['ジンベエ','', 'Jinbe', 'Jimbei', 'Jinbei' ], + 410: ['ジンベエ 王下七武海','', 'Jinbe Warlord of the Sea', 'Jimbei Warlord of the Sea', 'Jinbei Warlord of the Sea' ], + 411: ['バーソロミュー・くま',''], + 412: ['バーソロミュー・くま 王下七武海',''], + 413: ['ゲッコー・モリア','', 'Gekko Moriah'], + 414: ['ゲッコー・モリア 王下七武海','', 'Gekko Moriah Warlord of the Sea'], + 415: ['ボア・ハンコック','', 'Shichibukai', 'Legend Boa Hancock'], + 416: ['ボア・ハンコック 王下七武海','', 'Shichibukai', 'Legend Boa Hancock'], + 417: ['ドンキホーテ・ドフラミンゴ','', 'Raid Doffy', 'Raid Doflaming' ], + 418: ['ドンキホーテ・ドフラミンゴ 王下七武海','', 'Raid Doffy', 'Raid Doflaming' ], + 419: ['サンジ 整形ショット(パラージュショット) “嵐”','', 'Kimono Sanji' ], + 420: ['モンキー・D・ルフィ ゴムゴムのバズーカ“覇”','', 'Kimono Luffy' ], + 421: ['ロロノア・ゾロ 三・千・世・界“斬”','', 'Kimono Zoro' ], + 422: ['ナミ 蜃気楼=テンポ“天”','', 'Kimono Nami' ], + 423: ['ブルック',''], + 424: ['鼻唄のブルック',''], + 425: ['リューマ','', 'Ryuuma' ], + 426: ['マシラ','','Harambe'], + 427: ['ショウジョウ',''], + 428: ['モンブラン・クリケット',''], + 429: ['サウスバードと森の住民',''], + 430: ['ベラミー',''], + 431: ['ハイエナのベラミー',''], + 432: ['サーキース','', 'Sarkies' ], + 433: ['エリザベス',''], + 434: ['キャロライン',''], + 435: ['サンジ カマバッカ王国伝統の決闘スタイル',''], + 436: ['サンジ キャンディーちゃん',''], + 437: ['ペローナ スイート','', 'Valentine Perona' ], + 438: ['ペローナ スイート ゴーストプリンセス','', 'Valentine Perona' ], + 439: ['ネフェルタリ・ビビ ラブ','', 'Valentine Vivi' ], + 440: ['王女ビビ ラブ','', 'Valentine Vivi' ], + 441: ['カウボーイとバーボンJr. 超カルガモ部隊',''], + 442: ['ストンプとイワンX 超カルガモ部隊',''], + 443: ['ケンタロウスとヒコイチ 超カルガモ部隊',''], + 444: ['カルー','', 'Carue', 'Karue' ], + 445: ['カルー隊長と超カルガモ部隊','', 'Captain Karue and the Supersonic Duck Squadron', 'Captain Carue and the Supersonic Duck Squadron' ], + 446: ['マーシャル・D・ティーチ','', 'Raid Blackbeard', 'BB'], + 447: ['黒ひげ','', 'Raid Blackbeard', 'BB', 'Teach', 'Marshall D. Teach'], + 448: ['サッチ',''], + 449: ['双剣のサッチ',''], + 450: ['ナミュール','', 'Namur' ], + 451: ['一撃のナミュール','', 'One-Hit Namur' ], + 452: ['ラクヨウ',''], + 453: ['モーニングスターのラクヨウ',''], + 454: ['フォッサ',''], + 455: ['火炎刀のフォッサ',''], + 456: ['クリエル',''], + 457: ['重火器使いのクリエル',''], + 458: ['センゴク','', 'Legend Sengoku', 'Legend Goku'], + 459: ['仏のセンゴク','', 'Legend Sengoku', 'Legend Goku'], + 460: ['犯罪者ギャルディーノ Mr.3','','Mr 3'], + 461: ['脱走者ベンサム Mr.2・ボン・クレー','', 'Fugitive Bentham Mr. 2 Bonclay', 'Fugitive Bentham Mr 2 Bonclay' ], + 462: ['脱獄名人ベンサム Mr.2・ボン・クレー','', 'Prison Break Expert Mr. 2 Bonclay', 'Prison Break Expert Mr 2 Bonclay' ], + 463: ['サトリ',''], + 464: ['シュラ',''], + 465: ['ゲダツ',''], + 466: ['ブラハム',''], + 467: ['ヤマ',''], + 468: ['黄のホワイトベレー部隊 隊員 スカイピア神隊',''], + 469: ['黒のホワイトベレー部隊 隊員 スカイピア神隊',''], + 470: ['黄のホワイトベレー部隊 隊長 スカイピア神隊',''], + 471: ['黒のホワイトベレー部隊 隊長 スカイピア神隊',''], + 472: ['赤のゴッド近衛隊 隊員 スカイピア神兵','', 'Enel\'s Elect: Red Guard Skypiea Enforcer' ], + 473: ['青のゴッド近衛隊 隊員 スカイピア神兵','', 'Enel\'s Elect: Blue Guard Skypiea Enforcer' ], + 474: ['緑のゴッド近衛隊 隊員 スカイピア神兵','', 'Enel\'s Elect: Green Guard Skypiea Enforcer' ], + 475: ['黄のゴッド近衛隊 隊員 スカイピア神兵','', 'Enel\'s Elect: Yellow Guard Skypiea Enforcer' ], + 476: ['黒のゴッド近衛隊 隊員 スカイピア神兵','', 'Enel\'s Elect: Black Guard Skypiea Enforcer' ], + 477: ['赤の突撃隊 隊員 スカイピア神兵',''], + 478: ['青の突撃隊 隊員 スカイピア神兵',''], + 479: ['緑の突撃隊 隊員 スカイピア神兵',''], + 480: ['黄の突撃隊 隊員 スカイピア神兵',''], + 481: ['黒の突撃隊 隊員 スカイピア神兵',''], + 482: ['赤の突撃隊 エリート スカイピア神兵',''], + 483: ['青の突撃隊 エリート スカイピア神兵',''], + 484: ['緑の突撃隊 エリート スカイピア神兵',''], + 485: ['黄の突撃隊 エリート スカイピア神兵',''], + 486: ['黒の突撃隊 エリート スカイピア神兵',''], + 487: ['赤の遊牧隊 隊員 シャンディアの戦士',''], + 488: ['青の遊牧隊 隊員 シャンディアの戦士',''], + 489: ['緑の遊牧隊 隊員 シャンディアの戦士',''], + 490: ['赤の遊牧隊 達人 シャンディアの戦士',''], + 491: ['青の遊牧隊 達人 シャンディアの戦士',''], + 492: ['緑の遊牧隊 達人 シャンディアの戦士',''], + 493: ['黄の狩猟隊 隊員 シャンディアの戦士',''], + 494: ['黒の狩猟隊 隊員 シャンディアの戦士',''], + 495: ['黄の狩猟隊 達人 シャンディアの戦士',''], + 496: ['黒の狩猟隊 達人 シャンディアの戦士',''], + 497: ['ポートガス・D・エース コルボ山の悪ガキ3兄弟','','Kid Ace'], + 498: ['ポートガス・D・エース コルボ山の悪ガキ3兄弟“兄弟盃”','','Kid Ace'], + 499: ['ベルメール',''], + 500: ['ベルメール ナミとノジコの養母',''], + 501: ['カヤ',''], + 502: ['カヤ シロップ村のお嬢様',''], + 503: ['ホトリ・コトリ',''], + 504: ['ホトリ・コトリ スカイピア副神兵長',''], + 505: ['ペル',''], + 506: ['ペル アラバスタの守護神ファルコン',''], + 507: ['チャカ',''], + 508: ['チャカ アラバスタの守護神ジャッカル',''], + 509: ['最強の囚人サー・クロコダイル Mr.0 バロックワークス社元社長','','Mr 0', 'Mr. 0','Crocodile','Prisondile'], + 510: ['最強の囚人サー・クロコダイル 元王下七武海','','Mr 0','Mr. 0','Prisondile'], + 511: ['服役囚ダズ・ボーネス Mr.1','','Mr 1','Daz Bones'], + 512: ['サボ コルボ山の悪ガキ3兄弟','','Kid Sabo'], + 513: ['サボ コルボ山の悪ガキ3兄弟“兄弟盃”','','Kid Sabo'], + 514: ['ニコ・ロビン トロピカル', '','Summertime Robin', 'Swimsuit Robin'], + 515: ['ヘラクレスン','','Raid Heracles-un','Raid Heracles'], + 516: ['ヘラクレスン 森の勇者','','Raid Heracles-un','Raid Heracles'], + 517: ['ウソップン','', 'Raid Usoppun', 'Raid Usopp' ], + 518: ['ウソップン ヘラクレスンの生徒','', 'Raid Usoppun, Pupil of Heracles\'n', 'fat usopp', 'Raid Usopp' ], + 519: ['モンキー・D・ルフィ メルヴィユの冒険者','', 'Strong World Luffy', 'SW Luffy' ], + 520: ['モンキー・D・ルフィ 特攻の麦わらの一味','', 'Strong World Luffy', 'SW Luffy' ], + 521: ['サンジ メルヴィユの冒険者','', 'Strong World Sanji', 'SW Sanji' ], + 522: ['サンジ 特攻の麦わらの一味','', 'Strong World Sanji', 'SW Sanji' ], + 523: ['ナミ メルヴィユの冒険者','', 'Strong World Nami', 'SW Nami' ], + 524: ['ナミと雷鳥ビリー','', 'Strong World Nami', 'SW Nami' ], + 525: ['ブルック メルヴィユの冒険者','', 'Strong World Brook', 'SW Brook' ], + 526: ['ブルック 特攻の麦わらの一味','', 'Strong World Brook', 'SW Brook' ], + 527: ['チョッパー メルヴィユの冒険者','', 'Strong World Chopper', 'SW Chopper' ], + 528: ['チョッパー 特攻の麦わらの一味','', 'Strong World Chopper', 'SW Chopper' ], + 529: ['シャンクス 黒衣の赤髪','', 'Strong World Shanks', 'SW Shanks', 'Legend Shanks', 'Yonko' ], + 530: ['シャンクス 黒衣の四皇','', 'Strong World Shanks', 'SW Shanks', 'Legend Shanks', 'Yonko' ], + 531: ['ニコ・ロビン 桜吹雪','', 'Sakura Robin' ], + 532: ['ニコ・ロビン 桜満開','', 'Sakura Robin' ], + 533: ['ブルック チェリーヘッド','', 'Sakura Brook' ], + 534: ['ブルック 桜音色','', 'Sakura Brook' ], + 535: ['ナミ 桜雲','', 'Sakura Nami' ], + 536: ['ナミ 桜日和','', 'Sakura Nami' ], + 537: ['ドミノ',''], + 538: ['ドミノ インペルダウン副看守長',''], + 539: ['ミノリノケロス',''], + 540: ['バシリスク',''], + 541: ['オーム',''], + 542: ['ノラ ウワバミ',''], + 543: ['ワイパー','', 'Wiper' ], + 544: ['ワイパー 大戦士カルガラの子孫','', 'Wiper, Descendant of Great Warrior Calgara' ], + 545: ['エネル','', 'Enel', 'God Enel' ], + 546: ['ゴッド・エネル','', 'God Enel' ], + 547: ['モンキー・D・ルフィ コルボ山の悪ガキ3兄弟','','Kid Luffy'], + 548: ['モンキー・D・ルフィ コルボ山の悪ガキ3兄弟“兄弟盃”','','Kid Luffy'], + 549: ['サディちゃん',''], + 550: ['サディちゃん インペルダウン獄卒長',''], + 551: ['ミノコアラ',''], + 552: ['マンティコラ',''], + 553: ['ロロノア・ゾロ メルヴィユの冒険者','', 'Strong World Zoro', 'SW Zoro' ], + 554: ['ロロノア・ゾロ 特攻の麦わらの一味','', 'Strong World Zoro', 'SW Zoro' ], + 555: ['ウソップ メルヴィユの冒険者','', 'Strong World Usopp', 'SW Usopp' ], + 556: ['ウソップ 特攻の麦わらの一味','', 'Strong World Usopp', 'SW Usopp' ], + 557: ['ニコ・ロビン メルヴィユの冒険者','', 'Strong World Robin', 'SW Robin' ], + 558: ['ニコ・ロビン 特攻の麦わらの一味','', 'Strong World Robin', 'SW Robin' ], + 559: ['フランキー メルヴィユの冒険者','', 'Strong World Franky', 'SW Franky' ], + 560: ['フランキー 特攻の麦わらの一味','', 'Strong World Franky', 'SW Franky' ], + 561: ['ポートガス・D・エース 黒衣の火拳','', 'Strong World Ace', 'SW Ace', 'Legend Ace'], + 562: ['ポートガス・D・エース 黒衣の白ひげ海賊団2番隊隊長','', 'Strong World Ace', 'SW Ace', 'Legend Ace' ], + 563: ['ポルチェ',''], + 564: ['ポーティ',''], + 565: ['ハンバーグ',''], + 566: ['ピクルス',''], + 567: ['ビッグパン','', 'Big Pan' ], + 568: ['フォクシー',''], + 569: ['銀ギツネのフォクシー',''], + 570: ['モンキー・D・ルフィ デービーバックファイト・アフロ','', 'Afro Luffy', 'Afroluffy' ], + 571: ['モンキー・D・ルフィ デービーバックファイト・コンバット','', 'Afro Luffy', 'Afroluffy' ], + 572: ['ウソップ デービーバックファイト・セコンド',''], + 573: ['トニートニー・チョッパー デービーバックファイト・マスク',''], + 574: ['青キジ','','Raid Kuzan', 'Raid Aokiji' ], + 575: ['青キジ 氷結人間','','Raid Kuzan', 'Raid Aokiji' ], + 576: ['ナミのティータイム',''], + 577: ['モンキー・D・ルフィ 航海の記録・麦わらの一味','', 'Log Luffy','Logfy', 'LL', 'Legend Luffy', 'Legend LL' ], + 578: ['モンキー・D・ルフィ 航海の夢「海賊王」','', 'Log Luffy','Logfy', 'LL', 'Legend Luffy', 'Legend LL' ], + 579: ['ロロノア・ゾロ 航海の記録・麦わらの一味','', 'Log Zoro', 'Roronoa Zoro, Wakes of the Endless Dream, Straw Hat Crew' ], + 580: ['ロロノア・ゾロ 航海の夢「大剣豪」','', 'Log Zoro', 'Roronoa Zoro, A Vow in the Great Age of Pirates - Master Swordsman' ], + 581: ['ゲンボウ',''], + 582: ['カマキリ',''], + 583: ['ラキ','', 'Laki' ], + 584: ['アイサ',''], + 585: ['ノジコ',''], + 586: ['ノジコ ナミの義姉妹',''], + 587: ['クロッカス',''], + 588: ['クロッカス 双子岬の灯台守',''], + 589: ['コーザ',''], + 590: ['コーザ 反乱軍リーダー',''], + 591: ['朱の竜宮カメ姫','', 'Princess Turtle' ], + 592: ['蒼の竜宮カメ姫','', 'Princess Turtle' ], + 593: ['翠の竜宮カメ姫','', 'Princess Turtle' ], + 594: ['琥珀の竜宮カメ姫','', 'Princess Turtle' ], + 595: ['漆黒の竜宮カメ姫','', 'Princess Turtle' ], + 596: ['トニートニー・チョッパー 航海の記録・麦わらの一味','', 'Log Chopper', 'Tony Tony Chopper, Wakes of the Endless Dream, Straw Hat Crew' ], + 597: ['トニートニー・チョッパー 航海の憧れ「偉大な医者」','', 'Log Chopper', 'Tony Tony Chopper, A Vow in the Great Age of Pirates - Great Doctor' ], + 598: ['バギー 海賊見習い','','Young Buggy', 'Baggy'], + 599: ['バギー ロジャー海賊団','','Young Buggy', 'Baggy'], + 600: ['シャンクス 海賊見習い','','Young Shanks'], + 601: ['シャンクス ロジャー海賊団','','Young Shanks'], + 602: ['エネル 2億V 雷神','', 'Raid Enel, 200 Million Volt Thunder God', 'God Enel', 'Kami Eneru' ], + 603: ['エネル 雷人間 2億V 雷神','', 'Raid Enel the Lightning Human, 200 Million Volt Thunder God', 'God Enel', 'Kami Eneru' ], + 604: ['サンジ 航海の記録・麦わらの一味','', 'Log Sanji', 'Sanji, Wakes of the Endless Dream, Straw Hat Crew' ], + 605: ['サンジ 航海の夢「オールブルー」','', 'Log Sanji' ], + 606: ['海賊ゼフ',''], + 607: ['赫足のゼフ クック海賊団船長',''], + 608: ['ごろつきパティ',''], + 609: ['ごろつきカルネ',''], + 610: ['ハイキングベア',''], + 611: ['プリンプリン','', 'Pudding Pudding' ], + 612: ['ブルック 航海の記録・麦わらの一味','', 'Log Brook', 'Brook, Wakes of the Endless Dream, Straw Hat Crew' ], + 613: ['ブルック 航海の夢「約束の再会」','','Log Brook', 'Brook, A Vow in the Great Age of Pirates - Promised Meeting' ], + 614: ['ザンバイ',''], + 615: ['怪力デストロイヤーズ 斧使い',''], + 616: ['怪力デストロイヤーズ 槍使い',''], + 617: ['怪力デストロイヤーズ 大砲使い','','Gunner'], + 618: ['ナックルチンピラ 赤の賞金稼ぎ',''], + 619: ['ナックルチンピラ 緑の賞金稼ぎ',''], + 620: ['カタナチンピラ 青の賞金稼ぎ',''], + 621: ['カタナチンピラ 赤の賞金稼ぎ',''], + 622: ['ピストルチンピラ 緑の賞金稼ぎ',''], + 623: ['ピストルチンピラ 黄の賞金稼ぎ',''], + 624: ['棍棒チンピラ 黄の賞金稼ぎ',''], + 625: ['棍棒チンピラ 黒の賞金稼ぎ',''], + 626: ['ガトリングチンピラ 黒の賞金稼ぎ',''], + 627: ['ガトリングチンピラ 青の賞金稼ぎ',''], + 628: ['タイルストン',''], + 629: ['フランキー フランキー一家棟梁',''], + 630: ['カク サイファーポールNo.9',''], + 631: ['カク 六式 サイファーポールNo.9',''], + 632: ['ロブ・ルッチ サイファーポールNo.9',''], + 633: ['ロブ・ルッチ 六式 サイファーポールNo.9',''], + 634: ['ケイミー','','Keimi'], + 635: ['ケイミー タコ焼き屋店員','','Keimi, Takoyaki Stand Assistant'], + 636: ['パッパグ','', 'Pappug'], + 637: ['はっちゃん タコ焼き屋店主','', 'Hachi, Takoyaki Stand Owner' ], + 638: ['ドーマ',''], + 639: ['遊騎士ドーマ',''], + 640: ['ディカルバン兄弟',''], + 641: ['絆のディカルバン兄弟',''], + 642: ['スクアード','','Squardo'], + 643: ['大渦蜘蛛スクアード','','Maelstrom Spider Squardo'], + 644: ['ホワイティベイ',''], + 645: ['氷の魔女ホワイティベイ',''], + 646: ['リトルオーズJr.',''], + 647: ['猛攻のリトルオーズJr.',''], + 648: ['マルコ 白ひげ海賊団1番隊隊長','','LMarco','QMarco', 'Legend Marco'], + 649: ['不死鳥マルコ 白ひげ海賊団1番隊隊長','','LMarco','QMarco', 'Legend Marco'], + 650: ['ナミ 航海の記録・麦わらの一味','', 'Log Nami', 'Nami, Wakes of the Endless Dream, Straw Hat Crew' ], + 651: ['ナミ 航海の夢「世界地図」','', 'Log Nami', 'Nami, A Vow in the Great Age of Pirates - World Map' ], + 652: ['鉄仮面のデュバル','','Raid Duval'], + 653: ['デュバル トビウオライダーズ ヘッド','','Raid Duval'], + 654: ['デュバル 人生バラ色ライダーズ ヘッド','','Raid Duval'], + 655: ['海賊アーロン','','Young Arlong'], + 656: ['アーロン タイヨウの海賊団','','Young Arlong'], + 657: ['クロオビ タイヨウの海賊団','','Young Kuroobi'], + 658: ['チュウ タイヨウの海賊団','','Young Choo'], + 659: ['モンキー・D・ルフィ うきわ','','Summertime Luffy','Swimsuit Luffy'], + 660: ['ウソップ 航海の記録・麦わらの一味', '', 'Log Usopp', 'Usopp, Wakes of the Endless Dream, Straw Hat Crew' ], + 661: ['ウソップ 航海の夢「勇敢なる海の戦士」','', 'Log Usopp', 'Usopp, A Vow in the Great Age of Pirates - Brave Sea Warrior' ], + 662: ['ナミ バカンス', '', 'Summertime Nami', 'Swimsuit Nami'], + 663: ['ネフェルタリ・ビビ アラバスタ王国王女','','Young Vivi'], + 664: ['ネフェルタリ・ビビ 砂砂団 副リーダー','','Young Vivi'], + 665: ['コーザ アラバスタ住民','','Young Koza'], + 666: ['コーザ 砂砂団 リーダー','','Young Koza'], + 667: ['ネフェルタリ・コブラ アラバスタ王国国王',''], + 668: ['サボ','', 'Legend Sabo'], + 669: ['サボ 革命軍','', 'Legend Sabo'], + 670: ['コアラ',''], + 671: ['コアラ 革命軍',''], + 672: ['ハック',''], + 673: ['ハック 革命軍',''], + 674: ['エンポリオ・イワンコフ ニューカマー拳法 師範','','INTvankov'], + 675: ['エンポリオ・イワンコフ 革命軍','','INTvankov'], + 676: ['イナズマ',''], + 677: ['イナズマ 革命軍',''], + 678: ['ニコ・ロビン 航海の記録・麦わらの一味','', 'Log Robin', 'Nico Robin, Wakes of the Endless Dream, Straw Hat Crew' ], + 679: ['ニコ・ロビン 航海の夢「空白の歴史の解明」','', 'Log Robin', 'Nico Robin, A Vow in the Great Age of Pirates - 100-Year Void' ], + 680: ['アイス大好きナミ','','Summertime Nami','Swimsuit Nami'], + 681: ['アイス大好きナミ レモンアイス','','Summertime Nami','Swimsuit Nami'], + 682: ['アイス大好きロビン','','Summertime Robin','Swimsuit Robin'], + 683: ['アイス大好きロビン チョコアイス','','Summertime Robin','Swimsuit Robin'], + 684: ['アイス大好きペローナ','','Summertime Perona','Swimsuit Perona'], + 685: ['アイス大好きペローナ ストロベリーアイス','','Summertime Perona','Swimsuit Perona'], + 686: ['ビビのひとやすみ','', 'Summertime Vivi', 'Swimsuit Vivi' ], + 687: ['カルガラ',''], + 688: ['カルガラ シャンディアの大戦士',''], + 689: ['モンブラン・ノーランド',''], + 690: ['モンブラン・ノーランド ルブニール王国探検船提督',''], + 691: ['ナギナタ伍長 海軍本部',''], + 692: ['ピストル伍長 海軍本部',''], + 693: ['サーベル伍長 海軍本部',''], + 694: ['バズーカ伍長 海軍本部',''], + 695: ['ナックル伍長 海軍本部',''], + 696: ['ナギナタ少佐 海軍本部',''], + 697: ['ピストル少佐 海軍本部',''], + 698: ['サーベル少佐 海軍本部',''], + 699: ['バズーカ少佐 海軍本部',''], + 700: ['ナックル少佐 海軍本部',''], + 701: ['オイモ',''], + 702: ['カーシ―',''], + 703: ['法の番犬部隊',''], + 704: ['有罪陪審員',''], + 705: ['3つ首のバスカビル',''], + 706: ['ブルーノ サイファーポールNo.9',''], + 707: ['ブルーノ 六式 サイファーポールNo.9',''], + 708: ['ニコ・ロビン 悪魔の子',''], + 709: ['ニコ・ロビン 麦わらの一味',''], + 710: ['フランキー 航海の記録・麦わらの一味','', 'Log Franky', 'Franky, Wakes of the Endless Dream, Straw Hat Crew' ], + 711: ['フランキー 航海の夢「海の果てを旅する船」','', 'Log Franky', 'Franky, A Vow in the Great Age of Pirates - Ship of the Seven Seas' ], + 712: ['ガン・フォール','','Gan Fall','ganfall'], + 713: ['ガン・フォール 空の騎士','','Gan Fall the Knight of the Sky','ganfall'], + 714: ['ピエール',''], + 715: ['コニス',''], + 716: ['コニス スカイピアの少女',''], + 717: ['ジュラキュール・ミホーク 王下七武海','','INThawk', 'Legend Mihawk', 'Legend Dracule Mihawk', 'Shichibukai', 'Hawk' ], + 718: ['鷹の目のミホーク 世界最強の剣士','','INThawk', 'Legend Mihawk', 'Legend Dracule Mihawk', 'Shichibukai'], + 719: ['サー・クロコダイル ロギア 王下七武海','', 'Legend Crocodile', 'Shichibukai'], + 720: ['サー・クロコダイル ロギア 元王下七武海','', 'Legend Crocodile', 'Shichibukai'], + 721: ['ジェリー',''], + 722: ['ジェリー サイファーポールNo.6',''], + 723: ['Tボーン','', 'TBone', 'T Bone'], + 724: ['船斬りTボーン 海軍本部大佐','', 'TBone', 'T Bone'], + 725: ['ネフェルタリ・ビビ 航海の記録・アラバスタ王国王女','', 'Log Vivi' ], + 726: ['ネフェルタリ・ビビ 航海の夢「海賊女王」','', 'Log Vivi' ], + 727: ['モンキー・D・ルフィ ゴムゴムの銃乱打 (ガトリング)',''], + 728: ['カリファ サイファーポールNo.9','', 'Califa, Cipher Pol No.9', 'Calipha, Cipher Pol No.9', 'Kalipha, Cipher Pol No.9' ], + 729: ['カリファ 六式 サイファーポールNo.9','', 'Califa Rokushiki, Cipher Pol No.9', 'Calipha Rokushiki, Cipher Pol No.9', 'Kalipha Rokushiki, Cipher Pol No.9' ], + 730: ['ジャブラ サイファーポールNo.9','','Jabura'], + 731: ['ジャブラ 六式 サイファーポールNo.9','','Jabura'], + 732: ['フクロウ サイファーポールNo.9',''], + 733: ['フクロウ 六式 サイファーポールNo.9',''], + 734: ['クマドリ サイファーポールNo.9',''], + 735: ['クマドリ 六式 サイファーポールNo.9',''], + 736: ['カク 獣人 ウシウシの実 モデル麒麟(ジラフ)','','Box Kaku'], + 737: ['ルッチ 獣人 ネコネコの実 モデル豹(レオパルド)','','rob lucci'], + 738: ['スパンダム',''], + 739: ['フランキー 麦わらの一味',''], + 740: ['ネロ',''], + 741: ['ネロ サイファーポールNo.9',''], + 742: ['ワンゼ',''], + 743: ['ワンゼ サイファーポールNo.7',''], + 744: ['ポートガス・D・エース 航海の記録・白ひげ海賊団','', 'Log Ace' ], + 745: ['ポートガス・D・エース 航海の夢「海賊の高み」','', 'Log Ace' ], + 746: ['メガロ&しらほし姫',''], + 747: ['ロブ・ルッチ 闇の正義の「CP9」','', 'Legend Lucci', 'Legend Rob Lucci'], + 748: ['ロブ・ルッチ 歴代最強の「CP9」','', 'Legend Lucci', 'Legend Rob Lucci'], + 749: ['カク 闇の正義の「CP9」',''], + 750: ['カク 歴代最強の「CP9」',''], + 751: ['カリファ 闇の正義の「CP9」','', 'Califa, CP9\'s Dark Justice', 'Calipha, CP9\'s Dark Justice', 'Kalipha, CP9\'s Dark Justice' ], + 752: ['カリファ 歴代最強の「CP9」','', 'Califa, CP9\'s Strongest Generation', 'Calipha, CP9\'s Strongest Generation', 'Kalipha, CP9\'s Strongest Generation' ], + 753: ['ジャブラ 闇の正義の「CP9」','','Jabura'], + 754: ['ジャブラ 歴代最強の「CP9」','','Jabura'], + 755: ['ブルーノ 闇の正義の「CP9」',''], + 756: ['ブルーノ 歴代最強の「CP9」',''], + 757: ['フクロウ 闇の正義の「CP9」',''], + 758: ['フクロウ 歴代最強の「CP9」',''], + 759: ['クマドリ 闇の正義の「CP9」',''], + 760: ['クマドリ 歴代最強の「CP9」',''], + 761: ['モンキー・D・ルフィ ハロウィンモンスター','', 'Halloween Luffy' ], + 762: ['ウソップ うそつき狼','', 'Halloween Usopp' ], + 763: ['フランキー フランケンシュタイン','', 'Halloween Franky' ], + 764: ['ナミ かぼちゃランタン','', 'Halloween Nami' ], + 765: ['トニートニー・チョッパー リトルヴァンパイア','', 'Halloween Chopper' ], + 766: ['ロロノア・ゾロ ジャック・ザ・リッパ―','', 'Halloween Zoro' ], + 767: ['ニコ・ロビン セクシーデビル','', 'Halloween Robin' ], + 768: ['サンジ ゴーストナイト','', 'Halloween Sanji' ], + 769: ['ブルック こわがりスケルトン','', 'Halloween Brook' ], + 770: ['ダルメシアン 海軍本部中将','','Raid Dalmatian'], + 771: ['モモンガ 海軍本部中将','','Raid Momonga'], + 772: ['オニグモ 海軍本部中将','','Raid Onigumo'], + 773: ['シュウ','','Raid Shu'], + 774: ['ベリーグッド','','Very Good','Raid Berry Good'], + 775: ['ストロベリー 海軍本部中将','','Raid Strawberry'], + 776: ['ラッキー・ルウ','','Coliseum Lucky Roo'], + 777: ['ラッキー・ルウ 赤髪海賊団','','Coliseum Lucky Roo'], + 778: ['レベッカ 囚人剣闘士','','Coliseum Rebecca'], + 779: ['レベッカ コロシアム専属剣闘士','','Coliseum Rebecca'], + 780: ['ウルージ 破戒僧海賊団船長','','Supernova Urouge','Coliseum Urouge'], + 781: ['怪僧ウルージ 破戒僧海賊団船長','','Supernova Urouge','Coliseum Urouge'], + 782: ['たしぎ 正義の華','', 'Kimono Tashigi' ], + 783: ['たしぎ 海軍本部少尉・正義の華','', 'Kimono Tashigi' ], + 784: ['ゲンさん',''], + 785: ['ゲンゾウ ココヤシ村の駐在',''], + 786: ['Dr.ヒルルク','', 'Dr. Hiruruk', 'Dr Hiruruk'], + 787: ['Dr.ヒルルク ヤブ医者','', 'Dr. Hiruruk, Quack Doctor', 'Dr Hiruruk, Quack Doctor' ], + 788: ['くいな',''], + 789: ['くいな シモツキ村の少女剣士',''], + 790: ['たまねぎ&ピーマン&にんじん','', 'Usopp Pirates', 'Tamanegi, Piiman & Ninjin' ], + 791: ['たまねぎ&ピーマン&にんじん ウソップ海賊団','', 'Usopp Pirates', 'Tamanegi, Piiman & Ninjin' ], + 792: ['アイスバーグ','', 'Iceberg' ], + 793: ['アイスバーグ W7市長&ガレーラカンパニー社長','', 'Iceberg, Mayor of W7 and President of Galley-La Company' ], + 794: ['モンキー・D・ルフィ 希望の星','','Raid NM Luffy', 'Raid Luffy'], + 795: ['ナイトメア・ルフィ 希望の戦士','','Raid NM Luffy', 'Raid Luffy'], + 796: ['ブリード',''], + 797: ['ブリード ペトペトの実の能力者',''], + 798: ['クンフージュゴン 海獣海賊団',''], + 799: ['シーラパーン 海獣海賊団','', 'Sea Lapahn, Sea Animal Pirates', 'Sea Lapan, Sea Animal Pirates', 'Sea Rapan, Sea Animal Pirates' ], + 800: ['たこボクサー 海獣海賊団',''], + 801: ['Mr.2・ボン・クレー 航海の記録・B・W','', 'Log Bon Clay', 'Log Bonclay','Mr 2' ], + 802: ['Mr.2・ボン・クレー 航海の生き様「おかま道」','', 'Log Bon Clay', 'Log Bonclay', 'Mr 2' ], + 803: ['ヒナ 海軍本部大佐','','Coliseum Hina'], + 804: ['黒檻のヒナ 海軍本部大佐','','Coliseum Hina'], + 805: ['スモーカー 海軍本部大佐','','Coliseum Smoker'], + 806: ['白猟のスモーカー 海軍本部大佐','','Coliseum Smoker'], + 807: ['純白の天使ナミ ウエディング','','Bridal Nami'], + 808: ['純白の女神ナミ ウエディング','','Bridal Nami'], + 809: ['ローラ スリラーバークの花嫁',''], + 810: ['求愛のローラ スリラーバークの花嫁',''], + 811: ['リスキー兄弟',''], + 812: ['ケルベロス',''], + 813: ['タララン','', 'Spider Monkey' ], + 814: ['敷きグマ',''], + 815: ['ゲッコー・モリア スリラーバークの怪人','', 'Gekko Moriah, Thriller Bark\'s Mysterious Four'], + 816: ['ゲッコー・モリア スリラーバークの支配者','', 'Gekko Moriah, Ruler of Thriller Bark'], + 817: ['ソルジャーゾンビ 力自慢の影',''], + 818: ['ソルジャーゾンビ 素早さの影',''], + 819: ['ソルジャーゾンビ 悪巧みの影',''], + 820: ['ソルジャーゾンビ 憎しみの影',''], + 821: ['ソルジャーゾンビ 自尊心の影',''], + 822: ['トリッキー・ワイルドゾンビ',''], + 823: ['インテリ・ワイルドゾンビ',''], + 824: ['ハートフル・ワイルドゾンビ',''], + 825: ['ジェネラルゾンビ 怪力の影',''], + 826: ['ジェネラルゾンビ 奇技の影',''], + 827: ['ジェネラルゾンビ 疾速の影',''], + 828: ['???','','Kid Law','Young Law'], + 829: ['???','','Kid Law','Young Law'], + 830: ['バジル・ホーキンス ホーキンス海賊団船長','','Supernova Hawkins','Coliseum Hawkins', 'Coliseum Basil Hawkins'], + 831: ['魔術師バジル・ホーキンス ホーキンス海賊団船長','','Supernova Hawkins','Coliseum Hawkins', 'Coliseum Basil Hawkins'], + 832: ['ワイパー シャンディアの戦士','', 'Wiper, Warrior of Shandia','Coliseum Wyper' ], + 833: ['戦鬼ワイパー シャンディアの戦士','', 'Berserker Wiper, Warrior of Shandia','Coliseum Wyper' ], + 834: ['Mr.7 & ミス・ファーザーズデー','', 'Mr 7 and Miss Fathers Day', 'Coliseum Mr 7', 'Coliseum Miss Fathers Day'], + 835: ['暴君バーソロミュー・くま','','Raid Kuma'], + 836: ['暴君バーソロミュー・くま 政府の人間兵器','','Raid Kuma'], + 837: ['シーザー・クラウン',''], + 838: ['M(マスター)・シーザー',''], + 839: ['ヴェルゴ',''], + 840: ['ヴェルゴ ドンキホーテ海賊団',''], + 841: ['モネ',''], + 842: ['モネ ドンキホーテ海賊団',''], + 843: ['ベビー5',''], + 844: ['ベビー5 ドンキホーテ海賊団',''], + 845: ['バッファロー',''], + 846: ['バッファロー ドンキホーテ海賊団',''], + 847: ['トム トムズ ワーカーズ',''], + 848: ['伝説の船大工トム トムズ ワーカーズ',''], + 849: ['カティ・フラム トムズ ワーカーズ','', 'Franky, Tom\'s Workers','Young Franky' ], + 850: ['アイスバーグ トムズ ワーカーズ','', 'Iceburg, Tom\'s Workers','Young Iceberg' ], + 851: ['ブリキのワポル',''], + 852: ['スリムアップワポル',''], + 853: ['ロブソン',''], + 854: ['チョッパーの雪遊び','', 'Winter Chopper'], + 855: ['トラファルガー・ロー 聖夜の紳士','','Supernova Law','Christmas Law','CLaw'], + 856: ['トラファルガー・ロー 聖夜の貴公子','','Supernova Law','Christmas Law','CLaw'], + 857: ['ジュエリー・ボニー 食いしん坊のわがままサンタ','','Supernova Bonney'], + 858: ['ジュエリー・ボニー 食いしん坊の欲張りサンタ','','Supernova Bonney'], + 859: ['コビー 海軍本部曹長','','Coliseum Coby'], + 860: ['戦火の勇士コビー 海軍本部曹長','','Coliseum Coby'], + 861: ['レディー・アルビダ うるわしき美女','','Coliseum Alvida'], + 862: ['レディー・アルビダ 絶世の美女','','Coliseum Alvida'], + 863: ['銀世界のナミ','', 'Winter Nami'], + 864: ['ボア・ハンコック 九蛇海賊団船長','','Raid Boa'], + 865: ['女帝ボア・ハンコック 九蛇海賊団船長','','Raid Boa'], + 866: ['ニコ・ロビン 百花繚乱 ウイング“華”','', 'Kimono Robin' ], + 867: ['ウソップ タバスコ星“撃”','', 'Kimono Usopp' ], + 868: ['トニートニー・チョッパー 重量ゴング“獣”','', 'Kimono Chopper' ], + 869: ['ドンキホーテ・ドフラミンゴ ドンキホーテ海賊団','', 'Doffy', 'Legend Doflamingo', 'Legend Doffy', 'Shichibukai' ], + 870: ['天夜叉ドフラミンゴ','', 'Doffy', 'Legend Doflamingo', 'Legend Doffy', 'Shichibukai' ], + 871: ['シュガー',''], + 872: ['シュガー ドンキホーテ海賊団',''], + 873: ['セニョール・ピンク','', 'Senor Pink', 'Senior Pink' ], + 874: ['セニョール・ピンク ドンキホーテ海賊団','', 'Senor Pink', 'Senior Pink' ], + 875: ['トレーボル',''], + 876: ['トレーボル ドンキホーテ海賊団',''], + 877: ['ジョーラ','', 'Giolla', 'Jora' ], + 878: ['ジョーラ ドンキホーテ海賊団','', 'Giolla, Donquixote Pirates', 'Jora' ], + 879: ['ラオG',''], + 880: ['ラオG ドンキホーテ海賊団',''], + 881: ['スクラッチメン・アプー オンエア海賊団船長','','Supernova Apoo','Coliseum Apoo'], + 882: ['海鳴りスクラッチメン・アプー オンエア海賊団船長','','Supernova Apoo','Coliseum Apoo'], + 883: ['ドリー 巨兵海賊団','','Coliseum Dorry'], + 884: ['青鬼のドリー','','Coliseum Dorry'], + 885: ['ジンベエ 鮫の武人','', 'Kimono Jinbe', 'Kimono Jimbei', 'Kimono Jinbei' ], + 886: ['Mr.1 西の海の剣客','', 'Kimono Mr. 1', 'Kimono Mr 1','Daz Bones' ], + 887: ['バギー 陽気なかぶき者','', 'Kimono Buggy', 'Baggy'], + 888: ['ホロホロゴースト',''], + 889: ['ペローナ スリラーバークの怪人',''], + 890: ['ペローナ 巨大なゴーストプリンセス',''], + 891: ['ドクトル・ホグバック スリラーバークの怪人',''], + 892: ['墓場のアブサロム スリラーバークの怪人',''], + 893: ['オーズ 特別ゾンビ',''], + 894: ['ゲッコー・モリア 影の集合地(シャドーズ・アスガルド)','', 'Gekko Moriah, Shadow\'s Asgard'], + 895: ['ブルック 紳士なガイコツ',''], + 896: ['ブルック 麦わらの一味',''], + 897: ['サー・クロコダイル 砂の武将','', 'Kimono Crocodile' ], + 898: ['Mr.3 姑息な楽士','', 'Kimono Mr. 3', 'Kimono Galdino', 'Kimono Mr 3' ], + 899: ['Mr.2・ボン・クレー あやふやな侍','', 'Kimono Mr. 2', 'Kimono Bonclay', 'Kimono Bon Clay', 'Kimono Mr 2' ], + 900: ['フレッシュ・フランキー 健康第一','','Coliseum Franky'], + 901: ['鉄人(サイボーグ)フランキー','','Coliseum Franky'], + 902: ['ブロギー 巨兵海賊団','','Coliseum Broggy'], + 903: ['赤鬼のブロギー','','Coliseum Broggy'], + 904: ['ヨコヅナ','','Coliseum Yokozuna'], + 905: ['ロロノア・ゾロ クライガナ島をさすらう剣士','','3D2Y Zoro','Timeskip Zoro'], + 906: ['ロロノア・ゾロ 世界最強剣士の門弟','','3D2Y Zoro','Timeskip Zoro'], + 907: ['ニコ・ロビン テキーラウルフの収監者','','3D2Y Robin','Timeskip Robin'], + 908: ['ニコ・ロビン 革命の灯火(ともしび)','','3D2Y Robin','Timeskip Robin'], + 909: ['トニートニー・チョッパー トリノ王国の平和の架け橋','','3D2Y Chopper','Timeskip Chopper'], + 910: ['チョッパーマスク 世界の平和を守るヒーロー','','3D2Y Chopper','Timeskip Chopper'], + 911: ['サンジ カマバッカ王国の逃走者','','3D2Y Sanji','Timeskip Sanji'], + 912: ['サンジ 男を懸けた愛の料理人','','3D2Y Sanji','Timeskip Sanji'], + 913: ['ブルック ハラヘッターニャの悪魔王','','3D2Y Brook','Timeskip Brook'], + 914: ['ブルック 骨(ボーン) to be wild!!!','','3D2Y Brook','Timeskip Brook'], + 915: ['ニコ・ロビン オハラの花嫁','','Wedding Nico Robin'], + 916: ['麗らかな才女 ロビン ウエディング','','Bride Nico Robin'], + 917: ['マーガレット',''], + 918: ['マーガレット 護国の戦士',''], + 919: ['アフェランドラ',''], + 920: ['スイトピー','', 'Sweet Pea'], + 921: ['ボア・ハンコック 女ヶ島の花嫁','','Bridal Boa Hancock', " Wedding Hancock"], + 922: ['愛に生きる女帝ハンコック ウエディング','','Bridal Boa Hancock'], + 923: ['南の海のキャプテン・キッド','','Coliseum Kid', 'Coliseum Kidd'], + 924: ['キャプテン・キッド キッド海賊団船長','','Coliseum Kid', 'Coliseum Kidd'], + 925: ['獄卒長サディちゃん','','Coliseum Sadie', 'Secuurity Chief Sadie-chan'], + 926: ['獄卒長サディちゃん 獄卒獣の指揮官','','Coliseum Sadie', 'Secuurity Chief Sadie-chan'], + 927: ['ドーベルマン 海軍本部中将','','Coliseum Doberman'], + 928: ['ハンニャバル','','Hannibal'], + 929: ['ハンニャバル','','Hannibal'], + 930: ['サルデス',''], + 931: ['ブルゴリ ','','Blue Gorilla'], + 932: ['ピーカ','','Raid Pica'], + 933: ['ピーカ ドンキホーテ海賊団','','Raid Pica'], + 934: ['海峡のジンベエ','', 'Jinbe', 'Jimbei', 'Jinbei','INTbe', 'Legend Jinbe', 'Legend Jimbei', 'Legend Jinbei', 'Shichibukai'], + 935: ['海峡のジンベエ 元王下七武海','', 'Jinbe', 'Jimbei', 'Jinbei','INTbe', 'Legend Jinbe', 'Legend Jimbei', 'Legend Jinbei', 'Shichibukai'], + 936: ['モンキー・D・ルフィ 頂上戦争の生還者','','Timeskip Luffy','3D2Y Luffy'], + 937: ['モンキー・D・ルフィ 仲間との誓い『3D2Y』','','Timeskip Luffy','3D2Y Luffy'], + 938: ['ナミ 天候の科学の探求者','','Timeskip Nami','3D2Y Nami'], + 939: ['ナミ 空島ウェザリアの泥棒ネコ','','Timeskip Nami','3D2Y Nami'], + 940: ['ウソップ ボーイン列島の大食漢','','Timeskip Usopp','3D2Y Usopp'], + 941: ['ウソップ おいはぎの森の果敢な戦士','','Timeskip Usopp','3D2Y Usopp'], + 942: ['フランキー メカアニマルと戦う改造人間','','Timeskip Franky','3D2Y Franky'], + 943: ['鉄人(サイボーグ)フランキー バルジモアの霊獣','','Timeskip Franky','3D2Y Franky'], + 944: ['???','','Wedding Perona'], + 945: ['???','','Bride Perona'], + 946: ['ラクヨウ 白ひげ海賊団7番隊隊長',''], + 947: ['フォッサ 白ひげ海賊団15番隊隊長',''], + 948: ['クリエル 白ひげ海賊団10番隊隊長',''], + 949: ['サッチ 白ひげ海賊団4番隊隊長',''], + 950: ['火拳のエース','','Coliseum Ace'], + 951: ['火拳のエース 白ひげ海賊団2番隊隊長','', 'Coliseum Ace'], + 952: ['ベン・ベックマン','', 'Coliseum Ben Beckman', 'Coliseum Benn Beckman'], + 953: ['ベン・ベックマン 赤髪海賊団','', 'Coliseum Ben Beckman', 'Coliseum Benn Beckman'], + 954: ['ギャロ',''], + 955: ['マクロ','','Makuro'], + 956: ['タンスイ',''], + 957: ['早業のガンマン 青のボディガード',''], + 958: ['計略のガンマン 黒のボディガード',''], + 959: ['技巧のガンマン 緑のボディガード',''], + 960: ['速攻のガンマン 青のボディガード',''], + 961: ['豪腕のガンマン 赤のボディガード',''], + 962: ['強心のガンマン 黄のボディガード',''], + 963: ['チャルロス聖',''], + 964: ['ロズワード聖',''], + 965: ['シャルリア宮',''], + 966: ['ユースタス・キッド 超新星(スーパールーキー)','', 'Story Kidd'], + 967: ['トラファルガー・ロー 超新星(スーパールーキー)',''], + 968: ['パシフィスタ PX-1',''], + 969: ['パシフィスタ PX-2',''], + 970: ['パシフィスタ PX-3',''], + 971: ['パシフィスタ PX-4',''], + 972: ['パシフィスタ PX-5',''], + 973: ['戦桃丸','','Sentoumaru'], + 974: ['戦桃丸 海軍本部科学部隊隊長','','Sentoumaru'], + 975: ['スモーカー あらくれの一匹オオカミ','','Kid Smoker'], + 976: ['スモーカー 孤高の一匹オオカミ','','Kid Smoker'], + 977: ['黄猿','','Raid Borsalino', 'Raid Kizaru'], + 978: ['黄猿 光人間','','Raid Borsalino', 'Raid Kizaru'], + 979: ['イゾウ 白ひげ海賊団16番隊隊長',''], + 980: ['ブラメンコ 白ひげ海賊団6番隊隊長',''], + 981: ['ナミュール 白ひげ海賊団8番隊隊長',''], + 982: ['ビスタ 白ひげ海賊団5番隊隊長','','Coliseum Vista'], + 983: ['花剣のビスタ 白ひげ海賊団5番隊隊長','','Coliseum Vista'], + 984: ['パウリー ガレーラカンパニー1番ドック職長','','Coliseum Paulie'], + 985: ['デマロ・ブラック&ショコラ ニセ麦わらの一味','','Raid', 'Imposter', 'Fake'], + 986: ['ココア&のらギツネ ニセ麦わらの一味','','Raid', 'Imposter', 'Fake'], + 987: ['マンジャロウ&ドリップ ニセ麦わらの一味','','Raid', 'Imposter', 'Fake'], + 988: ['マウンブルテン&トルコ ニセ麦わらの一味','','Raid', 'Imposter', 'Fake'], + 989: ['ニセ麦わらの一味','','Raid', 'Imposter', 'Fake'], + 990: ['マッハ・バイス','','Mach Vise'], + 991: ['マッハ・バイス ドンキホーテ海賊団', '', 'Mach Vise'], + 992: ['グラディウス',''], + 993: ['グラディウス ドンキホーテ海賊団',''], + 994: ['ヴァイオレット','', 'Viola'], + 995: ['ヴァイオレット ドンキホーテ海賊団','', 'Viola'], + 996: ['デリンジャー',''], + 997: ['デリンジャー ドンキホーテ海賊団',''], + 998: ['ディアマンテ',''], + 999: ['ディアマンテ ドンキホーテ海賊団',''], + 1000: ['コラソン ドンキホーテ海賊団','','Rocinante','Rosinante', 'Corasan', 'Legend Corazon', 'Donquixote Rosinante'], + 1001: ['ドンキホーテ・ロシナンテ','','Rocinante','Corazon', 'Corasan', 'Legend Corazon'], + 1002: ['ベポ ハートの海賊団',''], + 1003: ['武闘家のベポ ハートの海賊団',''], + 1004: ['シャチ&ペンギン ハートの海賊団',''], + 1005: ['ジャンバール',''], + 1006: ['ジャンバール ハートの海賊団',''], + 1007: ['モネ 寒桜','','Sakura Monet'], + 1008: ['モネ 大寒桜','','Sakura Monet'], + 1009: ['キズナBOOOOSTルフィ','', 'Afro Luffy', 'Afroluffy' ], + 1010: ['バトラー伯爵',''], + 1011: ['バトラー伯爵(王なる力)',''], + 1012: ['ヘビー総裁',''], + 1013: ['ホットドッグ将軍',''], + 1014: ['トニートニー・チョッパー 動物王',''], + 1015: ['カポネ・ベッジ ファイアタンク海賊団船長','','Coliseum Capone Bege'], + 1016: ['カポネ・“ギャング”ベッジ ファイアタンク海賊団船長','','Coliseum Capone Bege'], + 1017: ['茶ひげ','','Coliseum Brownbeard'], + 1018: ['茶ひげ ワニのケンタウロス','','Coliseum Brownbeard'], + 1019: ['ピープリー・ルル ガレーラカンパニー1番ドック職長','','Coliseum Lulu'], + 1020: ['シュガー 実桜','','Sakura Sugar'], + 1021: ['シュガー 桜桃','','Sakura Sugar'], + 1022: ['モンキー・D・ルフィ 海賊王への軌跡','','Anniversary Luffy'], + 1023: ['ポートガス・D・エース 海賊王に馳せた夢',''], + 1024: ['首領・チンジャオ','Don Chinjao'], + 1025: ['首領・チンジャオ 花ノ国のギャング','Don Chinjao'], + 1026: ['ブルーギリー',''], + 1027: ['ブルーギリー 脚功道格闘家(ジャオクンドー)',''], + 1028: ['ボビー・ファンク&ケリー・ファンク',''], + 1029: ['ファンク兄弟 モガロ王国の殺し屋',''], + 1030: ['ハイルディン',''], + 1031: ['ハイルディン 海賊傭兵',''], + 1032: ['アブドーラ&ジェット','','Abdullah and Jeet'], + 1033: ['アブドーラ&ジェット 元賞金稼ぎ','','Abdullah and Jeet, Former Bounty Hunters'], + 1034: ['バルトロメオ','', 'Legend Bartolomeo'], + 1035: ['人食いのバルトロメオ','', 'Legend Bartolomeo'], + 1036: ['エンポリオ・イワンコフ 秘密の花園の女王',''], + 1037: ['エンポリオ・イワンコフ 奇跡を起こす花園の女王',''], + 1038: ['イナズマ 秘密の花園の乙女',''], + 1039: ['イナズマ 変革を画策する乙女',''], + 1040: [ 'ジョズ 白ひげ海賊団3番隊隊長', '','Coliseum Jozu' ], + 1041: [ '“ダイヤモンド”・ジョズ 白ひげ海賊団3番隊隊長', '','Coliseum Jozu' ], + 1042: [ 'キラー キッド海賊団', '','Coliseum Killer', 'Supernova Killer' ], + 1043: [ '“殺戮武人”キラー キッド海賊団', '','Coliseum Killer', 'Supernova Killer' ], + 1044: [ 'トラファルガー・ロー 最悪の世代', '','LLaw','PLaw', 'Legend Trafalgar Law', 'Legend Law', 'Shichibukai'], + 1045: [ 'トラファルガー・ロー 王下七武海', '','LLaw','PLaw', 'Legend Trafalgar Law', 'Legend Law', 'Shichibukai' ], + 1046: [ 'サボ 竜の爪', '','Raid Sabo' ], + 1047: [ 'サボ 革命軍参謀総長', '','Raid Sabo' ], + 1048: [ 'ニコ・オルビア', '' ], + 1049: [ 'ニコ・オルビア オハラの考古学者', '' ], + 1050: [ 'ハグワール・D・サウロ', '' ], + 1051: [ 'ハグワール・D・サウロ 海軍本部中将', '' ], + 1052: [ 'ニコ・ロビン オハラの少女', '' ], + 1053: [ 'ヒナ おしとやかな優等生', '', 'Kid Hina' ], + 1054: [ 'ヒナ れいぎ正しい優等生', '', 'Kid Hina' ], + 1055: [ 'ボア・サンダーソニア', '' ], + 1056: [ 'ボア・サンダーソニア 九蛇海賊団', '' ], + 1057: [ 'ボア・マリーゴールド', '' ], + 1058: [ 'ボア・マリーゴールド 九蛇海賊団', '' ], + 1059: [ 'マーガレット 女戦士', '' ], + 1060: [ 'マーガレット 九蛇の戦士', '' ], + 1061: [ 'キキョウ', '' ], + 1062: [ 'グロリオーサ', '' ], + 1063: [ '破壊の女射手 九蛇の戦士', '' ], + 1064: [ '謀略の女射手 九蛇の戦士', '' ], + 1065: [ 'かしこい女剣士 九蛇の戦士', '' ], + 1066: [ 'あかるい女剣士 九蛇の戦士', '' ], + 1067: [ '熟練女格闘士 九蛇の戦士', '' ], + 1068: [ '敏捷女格闘士 九蛇の戦士', '' ], + 1069: [ 'シュライヤ・バスクード', '', 'Shovel Guy' ], + 1070: [ 'シュライヤ・バスクード 海賊処刑人', '', 'Shovel Guy' ], + 1071: [ 'ガスパーデ', '' ], + 1072: [ 'ガスパーデ ガスパーデ海賊団', '' ], + 1073: [ 'ニードルス', '' ], + 1074: [ 'リッキー', '', 'King Riku' ], + 1075: [ 'リッキー 謎の剣闘士', '', 'King Riku' ], + 1076: [ 'レオ', '' ], + 1077: [ 'レオ トンタッタ族戦士長', '' ], + 1078: [ 'マンシェリー', '' ], + 1079: [ 'マンシェリー トンタッタ族王女', '' ], + 1080: [ 'キュロス', '' ], + 1081: [ 'キュロス 元リク王軍軍隊長', '' ], + 1082: [ '首領・サイ', '' ], + 1083: [ '首領・サイ 花ノ国のギャング', '' ], + 1084: [ '藤虎', '', 'Issho', 'Legend Issho', 'Legend Fujitora'], + 1085: [ 'イッショウ', '', 'Fujitora', 'Legend Issho', 'Legend Fujitora' ], + 1086: [ 'ムッシュール', '','Coliseum Musshuru' ], + 1087: [ 'ムッシュール 毒胞子人間', '','Coliseum Musshuru' ], + 1088: [ 'サガ', '','Coliseum Saga' ], + 1089: [ 'サガ 呪われた聖剣', '','Coliseum Saga' ], + 1090: [ 'X・ドレーク ドレーク海賊団', '', 'Coliseum Drake', 'Coliseum X Drake', 'Supernova Drake', 'Supernova X Drake' ], + 1091: [ '赤旗 X・ドレーク ドレーク海賊団', 'Coliseum Drake', 'Coliseum X Drake', 'Supernova Drake', 'Supernova X Drake' ], + 1092: [ 'レベッカ パラソルのリズム', '','Kid Rebecca' ], + 1093: [ 'レベッカ 虹のメロディ', '','Kid Rebecca' ], + 1094: [ 'Dr.インディゴ', '' ], + 1095: [ 'Dr.インディゴ 金獅子海賊団', '' ], + 1096: [ 'スカーレット隊長', '' ], + 1097: [ 'スカーレット隊長 金獅子海賊団', '' ], + 1098: [ '雷鳥ビリー', '' ], + 1099: [ 'コビー 雨の中の曹長', '' ], + 1100: [ 'コビー 露にきらめく曹長', '' ], + 1101: [ '黒腕のゼファー', '','Coliseum Zephyr' ], + 1102: [ '黒腕のゼファー 元海軍本部大将', '','Coliseum Zephyr' ], + 1103: [ 'アイン NEO海軍', '','Coliseum Ain' ], + 1104: [ 'アイン ゼファー最後の教え子', '','Coliseum Ain' ], + 1105: [ 'ビンズ NEO海軍', '','Coliseum Binz' ], + 1106: [ 'ビンズ ゼファー最後の教え子', '','Coliseum Binz' ], + 1107: [ '金獅子のシキ', '','Raid Shiki' ], + 1108: [ '金獅子のシキ 金獅子海賊団', '','Raid Shiki' ], + 1109: [ 'ナミ 若返った航海士', '' ], + 1110: [ 'ナミ 酒場のお茶目なアイドル', '' ], + 1111: [ 'ニコ・ロビン 若返った考古学者', '' ], + 1112: [ 'ニコ・ロビン 酒場の可憐な踊り娘', '' ], + 1113: [ 'チョッパー 若返った船医', '' ], + 1114: [ 'モンキー・D・ルフィ 夢を追い求める冒険者', 'New Strong World Luffy', 'SW Luffy' ], + 1115: [ 'モンキー・D・ルフィ 信念に生きる麦わらの一味', 'New Strong World Luffy', 'SW Luffy' ], + 1116: [ 'サンジ 夢を追い求める冒険者', 'New Strong World Sanji', 'SW Sanji' ], + 1117: [ 'サンジ 信念に生きる麦わらの一味', 'New Strong World Sanji', 'SW Sanji' ], + 1118: [ 'ナミ 夢を追い求める冒険者', 'New Strong World Nami', 'SW Nami' ], + 1119: [ 'ナミ 信念に生きる麦わらの一味', 'New Strong World Nami', 'SW Nami' ], + 1120: [ 'モンキー・D・ルフィ 終わらぬ夢の航跡・麦わらの一味', '', 'Log Luffy', 'Logfy', 'LL', 'Legend Luffy', 'Legend LL' ], + 1121: [ 'モンキー・D・ルフィ 大海賊時代への誓い「海賊王」', '', 'Log Luffy', 'Logfy', 'LL', 'Legend Luffy', 'Legend LL' ], + 1122: [ 'キャベンディッシュ', '','Hakuba', 'Cabbage', 'Legend Cavendish', 'Legend Hakuba' ], + 1123: [ '白馬のキャベンディッシュ', '','Hakuba', 'Cabbage', 'Legend Cavendish', 'Legend Hakuba' ], + 1124: ['スレイマン',''], + 1125: ['首はねスレイマン',''], + 1126: ['オオロンブス',''], + 1127: ['オオロンブス 殺戮支配者',''], + 1128: ['ダガマ',''], + 1129: ['ダガマ プロデンス王国軍師',''], + 1130: ['エリザベローII世',''], + 1131: ['エリザベローII世 プロデンス王国国王',''], + 1132: ['イデオ',''], + 1133: ['イデオ 破壊砲',''], + 1134: ['たしぎ がむしゃらな剣道少女','','Young Tashigi', 'Kid Tashigi'], + 1135: ['たしぎ 夢見る剣道少女','','Young Tashigi', 'Kid Tashigi'], + 1136: ['フクロウ 世界政府直下暗躍諜報機関',''], + 1137: ['ジャブラ 世界政府直下暗躍諜報機関','','Jabura'], + 1138: ['ブルーノ 世界政府直下暗躍諜報機関',''], + 1139: ['クマドリ 世界政府直下暗躍諜報機関',''], + 1140: ['ゲッコー・モリア 魔の三角地帯の主','','Coliseum Gekko Moriah'], + 1141: ['ゲッコー・モリア 魔の三角地帯の支配者','','Coliseum Gekko Moriah'], + 1142: ['フォクシー ドーナツレースの邪魔者','','Coliseum Foxy','Dying Foxy'], + 1143: ['フォクシー コンバットの卑怯者','','Coliseum Foxy','Nurse Foxy'], + 1144: ['ポルチェ お花チアリーダーズ','','Coliseum Porche'], + 1145: ['ポルチェ キューティバトンの使い手','','Coliseum Porche'], + 1146: ['制圧の制服看守',''], + 1147: ['火急の制服看守',''], + 1148: ['包囲の制服看守',''], + 1149: ['理論派獄卒',''], + 1150: ['行動派獄卒',''], + 1151: ['ミノタウロス',''], + 1152: ['ミノゼブラ',''], + 1153: ['スフィンクス',''], + 1154: ['サルデス 牢番長',''], + 1155: ['軍隊ウルフ',''], + 1156: ['ハンニャバル副署長',''], + 1157: ['ハンニャバル副署長 海底監獄インペルダウン',''], + 1158: ['マゼラン署長',''], + 1159: ['マゼラン署長 海底監獄インペルダウン',''], + 1160: ['コアラ ビーチの天使','','Summertime Koala','Swimsuit Koala'], + 1161: ['コアラ 楽園の女神','','Summertime Koala','Swimsuit Koala'], + 1162: ['ギルド・テゾーロ','','Raid Tesoro'], + 1163: ['ギルド・テゾーロ 黄金船のカジノ王','','Raid Tesoro'], + 1164: ['カリーナ','','Raid Carina'], + 1165: ['カリーナ 黄金船の歌姫','','Raid Carina'], + 1166: ['バカラ',''], + 1167: ['バカラ 黄金船のコンシェルジュ',''], + 1168: ['ダイス',''], + 1169: ['ダイス 黄金船のディーラー',''], + 1170: ['タナカさん',''], + 1171: ['タナカさん 黄金船の警備担当',''], + 1172: ['ブルック 夢を追い求める冒険者','','New Strong World Brook', 'SW Brook' ], + 1173: ['ブルック 信念に生きる麦わらの一味','','New Strong World Brook', 'SW Brook' ], + 1174: ['ロロノア・ゾロ 夢を追い求める冒険者','','New Strong World Zoro', 'SW Zoro' ], + 1175: ['ロロノア・ゾロ 信念に生きる麦わらの一味','','New Strong World Zoro', 'SW Zoro' ], + 1176: ['チョッパー 夢を追い求める冒険者','','New Strong World Chopper', 'SW Chopper' ], + 1177: ['チョッパー 信念に生きる麦わらの一味','','New Strong World Chopper', 'SW Chopper' ], + 1178: ['オーズ','','Oz'], + 1179: ['魔人オーズ','','Oz'], + 1180: ['虹ヨロイガニ',''], + 1181: ['ブレンハイム',''], + 1182: ['カトラスのブレンハイム',''], + 1183: ['キングデュー','','Heman'], + 1184: ['双拳ガントレットのキングデュー','','Heman'], + 1185: ['ハルタ',''], + 1186: ['疾風の小剣士ハルタ',''], + 1187: ['アトモス',''], + 1188: ['水牛のアトモス',''], + 1189: ['スピード・ジル','', 'Speed Jiru', 'Genocide Jil' ], + 1190: ['シールドランスのスピード・ジル','', 'Speed Jiru', 'Genocide Jil' ], + 1191: ['青キジ 海軍本部最高戦力','','Kuzan','Legend Kuzan', 'Legend Aokiji'], + 1192: ['クザン','','Aokiji','Legend Kuzan', 'Legend Aokiji'], + 1193: ['ボア・ハンコック 渚にたたずむ女帝','','Summertime Hancock','Swimsuit Hancock'], + 1194: ['ボア・ハンコック 恋に溺れた乙女','','Summertime Hancock','Swimsuit Hancock'], + 1195: ['ガン・フォール 先代“神”','','Coliseum Gan Fall', 'Coliseum Ganfor', 'Ganfall'], + 1196: ['ガン・フォール スカイピアの神','','Coliseum Gan Fall', 'Coliseum Ganfor', 'Ganfall'], + 1197: ['スカイブリーダー・オーム','','Coliseum Ohm'], + 1198: ['ジュエリー・ボニー 弾けるサファイア','','Summertime Jewelry Bonney','Swimsuit Jewelry Bonney'], + 1199: ['ジュエリー・ボニー パールホワイトの煌き','','Summertime Jewelry Bonney','Swimsuit Jewelry Bonney'], + 1200: ['ヴァイオレット 挑発のバカンス','','Summertime Viola','Swimsuit Viola'], + 1201: ['ヴァイオレット 紅潮のバカンス','','Summertime Viola','Swimsuit Viola'], + 1202: ['ヨーキ',''], + 1203: ['キャラコのヨーキ',''], + 1204: ['ブルック ルンバー海賊団',''], + 1205: ['“音楽家兼剣士”ブルック ルンバー海賊団',''], + 1206: ['ラブーン ルンバー海賊団',''], + 1207: ['ニコ・ロビン 夢を追い求める冒険者','','New Strong World Robin', 'SW Robin' ], + 1208: ['ニコ・ロビン 信念に生きる麦わらの一味','','New Strong World Robin', 'SW Robin' ], + 1209: ['ウソップ 夢を追い求める冒険者','','New Strong World Usopp', 'SW Usopp' ], + 1210: ['ウソップ 信念に生きる麦わらの一味','','New Strong World Usopp', 'SW Usopp' ], + 1211: ['フランキー 夢を追い求める冒険者','','New Strong World Franky', 'SW Franky' ], + 1212: ['フランキー 信念に生きる麦わらの一味','','New Strong World Franky', 'SW Franky' ], + 1213: ['ベビー5 ドルフィンフロート','','Summertime Baby 5','Swimsuit Baby 5'], + 1214: ['ベビー5 ドルフィンライダー','','Summertime Baby 5','Swimsuit Baby 5'], + 1215: ['ガイラム ワールド海賊団','',''], + 1216: ['セバスチャン ワールド海賊団','',''], + 1217: ['ナイチン ワールド海賊団','',''], + 1218: ['ボア・ハンコック アマゾン・リリー皇帝','',''], + 1219: ['バーンディ・ワールド','','Coliseum World', 'Coliseum Byrnndi World'], + 1220: ['バーンディ・ワールド ワールド海賊団船長','','Coliseum World', 'Coliseum Byrnndi World'], + 1221: ['リトルオーズJr. 白ひげ海賊団傘下','','Coliseum Oars Jr.'], + 1222: ['猛攻のリトルオーズJr. 白ひげ海賊団傘下','','Coliseum Oars Jr.'], + 1223: ['バスティーユ','',''], + 1224: ['ヤマカジ','',''], + 1225: ['ヒナ 黒檻部隊','',''], + 1226: ['スモーカー 海軍本部准将','',''], + 1227: ['ジュラキュール・ミホーク 鷹の目','',''], + 1228: ['黄猿 海軍本部大将','',''], + 1229: ['戦桃丸 海軍本部将校','','Sentoumaru'], + 1230: ['鉞の戦桃丸 海軍本部将校','','Sentoumaru'], + 1231: ['スモーカー 海軍GL第5支部','',''], + 1232: ['スモーカー 海軍GL第5支部「G‐5」中将','',''], + 1233: ['たしぎ 海軍GL第5支部','','Thiccshigi'], + 1234: ['たしぎ 海軍GL第5支部「G‐5」大佐','','Thiccshigi'], + 1235: ['メイナード 海軍本部中将','',''], + 1236: ['追撃のメイナード 海軍本部中将','',''], + 1237: ['バスティーユ 海軍本部中将','',''], + 1238: ['鮫切りバスティーユ 海軍本部中将','',''], + 1239: ['黄猿 海軍本部最高戦力','','Borsalino', 'Legend Kizaru', 'Legend Borsalino'], + 1240: ['ボルサリーノ','','Kizaru', 'Legend Kizaru', 'Legend Borsalino'], + 1241: ['コアラ 魚人空手師範代','',''], + 1242: ['コアラ 革命軍・魚人空手師範代','',''], + 1243: ['ハック 魚人空手師範','',''], + 1244: ['ハック 革命軍・魚人空手師範','',''], + 1245: ['モンキー・D・ルフィ マリンフォードに舞う“麦わら”','',''], + 1246: ['ポートガス・D・エース 処刑台の“火拳”','',''], + 1247: ['ポートガス・D・エース マリンフォードに舞う“火拳”','',''], + 1248: ['マルコ 秋風にはためく襟元','','Kimono Marco'], + 1249: ['マルコ ほろ酔いの着崩れ','','Kimono Marco'], + 1250: ['マルコ 白ひげ海賊団','','Coliseum Marco'], + 1251: ['マルコ 復活の炎 白ひげ海賊団','','Coliseum Marco'], + 1252: ['遊騎士ドーマ 白ひげ海賊団傘下','','Coliseum Doma'], + 1253: ['スカイライダー・シュラ','','Coliseum Shura'], + 1254: ['大渦蜘蛛スクアード 白ひげ海賊団傘下','','Squardo'], + 1255: ['絆のディカルバン兄弟 白ひげ海賊団傘下','',''], + 1256: ['“氷の魔女”ホワイティベイ 白ひげ海賊団傘下','',''], + 1257: ['エドワード・ニューゲート 海賊王のライバル','', 'Edward Newgate', 'Young Whitebeard', 'YWB'], + 1258: ['エドワード・ニューゲート 大海賊“白ひげ”','', 'Edward Newgate', 'Young Whitebeard', 'YWB'], + 1259: ['ドンキホーテ・ドフラミンゴ “北の海”の海賊','','Young Doffy','Donquixote Doflamingo'], + 1260: ['ドンキホーテ・ドフラミンゴ “北の海”の闇','','Young Doffy','Donquixote Doflamingo'], + 1261: ['セニョール・ピンク “北の海”の海賊','','Senor Pink', 'Young Senior Pink'], + 1262: ['セニョール・ピンク “北の海”の闇','','Senor Pink', 'Young Senior Pink'], + 1263: ['ヴェルゴ “北の海”の海賊','','Young Vergo'], + 1264: ['ヴェルゴ “北の海”の闇','','Young Vergo'], + 1265: ['エース 黄昏の道草','','Kimono Ace'], + 1266: ['エース 月下の艶肌','','Kimono Ace'], + 1267: ['マーシャル・D・ティーチ 黒ひげ海賊団船長','','BB', 'Legend Blackbeard', 'Legend BB', 'Legend Marshall D. Teach', 'Legend Teach', 'Yonko'], + 1268: ['黒ひげ 黒ひげ海賊団船長','','BB', 'Teach', 'Legend Blackbeard', 'Legend BB', 'Legend Marshall D. Teach', 'Legend Teach', 'Yonko'], + 1269: ['ラフィット','','Lafitte'], + 1270: ['“鬼保安官”ラフィット','','Lafitte'], + 1271: ['ヴァン・オーガー','','Vaper', 'Van Ogre'], + 1272: ['“音越”ヴァン・オーガー','','Vaper', 'Van Ogre'], + 1273: ['ジーザス・バージェス','',''], + 1274: ['“チャンピオン”ジーザス・バージェス','',''], + 1275: ['シリュウ','','Shiliew'], + 1276: ['雨のシリュウ','','Shiliew'], + 1277: ['ドクQ','',''], + 1278: ['“死神”ドクQ','',''], + 1279: ['ジョン・ジャイアント','',''], + 1280: ['青キジ 海軍本部大将','','Kuzan'], + 1281: ['ガープ 海軍本部中将','',''], + 1282: ['センゴク 海軍本部元帥','',''], + 1283: ['赤犬 海軍本部大将','','Sakazuki'], + 1284: ['モンキー・D・ルフィ 野生の海賊','','Wild Luffy'], + 1285: ['モンキー・D・ルフィ 大地の開拓者','','Wild Luffy'], + 1286: ['ベビー5 スパイダーマイルズの少女','','Kid Baby 5'], + 1287: ['ベビー5 ドンキホーテファミリーの一員','','Kid Baby 5'], + 1288: ['トラファルガー・ロー スパイダーマイルズの少年','','Kid Trafalgar Law', 'Kid Law'], + 1289: ['トラファルガー・ロー ドンキホーテファミリーの一員','','Kid Trafalgar Law', 'Kid Law'], + 1290: ['バッファロー ドンキホーテファミリーの一員','','Kid Buffalo'], + 1291: ['ラオG 地翁拳の使い手','','Coliseum Lao G'], + 1292: ['ラオG ディアマンテ軍幹部','','Coliseum Lao G'], + 1293: ['ボア・サンダーソニア 九蛇の戦士','','Coliseum Sandersonia','Coliseum Boa Sandersonia'], + 1294: ['ボア・サンダーソニア ゴルゴン三姉妹・次女','','Coliseum Sandersonia','Coliseum Boa Sandersonia'], + 1295: ['カリファ グラマラスミイラ','','Halloween Kalifa'], + 1296: ['カリファ グラマラスミイラ ハロウィンナイト・マスカレード','','Halloween Kalifa'], + 1297: ['赤犬','','Raid Sakazuki', 'Raid Akainu'], + 1298: ['赤犬 マグマ人間','','Raid Sakazuki', 'Raid Akainu'], + 1299: ['レベッカ ラブリーモンスターキャット','','Halloween Rebecca'], + 1300: ['レベッカ ラブリーモンスターキャット ハロウィンナイト・マスカレード','','Halloween Rebecca'], + 1301: ['受刑者 バギー','','Baggy'], + 1302: ['受刑者 道化のバギー 脱獄同盟','','Baggy'], + 1303: ['脱走囚 ギャルディーノ','','Mr 3', 'Mr. 3'], + 1304: ['脱走囚 ギャルディーノ 脱獄同盟','','Mr 3', 'Mr. 3'], + 1305: ['シュガー リトルサキュバス','','Halloween Sugar'], + 1306: ['シュガー リトルサキュバス ハロウィンナイト・マスカレード','','Halloween Sugar'], + 1307: ['バルトロメオ フルムーンウルフ','','Halloween Bartolomeo'], + 1308: ['バルトロメオ フルムーンウルフ ハロウィンナイト・マスカレード','','Halloween Bartolomeo'], + 1309: ['錦えもん','','Coliseum Kinemon','Coliseum Kin\'emon'], + 1310: ['狐火の錦えもん','','Coliseum Kinemon','Coliseum Kin\'emon'], + 1311: ['ボア・マリーゴールド 九蛇の戦士','','Coliseum Marigold','Coliseum Boa Marigold'], + 1312: ['ボア・マリーゴールド ゴルゴン三姉妹・三女','','Coliseum Marigold','Coliseum Boa Marigold'], + 1313: ['赤犬 海軍本部最高戦力','','Sakazuki', 'Legend Sakazuki', 'Legend Akainu'], + 1314: ['サカズキ','','Akainu', 'Legend Sakazuki', 'Legend Akainu'], + 1315: ['海軍本部曹長 コビー “偉大なる航路”の海兵','',''], + 1316: ['海軍本部曹長 コビー “海軍の英雄”の教え子','',''], + 1317: ['モンキー・D・ガープ 海軍本部中将','',''], + 1318: ['ゲンコツのガープ 海軍本部中将','',''], + 1319: ['つる 海軍本部中将','',''], + 1320: ['“大参謀”つる 海軍本部中将','',''], + 1321: ['モモンガ 怪物斬りの名将','',''], + 1322: ['海軍本部中将モモンガ 怪物斬りの名将','',''], + 1323: ['オニグモ 八刀流の剣士','',''], + 1324: ['海軍本部中将オニグモ 八刀流の剣士','',''], + 1325: ['コラソン ロイヤルヴァンパイア','','Halloween Corazon'], + 1326: ['コラソン ロイヤルヴァンパイア ハロウィンナイト・マスカレード','','Halloween Corazon'], + 1327: ['レオ トンタッタ族トンタ兵団','',''], + 1328: ['戦士レオ トンタッタ族トンタ兵団','',''], + 1329: ['ウィッカ','','Wicka'], + 1330: ['ガンチョ','',''], + 1331: ['マンシェリー トンタ長の娘','',''], + 1332: ['マンシェリー トンタッタ王国の姫','',''], + 1333: ['カブ','',''], + 1334: ['ビアン','',''], + 1335: ['サボ 貴女との一幕','','Gentleman Sabo'], + 1336: ['サボ 劇場の怪人','','Gentleman Sabo'], + 1337: ['カン十郎','','Coliseum Kanjuro'], + 1338: ['夕立ち カン十郎','','Coliseum Kanjuro'], + 1339: ['トニートニー・チョッパー 飛力強化(ジャンピングポイント)','','Coliseum Chopper','Coliseum Tony Tony Chopper'], + 1340: ['ゲダツ スカイピア神官','','Coliseum Gedatsu'], + 1341: ['空番長 ゲダツ スカイピア神官','','Coliseum Gedatsu'], + 1342: ['カーリー・ダダン','',''], + 1343: ['ポルシェーミ','',''], + 1344: ['ブルージャム','',''], + 1345: ['ジンベエ 魚人海賊団船長','','Jinbe','Jimbei','Jinbei'], + 1346: ['ヘラクレス おいはぎの森のスゴ腕先生','',''], + 1347: ['トリノ王国の怪鳥','',''], + 1348: ['ヒューマンドリル','',''], + 1349: ['ハレダス','',''], + 1350: ['テーナ・ゲーナ王国の手長族','',''], + 1351: ['テキーラウルフの警備兵','',''], + 1352: ['エンポリオ・イワンコフ キングオブニューカマー','',''], + 1353: ['シルバーズ・レイリー 海賊王の船員','','Silvers Rayleigh'], + 1354: ['シルバーズ・レイリー 眠らぬ街のマスター','','Secret Rayleigh', 'Silvers Rayleigh'], + 1355: ['シルバーズ・レイリー ライムライトに煌く冥王','','Secret Rayleigh', 'Silvers Rayleigh'], + 1356: ['ペコムズ','',''], + 1357: ['ペコムズ ビッグ・マム海賊団','',''], + 1358: ['タマゴ男爵','',''], + 1359: ['タマゴ男爵 ビッグ・マム海賊団','',''], + 1360: ['ルフィの冬島冒険','','Winter Luffy'], + 1361: ['ロロノア・ゾロ 集結の麦わらの一味','','New World Zoro', 'Timeskip Zoro', 'TS Zoro', 'Legend Zoro', 'Legend Roronoa Zoro'], + 1362: ['ロロノア・ゾロ 新生・麦わらの一味','','New World Zoro', 'Timeskip Zoro', 'TS Zoro', 'Legend Zoro', 'Legend Roronoa Zoro'], + 1363: ['フランキー 集結の麦わらの一味','','New World Franky', 'Timeskip Franky', 'TS Franky'], + 1364: ['フランキー 新生・麦わらの一味','','New World Franky', 'Timeskip Franky', 'TS Franky'], + 1365: ['ナミ 集結の麦わらの一味','','New World Nami', 'Timeskip Nami', 'TS Nami'], + 1366: ['ナミ 新生・麦わらの一味','','New World Nami', 'Timeskip Nami', 'TS Nami'], + 1367: ['サンジ 集結の麦わらの一味','','New World Sanji', 'Timeskip Sanji', 'TS Sanji'], + 1368: ['サンジ 新生・麦わらの一味','','New World Sanji', 'Timeskip Sanji', 'TS Sanji'], + 1369: ['トニートニー・チョッパー 集結の麦わらの一味','','New World Chopper', 'Timeskip Chopper', 'TS Chopper'], + 1370: ['トニートニー・チョッパー 新生・麦わらの一味','','New World Chopper', 'Timeskip Chopper', 'TS Chopper'], + 1371: ['ロロノア・ゾロ 野生の海賊','','Wild Zoro'], + 1372: ['ロロノア・ゾロ 大地の開拓者','','Wild Zoro'], + 1373: ['マゼラン','','Raid Magellan'], + 1374: ['マゼラン 監獄署長','','Raid Magellan'], + 1375: ['デリンジャー 闘魚の血を引く半魚人', '', 'Coliseum Dellinger'], + 1376: ['デリンジャー ディアマンテ軍戦闘員', '', 'Coliseum Dellinger'], + 1377: ['マーガレット アマゾン・リリーの弓兵', '', 'Coliseum Marguerite'], + 1378: ['マーガレット 九蛇の覇気使い', '', 'Coliseum Marguerite'], + 1379: ['シャンクス 赤髪海賊団大頭', '', 'Coliseum Shanks'], + 1380: ['赤髪のシャンクス 赤髪海賊団大頭', '', 'Coliseum Shanks'], + 1381: ['', '', 'Christmas Tashigi'], + 1382: ['', '', 'Christmas Tashigi'], + 1383: ['オモチャの兵隊さん', '', 'Toy Soldier', 'Kyros'], + 1384: ['オモチャの兵隊さん 雷兵', '', 'Toy Soldier', 'Kyros'], + 1385: ['レベッカ 生き残った旧王家の血', '', 'Kid Rebecca'], + 1386: ['レベッカ 狙われる旧王家の血', '', 'Kid Rebecca'], + 1387: ['', '', 'Mega Luffy', 'Super Luffy'], + 1388: ['ロロノア・ゾロ 厄港鳥(ヤッコウドリ)', '', 'Mega Zoro', 'Super Zoro'], + 1389: ['ナミ サンダーブリード=テンポ', '', 'Mega Nami', 'Super Nami'], + 1390: ['道化のバギー バギー海賊団船長', '', 'Legend Buggy', 'Legend Baggy', 'Shichibukai'], + 1391: ['キャプテン・バギー', '', 'Legend Buggy', 'Legend Baggy', 'Shichibukai'], + 1392: ['戦桃丸 シャボンディ諸島の壁', '', ''], + 1393: ['デマロ・ブラック', '', 'Fake Straw Hat', 'Impostor Straw Hat', 'Imposter Straw Hat'], + 1394: ['ベビー5 神前の晴れ着', '', 'Kimono Baby 5'], + 1395: ['ベビー5 ぎこちない振袖', '', 'Kimono Baby 5'], + 1396: ['たしぎ シャンブルズ', '', 'Smoker'], + 1397: ['たしぎ 七尺十手 シャンブルズ', '', 'Smoker'], + 1398: ['スモーカー シャンブルズ', '', 'Tashigi'], + 1399: ['スモーカー 時雨 シャンブルズ', '', 'Tashigi'], + 1400: ['グラディウス 破裂人間', '', 'Coliseum Gladius'], + 1401: ['グラディウス ピーカ軍幹部', '', 'Coliseum Gladius'], + 1402: ['ドルトン ドラム島民間護衛団団長', '', 'Coliseum Dalton'], + 1403: ['モンキー・D・ルフィ 集結の麦わらの一味', '', 'New World Luffy', 'Timeskip Luffy', 'TS Luffy', 'TSL', 'Legend Luffy', 'Legend TSL', 'Legend Monkey D. Luffy'], + 1404: ['モンキー・D・ルフィ 新生・麦わらの一味', '', 'New World Luffy', 'Timeskip Luffy', 'TS Luffy', 'TSL', 'Legend Luffy', 'Legend TSL', 'Legend Monkey D. Luffy'], + 1405: ['ウソップ 集結の麦わらの一味', '', 'New World Usopp', 'Timeskip Usopp', 'TS Usopp'], + 1406: ['ウソップ 新生・麦わらの一味', '', 'New World Usopp', 'Timeskip Usopp', 'TS Usopp'], + 1407: ['ニコ・ロビン 集結の麦わらの一味', '', 'New World Robin', 'Timeskip Robin', 'TS Robin'], + 1408: ['ニコ・ロビン 新生・麦わらの一味', '', 'New World Robin',, 'Timeskip Robin', 'TS Robin'], + 1409: ['ブルック 集結の麦わらの一味', '', 'New World Brook', 'Timeskip Brook', 'TS Brook'], + 1410: ['ブルック 新生・麦わらの一味', '', 'New World Brook', 'Timeskip Brook', 'TS Brook'], + 1411: ['トニートニー・チョッパー 脚力強化 集結の麦わらの一味', '', 'New World Chopper', 'Timeskip Chopper', 'TS Chopper', 'Monster Chopper'], + 1412: ['トニートニー・チョッパー 怪物強化 新生・麦わらの一味', '', 'New World Chopper', 'Timeskip Chopper', 'TS Chopper', 'Monster Chopper'], + 1413: ['白ひげ 四皇', '', 'Mega Whitebeard', 'Mega WB', 'Edward Newgate', 'Super Whitebeard', 'Super WB', 'Yonko', 'Legend Whitebeard', 'Legend WB'], + 1414: ['サンジ 料理を作って一服中', '', 'Naked Sanji'], + 1415: ['センゴク 智将', '', ''], + 1416: ['仏のセンゴク 智将', '', ''], + 1417: ['ロンズ', '', 'Lonz'], + 1418: ['カイゼルヒゲ', '', 'Kaiser Mustache'], + 1419: ['ロブ・ルッチ 紋付袴の手招き', '', 'Kimono Lucci'], + 1420: ['ロブ・ルッチ 羽二重のほころび', '', 'Kimono Lucci'], + 1421: ['ディアマンテ はためく旗(フラッグ)人間', '', 'Coliseum Diamante'], + 1422: ['ディアマンテ ドンキホーテファミリー最高幹部', '', 'Coliseum Diamante'], + 1423: ['Tボーン 海軍本部大佐', '', 'Coliseum T-Bone', 'TBone', 'Coliseum TBone', 'T Bone', 'Coliseum T Bone'], + 1424: ['ギン 海賊艦隊 戦闘“総隊長”', '', 'Coliseum Gin'], + 1425: ['サイ 八宝水軍', '', ''], + 1426: ['サイ 八宝水軍第13代棟梁', '', ''], + 1427: ['ブー 八宝水軍', '', ''], + 1428: ['ジャン・アンゴ', '', ''], + 1429: ['マンシェリー 2月の本命', '', 'Valentine Mansherry'], + 1430: ['マンシェリー 3月への勇気', '', 'Valentine Mansherry'], + 1431: ['フランキー将軍', '', 'General Franky', 'Raid Franky'], + 1432: ['フランキー将軍 鉄の海賊(アイアンパイレーツ)', '', 'Shogun Franky', 'Raid Franky'], + 1433: ['ホーディ・ジョーンズ 新魚人海賊団船長', '', 'Legend Hody Jones'], + 1434: ['ホーディ・ジョーンズ 魚人街の亡霊', '', 'Legend Hody Jones'], + 1435: ['ヒョウゾウ 新魚人海賊団', '', ''], + 1436: ['ヒョウゾウ 魚人街の亡霊', '', ''], + 1437: ['イカロス・ムッヒ 新魚人海賊団', '', ''], + 1438: ['イカロス・ムッヒ 魚人街の亡霊', '', ''], + 1439: ['ダルマ 新魚人海賊団', '', ''], + 1440: ['ダルマ 魚人街の亡霊', '', ''], + 1441: ['ゼオ 新魚人海賊団', '', ''], + 1442: ['ゼオ 魚人街の亡霊', '', ''], + 1443: ['ドスン 新魚人海賊団', '', ''], + 1444: ['ドスン 魚人街の亡霊', '', ''], + 1445: ['ボア・ハンコック 蛇姫', '', 'Mega Boa Hancock', 'Super Boa Hancock', 'Shichibukai', 'Legend Boa Hancock'], + 1446: ['ウソップ 「プラタナス」手裏剣', '', 'Mega Usopp', 'Super Usopp'], + 1447: ['サンジ グリル=ショット', '', 'Mega Sanji', 'Super Sanji'], + 1448: ['トニートニー・チョッパー ヘビーゴング', '', 'Mega Chopper', 'Super Chopper'], + 1449: ['ヴァイオレット 踊り娘', '', 'Viola'], + 1450: ['ヴァイオレット 追われる女', '', 'Viola'], + 1451: ['サンジ 恋人通りの変装男', '', ''], + 1452: ['サンジ となり町までの護衛', '', ''], + 1453: ['マーガレット 13日の胸騒ぎ', '', 'Valentine Marguerite'], + 1454: ['マーガレット 14日の記念日', '', 'Valentine Marguerite'], + 1455: ['首領・チンジャオ 八宝水軍', '', 'Coliseum Don Chinjao'], + 1456: ['首領・チンジャオ 元八宝水軍第12代棟梁', '', 'Coliseum Don Chinjao'], + 1457: ['クラハドール 執事', '', 'Coliseum Kuro'], + 1458: ['百計のクロ 海賊', '', 'Coliseum Kuro'], + 1459: ['ミス・バレンタイン キロキロの実の能力者', '', 'Coliseum Miss Valentine'], + 1460: ['ミス・バレンタイン B・Wオフィサーエージェント', '', 'Coliseum Miss Valentine'], + 1461: ['ゾロの寒稽古', '', 'Winter Zoro'], + 1462: ['ルフィのブレイクタイム', '', 'White Day Luffy'], + 1463: ['ルフィのティーパーティ', '', 'White Day Luffy'], + 1464: ['チョッパーのブレイクタイム', '', 'White Day Chopper'], + 1465: ['チョッパーのティーパーティ', '', 'White Day Chopper'], + 1466: ['キャベンディッシュ 白い日の優男', '', 'White Day Cavendish', 'White Day Cabbage'], + 1467: ['キャベンディッシュ 白い日の白昼夢', '', 'White Day Cavendish', 'White Day Cabbage'], + 1468: ['戦桃丸 海兵', '', ''], + 1469: ['鉞の戦桃丸 海兵', '', ''], + 1470: ['リップ・“サービス”・ドウティ', '', 'Lip Service'], + 1471: ['深手の・アルビオン', '', ''], + 1472: ['しらほし姫', '', 'Legend Shirahoshi-hime'], + 1473: ['しらほし姫 リュウグウ王国王女', '', 'Legend Shirahoshi-hime'], + 1474: ['ネプチューン', '', ''], + 1475: ['ネプチューン リュウグウ王国国王', '', ''], + 1476: ['フカボシ', '', ''], + 1477: ['フカボシ リュウグウ王国王子', '', ''], + 1478: ['カリブー カリブー海賊団船長', '', ''], + 1479: ['濡れ髪のカリブー カリブー海賊団船長', '', ''], + 1480: ['バンダー・デッケン九世 幽霊船の主', '', ''], + 1481: ['バンダー・デッケン九世 フライング海賊団船長', '', ''], + 1482: ['マダム・シャーリー', '', '', 'Madame Shirley'], + 1483: ['マダム・シャーリー 占い師', '', '', 'Madame Shirley'], + 1484: ['サンジ 野生の海賊', '', 'Wild Sanji'], + 1485: ['サンジ 大地の開拓者', '', 'Wild Sanji'], + 1486: ['イデオ XXX級ボクサー', '', 'Coliseum Ideo'], + 1487: ['破壊砲 イデオ XXX級ボクサー', '', 'Coliseum Ideo'], + 1488: ['首領・クリーク 海賊艦隊「提督」', '', 'Coliseum Don Krieg'], + 1489: ['首領・クリーク 東の海の覇者', '', 'Coliseum Don Krieg'], + 1490: ['Mr.5 爆弾人間', '', 'Coliseum Mr. 5', 'Mr 5'], + 1491: ['Mr.5 B・Wオフィサーエージェント', '', 'Coliseum Mr. 5', 'Mr 5'], + 1492: ['サボ メラメラの実の能力者', '', 'Mega Sabo', 'Super Sabo', 'Legend Sabo'], + 1493: ['荒くれのトゲ付き棍棒部隊 魚人街の無法者', '', ''], + 1494: ['速足のトゲ付き棍棒部隊 魚人街の無法者', '', ''], + 1495: ['やり手のトゲ付き棍棒部隊 魚人街の無法者', '', ''], + 1496: ['一発必中の砲撃部隊 魚人街の無法者', '', ''], + 1497: ['一発入魂の砲撃部隊 魚人街の無法者', '', ''], + 1498: ['赤のアンモナイツ 丈夫な警備隊', '', ''], + 1499: ['青のアンモナイツ 機敏な警備隊', '', ''], + 1500: ['緑のアンモナイツ 利発な警備隊', '', ''], + 1501: ['カリブー', '', ''], + 1502: ['コリブー', '', ''], + 1503: ['ハモンド', '', ''], + 1504: ['バンダー・デッケン九世', '', ''], + 1505: ['ホーディ・ジョーンズ', '', ''], + 1506: ['ホーディ・ジョーンズ 覚醒', '', ''], + 1507: ['サンジのブレイクタイム', '', 'White Day Sanji'], + 1508: ['サンジのティーパーティ', '', 'White Day Sanji'], + 1509: ['ハルタ 白ひげ海賊団12番隊隊長', '', ''], + 1510: ['スピード・ジル 白ひげ海賊団14番隊隊長', '', 'Speed Jiru', 'Genocide Jil'], + 1511: ['アトモス 白ひげ海賊団13番隊隊長', '', ''], + 1512: ['キングデュー 白ひげ海賊団11番隊隊長', '', 'Heman'], + 1513: ['サンジ 春先のお付き添い', '', 'Spring Sanji', 'White Day Sanji'], + 1514: ['サンジ 記念日の手作り', '', 'Spring Sanji', 'White Day Sanji'], + 1515: ['ブルックのブレイクタイム', '', 'White Day Brook'], + 1516: ['ブルックのティーパーティ', '', 'White Day Brook'], + 1517: ['ハイエナのベラミー 元ベラミー海賊団船長', '', 'Raid Bellamy'], + 1518: ['ハイエナのベラミー ドレスローザの凶弾', '', 'Raid Bellamy'], + 1519: ['カーリー・ダダン コルボ山 山賊', '', ''], + 1520: ['カーリー・ダダン ダダン一家 棟梁', '', ''], + 1521: ['ドグラ', '', ''], + 1522: ['ポートガス・D・エース 隠された鬼の子', '', 'Kid Ace'], + 1523: ['トニートニー・チョッパー フラスコの中の大きな夢', '', 'Spring Chopper', 'Sakura Chopper'], + 1524: ['トニートニー・チョッパー 冬島に見た春の景色', '', 'Spring Chopper', 'Sakura Chopper'], + 1525: ['首はねスレイマン ディアス海戦A級戦犯', '', 'Coliseum Suleiman'], + 1526: ['アーロン アーロン一味船長', '', 'Coliseum Arlong'], + 1527: ['ノコギリのアーロン アーロン一味船長', '', 'Coliseum Arlong'], + 1528: ['ブレンハイム 白ひげ海賊団9番隊隊長', '', 'Coliseum Blenheim'], + 1529: ['キャベンディッシュ 美しき海賊団船長', '', 'Invasion Cavendish', 'Invasion Cabbage'], + 1530: ['白馬のキャベンディッシュ 美しき海賊団船長', '', 'Invasion Cavendish', 'Invasion Cabbage'], + 1531: ['ウソランド', '', 'God Usopp', 'Legend Usopp', 'Legend Usoland', 'Legend God Usopp'], + 1532: ['ゴッド・ウソップ', '', 'God Usopp', 'Usoland', 'Legend Usopp', 'Legend Usoland', 'Legend God Usopp'], + 1533: ['シルバーズ・レイリー 麦わらの一味の協力者', '', 'Silvers Rayleigh'], + 1534: ['シルバーズ・レイリー 麦わらの一味の共犯者', '', 'Silvers Rayleigh'], + 1535: ['デュバル 麦わらの一味の協力者', '', ''], + 1536: ['デュバル 麦わらの一味の共犯者', '', ''], + 1537: ['ヘラクレス 麦わらの一味の協力者', '', ''], + 1538: ['ヘラクレス 麦わらの一味の共犯者', '', ''], + 1539: ['ペローナ 麦わらの一味の協力者', '', ''], + 1540: ['ペローナ 麦わらの一味の共犯者', '', ''], + 1541: ['エリザベス 麦わらの一味の協力者', '', ''], + 1542: ['エリザベス 麦わらの一味の共犯者', '', ''], + 1543: ['キャプテン・ウソップ 男ウソップ大冒険 ~第二章~', '', 'God Usopp', 'Mega Usopp', 'Super Usopp', 'Usoland', 'Legend Usopp', 'Legend Usoland', 'Legend God Usopp'], + 1544: ['コアラ 桜色の待ち合わせ', '', 'Sakura Koala'], + 1545: ['コアラ 桜色の口元', '', 'Sakura Koala'], + 1546: ['ソウルキング', '', 'Brook'], + 1547: ['“ソウルキング”ブルック 海賊', '', 'Brook'], + 1548: ['テーナ・ゲーナ王国の手長族 “ソウルキング”マネージャー', '', ''], + 1549: ['ニコ・ロビン 千紫万紅 花畑', '', 'Mega Robin', 'Super Robin'], + 1550: ['フランキー フランキ~~~ロケットランチャ――', '', 'Mega Franky', 'Super Franky'], + 1551: ['ブルック 掠り唄 吹雪斬り', '', 'Mega Brook', 'Super Brook'], + 1552: ['ハイルディン 「エルバフ」“新時代”の戦士', '', 'Coliseum Hajrudin'], + 1553: ['海賊傭兵 ハイルディン 「エルバフ」“新時代”の戦士', '', 'Coliseum Hajrudin'], + 1554: ['リューマ 侍の将軍ゾンビ', '', 'Coliseum Ryuma'], + 1555: ['剣豪リューマ 侍の将軍ゾンビ', '', 'Coliseum Ryuma'], + 1556: ['ワダツミ', '', ''], + 1557: ['ゼオ', '', ''], + 1558: ['イカロス', '', ''], + 1559: ['ヒョウゾウ', '', ''], + 1560: ['ダルマ', '', ''], + 1561: ['ドスン', '', ''], + 1562: ['ホーディ・ジョーンズ 暴走', '', ''], + 1563: ['“戦う王”エリザベローII世', '', ''], + 1564: ['“戦う王”エリザベローII世 プロデンス王国', '', ''], + 1565: ['軍師ダガマ', '', ''], + 1566: ['軍師ダガマ プロデンス王国', '', ''], + 1567: ['ボア・ハンコック 少女戦士', '', 'Kid Boa Hancock'], + 1568: ['ボア・ハンコック お姫さまの片鱗', '', 'Kid Boa Hancock'], + 1569: ['トラファルガー・ロー 麦わらの一味・ハートの海賊団海賊同盟', '', 'Anniversary Law'], + 1570: ['イヌアラシ', '', 'Inuyasha', 'Dogstorm', 'Dog Storm', 'Doggo Storm', 'Legend Inuarashi', 'Legend Dogstorm'], + 1571: ['“昼の王”イヌアラシ', '', 'Inuyasha', 'Dogstorm','Dog Storm', 'Doggo Storm', 'Legend Inuarashi', 'Legend Dogstorm'], + 1572: ['ワンダ', '', ''], + 1573: ['王の鳥 ワンダ', '', ''], + 1574: ['シシリアン', '', ''], + 1575: ['全力のシシリアン', '', ''], + 1576: ['錦えもん ワノ国の侍', '', 'Kin\'emon'], + 1577: ['狐火の錦えもん ワノ国の侍', '', 'Kin\'emon'], + 1578: ['モモの助', '', ''], + 1579: ['モモの助 ワノ国の子', '', ''], + 1580: ['トラファルガー・ロー パンクハザードの滞在者', '', ''], + 1581: ['トラファルガー・ロー 二人目の救いの神', '', ''], + 1582: ['モネ ユキユキの実の雪女', '', ''], + 1583: ['オオロンブス ヨンタマリア大船団提督', '', 'Coliseum Orlumbus'], + 1584: ['殺戮支配者オオロンブス ヨンタマリア大船団提督', '', 'Coliseum Orlumbus'], + 1585: ['ヘルメッポ 海軍本部軍曹', '', 'Coliseum Helmeppo'], + 1586: ['勇士の戦友ヘルメッポ 海軍本部軍曹', '', 'Coliseum Helmeppo'], + 1587: ['サンジ ヴィンスモーク家 三男', '', 'Vinsmoke Sanji', 'Germa Sanji', 'Legend Vinsmoke Sanji', 'Legend Germa Sanji', 'Legend Sanji'], + 1588: ['サンジ ジェルマ王国 プリンス', '', 'Vinsmoke Sanji', 'Germa Sanji', 'Legend Vinsmoke Sanji', 'Legend Germa Sanji', 'Legend Sanji'], + 1589: ['シャンクス Celebrate the long cruise', '', 'Anniversary Shanks'], + 1590: ['赤髪のシャンクス Celebrate the long cruise', '', 'Anniversary Shanks'], + 1591: ['ボア・ハンコック Celebrate the long cruise', '', 'Anniversary Boa'], + 1592: ['“女帝”ボア・ハンコック Celebrate the long cruise', '', 'Anniversary Boa'], + 1593: ['モンキー・D・ルフィ ギア“4” 「弾む男(バウンドマン)」', '', 'Gear 4 Luffy', 'G4', 'G4 Luffy', 'Mega Luffy', 'Super Luffy', 'Legend Luffy', 'Legend Gear 4 Luffy', 'Legend G4 Luffy'], + 1594: ['藤虎 海軍本部最高戦力', '', 'Raid Issho', 'Raid Fujitora'], + 1595: ['藤虎 重力刀 海軍本部最高戦力', '', 'Raid Issho', 'Raid Fujitora'], + 1596: ['しらほし', '', ''], + 1597: ['しらほし リュウグウ王国王女', '', ''], + 1598: ['リュウボシ', '', ''], + 1599: ['マンボシ', '', ''], + 1600: ['モンキー・D・ルフィ 麦わらの一味・ハートの海賊団海賊同盟', '', 'Anniversary Luffy'], + 1601: ['シリュウ 黒ひげ海賊団', '', 'Coliseum Shiryu'], + 1602: ['雨のシリュウ 黒ひげ海賊団', '', 'Coliseum Shiryu'], + 1603: ['雷卿マクガイ', '', 'Coliseum McGuy', 'Lightning McGuy'], + 1604: ['ポートガス・D・エース ルフィの“兄”', '', '0 Stamina Ace'], + 1605: ['ポートガス・D・エース 白ひげの“息子”', '', '0 Stamina Ace'], + 1606: ['ラフィット 黒ひげ海賊団', '', 'La Feet'], + 1607: ['ヴァン・オーガー 黒ひげ海賊団', '', 'Vaper', 'Van Ogre'], + 1608: ['ドクQ 黒ひげ海賊団', '', ''], + 1609: ['ゴッド・エネル 終わらぬ夢の宿敵', '', 'God Enel', 'Legend Enel', 'Legend God Enel', 'Kami Eneru'], + 1610: ['ゴッド・エネル 大海賊時代の死闘「限りない大地」', '', 'God Enel', 'Legend Enel', 'Legend God Enel', 'Kami Eneru'], + 1611: ['バーソロミュー・くま 終わらぬ夢の宿敵', '', ''], + 1612: ['バーソロミュー・くま 大海賊時代の死闘「一味抹殺」', '', ''], + 1613: ['ロブ・ルッチ 終わらぬ夢の宿敵', '', ''], + 1614: ['ロブ・ルッチ 大海賊時代の死闘「闇の正義」', '', ''], + 1615: ['Mr.0 終わらぬ夢の宿敵', '', 'Crocodile', 'Log Crocodile', 'MrUtopia', 'Mr Utopia', 'Mr 0'], + 1616: ['Mr.0 大海賊時代の死闘「理想郷」', '', 'Crocodile', 'Log Crocodile', 'MrUtopia', 'Mr Utopia' , 'Mr 0'], + 1617: ['ゲッコー・モリア 終わらぬ夢の宿敵', '', ''], + 1618: ['ゲッコー・モリア 大海賊時代の死闘「最強の部下」', '', ''], + 1619: ['“冥王”シルバーズ・レイリー 海賊王の右腕', '', 'Mega Rayleigh', 'Super Rayleigh', 'Legend Rayliegh'], + 1620: ['ユースタス・キッド 終わらぬ夢の航跡・キッド海賊団', '', 'Log Kid', 'Secret Kid', 'Log Kidd', 'Secret Kidd'], + 1621: ['ユースタス・キッド 大海賊時代への誓い「海賊王」', '', 'Log Kid', 'Secret Kid', 'Log Kidd', 'Secret Kidd'], + 1622: ['ドンキホーテ・ドフラミンゴ「改」', '', 'Kai Doffy', 'Kai Doflamingo', 'Neo Doffy', 'Neo Doflamingo', 'Raid Doffy', 'Raid Doflamingo'], + 1623: ['ドンキホーテ・ドフラミンゴ「改」 王下七武海', '', 'Kai Doffy', 'Kai Doflamingo', 'Neo Doffy', 'Neo Doflamingo', 'Raid Doffy', 'Raid Doflamingo'], + 1624: ['ヒョウゾウ 魚人海賊の用心棒', '', ''], + 1625: ['ダルマ 深海の魚人海賊', '', ''], + 1626: ['ドスン 深海の魚人海賊', '', ''], + 1627: ['マッハ・バイス 超体重人間', '', 'Coliseum Mach Vise', 'Coliseum Machvise'], + 1628: ['マッハ・バイス ディアマンテ軍幹部', '', 'Coliseum Mach Vise', 'Coliseum Machvise'], + 1629: ['イカロス・ムッヒ 深海の魚人海賊', '', 'Coliseum Ikaros Much'], + 1630: ['イカロス・ムッヒ 反逆の魚人海賊', '', 'Coliseum Ikaros Much'], + 1631: ['フィッシャー・タイガー', '', 'Secret Fisher Tiger'], + 1632: ['フィッシャー・タイガー タイヨウの海賊団船長', '', 'Secret Fisher Tiger'], + 1633: ['Dragon パンクハザード生息', '', ''], + 1634: ['ロック&スコッチ', '', ''], + 1635: ['茶ひげ PH巡回部隊“ボス”', '', ''], + 1636: ['シーザー・クラウン 元政府の科学者', '', ''], + 1637: ['M(マスター)・シーザー 元政府の科学者', '', ''], + 1638: ['PHガスマスク巡回兵・[力]', '', ''], + 1639: ['PHガスマスク巡回兵・[速]', '', ''], + 1640: ['PHガスマスク巡回兵・[技]', '', ''], + 1641: ['PHガスマスク巡回兵・[知]', '', ''], + 1642: ['PHガスマスク巡回兵・[心]', '', ''], + 1643: ['剛脚のケンタウロス PH巡回部隊隊員', '', ''], + 1644: ['快足のケンタウロス PH巡回部隊隊員', '', ''], + 1645: ['足業のケンタウロス PH巡回部隊隊員', '', ''], + 1646: ['ピーカ「改」', '', 'Kai Pica', 'STR Pica', 'Neo Pica', 'Raid Pica'], + 1647: ['ピーカ「改」 ドンキホーテ海賊団', '', 'Kai Pica', 'STR Pica', 'Neo Pica', 'Raid Pica'], + 1648: ['ジョーラ 芸術人間', '', 'Jora'], + 1649: ['ジョーラ トレーボル軍', '', 'Jora'], + 1650: ['ブルック サイケデリックアート', '', ''], + 1651: ['ネコマムシ', '', 'Cat Viper', 'Nekopara', 'Legend Nekomamushi'], + 1652: ['“夜の王”ネコマムシ', '', 'Cat Viper', 'Nekopara', 'Legend Nekomamushi'], + 1653: ['ペドロ', '', ''], + 1654: ['木の上のペドロ', '', ''], + 1655: ['キャロット', '', ''], + 1656: ['王の鳥 キャロット', '', ''], + 1657: ['カン十郎 ワノ国の侍', '', ''], + 1658: ['夕立ち カン十郎 ワノ国の侍', '', ''], + 1659: ['雷ぞう', '', ''], + 1660: ['霧の雷ぞう', '', ''], + 1661: ['コラソン 消したい雨雲', '', ''], + 1662: ['コラソン 消える雨音', '', ''], + 1663: ['ロブ・ルッチ “生命帰還” 歴代最強の「CP9」', '', 'Mega Rob Lucci', 'Mega Lucci', 'Super Rob Lucci', 'Super Lucci', 'Legend Lucci', 'Legend Rob Lucci'], + 1664: ['青キジ “一騎討ち”の相手', '', 'Secret Aokiji', 'Secret Kuzan'], + 1665: ['青キジ “一騎討ち”の勝者', '', 'Secret Aokiji', 'Secret Kuzan'], + 1666: ['キュロス 無敗の剣闘士', '', 'Coliseum Kyros'], + 1667: ['キュロス リク王軍軍隊長', '', 'Coliseum Kyros'], + 1668: ['青キジ「改」', '', 'Kai Aokiji', 'Kai Kuzan', 'Raid Aokiji', 'Raid Kuzan', 'Neo Aokiji', 'Neo Kuzan'], + 1669: ['青キジ 氷結人間「改」', '', 'Kai Aokiji', 'Kai Kuzan', 'Raid Aokiji', 'Raid Kuzan', 'Neo Aokiji', 'Neo Kuzan'], + 1670: ['マダム・シャーリー マーメイドカフェ 店長', '', 'Madame Shirley'], + 1671: ['ケイミー マーメイドカフェ', '', ''], + 1672: ['パッパグ “クリミナルブランド社”社長兼超人気セレブデザイナー', '', 'Pappug'], + 1673: ['ペローナ 暗い浜辺のプリンセス', '', 'Swimsuit Perona', 'Summer Perona'], + 1674: ['ペローナ 大胆水着なプリンセス', '', 'Swimsuit Perona', 'Summer Perona'], + 1675: ['ロロノア・ゾロ からかさ剣士', '', 'Kimono Zoro'], + 1676: ['ロロノア・ゾロ 雨濡れ剣客', '', 'Kimono Zoro'], + 1677: ['トラファルガー・ロー 終わらぬ夢の航跡・ハートの海賊団', '', 'Log Law', 'Secret Law'], + 1678: ['トラファルガー・ロー 大海賊時代への誓い「自由」', '', 'Log Law', 'Secret Law'], + 1679: ['ジュラキュール・ミホーク「改」', '', 'Kai Mihawk', 'Neo Mihawk', 'Raid Mihawk', 'Hawk' ], + 1680: ['鷹の目のミホーク「改」', '', 'Kai Mihawk', 'Neo Mihawk', 'Raid Mihawk'], + 1681: ['モンキー・D・ルフィ Celebrate 20th Anniversary Cruise', '', '20th Anniversary Luffy'], + 1682: ['モンキー・D・ルフィ 20th Anniversary Memorial Treasure', '', '20th Anniversary Luffy'], + 1683: ['ニコ・ロビン Celebrate 20th Anniversary Cruise', '', '20th Anniversary Robin'], + 1684: ['ニコ・ロビン 20th Anniversary Memorial Treasure', '', '20th Anniversary Robin'], + 1685: ['ウソップ Celebrate 20th Anniversary Cruise', '', '20th Anniversary Usopp'], + 1686: ['ウソップ 20th Anniversary Memorial Treasure', '', '20th Anniversary Usopp'], + 1687: ['フランキー Celebrate 20th Anniversary Cruise', '', '20th Anniversary Franky'], + 1688: ['フランキー 20th Anniversary Memorial Treasure', '', '20th Anniversary Franky'], + 1689: ['ユースタス・キッド “南の海”出身の超新星', '', 'Fortnight Kidd'], + 1690: ['キャプテン・キッド “南の海”出身の超新星', '', 'Fortnight Kidd'], + 1691: ['ヒート', '', ''], + 1692: ['ワイヤー', '', ''], + 1693: ['イヌアラシ モコモ公国', '', 'Coliseum Inuarashi', 'Dog Storm', 'Dogstorm', 'Doggo'], + 1694: ['“昼の王”イヌアラシ モコモ公国', '', 'Coliseum Inuarashi', 'Dog Storm', 'Dogstorm', 'Doggo'], + 1695: ['鬼竹のヴェルゴ', '', 'Raid Vergo'], + 1696: ['鬼竹のヴェルゴ ドンキホーテファミリー最高幹部', '', 'Raid Vergo'], + 1697: ['マゼラン 監獄の支配者', '', 'Legend Magellan'], + 1698: ['マゼラン 地獄の支配者', '', 'Legend Magellan'], + 1699: ['ジンベエ “無限地獄”の囚人', '', "Jinbe, 'Eternal Hell' Prisoner", "Jimbei, 'Eternal Hell' Prisoner", "Jimbe, 'Eternal Hell' Prisoner", "Jinbei, 'Eternal Hell' Prisoner"], + 1700: ['ジンベエ “地獄”の七武海', '', "Jinbe, 'Eternal Hell' Prisoner", "Jimbei, 'Eternal Hell' Prisoner", "Jimbe, 'Eternal Hell' Prisoner", "Jinbei, 'Eternal Hell' Prisoner"], + 1701: ['エンポリオ・イワンコフ “ニューカマーランド”の囚人', '', ''], + 1702: ['エンポリオ・イワンコフ “地獄”の革命家', '', ''], + 1703: ['ハンニャバル 支配者の腹心', '', ''], + 1704: ['ハンニャバル 今は支配者の腹心', '', ''], + 1705: ['Mr.2 ボン・クレー “飢餓地獄”の囚人', '', 'Mr 2'], + 1706: ['Mr.2 ボン・クレー “地獄”の友達(ダチ)', '', 'Mr 2'], + 1707: ['赤髪のシャンクス 四皇', '', 'Mega Shanks', 'Super Shanks', 'SW Shanks', 'Yonko'], + 1708: ['ナミ 真夏のドキドキ', '', 'Summer Nami', 'Swimsuit Nami', 'Summertime Nami'], + 1709: ['ナミ 真夏のワクワク', '', 'Summer Nami', 'Swimsuit Nami', 'Summertime Nami'], + 1710: ['ニコ・ロビン 健康的な美貌', '', 'Summer Robin', 'Swimsuit Robin', 'Summertime Robin'], + 1711: ['ニコ・ロビン 文化の象徴', '', 'Summer Robin', 'Swimsuit Robin', 'Summertime Robin'], + 1712: ['赤犬 頂上戦争の火蓋', '', 'Secret Akainu'], + 1713: ['赤犬 頂上戦争の業火', '', 'Secret Akainu'], + 1714: ['モネ 氷雪の化身', '', ''], + 1715: ['ヴェルゴ 海軍「G‐5」基地長', '', ''], + 1716: ['シーザー・クラウン 死の国の王', '', ''], + 1717: ['ベガパンクの竜(小型)', '', ''], + 1718: ['バッファロー ドンキホーテ海賊団 戦闘員', '', ''], + 1719: ['ベビー5 ドンキホーテ海賊団 使用人兼殺し屋', '', ''], + 1720: ['ジンベエ リュウグウ王国ネプチューン軍兵士', '', 'Secret Jinbe', 'Secret Jimbe', 'Young Jinbe', 'Young Jimbe'], + 1721: ['“親分”ジンベエ リュウグウ王国ネプチューン軍兵士', '', 'Secret Jinbe', 'Secret Jimbe', 'Young Jinbe', 'Young Jimbe'], + 1722: ['海神ネプチューン', '', ''], + 1723: ['海神ネプチューン リュウグウ王国国王', '', ''], + 1724: ['フカボシ ネプチューン家三兄弟 長男', '', ''], + 1725: ['フカボシ 王国軍三強', '', ''], + 1726: ['サボ「改」 竜の爪', '', 'Kai Sabo', 'Neo Sabo', 'Raid Sabo'], + 1727: ['サボ「改」 革命軍参謀総長', '', 'Kai Sabo', 'Neo Sabo', 'Raid Sabo'], + 1728: ['たしぎ ビーチの大佐', '', 'Summertime Tashigi', 'Swimsuit Tashigi', 'Summer Tashigi'], + 1729: ['たしぎ バカンスの大佐ちゃん', '', 'Summertime Tashigi', 'Swimsuit Tashigi', 'Summer Tashigi'], + 1730: ['ネフェルタリ・ビビ 眩しい純白', '', 'Summertime Vivi', 'Swimsuit Vivi', 'Summer Vivi', 'Secret Vivi'], + 1731: ['ネフェルタリ・ビビ 魅惑の透明感', '', 'Summertime Vivi', 'Swimsuit Vivi', 'Summer Vivi', 'Secret Vivi'], + 1732: ['', '', 'Nekopara', 'Coliseum Nekomamushi'], + 1733: ['', '', 'Nekopara', 'Coliseum Nekomamushi'], + 1734: ['シュガー ホビホビの実の能力者', '', ''], + 1735: ['シュガー トレーボル軍 特別幹部', '', ''], + 1736: ['トレーボル ベタベタの実の能力者', '', ''], + 1737: ['トレーボル ドンキホーテファミリー最高幹部', '', ''], + 1738: ['ハイエナのベラミー「改」 元ベラミー海賊団船長', '', 'Neo Bellamy', 'Kai Bellamy', 'Raid Bellamy'], + 1739: ['ハイエナのベラミー「改」 ドレスローザの凶弾', '', 'Neo Bellamy', 'Kai Bellamy', 'Raid Bellamy'], + 1740: ['ボア・サンダーソニア 麦わらのルフィの協力者', '', ''], + 1741: ['ボア・サンダーソニア 麦わらのルフィの共犯者', '', ''], + 1742: ['ボア・マリーゴールド 麦わらのルフィの協力者', '', ''], + 1743: ['ボア・マリーゴールド 麦わらのルフィの共犯者', '', ''], + 1744: ['マーガレット 麦わらのルフィの協力者', '', ''], + 1745: ['マーガレット 麦わらのルフィの共犯者', '', ''], + 1746: ['ボア・ハンコック 麦わらのルフィの協力者', '', 'Korean Boa', 'Legend Korean Boa', 'Legend Boa Hancock', 'Legend Boa', 'Shichibukai'], + 1747: ['ボア・ハンコック 麦わらのルフィの共犯者', '', 'Korean Boa', 'Legend Korean Boa', 'Legend Boa Hancock', 'Legend Boa', 'Shichibukai'], + 1748: ['ベポ 麦わらのルフィの協力者', '', ''], + 1749: ['ベポ 麦わらのルフィの共犯者', '', ''], + 1750: ['“死の外科医”トラファルガー・ロー “ジョーカー”を狙う“ハート”', '', 'Korean Law', 'Legend Korean Law', 'Legend Trafalgar Law', 'Legend Law', 'Shichibukai'], + 1751: ['“王下七武海”トラファルガー・ロー “ジョーカー”を狙う“ハート”', '', 'Korean Law', 'Legend Korean Law', 'Legend Trafalgar Law', 'Legend Law', 'Shichibukai'], + 1752: ['ロロノア・ゾロ Celebrate 20th Anniversary Cruise', '', '20th Anniversary Zoro'], + 1753: ['ロロノア・ゾロ 20th Anniversary Memorial Treasure', '', '20th Anniversary Zoro'], + 1754: ['サンジ Celebrate 20th Anniversary Cruise', '', '20th Anniversary Sanji'], + 1755: ['サンジ 20th Anniversary Memorial Treasure', '', '20th Anniversary Sanji'], + 1756: ['ナミ Celebrate 20th Anniversary Cruise', '', '20th Anniversary Nami'], + 1757: ['ナミ 20th Anniversary Memorial Treasure', '', '20th Anniversary Nami'], + 1758: ['ブルック Celebrate 20th Anniversary Cruise', '', '20th Anniversary Brook'], + 1759: ['ブルック 20th Anniversary Memorial Treasure', '', '20th Anniversary Brook'], + 1760: ['トニートニー・チョッパー Celebrate 20th Anniversary Cruise', '', '20th Anniversary Chopper'], + 1761: ['トニートニー・チョッパー 20th Anniversary Memorial Treasure', '', '20th Anniversary Chopper'], + 1762: ['ロブ・ルッチ 世界政府の怪物', '', 'Rob Lucci', 'Legend Rob Lucci', 'Legend Lucci'], + 1763: ['ルッチ 獣人 世界政府の怪物', '', 'Rob Lucci', 'Legend Rob Lucci', 'Legend Lucci'], + 1764: ['クザン 元海軍本部最高戦力', '', 'Super Aokiji', 'Mega Aokiji', 'Super Kuzan', 'Mega Kuzan', 'Legend Aokiji', 'Legend Kuzan'], + 1765: ['足長族 ブルーギリー', '', ''], + 1766: ['足長族 ブルーギリー 脚功道格闘家', '', ''], + 1767: ['殺し屋 ファンク兄弟', '', ''], + 1768: ['アブドーラ&ジェット 凶悪犯罪者', '', ''], + 1769: ['ベン・ベックマン 赤髪海賊団副船長', '', 'Secret Benn Beckman', 'Secret Ben Beckman'], + 1770: ['ベン・ベックマン “四皇”赤髪の右腕', '', 'Secret Benn Beckman', 'Secret Ben Beckman'], + 1771: ['暴君バーソロミュー・くま「改」', '', 'Neo Bartholomew Kuma', 'Neo Kuma', 'Kai Bartholomew Kuma', 'Kai Kuma', 'Raid Bartholomew Kuma', 'Raid Kuma'], + 1772: ['暴君バーソロミュー・くま「改」 政府の人間兵器', '', 'Neo Bartholomew Kuma', 'Neo Kuma', 'Kai Bartholomew Kuma', 'Kai Kuma', 'Raid Bartholomew Kuma', 'Raid Kuma'], + 1773: ['“侍” 錦えもん', '', 'Kin\'emon'], + 1774: ['“侍” 狐火の錦えもん', '', 'Kin\'emon'], + 1775: ['“侍” モモの助', '', ''], + 1776: ['“龍” モモの助', '', ''], + 1777: ['黄猿 聖地からの使者', '', 'Secret Kizaru', 'Secret Borsalino'], + 1778: ['黄猿 聖地からの光臨', '', 'Secret Kizaru', 'Secret Borsalino'], + 1779: ['黄猿「改」', '', 'Neo Kizaru', 'Neo Borsalino', 'Kai Kizaru', 'Kai Borsalino', 'Raid Kizaru', 'Raid Borsalino'], + 1780: ['黄猿「改」 光人間', '', 'Neo Kizaru', 'Neo Borsalino', 'Kai Kizaru', 'Kai Borsalino', 'Raid Kizaru', 'Raid Borsalino'], + 1781: ['闘魚', '', ''], + 1782: ['首領・チンジャオ チンジャオファミリー', '', ''], + 1783: ['ハイルディン 巨人傭兵', '', ''], + 1784: ['藤虎 海軍本部大将', '', ''], + 1785: ['スパルタン', '', ''], + 1786: ['ドンキホーテ海賊団構成員 格闘部隊下級兵', '', ''], + 1787: ['ドンキホーテ海賊団構成員 特攻部隊下級兵', '', ''], + 1788: ['ドンキホーテ海賊団構成員 特殊部隊下級兵', '', ''], + 1789: ['ドンキホーテ海賊団構成員 偵察部隊下級兵', '', ''], + 1790: ['ドンキホーテ海賊団構成員 諜報部隊下級兵', '', ''], + 1791: ['ルーシー コリーダコロシアムCブロックの謎の剣闘士', '', 'Luffy', 'Coliseum Luffy', 'Coliseum Lucy'], + 1792: ['ルーシー コリーダコロシアムCブロックの風雲児', '', 'Luffy', 'Coliseum Luffy', 'Coliseum Lucy'], + 1793: ['ルーシー コリーダコロシアム決勝戦の風雲児', '', 'Sabo', 'Legend Lucy', 'Legend Sabo'], + 1794: ['ルーシー コリーダコロシアム優勝者', '', 'Sabo', 'Legend Lucy', 'Legend Sabo'], + 1795: ['Mr.ディアマンテ コリーダコロシアムの英雄', '', 'Mr Diamante'], + 1796: ['ディアマンテ ドレスローザ現国王のファミリー', '', 'Mr Diamante'], + 1797: ['ジーザス・バージェス コリーダコロシアムAブロックの“チャンピオン”', '', ''], + 1798: ['ジーザス・バージェス 鳥カゴの中の暗躍者', '', ''], + 1799: ['キャベンディッシュ コリーダコロシアムDブロックの“白馬”', '', 'Cabbage'], + 1800: ['キャベンディッシュ 鳥カゴの中の反逆者', '', 'Cabbage'], + 1801: ['バルトロメオ コリーダコロシアムBブロックの“人食い”', '', ''], + 1802: ['バルトロメオ 鳥カゴの中の反逆者', '', ''], + 1803: ['ロロノア・ゾロ “東の海”の海賊', '', ''], + 1804: ['ロロノア・ゾロ “東の海”の剣豪', '', ''], + 1805: ['道化のバギー 斬っても斬れないバラバラ人間', '', ''], + 1806: ['キャプテン・バギー 斬っても斬れないバラバラ人間', '', ''], + 1807: ['ジュラキュール・ミホーク 世界中の剣士の頂点に立つ男', '', 'Hawk' ], + 1808: ['鷹の目のミホーク 世界中の剣士の頂点に立つ男', '', ''], + 1809: ['ワンダ モコモ公国', '', ''], + 1810: ['王の鳥 ワンダ モコモ公国', '', ''], + 1811: ['キャロット モコモ公国', '', ''], + 1812: ['王の鳥 キャロット モコモ公国', '', ''], + 1813: ['コアラ 極秘任務の革命軍', '', ''], + 1814: ['ヴィンスモーク・サンジ', '', 'Raid Sanji'], + 1815: ['ヴィンスモーク・サンジ ジェルマ王国', '', 'Raid Sanji'], + 1816: ['ポートガス・D・エース 闇討つ太陽', '', 'Super Ace', 'Mega Ace', 'SW Ace', 'Legend Ace',], + 1817: ['リク王', '', ''], + 1818: ['リク・ドルド3世', '', ''], + 1819: ['タンク・レパント', '', ''], + 1820: ['スカーレット', '', ''], + 1821: ['サンジ ステージ衣装の海賊', '', 'Husbando Sanji'], + 1822: ['サンジ ステージ衣装の王子様', '', 'Husbando Sanji'], + 1823: ['バーンディ・ワールド モアモアの実の能力者', '', 'Secret World', 'Secret Byrnndi World'], + 1824: ['バーンディ・ワールド 世界の破壊者', '', 'Secret World', 'Secret Byrnndi World'], + 1825: ['赤犬「改」', '', 'Kaikainu', 'Kai Akainu', 'Neo Akainu'], + 1826: ['赤犬「改」 マグマ人間', '', 'Kaikainu', 'Kai Akainu', 'Neo Akainu'], + 1827: ['シシリアン モコモ公国', '', ''], + 1828: ['全力のシシリアン モコモ公国', '', ''], + 1829: ['シーザー・クラウン 大気の支配者', '', ''], + 1830: ['M(マスター)・シーザー 大気の支配者', '', ''], + 1831: ['', '', ''], + 1832: ['', '', ''], + 1833: ['', '', ''], + 1834: ['', '', ''], + 1835: ['', '', ''], + 1836: ['', '', ''], + 1837: ['', '', ''], + 1838: ['', '', ''], + 1839: ['', '', ''], + 1840: ['', '', ''], + 1841: ['', '', ''], + 1842: ['', '', ''], + 1843: ['', '', ''], + 1844: ['', '', ''], + 1845: ['', '', 'Invasion Garp', 'Ambush Garp'], + 1846: ['', '', 'Invasion Garp', 'Ambush Garp'], + 1847: ['', '', ''], + 1848: ['', '', 'Sakazuki'], + 1849: ['', '', 'Akainu'], + 1850: ['', '', 'Squardo'], + 1851: ['', '', 'Squardo'], + 1852: ['', '', 'Adventure Whitebeard'], + 1853: ['', '', 'Adventure Whitebeard'], + 1854: ['', '', ''], + 1855: ['', '', ''], + 1856: ['', '', ''], + 1857: ['', '', ''], + 1858: ['', '', ''], + 1859: ['', '', ''], + 1860: ['', '', ''], + 2000: ['', '', 'Global Rayleigh', 'Raidleigh'], + 2001: ['', '', 'Global Rayleigh', 'Raidleigh'], }; + +// xxxx: ['JPN', 'FR', 'Other'], diff --git a/common/data/captains.js b/common/data/captains.js index 649838608..fedeafc22 100644 --- a/common/data/captains.js +++ b/common/data/captains.js @@ -1,2113 +1,5930 @@ window.captains = { - 2: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 3: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 4: { - atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } - }, - 5: { - atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } - }, - 6: { - atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } - }, - 7: { - atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } - }, - 8: { - atk: function(p) { return p.unit.type == "DEX" ? 2 : 1; }, - hp: function(p) { return p.unit.type == "DEX" ? 2 : 1; } - }, - 10: { - atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } - }, - 11: { - atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } - }, - 12: { - atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, - hp: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } - }, - 13: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.2 : 1; } - }, - 14: { - atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 15: { - atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 16: { - atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, - hp: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 17: { - atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } - }, - 18: { - hp: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } - }, - 19: { - atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } - }, - 20: { - atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, - hp: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } - }, - 21: { - rcv: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; } - }, - 22: { - rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 23: { - rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } - }, - 24: { - rcv: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 25: { - rcv: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } - }, - 26: { - rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } - }, - 27: { - hp: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; } - }, - 28: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.2 : 1; } - }, - 35: { - hp: function(p) { return p.unit.class.has("Slasher") ? 1.2 : 1; } - }, - 36: { - atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 37: { - atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } - }, - 38: { - atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } - }, - 39: { - atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } - }, - 41: { - rcv: function(p) { return p.unit.type == "INT" ? 1.2 : 1; } - }, - 42: { - atk: function(p) { return p.unit.type == "STR" ? 1.2 : 1; } - }, - 45: { - atk: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; } - }, - 46: { - atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } - }, - 49: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 52: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2.5 : 1; } - }, - 59: { - atk: function(p) { return p.unit.type == "INT" ? 1.2 : 1; } - }, - 60: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 61: { - hp: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 62: { - hp: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } - }, - 65: { - atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } - }, - 66: { - atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } - }, - 67: { - rcv: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } - }, - 68: { - rcv: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } - }, - 74: { - atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } - }, - 75: { - atk: function(p) { return p.unit.type == "QCK" ? 2.5 : 1; } - }, - 76: { - atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } - }, - 77: { - atk: function(p) { return p.unit.type == "PSY" ? 2.5 : 1; } - }, - 194: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 195: { - rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } - }, - 196: { - atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } - }, - 198: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 199: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 200: { - atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } - }, - 201: { - hp: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } - }, - 202: { - hp: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } - }, - 205: { - hp: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; }, - rcv: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; } - }, - 206: { - hp: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; }, - rcv: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; } - }, - 209: { - rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } - }, - 210: { - rcv: function(p) { return p.unit.type == "INT" ? 2 : 1; } - }, - 211: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.2 : 1; } - }, - 212: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } - }, - 215: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } - }, - 217: { - hitAtk: function(p) { - return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 3.5 : 1; - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 220: { - atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } - }, - 221: { - atk: function(p) { return p.unit.type == "INT" ? 2.5 : 1; } - }, - 222: { - atk: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; } - }, - 223: { - atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 224: { - hitAtk: function(p) { - return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect"]) ? 2 : 1; - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 225: { - hitAtk: function(p) { - return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect"]) ? 2.5 : 1; - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 226: { - atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } - }, - 227: { - atk: function(p) { return p.unit.class.has("Slasher") ? 2.5 : 1; } - }, - 228: { - hp: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } - }, - 230: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 231: { - atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } - }, - 232: { - atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } - }, - 233: { - hp: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 234: { - hp: function(p) { return p.unit.type == "PSY" ? 2 : 1; } - }, - 235: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.2 : 1; } - }, - 236: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } - }, - 248: { - atk: function(p) { return p.unit.type == "STR" ? 2.5 : 1; }, - hp: function(p) { return p.unit.type == "STR" ? 0.4 : 1; } - }, - 249: { - atk: function(p) { return p.unit.type == "STR" ? 3 : 1; }, - hp: function(p) { return p.unit.type == "STR" ? 0.4 : 1; } - }, - 250: { - atk: function(p) { return p.unit.type == "PSY" && p.percHP >= 99.0 ? 3 : 1; } - }, - 251: { - atk: function(p) { return p.unit.type == "PSY" && p.percHP >= 99.0 ? 3 : 1; } - }, - 252: { - atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, - hp: function(p) { return p.unit.type == "QCK" ? 2 : 1; } - }, - 253: { - atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, - hp: function(p) { return p.unit.type == "QCK" ? 2 : 1; } - }, - 254: { - hp: function(p) { return p.unit.type == "INT" ? 2 : 1; }, - atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } - }, - 255: { - hp: function(p) { return p.unit.type == "INT" ? 2 : 1; }, - atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } - }, - 256: { - atk: function(p) { return p.unit.type == "DEX" ? 2 : 1; }, - rcv: function(p) { return p.unit.type == "DEX" ? 2 : 1; } - }, - 257: { - atk: function(p) { return p.unit.type == "DEX" ? 2 : 1; }, - rcv: function(p) { return p.unit.type == "DEX" ? 2 : 1; } - }, - 258: { - atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, - rcv: function(p) { return p.unit.type == "STR" ? 2 : 1; } - }, - 259: { - atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, - rcv: function(p) { return p.unit.type == "STR" ? 2 : 1; } - }, - 260: { - atk: function(p) { return p.percHP <= 30.0 ? 3 : 1; } - }, - 261: { - atk: function(p) { return p.percHP <= 30.0 ? 3 : 1; } - }, - 263: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } - }, - 265: { - atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } - }, - 267: { - atk: function(p) { return 1.5; }, - hp: function(p) { return 1.5; }, - rcv: function(p) { return 1.5; } - }, - 290: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 293: { - hp: function(p) { return p.unit.type == "QCK" ? 2 : 1; } - }, - 294: { - hp: function(p) { return p.unit.type == "STR" ? 2 : 1; } - }, - 295: { - hp: function(p) { return p.unit.type == "DEX" ? 2 : 1; } - }, - 296: { - atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } - }, - 297: { - atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } - }, - 298: { - hp: function(p) { return p.unit.type == "PSY" ? 2 : 1; } - }, - 299: { - atk: function(p) { return p.unit.type == "DEX" ? 2 : 1; } - }, - 305: { - atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, - hp: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 306: { - atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; }, - hp: function(p) { return p.unit.type == "PSY" ? 2 : 1; } - }, - 307: { - atk: function(p) { return p.unit.type == "DEX" ? 2.5 : 1; } - }, - 308: { - atk: function(p) { return p.unit.type == "DEX" ? 2.5 : 1; } - }, - 311: { - hitAtk: function(p) { - return p.modifiers.slice(0, p.chainPosition).subcontains(["Below Good", "Below Good", "Below Good"]) ? 3.5 : 1; - }, - hitModifiers: ["Below Good", "Below Good", "Below Good", "Perfect", "Perfect", "Perfect"] - }, - 312: { - hitAtk: function(p) { - return p.modifiers.slice(0, p.chainPosition).subcontains(["Below Good", "Below Good", "Below Good"]) ? 3.5 : 1; - }, - hitModifiers: ["Below Good", "Below Good", "Below Good", "Perfect", "Perfect", "Perfect"] - }, - 313: { - atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; }, - hp: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } - }, - 314: { - atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; }, - hp: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } - }, - 315: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, - hp: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } - }, - 316: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, - hp: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } - }, - 319: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } - }, - 320: { - atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } - }, - 321: { - atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } - }, - 322: { - atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } - }, - 323: { - atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } - }, - 324: { - atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } - }, - 328: { - rcv: function(p) { return p.percHP <= 30.0 ? 5 : 1; } - }, - 329: { - rcv: function(p) { return p.percHP <= 30.0 ? 5 : 1; } - }, - 332: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.2 : 1; }, - hp: function(p) { return p.unit.class.has("Striker") ? 1.2 : 1; }, - rcv: function(p) { return p.unit.class.has("Striker") ? 1.2 : 1; } - }, - 333: { - atk: function(p) { return p.unit.type == "INT" || p.unit.type == "PSY" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "INT" || p.unit.type == "PSY" ? 1.5 : 1; } - }, - 336: { - atk: function(p) { return p.percHP <= 50.0 ? 1 : (p.unit.type == "PSY" ? 2 : 0.8); } - }, - 337: { - atk: function(p) { return p.percHP <= 50.0 ? 1 : (p.unit.type == "PSY" ? 2.5 : 0.8); } - }, - 340: { - atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } - }, - 341: { - atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } - }, - 352: { - atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } - }, - 353: { - atk: function(p) { return p.unit.class.has("Shooter") ? 2.5 : 1; } - }, - 356: { - atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } - }, - 357: { - atk: function(p) { return p.unit.class.has("Striker") ? 2.5 : 1; } - }, - 358: { - atk: function(p) { return p.unit.type == "DEX" && p.percHP >= 99.0 ? 2.5 : 1; } - }, - 359: { - atk: function(p) { return p.unit.type == "DEX" && p.percHP >= 99.0 ? 3 : 1; } - }, - 360: { - atk: function(p) { return p.unit.type == "INT" && p.percHP <= 30.0 ? 3 : 1; } - }, - 361: { - atk: function(p) { return p.unit.type == "INT" && p.percHP <= 30.0 ? 3 : 1; } - }, - 362: { - atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; }, - rcv: function(p) { return p.unit.type == "PSY" ? 2 : 1; } - }, - 363: { - atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; }, - rcv: function(p) { return p.unit.type == "PSY" ? 2 : 1; } - }, - 364: { - atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, - rcv: function(p) { return p.unit.type == "QCK" ? 2 : 1; } - }, - 365: { - atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, - rcv: function(p) { return p.unit.type == "QCK" ? 2 : 1; } - }, - 366: { - chainModifier: function(p) { return 4; } - }, - 367: { - chainModifier: function(p) { return 4; } - }, - 373: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } - }, - 374: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 375: { - hp: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } - }, - 376: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } - }, - 377: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } - }, - 378: { - rcv: function(p) { return 1.5; } - }, - 380: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 383: { - atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } - }, - 384: { - atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } - }, - 385: { - atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } - }, - 386: { - atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } - }, - 387: { - rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 388: { - rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 389: { - damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['DEX', 'INT', 'QCK']); }, - hitAtk: function(p) { - return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ - type: 'DEX', - minModifier: 'Good' - }, { - type: 'INT', - minModifier: 'Good' - }, { - type: 'QCK', - minModifier: 'Good' - }]) ? 2 : 1; - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 390: { - damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['DEX', 'INT', 'QCK']); }, - hitAtk: function(p) { - return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ - type: 'DEX', - minModifier: 'Good' - }, { - type: 'INT', - minModifier: 'Good' - }, { - type: 'QCK', - minModifier: 'Good' - }]) ? 2.75 : 1; - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 391: { - rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } - }, - 392: { - rcv: function(p) { return p.unit.type == "DEX" ? 2 : 1; } - }, - 395: { - atk: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; }, - rcv: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; } - }, - 396: { - atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } - }, - 397: { - hitAtk: function(p) { - return p.modifiers.slice(0, p.chainPosition) - .subcontains(["Perfect", "Perfect", "Perfect", "Perfect", "Perfect"]) ? 3 : 1; - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 398: { - hitAtk: function(p) { - return p.modifiers.slice(0, p.chainPosition) - .subcontains(["Perfect", "Perfect", "Perfect", "Perfect", "Perfect"]) ? 4 : 1; - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 399: { - hp: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } - }, - 400: { - hp: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } - }, - 401: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } - }, - 402: { - atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } - }, - 403: { - rcv: function(p) { return p.percHP <= 30.0 ? 3 : 1; } - }, - 404: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 405: { - atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } - }, - 408: { - atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } - }, - 409: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } - }, - 410: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2.5 : 1; } - }, - 411: { - atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, - hp: function(p) { return p.unit.type == "STR" ? 2 : 1; } - }, - 412: { - atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, - hp: function(p) { return p.unit.type == "STR" ? 2 : 1; } - }, - 413: { - atk: function(p) { return p.unit.type == "INT" && p.percHP >= 99.0 ? 2.5 : 1; } - }, - 414: { - atk: function(p) { return p.unit.type == "INT" && p.percHP >= 99.0 ? 3 : 1; } - }, - 415: { - atk: function(p) { - return (p.unit.type == "QCK" || p.unit.type == "PSY") && p.percHP >= 70.0 ? 2.75 : 1; - }, - rcv: function(p) { - return (p.unit.type == "QCK" || p.unit.type == "PSY") && p.percHP >= 70.0 ? 1.5 : 1; - } - }, - 416: { - atk: function(p) { - return (p.unit.type == "QCK" || p.unit.type == "PSY") && p.percHP >= 70.0 ? 2.75 : 1; - }, - rcv: function(p) { - return (p.unit.type == "QCK" || p.unit.type == "PSY") && p.percHP >= 70.0 ? 1.5 : 1; - } - }, - 417: { - atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } - }, - 418: { - hp: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; }, - atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } - }, - 419: { - atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } - }, - 420: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, - hp: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 421: { - atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, - hp: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } - }, - 422: { - atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, - hp: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } - }, - 424: { - atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } - }, - 425: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, - hp: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } - }, - 426: { - hp: function(p) { return p.unit.type == "STR" ? 2 : 1; } - }, - 427: { - hp: function(p) { return p.unit.type == "DEX" ? 2 : 1; } - }, - 428: { - atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } - }, - 430: { - atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } - }, - 431: { - atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, - hp: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } - }, - 433: { - damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['QCK', 'STR', 'DEX']); }, - hitAtk: function(p) { - return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ - type: 'QCK', - minModifier: 'Good' - }, { - type: 'STR', - minModifier: 'Good' - }, { - type: 'DEX', - minModifier: 'Good' - }]) ? 2 : 1; - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 434: { - damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['PSY', 'INT', 'INT']); }, - hitAtk: function(p) { - return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ - type: 'PSY', - minModifier: 'Good' - }, { - type: 'INT', - minModifier: 'Good' - }, { - type: 'INT', - minModifier: 'Good' - }]) ? 2 : 1; - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 435: { - damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['INT', 'PSY', 'QCK']); }, - hitAtk: function(p) { - return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ - type: 'INT', - minModifier: 'Good' - }, { - type: 'PSY', - minModifier: 'Good' - }, { - type: 'QCK', - minModifier: 'Good' - }]) ? 2 : 1; - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 437: { - rcv: function(p) { return p.percHP <= 30.0 ? 3 : 1; } - }, - 438: { - rcv: function(p) { return p.percHP <= 30.0 ? 5 : 1; } - }, - 444: { - atk: function(p) { - return p.percHP >= 50.0 && (p.unit.class.has("Booster") || p.unit.class.has("Evolver")) ? 2 : 1; - } - }, - 445: { - atk: function(p) { - return p.percHP >= 50.0 && (p.unit.class.has("Booster") || p.unit.class.has("Evolver")) ? 2.5 : 1; - } - }, - 446: { - atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, - hp: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 447: { - atk: function(p) { return p.unit.type == "STR" ? 2.5 : 1; }, - hp: function(p) { return p.unit.type == "STR" ? 2.25 : 1; } - }, - 448: { - atk: function(p) { return p.unit.type == "QCK" && p.percHP >= 99.0 ? 3 : 1; } - }, - 449: { - atk: function(p) { return p.unit.type == "QCK" && p.percHP >= 99.0 ? 3 : 1; } - }, - 450: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; }, - hp: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } - }, - 451: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; }, - hp: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } - }, - 452: { - atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } - }, - 453: { - atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } - }, - 454: { - atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } - }, - 455: { - atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } - }, - 456: { - atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; }, - rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 457: { - atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; }, - rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 458: { - atk: function(p) { return p.unit.cost <= 20 ? 3 : 1; } - }, - 459: { - atk: function(p) { return p.unit.number == 458 || p.unit.cost <= 20 ? 3 : 1; } - }, - 461: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } - }, - 462: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } - }, - 463: { - hp: function(p) { return p.unit.type == "PSY" ? 2 : 1; } - }, - 464: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, - hp: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } - }, - 465: { - hitAtk: function(p) { - return p.modifiers.slice(0, p.chainPosition).subcontains(["Below Good", "Below Good", "Below Good", "Below Good"]) ? 3 : 1; - }, - hitModifiers: ["Below Good", "Below Good", "Below Good", "Below Good", "Perfect", "Perfect"] - }, - 466: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, - hp: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 467: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, - hp: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 470: { - rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 471: { - atk: function(p) { return p.unit.type == "INT" ? 1.2 : 1; }, - hp: function(p) { return p.unit.type == "INT" ? 1.2 : 1; } - }, - 482: { - hp: function(p) { return p.unit.class.has("Striker") ? 1.2 : 1; } - }, - 483: { - atk: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; }, - rcv: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; } - }, - 485: { - hp: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; }, - rcv: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; } - }, - 486: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.2 : 1; } - }, - 490: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.2 : 1; }, - hp: function(p) { return p.unit.class.has("Striker") ? 1.2 : 1; } - }, - 491: { - rcv: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } - }, - 492: { - atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } - }, - 496: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 497: { - atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } - }, - 498: { - atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, - hp: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } - }, - 499: { - rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 500: { - rcv: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } - }, - 501: { - atk: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; }, - hp: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; }, - rcv: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; } - }, - 502: { - atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, - hp: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 503: { - hp: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } - }, - 504: { - hp: function(p) { return p.unit.type == "INT" ? 2 : 1; } - }, - 507: { - atk: function(p) { return p.unit.type == "STR" ? 1.2 : 1; }, - hp: function(p) { return p.unit.type == "STR" ? 1.2 : 1; } - }, - 508: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, - hp: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 509: { - atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } - }, - 510: { - atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } - }, - 511: { - atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } - }, - 513: { - atk: function(p) { return p.unit.type == "PSY" && p.percHP >= 50.0 ? 1.5 : 1; } - }, - 514: { - atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } - }, - 515: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, - hp: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 516: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, - hp: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 517: { - hp: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 518: { - hp: function(p) { return p.unit.type == "PSY" ? 2 : 1; } - }, - 519: { - atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } - }, - 520: { - atk: function(p) { return p.unit.type == "STR" ? 2.5 : 1; } - }, - 523: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } - }, - 524: { - atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; }, - rcv: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } - }, - 525: { - atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } - }, - 526: { - atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } - }, - 527: { - atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } - }, - 528: { - atk: function(p) { return p.unit.type == "DEX" ? 2 : 1; }, - rcv: function(p) { return p.unit.type == "DEX" ? 2 : 1; } - }, - 529: { - atk: function(p) { return p.unit.type == "PSY" ? 2 + 0.75 * p.percHP / 100 : 1; } - }, - 530: { - atk: function(p) { return p.unit.type == "PSY" ? 2 + 0.75 * p.percHP / 100 : 1; } - }, - 533: { - atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } - }, - 534: { - atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } - }, - 535: { - rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } - }, - 536: { - rcv: function(p) { return p.unit.type == "DEX" ? 2 : 1; } - }, - 537: { - chainModifier: function(p) { return 2; } - }, - 538: { - chainModifier: function(p) { return 2; } - }, - 541: { - atk: function(p) { return p.unit.type == "STR" && p.percHP <= 50.0 ? 2.5 : 1; } - }, - 542: { - hp: function(p) { return 1.5; } - }, - 543: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, - hp: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, - rcv: function(p) { return 0; } - }, - 544: { - atk: function(p) { return p.unit.class.has("Shooter") ? 2.25 : 1; }, - hp: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, - rcv: function(p) { return 0; } - }, - 545: { - atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } - }, - 546: { - atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } - }, - 548: { - atk: function(p) { return 1.2; } - }, - 549: { - hitAtk: function(p) { - return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2 : 1; - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 550: { - hitAtk: function(p) { - return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.5 : 1; - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 553: { - atk: function(p) { return p.unit.type == "DEX" && p.percHP <= 30.0 ? 2.75 : 1; } - }, - 554: { - atk: function(p) { return p.unit.type == "DEX" && p.percHP <= 30.0 ? 3 : 1; } - }, - 555: { - atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } - }, - 556: { - atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; }, - rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 557: { - atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } - }, - 558: { - atk: function(p) { return p.unit.type == "INT" ? 2 : 1; }, - rcv: function(p) { return p.unit.type == "INT" ? 2 : 1; } - }, - 559: { - atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } - }, - 560: { - atk: function(p) { return p.unit.type == "STR" ? 2.25 : 1; } - }, - 561: { - atk: function(p) { return !p.unit.class.has("Shooter") ? 1 : (p.orb == 2.0 ? 3 : 2); }, - hp: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 562: { - atk: function(p) { return !p.unit.class.has("Shooter") ? 1 : (p.orb == 2.0 ? 3 : 2); }, - hp: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 568: { - atk: function(p) { return 1.25; }, - hp: function(p) { return 1.25; }, - rcv: function(p) { return 1.25; } - }, - 569: { - atk: function(p) { return 1.5; }, - hp: function(p) { return 1.5; }, - rcv: function(p) { return 1.5; } - }, - 570: { - atk: function(p) { - return p.unit.class.has("Fighter") && p.unit.type == "STR" ? 2.25 : - p.unit.type == "STR" || p.unit.class.has("Fighter") ? 1.5 : - 1; - } - }, - 571: { - atk: function(p) { - return p.unit.class.has("Fighter") && p.unit.type == "STR" ? 2.25 : - p.unit.type == "STR" || p.unit.class.has("Fighter") ? 1.5 : - 1; - } - }, - 572: { - atk: function(p) { return p.unit.class.has("Fighter") && p.percHP >= 99.0 ? 2.5 : 1; } - }, - 573: { - rcv: function(p) { return 1.2; } - }, - 574: { - atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } - }, - 575: { - atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; }, - hp: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } - }, - 576: { - atk: function(p) { return 1.5; }, - rcv: function(p) { return 1.2; } - }, - 577: { - hitAtk: function(p) { - return p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 4 : 1; - }, - hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 578: { - hitAtk: function(p) { - return p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 4 : 1; - }, - hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 579: { - atk: function(p) { return (p.unit.type == "QCK" || p.unit.type == "DEX") ? 1.5 : 1; } - }, - 580: { - atk: function(p) { return (p.unit.type == "QCK" || p.unit.type == "DEX") ? 2 : 1; } - }, - 581: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 582: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, - hp: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } - }, - 583: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 584: { - atk: function(p) { return 0.1; }, - hp: function(p) { return 0.1; }, - rcv: function(p) { return 0.1; } - }, - 585: { - rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 586: { - hp: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 589: { - atk: function(p) { return 1.5; }, - hp: function(p) { return 0.2; }, - rcv: function(p) { return 0.2; } - }, - 590: { - atk: function(p) { return 1.5; }, - hp: function(p) { return 0.2; }, - rcv: function(p) { return 0.2; } - }, - 596: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 597: { - atk: function(p) { return p.unit.type == "STR" ? 1.75 : 1; } - }, - 598: { - atk: function(p) { return p.unit.stars < 3 ? 2.5 : 1; } - }, - 599: { - atk: function(p) { return p.unit.stars < 3 ? 3 : 1; } - }, - 600: { - atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 601: { - atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } - }, - 602: { - atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } - }, - 603: { - atk: function(p) { return p.unit.type == "QCK" ? 2.25 : 1; } - }, - 604: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } - }, - 605: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } - }, - 606: { - atk: function(p) { return p.percHP >= 50.0 && p.unit.class.has("Fighter") ? 2 : 1; } - }, - 607: { - atk: function(p) { return p.percHP >= 50.0 && p.unit.class.has("Fighter") ? 2.5 : 1; } - }, - 612: { - hp: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, - atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } - }, - 613: { - hp: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, - atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } - }, - 614: { - atk: function(p) { return p.unit.cost <= 20 && p.percHP <= 30.0 ? 2.25 : 1; } - }, - 629: { - atk: function(p) { return p.unit.stars <= 3 ? 2 : 1; } - }, - 630: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } - }, - 631: { - atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } - }, - 632: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } - }, - 633: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } - }, - 634: { - atk: function(p) { return p.unit.type == "QCK" || p.unit.type == "PSY" ? 1.25 : 1; }, - rcv: function(p) { return p.unit.type == "QCK" || p.unit.type == "PSY" ? 1.25 : 1; } - }, - 635: { - atk: function(p) { return p.unit.type == "QCK" || p.unit.type == "PSY" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "QCK" || p.unit.type == "PSY" ? 1.5 : 1; } - }, - 636: { - atk: function(p) { return p.unit.cost <= 2 ? 3 : 1; } - }, - 637: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } - }, - 638: { - atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } - }, - 639: { - atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } - }, - 640: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } - }, - 641: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2.25 : 1; } - }, - 642: { - atk: function(p) { return p.unit.type == "PSY" && p.percHP <= 30.0 ? 2.5 : 1; } - }, - 643: { - atk: function(p) { return p.unit.type == "PSY" && p.percHP <= 30.0 ? 3 : 1; } - }, - 644: { - atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } - }, - 645: { - atk: function(p) { return p.unit.type == "INT" ? 2.5 : 1; } - }, - 646: { - atk: function(p) { return p.unit.class.has("Shooter") && p.percHP <= 30.0 ? 2.5 : 1; } - }, - 647: { - atk: function(p) { return p.unit.class.has("Shooter") && p.percHP <= 30.0 ? 2.75 : 1; } - }, - 648: { - atk: function(p) { - return (p.unit.type == "QCK" || p.unit.type == "PSY") && p.percHP >= 70.0 ? 2.75 : 1; - } - }, - 649: { - atk: function(p) { - return (p.unit.type == "QCK" || p.unit.type == "PSY") && p.percHP >= 70.0 ? 2.75 : 1; - } - }, - 650: { - atk: function(p) { return p.unit.type == "INT" ? 2 : 1; }, - rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } - }, - 651: { - atk: function(p) { return p.unit.type == "INT" ? 2 : 1; }, - rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } - }, - 652: { - atk: function(p) { return p.unit.type != "DEX" ? 1 : (p.orb == 2.0 ? 2 : 1); } - }, - 653: { - atk: function(p) { return p.unit.type != "DEX" ? 1 : (p.orb == 2.0 ? 2.25 : 1); } - }, - 654: { - atk: function(p) { return p.unit.type != "DEX" ? 1 : (p.orb == 2.0 ? 2.75 : 1); } - }, - 655: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 656: { - atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } - }, - 657: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } - }, - 658: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 659: { - hitAtk: function(p) { - return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.5 : 1; - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 660: { - atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } - }, - 661: { - atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } - }, - 662: { - atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } - }, - 665: { - atk: function(p) { return 1.2; }, - hp: function(p) { return 0.2; }, - rcv: function(p) { return 0.2; } - }, - 666: { - atk: function(p) { return 1.75; }, - hp: function(p) { return 0.2; }, - rcv: function(p) { return 0.2; } - }, - 667: { - atk: function(p) { return 1.75; } - }, - 668: { - atk: function(p) { return p.unit.class.has("Freedom") ? 2 + 0.75 * p.percHP / 100 : 1; }, - hp: function(p) { return 1.2; }, - rcv: function(p) { return 1.2; } - }, - 669: { - atk: function(p) { return p.unit.class.has("Freedom") ? 2 + 0.75 * p.percHP / 100 : 1; }, - hp: function(p) { return 1.2; }, - rcv: function(p) { return 1.2; } - }, - 670: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } - }, - 671: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2.25 : 1; }, - rcv: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } - }, - 672: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } - }, - 673: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } - }, - 674: { - atk: function(p) { return p.unit.class.has("Freedom") ? 2 : 1; } - }, - 675: { - atk: function(p) { return p.unit.class.has("Freedom") ? 2.5 : 1; } - }, - 676: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } - }, - 677: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } - }, - 678: { - atk: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; }, - rcv: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; } - }, - 679: { - atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 681: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } - }, - 683: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } - }, - 684: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 686: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } - }, - 687: { - atk: function(p) { return p.unit.class.has("Freedom") ? 1.5 : 1; } - }, - 688: { - atk: function(p) { return p.unit.class.has("Freedom") ? 2 : 1; } - }, - 689: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.2 : 1; }, - rcv: function(p) { return p.unit.class.has("Slasher") ? 1.2 : 1; } - }, - 690: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } - }, - 696: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.75 : 1; } - }, - 697: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.75 : 1; } - }, - 698: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.75 : 1; } - }, - 699: { - atkStatic: function(p) { return p.unit.class.has("Shooter") ? 500 : 0; } - }, - 700: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.75 : 1; } - }, - 701: { - hp: function(p) { return p.unit.type == "PSY" ? 2.25 : 1; } - }, - 702: { - hp: function(p) { return p.unit.type == "INT" ? 2.25 : 1; } - }, - 705: { - atk: function(p) { - return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 1.25 : 1; - }, - hp: function(p) { - return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 1.25 : 1; - } - }, - 706: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 707: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 708: { - atk: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; }, - rcv: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; } - }, - 709: { - atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 710: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 711: { - atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } - }, - 712: { - atk: function(p) { return p.unit.class.has("Striker") && p.percHP >= 50 ? 2 : 1; } - }, - 713: { - atk: function(p) { return p.unit.class.has("Striker") && p.percHP >= 50 ? 2.5 : 1; } - }, - 715: { - rcv: function(p) { return p.percHP <= 30 ? 3 : 1; } - }, - 716: { - rcv: function(p) { return p.percHP <= 30 ? 5 : 1; } - }, - 717: { - damageSorter: function(d) { return CrunchUtils.mihawkSort(d); }, - hitAtk: function(p) { - if (!p.unit.class.has('Slasher')) return 1; - var prev = p.modifiers.slice(p.chainPosition - 1, p.chainPosition)[0]; - return p.chainPosition === 0 ? 2 : (prev == 'Good' ? 2.25 : (prev == 'Great' ? 2.5 : (prev == 'Perfect' ? 2.75 : 2))); - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 718: { - damageSorter: function(d) { return CrunchUtils.mihawkSort(d); }, - hitAtk: function(p) { - if (!p.unit.class.has('Slasher')) return 1; - var prev = p.modifiers.slice(p.chainPosition - 1, p.chainPosition)[0]; - return p.chainPosition === 0 ? 2 : (prev == 'Good' ? 2.25 : (prev == 'Great' ? 2.5 : (prev == 'Perfect' ? 2.75 : 2))); - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 719: { - atk: function(p) { - return p.unit.class.has("Knowledge") ? 1.5 + 1.75 * ((100 - p.percHP) / 100) : 1; - } - }, - 720: { - atk: function(p) { - return p.unit.class.has("Knowledge") ? 1.5 + 1.75 * ((100 - p.percHP) / 100) : 1; - } - }, - 721: { - atk: function(p) { return p.unit.class.has("Fighter") && p.percHP >= 99.0 ? 1.5 : 1; } - }, - 722: { - atk: function(p) { return p.unit.class.has("Fighter") && p.percHP >= 99.0 ? 2 : 1; } - }, - 723: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } - }, - 724: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.75 : 1; } - }, - 727: { - atk: function(p) { - return p.unit.class.has("Freedom") || p.unit.class.has("Fighter") ? 1.75 : 1; - } - }, - 728: { - atk: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; }, - rcv: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; } - }, - 730: { - atk: function(p) { return p.unit.type == "INT" ? 1.2 : 1; }, - hp: function(p) { return p.unit.type == "INT" ? 1.2 : 1; } - }, - 731: { - atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, - hp: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } - }, - 732: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 733: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } - }, - 734: { - atk: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; }, - rcv: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; } - }, - 735: { - atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 736: { - atk: function(p) { return p.unit.class.has("Slasher") && p.percHP >= 50.0 ? 2.5 : 1; } - }, - 737: { - atk: function(p) { return p.unit.class.has("Fighter") && p.percHP <= 30.0 ? 2.75 : 1; } - }, - 738: { - atk: function(p) { return p.unit.cost >= 21 ? 2 : 1; } - }, - 739: { - atk: function(p) { return p.unit.class.has("Freedom") ? 2 : 1; } - }, - 742: { - atk: function(p) { return p.unit.class.has("Freedom") ? 1.2 : 1; }, - rcv: function(p) { return p.unit.class.has("Freedom") ? 1.2 : 1; } - }, - 743: { - atk: function(p) { return p.unit.class.has("Freedom") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Freedom") ? 1.5 : 1; } - }, - 744: { - atk: function(p) { return p.unit.class.has("Freedom") ? 2 : 1; } - }, - 745: { - atk: function(p) { return p.unit.class.has("Freedom") ? 2.5 : 1; } - }, - 747: { - atk: function(p) { return !p.unit.class.has("Tough") ? 1 : (p.orb == 2.0 ? 3 : 2.5); }, - rcv: function(p) { return 0; } - }, - 748: { - atk: function(p) { return !p.unit.class.has("Tough") ? 1 : (p.orb == 2.0 ? 3 : 2.5); }, - rcv: function(p) { return 0; } - }, - 749: { - atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } - }, - 750: { - atk: function(p) { return p.unit.type == "DEX" ? 2 : 1; } - }, - 751: { - atk: function(p) { return p.unit.class.has("Knowledge") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Knowledge") ? 1.5 : 1; } - }, - 752: { - atk: function(p) { return p.unit.class.has("Knowledge") ? 2.25 : 1; }, - rcv: function(p) { return p.unit.class.has("Knowledge") ? 1.5 : 1; } - }, - 753: { - atk: function(p) { return p.unit.class.has("Tough") ? 2 : 1; } - }, - 754: { - atk: function(p) { return p.unit.class.has("Tough") ? 2.5 : 1; } - }, - 755: { - atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } - }, - 756: { - atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } - }, - 757: { - atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } - }, - 758: { - atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } - }, - 759: { - atk: function(p) { return p.unit.type == "STR" && p.percHP <= 30.0 ? 2.5 : 1; } - }, - 760: { - atk: function(p) { return p.unit.type == "STR" && p.percHP <= 30.0 ? 3 : 1; } - }, - 761: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } - }, - 762: { - atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 763: { - atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } - }, - 764: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } - }, - 766: { - atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } - }, - 767: { - atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } - }, - 768: { - atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } - }, - 769: { - atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } - }, - 770: { - atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } - }, - 771: { - atk: function(p) { return p.unit.class.has("Knowledge") ? 2.5 : 1; } - }, - 772: { - atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } - }, - 774: { - atk: function(p) { return p.unit.class.has("Freedom") ? 2 : 1; } - }, - 775: { - atk: function(p) { return p.unit.class.has("Knowledge") ? 1.5 : 1; }, - hp: function(p) { return p.unit.class.has("Knowledge") ? 1.5 : 1; } - }, - 776: { - atk: function(p) { return p.unit.type == "PSY" ? 1.25 : 1; }, - rcv: function(p) { return p.unit.type == "PSY" ? 1.25 : 1; } - }, - 777: { - atk: function(p) { return p.unit.type == "PSY" ? 1.75 : 1; }, - rcv: function(p) { return p.unit.type == "PSY" ? 1.75 : 1; } - }, - 780: { - atk: function(p) { return p.percHP <= 30.0 ? 2 : 1; } - }, - 781: { - atk: function(p) { return p.percHP <= 30.0 ? 2.5 : 1; } - }, - 782: { - rcv: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } - }, - 783: { - atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; }, - rcv: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } - }, - 789: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } - }, - 791: { - atk: function(p) { return /STR|DEX|QCK/.test(p.unit.type) ? 1.25 : 1; }, - hp: function(p) { return /STR|DEX|QCK/.test(p.unit.type) ? 1.25 : 1; }, - rcv: function(p) { return /STR|DEX|QCK/.test(p.unit.type) ? 1.25 : 1; } - }, - 793: { - atk: function(p) { return p.unit.class.has("Knowledge") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Knowledge") ? 1.5 : 1; } - }, - 794: { - atk: function(p) { - return p.unit.class.has("Tough") ? Math.max(1.0, 3.0 - 0.1 * p.turnCounter) : 1; - } - }, - 795: { - atk: function(p) { - return p.unit.class.has("Tough") ? Math.max(1.0, 3.5 - 0.1 * p.turnCounter) : 1; - } - }, - 796: { - atk: function(p) { return p.unit.class.has("Knowledge") ? 2 : 1; } - }, - 797: { - atk: function(p) { return p.unit.class.has("Knowledge") || p.unit.class.has("Tough") ? 2 : 1; } - }, - 798: { - hitAtk: function(p) { - return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.5 : 1; - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 801: { - atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } - }, - 802: { - atk: function(p) { return p.unit.type == "PSY" ? 2.5 : 1; } - }, - 803: { - atk: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; }, - rcv: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; } - }, - 804: { - atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } - }, - 805: { - atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } - }, - 806: { - atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } - }, - 807: { - atk: function(p) { return p.unit.class.has("Knowledge") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Knowledge") ? 1.5 : 1; } - }, - 808: { - atk: function(p) { return p.unit.class.has("Knowledge") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Knowledge") ? 1.5 : 1; } - }, - 809: { - atk: function(p) { return p.unit.class.has("Tough") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Tough") ? 1.5 : 1; } - }, - 810: { - atk: function(p) { return p.unit.class.has("Tough") ? 2 : 1; }, - rcv: function(p) { return p.unit.class.has("Tough") ? 1.5 : 1; } - }, - 815: { - damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['STR', 'INT', 'DEX']); }, - hitAtk: function(p) { - return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ - type: 'STR', - minModifier: 'Good' - }, { - type: 'INT', - minModifier: 'Good' - }, { - type: 'DEX', - minModifier: 'Good' - }]) ? 2.5 : 1; - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 816: { - damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['STR', 'INT', 'DEX']); }, - hitAtk: function(p) { - return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ - type: 'STR', - minModifier: 'Good' - }, { - type: 'INT', - minModifier: 'Good' - }, { - type: 'DEX', - minModifier: 'Good' - }]) ? 2.75 : 1; - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 825: { - atk: function(p) { return p.unit.type == 'STR' ? 1.5 : 1; }, - hp: function(p) { return p.unit.type == 'STR' ? 1.5 : 1; } - }, - 826: { - atk: function(p) { return p.unit.type == 'DEX' ? 1.5 : 1; }, - hp: function(p) { return p.unit.type == 'DEX' ? 1.5 : 1; } - }, - 827: { - atk: function(p) { return p.unit.type == 'QCK' ? 1.5 : 1; }, - hp: function(p) { return p.unit.type == 'QCK' ? 1.5 : 1; } - }, - 830: { - atk: function(p) { - return p.unit.class.has("Striker") || p.unit.class.has("Knowledge") ? 1.75 : 1; - } - }, - 831: { - atk: function(p) { - return p.unit.class.has("Striker") || p.unit.class.has("Knowledge") ? 2 : 1; - } - }, - 832: { - atk: function(p) { - return p.unit.class.has("Freedom") ? 1 + 1.5 * ((100 - p.percHP) / 100) : 1; - } - }, - 833: { - atk: function(p) { - return p.unit.class.has("Freedom") ? 1 + 1.75 * ((100 - p.percHP) / 100) : 1; - } - }, - 834: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 835: { - atk: function(p) { return p.unit.class.has("Knowledge") ? 2 : 1; }, - hp: function(p) { return p.unit.class.has("Knowledge") ? 2 : 1; } - }, - 836: { - atk: function(p) { return p.unit.class.has("Knowledge") ? 2 : 1; }, - hp: function(p) { return p.unit.class.has("Knowledge") ? 2 : 1; } - }, - 837: { - atk: function(p) { return p.unit.class.has("Ambition") ? 2 : 1; } - }, - 838: { - atk: function(p) { return p.unit.class.has("Ambition") ? 2.5 : 1; } - }, - 839: { - atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } - }, - 840: { - atk: function(p) { return p.unit.class.has("Striker") ? 2.5 : 1; } - }, - 843: { - atk: function(p) { - return p.unit.class.has("Shooter") || p.unit.class.has("Slasher") || p.unit.class.has("Striker") ? 1.5 : 1; - } - }, - 844: { - atk: function(p) { - return p.unit.class.has("Shooter") || p.unit.class.has("Slasher") || p.unit.class.has("Striker") ? 2 : 1; - } - }, - 845: { - hit: function(n) { - return n > 22 ? 2.5 : - n > 11 ? 1.5 : 1; - } - }, - 846: { - hit: function(n) { - return n > 40 ? 3.5 : - n > 30 ? 2.75 : - n > 22 ? 2.5 : - n > 11 ? 1.5 : 1; - } - }, - 847: { - atk: function(p) { return p.percHP <= 30.0 ? 1.5 : 1; } - }, - 848: { - atk: function(p) { return p.percHP <= 30.0 ? 1.5 : 1; } - }, - 849: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.75 : 1; } - }, - 850: { - atk: function(p) { - return p.unit.class.has("Striker") || p.unit.class.has("Knowledge") ? 1.5 : 1; - } - }, - 851: { - atk: function(p) { return p.unit.class.has("Ambition") ? 1.5 : 1; } - }, - 852: { - atk: function(p) { return p.unit.class.has("Ambition") ? 2 : 1; } - }, - 854: { - atk: function(p) { return p.unit.type == 'DEX' ? 1.5 : 1; } - }, - 855: { - atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } - }, - 856: { - atk: function(p) { return p.unit.class.has("Slasher") ? 2.5 : 1; } - }, - 857: { - atk: function(p) { return p.unit.type == 'PSY' ? 2 : 1; } - }, - 858: { - atk: function(p) { return p.unit.type == 'PSY' ? 2 : 1; }, - rcv: function(p) { return p.unit.type == 'PSY' ? 2 : 1; } - }, - 859: { - atk: function(p) { return p.unit.class.has("Ambition") ? 1.5 : 1; } - }, - 860: { - atk: function(p) { return p.unit.class.has("Ambition") ? 2 : 1; } - }, - 862: { - atk: function(p) { return p.unit.type == 'QCK' ? 2 : 1; } - }, - 863: { - atk: function(p) { return p.unit.type == 'QCK' ? 1.75 : 1; } - }, - 864: { - atk: function(p) { return p.unit.class.has("Freedom") ? 2 : 1; } - }, - 865: { - atk: function(p) { return p.unit.class.has("Freedom") ? 2 : 1; }, - hp: function(p) { return p.unit.class.has("Freedom") ? 2 : 1; } - }, - 866: { - atk: function(p) { return p.unit.class.has("Knowledge") ? 2 : 1; } - }, - 867: { - hit: function(n) { return n > 11 ? 1.5 : 1; } - }, - 868: { - atk: function(p) { return 1.2; } - }, - 869: { - hitAtk: function(p) { - if (!p.unit.class.has("Ambition")) return 1; - return p.modifiers.slice(0, p.chainPosition).count("Perfect") == p.chainPosition ? 3 : 1; - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 870: { - hitAtk: function(p) { - if (!p.unit.class.has("Ambition")) return 1; - return p.modifiers.slice(0, p.chainPosition).count("Perfect") == p.chainPosition ? 3 : 1; - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 871: { - atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } - }, - 872: { - atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, - rcv: function(p) { return p.unit.type == "QCK" ? 2 : 1; } - }, - 873: { - atk: function(p) { return p.unit.class.has("Fighter") && p.percHP <= 30.0 ? 2.5 : 1; } - }, - 874: { - atk: function(p) { return p.unit.class.has("Fighter") && p.percHP <= 30.0 ? 3 : 1; } - }, - 875: { - atk: function(p) { - return p.unit.class.has("Knowledge") || p.unit.class.has("Ambition") ? 2 : 1; - } - }, - 876: { - atk: function(p) { - return p.unit.class.has("Knowledge") || p.unit.class.has("Ambition") ? 2.25 : 1; - } - }, - 878: { - atk: function(p) { return 1.5; } - }, - 879: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.75 : 1; } - }, - 880: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } - }, - 881: { - hitAtk: function(p) { - if (!p.unit.class.has("Shooter") && !p.unit.class.has("Freedom")) return 1; - return p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 2 : 1; - }, - hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 882: { - hitAtk: function(p) { - if (!p.unit.class.has("Shooter") && !p.unit.class.has("Freedom")) return 1; - return p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 3 : 1; - }, - hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 883: { - atk: function(p) { return p.unit.class.has("Tough") ? 1.25 : 1; }, - hp: function(p) { return p.unit.class.has("Tough") ? 1.25 : 1; } - }, - 884: { - atk: function(p) { return p.unit.class.has("Tough") ? 1.5 : 1; }, - hp: function(p) { return p.unit.class.has("Tough") ? 1.5 : 1; } - }, - 885: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } - }, - 886: { - atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } - }, - 887: { - atk: function(p) { return p.unit.class.has("Ambition") ? 1.5 : 1; } - }, - 889: { - atk: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; }, - rcv: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; } - }, - 890: { - atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } - }, - 891: { - atk: function(p) { return p.unit.class.has("Tough") ? 1.5 : 1; }, - hp: function(p) { return p.unit.class.has("Tough") ? 1.5 : 1; } - }, - 892: { - chainModifier: function(p) { return 2; } - }, - 893: { - hitAtk: function(p) { - if (!p.unit.class.has("Tough")) return 1; - return p.modifiers.slice(0, p.chainPosition) - .subcontains(["Perfect", "Perfect", "Perfect"]) ? 3 : 1; - }, - hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 894: { - hitAtk: function(p) { - if (!p.unit.class.has("Ambition")) return 1; - return p.modifiers.slice(0, p.chainPosition) - .subcontains(["Good", "Great", "Perfect"]) ? 3 : 1; - }, - hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] - }, - 895: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } - }, - 896: { - atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } - }, - 897: { - atk: function(p) { - return p.unit.class.has("Knowledge") || p.unit.class.has("Ambition") ? 2 : 1; - } - }, - 898: { - atk: function(p) { - return p.unit.class.has("Striker") || p.unit.class.has("Knowledge") ? 1.5 : 1; - }, - hp: function(p) { - return p.unit.class.has("Striker") || p.unit.class.has("Knowledge") ? 1.5 : 1; - } - }, - 899: { - atk: function(p) { - return p.unit.class.has("Fighter") || p.unit.class.has("Freedom") ? 1.75 : 1; - }, - hp: function(p) { - return p.unit.class.has("Fighter") || p.unit.class.has("Freedom") ? 1.25 : 1; - } - }, - 900: { - atk: function(p) { return p.unit.class.has("Shooter") && p.percHP >= 99.0 ? 2 : 1; } - }, - 901: { - atk: function(p) { return p.unit.class.has("Shooter") && p.percHP >= 99.0 ? 2.75 : 1; } - }, - 902: { - atk: function(p) { return p.class.has("Tough") ? 1.25 : 1; }, - hp: function(p) { return p.class.has("Tough") ? 1.25 : 1; } - }, - 903: { - atk: function(p) { return p.class.has("Tough") ? 1.25 : 1; }, - hp: function(p) { return p.class.has("Tough") ? 1.25 : 1; } - }, - 905: { - atk: function(p) { return p.unit.class.has("Slasher") && p.percHP <= 30 ? 2.5 : 1; } - }, - 906: { - atk: function(p) { return p.unit.class.has("Slasher") && p.percHP <= 30 ? 2.75 : 1; } - }, - 907: { - atk: function(p) { return p.unit.class.has("Knowledge") && p.percHP <= 30 ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Knowledge") && p.percHP <= 30 ? 1.5 : 1; } - }, - 908: { - atk: function(p) { return p.unit.class.has("Knowledge") && p.percHP <= 30 ? 2.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Knowledge") && p.percHP <= 30 ? 1.75 : 1; } - }, - 909: { - atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, - rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 910: { - atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; }, - rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } - }, - 911: { - atk: function(p) { return p.unit.class.has("Tough") ? 1.5 : 1; }, - hp: function(p) { return p.unit.class.has("Tough") ? 1.5 : 1; } - }, - 912: { - atk: function(p) { return p.unit.class.has("Tough") ? 2.25 : 1; }, - hp: function(p) { return p.unit.class.has("Tough") ? 2.25 : 1; } - }, - 913: { - atk: function(p) { return p.unit.type != "QCK" ? 1 : (p.orb == 2.0 ? 3 : 1); } - }, - 914: { - atk: function(p) { return p.unit.type != "QCK" ? 1 : (p.orb == 2.0 ? 3 : 1.2); } - }, - 915: { - atk: function(p) { return p.unit.class.has("Knowledge") ? 1.2 : 1; }, - rcv: function(p) { return p.unit.class.has("Knowledge") ? 1.2 : 1; } - }, - 916: { - atk: function(p) { return p.unit.class.has("Knowledge") ? 1.75 : 1; }, - rcv: function(p) { return p.unit.class.has("Knowledge") ? 1.75 : 1; } - }, - 917: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } - }, - 918: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.75 : 1; } - } -}; \ No newline at end of file + 2: { + atk: function(p) { return 1.5; } + }, + 3: { + atk: function(p) { return 1.5; } + }, + 4: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1.5; } + }, + 5: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 6: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 7: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 8: { + atk: function(p) { return p.unit.type == "DEX" ? 2 : 1; }, + hp: function(p) { return p.unit.type == "DEX" ? 2 : 1; } + }, + 10: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } + }, + 11: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } + }, + 12: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } + }, + 13: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.2 : 1; } + }, + 14: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 15: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 16: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 17: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 18: { + hp: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 19: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 20: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 21: { + rcv: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; } + }, + 22: { + rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 23: { + rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } + }, + 24: { + rcv: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 25: { + rcv: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 26: { + rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 27: { + hp: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; } + }, + 28: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.2 : 1; } + }, + 35: { + hp: function(p) { return p.unit.class.has("Slasher") ? 1.2 : 1; } + }, + 36: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 37: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 38: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } + }, + 39: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } + }, + 41: { + rcv: function(p) { return p.unit.type == "INT" ? 1.2 : 1; } + }, + 42: { + atk: function(p) { return p.unit.type == "STR" ? 1.2 : 1; } + }, + 45: { + atk: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; } + }, + 46: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 49: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 52: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.5 : 1; } + }, + 59: { + atk: function(p) { return p.unit.type == "INT" ? 1.2 : 1; } + }, + 60: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 61: { + hp: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 62: { + hp: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } + }, + 65: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 66: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 67: { + rcv: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 68: { + rcv: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 74: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 75: { + atk: function(p) { return p.unit.type == "QCK" ? 2.5 : 1; } + }, + 76: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 77: { + atk: function(p) { return p.unit.type == "PSY" ? 2.5 : 1; } + }, + 194: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 195: { + rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 196: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 198: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 199: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 200: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } + }, + 201: { + hp: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } + }, + 202: { + hp: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } + }, + 205: { + hp: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; } + }, + 206: { + hp: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; } + }, + 209: { + rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } + }, + 210: { + rcv: function(p) { return p.unit.type == "INT" ? 2 : 1; } + }, + 211: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.2 : 1; } + }, + 212: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 215: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 217: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 3.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 220: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } + }, + 221: { + atk: function(p) { return p.unit.type == "INT" ? 2.5 : 1; } + }, + 222: { + atk: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; } + }, + 223: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 224: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect"]) ? 2 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 225: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect"]) ? 2.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 226: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 227: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2.5 : 1; }, + }, + 228: { + hp: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 230: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 231: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 232: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 233: { + hp: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 234: { + hp: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 235: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.2 : 1; } + }, + 236: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } + }, + 248: { + atk: function(p) { return p.unit.type == "STR" ? 2.5 : 1; }, + hp: function(p) { return p.unit.type == "STR" ? 0.4 : 1; } + }, + 249: { + atk: function(p) { return p.unit.type == "STR" ? 3 : 1; }, + hp: function(p) { return p.unit.type == "STR" ? 0.4 : 1; } + }, + 250: { + atk: function(p) { return p.unit.type == "PSY" && p.percHP >= 99.0 ? 3 : 1; } + }, + 251: { + atk: function(p) { return p.unit.type == "PSY" && p.percHP >= 99.0 ? 3 : 1; } + }, + 252: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, + hp: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 253: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, + hp: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 254: { + hp: function(p) { return p.unit.type == "INT" ? 2 : 1; }, + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } + }, + 255: { + hp: function(p) { return p.unit.type == "INT" ? 2 : 1; }, + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } + }, + 256: { + atk: function(p) { return p.unit.type == "DEX" ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 2 : 1; } + }, + 257: { + atk: function(p) { return p.unit.type == "DEX" ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 2 : 1; } + }, + 258: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "STR" ? 2 : 1; } + }, + 259: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "STR" ? 2 : 1; } + }, + 260: { + atk: function(p) { return p.percHP <= 30.0 ? 3 : 1; } + }, + 261: { + atk: function(p) { return p.percHP <= 30.0 ? 3 : 1; } + }, + 263: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } + }, + 265: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } + }, + 267: { + atk: function(p) { return 1.5; }, + hp: function(p) { return 1.5; }, + rcv: function(p) { return 1.5; } + }, + 290: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 293: { + hp: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 294: { + hp: function(p) { return p.unit.type == "STR" ? 2 : 1; } + }, + 295: { + hp: function(p) { return p.unit.type == "DEX" ? 2 : 1; } + }, + 296: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } + }, + 297: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } + }, + 298: { + hp: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 299: { + atk: function(p) { return p.unit.type == "DEX" ? 2 : 1; } + }, + 305: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 306: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; }, + hp: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 307: { + atk: function(p) { return p.unit.type == "DEX" ? 2.5 : 1; } + }, + 308: { + atk: function(p) { return p.unit.type == "DEX" ? 2.5 : 1; } + }, + 311: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Below Good", "Below Good", "Below Good"]) ? 3.5 : 1; + }, + hitModifiers: ["Below Good", "Below Good", "Below Good", "Perfect", "Perfect", "Perfect"] + }, + 312: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Below Good", "Below Good", "Below Good"]) ? 3.5 : 1; + }, + hitModifiers: ["Below Good", "Below Good", "Below Good", "Perfect", "Perfect", "Perfect"] + }, + 313: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 314: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 315: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } + }, + 316: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } + }, + 319: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 320: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 321: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 322: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 323: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 324: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 328: { + rcv: function(p) { return p.percHP <= 30.0 ? 5 : 1; } + }, + 329: { + rcv: function(p) { return p.percHP <= 30.0 ? 5 : 1; } + }, + 332: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.2 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") ? 1.2 : 1; }, + rcv: function(p) { return p.unit.class.has("Striker") ? 1.2 : 1; } + }, + 333: { + atk: function(p) { return p.unit.type == "INT" || p.unit.type == "PSY" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "INT" || p.unit.type == "PSY" ? 1.5 : 1; } + }, + 336: { + atk: function(p) { return p.percHP <= 50.0 ? 1 : (p.unit.type == "PSY" ? 2 : 0.8); } + }, + 337: { + atk: function(p) { return p.percHP <= 50.0 ? 1 : (p.unit.type == "PSY" ? 2.5 : 0.8); } + }, + 340: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 341: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 352: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } + }, + 353: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2.5 : 1; } + }, + 356: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 357: { + atk: function(p) { return p.unit.class.has("Striker") ? 2.5 : 1; } + }, + 358: { + atk: function(p) { return p.unit.type == "DEX" && p.percHP >= 99.0 ? 2.5 : 1; } + }, + 359: { + atk: function(p) { return p.unit.type == "DEX" && p.percHP >= 99.0 ? 3 : 1; } + }, + 360: { + atk: function(p) { return p.unit.type == "INT" && p.percHP <= 30.0 ? 3 : 1; } + }, + 361: { + atk: function(p) { return p.unit.type == "INT" && p.percHP <= 30.0 ? 3 : 1; } + }, + 362: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 363: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 364: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 365: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 366: { + chainModifier: function(p) { return 4; } + }, + 367: { + chainModifier: function(p) { return 4; } + }, + 373: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 374: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 375: { + hp: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 376: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } + }, + 377: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 378: { + rcv: function(p) { return 1.5; } + }, + 380: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 383: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } + }, + 384: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } + }, + 385: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } + }, + 386: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } + }, + 387: { + rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 388: { + rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 389: { + damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['DEX', 'INT', 'QCK']); }, + hitAtk: function(p) { + return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ + type: 'DEX', + minModifier: 'Good' + }, { + type: 'INT', + minModifier: 'Good' + }, { + type: 'QCK', + minModifier: 'Good' + }]) ? 2 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 390: { + damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['DEX', 'INT', 'QCK']); }, + hitAtk: function(p) { + return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ + type: 'DEX', + minModifier: 'Good' + }, { + type: 'INT', + minModifier: 'Good' + }, { + type: 'QCK', + minModifier: 'Good' + }]) ? 2.75 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 391: { + rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 392: { + rcv: function(p) { return p.unit.type == "DEX" ? 2 : 1; } + }, + 395: { + atk: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; } + }, + 396: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 397: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition) + .subcontains(["Perfect", "Perfect", "Perfect", "Perfect", "Perfect"]) ? 3 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 398: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition) + .subcontains(["Perfect", "Perfect", "Perfect", "Perfect", "Perfect"]) ? 4 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 399: { + hp: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 400: { + hp: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 401: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 402: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 403: { + rcv: function(p) { return p.percHP <= 30.0 ? 3 : 1; } + }, + 404: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 405: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } + }, + 408: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 409: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } + }, + 410: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.5 : 1; } + }, + 411: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, + hp: function(p) { return p.unit.type == "STR" ? 2 : 1; } + }, + 412: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, + hp: function(p) { return p.unit.type == "STR" ? 2 : 1; } + }, + 413: { + atk: function(p) { return p.unit.type == "INT" && p.percHP >= 99.0 ? 2.5 : 1; } + }, + 414: { + atk: function(p) { return p.unit.type == "INT" && p.percHP >= 99.0 ? 3 : 1; } + }, + 415: { + atk: function(p) { + return (p.unit.type == "QCK" || p.unit.type == "PSY") && p.percHP >= 70.0 ? 2.75 : 1; + }, + rcv: function(p) { + return (p.unit.type == "QCK" || p.unit.type == "PSY") && p.percHP >= 70.0 ? 1.5 : 1; + } + }, + 416: { + atk: function(p) { + return (p.unit.type == "QCK" || p.unit.type == "PSY") && p.percHP >= 70.0 ? 2.75 : 1; + }, + rcv: function(p) { + return (p.unit.type == "QCK" || p.unit.type == "PSY") && p.percHP >= 70.0 ? 1.5 : 1; + } + }, + 417: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 418: { + hp: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; }, + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 419: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 420: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 421: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 422: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } + }, + 424: { + atk: function(p) { return p.percHP >= 70.0 ? 1.5 : 1; } + }, + 425: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 426: { + hp: function(p) { return p.unit.type == "STR" ? 2 : 1; } + }, + 427: { + hp: function(p) { return p.unit.type == "DEX" ? 2 : 1; } + }, + 428: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 430: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 431: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 433: { + damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['QCK', 'STR', 'DEX']); }, + hitAtk: function(p) { + return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ + type: 'QCK', + minModifier: 'Good' + }, { + type: 'STR', + minModifier: 'Good' + }, { + type: 'DEX', + minModifier: 'Good' + }]) ? 2 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 434: { + damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['PSY', 'INT', 'INT']); }, + hitAtk: function(p) { + return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ + type: 'PSY', + minModifier: 'Good' + }, { + type: 'INT', + minModifier: 'Good' + }, { + type: 'INT', + minModifier: 'Good' + }]) ? 2 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 435: { + damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['INT', 'PSY', 'QCK']); }, + hitAtk: function(p) { + return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ + type: 'INT', + minModifier: 'Good' + }, { + type: 'PSY', + minModifier: 'Good' + }, { + type: 'QCK', + minModifier: 'Good' + }]) ? 2 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 437: { + rcv: function(p) { return p.unit.type == "DEX" && p.percHP <= 30.0 ? 3 : 1; } + }, + 438: { + rcv: function(p) { return p.unit.type == "DEX" && p.percHP <= 30.0 ? 5 : 1; } + }, + 444: { + atk: function(p) { + return p.percHP >= 50.0 && (p.unit.class.has("Booster") || p.unit.class.has("Evolver")) ? 2 : 1; + } + }, + 445: { + atk: function(p) { + return p.percHP >= 50.0 && (p.unit.class.has("Booster") || p.unit.class.has("Evolver")) ? 2.5 : 1; + } + }, + 446: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, + hp: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 447: { + atk: function(p) { return p.unit.type == "STR" ? 2.5 : 1; }, + hp: function(p) { return p.unit.type == "STR" ? 2.25 : 1; } + }, + 448: { + atk: function(p) { return p.unit.type == "QCK" && p.percHP >= 99.0 ? 3 : 1; } + }, + 449: { + atk: function(p) { return p.unit.type == "QCK" && p.percHP >= 99.0 ? 3 : 1; } + }, + 450: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } + }, + 451: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } + }, + 452: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 453: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 454: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } + }, + 455: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } + }, + 456: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 457: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 458: { + atk: function(p) { return p.unit.cost <= 20 ? 3 : 1; } + }, + 459: { + atk: function(p) { return p.unit.number == 458 || p.unit.cost <= 20 ? 3 : 1; } + }, + 461: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } + }, + 462: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } + }, + 463: { + hp: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 464: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 465: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Below Good", "Below Good", "Below Good", "Below Good"]) ? 3 : 1; + }, + hitModifiers: ["Below Good", "Below Good", "Below Good", "Below Good", "Perfect", "Perfect"] + }, + 466: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 467: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 470: { + rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 471: { + atk: function(p) { return p.unit.type == "INT" ? 1.2 : 1; }, + hp: function(p) { return p.unit.type == "INT" ? 1.2 : 1; } + }, + 482: { + hp: function(p) { return p.unit.class.has("Striker") ? 1.2 : 1; } + }, + 483: { + atk: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; } + }, + 485: { + hp: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; } + }, + 486: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.2 : 1; } + }, + 490: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.2 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") ? 1.2 : 1; } + }, + 491: { + rcv: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 492: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 496: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 497: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 498: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 499: { + rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 500: { + rcv: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } + }, + 501: { + atk: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; }, + hp: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; } + }, + 502: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 503: { + hp: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } + }, + 504: { + hp: function(p) { return p.unit.type == "INT" ? 2 : 1; } + }, + 507: { + atk: function(p) { return p.unit.type == "STR" ? 1.2 : 1; }, + hp: function(p) { return p.unit.type == "STR" ? 1.2 : 1; } + }, + 508: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 509: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 510: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 511: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 513: { + atk: function(p) { return p.unit.type == "PSY" && p.percHP >= 50.0 ? 1.5 : 1; } + }, + 514: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } + }, + 515: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 516: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 517: { + hp: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 518: { + hp: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 519: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } + }, + 520: { + atk: function(p) { return p.unit.type == "STR" ? 2.5 : 1; } + }, + 523: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 524: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; }, + rcv: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 525: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 526: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 527: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 528: { + atk: function(p) { return p.unit.type == "DEX" ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 2 : 1; } + }, + 529: { + atk: function(p) { return p.unit.type == "PSY" ? 2 + 0.75 * p.percHP / 100 : 1; } + }, + 530: { + atk: function(p) { return p.unit.type == "PSY" ? 2 + 0.75 * p.percHP / 100 : 1; } + }, + 533: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 534: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 535: { + rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 536: { + rcv: function(p) { return p.unit.type == "DEX" ? 2 : 1; } + }, + 537: { + chainModifier: function(p) { return 2; } + }, + 538: { + chainModifier: function(p) { return 2; } + }, + 541: { + atk: function(p) { return p.unit.type == "STR" && p.percHP <= 50.0 ? 2.5 : 1; } + }, + 542: { + hp: function(p) { return 1.5; } + }, + 543: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") ? 0 : 1; } + }, + 544: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2.25 : 1; }, + hp: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") ? 0 : 1; } + }, + 545: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 546: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 548: { + atk: function(p) { return 1.2; } + }, + 549: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 550: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 553: { + atk: function(p) { return p.unit.type == "DEX" && p.percHP <= 30.0 ? 2.75 : 1; } + }, + 554: { + atk: function(p) { return p.unit.type == "DEX" && p.percHP <= 30.0 ? 3 : 1; } + }, + 555: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } + }, + 556: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 557: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } + }, + 558: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "INT" ? 2 : 1; } + }, + 559: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } + }, + 560: { + atk: function(p) { return p.unit.type == "STR" ? 2.25 : 1; } + }, + 561: { + atk: function(p) { return !p.unit.class.has("Shooter") ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 3 : 2); }, + hp: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 562: { + atk: function(p) { return !p.unit.class.has("Shooter") ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 3 : 2); }, + hp: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 568: { + atk: function(p) { return 1.25; }, + hp: function(p) { return 1.25; }, + rcv: function(p) { return 1.25; } + }, + 569: { + atk: function(p) { return 1.5; }, + hp: function(p) { return 1.5; }, + rcv: function(p) { return 1.5; } + }, + 570: { + atk: function(p) { + return p.unit.class.has("Fighter") && p.unit.type == "STR" ? 2.25 : + p.unit.type == "STR" || p.unit.class.has("Fighter") ? 1.5 : + 1; + } + }, + 571: { + atk: function(p) { + return p.unit.class.has("Fighter") && p.unit.type == "STR" ? 2.25 : + p.unit.type == "STR" || p.unit.class.has("Fighter") ? 1.5 : + 1; + } + }, + 572: { + atk: function(p) { return p.unit.class.has("Fighter") && p.percHP >= 99.0 ? 2.5 : 1; } + }, + 573: { + rcv: function(p) { return 1.2; } + }, + 574: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 575: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 576: { + atk: function(p) { return 1.5; }, + rcv: function(p) { return 1.2; } + }, + 577: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 4 : 1; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 578: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 4 : 1; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 579: { + atk: function(p) { return (p.unit.type == "QCK" || p.unit.type == "DEX") ? 1.5 : 1; } + }, + 580: { + atk: function(p) { return (p.unit.type == "QCK" || p.unit.type == "DEX") ? 2 : 1; } + }, + 581: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 582: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 583: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 584: { + atk: function(p) { return 0.1; }, + hp: function(p) { return 0.1; }, + rcv: function(p) { return 0.1; } + }, + 585: { + rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 586: { + hp: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 589: { + atk: function(p) { return 1.5; }, + hp: function(p) { return 0.2; }, + rcv: function(p) { return 0.2; } + }, + 590: { + atk: function(p) { return 1.5; }, + hp: function(p) { return 0.2; }, + rcv: function(p) { return 0.2; } + }, + 596: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 597: { + atk: function(p) { return p.unit.type == "STR" ? 1.75 : 1; } + }, + 598: { + atk: function(p) { return p.unit.stars < 3 ? 2.5 : 1; } + }, + 599: { + atk: function(p) { return p.unit.stars < 3 ? 3 : 1; } + }, + 600: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 601: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 602: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 603: { + atk: function(p) { return p.unit.type == "QCK" ? 2.25 : 1; } + }, + 604: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } + }, + 605: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } + }, + 606: { + atk: function(p) { return p.percHP >= 50.0 && p.unit.class.has("Fighter") ? 2 : 1; } + }, + 607: { + atk: function(p) { return p.percHP >= 50.0 && p.unit.class.has("Fighter") ? 2.5 : 1; } + }, + 612: { + hp: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 613: { + hp: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 614: { + atk: function(p) { return p.unit.cost <= 20 && p.percHP <= 30.0 ? 2.25 : 1; } + }, + 629: { + atk: function(p) { return p.unit.stars <= 3 ? 2 : 1; } + }, + 630: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 631: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 632: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } + }, + 633: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } + }, + 634: { + atk: function(p) { return p.unit.type == "QCK" || p.unit.type == "PSY" ? 1.25 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" || p.unit.type == "PSY" ? 1.25 : 1; } + }, + 635: { + atk: function(p) { return p.unit.type == "QCK" || p.unit.type == "PSY" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" || p.unit.type == "PSY" ? 1.5 : 1; } + }, + 636: { + atk: function(p) { return p.unit.cost <= 2 ? 3 : 1; } + }, + 637: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 638: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 639: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 640: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } + }, + 641: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.25 : 1; } + }, + 642: { + atk: function(p) { return p.unit.type == "PSY" && p.percHP <= 30.0 ? 2.5 : 1; } + }, + 643: { + atk: function(p) { return p.unit.type == "PSY" && p.percHP <= 30.0 ? 3 : 1; } + }, + 644: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } + }, + 645: { + atk: function(p) { return p.unit.type == "INT" ? 2.5 : 1; } + }, + 646: { + atk: function(p) { return p.unit.class.has("Shooter") && p.percHP <= 30.0 ? 2.5 : 1; } + }, + 647: { + atk: function(p) { return p.unit.class.has("Shooter") && p.percHP <= 30.0 ? 2.75 : 1; } + }, + 648: { + atk: function(p) { + return (p.unit.type == "QCK" || p.unit.type == "PSY") && p.percHP >= 70.0 ? 2.75 : 1; + } + }, + 649: { + atk: function(p) { + return (p.unit.type == "QCK" || p.unit.type == "PSY") && p.percHP >= 70.0 ? 2.75 : 1; + } + }, + 650: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } + }, + 651: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } + }, + 652: { + atk: function(p) { return p.unit.type != "DEX" ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 2 : 1); } + }, + 653: { + atk: function(p) { return p.unit.type != "DEX" ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 2.25 : 1); } + }, + 654: { + atk: function(p) { return p.unit.type != "DEX" ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 2.75 : 1); } + }, + 655: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 656: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } + }, + 657: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } + }, + 658: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 659: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 660: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } + }, + 661: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } + }, + 662: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 665: { + atk: function(p) { return 1.2; }, + hp: function(p) { return 0.2; }, + rcv: function(p) { return 0.2; } + }, + 666: { + atk: function(p) { return 1.75; }, + hp: function(p) { return 0.2; }, + rcv: function(p) { return 0.2; } + }, + 667: { + atk: function(p) { return 1.75; } + }, + 668: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 + 0.75 * p.percHP / 100 : 1; }, + hp: function(p) { return 1.2; }, + rcv: function(p) { return 1.2; } + }, + 669: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 + 0.75 * p.percHP / 100 : 1; }, + hp: function(p) { return 1.2; }, + rcv: function(p) { return 1.2; } + }, + 670: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } + }, + 671: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.25 : 1; }, + rcv: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } + }, + 672: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } + }, + 673: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } + }, + 674: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 : 1; } + }, + 675: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2.5 : 1; } + }, + 676: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 677: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 678: { + atk: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; } + }, + 679: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 681: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 683: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } + }, + 684: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 686: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 687: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; } + }, + 688: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 : 1; } + }, + 689: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.2 : 1; }, + rcv: function(p) { return p.unit.class.has("Slasher") ? 1.2 : 1; } + }, + 690: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 696: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.75 : 1; } + }, + 697: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.75 : 1; } + }, + 698: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.75 : 1; } + }, + 699: { + atkStatic: function(p) { return p.unit.class.has("Shooter") ? 500 : 0; } + }, + 700: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.75 : 1; } + }, + 701: { + hp: function(p) { return p.unit.type == "PSY" ? 2.25 : 1; } + }, + 702: { + hp: function(p) { return p.unit.type == "INT" ? 2.25 : 1; } + }, + 705: { + atk: function(p) { + return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 1.25 : 1; + }, + hp: function(p) { + return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 1.25 : 1; + } + }, + 706: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 707: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 708: { + atk: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; } + }, + 709: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 710: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 711: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } + }, + 712: { + atk: function(p) { return p.unit.class.has("Striker") && p.percHP >= 50 ? 2 : 1; } + }, + 713: { + atk: function(p) { return p.unit.class.has("Striker") && p.percHP >= 50 ? 2.5 : 1; } + }, + 715: { + rcv: function(p) { return p.percHP <= 30 ? 3 : 1; } + }, + 716: { + rcv: function(p) { return p.percHP <= 30 ? 5 : 1; } + }, + 717: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 2.75, [ "Slasher" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has('Slasher')) return 1; + var prev = p.modifiers.slice(p.chainPosition - 1, p.chainPosition)[0]; + return p.chainPosition === 0 ? 2 : (prev == 'Good' ? 2.25 : (prev == 'Great' ? 2.5 : (prev == 'Perfect' ? 2.75 : 2))); + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 718: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 2.75, [ "Slasher" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has('Slasher')) return 1; + var prev = p.modifiers.slice(p.chainPosition - 1, p.chainPosition)[0]; + return p.chainPosition === 0 ? 2 : (prev == 'Good' ? 2.25 : (prev == 'Great' ? 2.5 : (prev == 'Perfect' ? 2.75 : 2))); + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 719: { + atk: function(p) { + return p.unit.class.has("Cerebral") ? 1.5 + 1.75 * ((100 - p.percHP) / 100) : 1; + } + }, + 720: { + atk: function(p) { + return p.unit.class.has("Cerebral") ? 1.5 + 1.75 * ((100 - p.percHP) / 100) : 1; + } + }, + 721: { + atk: function(p) { return p.unit.class.has("Fighter") && p.percHP >= 99.0 ? 1.5 : 1; } + }, + 722: { + atk: function(p) { return p.unit.class.has("Fighter") && p.percHP >= 99.0 ? 2 : 1; } + }, + 723: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 724: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.75 : 1; } + }, + 727: { + atk: function(p) { + return p.unit.class.has("Free Spirit") || p.unit.class.has("Fighter") ? 1.75 : 1; + } + }, + 728: { + atk: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; } + }, + 730: { + atk: function(p) { return p.unit.type == "INT" ? 1.2 : 1; }, + hp: function(p) { return p.unit.type == "INT" ? 1.2 : 1; } + }, + 731: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } + }, + 732: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 733: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 734: { + atk: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.2 : 1; } + }, + 735: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 736: { + atk: function(p) { return p.unit.class.has("Slasher") && p.percHP >= 50.0 ? 2.5 : 1; } + }, + 737: { + atk: function(p) { return p.unit.class.has("Fighter") && p.percHP <= 30.0 ? 2.75 : 1; } + }, + 738: { + atk: function(p) { return p.unit.cost >= 21 ? 2 : 1; } + }, + 739: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 : 1; } + }, + 742: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.2 : 1; }, + rcv: function(p) { return p.unit.class.has("Free Spirit") ? 1.2 : 1; } + }, + 743: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; } + }, + 744: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 : 1; } + }, + 745: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2.5 : 1; } + }, + 747: { + atk: function(p) { return !p.unit.class.has("Powerhouse") ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 3 : 2.5); }, + rcv: function(p) { return 0; } + }, + 748: { + atk: function(p) { return !p.unit.class.has("Powerhouse") ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 3 : 2.5); }, + rcv: function(p) { return 0; } + }, + 749: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 750: { + atk: function(p) { return p.unit.type == "DEX" ? 2 : 1; } + }, + 751: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; } + }, + 752: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2.25 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; } + }, + 753: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2 : 1; } + }, + 754: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2.5 : 1; } + }, + 755: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } + }, + 756: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } + }, + 757: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 758: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 759: { + atk: function(p) { return p.unit.type == "STR" && p.percHP <= 30.0 ? 2.5 : 1; } + }, + 760: { + atk: function(p) { return p.unit.type == "STR" && p.percHP <= 30.0 ? 3 : 1; } + }, + 761: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } + }, + 762: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 763: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } + }, + 764: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 766: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 767: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 768: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 769: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } + }, + 770: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } + }, + 771: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2.5 : 1; } + }, + 772: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 774: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 : 1; } + }, + 775: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; } + }, + 776: { + atk: function(p) { return p.unit.type == "PSY" ? 1.25 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.25 : 1; } + }, + 777: { + atk: function(p) { return p.unit.type == "PSY" ? 1.75 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.75 : 1; } + }, + 780: { + atk: function(p) { return p.percHP <= 30.0 ? 2 : 1; } + }, + 781: { + atk: function(p) { return p.percHP <= 30.0 ? 2.5 : 1; } + }, + 782: { + rcv: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 783: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; }, + rcv: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 789: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 791: { + atk: function(p) { return /STR|DEX|QCK/.test(p.unit.type) ? 1.25 : 1; }, + hp: function(p) { return /STR|DEX|QCK/.test(p.unit.type) ? 1.25 : 1; }, + rcv: function(p) { return /STR|DEX|QCK/.test(p.unit.type) ? 1.25 : 1; } + }, + 793: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; } + }, + 794: { + atk: function(p) { + return p.unit.class.has("Powerhouse") ? Math.max(1.0, 3.0 - 0.1 * p.turnCounter) : 1; + } + }, + 795: { + atk: function(p) { + return p.unit.class.has("Powerhouse") ? Math.max(1.0, 3.5 - 0.1 * p.turnCounter) : 1; + } + }, + 796: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2 : 1; } + }, + 797: { + atk: function(p) { return p.unit.class.has("Cerebral") || p.unit.class.has("Powerhouse") ? 2 : 1; } + }, + 798: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 801: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 802: { + atk: function(p) { return p.unit.type == "PSY" ? 2.5 : 1; } + }, + 803: { + atk: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; } + }, + 804: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 805: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 806: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 807: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; } + }, + 808: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; } + }, + 809: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 810: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2 : 1; }, + rcv: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 815: { + damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['STR', 'INT', 'DEX']); }, + hitAtk: function(p) { + return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ + type: 'STR', + minModifier: 'Good' + }, { + type: 'INT', + minModifier: 'Good' + }, { + type: 'DEX', + minModifier: 'Good' + }]) ? 2.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 816: { + damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['STR', 'INT', 'DEX']); }, + hitAtk: function(p) { + return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ + type: 'STR', + minModifier: 'Good' + }, { + type: 'INT', + minModifier: 'Good' + }, { + type: 'DEX', + minModifier: 'Good' + }]) ? 2.75 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 825: { + atk: function(p) { return p.unit.type == 'STR' ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == 'STR' ? 1.5 : 1; } + }, + 826: { + atk: function(p) { return p.unit.type == 'DEX' ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == 'DEX' ? 1.5 : 1; } + }, + 827: { + atk: function(p) { return p.unit.type == 'QCK' ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == 'QCK' ? 1.5 : 1; } + }, + 830: { + atk: function(p) { + return p.unit.class.has("Striker") || p.unit.class.has("Cerebral") ? 1.75 : 1; + } + }, + 831: { + atk: function(p) { + return p.unit.class.has("Striker") || p.unit.class.has("Cerebral") ? 2 : 1; + } + }, + 832: { + atk: function(p) { + return p.unit.class.has("Free Spirit") ? 1 + 1.5 * ((100 - p.percHP) / 100) : 1; + } + }, + 833: { + atk: function(p) { + return p.unit.class.has("Free Spirit") ? 1 + 1.75 * ((100 - p.percHP) / 100) : 1; + } + }, + 834: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 835: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Cerebral") ? 2 : 1; } + }, + 836: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Cerebral") ? 2 : 1; } + }, + 837: { + atk: function(p) { return p.unit.class.has("Driven") ? 2 : 1; } + }, + 838: { + atk: function(p) { return p.unit.class.has("Driven") ? 2.5 : 1; } + }, + 839: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 840: { + atk: function(p) { return p.unit.class.has("Striker") ? 2.5 : 1; } + }, + 843: { + atk: function(p) { + return p.unit.class.has("Shooter") || p.unit.class.has("Slasher") || p.unit.class.has("Striker") ? 1.5 : 1; + } + }, + 844: { + atk: function(p) { + return p.unit.class.has("Shooter") || p.unit.class.has("Slasher") || p.unit.class.has("Striker") ? 2 : 1; + } + }, + 845: { + hit: function(n) { + return n > 22 ? 2.5 : + n > 11 ? 1.5 : 1; + } + }, + 846: { + hit: function(n) { + return n > 40 ? 3.5 : + n > 30 ? 2.75 : + n > 22 ? 2.5 : + n > 11 ? 1.5 : 1; + } + }, + 847: { + atk: function(p) { return p.percHP <= 30.0 ? 1.5 : 1; } + }, + 848: { + atk: function(p) { return p.percHP <= 30.0 ? 1.5 : 1; } + }, + 849: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.75 : 1; } + }, + 850: { + atk: function(p) { + return p.unit.class.has("Striker") || p.unit.class.has("Cerebral") ? 1.5 : 1; + } + }, + 851: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; } + }, + 852: { + atk: function(p) { return p.unit.class.has("Driven") ? 2 : 1; } + }, + 854: { + atk: function(p) { return p.unit.type == 'DEX' ? 1.5 : 1; } + }, + 855: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 856: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2.5 : 1; } + }, + 857: { + atk: function(p) { return p.unit.type == 'PSY' ? 2 : 1; } + }, + 858: { + atk: function(p) { return p.unit.type == 'PSY' ? 2 : 1; }, + rcv: function(p) { return p.unit.type == 'PSY' ? 2 : 1; } + }, + 859: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; } + }, + 860: { + atk: function(p) { return p.unit.class.has("Driven") ? 2 : 1; } + }, + 862: { + atk: function(p) { return p.unit.type == 'QCK' ? 2 : 1; } + }, + 863: { + atk: function(p) { return p.unit.type == 'QCK' ? 1.75 : 1; } + }, + 864: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 : 1; } + }, + 865: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Free Spirit") ? 2 : 1; } + }, + 866: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2 : 1; } + }, + 867: { + hit: function(n) { return n > 11 ? 1.5 : 1; } + }, + 868: { + atk: function(p) { return 1.2; } + }, + 869: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3, [ "Driven" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Driven")) return 1; + return p.modifiers.slice(0, p.chainPosition).count("Perfect") == p.chainPosition ? 3 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 870: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3, [ "Driven" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Driven")) return 1; + return p.modifiers.slice(0, p.chainPosition).count("Perfect") == p.chainPosition ? 3 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 871: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 872: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 873: { + atk: function(p) { return p.unit.class.has("Fighter") && p.percHP <= 30.0 ? 2.5 : 1; } + }, + 874: { + atk: function(p) { return p.unit.class.has("Fighter") && p.percHP <= 30.0 ? 3 : 1; } + }, + 875: { + atk: function(p) { + return p.unit.class.has("Cerebral") || p.unit.class.has("Driven") ? 2 : 1; + } + }, + 876: { + atk: function(p) { + return p.unit.class.has("Cerebral") || p.unit.class.has("Driven") ? 2.25 : 1; + } + }, + 878: { + atk: function(p) { return 1.5; } + }, + 879: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.75 : 1; } + }, + 880: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } + }, + 881: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 2, [ "Shooter", "Free Spirit" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Shooter") && !p.unit.class.has("Free Spirit")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 2 : 1; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 882: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3, [ "Shooter", "Free Spirit" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Shooter") && !p.unit.class.has("Free Spirit")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 3 : 1; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 883: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.25 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.25 : 1; } + }, + 884: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 885: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } + }, + 886: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 887: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; } + }, + 889: { + atk: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; } + }, + 890: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 891: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 892: { + chainModifier: function(p) { return 2; } + }, + 893: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3, [ "Powerhouse" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Powerhouse")) return 1; + return p.modifiers.slice(0, p.chainPosition) + .subcontains(["Perfect", "Perfect", "Perfect"]) ? 3 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 894: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3, [ "Driven" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Driven")) return 1; + return p.modifiers.slice(0, p.chainPosition) + .subcontains(["Good", "Great", "Perfect"]) ? 3 : 1; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 895: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 896: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 897: { + atk: function(p) { + return p.unit.class.has("Cerebral") || p.unit.class.has("Driven") ? 2 : 1; + } + }, + 898: { + atk: function(p) { + return p.unit.class.has("Striker") || p.unit.class.has("Cerebral") ? 1.5 : 1; + }, + hp: function(p) { + return p.unit.class.has("Striker") || p.unit.class.has("Cerebral") ? 1.5 : 1; + } + }, + 899: { + atk: function(p) { + return p.unit.class.has("Fighter") || p.unit.class.has("Free Spirit") ? 1.75 : 1; + }, + hp: function(p) { + return p.unit.class.has("Fighter") || p.unit.class.has("Free Spirit") ? 1.25 : 1; + } + }, + 900: { + atk: function(p) { return p.unit.class.has("Shooter") && p.percHP >= 99.0 ? 2 : 1; } + }, + 901: { + atk: function(p) { return p.unit.class.has("Shooter") && p.percHP >= 99.0 ? 2.75 : 1; } + }, + 902: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.25 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.25 : 1; } + }, + 903: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.25 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.25 : 1; } + }, + 905: { + atk: function(p) { return p.unit.class.has("Slasher") && p.percHP <= 30 ? 2.5 : 1; } + }, + 906: { + atk: function(p) { return p.unit.class.has("Slasher") && p.percHP <= 30 ? 2.75 : 1; } + }, + 907: { + atk: function(p) { return p.unit.class.has("Cerebral") && p.percHP <= 30 ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") && p.percHP <= 30 ? 1.5 : 1; } + }, + 908: { + atk: function(p) { return p.unit.class.has("Cerebral") && p.percHP <= 30 ? 2.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") && p.percHP <= 30 ? 1.75 : 1; } + }, + 909: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 910: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 911: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 912: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2.25 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 913: { + atk: function(p) { return p.unit.type != "QCK" ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 3 : 1); } + }, + 914: { + atk: function(p) { return p.unit.type != "QCK" ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 3 : 1.2); } + }, + 915: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.2 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.2 : 1; } + }, + 916: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.75 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.75 : 1; } + }, + 917: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 918: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.75 : 1; } + }, + 921: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.2 : 1; }, + rcv: function(p) { return p.unit.class.has("Free Spirit") ? 1.2 : 1; } + }, + 922: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.75 : 1; }, + rcv: function(p) { return p.unit.class.has("Free Spirit") ? 1.75 : 1; } + }, + 923: { + atk: function(p) { + if(p.percHP<30){ + return p.unit.class.has("Driven") ? 2.5 : 1; + } else { + return p.unit.class.has("Driven") ? 2 : 1; + } + } + }, + 924: { + atk: function(p) { + if(p.percHP<30){ + return p.unit.class.has("Driven") ? 2.75 : 1; + } else { + return p.unit.class.has("Driven") ? 2 : 1; + } + } + }, + 925: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2 : 1; } + }, + 926: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2.5 : 1; } + }, + 927: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; } + }, + 928: { + atk: function(p) { + if(p.percHP<30){ + return p.unit.class.has("Driven") ? 1.75 : 1; + } else { + return p.unit.class.has("Striker") ? 1.75 : 1; + } + } + }, + 929: { + atk: function(p) { + if(p.percHP<30){ + return p.unit.class.has("Driven") ? 2.25 : 1; + } else { + return p.unit.class.has("Striker") ? 2.25 : 1; + } + } + }, + 930: { + chainModifier: function(p) { return 2; } + }, + 932: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 933: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2.25 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 934: { + atk: function(p) { + if(p.percHP<30 || p.percHP>70){ + return p.unit.class.has("Fighter") ? 2.75 : 1; + } else { + return p.unit.class.has("Fighter") ? 2 : 1; + } + }, + hp: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } + }, + 935: { + atk: function(p) { + if(p.percHP<30 || p.percHP>70){ + return p.unit.class.has("Fighter") ? 2.75 : 1; + } else { + return p.unit.class.has("Fighter") ? 2 : 1; + } + }, + hp: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } + }, + 936: { + chainModifier: function(p) { return 3; } + }, + 937: { + chainModifier: function(p) { return 3.5; }, + hp: function(p) { return 1.25; } + }, + 938: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; } + }, + 939: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2 : 1; } + }, + 940: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 941: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "DEX" ? 2.25 : 1; } + }, + 942: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 943: { + atk: function(p) { return p.unit.type == "STR" ? 2.25 : 1; }, + hp: function(p) { return p.unit.type == "STR" ? 1.75 : 1; } + }, + 944: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.2 : 1; }, + rcv: function(p) { return p.unit.class.has("Driven") ? 1.2 : 1; } + }, + 945: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.75 : 1; }, + rcv: function(p) { return p.unit.class.has("Driven") ? 1.75 : 1; } + }, + 946: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.75 : 1; } + }, + 947: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } + }, + 948: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") ? 1.2 : 1; } + }, + 949: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 950: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 2.5, [ "Free Spirit" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Fighter") && !p.unit.class.has("Free Spirit")) return 1; + return p.modifiers.slice(0, p.chainPosition) + .subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 951: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 2.75, [ "Free Spirit" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Fighter") && !p.unit.class.has("Free Spirit")) return 1; + return p.modifiers.slice(0, p.chainPosition) + .subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.75 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 952: { + atk: function(p) { + return p.unit.class.has("Shooter") || p.unit.class.has("Striker") ? 1.2 : 1; + }, + hp: function(p) { + return p.unit.class.has("Shooter") || p.unit.class.has("Striker") ? 1.2 : 1; + } + }, + 953: { + atk: function(p) { + return p.unit.class.has("Shooter") || p.unit.class.has("Striker") ? 1.5 : 1; + }, + hp: function(p) { + return p.unit.class.has("Shooter") || p.unit.class.has("Striker") ? 1.5 : 1; + } + }, + 954: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 955: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 956: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } + }, + 963: { + atk: function(p) { + if(p.unit.cost >= 50 && p.unit.cost <= 55) return 2; + return 1; + } + }, + 964: { + atk: function(p) { + if(p.unit.cost >= 50 && p.unit.cost <= 55) return 1.5; + return 1; + }, + hp: function(p) { + if(p.unit.cost >= 50 && p.unit.cost <= 55) return 1.5; + return 1; + }, + rcv: function(p) { + if(p.unit.cost >= 50 && p.unit.cost <= 55) return 1.5; + return 1; + } + }, + 965: { + atk: function(p) { + if(p.unit.cost >= 50 && p.unit.cost <= 55) return 1.5; + return 1; + } + }, + 966: { + atk: function(p) { return p.unit.class.has("Driven") ? 2.25 : 1; } + }, + 967: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2.25 : 1; } + }, + 973: { + atk: function(p) { return p.unit.class.has("Powerhouse") && p.percHP >= 99.0 ? 2 : 1; } + }, + 974: { + atk: function(p) { return p.unit.class.has("Powerhouse") && p.percHP >= 99.0 ? 2.5 : 1; } + }, + 976: { + atk: function(p) { + return p.unit.class.has("Striker") || p.unit.class.has("Driven") ? 2 : 1; + } + }, + 977: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } + }, + 978: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2.25 : 1; }, + hp: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 979: { + atk: function(p) { return p.unit.type == "PSY" || p.unit.type == "DEX" ? 1.75 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" || p.unit.type == "DEX" ? 1.2 : 1; } + }, + 980: { + atk: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" ? 1.75 : 1; }, + rcv: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" ? 1.2 : 1; } + }, + 981: { + atk: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Powerhouse") ? 2 : 1; }, + rcv: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Powerhouse") ? 0.1 : 1; } + }, + 982: { + atk: function(p) {return p.unit.class.has("Slasher") ? 2 : 1} + }, + 983: { + atk: function(p) {return p.unit.class.has("Slasher") ? 2.25 : 1} + }, + 984: { + atk: function(p) {return p.unit.class.has("Striker") ? 2.25 : 1} + }, + 989: { + atk: function(p) { return p.unit.cost < 30 && p.unit.cost >20 ? 2.5 : 1; }, + hp: function(p) { return 0.1 ; } + }, + 990: { + atk: function(p) { return p.unit.class.has("Free Spirit") && p.percHP >= 99.0 ? 2.5 : 1; } + }, + 991: { + atk: function(p) { return p.unit.class.has("Free Spirit") && p.percHP >= 99.0 ? 2.75 : 1; } + }, + 992: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1 ; } + }, + 993: { + atk: function(p) { return p.unit.type == "QCK" ? 2.5 : 1 ; } + }, + 996: { + atk: function(p) {return p.unit.class.has("Powerhouse") ? 2 : 1; } + }, + 997: { + atk: function(p) {return p.unit.class.has("Powerhouse") ? 2.25 : 1; } + }, + 998: { + atk: function(p) {return p.unit.class.has("Driven") ? 2 : 1; } + }, + 999: { + atk: function(p) {return p.unit.class.has("Driven") ? 2.25 : 1; } + }, + 1000: { + atk: function(p) { return 1 + p.percHP / 100; } + }, + 1001: { + atk: function(p) { return 1 + p.percHP / 100; } + }, + 1002: { + atk: function(p) {return p.unit.class.has("Fighter") ? 1.5 : 1; } + }, + 1003: { + atk: function(p) {return p.unit.class.has("Fighter") ? 2 : 1; } + }, + 1004: { + rcv: function(p) { return 1.5; } + }, + 1005: { + atk: function(p) {return p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 1006: { + atk: function(p) {return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + hp: function(p) {return p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 1007: { + atk: function(p) { return p.unit.class.has("Free Spirit") || p.unit.class.has("Cerebral") ? 1.5 : 1; } + }, + 1008: { + atk: function(p) { return p.unit.class.has("Free Spirit") || p.unit.class.has("Cerebral") ? 2 : 1; } + }, + 1009: { + atk: function(p) { + return p.unit.class.has("Fighter") && p.unit.type == "STR" ? 2.25 : + p.unit.type == "STR" || p.unit.class.has("Fighter") ? 1.5 : + 1; + } + }, + 1010:{ + atk: function(p) {return p.unit.class.has("Driven") ? 1.5 : 1; } + }, + 1011:{ + atk: function(p) { + if (p.unit.class.has("Driven") && p.unit.class.has("Powerhouse")){ + return 2.625; + } else if (p.unit.class.has("Driven")){ + return 1.75; + } else if (p.unit.class.has("Powerhouse")){ + return 1.5; + } return 1; + } + }, + 1014:{ + atk: function(p) {return p.unit.class.has("Powerhouse") ? 2 : 1; } + }, + 1015: { + atk: function(p) { return p.unit.type == "INT" ? (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 2.75 : 1) : 1; }, + }, + 1016: { + atk: function(p) { return p.unit.type == "INT" ? (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 3 : 1.5) : 1; }, + }, + 1017: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 1018: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 1020: { + atk: function(p) { return p.unit.class.has("Shooter") || p.unit.class.has("Cerebral") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") || p.unit.class.has("Cerebral") ? 1.5 : 1; } + }, + 1021: { + atk: function(p) { return p.unit.class.has("Shooter") || p.unit.class.has("Cerebral") ? 1.75 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") || p.unit.class.has("Cerebral") ? 1.75 : 1; } + }, + 1022: { + atk: function(p) { return 2; } + }, + 1023: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2.25 : 1; } + }, + 1024: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2 : 1; } + }, + 1025: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 1026: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } + }, + 1027: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; }, + rcv: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; } + }, + 1028: { + hit: function(n) { return n > 21 ? 2.5 : 1; } + }, + 1029: { + hit: function(n) { + return n > 36 ? 3.5 : + n > 21 ? 2.5 : 1; + } + }, + 1030: { + atk: function(p) { return p.unit.class.has("Powerhouse") && p.percHP >= 99.0 ? 2.5 : 1; } + }, + 1031: { + atk: function(p) { return p.unit.class.has("Powerhouse") && p.percHP >= 99.0 ? 2.75 : 1; } + }, + 1032: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 1033: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Slasher") ? 2.25 : 1; } + }, + 1034: { + atk: function(p) { + return p.unit.class.has("Striker") ? p.classCount.Striker==6 ? 2.75 : p.classCount.Striker==5 ? 2.5 : p.classCount.Striker==4 ? 2 : p.classCount.Striker==3 ? 1.75 : p.classCount.Striker==2 ? 1.5 : p.classCount.Striker==1 ? 1.25 : 1 : 1; } + }, + 1035: { + atk: function(p) { return p.unit.class.has("Striker") ? p.classCount.Striker==6 ? 2.75 : p.classCount.Striker==5 ? 2.5 : p.classCount.Striker==4 ? 2 : p.classCount.Striker==3 ? 1.75 : p.classCount.Striker==2 ? 1.5 : p.classCount.Striker==1 ? 1.25 : 1 : 1; } + }, + 1036: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 2, [ "Free Spirit" ]); }, + hitAtk: function(p) { + return !p.unit.class.has("Free Spirit")? 1 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1037: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 2.5, [ "Free Spirit" ]); }, + hitAtk: function(p) { + return !p.unit.class.has("Free Spirit")? 1 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1038: { + atk: function(p) { return p.unit.type == "DEX" || p.unit.type == "QCK" ? 1.2 : 1; } + }, + 1039: { + atk: function(p) { return p.unit.type == "DEX" || p.unit.type == "QCK" ? 1.5 : 1; } + }, + 1040: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "STR" ? 1.5 : 1; } + }, + 1041: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, + hp: function(p) { return p.unit.type == "STR" ? 2 : 1; } + }, + 1042: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Slasher") ? 2 : 1;}, + rcv: function(p) { return 0; } + }, + 1043: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Slasher") ? (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 2.75 : 2) : 1;}, + rcv: function(p) { return 0; } + }, + 1044: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 4, [ "Slasher", "Free Spirit" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Slasher") && !p.unit.class.has("Free Spirit")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect", "Perfect"]) ? 4 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 3 : 2; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1045: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 4, [ "Slasher", "Free Spirit" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Slasher") && !p.unit.class.has("Free Spirit")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect", "Perfect"]) ? 4 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 3 : 2; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1046: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 2.75, [ "Free Spirit" ]); }, + hitAtk: function(p) { + return !p.unit.class.has("Free Spirit") ? 1 : p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 2.75 : 1; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1047: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3.5, [ "Free Spirit" ]); }, + hitAtk: function(p) { + return !p.unit.class.has("Free Spirit") ? 1 : p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 3.5 : 1; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1048: { + atk: function(p) { return p.unit.type == 'PSY' ? 1.2 : 1; }, + rcv: function(p) { return p.unit.type == 'PSY' ? 1.2 : 1; } + }, + 1049: { + atk: function(p) { return p.unit.type == 'PSY' ? (p.percHP >= 30.0 ? 1.5 : 2.25) : 1; }, + rcv: function(p) { return p.unit.type == 'PSY' ? 1.5 : 1; } + }, + 1050: { + atk: function(p) { return p.unit.type == 'PSY' ? 1.5 : 1; } + }, + 1051: { + atk: function(p) { return p.unit.type == 'PSY' ? 2 : 1; } + }, + 1056:{ + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2 : 1;}, + rcv: function(p) { return 1.25; } + }, + 1058:{ + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2 : 1;}, + hp: function(p) { return 1.25; } + }, + 1059:{ + atk: function(p) { return p.unit.class.has("Shooter") ? 1.2 : 1;}, + rcv: function(p) { return p.unit.class.has("Shooter") ? 1.2 : 1;} + }, + 1060:{ + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1;}, + rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1;} + }, + 1061:{ + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1;} + }, + 1062:{ + atk: function(p) { return p.unit.class.has("Cerebral") ? 2 : 1;} + }, + 1063:{ + atk: function(p) { return p.unit.class.has("Shooter") ? 1.2 : 1;}, + hp: function(p) { return p.unit.class.has("Shooter") ? 1.2 : 1;} + }, + 1064: { + atk: function(p) { return p.unit.type == 'INT' ? 1.2 : 1; }, + hp: function(p) { return p.unit.type == 'INT' ? 1.2 : 1; } + }, + 1065:{ + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1;} + }, + 1066: { + atk: function(p) { return p.unit.type == 'PSY' ? 1.2 : 1; }, + hp: function(p) { return p.unit.type == 'PSY' ? 1.2 : 1; } + }, + 1067:{ + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1;} + }, + 1068: { + chainModifier: function(p) { return 1.5; } + }, + 1069:{ + atk: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1;} + }, + 1070:{ + atk: function(p) { return p.unit.class.has("Driven") ? 2.25 : 1;} + }, + 1071: { + atk: function(p) { return p.unit.cost <= 20 ? 1.5 : 1; } + }, + 1072: { + atk: function(p) { return p.unit.cost <= 30 ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.2 : 1;} + }, + 1073:{ + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1;} + }, + 1074: { + atk: function(p) { return p.unit.type == 'INT' ? 2 : 1; } + }, + 1075: { + atk: function(p) { return p.unit.type == 'INT' ? 2 : 1; }, + hp: function(p) { return p.unit.type == 'INT' ? 2 : 1; } + }, + 1076: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Free Spirit") ? 1.75 : 1; } + }, + 1077: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Free Spirit") ? 2.25 : 1; }, + rcv: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Free Spirit") ? 1.5 : 1; } + }, + 1080: { + atk: function(p) { return p.unit.cost <= 20 ? 2.5 : 1; } + }, + 1081: { + atk: function(p) { return p.unit.cost <= 30 ? 2.5 : 1; } + }, + 1082: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Fighter") ? 1.2 : 1; } + }, + 1083: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3, [ "Striker", "Fighter" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Striker") && !p.unit.class.has("Fighter")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 3 : 1.5; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1084: { + atk: function(p) { return !p.unit.class.has("Driven") ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 3 : 1.5); }, + hp: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; } + }, + 1085: { + atk: function(p) { return !p.unit.class.has("Driven") ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 3 : 1.5); }, + hp: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; } + }, + 1086:{ + atk: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1;}, + rcv: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1;} + }, + 1087:{ + atk: function(p) { return p.unit.class.has("Driven") ? 2 : 1;}, + rcv: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1;} + }, + 1088:{ + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1;} + }, + 1089:{ + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1;}, + hp: function(p) { return p.unit.class.has("Driven") ? 1.75 : 1;} + }, + 1090: { + atk: function(p) { return p.percHP <= 30.0 ? 2 : 1; } + }, + 1091: { + atk: function(p) { return p.percHP <= 30.0 ? 2.5 : 1; } + }, + 1092: { + rcv: function(p) { return 1 + .5 * ((100 - p.percHP) / 100); } + }, + 1093: { + rcv: function(p) { return 1 + 1 * ((100 - p.percHP) / 100); } + }, + 1094: { + atk: function(p) { return p.unit.class.has('Cerebral') ? 2.0 : 1.0; } + }, + 1095: { + atk: function(p) { return p.unit.class.has('Cerebral') ? 2.0 : 1.0; } + }, + 1096: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3, [ "Powerhouse" ]); }, + hitAtk: function(p) { + return !(p.unit.class.has('Powerhouse')) ? 1.0 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect", "Perfect"]) ? 3 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1097: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3.5, [ "Powerhouse" ]); }, + hitAtk: function(p) { + return !(p.unit.class.has('Powerhouse')) ? 1.0 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect", "Perfect"]) ? 3.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1098: { + chainModifier: function(p) { return 2; } + }, + 1099: { + atk: function(p) { return p.unit.class.has('Fighter') ? 2.0 : 1.0; } + }, + 1100: { + atk: function(p) { return p.unit.class.has('Fighter') ? 2.25 : 1.0; }, + rcv: function(p) { return p.unit.class.has('Fighter') ? 1.2 : 1.0; } + }, + 1101: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).count("Perfect") == p.chainPosition ? 2.25 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1102: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).count("Perfect") == p.chainPosition ? 2.75 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1103: { + atk: function(p) { return p.unit.class.has('Cerebral') ? 1.5 : 1.0; }, + rcv: function(p) { return p.unit.class.has('Cerebral') ? 1.5 : 1.0; } + }, + 1104: { + atk: function(p) { return p.unit.class.has('Cerebral') ? 1.75 : 1.0; }, + rcv: function(p) { return p.unit.class.has('Cerebral') ? 1.75 : 1.0; } + }, + 1105: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Free Spirit") ? 1.5 : 1; } + }, + 1106: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Free Spirit") ? 2 : 1; } + }, + 1107: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; } + }, + 1108: { + atk: function(p) { return p.unit.class.has("Driven") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Driven") ? 2 : 1; } + }, + 1110: { + atk: function(p) { return p.unit.type == "PSY" ? 1.25 : 1; } + }, + 1111: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.25 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.25 : 1; } + }, + 1112: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; } + }, + 1113: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } + }, + 1114: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } + }, + 1115: { + atk: function(p) { return p.unit.type == "STR" ? 2.5 : 1; } + }, + 1118: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 1119: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; }, + rcv: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 1120: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 4 : 1; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1121: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 4 : 1; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1122: { + atk: function(p) { return p.slot == p.sourceSlot ? 4 : p.unit.type == "STR" || p.unit.type == "QCK" || p.unit.type == "DEX" ? 2.5 : 1; } + }, + 1123: { + atk: function(p) { return p.slot == p.sourceSlot ? 4 : p.unit.type == "STR" || p.unit.type == "QCK" || p.unit.type == "DEX" ? 2.5 : 1; } + }, + 1124: { + atk: function(p) { + return p.unit.class.has("Slasher") ? Math.max(1.0, 3.0 - 0.1 * p.turnCounter) : 1; + } + }, + 1125: { + atk: function(p) { + return p.unit.class.has("Slasher") ? Math.max(1.0, 3.5 - 0.1 * p.turnCounter) : 1; + } + }, + 1126: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 1127: { + atk: function(p) { return p.unit.type == "DEX" ? 2.25 : 1; }, + hp: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 1128: { + atk: function(p) { return 1.75; } + }, + 1129: { + atk: function(p) { return 2; } + }, + 1130: { + atk: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 1131: { + atk: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Powerhouse") ? 2 : 1; } + }, + 1132: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } + }, + 1133: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.25 : 1; }, + hp: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } + }, + 1134: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Slasher") ? 1.2 : 1; }, + rcv: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Slasher") ? 1.2 : 1; } + }, + 1135: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Slasher") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 1136: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 1137: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2.25 : 1; } + }, + 1139: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 1140: { + atk: function(p) { return p.unit.class.has("Driven") ? 2 : 1; } + }, + 1141: { + atk: function(p) { return p.unit.class.has("Driven") ? 2.25 : 1; } + }, + 1142: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; } + }, + 1143: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 : 1; } + }, + 1144: { + atk: function(p) { return p.unit.type == "PSY" ? 1.75 : 1; } + }, + 1145: { + atk: function(p) { return p.unit.type == "PSY" ? 1.75 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; } + }, + 1154: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.3 : 1; } + }, + 1156: { + atk: function(p) { return ( p.unit.class.has("Driven") || p.unit.class.has("Striker") ) && p.percHP >= 50.0 ? 1.2 : 1; } + }, + 1157: { + atk: function(p) { return ( p.unit.class.has("Driven") || p.unit.class.has("Striker") ) && p.percHP >= 50.0 ? 1.75 : 1; } + }, + 1158: { + atk: function(p) { return p.unit.class.has("Shooter") || p.unit.class.has("Striker") || p.unit.class.has("Powerhouse") ? 1.75 : 1; } + }, + 1159: { + atk: function(p) { return p.unit.class.has("Shooter") || p.unit.class.has("Striker") || p.unit.class.has("Powerhouse") ? 2.25 : 1; } + }, + 1160: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; } + }, + 1161: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 : 1; }, + rcv: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; } + }, + 1162: { + atk: function(p) { return p.unit.type == "PSY" ? 1.75 : 1; } + }, + 1163: { + atk: function(p) { return (p.unit.type == "PSY" && (p.unit.class.has("Driven") || p.unit.class.has("Cerebral"))) ? 2.625 : (p.unit.type == "PSY" && !(p.unit.class.has("Driven") || p.unit.class.has("Cerebral"))) ? 1.75 : (!(p.unit.type == "PSY") && (p.unit.class.has("Driven") || p.unit.class.has("Cerebral"))) ? 1.5 : 1; } + }, + 1164: { + rcv: function(p) { return 1.2; } + }, + 1165: { + rcv: function(p) { return 1.5; } + }, + 1167: { + atk: function(p) { return 1.2; } + }, + 1168: { + atk: function(p) { return p.unit.type == "STR" && p.percHP <= 30.0 ? 2 : 1; } + }, + 1169: { + atk: function(p) { + return p.unit.type == "STR" ? 1 + 1.5 * ((100 - p.percHP) / 100) : 1; + } + }, + 1170: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 1171: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 1172: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 1173: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 1174: { + atk: function(p) { return p.unit.type == "DEX" && p.percHP <= 30.0 ? 2.75 : 1; } + }, + 1175: { + atk: function(p) { return p.unit.type == "DEX" && p.percHP <= 30.0 ? 3 : 1; } + }, + 1176: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; } + }, + 1177: { + atk: function(p) { return p.unit.type == "DEX" ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 2 : 1; } + }, + 1178: { + atk: function(p) { return p.unit.type == "STR" && p.percHP >= 99.0 ? 2 : 1; } + }, + 1179: { + atk: function(p) { return p.unit.type == "STR" && p.percHP >= 99.0 ? 2.75 : 1; } + }, + 1181: { + atk: function(p) { return p.unit.type == "DEX" ? 2.5 : 1; } + }, + 1182: { + atk: function(p) { return p.unit.type == "DEX" ? 2.5 : 1; } + }, + 1183: { + atk: function(p) { return p.unit.type == "PSY" ? 2.5 : 1; } + }, + 1184: { + atk: function(p) { return p.unit.type == "PSY" ? 2.5 : 1; } + }, + 1185: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Cerebral") ? 1.75 : 1; } + }, + 1186: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Cerebral") ? 1.75 : 1; } + }, + 1187: { + atk: function(p) { return p.unit.type == "STR" ? 2.5 : 1; } + }, + 1188: { + atk: function(p) { return p.unit.type == "STR" ? 2.5 : 1; } + }, + 1189: { + atk: function(p) { return p.unit.type == "QCK" ? 2.25 : 1; } + }, + 1190: { + atk: function(p) { return p.unit.type == "QCK" ? 2.25 : 1; } + }, + 1191: { + atk: function(p) { + return Math.min(3.5, 2.0 + 0.1875 * p.turnCounter); + }, + hp: function(p) { return 1.2; } + }, + 1192: { + atk: function(p) { + return Math.min(3.5, 2.0 + 0.1875 * p.turnCounter); + }, + hp: function(p) { return 1.2; } + }, + 1193: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 : 1; } + }, + 1194: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2.5 : 1; } + }, + 1195: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.75 : 1; } + }, + 1196: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 1197: { + atk: function(p) { return p.unit.class.has("Powerhouse") || p.unit.class.has("Cerebral") ? (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 2.5 : 1) : 1; } + }, + 1198: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; } + }, + 1199: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; } + }, + 1202: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; } + }, + 1203: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2.25 : 1; } + }, + 1204: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.2 : 1; }, + rcv: function(p) { return p.unit.class.has("Free Spirit") ? 1.2 : 1; } + }, + 1205: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; } + }, + 1206: { + hp: function(p) { return 1.3; } + }, + 1207: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } + }, + 1208: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "INT" ? 2 : 1; } + }, + 1209: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } + }, + 1210: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 1211: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } + }, + 1212: { + atk: function(p) { return p.unit.type == "STR" ? 2.25 : 1; } + }, + 1213: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") ? 1.2 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") ? 1.2 : 1; }, + }, + 1214: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") ? 1.25 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") ? 1.25 : 1; }, + }, + 1215: { + damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['QCK', 'PSY', 'DEX']); }, + hitAtk: function(p) { + return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ + type: 'QCK', + minModifier: 'Good' + }, { + type: 'PSY', + minModifier: 'Good' + }, { + type: 'DEX', + minModifier: 'Good' + }]) ? 2.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1216: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2 : 1; } + }, + 1217: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; } + }, + 1218: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1219: { + atk: function(p) { + return p.unit.class.has("Shooter") ? Math.min(3, 1 + 0.125 * p.turnCounter) : 1; + } + }, + 1220: { + atk: function(p) { + return p.unit.class.has("Shooter") ? Math.min(3.25, 1 + 0.225 * p.turnCounter) : 1; + } + }, + 1221: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.75 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.2 : 1; }, + }, + 1222: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.75 : 1; }, + }, + 1223: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } + }, + 1224: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 1225: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + }, + 1226: { + atk: function(p) { return p.unit.class.has("Driven") ? 2 : 1; } + }, + 1227: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2.25 : 1; } + }, + 1228: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2.5 : 1; } + }, + 1229: { + atk: function(p) { return p.slot == p.sourceSlot ? 2 : p.unit.class.has("Powerhouse") ? 2 : 1; } + }, + 1230: { + atk: function(p) { return p.slot == p.sourceSlot ? 2.75 : p.unit.class.has("Powerhouse") ? 2.5 : 1; } + }, + 1231: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Driven") ? (window.specials[1231].turnedOn || window.specials[1232].turnedOn ? 2.1875 : 1.75) : 1; }, + rcv: function(p) { return .5 } + }, + 1232: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Driven") ? (window.specials[1231].turnedOn || window.specials[1232].turnedOn ? 2.925 : 2.25) : 1; }, + rcv: function(p) { return .5 } + }, + 1233: { + atk: function(p) { + return p.unit.class.has("Slasher") && p.unit.class.has("Cerebral") ? 2.25 : + p.unit.class.has("Slasher") || p.unit.class.has("Cerebral") ? 1.5 : + 1; + }, + rcv: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Cerebral") ? 1.2 : 1; } + }, + 1234: { + atk: function(p) { + return p.unit.class.has("Slasher") && p.unit.class.has("Cerebral") ? 2.56 : + p.unit.class.has("Slasher") || p.unit.class.has("Cerebral") ? 1.6 : + 1; + }, + rcv: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Cerebral") ? 1.3 : 1; } + }, + 1235: { + atk: function(p) { return p.unit.type == "PSY" ? 1.75 : 1; }, + }, + 1236: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; }, + }, + 1237: { + hit: function(n) { + return n > 15 ? 2 : 1; + } + }, + 1238: { + hit: function(n) { + return n > 30 ? 3 : + n > 15 ? 2 : 1; + } + }, + 1239: { + atk: function(p){ + var specialEnabled = false; + for(var i=0;i<2;i++) + { + if(window.specials[1239].turnedOn[i]==true){specialEnabled = true;} + if(window.specials[1240].turnedOn[i]==true){specialEnabled = true;} + } + return specialEnabled ? 3 : 2; }, + rcv: function(p) { return 1.3 } + }, + 1240: { + atk: function(p){ + var specialEnabled = false; + for(var i=0;i<2;i++) + { + if(window.specials[1239].turnedOn[i]==true){specialEnabled = true;} + if(window.specials[1240].turnedOn[i]==true){specialEnabled = true;} + } + return specialEnabled ? 3 : 2; }, + rcv: function(p) { return 1.3 } + }, + 1241: { + chainModifier: function(p) { return 1.5; } + }, + 1242: { + chainModifier: function(p) { return 2; } + }, + 1243: { + atk: function(p) { + return p.unit.class.has("Fighter") && p.unit.class.has("Powerhouse") ? 1.69 : + p.unit.class.has("Fighter") || p.unit.class.has("Powerhouse") ? 1.3 : + 1; + }, + }, + 1244: { + atk: function(p) { + return p.unit.class.has("Fighter") && p.unit.class.has("Powerhouse") ? 2.276 : + p.unit.class.has("Fighter") && !p.unit.class.has("Powerhouse") ? 1.75 : + !p.unit.class.has("Fighter") && p.unit.class.has("Powerhouse") ? 1.3 : + 1; + }, + }, + 1245: { + atk: function(p) { return !p.unit.class.has("Fighter") ? 1 : p.percHP <= 10.0 && p.unit.class.has("Fighter") ? 3 : 1.75; } + }, + 1246: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.2 : 1; } + }, + 1247: { + atk: function(p) { return !p.unit.class.has("Fighter") ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 2.75 : 2); }, + hp: function(p) { return p.unit.class.has("Fighter") ? 1.2 : 1; } + }, + 1248: { + atk: function(p) { + return p.unit.class.has("Fighter") && p.unit.class.has("Powerhouse") ? 1.69 : + p.unit.class.has("Fighter") || p.unit.class.has("Powerhouse") ? 1.3 : + 1; + }, + }, + 1249: { + atk: function(p) { + return p.unit.class.has("Fighter") && p.unit.class.has("Powerhouse") ? 2.56 : + p.unit.class.has("Fighter") || p.unit.class.has("Powerhouse") ? 1.6 : + 1; + }, + }, + 1250: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + }, + 1251: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2 : 1; }, + }, + 1252: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; }, + }, + 1253: { + atk: function(p) { return p.unit.type == "DEX" && p.percHP >= 99.0 ? 2.25 : 1; } + }, + 1254: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).count("Perfect") == p.chainPosition ? p.unit.class.has("Striker") ? 2.75 : 1 : 1; }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1256: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Driven") ? 2 : 1; }, + rcv: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Driven") ? 0.1 : 1; }, + }, + 1257: { + atk: function(p) { return p.percHP <= 50.0 ? 2 : 1; } + }, + 1258: { + atk: function(p) { return p.percHP <= 50.0 ? 2.5 : 1; } + }, + 1259: { + atk: function(p) { return p.unit.class.has("Driven") ? 2.5 : 1; }, + }, + 1260: { + atk: function(p) { return p.unit.class.has("Driven") ? 2.5 : 1; }, + }, + 1261: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; }, + }, + 1262: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.75 : 1; }, + }, + 1263: { + atk: function(p) { return p.unit.cost <= 20 ? 2.5 : 1; } + }, + 1264: { + atk: function(p) { return p.unit.cost <= 30 ? 2.5 : 1; } + }, + 1265: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; }, + }, + 1266: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2.5 : 1; }, + }, + 1267: { + atk: function(p) { if(p.classCount.Striker>=1 && p.classCount.Fighter>=1 && p.classCount.Shooter>=1 && p.classCount.Slasher>=1) + return 2.75; + else + return 1; + }, + hp: function(p) { if(p.classCount.Striker>=1 && p.classCount.Fighter>=1 && p.classCount.Shooter>=1 && p.classCount.Slasher>=1) + return 1.5; + else + return 1; + }, + }, + 1268: { + atk: function(p) { if(p.classCount.Striker>=1 && p.classCount.Fighter>=1 && p.classCount.Shooter>=1 && p.classCount.Slasher>=1) + return 2.75; + else + return 1; + }, + hp: function(p) { if(p.classCount.Striker>=1 && p.classCount.Fighter>=1 && p.classCount.Shooter>=1 && p.classCount.Slasher>=1) + return 1.5; + else + return 1; + }, + }, + 1271: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; }, + }, + 1272: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2.5 : 1; }, + }, + 1273: { + atk: function(p) { + return p.unit.class.has("Fighter") && p.unit.class.has("Powerhouse") ? 2.25 : + p.unit.class.has("Fighter") && !p.unit.class.has("Powerhouse") ? 1.5 : + !p.unit.class.has("Fighter") && p.unit.class.has("Powerhouse") ? 1.5 : + 1; + }, + hp: function(p) { + return p.unit.class.has("Fighter") && p.unit.class.has("Powerhouse") ? 1.44 : + p.unit.class.has("Fighter") && !p.unit.class.has("Powerhouse") ? 1.2 : + !p.unit.class.has("Fighter") && p.unit.class.has("Powerhouse") ? 1.2 : + 1; + }, + }, + 1274: { + atk: function(p) { + return p.unit.class.has("Fighter") && p.unit.class.has("Powerhouse") ? 2.56 : + p.unit.class.has("Fighter") && !p.unit.class.has("Powerhouse") ? 1.6 : + !p.unit.class.has("Fighter") && p.unit.class.has("Powerhouse") ? 1.6 : + 1; + }, + hp: function(p) { + return p.unit.class.has("Fighter") && p.unit.class.has("Powerhouse") ? 1.44 : + p.unit.class.has("Fighter") && !p.unit.class.has("Powerhouse") ? 1.2 : + !p.unit.class.has("Fighter") && p.unit.class.has("Powerhouse") ? 1.2 : + 1; + }, + }, + 1275: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, + }, + 1276: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; }, + }, + 1277: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Striker") && p.percHP >= 99.0 ? 2.25 : 1; }, + rcv: function(p) { return .01; }, + }, + 1278: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Striker") && p.percHP >= 99.0 ? 2.75 : 1; }, + rcv: function(p) { return .01; }, + }, + 1279: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, + }, + 1280: { + atk: function(p) { return p.unit.type == "PSY" ? 2.5 : 1; }, + }, + 1281: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.25 : 1; }, + }, + 1282: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2.5 : 1; }, + }, + 1283: { + atk: function(p) { return p.unit.class.has("Driven") ? 2.5 : 1; }, + }, + 1284: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") ? 1.2 : 1; }, + }, + 1285: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3.375, [ "Striker" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Striker")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 3.375 : 1.5; + }, + hp: function(p) { return p.unit.class.has("Striker") ? 1.25 : 1; }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1286: { + atk: function(p) { return p.unit.type == "PSY" ? 1.3 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.3 : 1; }, + }, + 1287: { + atk: function(p) { return p.unit.type == "PSY" ? 1.3 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.3 : 1; }, + }, + 1288: { + atk: function(p) { + return p.unit.class.has("Driven") ? Math.max(1.0, 2.5 - 0.1 * p.turnCounter) : 1; + } + }, + 1289: { + atk: function(p) { + return p.unit.class.has("Driven") ? Math.max(1.0, 2.75 - 0.1 * p.turnCounter) : 1; + } + }, + 1291: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.75 : 1; }, + }, + 1292: { + atk: function(p) { return !p.unit.class.has("Driven") ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 2.5 : 2); }, + }, + 1293: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.75 : 1; }, + }, + 1294: { + atk: function(p) { return p.unit.class.has("Driven") ? 2 : 1; }, + }, + + 1297: { + damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['STR', 'STR', 'STR']); }, + hitAtk: function(p) { + return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ + type: 'STR', + minModifier: 'Good' + }, { + type: 'STR', + minModifier: 'Good' + }, { + type: 'STR', + minModifier: 'Good' + }]) ? 2.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1298: { + damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['STR', 'STR', 'STR']); }, + hitAtk: function(p) { + return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ + type: 'STR', + minModifier: 'Good' + }, { + type: 'STR', + minModifier: 'Good' + }, { + type: 'STR', + minModifier: 'Good' + }]) ? 3 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1299: { + atk: function(p) { return p.unit.type == "INT" ? 1.2 : 1; }, + rcv: function(p) { return p.unit.type == "INT" ? 1.2 : 1; }, + }, + 1300: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + }, + 1301: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.75 : 1; }, + }, + 1302: { + atk: function(p) { + return p.unit.class.has("Slasher") && p.unit.class.has("Driven") ? 2.625 : + p.unit.class.has("Slasher") && !p.unit.class.has("Driven") ? 1.75 : + !p.unit.class.has("Slasher") && p.unit.class.has("Driven") ? 1.5 : + 1; + }, + }, + 1303: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; }, + }, + 1304: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2 : 1; }, + }, + 1305: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.3 : 1; }, + }, + 1306: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.75 : 1; }, + }, + 1307: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.75 : 1; }, + }, + 1308: { + atk: function(p) { return p.unit.class.has("Driven") ? 2 : 1; }, + }, + 1309: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 : 1; }, + }, + 1310: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2.5 : 1; }, + }, + 1311: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + }, + 1312: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.75 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.75 : 1; }, + }, + 1313: { + atk: function(p) { + return p.unit.type == "STR" ? ((p.orb == 2) ? 3.9375 : 2.25) : (p.unit.type == "DEX" ? (p.orb == 0.5 ? 3.9375 : 2.25) : (p.orb == 'str' ? 3.9375 : 2.25)); + $scope.notify({ text: p.orb }); + }, + }, + 1314: { + atk: function(p) { + return p.unit.type == "STR" ? ((p.orb == 2) ? 3.9375 : 2.25) : (p.unit.type == "DEX" ? (p.orb == 0.5 ? 3.9375 : 2.25) : (p.orb == 'str' ? 3.9375 : 2.25)); + }, + }, + 1315: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect", "Perfect"]) ? 3 : + //p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect"]) ? 3 : + //p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.75 : + p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect"]) ? 2 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1316: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect", "Perfect"]) ? 3.5 : + //p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect"]) ? 3 : + //p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.75 : + p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect"]) ? 2.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1317: { + atk: function(p) { return p.unit.type == "PSY" || p.unit.type == "STR" ? 2 : 1; }, + }, + 1318: { + atk: function(p) { return p.unit.type == "PSY" || p.unit.type == "STR" ? 2.5 : 1; }, + }, + 1321: { + atk: function(p) { if((p.colorCount.INT>=1 && p.colorCount.PSY>=1 && p.colorCount.STR>=1 && p.colorCount.DEX>=1 && p.colorCount.QCK>=1) && (p.unit.class.has("Cerebral") || p.unit.class.has("Slasher"))) + return 2.25; + else + return 1; + }, + }, + 1322: { + atk: function(p) { if((p.colorCount.INT>=1 && p.colorCount.PSY>=1 && p.colorCount.STR>=1 && p.colorCount.DEX>=1 && p.colorCount.QCK>=1) && (p.unit.class.has("Cerebral") || p.unit.class.has("Slasher"))) + return 2.5; + else + return 1; + }, + }, + 1323: { + atk: function(p) { + return p.unit.class.has("Slasher") && p.unit.class.has("Driven") ? 1.69 : + p.unit.class.has("Driven") || p.unit.class.has("Slasher") ? 1.3 : + 1; + } + }, + 1324: { + atk: function(p) { + return p.unit.class.has("Slasher") && p.unit.class.has("Driven") ? 2.56 : + p.unit.class.has("Driven") || p.unit.class.has("Slasher") ? 1.6 : + 1; + } + }, + 1326: { + atk: function(p) { return 1.3; }, + }, + 1327: { + atk: function(p) { return p.unit.cost <= 20 ? 2 : 1; }, + }, + 1328: { + atk: function(p) { return p.unit.cost <= 20 ? 2.5 : 1; }, + }, + 1330: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 1333: { + atk: function(p) { + return p.unit.class.has("Powerhouse") && p.unit.type == "STR" ? 1.96 : + p.unit.class.has("Powerhouse") || p.unit.type == "STR" ? 1.4 : + 1; + } + }, + 1334: { + atk: function(p) { + return p.unit.class.has("Free Spirit") && p.unit.type == "DEX" ? 1.96 : + p.unit.class.has("Free Spirit") || p.unit.type == "DEX" ? 1.4 : + 1; + } + }, + 1335: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; } + }, + 1336: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 : 1; } + }, + 1337: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Free Spirit") ? 2 : 1; } + }, + 1338: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Free Spirit") ? 2.25 : 1; } + }, + 1339: { + atk: function(p) { return p.unit.type == "DEX" ? 2.25 : 1; } + }, + 1340: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 1341: { + damageSorter: function(d) { return CrunchUtils.typeSort(d, 2.625, ["QCK"]); }, + hitAtk: function(p) { + if (!(p.unit.type == "QCK")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Below Good", "Below Good", "Below Good"]) ? 2.625 : 1.75; + }, + hitModifiers: ["Below Good", "Below Good", "Below Good", "Perfect", "Perfect", "Perfect"] + }, + 1342: { + hp: function(p) { return p.unit.type == "PSY" ? 1.75 : 1; } + }, + 1343: { + hp: function(p) { return 0.5; }, + atk: function(p) { return p.unit.class.has("Driven") ? 2 : 1; }, + }, + 1344: { + hp: function(p) { return 0.5; }, + atk: function(p) { return p.unit.class.has("Driven") ? 2.25 : 1; }, + }, + 1345: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.5 : 1; }, + }, + 1346: { + hp: function(p) { return p.unit.class.has("Shooter") || p.unit.class.has("Cerebral") ? 1.5 : 1; }, + atk: function(p) { return p.unit.class.has("Shooter") || p.unit.class.has("Cerebral") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") || p.unit.class.has("Cerebral") ? 1.5 : 1; }, + }, + 1349: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.75 : 1; }, + }, + 1352: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3.5, ["Fighter"]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Fighter")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect", "Perfect"]) ? 3.5 : 2; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1353: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2.5 : 1; }, + }, + 1354: { + chainModifier: function(p) { return 2; } + }, + 1355: { + chainModifier: function(p) { return 3; } + }, + 1356:{ + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + }, + 1357:{ + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 1358: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 1359: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.75 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") ? 1.75 : 1; } + }, + 1360: { + atk: function(p) { return p.unit.cost <= 30 ? 2 : 1; }, + hp: function(p) { return p.unit.cost <= 30 ? 1.2 : 1; } + }, + 1361: { + atk: function(p) { return p.unit.class.has("Slasher") ? p.classCount.Slasher>=5 ? Math.max(2.5, 2.5 + .5 * Math.min(p.turnCounter,1)) : 1 : Math.max(1, 1 + .2 * Math.min(p.turnCounter,1)); }, + hp: function(p) { return p.unit.class.has("Slasher") ? + p.classCount.Slasher>=5 ? 1.5 : 1 : 1; }, + }, + 1362: { + atk: function(p) { return p.unit.class.has("Slasher") ? p.classCount.Slasher>=5 ? Math.max(2.5, 2.5 + .5 * Math.min(p.turnCounter,1)) : 1 : Math.max(1, 1 + .2 * Math.min(p.turnCounter,1)); }, + hp: function(p) { return p.unit.class.has("Slasher") ? + p.classCount.Slasher>=5 ? 1.5 : 1 : 1; }, + }, + 1363: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; } + }, + 1364: { + atk: function(p) { return p.unit.type == "PSY" ? 2.5 : 1; } + }, + 1365: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; } + }, + 1366: { + atk: function(p) { return !p.unit.class.has("Cerebral") ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 2.75 : 1.5); }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; } + }, + 1367: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; } + }, + 1368: { + atk: function(p) { return !(p.unit.type == "STR") ? 1 : p.percHP <= 30.0 ? 3 : 2.5; } + }, + 1369: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; } + }, + 1370: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, + hp: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; } + }, + 1371: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 4, [ "Slasher", "Powerhouse" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Slasher") && !p.unit.class.has("Powerhouse")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect"]) ? 2.5 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect"]) ? 2.25 : 2; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1372: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 4, [ "Slasher", "Powerhouse" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Slasher") && !p.unit.class.has("Powerhouse")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect"]) ? 3 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect"]) ? 2.5 : 2; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1373: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "INT" ? 1.2 : 1; }, + }, + 1374: { + atk: function(p) { return p.unit.type == "INT" ? 2.25 : 1; }, + hp: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + }, + 1375: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2.5 : 1; }, + }, + 1376: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2.75 : 1; }, + }, + 1377: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Shooter") ? 1.3 : 1; }, + rcv: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Shooter") ? 1.3 : 1; } + }, + 1378: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Shooter") ? 1.75 : 1; }, + rcv: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Shooter") ? 1.75 : 1; } + }, + 1379: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2 : 1; }, + }, + 1380: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2.5 : 1; }, + }, + 1381: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Cerebral") ? 1.2 : 1; }, + rcv: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Cerebral") ? 1.2 : 1; } + }, + 1382: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Cerebral") ? 1.75 : 1; }, + rcv: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Cerebral") ? 1.75 : 1; } + }, + 1383: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; }, + }, + 1384: { + atk: function(p) { return p.unit.class.has("Striker") ? 2.5 : 1; }, + }, + 1387: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect"]) ? 2.8125 : 2.25; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"], + hp: function(p) { return 1.25; }, + }, + 1388: { + atk: function(p) { return p.unit.type == "DEX" ? 2.5 : 1; }, + }, + 1389: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + }, + 1390: { + atk: function(p) { return p.unit.cost <= 40 ? 1.5 : 0.5; }, + hp: function(p) { return p.unit.cost <= 40 ? 1 : 0.5; } + }, + 1391: { + atk: function(p) { return p.unit.cost <= 40 ? 1.5 : 0.5; }, + hp: function(p) { return p.unit.cost <= 40 ? 1 : 0.5; } + }, + 1392: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; }, + hp: function(p) { return p.unit.type == "PSY" ? 1.25 : 1; }, + }, + 1393: { + atk: function(p) { return p.unit.cost <= 30 ? 2 : 1; }, + }, + 1394: { + atk: function(p) { return p.unit.type == "QCK" || p.unit.type == "STR" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" || p.unit.type == "STR" ? 1.1 : 1; }, + }, + 1395: { + atk: function(p) { return p.unit.type == "QCK" || p.unit.type == "STR" ? 2.25 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" || p.unit.type == "STR" ? 1.2 : 1; }, + }, + 1396: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.75 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") ? 1.25 : 1; }, + }, + 1397: { + atk: function(p) { return p.unit.class.has("Driven") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, + }, + 1398: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Cerebral") ? 1.5 : 1; } + }, + 1399: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Cerebral") ? 1.5 : 1; } + }, + 1400: { + atk: function(p) { + return p.unit.class.has("Shooter") && p.unit.class.has("Driven") ? 2.275 : + p.unit.class.has("Shooter") && !p.unit.class.has("Driven") ? 1.75 : + !p.unit.class.has("Shooter") && p.unit.class.has("Driven") ? 1.3 : + 1; + }, + }, + 1401: { + atk: function(p) { + return p.unit.class.has("Shooter") && p.unit.class.has("Driven") ? 2.625 : + p.unit.class.has("Shooter") && !p.unit.class.has("Driven") ? 1.75 : + !p.unit.class.has("Shooter") && p.unit.class.has("Driven") ? 1.5 : + 1; + }, + }, + 1402: { + atk: function(p) { return p.unit.type == "QCK" || p.unit.type == "PSY" ? 2 : 1; }, + }, + 1403: { + atk: function(p){ + return p.unit.class.has("Free Spirit") ? p.actions[p.sourceSlot] ? 4 : 2.5 : 1; + + }, + }, + 1404: { + atk: function(p){ + return p.unit.class.has("Free Spirit") ? p.actions[p.sourceSlot] ? 4 : 2.5 : 1; + }, + }, + 1405: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.75 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") ? 1.25 : 1; }, + }, + 1406: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2.25 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, + }, + 1407: { + atk: function(p) { return p.unit.type == "DEX" || p.unit.type == "PSY" ? 1.75 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" || p.unit.type == "PSY" ? 1.25 : 1; }, + }, + 1408: { + atk: function(p) { return p.unit.type == "DEX" || p.unit.type == "PSY" ? 2.25 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" || p.unit.type == "PSY" ? 1.5 : 1; }, + }, + 1410: { + chainModifier: function(p) { return 2.5; } + }, + 1411: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2.25 : 1; }, + rcv: function(p) { return 0; } + }, + 1412: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2.75 : 1; }, + rcv: function(p) { return 0; } + }, + 1413: { + atk: function(p) { return p.percHP <= 30.0 ? 3 : 1.75; }, + hp: function(p) { return 1.2; } + }, + 1414: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2.5 : 1; }, + }, + 1415: { + atk: function(p) { return p.unit.cost <= 30 ? 1.5 : 1; }, + }, + 1416: { + atk: function(p) { return p.unit.cost <= 30 ? 2.25 : 1; }, + hp: function(p) { return p.unit.cost <= 30 ? 1.2 : 1; }, + }, + 1417: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, + }, + 1418: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + }, + 1419: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2 : 1; }, + }, + 1420: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2.5 : 1; }, + }, + 1422: { + atk: function(p) { return p.unit.class.has("Driven") ? 2 : 1; }, + }, + 1422: { + atk: function(p) { return p.unit.class.has("Driven") ? 2.25 : 1; }, + hp: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Striker") ? 1.5 : 1; }, + }, + 1423: { + atk: function(p) { return 1.75; }, + }, + 1424: { + atk: function(p) { return p.unit.class.has("Striker") ? 1 + 1.25 * p.percHP / 100 : 1; } + }, + 1425: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Fighter") ? 1.75 : 1; }, + }, + 1426: { + atk: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Striker") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Striker") ? 1.25 : 1; }, + }, + 1427: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, + }, + 1429: { + rcv: function(p) { return p.unit.class.has("Free Spirit") || p.unit.class.has("Striker") ? 1.5 : 1; }, + }, + 1430: { + rcv: function(p) { return p.unit.class.has("Free Spirit") || p.unit.class.has("Striker") ? 2 : 1; }, + }, + 1431: { + atk: function(p) { if(p.colorCount.INT>=1 && p.colorCount.PSY>=1 && p.colorCount.STR>=1 && p.colorCount.DEX>=1 && p.colorCount.QCK>=1) + return 2; + else + return 1; + }, + hp: function(p) { if(p.classCount.FreeSpirit>=1 && p.classCount.Fighter>=1 && p.classCount.Shooter>=1 && p.classCount.Slasher>=1 && p.classCount.Powerhouse>=1 && p.classCount.Driven>=1) + return 1.2; + else + return 1; + }, + }, + 1432: { + atk: function(p) { if(p.colorCount.INT>=1 && p.colorCount.PSY>=1 && p.colorCount.STR>=1 && p.colorCount.DEX>=1 && p.colorCount.QCK>=1) + return 2.5; + else + return 1; + }, + hp: function(p) { if(p.classCount.FreeSpirit>=1 && p.classCount.Fighter>=1 && p.classCount.Shooter>=1 && p.classCount.Slasher>=1 && p.classCount.Powerhouse>=1 && p.classCount.Driven>=1) + return 1.5; + else + return 1; + }, + }, + 1433: { + atk: function(p) { + return p.unit.class.has("Powerhouse") ? p.classCount.Powerhouse==6 ? 3 : 1 : 1; }, + hp: function(p) { + return p.unit.class.has("Powerhouse") ? p.classCount.Powerhouse==6 ? 2 : p.classCount.Powerhouse==5 ? 1.5 : p.classCount.Powerhouse==4 ? 1.4 : p.classCount.Powerhouse==3 ? 1.3 : p.classCount.Powerhouse==2 ? 1.2 : p.classCount.Powerhouse==1 ? 1.1 : 1 : 1; }, + }, + 1434: { + atk: function(p) { + return p.unit.class.has("Powerhouse") ? p.classCount.Powerhouse==6 ? 3 : 1 : 1; }, + hp: function(p) { + return p.unit.class.has("Powerhouse") ? p.classCount.Powerhouse==6 ? 2 : p.classCount.Powerhouse==5 ? 1.5 : p.classCount.Powerhouse==4 ? 1.4 : p.classCount.Powerhouse==3 ? 1.3 : p.classCount.Powerhouse==2 ? 1.2 : p.classCount.Powerhouse==1 ? 1.1 : 1 : 1; }, + }, + 1435: { + atk: function(p) { + return p.unit.class.has("Slasher") ? 2 : 1; }, + hp: function(p) { + return p.unit.class.has("Powerhouse") ? 1.2 : 1; }, + }, + 1436: { + atk: function(p) { + return p.unit.class.has("Slasher") ? 2.5 : 1; }, + hp: function(p) { + return p.unit.class.has("Powerhouse") ? 1.25 : 1; }, + }, + 1437: { + atk: function(p) { + return p.unit.class.has("Powerhouse") && p.unit.class.has("Striker") ? 1.69 : + p.unit.class.has("Powerhouse") || p.unit.class.has("Striker") ? 1.3 : + 1; + } + }, + 1438: { + atk: function(p) { + return p.unit.class.has("Powerhouse") && p.unit.class.has("Striker") ? 2.56 : + p.unit.class.has("Powerhouse") || p.unit.class.has("Striker") ? 1.6 : + 1; + } + }, + 1439: { + atk: function(p) { + return p.unit.class.has("Powerhouse") || p.unit.class.has("Fighter") ? 1.2 : 1; + } + }, + 1440: { + atk: function(p) { + return p.unit.class.has("Powerhouse") || p.unit.class.has("Fighter") ? 1.5 : 1; + } + }, + 1441: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + }, + 1442: { + atk: function(p) { return p.unit.type == "INT" ? 2.25 : 1; }, + }, + 1443: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 2.75, [ "Powerhouse" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Powerhouse")) return 1; + return p.modifiers.slice(0, p.chainPosition) + .subcontains(["Good", "Great", "Perfect"]) ? 2.75 : 1; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1444: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3.25, [ "Powerhouse" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Powerhouse")) return 1; + return p.modifiers.slice(0, p.chainPosition) + .subcontains(["Good", "Great", "Perfect"]) ? 3.25 : 1; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1445: { + atk: function(p) { + return (p.unit.type == "QCK" || p.unit.type == "PSY") ? 2.25 + 0.5 * p.percHP / 100 : 1; + }, + rcv: function(p) { + return (p.unit.type == "QCK" || p.unit.type == "PSY") && p.percHP <= 50.0 ? 1.5 : 1; + } + }, + 1446: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; }, + rcv: function(p) { return p.unit.class.has("Shooter") ? 1.2 : 1; } + }, + 1447: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2.5 : 1; }, + }, + 1448: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.5 : 1; }, + }, + 1449: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; }, + }, + 1450: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.75 : 1; }, + }, + 1451: { + atk: function(p) { return p.unit.type != "DEX" ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 2.25 : 1.5); } + }, + 1452: { + atk: function(p) { return p.unit.type != "DEX" ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 2.5 : 2); } + }, + 1453: { + atk: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 1.5 : 1; }, + }, + 1454: { + atk: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 1.75 : 1; }, + rcv: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 1.5 : 1; }, + }, + 1455: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 2.5, [ "Powerhouse" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Powerhouse")) return 1; + return p.modifiers.slice(0, p.chainPosition).count("Perfect") == p.chainPosition ? 2.75 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1456: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 2.75, [ "Powerhouse" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Powerhouse")) return 1; + return p.modifiers.slice(0, p.chainPosition).count("Perfect") == p.chainPosition ? 2.75 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1457: { + atk: function(p) { return p.unit.type == "INT" || p.unit.type == "QCK" ? 1.75 : 1; }, + }, + 1458: { + atk: function(p) { return p.unit.type == "INT" || p.unit.type == "QCK" ? 2 : 1; }, + }, + 1459: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Good", "Great", "Perfect"]) ? 1.75 : 1; + }, + hitModifiers: ["Good", "Good", "Great", "Perfect", "Perfect", "Perfect"] + }, + 1460: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Good", "Great", "Perfect"]) ? 2.14 : 1; + }, + hitModifiers: ["Good", "Good", "Great", "Perfect", "Perfect", "Perfect"] + }, + 1461: { + damageSorter: function(d) { return CrunchUtils.typeSort(d, 2.6, ["QCK"]); }, + hitAtk: function(p) { + if (!(p.unit.type == "QCK")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.6 : 2; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1462: { + chainModifier: function(p) { return 2; } + }, + 1463: { + chainModifier: function(p) { return 2.5; } + }, + 1465: { + atk: function(p) { return 1.25; }, + rcv: function(p) { return 1.25; } + }, + 1466: { + atk: function(p) { return p.unit.type == "PSY" || p.unit.type == "QCK" ? 2 : 1; }, + }, + 1467: { + atk: function(p) { return p.unit.type == "PSY" || p.unit.type == "QCK" ? 2.25 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" || p.unit.type == "QCK" ? 1.3 : 1; }, + }, + 1468: { + atk: function(p) { return p.unit.type == "STR" ? 1.75 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.2 : 1; }, + }, + 1469: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.25 : 1; }, + }, + 1470: { + atk: function(p) { return p.slot == p.sourceSlot ? 3 : p.unit.class.has("Powerhouse") || p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 1471: { + atk: function(p) { + return p.unit.class.has("Slasher") ? 1 + 1 * ((100 - p.percHP) / 100) : 1; + } + }, + 1472: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.125 : 2.25; } + }, + 1473: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.125 : 2.25; } + }, + 1474: { + atk: function(p) { return 1.5; } + }, + 1475: { + atk: function(p) { return 2.25; } + }, + 1476: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; }, + }, + 1477: { + atk: function(p) { return p.unit.class.has("Striker") ? 2.5 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.25 : 1; }, + }, + 1478: { + hit: function(n) { + return n > 44 ? 3 : + n > 33 ? 2 : + n > 22 ? 1.75 : + n > 11 ? 1.5 : 1; + } + }, + 1479: { + hit: function(n) { + return n > 44 ? 3.5 : + n > 33 ? 2.75 : + n > 22 ? 2.5 : + n > 11 ? 1.75 : 1; + } + }, + 1480: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect"]) ? 2.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1481: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect", "Perfect"]) ? 3.5 : + p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect"]) ? 2.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1482: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "INT" ? 1.2 : 1; } + }, + 1483: { + atk: function(p) { return p.unit.type == "INT" ? 2.5 : 1; }, + rcv: function(p) { return p.unit.type == "INT" ? 1.2 : 1; } + }, + 1484: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1485: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 3.25 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"], + hp: function(p) { return 1.2; }, + rcv: function(p) { return 1.2; }, + }, + 1486: { + atk: function(p) { return !p.unit.class.has("Fighter") ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 2.5 : 1); }, + }, + 1487: { + atk: function(p) { return !p.unit.class.has("Fighter") ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 3 : 1); }, + }, + 1488: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; }, + }, + 1489: { + atk: function(p) { return p.unit.class.has("Driven") ? 2 : 1; }, + }, + 1490: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Good", "Great"]) ? 1.75 : 1; + }, + hitModifiers: ["Good", "Good", "Great", "Perfect", "Perfect", "Perfect"] + }, + 1491: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Good", "Great"]) ? 2 : 1; + }, + hitModifiers: ["Good", "Good", "Great", "Perfect", "Perfect", "Perfect"] + }, + 1492: {//CHANGE THIS IF THIS ISN'T SABO + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2.75 : 1; }, + hp: function(p) { return 1.2; }, + rcv: function(p) { return 1.2; } + }, + 1493: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, + }, + 1494: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, + }, + 1495: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, + }, + 1496: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + }, + 1497: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, + }, + 1498: { + atk: function(p) { return p.unit.type == "STR" ? 1.2 : 1; }, + hp: function(p) { return p.unit.type == "STR" ? 1.2 : 1; }, + rcv: function(p) { return p.unit.type == "STR" ? 1.2 : 1; } + }, + 1499: { + atk: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; }, + hp: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; } + }, + 1500: { + atk: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; }, + hp: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; } + }, + 1501: { + atk: function(p) { return p.unit.cost <= 15 ? 2 : 1; } + }, + 1504: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 2.4, [ "Driven" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Driven")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.4 : 2; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1505: { + atk: function(p) { return !(p.unit.class.has("Powerhouse")) ? 1 : p.percHP <= 30.0 ? 2.25 : 1; } + }, + 1506: { + atk: function(p) { return !(p.unit.class.has("Powerhouse")) ? 1 : p.percHP <= 30.0 ? 2.5 : 2.25; } + }, + 1507: { + atk: function(p) { + return p.unit.class.has("Fighter") && p.unit.class.has("Powerhouse") ? 1.69 : + p.unit.class.has("Fighter") || p.unit.class.has("Powerhouse") ? 1.3 : + 1; + } + }, + 1508: { + atk: function(p) { + return p.unit.class.has("Fighter") && p.unit.class.has("Powerhouse") ? 2.25 : + p.unit.class.has("Fighter") || p.unit.class.has("Powerhouse") ? 1.5 : + 1; + } + }, + 1509: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; }, + }, + 1510: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Driven") ? 2 : 1; }, + }, + 1511: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; }, + }, + 1512: { + atk: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Powerhouse") ? 2 : 1; }, + }, + 1513: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.75 : 1; }, + rcv: function(p) { return p.unit.class.has("Powerhouse") ? 1.2 : 1; }, + }, + 1514: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Powerhouse") ? 1.2 : 1; }, + }, + 1515: { + atk: function(p) { return p.unit.type == "STR" || p.unit.type == "QCK" ? 1.5 : 1; }, + }, + 1516: { + atk: function(p) { return p.unit.type == "STR" || p.unit.type == "QCK" ? 2 : 1; }, + }, + 1517: { + atk: function(p) { return p.unit.class.has("Driven") ? 2 : 1; }, + }, + 1518: { + atk: function(p) { return p.unit.class.has("Driven") ? 2.5 : 1; }, + }, + 1519: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, + }, + 1520: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; }, + }, + 1521: { + atk: function(p) { + return p.unit.class.has("Slasher") && p.unit.type == "QCK" ? 1.44 : + p.unit.class.has("Slasher") || p.unit.type == "QCK" ? 1.2 : + 1; + } + }, + 1522: { + atk: function(p) { return p.unit.type == "DEX" ? 1.75 : 1; }, + hp: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; } + }, + 1523: { + atk: function(p) { return p.unit.type == "PSY" ? 1.75 : 1; }, + }, + 1524: { + atk: function(p) { return p.unit.type == "PSY" ? 2.25 : 1; }, + }, + 1525: { + atk: function(p) { + return p.unit.class.has("Slasher") ? Math.max(2.0, 3.25 - 0.0625 * p.turnCounter) : 1; + } + }, + 1526: { + atk: function(p) { return p.unit.type == "PSY" ? 1.75 : 1; }, + }, + 1527: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; }, + }, + 1528: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2.25 : 1; }, + }, + 1529: { + atk: function(p) { return p.slot == p.sourceSlot ? 3 : 1.5; } + }, + 1530: { + atk: function(p) { return p.slot == p.sourceSlot ? 3.5 : 1.75; } + }, + 1531: { + atk: function(p) { return p.percHP <= 30.0 ? 1.75 : p.percHP <= 50.0 ? 1.5 : 1; } + }, + 1532: { + atk: function(p) { return p.percHP <= 30.0 ? 1.75 : p.percHP <= 50.0 ? 1.5 : 1; } + }, + 1533: { + damageSorter: function(d) { return CrunchUtils.typeSort(d, 2.5, ["QCK"]); }, + hitAtk: function(p) { + return !p.unit.type == "QCK" ? 1 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect"]) ? 2.5 : 2; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"], + hp: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; } + }, + 1534: { + damageSorter: function(d) { return CrunchUtils.typeSort(d, 2.5, ["QCK"]); }, + hitAtk: function(p) { + return !p.unit.type == "QCK" ? 1 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect"]) ? 3 : 2.5; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"], + hp: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; } + }, + 1535: { + atk: function(p) { return !p.unit.type == "PSY" ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 2.5 : 1); } + }, + 1536: { + atk: function(p) { return !p.unit.type == "PSY" ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 3 : 1); } + }, + 1537: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Shooter") ? 1.2 : 1; } + }, + 1538: { + atk: function(p) { return p.unit.type == "STR" ? 2.5 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Shooter") ? 1.25 : 1; } + }, + 1539: { + atk: function(p) { return p.unit.cost <= 20 ? 1.5 : 1; }, + rcv: function(p) { return p.unit.cost <= 20 ? 1.5 : 1; } + }, + 1540: { + atk: function(p) { return p.unit.cost <= 30 ? 2.25 : 1; }, + rcv: function(p) { return p.unit.cost <= 30 ? 1.5 : 1; } + }, + 1541: { + damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['STR', 'DEX', 'QCK']); }, + hitAtk: function(p) { + return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ + type: 'STR', + minModifier: 'Good' + }, { + type: 'DEX', + minModifier: 'Good' + }, { + type: 'QCK', + minModifier: 'Good' + }]) ? 2 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1542: { + damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['STR', 'DEX', 'QCK']); }, + hitAtk: function(p) { + return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ + type: 'STR', + minModifier: 'Good' + }, { + type: 'DEX', + minModifier: 'Good' + }, { + type: 'QCK', + minModifier: 'Good' + }]) ? 2.5 : 1; + }, + rcv: function(p) { return 1.2; }, + hp: function(p) { return 1.2; }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1543: { + atk: function(p) { return !(p.unit.class.has("Shooter")) ? 1 : p.percHP <= 30.0 ? 1.75 : p.percHP <= 50.0 ? 1.5 : 1; } + }, + 1544: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.75 : 1; } + }, + 1545: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.25 : 1; } + }, + 1546: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Free Spirit") ? 1.2 : 1; } + }, + 1547: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Free Spirit") ? 1.3 : 1; } + }, + 1548: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; } + }, + 1549: { + atk: function(p) { return p.unit.type == "PSY" ? 2.25 : 1; }, + }, + 1550: { + atk: function(p) { return p.unit.type == "INT" ? 2.5 : 1; }, + }, + 1551: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2.5 : 1; } + }, + 1552: { + atk: function(p) { return p.unit.cost == 40 ? 2.5 : 1; }, + }, + 1553: { + atk: function(p) { return p.unit.cost == 40 ? 2.75 : 1; }, + }, + 1554: { + atk: function(p) { return p.unit.type == "DEX" ? 2 : 1; }, + }, + 1555: { + atk: function(p) { return p.unit.type == "DEX" ? 2.25 : 1; }, + }, + 1556: { + hp: function(p) { return p.unit.type == "STR" ? 2 : 1; }, + }, + 1557: { + atk: function(p) { + return p.unit.class.has("Striker") ? Math.max(1.0, 3.0 - 0.1 * p.turnCounter) : 1; + } + }, + 1558: { + atk: function(p) { + return p.unit.class.has("Shooter") ? Math.max(1.0, 3.0 - 0.1 * p.turnCounter) : 1; + } + }, + 1559: { + atk: function(p) { + return p.unit.class.has("Slasher") ? Math.max(1.0, 3.0 - 0.1 * p.turnCounter) : 1; + } + }, + 1560: { + atk: function(p) { + return p.unit.class.has("Fighter") ? Math.max(1.0, 3.0 - 0.1 * p.turnCounter) : 1; + } + }, + 1561: { + atk: function(p) { + return p.unit.type == "INT" ? Math.max(1.0, 3.0 - 0.1 * p.turnCounter) : 1; + } + }, + 1562: { + atk: function(p) { + return p.unit.class.has("Powerhouse") ? Math.max(1.5, 3.5 - 0.1 * p.turnCounter) : 1; + } + }, + 1563: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 4, [ "Fighter", "Powerhouse" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Fighter") && !p.unit.class.has("Powerhouse")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect", "Perfect"]) ? 2.1875 : 1.75; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1564: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 4, [ "Fighter", "Powerhouse" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Fighter") && !p.unit.class.has("Powerhouse")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect", "Perfect"]) ? 3 : 2; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1565: { + atk: function(p) { return 1.75; } + }, + 1566: { + atk: function(p) { return 2; } + }, + 1567: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 1568: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 1569: { + atk: function(p) { return 2.25; } + }, + 1570: { + atk: function(p) { return !(p.unit.class.has("Cerebral")) ? 1 : p.percHP <= 30.0 ? 2.75 : 2.5; }, + chainModifier: function(p) { return p.percHP <= 30.0 ? 1.5 : 1; } + }, + 1571: { + atk: function(p) { return !(p.unit.class.has("Cerebral")) ? 1 : p.percHP <= 30.0 ? 2.75 : 2.5; }, + chainModifier: function(p) { return p.percHP <= 30.0 ? 1.5 : 1; } + }, + 1572: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.2 : 1; } + }, + 1573: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.2 : 1; } + }, + 1574: { + atk: function(p) { return p.unit.type == "INT" ? 2.25 : 1; }, + }, + 1575: { + atk: function(p) { return p.unit.type == "INT" ? 2.5 : 1; }, + hp: function(p) { return p.unit.type == "INT" ? 1.25 : 1; } + }, + 1576: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 2.5 : 1; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1577: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 3.5 : 1; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1579: { + atk: function(p) { return 1.3; }, + rcv: function(p) { return 1.3; }, + hp: function(p) { return 1.3; }, + }, + 1580: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; }, + }, + 1581: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, + }, + 1582: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.2 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.2 : 1; }, + }, + 1583: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 1584: { + atk: function(p) { return !(p.unit.class.has("Striker")) ? 1 : p.percHP <= 30.0 ? 3 : 2.5; } + }, + 1585: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Driven") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Driven") ? 1.5 : 1; }, + }, + 1586: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Driven") ? 2 : 1; }, + rcv: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Driven") ? 1.5 : 1; }, + }, + 1587: { + atk: function(p) { return (p.slot == p.sourceSlot && p.actions[p.sourceSlot]) ? 6.25 : 2.5; }, + hp: function(p) { return 1.3 }, + }, + 1588: { + atk: function(p) { return (p.slot == p.sourceSlot && p.actions[p.sourceSlot]) ? 6.25 : 2.5; }, + hp: function(p) { return 1.3 }, + }, + 1589: { + chainModifier: function(p) { return 3; }, + }, + 1590: { + chainModifier: function(p) { return 3.5; }, + rcv: function(p) { return 1.2 }, + hp: function(p) { return 1.2 }, + }, + 1591: { + atk: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Free Spirit") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Free Spirit") ? 1.5 : 1; }, + }, + 1592: { + atk: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Free Spirit") ? 2.25 : 1; }, + rcv: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Free Spirit") ? 1.75 : 1; }, + }, + 1593: { + atk: function(p){ + return p.unit.class.has("Fighter") ? p.actions[p.sourceSlot] ? 4 : 2.5 : 1; + }, + }, + 1595: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2.25 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 1596: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; } + }, + 1597: { + atk: function(p) { return p.unit.type == "INT" ? 1.75 : 1; }, + rcv: function(p) { return p.unit.type == "INT" ? 1.75 : 1; } + }, + 1598: { + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 1599: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.75 : 1; } + }, + 1600: { + atk: function(p) { return p.unit.type == "INT" || p.unit.type == "PSY" ? 2.5 : 1; }, + }, + 1601: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 1602: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3, [ "Slasher" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Slasher")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 3 : 2; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1603: { + atk: function(p) { return p.unit.type == "STR" ? 2.25 : 1; }, + rcv: function(p) { return p.unit.type == "STR" ? 1.25 : 1; } + }, + 1604: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, + }, + 1605: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, + }, + 1606: {//BB Pirates FN Lafitte + atk: function(p) { return p.unit.type == "PSY" ? 1.75 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.75 : 1; }, + }, + 1607: {//BB Pirates FN Van Augur + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; }, + }, + 1608: {//BB Pirates FN Doc Q + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + }, + 1609: {//Enel TO DO + hp: function(p) { return 0.8 }, + atk: function(p) { return Math.max(2.0, 2.0 + 0.000125 * p.healCounter); }, + }, + 1610: {//Enel TO DO + hp: function(p) { return 0.8 }, + atk: function(p) { return Math.max(2.0, 2.0 + 0.000125 * p.healCounter); }, + }, + 1611: { + atk: function(p) {return p.unit.class.has("Shooter") ? 1.75 : 1; }, + hp: function(p) { return p.unit.class.has("Shooter") ? 1.2 : 1; }, + }, + 1612: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2.5 : 1; }, + hp: function(p) { return p.unit.class.has("Shooter") ? 1.2 : 1; }, + }, + 1613: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.25 : 1; }, + }, + 1614: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.5 : 1; }, + hp: function(p) { return p.unit.class.has("Fighter") ? 1.25 : 1; }, + }, + 1615: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; }, + }, + 1616: { + atk: function(p) { return p.unit.class.has("Striker") ? 2.5 : 1; }, + }, + 1617: { + atk: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "INT" ? 2 : 1; }, + }, + 1618: { + atk: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "INT" ? 2.5 : 1; }, + }, + 1619: { + chainModifier: function(p) { return 4; }, + hp: function(p) { return 1.2 }, + rcv: function(p) { return 1.2 }, + }, + 1620: { + atk: function(p) { return p.unit.class.has("Striker") && p.percHP <= 30.0 ? 2.5 : 1; } + }, + 1621: { + atk: function(p) { return !(p.unit.class.has("Striker")) ? 1 : p.percHP <= 30.0 ? 3 : 2.5; }, + hp: function(p) { return p.unit.class.has("Slasher") ? 1.2 : 1; } + }, + 1622: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 1623: { + hp: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; }, + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 1624: { + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.25 : 1; }, + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 1625: { + atk: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Powerhouse") ? 1.75 : 1; }, + }, + 1626: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 2.5, [ "Powerhouse" ]); }, + hitAtk: function(p) { + return !p.unit.class.has("Powerhouse") ? 1 : p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 2.5 : 1; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1627: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 : 1; } + }, + 1628: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Free Spirit") ? 2.25 : 1; }, + rcv: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Free Spirit") ? 1.5 : 1; }, + }, + 1629: { + hp: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; } + }, + 1630: { + hp: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 1631: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2.25 : 1; } + }, + 1632: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2.75 : 1; } + }, + 1633: { + atk: function(p) { return p.unit.type == "STR" ? 1.75 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.2 : 1; } + }, + 1634: { + hp: function(p) { return p.unit.type == "INT" ? 2 : 1; } + }, + 1635: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.5 : p.unit.class.has("Cerebral") ? 2 : 1; } + }, + 1636: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2 : 1; } + }, + 1637: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2.25: 1; } + }, + 1644: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 1645: { + atk: function(p) { + return p.unit.class.has("Slasher") && p.unit.type == "DEX" ? 1.96 : + p.unit.class.has("Slasher") && !p.unit.type == "DEX" ? 1.3 : + !p.unit.class.has("Slasher") && p.unit.type == "DEX" ? 1.5 : + 1; + } + }, + 1646: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 1647: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2.25 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 1648: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect"]) ? 2.4 : 1.2; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"], + }, + 1649: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect"]) ? 3 : 1.2; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"], + }, + 1650: { + atk: function(p) { return p.unit.type == "DEX" ? (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 3 : 1.5) : 1; }, + }, + 1651: { + atk: function(p) { return p.unit.class.has("Striker") ? (p.orb == 'meat' || p.orb == 'g') ? 1 : 3.75 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") ? 1.25 : 1; } + }, + 1652: { + atk: function(p) { return p.unit.class.has("Striker") ? (p.orb == 'meat' || p.orb == 'g') ? 1 : 3.75 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") ? 1.25 : 1; } + }, + 1653: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; } + }, + 1654: { + atk: function(p) { return p.unit.type == "INT" ? 2.5 : 1; } + }, + 1655: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 1656: { + atk: function(p) { return p.unit.type == "QCK" ? 2.25 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 1657: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Free Spirit") ? 2 : 1; } + }, + 1658: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Free Spirit") ? 2.5 : 1; } + }, + 1659: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } + }, + 1660: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2.5 : 1; } + }, + 1661: { + atk: function(p) { return p.unit.type == "PSY" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 2 : 1; }, + }, + 1662: { + atk: function(p) { return p.unit.type == "PSY" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 2.5 : 1; }, + }, + 1663: { + atk: function(p) { return !p.unit.class.has("Powerhouse") ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 3.5 : 2.5); }, + rcv: function(p) { return 0; } + }, + 1664: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2.5 : 1; } + }, + 1665: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3, [ "Shooter" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Shooter")) return 1; + return p.modifiers.slice(0, p.chainPosition) + .subcontains(["Perfect", "Perfect", "Perfect"]) ? 3.25 : 2.5; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1667: { + atk: function(p) { return !(p.unit.class.has("Striker")) ? 1 : p.percHP <= 30.0 ? 2.75 : 2.25; }, + hp: function(p) { return p.unit.class.has("Slasher") ? 1.2 : 1; } + }, + 1668: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 1669: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 1670: { + atk: function(p) { return p.unit.type == "DEX" ? 1.75 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; } + }, + 1671: { + rcv: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; } + }, + 1672: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 1673: { + atk: function(p) { return 1.75; } + }, + 1674: { + atk: function(p) { return 2.25; } + }, + 1675: { + chainModifier: function(p) { return 2; } + }, + 1676: { + chainModifier: function(p) { return 3.25; } + }, + 1677: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2.5 : 1; } + }, + 1678: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3.25, [ "Slasher" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Slasher")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 3.25 : 2.5; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1679: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 1680: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2.5 : 1; } + }, + 1681: { + atk: function(p) { return p.unit.cost <= 30 ? 2.5 : 1; } + }, + 1682: { + damageSorter: function(d) { return CrunchUtils.lowCostSort(d, 3.5, 30); }, + hitAtk: function(p) { + if (!(p.unit.cost <= 30)) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 3.5 : 2.5; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"], + hp: function(p) { return p.unit.cost <= 30 ? 1.3 : 1; } + }, + 1683: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.3 : 1; } + }, + 1684: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.3 : 1; } + }, + 1685: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 2.75, [ "Shooter" ]); }, + hitAtk: function(p) { + return !p.unit.class.has("Shooter") ? 1 : p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 2.75 : 1; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1686: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3.25, [ "Shooter" ]); }, + hitAtk: function(p) { + return !p.unit.class.has("Shooter") ? 1 : p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 3.25 : 1; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1687: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; }, + }, + 1688: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.5 : 1; }, + }, + 1689: { + damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['STR', 'DEX', 'INT']); }, + hitAtk: function(p) { + return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ + type: 'STR', + minModifier: 'Good' + }, { + type: 'DEX', + minModifier: 'Good' + }, { + type: 'INT', + minModifier: 'Good' + }]) ? 2.25 : 1.5; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1690: { + damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['STR', 'DEX', 'INT']); }, + hitAtk: function(p) { + return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ + type: 'STR', + minModifier: 'Good' + }, { + type: 'DEX', + minModifier: 'Good' + }, { + type: 'INT', + minModifier: 'Good' + }]) ? 3 : 2; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1691: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.75 : 1; } + }, + 1692: { + hp: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; } + }, + 1693: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; }, + }, + 1694: { + atk: function(p) { return p.unit.type == "PSY" ? 2.75 : 1; }, + }, + 1695: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; } + }, + 1696: { + atk: function(p) { return p.unit.class.has("Striker") ? 2.5 : 1; } + }, + 1697: { + atk: function(p) { if(p.colorCount.INT>=1 && p.colorCount.PSY>=1 && p.colorCount.STR>=1 && p.colorCount.DEX>=1 && p.colorCount.QCK>=1) + return 2.25; + else + return 1; + }, + hp: function(p) { if(p.colorCount.INT>=1 && p.colorCount.PSY>=1 && p.colorCount.STR>=1 && p.colorCount.DEX>=1 && p.colorCount.QCK>=1) + return 1.5; + else + return 1; + }, + }, + 1698: { + atk: function(p) { if(p.colorCount.INT>=1 && p.colorCount.PSY>=1 && p.colorCount.STR>=1 && p.colorCount.DEX>=1 && p.colorCount.QCK>=1) + return 2.25; + else + return 1; + }, + hp: function(p) { if(p.colorCount.INT>=1 && p.colorCount.PSY>=1 && p.colorCount.STR>=1 && p.colorCount.DEX>=1 && p.colorCount.QCK>=1) + return 1.5; + else + return 1; + }, + }, + 1699: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Fighter") ? 1.2 : 1; } + }, + 1700: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.5 : 1; }, + hp: function(p) { return p.unit.class.has("Fighter") ? 1.3 : 1; } + }, + 1701: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 : 1; }, + }, + 1702: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2.5 : 1; }, + }, + 1703: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; }, + }, + 1704: { + atk: function(p) { return p.unit.type == "INT" ? 2.5 : 1; }, + }, + 1705: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, + }, + 1706: { + damageSorter: function(d) { return CrunchUtils.typeSort(d, 2.625, ["STR"]); }, + hitAtk: function(p) { + return !p.unit.type == "STR" ? 1 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 3.125 : 2.5; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"], + }, + 1707: { + atk: function(p) { return p.unit.type == "PSY" ? 2.75 : 1; }, + hp: function(p) { return p.unit.type == "PSY" ? 1.3 : 1; }, + }, + 1709: { + atk: function(p) { return 1.5; }, + }, + 1710: { + atk: function(p) { return !p.unit.class.has("Cerebral") ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 3 : 1.5); }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.2 : 1; } + }, + 1711: { + atk: function(p) { return !p.unit.class.has("Cerebral") ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 3 : 1.5); }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.2 : 1; } + }, + 1712: { + atk: function(p) { return p.unit.class.has("Driven") ? 2.5 : 1; } + }, + 1713: { + atk: function(p) { return p.unit.class.has("Driven") ? Math.min(3.25, 2.5 + 0.25 * p.turnCounter) : 1; } + }, + 1714: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; }, + }, + 1715: { + atk: function(p) { return !p.unit.class.has("Striker") ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 2.5 : 2); }, + }, + 1716: { + atk: function(p) { + return p.unit.class.has("Driven") ? Math.min(3, 1.2 + 0.1 * p.turnCounter) : 1; + } + }, + 1718: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 2.5, [ "Driven" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Driven")) return 1; + return p.modifiers.slice(0, p.chainPosition).count("Perfect") == p.chainPosition ? 2.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1719: { + atk: function(p) { return p.unit.type != "PSY" ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 2 : 1); } + }, + 1720: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.5 : 1; } + }, + 1721: { + atk: function(p) { return !p.unit.class.has("Fighter") ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 2.75 : 2.5); }, + hp: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; } + }, + 1722: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2 : 1; } + }, + 1723: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2 : 1; }, + rcv: function(p) { return p.unit.class.has("Powerhouse") ? 1.2 : 1; } + }, + 1724: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 1725: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 1726: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 2.75, [ "Free Spirit" ]); }, + hitAtk: function(p) { + return !p.unit.class.has("Free Spirit") ? 1 : p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 2.75 : 1; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1727: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3.5, [ "Free Spirit" ]); }, + hitAtk: function(p) { + return !p.unit.class.has("Free Spirit") ? 1 : p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 3.5 : 1; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1728: { + atk: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 2 : 1; }, + }, + 1729: { + atk: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 2.25 : 1; }, + hp: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 1.25 : 1; }, + }, + 1730: { + atk: function(p) { return 2; }, + }, + 1731: { + atk: function(p) { return 2; }, + }, + 1732: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Powerhouse") ? 1.1 : 1; }, + }, + 1733: { + atk: function(p) { return p.unit.type == "STR" ? 2.5 : 1; }, + hp: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Powerhouse") ? 1.25 : 1; }, + }, + 1734: { + atk: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Cerebral") ? 1.5 : 1; }, + }, + 1735: { + atk: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Cerebral") ? 1.75 : 1; }, + }, + 1736: { + atk: function(p) { return p.unit.type == "INT" ? 2.25 : 1; }, + }, + 1737: { + atk: function(p) { return p.unit.type == "INT" ? 2.25 : 1; }, + hp: function(p) { return p.unit.type == "INT" ? 1.2 : 1; }, + }, + 1738: { + atk: function(p) { return p.unit.class.has("Driven") ? 2 : 1; }, + }, + 1739: { + atk: function(p) { return p.unit.class.has("Driven") ? 2.5 : 1; }, + }, + 1740: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Powerhouse") ? 2 : 1; }, + hp: function(p) { return p.unit.type == "DEX" ? 1.1 : 1; }, + }, + 1741: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Powerhouse") ? 2.5 : 1; }, + hp: function(p) { return p.unit.type == "DEX" ? 1.3 : 1; }, + }, + 1742: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Powerhouse") ? 2 : 1; }, + hp: function(p) { return p.unit.type == "STR" ? 1.1 : 1; }, + }, + 1743: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Powerhouse") ? 2.5 : 1; }, + hp: function(p) { return p.unit.type == "STR" ? 1.3 : 1; }, + }, + 1744: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; }, + }, + 1745: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; }, + }, + 1746: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3.25, [ "Shooter" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has('Shooter')) return 1; + var prev = p.modifiers.slice(p.chainPosition - 1, p.chainPosition)[0]; + return p.chainPosition === 0 ? 2.5 : (prev == 'Good' ? 2.75 : (prev == 'Great' ? 3 : (prev == 'Perfect' ? 3.25 : 2.5))); + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1747: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3.25, [ "Shooter" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has('Shooter')) return 1; + var prev = p.modifiers.slice(p.chainPosition - 1, p.chainPosition)[0]; + return p.chainPosition === 0 ? 2.5 : (prev == 'Good' ? 2.75 : (prev == 'Great' ? 3 : (prev == 'Perfect' ? 3.25 : 2.5))); + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1748: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, + hp: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 1749: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, + hp: function(p) { return p.unit.type == "QCK" ? 2 : 1; } + }, + 1750: { + atk: function(p) { return p.unit.class.has("Striker") ? 3 : 1; } + }, + 1751: { + atk: function(p) { return p.unit.class.has("Striker") ? 3 : 1; } + }, + 1752: { + atk: function(p) { return p.unit.cost <= 30 ? 2.5 : 1; } + }, + 1753: { + damageSorter: function(d) { return CrunchUtils.lowCostSort(d, 3.5, 30); }, + hitAtk: function(p) { + if (!(p.unit.cost <= 30)) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 3.5 : 2.5; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"], + hp: function(p) { return p.unit.cost <= 30 ? 1.3 : 1; } + }, + 1754: { + atk: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Powerhouse") ? 2 : 1; }, + }, + 1755: { + atk: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Powerhouse") ? 2.5 : 1; }, + hp: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Powerhouse") ? 1.2 : 1; }, + }, + 1758: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Free Spirit") ? 1.1 : 1; }, + }, + 1759: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2.5 : 1; }, + hp: function(p) { return p.unit.class.has("Free Spirit") ? 1.2 : 1; }, + }, + 1760: { + atk: function(p) { return p.unit.type == "DEX" || p.unit.type == "INT" ? 2 : 1; }, + }, + 1761: { + atk: function(p) { return p.unit.type == "DEX" || p.unit.type == "INT" ? 2.5 : 1; }, + }, + 1762: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 4.026275, [ "Powerhouse" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Powerhouse")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect", "Perfect"]) ? 4.026275 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect"]) ? 3.66025 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 3.3275 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect"]) ? 3.025 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect"]) ? 2.75 : 2.5; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"], + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.2 : 1; }, + rcv: function(p) { return 0.5; }, + }, + 1763: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 4.026275, [ "Powerhouse" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Powerhouse")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect", "Perfect"]) ? 4.026275 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect"]) ? 3.66025 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 3.3275 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect"]) ? 3.025 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect"]) ? 2.75 : 2.5; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"], + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.2 : 1; }, + rcv: function(p) { return 0.5; }, + }, + 1764: { + atk: function(p) { + return Math.min(3.5, 2.25 + 0.25 * p.turnCounter); + }, + hp: function(p) { return 1.25; } + }, + 1765: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, + }, + 1766: { + chainModifier: function(p) { return 1.5; }, + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, + }, + 1767: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.75 : 1; }, + }, + 1767: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Slasher") ? 1.5 : 1; }, + }, + 1769: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2.5 : 1; }, + }, + 1770: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3.25, [ "Cerebral" ]); }, + hitAtk: function(p) { + return !p.unit.class.has("Cerebral") ? 1 : p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 3.25 : 2.5; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"], + hp: function(p) { return p.unit.class.has("Cerebral") ? 1.2 : 1; } + }, + 1771: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Cerebral") ? 2 : 1; } + }, + 1772: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Cerebral") ? 2 : 1; } + }, + 1773: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 : 1; }, + hp: function(p) { return p.unit.class.has("Free Spirit") ? 1.2 : 1; } + }, + 1774: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2.25 : 1; }, + hp: function(p) { return p.unit.class.has("Free Spirit") ? 1.25 : 1; } + }, + 1775: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; } + }, + 1776: { + atk: function(p) { return p.unit.type == "QCK" ? 1.75 : 1; }, + rcv: function(p) { return p.unit.type == "QCK" ? 1.75 : 1; } + }, + 1778: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2.5 : 1; }, + hp: function(p) { return p.unit.class.has("Free Spirit") ? 1.2 : 1; } + }, + 1779: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; } + }, + 1780: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2.25 : 1; }, + hp: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 1781: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.75 : 1; } + }, + 1782: { + atk: function(p) { return p.unit.type == "2.25" ? 1.75 : 1; }, + }, + 1783: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; } + }, + 1784: { + atk: function(p) { return p.unit.stars <= 4 ? 2.5 : 1; } + }, + 1791: { + damageSorter: function(d) { return CrunchUtils.typeSort(d, 2.5, [ "QCK", "STR", "DEX" ]); }, + hitAtk: function(p) { + return !(p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK") ? 1 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"], + }, + 1792: { + damageSorter: function(d) { return CrunchUtils.typeSort(d, 3.25, [ "QCK", "STR", "DEX" ]); }, + hitAtk: function(p) { + return !(p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK") ? 1 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 3.25 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"], + }, + 1793: { + atk: function(p) { + if(p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK"){ + if(p.colorCount.INT==0 && p.colorCount.PSY==0 && p.colorCount.STR>=1 && p.colorCount.DEX>=1 && p.colorCount.QCK>=1) + return 3.7125; + else if(p.colorCount.STR>=1 && p.colorCount.DEX>=1 && p.colorCount.QCK>=1) + return 2.75; + else if(p.colorCount.INT==0 && p.colorCount.PSY==0) + return 1.35; + else + return 1; + } + else + return 1; + }, + hp: function(p) { + if(p.colorCount.STR>=1 && p.colorCount.DEX>=1 && p.colorCount.QCK>=1) + return 1.3; + else + return 1; + }, + }, + 1794: { + atk: function(p) { + if(p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK"){ + if(p.colorCount.INT==0 && p.colorCount.PSY==0 && p.colorCount.STR>=1 && p.colorCount.DEX>=1 && p.colorCount.QCK>=1) + return 3.7125; + else if(p.colorCount.STR>=1 && p.colorCount.DEX>=1 && p.colorCount.QCK>=1) + return 2.75; + else if(p.colorCount.INT==0 && p.colorCount.PSY==0) + return 1.35; + else + return 1; + } + else + return 1; + }, + hp: function(p) { + if(p.colorCount.STR>=1 && p.colorCount.DEX>=1 && p.colorCount.QCK>=1) + return 1.3; + else + return 1; + }, + }, + 1795: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Driven") ? 2 : 1; }, + }, + 1796: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Driven") ? 2.5 : 1; }, + }, + 1797: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.25 : 1; } + }, + 1798: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.5 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") || p.unit.class.has("Driven") ? 1.25 : 1; }, + }, + 1799: { + atk: function(p) { return (p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK") ? 2.25 : 1; } + }, + 1800: { + atk: function(p) { return (p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK") ? 2.5 : 1; }, + rcv: function(p) { return (p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK") ? 1.2 : 1; } + }, + 1801: { + atk: function(p) { return (p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK") ? 2 : 1; } + }, + 1802: { + atk: function(p) { return (p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK") ? 2.5 : 1; } + }, + 1803: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; }, + }, + 1804: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2.25 : 1; }, + hp: function(p) { return p.unit.class.has("Slasher") ? 1.3 : 1; }, + }, + 1805: { + atk: function(p) { return p.unit.cost <= 30 ? 1.5 : 1; }, + hp: function(p) { return p.unit.cost <= 30 ? 1.2 : 1; }, + }, + 1806: { + atk: function(p) { return p.unit.cost <= 30 ? 2.25 : 1; }, + hp: function(p) { return p.unit.cost <= 30 ? 1.2 : 1; }, + }, + 1807: { + atk: function(p){ + var specialEnabled = false; + for(var i=0;i<2;i++) + { + if(window.specials[1807].turnedOn[i]==true){specialEnabled = true;} + if(window.specials[1808].turnedOn[i]==true){specialEnabled = true;} + } + return p.unit.class.has("Slasher") ? specialEnabled ? 1.35 : 1 : 1; + }, + }, + 1808: { + atk: function(p){ + var specialEnabled = false; + for(var i=0;i<2;i++) + { + if(window.specials[1807].turnedOn[i]==true){specialEnabled = true;} + if(window.specials[1808].turnedOn[i]==true){specialEnabled = true;} + } + if(p.unit.class.has("Slasher")){ + if(p.actions[p.sourceSlot]){ + if (specialEnabled){ + return 3.5; + } else { + return 2.5; + } + } else { + if (specialEnabled){ + return 1.62; + } else { + return 1.2; + } + } + }else{ + return 1; + } + // return p.unit.class.has("Slasher") ? specialEnabled ? 1.62 : 1.2 : 1; + }, + hp: function(p) { return p.actions[p.sourceSlot] ? 1.3 : 1.1 } + }, + 1809: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect"]) ? 2.25 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1810: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect"]) ? 2.25 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1811: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; }, + }, + 1812: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.25 : 1; }, + }, + 1813: { + atk: function(p) { return 2.25; } + }, + 1814: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 2.5, [ "Powerhouse" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Powerhouse")) return 1; + return p.modifiers.slice(0, p.chainPosition).count("Perfect") == p.chainPosition ? 2.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1815: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 2.75, [ "Powerhouse" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Powerhouse")) return 1; + return p.modifiers.slice(0, p.chainPosition).count("Perfect") == p.chainPosition ? 2.75 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1816: { + atk: function(p) { return !p.unit.class.has("Shooter") ? 1 : (((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 3.25 : 2.25); }, + hp: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; } + }, + 1817: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Great", "Great", "Great"]) ? 2 : 1; + }, + hitModifiers: ["Great", "Great", "Great", "Perfect", "Perfect", "Perfect"], + }, + 1818: { + hitAtk: function(p) { + return p.modifiers.slice(0, p.chainPosition).subcontains(["Great", "Great", "Great"]) ? 2.5 : 1.5; + }, + hitModifiers: ["Great", "Great", "Great", "Perfect", "Perfect", "Perfect"], + hp: function(p) { return 1.2; }, + }, + 1819: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Powerhouse") ? 1.75 : 1; }, + }, + 1820: { + hp: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, + }, + 1821: { + atk: function(p) { return 1.5; } + }, + 1822: { + atk: function(p) { return 2; } + }, + 1823: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3.543122, [ "Shooter" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Shooter")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect", "Perfect"]) ? 3.543122 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect"]) ? 3.22102 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.9282 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect"]) ? 2.662 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect"]) ? 2.42 : 2.2; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"], + }, + 1824: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 3.543122, [ "Shooter" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Shooter")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect", "Perfect"]) ? 3.543122 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect"]) ? 3.22102 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.9282 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect"]) ? 2.662 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect"]) ? 2.42 : 2.2; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"], + }, + 1825: { + damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['INT', 'INT', 'INT']); }, + hitAtk: function(p) { + return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ + type: 'INT', + minModifier: 'Good' + }, { + type: 'INT', + minModifier: 'Good' + }, { + type: 'INT', + minModifier: 'Good' + }]) ? 2.5 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1826: { + damageSorter: function(d) { return CrunchUtils.okamaSort(d, ['INT', 'INT', 'INT']); }, + hitAtk: function(p) { + return CrunchUtils.okamaCheck(p.damage.slice(0, p.chainPosition), p.modifiers, [{ + type: 'INT', + minModifier: 'Good' + }, { + type: 'INT', + minModifier: 'Good' + }, { + type: 'INT', + minModifier: 'Good' + }]) ? 3 : 1; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1827: { + atk: function(p) { return !(p.unit.type == "INT") ? 1 : p.percHP <= 30.0 ? 3 : 2.5; } + }, + 1828: { + atk: function(p) { return !(p.unit.type == "INT") ? 1 : p.percHP <= 30.0 ? 3 : 2.5; } + }, + 1829: { + atk: function(p) { return p.unit.class.has("Cerebral") || p.unit.class.has("Driven") ? 2 : 1; }, + }, + 1830: { + atk: function(p) { return p.unit.class.has("Cerebral") || p.unit.class.has("Driven") ? 2.5 : 1; }, + }, + 1831: { + atk: function(p) { + if(p.colorCount.INT>=1 && p.colorCount.PSY>=1 && p.colorCount.STR>=1 && p.colorCount.DEX>=1 && p.colorCount.QCK>=1){ + return ((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 3.9375 : 2.25; + } + else + return 1; + }, + hp: function(p) { return 1.25; } + }, + 1832: { + atk: function(p) { + if(p.colorCount.INT>=1 && p.colorCount.PSY>=1 && p.colorCount.STR>=1 && p.colorCount.DEX>=1 && p.colorCount.QCK>=1){ + return ((CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) == 2) && (p.orb != 'g')) ? 3.9375 : 2.25; + } + else + return 1; + }, + hp: function(p) { return 1.25; } + }, + 1833: { + atk: function(p) { + return p.unit.class.has("Powerhouse") && p.unit.type == "INT" ? 2.1 : + !p.unit.class.has("Powerhouse") && p.unit.type == "INT" ? 1.75 : + p.unit.class.has("Powerhouse") && !p.unit.type == "INT" ? 1.2 : + 1; + }, + rcv: function(p) { return p.unit.class.has("Powerhouse") ? 1.1 : 1; }, + }, + 1834: { + atk: function(p) { + return p.unit.class.has("Powerhouse") && p.unit.type == "INT" ? 2.925 : + !p.unit.class.has("Powerhouse") && p.unit.type == "INT" ? 2.25 : + p.unit.class.has("Powerhouse") && !p.unit.type == "INT" ? 1.3 : + 1; + }, + rcv: function(p) { return p.unit.class.has("Powerhouse") ? 1.2 : 1; }, + }, + 1835: { + atk: function(p) { + return p.unit.class.has("Powerhouse") && p.unit.type == "STR" ? 2.1 : + !p.unit.class.has("Powerhouse") && p.unit.type == "STR" ? 1.75 : + p.unit.class.has("Powerhouse") && !p.unit.type == "STR" ? 1.2 : + 1; + }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.2 : 1; }, + }, + 1836: { + atk: function(p) { + return p.unit.class.has("Powerhouse") && p.unit.type == "STR" ? 2.925 : + !p.unit.class.has("Powerhouse") && p.unit.type == "STR" ? 2.25 : + p.unit.class.has("Powerhouse") && !p.unit.type == "STR" ? 1.3 : + 1; + }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.2 : 1; }, + }, + 1837: { + atk: function(p) { + return p.unit.class.has("Powerhouse") && p.unit.type == "QCK" ? 2.1 : + !p.unit.class.has("Powerhouse") && p.unit.type == "QCK" ? 1.75 : + p.unit.class.has("Powerhouse") && !p.unit.type == "QCK" ? 1.2 : + 1; + }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.2 : 1; }, + }, + 1838: { + atk: function(p) { + return p.unit.class.has("Powerhouse") && p.unit.type == "QCK" ? 2.925 : + !p.unit.class.has("Powerhouse") && p.unit.type == "QCK" ? 2.25 : + p.unit.class.has("Powerhouse") && !p.unit.type == "QCK" ? 1.3 : + 1; + }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.2 : 1; }, + }, + 1839: { + atk: function(p) { + return p.unit.class.has("Powerhouse") && p.unit.type == "DEX" ? 2.1 : + !p.unit.class.has("Powerhouse") && p.unit.type == "DEX" ? 1.75 : + p.unit.class.has("Powerhouse") && !p.unit.type == "DEX" ? 1.2 : + 1; + }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.2 : 1; }, + }, + 1840: { + atk: function(p) { + return p.unit.class.has("Powerhouse") && p.unit.type == "DEX" ? 2.925 : + !p.unit.class.has("Powerhouse") && p.unit.type == "DEX" ? 2.25 : + p.unit.class.has("Powerhouse") && !p.unit.type == "DEX" ? 1.3 : + 1; + }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.2 : 1; }, + }, + 1841: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; }, + }, + 1842: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; }, + }, + 1843: { + atk: function(p) { return p.unit.class.has("Driven") || p.unit.class.has("Striker") ? 1.5 : 1; }, + }, + 1844: { + atk: function(p) { return p.unit.class.has("Driven") || p.unit.class.has("Striker") ? 1.75 : 1; }, + }, + 1845: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.5 : 1; }, + }, + 1846: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2.75 : 1; }, + }, + 1847: { + atk: function(p) { + + if(p.unit.cost <= 29){ + return 3.25; + }else if(p.unit.cost == 54){ + return 3; + }else{ + return 1; + } + }, + hp: function(p) { return p.unit.cost <= 29 ? 1.2 : 1; }, + }, + 1848: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2 : 1; }, + }, + 1849: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2.25 : 1; }, + hp: function(p) { return p.unit.class.has("Powerhouse") ? 1.3 : 1; }, + }, + 1850: { + atk: function(p) { return p.unit.class.has("Driven") ? 2 : 1; }, + }, + 1851: { + atk: function(p) { return p.unit.class.has("Driven") ? 2.25 : 1; }, + hp: function(p) { return p.unit.class.has("Driven") ? 1.3 : 1; }, + }, + 1853: { + atk: function(p) { + return (1 + 1.25 * ((100 - p.percHP) / 100)); + }, + hp: function(p) { return 1.2; }, + }, + 1854: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2 : 1; }, + }, + 1855: { + damageSorter: function(d) { return CrunchUtils.classSort(d, 4, [ "Free Spirit" ]); }, + hitAtk: function(p) { + if (!p.unit.class.has("Free Spirit")) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect", "Perfect", "Perfect"]) ? 3 : p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.5 : 2; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"] + }, + 1856: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2 : 1; }, + }, + 1857: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2.5 : 1; }, + }, + 1858: { + hitAtk: function(p) { + if (!(p.unit.class.has("Striker"))) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 2.4 : 2; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"], + }, + 1859: { + hitAtk: function(p) { + if (!(p.unit.class.has("Striker"))) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Perfect", "Perfect", "Perfect"]) ? 3.25 : 2.5; + }, + hitModifiers: ["Perfect", "Perfect", "Perfect", "Perfect", "Perfect", "Perfect"], + hp: function(p) { return p.unit.class.has("Striker") ? 1.2 : 1; } + }, + 1861: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2.5 : 1; }, + }, + 1863: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 2.5 : 1; }, + }, + 1869: { + hitAtk: function(p) { + if (!(p.unit.class.has("Slasher"))) return 1; + return p.modifiers.slice(0, p.chainPosition).subcontains(["Good", "Great", "Perfect"]) ? 4.225 : 3.25; + }, + hitModifiers: ["Good", "Great", "Perfect", "Perfect", "Perfect", "Perfect"], + hp: function(p) { return p.unit.class.has("Slasher") ? 1.2 : 1; } + }, + 1871: { + atk: function(p) { return p.unit.class.has("Driven") ? 2.25 : 1; } + }, + 1873: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Slasher") ? 2.25 : 1; } + }, + 1877: { + atk: function(p) { return p.unit.class.has("Slasher") ? 2 : 1; } + }, + 2000: { + atk: function(p) { return p.unit.class.has("Cerebral") || p.unit.class.has("Slasher") ? 2 : 1; }, + }, + 2001: { + atk: function(p) { return p.unit.class.has("Cerebral") || p.unit.class.has("Slasher") ? 2.5 : 1; }, + }, +}; diff --git a/common/data/cooldowns.js b/common/data/cooldowns.js index 38da79c9c..a05aa1906 100644 --- a/common/data/cooldowns.js +++ b/common/data/cooldowns.js @@ -1,922 +1,2003 @@ window.cooldowns = [ - [ 3, 2 ], - [ 12, 9 ], - [ 23, 15 ], - [ 25, 18 ], - [ 12, 9 ], - [ 15, 10 ], - [ 15, 10 ], - [ 25, 20 ], - [ 12, 7 ], - [ 23, 15 ], - [ 15, 8 ], - [ 25, 20 ], - [ 15, 10 ], - [ 15, 10 ], - [ 15, 10 ], - [ 20, 15 ], - [ 23, 15 ], - [ 15, 10 ], - [ 23, 15 ], - [ 15, 10 ], - [ 15, 8 ], - [ 23, 15 ], - [ 15, 8 ], - [ 15, 10 ], - [ 25, 15 ], - [ 22, 15 ], - [ 40, 15 ], - [ 40, 15 ], - [ 15, 9 ], - [ 15, 9 ], - null, - [ 13, 7 ], - null, - [ 25, 20 ], - [ 15, 9 ], - [ 15, 10 ], - [ 15, 10 ], - [ 13, 7 ], - [ 13, 7 ], - [ 18, 8 ], - [ 13, 7 ], - [ 10, 5 ], - [ 13, 7 ], - [ 13, 7 ], - [ 15, 8 ], - [ 15, 8 ], - [ 15, 7 ], - [ 18, 8 ], - [ 40, 15 ], - [ 15, 10 ], - null, - [ 13, 7 ], - null, - [ 15, 9 ], - null, - [ 13, 7 ], - [ 15, 9 ], - [ 15, 12 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 8 ], - [ 15, 9 ], - null, - [ 15, 10 ], - [ 15, 9 ], - [ 23, 15 ], - [ 25, 18 ], - [ 25, 18 ], - [ 22, 15 ], - [ 22, 15 ], - [ 17, 10 ], - [ 12, 6 ], - [ 12, 6 ], - [ 25, 18 ], - [ 25, 20 ], - [ 25, 20 ], - [ 25, 20 ], - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - [ 40, 15 ], - [ 35, 10 ], - [ 40, 15 ], - [ 25, 10 ], - [ 15, 7 ], - [ 25, 10 ], - [ 40, 15 ], - [ 40, 15 ], - [ 15, 10 ], - [ 15, 7 ], - [ 15, 7 ], - [ 40, 15 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 40, 15 ], - [ 35, 10 ], - [ 15, 10 ], - [ 15, 7 ], - [ 15, 7 ], - [ 35, 10 ], - [ 25, 10 ], - [ 40, 15 ], - [ 25, 10 ], - [ 15, 7 ], - [ 25, 10 ], - [ 40, 15 ], - [ 40, 15 ], - [ 15, 10 ], - [ 15, 7 ], - [ 15, 7 ], - [ 40, 15 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 40, 15 ], - [ 35, 10 ], - [ 15, 10 ], - [ 15, 7 ], - [ 15, 7 ], - [ 35, 10 ], - [ 25, 10 ], - [ 15, 7 ], - [ 15, 7 ], - [ 12, 8 ], - [ 12, 8 ], - [ 12, 8 ], - [ 12, 8 ], - [ 12, 8 ], - [ 25, 10 ], - [ 25, 10 ], - [ 25, 10 ], - [ 25, 10 ], - [ 25, 10 ], - [ 40, 15 ], - [ 40, 15 ], - [ 40, 15 ], - [ 35, 10 ], - [ 15, 7 ], - [ 12, 8 ], - [ 15, 7 ], - [ 12, 8 ], - [ 15, 7 ], - [ 15, 7 ], - [ 12, 8 ], - [ 15, 7 ], - [ 12, 8 ], - [ 15, 7 ], - null, - null, - null, - null, - null, - [ 15, 7 ], - [ 12, 8 ], - [ 15, 7 ], - [ 12, 8 ], - [ 15, 7 ], - [ 15, 11 ], - [ 20, 14 ], - null, - [ 15, 6 ], - null, - [ 13, 9 ], - null, - [ 15, 10 ], - null, - [ 13, 7 ], - [ 17, 8 ], - [ 17, 12 ], - null, - [ 15, 10 ], - [ 20, 15 ], - [ 20, 15 ], - [ 15, 12 ], - [ 22, 15 ], - [ 25, 20 ], - [ 15, 8 ], - [ 25, 18 ], - [ 13, 7 ], - [ 13, 7 ], - [ 17, 8 ], - [ 17, 12 ], - [ 15, 11 ], - [ 20, 11 ], - [ 32, 17 ], - [ 32, 17 ], - [ 15, 9 ], - [ 13, 7 ], - [ 10, 5 ], - [ 22, 14 ], - [ 22, 14 ], - null, - [ 15, 8 ], - null, - [ 20, 11 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 10, 10 ], - [ 30, 15 ], - [ 30, 15 ], - [ 30, 20 ], - [ 30, 20 ], - [ 15, 8 ], - [ 15, 8 ], - [ 15, 10 ], - [ 15, 10 ], - [ 20, 10 ], - [ 20, 10 ], - [ 20, 10 ], - [ 20, 10 ], - [ 25, 17 ], - [ 25, 17 ], - null, - [ 17, 10 ], - null, - [ 17, 11 ], - null, - [ 15, 10 ], - [ 22, 15 ], - [ 40, 15 ], - [ 25, 10 ], - [ 15, 7 ], - [ 25, 10 ], - [ 40, 15 ], - [ 40, 15 ], - [ 15, 10 ], - [ 15, 7 ], - [ 15, 7 ], - [ 40, 15 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 40, 15 ], - [ 35, 10 ], - [ 15, 10 ], - [ 15, 7 ], - [ 15, 7 ], - [ 35, 10 ], - [ 25, 10 ], - [ 25, 18 ], - [ 18, 8 ], - [ 18, 8 ], - [ 25, 10 ], - [ 40, 15 ], - [ 15, 10 ], - [ 20, 12 ], - [ 20, 12 ], - [ 25, 18 ], - [ 21, 16 ], - null, - null, - null, - null, - null, - [ 28, 13 ], - [ 28, 13 ], - [ 18, 10 ], - [ 18, 10 ], - [ 23, 15 ], - [ 23, 15 ], - [ 35, 25 ], - [ 35, 25 ], - [ 25, 18 ], - [ 25, 18 ], - [ 20, 10 ], - [ 20, 10 ], - [ 25, 18 ], - [ 25, 18 ], - [ 20, 15 ], - [ 20, 15 ], - [ 25, 18 ], - [ 25, 18 ], - [ 17, 10 ], - [ 17, 10 ], - [ 14, 10 ], - [ 22, 16 ], - [ 22, 16 ], - [ 20, 15 ], - [ 20, 15 ], - null, - null, - [ 16, 10 ], - [ 20, 15 ], - [ 12, 8 ], - [ 12, 8 ], - [ 14, 6 ], - [ 14, 6 ], - [ 14, 6 ], - [ 14, 6 ], - [ 25, 18 ], - [ 25, 18 ], - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - [ 30, 16 ], - [ 30, 16 ], - [ 22, 15 ], - [ 22, 15 ], - [ 11, 6 ], - [ 11, 6 ], - [ 20, 12 ], - [ 20, 12 ], - [ 28, 20 ], - [ 28, 20 ], - [ 13, 8 ], - [ 13, 8 ], - [ 20, 10 ], - [ 20, 10 ], - [ 23, 18 ], - [ 23, 18 ], - [ 25, 12 ], - [ 25, 12 ], - [ 25, 12 ], - [ 25, 12 ], - [ 25, 12 ], - [ 25, 12 ], - [ 25, 12 ], - [ 25, 12 ], - [ 25, 12 ], - [ 25, 12 ], - [ 10, 5 ], - [ 15, 10 ], - [ 15, 10 ], - [ 25, 10 ], - [ 15, 10 ], - [ 17, 12 ], - [ 17, 12 ], - [ 20, 10 ], - [ 20, 10 ], - [ 25, 18 ], - [ 25, 18 ], - [ 17, 8 ], - [ 17, 8 ], - [ 23, 14 ], - [ 23, 14 ], - [ 38, 18 ], - [ 17, 8 ], - [ 15, 8 ], - [ 15, 8 ], - [ 25, 20 ], - [ 25, 20 ], - [ 15, 8 ], - [ 15, 8 ], - [ 18, 12 ], - [ 18, 12 ], - [ 20, 20 ], - [ 23, 14 ], - [ 23, 14 ], - [ 30, 15 ], - [ 20, 10 ], - [ 23, 18 ], - [ 11, 6 ], - [ 11, 6 ], - [ 20, 14 ], - [ 20, 14 ], - [ 20, 10 ], - [ 20, 10 ], - [ 17, 13 ], - [ 17, 13 ], - [ 28, 14 ], - [ 28, 14 ], - [ 15, 15 ], - [ 23, 13 ], - [ 20, 10 ], - [ 20, 10 ], - [ 24, 15 ], - [ 24, 15 ], - [ 35, 18 ], - [ 17, 12 ], - [ 21, 16 ], - [ 20, 15 ], - [ 20, 15 ], - [ 14, 9 ], - [ 14, 9 ], - [ 25, 18 ], - [ 16, 6 ], - [ 21, 11 ], - [ 12, 8 ], - [ 12, 8 ], - [ 18, 18 ], - [ 18, 18 ], - [ 16, 16 ], - [ 16, 16 ], - null, - null, - null, - null, - [ 26, 17 ], - [ 30, 15 ], - [ 30, 15 ], - [ 16, 10 ], - [ 16, 10 ], - [ 25, 18 ], - [ 25, 18 ], - [ 16, 10 ], - [ 16, 10 ], - [ 25, 18 ], - [ 25, 18 ], - [ 18, 10 ], - [ 18, 10 ], - [ 28, 19 ], - [ 28, 19 ], - [ 14, 10 ], - [ 25, 15 ], - [ 25, 15 ], - [ 25, 20 ], - [ 20, 15 ], - [ 25, 18 ], - [ 15, 10 ], - [ 15, 10 ], - [ 25, 16 ], - [ 18, 10 ], - [ 25, 16 ], - [ 18, 10 ], - [ 20, 15 ], - [ 20, 15 ], - [ 25, 15 ], - [ 25, 15 ], - [ 20, 10 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 25, 15 ], - [ 25, 15 ], - [ 25, 15 ], - [ 25, 15 ], - [ 25, 15 ], - [ 25, 15 ], - [ 20, 15 ], - [ 20, 15 ], - [ 20, 15 ], - [ 20, 15 ], - [ 11, 11 ], - [ 11, 11 ], - [ 13, 9 ], - [ 13, 9 ], - [ 21, 16 ], - [ 21, 16 ], - [ 20, 15 ], - [ 20, 15 ], - [ 21, 15 ], - [ 21, 15 ], - [ 25, 18 ], - [ 25, 18 ], - [ 24, 14 ], - [ 24, 14 ], - [ 22, 17 ], - [ 15, 15 ], - [ 15, 15 ], - [ 14, 14 ], - [ 24, 11 ], - [ 24, 11 ], - [ 10, 5 ], - [ 10, 5 ], - [ 25, 18 ], - [ 25, 18 ], - [ 23, 17 ], - [ 23, 17 ], - [ 23, 16 ], - [ 23, 16 ], - [ 23, 16 ], - [ 23, 16 ], - [ 23, 17 ], - [ 23, 17 ], - [ 25, 20 ], - [ 25, 20 ], - [ 16, 16 ], - [ 16, 16 ], - [ 18, 18 ], - [ 18, 18 ], - [ 16, 16 ], - [ 16, 16 ], - [ 25, 16 ], - [ 25, 16 ], - [ 50, 20 ], - [ 16, 12 ], - [ 15, 10 ], - [ 18, 12 ], - [ 25, 20 ], - [ 25, 20 ], - [ 20, 15 ], - [ 20, 15 ], - [ 18, 18 ], - [ 18, 18 ], - [ 20, 10 ], - [ 20, 10 ], - [ 45, 15 ], - [ 33, 18 ], - [ 20, 14 ], - [ 20, 14 ], - [ 21, 14 ], - [ 21, 14 ], - [ 16, 10 ], - [ 16, 10 ], - [ 17, 11 ], - [ 17, 11 ], - [ 22, 17 ], - [ 22, 17 ], - [ 15, 9 ], - [ 16, 10 ], - [ 18, 10 ], - [ 14, 6 ], - [ 23, 18 ], - [ 25, 20 ], - [ 25, 20 ], - [ 25, 14 ], - [ 25, 14 ], - [ 30, 15 ], - [ 20, 15 ], - [ 33, 18 ], - [ 33, 18 ], - [ 12, 12 ], - [ 23, 17 ], - [ 23, 17 ], - [ 20, 17 ], - [ 20, 17 ], - [ 20, 11 ], - [ 26, 17 ], - [ 21, 10 ], - [ 22, 8 ], - [ 20, 13 ], - [ 20, 13 ], - [ 21, 14 ], - [ 21, 14 ], - [ 20, 10 ], - [ 20, 10 ], - null, - null, - null, - null, - null, - [ 20, 17 ], - [ 20, 17 ], - [ 16, 6 ], - [ 16, 6 ], - [ 18, 10 ], - [ 18, 10 ], - [ 32, 17 ], - [ 32, 17 ], - [ 18, 15 ], - [ 18, 15 ], - [ 23, 13 ], - [ 23, 13 ], - [ 14, 7 ], - [ 15, 8 ], - [ 15, 7 ], - [ 18, 8 ], - [ 13, 10 ], - [ 13, 10 ], - [ 23, 17 ], - [ 20, 15 ], - [ 13, 7 ], - [ 18, 12 ], - [ 33, 18 ], - [ 25, 10 ], - [ 15, 7 ], - [ 15, 7 ], - [ 20, 10 ], - [ 28, 18 ], - [ 25, 15 ], - [ 25, 15 ], - [ 35, 18 ], - [ 18, 8 ], - [ 20, 14 ], - [ 23, 17 ], - [ 25, 18 ], - [ 25, 18 ], - [ 25, 18 ], - [ 25, 18 ], - [ 25, 16 ], - [ 25, 16 ], - [ 23, 15 ], - [ 25, 12 ], - [ 20, 11 ], - [ 20, 11 ], - [ 23, 17 ], - [ 23, 17 ], - [ 21, 14 ], - [ 21, 14 ], - [ 18, 12 ], - [ 18, 12 ], - [ 25, 18 ], - [ 25, 18 ], - [ 25, 18 ], - [ 25, 18 ], - [ 15, 12 ], - [ 15, 12 ], - [ 28, 14 ], - [ 28, 14 ], - [ 28, 14 ], - [ 24, 15 ], - [ 24, 15 ], - [ 20, 10 ], - [ 30, 17 ], - [ 20, 15 ], - [ 13, 10 ], - [ 13, 10 ], - [ 15, 15 ], - [ 25, 16 ], - [ 25, 16 ], - [ 19, 10 ], - [ 19, 10 ], - [ 28, 15 ], - [ 20, 14 ], - [ 20, 14 ], - [ 15, 11 ], - [ 15, 11 ], - [ 20, 15 ], - [ 20, 15 ], - [ 21, 15 ], - [ 21, 15 ], - [ 18, 14 ], - [ 18, 14 ], - [ 19, 16 ], - [ 19, 16 ], - [ 20, 13 ], - [ 20, 13 ], - [ 22, 15 ], - [ 22, 15 ], - [ 23, 16 ], - [ 23, 16 ], - [ 13, 13 ], - [ 19, 14 ], - [ 19, 14 ], - [ 18, 10 ], - [ 18, 10 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 35, 18 ], - [ 25, 10 ], - [ 15, 7 ], - [ 15, 7 ], - [ 15, 7 ], - [ 35, 18 ], - [ 25, 10 ], - [ 25, 20 ], - [ 25, 20 ], - [ 12, 5 ], - [ 25, 18 ], - 20, - [ 18, 10 ], - [ 18, 10 ], - [ 21, 15 ], - [ 21, 15 ], - [ 23, 20 ], - [ 23, 20 ], - [ 22, 14 ], - [ 22, 14 ], - [ 22, 14 ], - [ 27, 14 ], - [ 27, 14 ], - 25, - 25, - [ 21, 14 ], - [ 21, 14 ], - [ 16, 7 ], - [ 16, 7 ], - [ 25, 16 ], - [ 25, 16 ], - [ 11, 8 ], - [ 11, 8 ], - [ 15, 15 ], - 20, - 20, - 25, - 25, - 18, - 18, - 14, - 14, - 25, - 18, - 35, - 20, - [ 23, 15 ], - [ 23, 15 ], - [ 20, 12 ], - [ 20, 12 ], - [ 18, 15 ], - [ 18, 15 ], - [ 20, 20 ], - 25, - 25, - [ 23, 16 ], - [ 23, 16 ], - 21, - 21, - [ 22, 15 ], - [ 22, 15 ], - [ 20, 14 ], - [ 20, 14 ], - 18, - 18, - 21, - 21, - [ 23, 15 ], - [ 14, 10 ], - [ 15, 7 ], - [ 16, 8 ], - [ 17, 9 ], - [ 18, 10 ], - [ 19, 11 ], - [ 21, 13 ], - [ 23, 15 ], - [ 23, 13 ], - [ 25, 15 ], - [ 25, 15 ], - [ 20, 8 ], - [ 20, 11 ], - [ 27, 17 ], - [ 20, 10 ], - [ 20, 10 ], - [ 26, 16 ], - [ 26, 16 ], - [ 19, 7 ], - [ 19, 7 ], - [ 11, 11 ], - [ 11, 11 ], - 15, - 15, - [ 23, 17 ], - [ 23, 17 ], - [ 15, 8 ], - [ 15, 8 ], - [ 17, 10 ], - [ 17, 10 ], - [ 22, 16 ], - [ 22, 16 ], - [ 30, 16 ], - [ 30, 16 ], - [ 22, 14 ], - [ 22, 14 ], - [ 20, 12 ], - [ 20, 12 ], - [ 27, 12 ], - [ 15, 12 ], - [ 15, 12 ], - [ 27, 17 ], - [ 27, 17 ], - [ 27, 15 ], - [ 27, 15 ], - [ 23, 14 ], - [ 23, 14 ], - [ 25, 13 ], - [ 25, 13 ], - [ 20, 6 ], - 20, - 17, - 18, - [ 22, 16 ], - [ 22, 16 ], - [ 15, 7 ], - [ 18, 10 ], - [ 35, 18 ], - [ 15, 7 ], - [ 18, 8 ], - [ 20, 10 ], - [ 25, 15 ], - [ 28, 18 ], - [ 20, 12 ], - [ 16, 9 ], - [ 25, 18 ], - null, - null, - [ 24, 12 ], - [ 24, 12 ], - [ 28, 18 ], - [ 28, 18 ], - [ 20, 10 ], - [ 28, 14 ], - [ 28, 14 ], - 25, - 25, - [ 18, 12 ], - [ 18, 12 ], - [ 16, 10 ], - [ 16, 10 ], - [ 25, 19 ], - [ 25, 19 ], - [ 13, 7 ], - [ 13, 7 ], - [ 25, 16 ], - [ 25, 16 ], - [ 25, 12 ], - [ 19, 10 ], - [ 25, 16 ], - [ 25, 16 ], - [ 25, 15 ], - [ 30, 17 ], - [ 15, 15 ], - [ 15, 15 ], - [ 15, 15 ], - [ 15, 15 ], - [ 25, 15 ], - [ 25, 15 ], - [ 23, 14 ], - [ 23, 14 ], - [ 13, 13 ], - [ 28, 14 ], - [ 28, 14 ], - [ 24, 14 ], - [ 24, 14 ], - [ 24, 14 ], - 20, - 20, - 16, - 16, - [ 19, 14 ], - [ 19, 14 ], - 21, - 21, - [ 21, 15 ], - [ 21, 15 ], - 25, - 25, - [ 22, 10 ], - [ 22, 10 ], - [ 29, 19 ], - [ 29, 19 ], - [ 27, 18 ], - [ 28, 19 ], - [ 32, 18 ], - [ 25, 15 ], - 20, - 20, - 18, - 14, - [ 28, 22 ], - [ 25, 18 ], - 21, - 21, - [ 27, 18 ], - [ 24, 15 ], - [ 24, 14 ], - [ 28, 16 ], - [ 28, 16 ], - [ 29, 19 ], - [ 29, 19 ], - [ 23, 14 ], - 24, - 24, - 15, - 15, - 20, - 20, - 25, - 25, - 16, - 16, - [ 13, 13 ], - [ 13, 13 ], - [ 18, 9 ], - [ 18, 9 ], - [ 22, 10 ], - [ 19, 14 ] + [ 3, 2 ], + [ 12, 9 ], + [ 23, 15 ], + [ 25, 18 ], + [ 12, 9 ], + [ 15, 10 ], + [ 15, 10 ], + [ 25, 20 ], + [ 12, 7 ], + [ 23, 15 ], + [ 15, 8 ], + [ 25, 20 ], + [ 15, 10 ], + [ 15, 10 ], + [ 15, 10 ], + [ 20, 15 ], + [ 23, 15 ], + [ 15, 10 ], + [ 23, 15 ], + [ 15, 10 ], + [ 15, 8 ], + [ 23, 15 ], + [ 15, 8 ], + [ 15, 10 ], + [ 25, 15 ], + [ 22, 15 ], + [ 40, 15 ], + [ 40, 15 ], + [ 15, 9 ], + [ 15, 9 ], + null, + [ 13, 7 ], + null, + [ 25, 20 ], + [ 15, 9 ], + [ 15, 10 ], + [ 15, 10 ], + [ 13, 7 ], + [ 13, 7 ], + [ 18, 8 ], + [ 13, 7 ], + [ 10, 5 ], + [ 13, 7 ], + [ 13, 7 ], + [ 15, 8 ], + [ 15, 8 ], + [ 15, 7 ], + [ 18, 8 ], + [ 40, 15 ], + [ 15, 10 ], + null, + [ 13, 7 ], + null, + [ 15, 9 ], + null, + [ 13, 7 ], + [ 15, 9 ], + [ 15, 12 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 8 ], + [ 15, 9 ], + null, + [ 15, 10 ], + [ 15, 9 ], + [ 23, 15 ], + [ 25, 18 ], + [ 25, 18 ], + [ 22, 15 ], + [ 22, 15 ], + [ 17, 10 ], + [ 12, 6 ], + [ 12, 6 ], + [ 25, 18 ], + [ 25, 20 ], + [ 25, 20 ], + [ 25, 20 ], + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + [ 40, 15 ], + [ 35, 10 ], + [ 40, 15 ], + [ 25, 10 ], + [ 15, 7 ], + [ 25, 10 ], + [ 40, 15 ], + [ 40, 15 ], + [ 15, 10 ], + [ 15, 7 ], + [ 15, 7 ], + [ 40, 15 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 40, 15 ], + [ 35, 10 ], + [ 15, 10 ], + [ 15, 7 ], + [ 15, 7 ], + [ 35, 10 ], + [ 25, 10 ], + [ 40, 15 ], + [ 25, 10 ], + [ 15, 7 ], + [ 25, 10 ], + [ 40, 15 ], + [ 40, 15 ], + [ 15, 10 ], + [ 15, 7 ], + [ 15, 7 ], + [ 40, 15 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 40, 15 ], + [ 35, 10 ], + [ 15, 10 ], + [ 15, 7 ], + [ 15, 7 ], + [ 35, 10 ], + [ 25, 10 ], + [ 15, 7 ], + [ 15, 7 ], + [ 12, 8 ], + [ 12, 8 ], + [ 12, 8 ], + [ 12, 8 ], + [ 12, 8 ], + [ 25, 10 ], + [ 25, 10 ], + [ 25, 10 ], + [ 25, 10 ], + [ 25, 10 ], + [ 40, 15 ], + [ 40, 15 ], + [ 40, 15 ], + [ 35, 10 ], + [ 15, 7 ], + [ 12, 8 ], + [ 15, 7 ], + [ 12, 8 ], + [ 15, 7 ], + [ 15, 7 ], + [ 12, 8 ], + [ 15, 7 ], + [ 12, 8 ], + [ 15, 7 ], + null, + null, + null, + null, + null, + [ 15, 7 ], + [ 12, 8 ], + [ 15, 7 ], + [ 12, 8 ], + [ 15, 7 ], + [ 15, 11 ], + [ 20, 14 ], + null, + [ 15, 6 ], + null, + [ 13, 9 ], + null, + [ 15, 10 ], + null, + [ 13, 7 ], + [ 17, 8 ], + [ 17, 12 ], + null, + [ 15, 10 ], + [ 20, 15 ], + [ 20, 15 ], + [ 15, 12 ], + [ 22, 15 ], + [ 25, 20 ], + [ 15, 8 ], + [ 25, 18 ], + [ 13, 7 ], + [ 13, 7 ], + [ 17, 8 ], + [ 17, 12 ], + [ 15, 11 ], + [ 20, 11 ], + [ 32, 17 ], + [ 32, 17 ], + [ 15, 9 ], + [ 13, 7 ], + [ 10, 5 ], + [ 22, 14 ], + [ 22, 14 ], + null, + [ 15, 8 ], + null, + [ 20, 11 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 10, 10 ], + [ 30, 15 ], + [ 30, 15 ], + [ 30, 20 ], + [ 30, 20 ], + [ 15, 8 ], + [ 15, 8 ], + [ 15, 10 ], + [ 15, 10 ], + [ 20, 10 ], + [ 20, 10 ], + [ 20, 10 ], + [ 20, 10 ], + [ 25, 17 ], + [ 25, 17 ], + null, + [ 17, 10 ], + null, + [ 17, 11 ], + null, + [ 15, 10 ], + [ 22, 15 ], + [ 40, 15 ], + [ 25, 10 ], + [ 15, 7 ], + [ 25, 10 ], + [ 40, 15 ], + [ 40, 15 ], + [ 15, 10 ], + [ 15, 7 ], + [ 15, 7 ], + [ 40, 15 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 40, 15 ], + [ 35, 10 ], + [ 15, 10 ], + [ 15, 7 ], + [ 15, 7 ], + [ 35, 10 ], + [ 25, 10 ], + [ 25, 18 ], + [ 18, 8 ], + [ 18, 8 ], + [ 25, 10 ], + [ 40, 15 ], + [ 15, 10 ], + [ 20, 12 ], + [ 20, 12 ], + [ 25, 18 ], + [ 21, 16 ], + null, + null, + null, + null, + null, + [ 28, 13 ], + [ 28, 13 ], + [ 18, 10 ], + [ 18, 10 ], + [ 23, 15 ], + [ 23, 15 ], + [ 35, 25 ], + [ 35, 25 ], + [ 25, 18 ], + [ 25, 18 ], + [ 20, 10 ], + [ 20, 10 ], + [ 25, 18 ], + [ 25, 18 ], + [ 20, 15 ], + [ 20, 15 ], + [ 25, 18 ], + [ 25, 18 ], + [ 17, 10 ], + [ 17, 10 ], + [ 14, 10 ], + [ 22, 16 ], + [ 22, 16 ], + [ 20, 15 ], + [ 20, 15 ], + null, + null, + [ 16, 10 ], + [ 20, 15 ], + [ 12, 8 ], + [ 12, 8 ], + [ 14, 6 ], + [ 14, 6 ], + [ 14, 6 ], + [ 14, 6 ], + [ 25, 18 ], + [ 25, 18 ], + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + [ 30, 16 ], + [ 30, 16 ], + [ 22, 15 ], + [ 22, 15 ], + [ 11, 6 ], + [ 11, 6 ], + [ 20, 12 ], + [ 20, 12 ], + [ 28, 20 ], + [ 28, 20 ], + [ 13, 8 ], + [ 13, 8 ], + [ 20, 10 ], + [ 20, 10 ], + [ 23, 18 ], + [ 23, 18 ], + [ 25, 12 ], + [ 25, 12 ], + [ 25, 12 ], + [ 25, 12 ], + [ 25, 12 ], + [ 25, 12 ], + [ 25, 12 ], + [ 25, 12 ], + [ 25, 12 ], + [ 25, 12 ], + [ 10, 5 ], + [ 15, 10 ], + [ 15, 10 ], + [ 25, 10 ], + [ 15, 10 ], + [ 17, 12 ], + [ 17, 12 ], + [ 20, 10 ], + [ 20, 10 ], + [ 25, 18 ], + [ 25, 18 ], + [ 17, 8 ], + [ 17, 8 ], + [ 23, 14 ], + [ 23, 14 ], + [ 38, 18 ], + [ 17, 8 ], + [ 15, 8 ], + [ 15, 8 ], + [ 25, 20 ], + [ 25, 20 ], + [ 15, 8 ], + [ 15, 8 ], + [ 18, 12 ], + [ 18, 12 ], + [ 20, 20 ], + [ 23, 14 ], + [ 23, 14 ], + [ 30, 15 ], + [ 20, 10 ], + [ 23, 18 ], + [ 11, 6 ], + [ 11, 6 ], + [ 20, 14 ], + [ 20, 14 ], + [ 20, 10 ], + [ 20, 10 ], + [ 17, 13 ], + [ 17, 13 ], + [ 28, 14 ], + [ 28, 14 ], + [ 15, 15 ], + [ 23, 13 ], + [ 20, 10 ], + [ 20, 10 ], + [ 24, 15 ], + [ 24, 15 ], + [ 35, 18 ], + [ 17, 12 ], + [ 21, 16 ], + [ 20, 15 ], + [ 20, 15 ], + [ 14, 9 ], + [ 14, 9 ], + [ 25, 18 ], + [ 16, 6 ], + [ 21, 11 ], + [ 12, 8 ], + [ 12, 8 ], + [ 18, 18 ], + [ 18, 18 ], + [ 16, 16 ], + [ 16, 16 ], + null, + null, + null, + null, + [ 26, 17 ], + [ 30, 15 ], + [ 30, 15 ], + [ 16, 10 ], + [ 16, 10 ], + [ 25, 18 ], + [ 25, 18 ], + [ 16, 10 ], + [ 16, 10 ], + [ 25, 18 ], + [ 25, 18 ], + [ 18, 10 ], + [ 18, 10 ], + [ 28, 19 ], + [ 28, 19 ], + [ 14, 10 ], + [ 25, 15 ], + [ 25, 15 ], + [ 25, 20 ], + [ 20, 15 ], + [ 25, 18 ], + [ 15, 10 ], + [ 15, 10 ], + [ 25, 16 ], + [ 18, 10 ], + [ 25, 16 ], + [ 18, 10 ], + [ 20, 15 ], + [ 20, 15 ], + [ 25, 15 ], + [ 25, 15 ], + [ 20, 10 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 25, 15 ], + [ 25, 15 ], + [ 25, 15 ], + [ 25, 15 ], + [ 25, 15 ], + [ 25, 15 ], + [ 20, 15 ], + [ 20, 15 ], + [ 20, 15 ], + [ 20, 15 ], + [ 11, 11 ], + [ 11, 11 ], + [ 13, 9 ], + [ 13, 9 ], + [ 21, 16 ], + [ 21, 16 ], + [ 20, 15 ], + [ 20, 15 ], + [ 21, 15 ], + [ 21, 15 ], + [ 25, 18 ], + [ 25, 18 ], + [ 24, 14 ], + [ 24, 14 ], + [ 22, 17 ], + [ 15, 15 ], + [ 15, 15 ], + [ 14, 14 ], + [ 24, 11 ], + [ 24, 11 ], + [ 10, 5 ], + [ 10, 5 ], + [ 25, 18 ], + [ 25, 18 ], + [ 23, 17 ], + [ 23, 17 ], + [ 23, 16 ], + [ 23, 16 ], + [ 23, 16 ], + [ 23, 16 ], + [ 23, 17 ], + [ 23, 17 ], + [ 25, 20 ], + [ 25, 20 ], + [ 16, 16 ], + [ 16, 16 ], + [ 18, 18 ], + [ 18, 18 ], + [ 16, 16 ], + [ 16, 16 ], + [ 25, 16 ], + [ 25, 16 ], + [ 50, 20 ], + [ 16, 12 ], + [ 15, 10 ], + [ 18, 12 ], + [ 25, 20 ], + [ 25, 20 ], + [ 20, 15 ], + [ 20, 15 ], + [ 18, 18 ], + [ 18, 18 ], + [ 20, 10 ], + [ 20, 10 ], + [ 45, 15 ], + [ 33, 18 ], + [ 20, 14 ], + [ 20, 14 ], + [ 21, 14 ], + [ 21, 14 ], + [ 16, 10 ], + [ 16, 10 ], + [ 17, 11 ], + [ 17, 11 ], + [ 22, 17 ], + [ 22, 17 ], + [ 15, 9 ], + [ 16, 10 ], + [ 18, 10 ], + [ 14, 6 ], + [ 23, 18 ], + [ 25, 20 ], + [ 25, 20 ], + [ 25, 14 ], + [ 25, 14 ], + [ 30, 15 ], + [ 20, 15 ], + [ 33, 18 ], + [ 33, 18 ], + [ 12, 12 ], + [ 23, 17 ], + [ 23, 17 ], + [ 20, 17 ], + [ 20, 17 ], + [ 20, 11 ], + [ 26, 17 ], + [ 21, 10 ], + [ 22, 8 ], + [ 20, 13 ], + [ 20, 13 ], + [ 21, 14 ], + [ 21, 14 ], + [ 20, 10 ], + [ 20, 10 ], + null, + null, + null, + null, + null, + [ 20, 17 ], + [ 20, 17 ], + [ 16, 6 ], + [ 16, 6 ], + [ 18, 10 ], + [ 18, 10 ], + [ 32, 17 ], + [ 32, 17 ], + [ 18, 15 ], + [ 18, 15 ], + [ 23, 13 ], + [ 23, 13 ], + [ 14, 7 ], + [ 15, 8 ], + [ 15, 7 ], + [ 18, 8 ], + [ 13, 10 ], + [ 13, 10 ], + [ 23, 17 ], + [ 20, 15 ], + [ 13, 7 ], + [ 18, 12 ], + [ 33, 18 ], + [ 25, 10 ], + [ 15, 7 ], + [ 15, 7 ], + [ 20, 10 ], + [ 28, 18 ], + [ 25, 15 ], + [ 25, 15 ], + [ 35, 18 ], + [ 18, 8 ], + [ 20, 14 ], + [ 23, 17 ], + [ 25, 18 ], + [ 25, 18 ], + [ 25, 18 ], + [ 25, 18 ], + [ 25, 16 ], + [ 25, 16 ], + [ 23, 15 ], + [ 25, 12 ], + [ 20, 11 ], + [ 20, 11 ], + [ 23, 17 ], + [ 23, 17 ], + [ 21, 14 ], + [ 21, 14 ], + [ 18, 12 ], + [ 18, 12 ], + [ 25, 18 ], + [ 25, 18 ], + [ 25, 18 ], + [ 25, 18 ], + [ 15, 12 ], + [ 15, 12 ], + [ 28, 14 ], + [ 28, 14 ], + [ 28, 14 ], + [ 24, 15 ], + [ 24, 15 ], + [ 20, 10 ], + [ 30, 17 ], + [ 20, 15 ], + [ 13, 10 ], + [ 13, 10 ], + [ 15, 15 ], + [ 25, 16 ], + [ 25, 16 ], + [ 19, 10 ], + [ 19, 10 ], + [ 28, 15 ], + [ 20, 14 ], + [ 20, 14 ], + [ 15, 11 ], + [ 15, 11 ], + [ 20, 15 ], + [ 20, 15 ], + [ 21, 15 ], + [ 21, 15 ], + [ 18, 14 ], + [ 18, 14 ], + [ 19, 16 ], + [ 19, 16 ], + [ 20, 13 ], + [ 20, 13 ], + [ 22, 15 ], + [ 22, 15 ], + [ 23, 16 ], + [ 23, 16 ], + [ 13, 13 ], + [ 19, 14 ], + [ 19, 14 ], + [ 18, 10 ], + [ 18, 10 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 35, 18 ], + [ 25, 10 ], + [ 15, 7 ], + [ 15, 7 ], + [ 15, 7 ], + [ 35, 18 ], + [ 25, 10 ], + [ 25, 20 ], + [ 25, 20 ], + [ 12, 5 ], + [ 25, 18 ], + [ 20, 14 ], + [ 18, 10 ], + [ 18, 10 ], + [ 21, 15 ], + [ 21, 15 ], + [ 23, 20 ], + [ 23, 20 ], + [ 22, 14 ], + [ 22, 14 ], + [ 22, 14 ], + [ 27, 14 ], + [ 27, 14 ], + [ 25, 19 ], + [ 25, 19 ], + [ 21, 14 ], + [ 21, 14 ], + [ 16, 7 ], + [ 16, 7 ], + [ 25, 16 ], + [ 25, 16 ], + [ 11, 8 ], + [ 11, 8 ], + [ 15, 15 ], + [ 20, 14 ], + [ 20, 14 ], + [ 25, 18 ], + [ 25, 18 ], + [ 18, 12 ], + [ 18, 12 ], + [ 14, 7 ], + [ 14, 7 ], + [ 25, 18 ], + [ 18, 12 ], + [ 35, 20 ], + [ 20, 14 ], + [ 23, 15 ], + [ 23, 15 ], + [ 20, 12 ], + [ 20, 12 ], + [ 18, 15 ], + [ 18, 15 ], + [ 20, 20 ], + [ 25, 15 ], + [ 25, 15 ], + [ 23, 16 ], + [ 23, 16 ], + [ 21, 14 ], + [ 21, 14 ], + [ 22, 15 ], + [ 22, 15 ], + [ 20, 14 ], + [ 20, 14 ], + [ 18, 10 ], + [ 18, 10 ], + [ 21, 15 ], + [ 21, 15 ], + [ 23, 15 ], + [ 14, 10 ], + [ 15, 7 ], + [ 16, 8 ], + [ 17, 9 ], + [ 18, 10 ], + [ 19, 11 ], + [ 21, 13 ], + [ 23, 15 ], + [ 23, 13 ], + [ 25, 15 ], + [ 25, 15 ], + [ 17, 8 ], + [ 20, 11 ], + [ 27, 17 ], + [ 20, 10 ], + [ 20, 10 ], + [ 26, 16 ], + [ 26, 16 ], + [ 19, 7 ], + [ 19, 7 ], + [ 11, 11 ], + [ 11, 11 ], + [ 15, 8 ], + [ 15, 8 ], + [ 23, 17 ], + [ 23, 17 ], + [ 15, 8 ], + [ 15, 8 ], + [ 17, 10 ], + [ 17, 10 ], + [ 22, 16 ], + [ 22, 16 ], + [ 30, 16 ], + [ 30, 16 ], + [ 22, 14 ], + [ 22, 14 ], + [ 20, 12 ], + [ 20, 12 ], + [ 27, 12 ], + [ 15, 12 ], + [ 15, 12 ], + [ 27, 17 ], + [ 27, 17 ], + [ 27, 15 ], + [ 27, 15 ], + [ 23, 14 ], + [ 23, 14 ], + [ 25, 13 ], + [ 25, 13 ], + [ 20, 6 ], + [ 20, 13 ], + [ 17, 10 ], + [ 18, 11 ], + [ 22, 16 ], + [ 22, 16 ], + [ 15, 7 ], + [ 18, 10 ], + [ 35, 18 ], + [ 15, 7 ], + [ 18, 8 ], + [ 20, 10 ], + [ 25, 15 ], + [ 28, 18 ], + [ 20, 12 ], + [ 16, 9 ], + [ 25, 18 ], + [ 10, 10 ], + [ 10, 10 ], + [ 24, 12 ], + [ 24, 12 ], + [ 28, 18 ], + [ 28, 18 ], + [ 20, 10 ], + [ 28, 14 ], + [ 28, 14 ], + [ 25, 18 ], + [ 25, 18 ], + [ 18, 12 ], + [ 18, 12 ], + [ 16, 10 ], + [ 16, 10 ], + [ 25, 19 ], + [ 25, 19 ], + [ 13, 7 ], + [ 13, 7 ], + [ 25, 16 ], + [ 25, 16 ], + [ 25, 12 ], + [ 19, 10 ], + [ 25, 16 ], + [ 25, 16 ], + [ 25, 15 ], + [ 30, 17 ], + [ 15, 15 ], + [ 15, 15 ], + [ 15, 15 ], + [ 15, 15 ], + [ 25, 15 ], + [ 25, 15 ], + [ 23, 14 ], + [ 23, 14 ], + [ 13, 13 ], + [ 28, 14 ], + [ 28, 14 ], + [ 24, 14 ], + [ 24, 14 ], + [ 24, 14 ], + [ 20, 15 ], + [ 20, 15 ], + [ 16, 10 ], + [ 16, 10 ], + [ 19, 14 ], + [ 19, 14 ], + [ 21, 15 ], + [ 21, 15 ], + [ 21, 15 ], + [ 21, 15 ], + [ 25, 18 ], + [ 25, 18 ], + [ 22, 10 ], + [ 22, 10 ], + [ 29, 19 ], + [ 29, 19 ], + [ 27, 18 ], + [ 28, 19 ], + [ 32, 18 ], + [ 25, 15 ], + [ 20, 12 ], + [ 20, 12 ], + [ 18, 10 ], + [ 14, 8 ], + [ 28, 22 ], + [ 25, 18 ], + [ 21, 15 ], + [ 21, 15 ], + [ 27, 18 ], + [ 24, 15 ], + [ 24, 14 ], + [ 28, 16 ], + [ 28, 16 ], + [ 29, 19 ], + [ 29, 19 ], + [ 23, 14 ], + [ 24, 18 ], + [ 24, 18 ], + [ 15, 9 ], + [ 15, 9 ], + [ 20, 15 ], + [ 20, 15 ], + [ 25, 18 ], // 3d2y Sanji + [ 25, 18 ], // 3d2y Sanji + [ 16, 10 ], + [ 16, 10 ], + [ 13, 13 ], + [ 13, 13 ], + [ 18, 9 ], + [ 18, 9 ], + [ 22, 10 ], + [ 19, 14 ], + [ 15, 15 ], + [ 15, 15 ], + [ 28, 16 ], + [ 28, 16 ], + [ 22, 12 ], + [ 22, 12 ], + [ 18, 8 ], + [ 21, 12 ], + [ 21, 12 ], + [ 16, 11 ], + [ 30, 17 ], + [ 31, 17 ], + [ 31, 17 ], + [ 19, 14 ], + [ 19, 14 ], + [ 19, 14 ], + [ 19, 14 ], + [ 24, 17 ], + [ 24, 17 ], + [ 21, 15 ], + [ 21, 15 ], + [ 15, 8 ], + [ 15, 8 ], + [ 13, 13 ], + [ 13, 13 ], + [ 20, 12 ], + [ 25, 17 ], + [ 25, 18 ], + [ 20, 15 ], + [ 21, 9 ], + [ 21, 9 ], + [ 18, 10 ], + [ 18, 10 ], + [ 20, 14 ], + [ 16, 10 ], + [ 20, 14 ], + 20, + [ 18, 10 ], + [ 18, 10 ], + [ 22, 14 ], + [ 16, 8 ], + [ 16, 8 ], + [ 23, 16 ], + [ 23, 17 ], + [ 23, 17 ], + [ 25, 18 ], + [ 21, 15 ], + [ 28, 20 ], + [ 28, 20 ], + [ 28, 20 ], + [ 28, 20 ], + [ 28, 20 ], + [ 22, 15 ], + [ 22, 15 ], + [ 15, 15 ], + [ 15, 15 ], + [ 25, 11 ], + [ 25, 11 ], + [ 25, 18 ], + [ 15, 7 ], + [ 16, 8 ], + [ 22, 12 ], + [ 22, 12 ], + [ 22, 14 ], + null, + null, + null, + null, + [ 19, 12 ], + [ 15, 9 ], + [ 15, 9 ], + [ 20, 15 ], + [ 20, 15 ], + [ 20, 14 ], //Violet + [ 20, 14 ], //Violet + [ 20, 14 ], //Dellinger + [ 20, 14 ], //Dellinger + [ 23, 17 ], + [ 23, 17 ], + [ 23, 17 ], + [ 23, 17 ], + [ 20, 12 ], + [ 20, 12 ], + [ 20, 10 ], + [ 15, 7 ], + [ 15, 7 ], + [ 13, 13 ], + [ 13, 13 ], + [ 25, 14 ], + [ 23, 14 ], + [ 23, 14 ], + [ 19, 10 ], + [ 19, 10 ], + [ 16, 6 ], + [ 24, 12 ], + [ 24, 12 ], + [ 26, 16 ], + [ 26, 16 ], + [ 16, 6 ], + [ 13, 13 ], + [ 13, 13 ], + [ 15, 15 ], + [ 17, 17 ], + [ 19, 13 ], + [ 19, 13 ], + [ 11, 5 ], + [ 11, 5 ], + [ 18, 12 ], + [ 18, 12 ], + [ 23, 15 ], + [ 23, 15 ], + [ 11, 5 ], + [ 11, 5 ], + [ 23, 18 ], + [ 23, 18 ], + [ 23, 15 ], + [ 23, 15 ], + [ 11, 3 ], + [ 11, 3 ], + [ 29, 18 ], + [ 29, 18 ], + [ 18, 8 ], + [ 18, 8 ], + [ 25, 20 ],//Law + [ 25, 20 ],//Law + [ 30, 14 ], + [ 30, 14 ], + [ 22, 15 ], + [ 22, 15 ], + [ 23, 15 ], + [ 23, 15 ], + [ 14, 8 ], + [ 13, 13 ], + [ 13, 13 ], + [ 21, 15 ], + [ 21, 15 ], + [ 17, 12 ], + [ 17, 12 ], + [ 15, 9 ], + [ 15, 9 ], + [ 10, 5 ], + [ 21, 15 ], + [ 20, 13 ], + [ 28, 18 ], + [ 16, 8 ], + 13, + [ 16, 9 ], + 16, + [ 13, 6 ], + [ 13, 6 ], + [ 26, 18 ], + [ 26, 18 ], + [ 15, 6 ], + [ 17, 10], + [ 17, 10], + [ 20, 16 ], //Leo + [ 20, 16 ], //Leo + [ 24, 18 ], //Mansherry + [ 24, 18 ], //Mansherry + [ 18, 12 ], + [ 18, 12 ], + [ 23, 16 ], + [ 23, 16 ], + [ 24, 17 ], + [ 24, 17 ], + [ 20, 10 ], + [ 20, 10 ], + [ 20, 10 ], + [ 20, 10 ], + [ 25, 12 ], + [ 25, 12 ], + [ 13, 13 ], + [ 13, 13 ], + [ 24, 15 ], + [ 24, 15 ], + [ 20, 11 ], + [ 20, 11 ], + [ 13, 8 ], + [ 11, 11 ], + [ 11, 11 ], + [ 30, 15 ], + [ 30, 15 ], + [ 27, 17 ],//Ain + [ 27, 17 ],//Ain + [ 23, 12 ], + [ 23, 12 ], + [ 30, 15 ], + [ 30, 15 ], + [ 13, 6 ], + [ 13, 6 ], + [ 22, 15 ], + [ 22, 15 ], + [ 12, 7 ], + [ 25, 18 ], + [ 25, 18 ], + [ 23, 17 ], + [ 23, 17 ], + [ 23, 16 ], + [ 23, 16 ], + [ 23, 17 ], + [ 23, 17 ], + [ 20, 15 ], + [ 20, 15 ], + [ 20, 14 ], + [ 20, 14 ], + [ 20, 14 ], + [ 20, 14 ], + [ 20, 15 ], + [ 20, 15 ], + [ 26, 20 ],//Elizabello + [ 26, 20 ],//Elizabello + [ 23, 17 ],//Ideo + [ 23, 17 ],//Ideo + [ 6, 6 ], + [ 6, 6 ], + [ 16, 12], + [ 18 , 11 ], + [ 19, 12 ], + [ 15, 8 ], + [ 30, 16 ], + [ 30, 16 ], + [ 24, 12 ], + [ 24, 12 ], + [ 22, 12 ], + [ 22, 12 ], + [ 18, 10 ], + [ 20, 11 ], + [ 15, 6 ], + [ 20, 15 ], + [ 15, 6 ], + [ 25, 18 ], + 19, + [ 25, 18 ], + [ 21, 16 ], + [ 10, 4 ], + [ 23, 17 ], + [ 23, 17 ], + [ 21, 15 ], + [ 21, 15 ], + [ 13, 13 ], + [ 13, 13 ], + [ 25, 14 ], + [ 25, 14 ], + [ 17, 10 ], + [ 17, 10 ], + [ 14, 8 ], + [ 14, 8 ], + [ 24, 18 ], + [ 24, 18 ], + [ 19, 9 ], + [ 19, 9 ], + [ 23, 16 ], + [ 23, 16 ], + [ 20, 14 ], + [ 20, 14 ], + [ 23, 17 ], + [ 23, 17 ], + [ 17, 17 ], + [ 17, 17 ], + null,//Rainbow Armored Crab + [ 19, 13 ], + [ 19, 13 ], + [ 23, 17 ], + [ 23, 17 ], + [ 17, 12 ],// Haruta + [ 17, 12 ],// Haruta + [ 23, 16 ], + [ 23, 16 ], + [ 11, 5 ], + [ 11, 5 ], + [ 19, 13 ], + [ 19, 13 ], + [ 15, 15 ], + [ 15, 15 ], + [ 29, 15 ], + [ 29, 15 ], + [ 17, 7 ], + [ 18, 10 ], + [ 18, 10 ], + [ 22, 14 ], + [ 22, 14 ], + [ 14, 6 ], + [ 14, 6 ], + [ 17, 9 ], + [ 17, 9 ], + [ 25, 15 ], + [ 16, 10 ], + [ 16, 10 ], + [ 21, 14 ], + [ 21, 14 ], + [ 17, 11 ], + [ 17, 11 ], + [ 15, 15 ], + [ 15, 15 ], + [ 18, 12 ], + [ 17, 10 ], + [ 17, 11 ], + [ 25, 14 ], + [ 34, 18 ],//byrnndi world + [ 34, 18 ],//byrnndi world + [ 29, 16 ], + [ 29, 16 ], + [ 20, 10 ], + [ 15, 9 ], + [ 16, 10 ], + [ 17, 10 ], + [ 23, 16 ], + [ 22, 15 ], + [ 22, 15 ],//Sentomaru + [ 22, 15 ],//Sentomaru + [ 19, 12 ], + [ 19, 12 ], + [ 23, 15 ], + [ 23, 15 ], + [ 20, 13 ], + [ 20, 13 ], + [ 22, 14 ], + [ 22, 14 ], + [ 20, 17 ],//Kizaru + [ 20, 17 ],//Kizaru + [ 19, 11 ], + [ 19, 11 ], + [ 20, 15 ], + [ 20, 15 ], + [ 23, 17 ], + [ 17, 17 ], + [ 17, 17 ], + [ 13, 13 ], + [ 13, 13 ], + [ 24, 9 ],//Colo Marco + [ 24, 9 ],//Colo Marco + [ 24, 14 ], + [ 14, 6 ], + [ 21, 14 ], + [ 19, 12 ], + [ 18, 12 ], + [ 36, 24 ],//Young Whitebeard + [ 36, 24 ],//Young Whitebeard + [ 17, 15 ], + [ 17, 15 ], + [ 12, 10 ], + [ 12, 10 ], + [ 13, 11 ], + [ 13, 11 ], + [ 14, 14 ], + [ 14, 14 ], + [ 25, 19 ], + [ 25, 19 ], + [ 14, 8 ], + [ 14, 8 ], + [ 19, 15 ], + [ 19, 15 ], + [ 25, 17 ], + [ 25, 17 ], + [ 25, 19 ], + [ 25, 19 ], + [ 10, 4 ], + [ 10, 4 ], + [ 14, 7 ], + [ 21, 15 ], + [ 25, 18 ], + [ 19, 13 ], + [ 25, 18 ], + [ 12, 12 ], + [ 12, 12 ], + [ 18, 10 ], + [ 18, 10 ], + [ 13, 9 ], + [ 13, 9 ], + [ 20, 10 ], + [ 29, 17 ], + [ 29, 17 ], + [ 26, 16 ],//Coliseumn Sandersonia + [ 26, 16 ],//Coliseumn Sandersonia + [ 16, 16 ], + [ 16, 16 ], + [ 32, 17 ], + [ 32, 17 ], + [ 19, 12 ], + [ 19, 12 ], + [ 20, 14 ], + [ 20, 14 ], + [ 20, 12 ], + [ 20, 12 ], + [ 12, 5 ], + [ 12, 5 ], + [ 14, 14 ], + [ 14, 14 ], + [ 16, 5 ], + [ 16, 5 ], + [ 25, 15 ], + [ 25, 15 ], + [ 25, 18 ], + [ 25, 18 ], + [ 28, 18 ],//Coby + [ 28, 18 ],//Coby + [ 22, 17 ], + [ 22, 17 ], + [ 21, 17 ], + [ 21, 17 ], + [ 18, 12 ], + [ 18, 12 ], + [ 15, 9 ], + [ 15, 9 ], + [ 13, 6 ], + [ 13, 6 ], + [ 19, 12 ],//Leo + [ 19, 12 ],//Leo + [ 16, 10 ],//Wicca + [ 20, 12 ], + [ 24, 17 ],//Mansherry + [ 24, 17 ],//Mansherry + [ 20, 12 ], + [ 19, 12 ], + [ 6, 6 ], + [ 6, 6 ], + [ 27, 15 ], + [ 27, 15 ], + [ 25, 15 ],//Jump Point Chopper + [ 23, 13 ], + [ 23, 13 ], + [ 15, 9 ], + [ 16, 10 ], + [ 20, 14 ], + [ 18, 13 ], + [ 15, 10 ], + [ 25, 17 ], + [ 17, 10 ], + [ 13, 6 ], + [ 14, 8 ], + [ 20, 13 ], + [ 15, 9 ], + [ 16, 12 ], + [ 14, 14 ], + [ 14, 14 ], + [ 18, 10 ], + [ 18, 10 ], + [ 20, 13 ], + [ 20, 13 ], + [ 15, 15 ], + [ 20, 16 ], + [ 20, 16 ], + [ 21, 15 ], + [ 21, 15 ], + [ 18, 13 ],//New World Nami + [ 18, 13 ],//New World Nami + [ 20, 15 ],//New World Sanji + [ 20, 15 ],//New World Sanji + [ 12, 6 ], + [ 12, 6 ], + [ 15, 15 ], + [ 15, 15 ], + [ 31, 16 ],//Magellan + [ 31, 16 ],//Magellan + [ 26, 12 ], + [ 26, 12 ], + [ 26, 14 ], + [ 26, 14 ], + [ 27, 15 ], + [ 27, 15 ], + [ 15, 15 ], + [ 15, 15 ], + [ 14, 6 ], + [ 14, 6 ], + [ 12, 8 ], + [ 12, 8 ], + [ 23, 16 ], + [ 12, 7 ], + [ 21, 16 ], + [ 17, 12 ], + [ 17, 12 ], + [ 22, 15 ], + [ 19, 12 ], + [ 10, 10 ], + [ 10, 10 ], + [ 21, 14 ], + [ 21, 14 ], + [ 19, 14 ], + [ 19, 14 ], + [ 33, 18 ],//Colo Gladius + [ 33, 18 ],//Colo Gladius + [ 18, 8 ],//Colo Dalton + [ 18, 13 ],//New World Luffy + [ 18, 13 ],//New World Luffy + [ 20, 14 ], + [ 20, 14 ], + [ 22, 16 ], + [ 22, 16 ], + [ 16, 10 ], + [ 16, 10 ], + [ 25, 18 ], + [ 25, 18 ], + [ 25, 17 ], + [ 6, 6 ], + [ 20, 12 ], + [ 20, 12 ], + [ 21, 13 ], + [ 22, 15 ], + [ 15, 15 ], + [ 15, 15 ], + [ 33, 17 ], + [ 33, 17 ], + [ 26, 14 ], + [ 16, 7 ], + [ 20, 13 ], + [ 20, 13 ], + [ 18, 11 ], + [ 12, 8 ], + [ 14, 14 ], + [ 14, 14 ], + [ 33, 17 ], + [ 33, 17 ], + [ 22, 17 ],//Hody Jones + [ 22, 17 ],//Hody Jones + [ 21, 15 ], + [ 21, 15 ], + [ 21, 15 ], + [ 21, 15 ], + [ 22, 15 ], + [ 22, 15 ], + [ 17, 10 ], + [ 17, 10 ], + [ 20, 15 ], + [ 20, 15 ], + [ 17, 13 ], + [ 17, 12 ], + [ 20, 15 ],//5+ Sanji + [ 20, 12 ], + [ 22, 14 ], + [ 22, 14 ], + [ 20, 13 ], + [ 20, 13 ], + [ 12, 12 ], + [ 12, 12 ], + [ 30, 15 ],//Colo Don Chinjao + [ 30, 15 ],//Colo Don Chinjao + [ 18, 7 ], + [ 18, 7 ], + [ 22, 11 ], + [ 22, 11 ], + [ 14, 14 ], + [ 21, 17 ], + [ 21, 17 ], + [ 11, 7 ], + [ 11, 7 ], + [ 15, 15 ], + [ 15, 15 ], + [ 18, 11 ], + [ 18, 11 ], + [ 14, 5 ], + [ 17, 10 ], + [ 22, 18 ],//Shirahoshi + [ 22, 18 ],//Shirahoshi + [ 21, 15 ], + [ 21, 15 ], + [ 16, 10 ], + [ 16, 10 ], + [ 22, 16 ], + [ 22, 16 ], + [ 20, 15 ], + [ 20, 15 ], + [ 15, 9 ], + [ 15, 9 ], + [ 14, 14 ], + [ 14, 14 ], + [ 28, 13 ], + [ 28, 13 ], + [ 20, 10 ], + [ 20, 10 ], + [ 20, 11 ], + [ 20, 11 ], + [ 23, 17 ],//6+ Sabo + 22, + 19, + 19, + [ 18, 10 ], + 16, + 17, + 15, + 20, + [ 15, 9 ], + 16, + 14, + [ 19, 13 ], + [ 22, 15 ], + [ 22, 15 ], + [ 20, 16 ], + [ 20, 16 ], + [ 18, 10 ], + [ 14, 7 ], + [ 19, 11 ], + [ 19, 14 ], + [ 5, 5 ], + [ 5, 5 ], + [ 14, 10 ], + [ 14, 10 ], + [ 28, 15 ], + [ 28, 15 ], + [ 17, 8 ], + [ 17, 8 ], + [ 16, 8 ], + [ 15, 4 ], + [ 11, 11 ], + [ 11, 11 ], + [ 30, 16 ], + [ 21, 12 ],//Coliseum Arlong + [ 21, 12 ],//Coliseum Arlong + [ 21, 12 ], + [ 28, 15 ], + [ 28, 15 ], + [ 24, 21 ],//Legend Usopp + [ 24, 21 ],//Legend Usopp + [ 17, 11 ], + [ 17, 11 ], + [ 19, 14 ], + [ 19, 14 ], + [ 19, 12 ], + [ 19, 12 ], + [ 20, 14 ], + [ 20, 14 ], + [ 22, 15 ], + [ 22, 15 ], + [ 16, 13 ], + [ 7, 7 ], + [ 7, 7 ], + [ 13, 7 ], + [ 13, 7 ], + [ 19, 13 ], + [ 20, 14 ], + [ 19, 13 ], + [ 17, 11 ], + [ 30, 17 ], + [ 30, 17 ], + [ 16, 7 ], + [ 16, 7 ], + 20, + [ 12, 6 ], + [ 20, 12 ], + [ 19, 14 ], + [ 11, 5 ], + [ 23, 17 ], + [ 15, 9 ], + [ 24, 16 ],//Fortnight Elizabello + [ 24, 16 ],//Fortnight Elizabello + [ 15, 9 ], + [ 15, 9 ], + [ 13, 13 ], + [ 13, 13 ], + [ 11, 11 ], + [ 19, 14 ], + [ 19, 14 ], + [ 21, 16 ], + [ 21, 16 ], + [ 19, 14 ], + [ 19, 14 ], + [ 19, 13 ], + [ 19, 13 ], + [ 14, 9 ],//Momonosuke + [ 14, 9 ],//Momonosuke + [ 20, 13 ], + [ 20, 13 ], + [ 22, 15 ], + [ 29, 15 ], + [ 29, 15 ], + [ 20, 11 ], + [ 20, 11 ], + [ 19, 14 ], + [ 19, 14 ], + [ 17, 17 ], + [ 17, 17 ], + [ 11, 11 ], + [ 11, 11 ], + [ 18, 13 ],//Gear 4 Luffy + [ 29, 14 ], + [ 29, 14 ], + [ 20, 15 ], + [ 20, 15 ], + [ 16, 10 ], + [ 17, 11 ], + [ 20, 16 ], + [ 29, 15 ], + [ 29, 15 ], + [ 21, 12 ], + [ 15, 10 ], + [ 15, 10 ], + [ 15, 9 ], + [ 20, 14 ], + [ 24, 18 ], + [ 21, 16 ], + [ 21, 16 ], + [ 20, 15 ], + [ 20, 15 ], + [ 16, 10 ], + [ 16, 10 ], + [ 21, 15 ], + [ 21, 15 ], + [ 24, 17 ], + [ 24, 17 ], + [ 19, 14 ], + [ 17, 13 ], + [ 17, 13 ], + [ 23, 14 ], + [ 23, 14 ], + [ 15, 9 ], + [ 20, 14 ], + [ 15, 9 ], + [ 31, 17 ],//Mach Vise + [ 31, 17 ],//Mach Vise + [ 15, 5 ], + [ 15, 5 ], + [ 21, 17 ], + [ 21, 17 ], + [ 14, 7 ], + 19, + 19, + [ 17, 10 ], + [ 17, 10 ], + [ 15, 9 ], + 15, + 16, + 22, + 20, + 19, + 19, + 22, + [ 26, 17 ],//Pica + [ 26, 17 ],//Pica + [ 20, 14 ], + [ 20, 14 ], + [ 15, 11 ], + [ 16, 11 ], + [ 16, 11 ], + [ 18, 13 ], + [ 18, 13 ], + [ 18, 12 ], + [ 18, 12 ], + [ 17, 12 ], + [ 17, 12 ], + [ 15, 10 ], + [ 15, 10 ], + [ 10, 10 ], + [ 10, 10 ], + [ 22, 12 ], + [ 16, 12 ], + [ 16, 12 ], + [ 21, 6 ], + [ 21, 6 ], + [ 26, 17 ], + [ 26, 17 ], + [ 15, 9 ], + 16, + [ 20, 14 ], + [ 13, 13 ], + [ 13, 13 ], + [ 9, 9 ], + [ 9, 9 ], + [ 11, 7 ], + [ 11, 7 ], + [ 25, 16 ], + [ 25, 16 ], + [ 18, 14 ], + [ 18, 14 ], + [ 17, 13 ], + [ 17, 13 ], + [ 11, 7 ], + [ 11, 7 ], + [ 19, 15 ], + [ 19, 15 ], + [ 20, 14 ], + [ 20, 14 ], + [ 20, 14 ], + [ 17, 14 ], + [ 24, 9 ], + [ 24, 9 ], + [ 30, 16 ], + [ 30, 16 ], + [ 19, 14 ], + [ 19, 14 ], + [ 16, 10 ], + [ 16, 10 ], + [ 15, 10 ], + [ 15, 10 ], + [ 20, 14 ], + [ 20, 14 ], + [ 19, 14 ], + [ 19, 14 ], + [ 19, 14 ], + [ 15, 6 ], + [ 15, 6 ], + [ 25, 16 ], + [ 25, 16 ], + [ 17, 13 ], + [ 17, 13 ], + 21, + 19, + 21, + 19, + 20, + 20, + [ 10, 6 ], + [ 10, 6 ], + [ 15, 12 ], + [ 15, 12 ], + [ 19, 13 ], + [ 19, 13 ], + [ 23, 14 ], + [ 23, 14 ], + [ 8, 8 ], + [ 8, 8 ], + [ 16, 16 ], + [ 16, 16 ], + [ 21, 9 ], + [ 21, 9 ], + [ 13, 6 ], + [ 13, 6 ], + [ 19, 12 ], + [ 19, 12 ], + [ 22, 14 ], + [ 22, 14 ], + [ 19, 14 ], + [ 19, 14 ], + [ 19, 14 ], + [ 19, 14 ], + [ 19, 14 ], + [ 19, 14 ], + [ 20, 15 ], + [ 20, 15 ], + [ 18, 11 ], + [ 18, 11 ], + [ 20, 15 ], + [ 20, 15 ], + [ 18, 14 ], + [ 18, 14 ], + [ 16, 12 ], + [ 16, 12 ], + [ 14, 10 ], + [ 14, 10 ], + [ 11, 7 ], + [ 11, 7 ], + [ 13, 9 ], + [ 13, 9 ], + [ 20, 15 ], + [ 20, 15 ], + [ 19, 13 ], + [ 17, 11 ], + [ 17, 11 ], + [ 18, 12 ], + [ 20, 14 ], + [ 13, 9 ], + [ 13, 9 ], + [ 23, 14 ], + [ 23, 14 ], + [ 21, 14 ], + [ 21, 14 ], + [ 12, 9 ], + [ 12, 9 ], + [ 15, 11 ], + [ 15, 11 ], + [ 20, 11 ], + [ 20, 11 ], + 25, + [ 24, 18 ], + 22, + [ 25, 19 ], + 22, + null, + null, + null, + null, + null, + [ 28, 14 ], + [ 28, 14 ], + [ 19, 14 ], + [ 19, 14 ], + [ 18, 12 ], + [ 18, 12 ], + [ 21, 15 ], + [ 21, 15 ], + [ 16, 10 ], + [ 16, 10 ], + [ 18, 12 ], + [ 18, 12 ], + [ 9, 9 ], + [ 9, 9 ], + [ 15, 15 ], + [ 15, 15 ], + [ 37, 29 ], + [ 37, 29 ], + [ 15, 9 ], + [ 15, 9 ], + [ 21, 15 ], + [ 21, 15 ], + [ 12, 8 ], + [ 30, 15 ], + [ 30, 15 ], + [ 20, 15 ], + [ 20, 13 ], + [ 20, 13 ], + [ 16, 10 ], + [ 18, 14 ], + [ 14, 14 ], + [ 14, 14 ], + [ 22, 18 ], + [ 22, 18 ], + [ 25, 16 ], + [ 25, 16 ], + [ 25, 10 ], + [ 25, 10 ], + [ 29, 15 ], + [ 29, 15 ], + [ 19, 14 ], + [ 19, 14 ], + [ 20, 14 ], + [ 20, 14 ], + [ 20, 14 ], + [ 20, 14 ], + [ 20, 14 ], + [ 20, 14 ], + [ 20, 14 ], + [ 20, 14 ], + [ 16, 10 ], + [ 16, 10 ], + [ 12, 6 ], + [ 12, 6 ], + [ 32, 15 ], + [ 32, 15 ], + [ 23, 14 ], + [ 14, 14 ], + [ 14, 14 ], + [ 13, 13 ], + [ 13, 13 ], + [ 37, 30 ], + [ 37, 30 ], + [ 20, 13 ], + [ 20, 13 ], + [ null, 7 ], + [ null, 7 ], + [ 18, 14 ], + [ 18, 14 ], + [ 30, 15 ], + [ 30, 15 ], + null, + null, + [ 22, 15 ], + [ 22, 15 ], + [ 24, 17 ], + [ 24, 17 ], + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + [ 30, 16 ], + [ 30, 16 ], ]; diff --git a/common/data/defenses.js b/common/data/defenses.js index aea0396c1..1f261952d 100644 --- a/common/data/defenses.js +++ b/common/data/defenses.js @@ -45,10 +45,10 @@ window.defenses = [ [ 'Kuma (def up)' , 'Kuma Raid' , 'Master', 835, 1500 ], [ 'Kuma' , 'Kuma Raid' , 'Ultimate', 836, 1000 ], [ 'Kuma (def up)' , 'Kuma Raid' , 'Ultimate', 836, 2000 ], - //[ 'Hancock' , 'Hancock Raid' , 'Expert', 835, 750 ], - //[ 'Hancock (def up)' , 'Hancock Raid' , 'Expert', 835, 750 ], - //[ 'Hancock' , 'Hancock Raid' , 'Master', 835, 1500 ], - //[ 'Hancock (def up)' , 'Hancock Raid' , 'Master', 835, 1500 ], + //[ 'Hancock' , 'Hancock Raid' , 'Expert', 835, 750 ], + //[ 'Hancock (def up)' , 'Hancock Raid' , 'Expert', 835, 750 ], + //[ 'Hancock' , 'Hancock Raid' , 'Master', 835, 1500 ], + //[ 'Hancock (def up)' , 'Hancock Raid' , 'Master', 835, 1500 ], [ 'Giantess' , 'Hancock Raid' , 'Ultimate', 375, 250 ], [ 'Hancock' , 'Hancock Raid' , 'Ultimate', 865, 260 ], [ 'Hancock (def up)' , 'Hancock Raid' , 'Ultimate', 865, 38850 ], @@ -113,15 +113,15 @@ window.defenses = [ [ 'Manticore' , 'Sadi-chan Fortnight' , 'Expert', 552, 100 ], [ 'Sadi-chan' , 'Sadi-chan Fortnight' , 'Expert', 550, 750 ], [ 'DBF Usopp' , 'Afro Luffy Fortnight, mid round' , 'Expert', 572, 150 ], - [ 'DBF Chopper' , 'Afro Luffy Fortnight' , 'Expert', 572, 70 ], + [ 'DBF Chopper' , 'Afro Luffy Fortnight' , 'Expert', 573, 70 ], [ 'DBF Usopp' , 'Afro Luffy Fortnight, last round' , 'Expert', 572, 78 ], [ 'Afro Luffy' , 'Afro Luffy Fortnight' , 'Expert', 571, 85 ], [ 'Genbou' , 'Skypiea Warriors Fortnight' , 'Expert', 581, 100 ], [ 'Kamakiri' , 'Skypiea Warriors Fortnight' , 'Expert', 582, 90 ], [ 'Laki' , 'Skypiea Warriors Fortnight' , 'Expert', 583, 65 ], - [ 'Young Buggy' , 'Young Pirates Fortnight' , 'Expert', 599, 80 ], + [ 'Young Buggy' , 'Young Pirates Fortnight' , 'Expert', 598, 80 ], [ 'Young Shanks' , 'Young Pirates Fortnight' , 'Expert', 601, 100 ], - [ 'Young Buggy' , 'Young Pirates Fortnight, last round' , 'Expert', 600, 100 ], + [ 'Young Buggy' , 'Young Pirates Fortnight, last round' , 'Expert', 599, 100 ], [ 'Young Zeff' , 'Young Zeff Fortnight, 1st round' , 'Expert', 606, 250 ], [ 'Young Patty' , 'Young Zeff Fortnight' , 'Expert', 608, 50 ], [ 'Young Carne' , 'Young Zeff Fortnight' , 'Expert', 609, 50 ], @@ -130,12 +130,12 @@ window.defenses = [ [ 'Keimi' , 'Keimi Fortnight' , 'Expert', 635, 100 ], [ 'Keimi (def up)' , 'Keimi Fortnight' , 'Expert', 635, 1000 ], [ 'Young Kuroobi' , 'Young Arlong Fortnight' , 'Expert', 657, 500 ], - // [ 'Young Choo' , 'Expert', 657, ? ], + // [ 'Young Choo' , 'Expert', 657, ? ], [ 'Young Arlong' , 'Young Arlong Fortnight' , 'Expert', 656, 400 ], [ 'Young Kohza' , 'Suna Suna Clan Fortnight' , 'Expert', 665, 50 ], [ 'Young Vivi' , 'Suna Suna Clan Fortnight, last round' , 'Expert', 664, 1100 ], [ 'Young Kohza' , 'Suna Suna Clan Fortnight, last round' , 'Expert', 665, 50 ], - // [ 'Cobra' , 'Fortnight' , 'Expert', 666, ? ], + // [ 'Cobra' , 'Fortnight' , 'Expert', 666, ? ], [ 'Noland' , 'Noland Fortnight, mid round' , 'Expert', 689, 300 ], [ 'Calgara' , 'Noland Fortnight, mid round' , 'Expert', 688, 300 ], [ 'Noland (last round)' , 'Nolad Fortnight, last round' , 'Expert', 690, 350 ], @@ -184,15 +184,15 @@ window.defenses = [ [ 'Mr. 3' , 'Mountaintop Banquet Fortnight' , 'Expert', 898, 150 ] , [ 'Crocodile' , 'Mountaintop Banquet Fortnight' , 'Expert', 897, 1000 ] , [ 'Crocodile (def up)' , 'Mountaintop Banquet Fortnight' , 'Expert', 897, 30000 ] , - /* * * * * Colosseum * * * * */ - [ 'Dr. Kureha' , 'Colosseum, 1st Hina Round' , 'Chaos' , 333, 20 ], - [ 'Hotori and Kotori' , 'Colosseum, 2nd Hina Round' , 'Chaos' , 504, 250 ], - [ 'Hamburg' , 'Colosseum, 3rd Hina Round' , 'Chaos' , 565, 200 ], - [ 'Pickles' , 'Colosseum, 3rd Hina Round' , 'Chaos' , 566, 250 ], - [ 'Big Pan' , 'Colosseum, 3rd Hina Round' , 'Chaos' , 567, 250 ], - [ 'Pell' , 'Colosseum, 4th Hina Round' , 'Chaos' , 505, 150 ], - [ 'Pell' , 'Colosseum, 5th Hina Round' , 'Chaos' , 505, 150 ], - [ 'Hina' , 'Colosseum, 5th Hina Round' , 'Chaos' , 804, 150 ], + /* * * * * Coliseum * * * * */ + [ 'Dr. Kureha' , 'Coliseum, 1st Hina Round' , 'Chaos' , 333, 20 ], + [ 'Hotori and Kotori' , 'Coliseum, 2nd Hina Round' , 'Chaos' , 504, 250 ], + [ 'Hamburg' , 'Coliseum, 3rd Hina Round' , 'Chaos' , 565, 200 ], + [ 'Pickles' , 'Coliseum, 3rd Hina Round' , 'Chaos' , 566, 250 ], + [ 'Big Pan' , 'Coliseum, 3rd Hina Round' , 'Chaos' , 567, 250 ], + [ 'Pell' , 'Coliseum, 4th Hina Round' , 'Chaos' , 505, 150 ], + [ 'Pell' , 'Coliseum, 5th Hina Round' , 'Chaos' , 505, 150 ], + [ 'Hina' , 'Coliseum, 5th Hina Round' , 'Chaos' , 804, 150 ], /* * * * * Others * * * * */ [ 'Thatch' , 'Whitebeard\'s island, 11th round' , '', 448, 50 ], [ 'Namur' , 'Whitebeard\'s island, 12th round' , '', 450, 500 ], @@ -237,12 +237,12 @@ window.defenses = [ [ 'Garp' , 'Aokiji\'s island, 19th round' , '', 306, 500 ], [ 'Sengoku' , 'Aokiji\'s island, 19th round' , '', 458, 1000 ], [ 'Aokiji' , 'Aokiji\'s island, 20th round' , '', 575, 500 ], - // Turtles + /* * * * * Turtles * * * * */ [ 'Baby Turtle' , '' , '', 109, 10000 ], [ 'Adult Turtle' , '' , '', 114, 20000 ], [ 'Elder Turtle' , '' , '', 193, 100000 ], [ 'Princess Turtle' , '' , '', 595, 500000 ], - // Evolvers + /* * * * * Evolvers * * * * */ [ 'Hermit Crab' , '' , '', 93, 2000 ], [ 'Armored Crab' , '' , '', 99, 10000 ], [ 'Plated Lobster' , '' , '', 304, 100000 ] diff --git a/common/data/details.js b/common/data/details.js index 2be75457f..db31deae3 100644 --- a/common/data/details.js +++ b/common/data/details.js @@ -1,4260 +1,13925 @@ window.details = { - 1: { - special: "Deals 5x character's ATK in STR damage to one enemy", - specialName: "Spinning Gum Punch" - }, - 2: { - special: "Deals 7x character's ATK in STR damage to one enemy", - specialName: "Gum-Gum Pistol", - captain: "Boosts ATK of STR characters by 1.5x" - }, - 3: { - special: "Deals 15x character's ATK in STR damage to one enemy", - specialName: "Gum-Gum Bazooka", - captain: "Boosts ATK of STR characters by 1.5x" - }, - 4: { - special: "Deals 25x character's ATK in STR damage to one enemy", - specialName: "Gum-Gum Twin Jet Pistol", - captain: "Boosts ATK of STR characters by 2x" - }, - 5: { - special: "Deals 7x character's ATK in DEX damage to one enemy", - specialName: "Oni Giri", - captain: "Boosts ATK of DEX characters by 1.5x" - }, - 6: { - special: "Deals 10x character's ATK in DEX damage to all enemies", - specialName: "Three Thousand Worlds", - captain: "Boosts ATK of DEX characters by 1.5x" - }, - 7: { - special: "Deals 10x character's ATK in DEX damage to all enemies", - specialName: "108 Pound Phoenix", - captain: "Boosts ATK of DEX characters by 1.5x" - }, - 8: { - special: "Deals 15x character's ATK in DEX damage to all enemies", - specialName: "Ashura Ichibugin", - captain: "Boosts ATK and HP of DEX characters by 2x" - }, - 9: { - special: "Recovers 1,000 HP", - specialName: "Cat Burglar", - captain: "Reduces damage received from INT enemies by 20%" - }, - 10: { - special: "Deals 15x character's ATK in INT damage to one enemy", - specialName: "Tornado Tempo", - captain: "Boosts ATK of INT characters by 1.5x" - }, - 11: { - special: "Reduces damage received from INT enemies by 100% for 1 turn", - specialName: "Mirage Tempo", - captain: "Boosts ATK of INT characters by 1.5x" - }, - 12: { - special: "Deals 15x character's ATK in INT damage to all enemies", - specialName: "Thunderbolt Tempo", - captain: "Boosts ATK and HP of INT characters by 1.5x" - }, - 13: { - special: "Delays all enemies for 1 turn", - specialName: "Liar", - captain: "Boosts ATK of Shooter characters by 1.2x" - }, - 14: { - special: "Delays all enemies for 2 turns", - specialName: "Tabasco Star", - captain: "Boosts ATK of PSY characters by 1.5x" - }, - 15: { - special: "Delays all enemies for 3 turns", - specialName: "Usopp Golden Pound", - captain: "Boosts ATK of PSY characters by 1.5x" - }, - 16: { - special: "Delays all enemies for 3 turns, deals 15x character's ATK in PSY damage to all enemies", - specialName: "Fire Bird Star", - captain: "Boosts ATK and HP of PSY characters by 1.5x" - }, - 17: { - special: "Recovers 10x character's RCV in HP", - specialName: "Special Fried Rice", - captain: "Boosts ATK of QCK characters by 1.5x" - }, - 18: { - special: "Reduces the defense of all enemies by 50% for 2 turns", - specialName: "Plastic Surgery Shot", - captain: "Boosts HP of QCK characters by 1.5x" - }, - 19: { - special: "Recovers 10x character's RCV in HP", - specialName: "Hot Rock Stew", - captain: "Boosts ATK of QCK characters by 1.5x" - }, - 20: { - special: "Deals 5,000 fixed damage to all enemies", - specialName: "Diable Jambe", - specialNotes: "#{fixed}", - captain: "Boosts ATK and HP of QCK characters by 1.5x" - }, - 21: { - special: "Changes adjacent orbs into [RCV] orbs", - specialName: "Hearty Yell", - captain: "Boosts RCV of PSY characters by 1.2x" - }, - 22: { - special: "Deals 15x character's ATK in PSY damage to one enemy", - specialName: "Heavy Gong", - captain: "Boosts RCV of PSY characters by 1.5x" - }, - 23: { - special: "Changes adjacent orbs into [RCV] orbs", - specialName: "Scope", - captain: "Boosts RCV of INT characters by 1.5x" - }, - 24: { - special: "Reduces the defense of all enemies by 50% for 2 turns", - specialName: "Hoofprint Roseo", - captain: "Boosts RCV of STR characters by 1.5x" - }, - 25: { - special: "Deals 7x character's ATK in QCK damage to all enemies", - specialName: "Horn Point Roseo Colonnade", - captain: "Boosts RCV of QCK characters by 1.5x" - }, - 26: { - special: "Reduces damage received by 50% for 3 turns", - specialName: "Guard Point", - captain: "Boosts RCV of DEX characters by 1.5x" - }, - 27: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Slash", - captain: "Boosts HP of QCK characters by 1.2x" - }, - 28: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Straight", - captain: "Boosts ATK of Fighter characters by 1.2x" - }, - 29: { - special: "Deals 7x character's ATK in STR damage to one enemy", - specialName: "Iron Mace Beauty", - captain: "Reduces damage received from STR enemies by 30%" - }, - 30: { - special: "Reduces damage received by 80% for 1 turn", - specialName: "Slip-Slip Tracks", - captain: "Reduces damage received from STR enemies by 50%" - }, - 31: { - captain: "Recovers 2x character's RCV in HP at the end of each turn" - }, - 32: { - special: "Changes [RCV] orbs into [TND] orbs", - specialName: "Shooting Spree", - captain: "Recovers 2x character's RCV in HP at the end of each turn" - }, - 33: { - captain: "Reduces damage received from INT enemies by 30%" - }, - 34: { - special: "Reduces the defense of all enemies by 100% for 1 turn", - specialName: "Straw Doll Of Resentment", - captain: "Reduces damage received from INT enemies by 30%" - }, - 35: { - special: "Deals 5x character's ATK in STR damage to one enemy", - specialName: "Execution Axe-Hand", - captain: "Boosts HP of Slasher characters by 1.2x" - }, - 36: { - special: "Deals 5x character's ATK in PSY damage to one enemy", - specialName: "Fierce Bite", - captain: "Boosts ATK of PSY characters by 1.5x" - }, - 37: { - special: "Deals 5x character's ATK in DEX damage to one enemy", - specialName: "The Dance Of A Hundred Kamikaze Tops", - captain: "Boosts ATK of DEX characters by 1.5x" - }, - 38: { - special: "Changes [RCV] orbs into [INT] orbs", - specialName: "Chop-Chop Festival", - captain: "Boosts ATK of INT characters by 1.5x" - }, - 39: { - special: "Changes [RCV] orbs into [INT] orbs", - specialName: "Chop-Chop Festival", - captain: "Boosts ATK of INT characters by 2x" - }, - 40: { - special: "Changes adjacent orbs into [RCV] orbs", - specialName: "[RCV] Slot Storm", - captain: "Reduces damage received from Shooter enemies by 30%" - }, - 41: { - special: "Changes [RCV] orbs into [INT] orbs", - specialName: "Cat Snatch", - captain: "Boosts RCV of INT characters by 1.2x" - }, - 42: { - special: "Deals 3x character's ATK in STR damage to all enemies", - specialName: "Cat-A-Pult Cat-Astrophe", - captain: "Boosts ATK of STR characters by 1.2x" - }, - 43: { - special: "Changes [RCV] orbs into [DEX] orbs", - specialName: "One, Two, Django", - captain: "Reduces damage received by 10%" - }, - 44: { - special: "Changes [RCV] orbs into [DEX] orbs", - specialName: "Dance Heaven", - captain: "Reduces damage received by 10%" - }, - 45: { - special: "Deals 5x character's ATK in QCK damage to all enemies", - specialName: "Death Scoop", - captain: "Boosts ATK of QCK characters by 1.2x" - }, - 46: { - special: "Deals 5x character's ATK in QCK damage to all enemies", - specialName: "Death Scoop", - captain: "Boosts ATK of QCK characters by 1.5x" - }, - 47: { - special: "Changes [TND] orbs into [RCV] orbs", - specialName: "[TND] Slot Change [RCV]" - }, - 48: { - special: "Changes adjacent orbs into [RCV] orbs", - specialName: "[RCV] Slot Storm" - }, - 49: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Straight", - captain: "Boosts ATK of STR characters by 1.5x" - }, - 50: { - special: "Deals 5x character's ATK in STR damage to one enemy", - specialName: "The Meatball Of Doom", - captain: "Recovers 4x character's RCV in HP at the end of each turn" - }, - 51: { - captain: "Recovers 3x character's RCV in HP at the end of each turn" - }, - 52: { - special: "Changes [STR] orbs into [DEX] orbs", - specialName: "Chef Drop", - captain: "Boosts ATK of Fighter characters by 2.5x" - }, - 53: { - captain: "Reduces damage received from QCK enemies by 30%" - }, - 54: { - special: "Deals 7x character's ATK in QCK damage to one enemy", - specialName: "Demonic Dance", - captain: "Reduces damage received from QCK enemies by 50%" - }, - 55: { - captain: "Reduces damage received from STR enemies by 30%" - }, - 56: { - special: "Changes [RCV] orbs into [STR] orbs", - specialName: "Fire Pearl Privilege", - captain: "Reduces damage received from STR enemies by 50%" - }, - 57: { - special: "Deals 7x character's ATK in INT damage to one enemy", - specialName: "Chain Hammer", - captain: "Reduces damage received by 10%" - }, - 58: { - special: "Poisons all enemies", - specialNotes: "#{poison}", - specialName: "MH5", - captain: "Reduces damage received by 20%" - }, - 59: { - special: "Changes [PSY] orbs into [INT] orbs", - specialName: "[PSY] Slot Change [INT]", - captain: "Boosts ATK of INT characters by 1.2x" - }, - 60: { - special: "Changes [TND] orbs into [STR] orbs", - specialName: "[TND] Slot Change [STR]", - captain: "Boosts ATK of STR characters by 1.5x" - }, - 61: { - special: "Deals 5x character's ATK in INT damage to all enemies", - specialName: "Lip-O-Cannon", - captain: "Boosts HP of Shooter characters by 1.5x" - }, - 62: { - special: "Deals 7x character's ATK in STR damage to one enemy", - specialName: "Guffaw Palm Bomb", - captain: "Boosts HP of Fighter characters by 1.5x" - }, - 63: { - captain: "Reduces damage received from DEX enemies by 30%" - }, - 64: { - special: "Deals 10x character's ATK in DEX damage to all enemies", - specialName: "New Year's Open Body Slam", - captain: "Reduces damage received from DEX enemies by 50%" - }, - 65: { - special: "Deals 7x character's ATK in STR damage to one enemy", - specialName: "Shark On Darts", - captain: "Boosts ATK of Slasher characters by 2x" - }, - 66: { - special: "Deals 15x character's ATK in STR damage to one enemy", - specialName: "Shark On Tooth", - captain: "Boosts ATK of Slasher characters by 2x" - }, - 67: { - special: "Deals 25x character's ATK in QCK damage to one enemy", - specialName: "Quick Draw", - captain: "Boosts RCV of Slasher characters by 1.5x" - }, - 68: { - special: "Deals 25x character's ATK in QCK damage to one enemy", - specialName: "Quick Draw", - captain: "Boosts RCV of Slasher characters by 2x" - }, - 69: { - special: "Reduces damage received by 50% for 3 turns", - specialName: "White Out", - captain: "Reduces damage received by 20%" - }, - 70: { - special: "Reduces damage received by 50% for 3 turns", - specialName: "White Out", - captain: "Reduces damage received by 20%" - }, - 71: { - special: "Reduces damage received by 50% for 1 turn", - specialName: "Enchanting Vertigo Dance", - captain: "Recovers 2x character's RCV in HP at the end of each turn" - }, - 72: { - special: "Randomizes all orbs", - specialName: "Charge! Supersonic Duck Squadron!", - captain: "Recovers 3x character's RCV in HP at the end of each turn" - }, - 73: { - special: "Randomizes all orbs", - specialName: "Charge! Supersonic Duck Squadron!", - captain: "Recovers 5x character's RCV in HP at the end of each turn" - }, - 74: { - special: "Deals 25x character's ATK in QCK damage to one enemy", - specialName: "Flame Fist", - captain: "Boosts ATK of QCK characters by 2x" - }, - 75: { - special: "Deals 15x character's ATK in QCK to all enemies", - specialName: "Flame Mirror", - captain: "Boosts ATK of QCK characters by 2.5x" - }, - 76: { - special: "Deals 15x character's ATK in PSY damage to all enemies", - specialName: "Conqueror's Haki", - captain: "Boosts ATK of PSY characters by 2x" - }, - 77: { - special: "Deals 15x character's ATK in PSY damage to all enemies", - specialName: "Conqueror's Haki", - captain: "Boosts ATK of PSY characters by 2.5x" - }, - 119: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Slash" - }, - 120: { - special: "Deals 5x character's ATK in character's type damage to all enemies", - specialName: "Hyper Shot" - }, - 121: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Straight" - }, - 122: { - special: "Reduces damage received by 20% for 1 turn", - specialName: "Iron Shield" - }, - 123: { - special: "Changes [STR] orbs into [DEX] orbs", - specialName: "[STR] Slot Change [DEX]" - }, - 124: { - special: "Reduces damage received by 20% for 1 turn", - specialName: "Iron Shield" - }, - 125: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Straight" - }, - 126: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Slash" - }, - 127: { - special: "Reduces the defense of all enemies by 50% for 1 turn", - specialName: "Shield Crusher" - }, - 128: { - special: "Changes [QCK] orbs into [DEX] orbs", - specialName: "[QCK] Slot Change [DEX]" - }, - 129: { - special: "Changes [INT] orbs into [PSY] orbs", - specialName: "[INT] Slot Change [PSY]" - }, - 130: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Slash" - }, - 131: { - special: "Changes [RCV] orbs into [STR] orbs", - specialName: "[RCV] Slot Change [STR]" - }, - 132: { - special: "Changes [DEX] orbs into [QCK] orbs", - specialName: "[DEX] Slot Change [QCK]" - }, - 133: { - special: "Changes [QCK] orbs into [DEX] orbs", - specialName: "[QCK] Slot Change [DEX]" - }, - 134: { - special: "Changes [QCK] orbs into [RCV] orbs", - specialName: "[QCK] Slot Change [RCV]" - }, - 135: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Spiral" - }, - 136: { - special: "Deals 5x character's ATK in character's type damage to all enemies", - specialName: "Hyper Shot" - }, - 137: { - special: "Reduces the defense of all enemies by 50% for 1 turn", - specialName: "Shield Crusher" - }, - 138: { - special: "Changes [DEX] orbs into [RCV] orbs", - specialName: "[DEX] Slot Change [RCV]" - }, - 139: { - special: "Changes [PSY] orbs into [RCV] orbs", - specialName: "[PSY] Slot Change [RCV]" - }, - 140: { - special: "Deals 5x character's ATK in character's type damage to all enemies", - specialName: "Hyper Shot" - }, - 141: { - special: "Reduces damage received by 20% for 1 turn", - specialName: "Iron Shield" - }, - 142: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Straight" - }, - 143: { - special: "Reduces damage received by 20% for 1 turn", - specialName: "Iron Shield" - }, - 144: { - special: "Changes [STR] orbs into [DEX] orbs", - specialName: "[STR] Slot Change [DEX]" - }, - 145: { - special: "Reduces damage received by 20% for 1 turn", - specialName: "Iron Shield" - }, - 146: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Straight" - }, - 147: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Slash" - }, - 148: { - special: "Reduces the defense of all enemies by 50% for 1 turn", - specialName: "Shield Crusher" - }, - 149: { - special: "Changes [QCK] orbs into [DEX] orbs", - specialName: "[QCK] Slot Change [DEX]" - }, - 150: { - special: "Changes [INT] orbs into [PSY] orbs", - specialName: "[INT] Slot Change [PSY]" - }, - 151: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Slash" - }, - 152: { - special: "Changes [RCV] orbs into [STR] orbs", - specialName: "[RCV] Slot Change [STR]" - }, - 153: { - special: "Changes [DEX] orbs into [QCK] orbs", - specialName: "[DEX] Slot Change [QCK]" - }, - 154: { - special: "Changes [QCK] orbs into [DEX] orbs", - specialName: "[QCK] Slot Change [DEX]" - }, - 155: { - special: "Changes [QCK] orbs into [RCV] orbs", - specialName: "[QCK] Slot Change [RCV]" - }, - 156: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Spiral" - }, - 157: { - special: "Deals 5x character's ATK in character's type damage to all enemies", - specialName: "Hyper Shot" - }, - 158: { - special: "Reduces the defense of all enemies by 50% for 1 turn", - specialName: "Shield Crusher" - }, - 159: { - special: "Changes [DEX] orbs into [RCV] orbs", - specialName: "[DEX] Slot Change [RCV]" - }, - 160: { - special: "Changes [PSY] orbs into [RCV] orbs", - specialName: "[PSY] Slot Change [RCV]" - }, - 161: { - special: "Deals 5x character's ATK in character's type damage to all enemies", - specialName: "Hyper Shot" - }, - 162: { - special: "Reduces damage received by 20% for 1 turn", - specialName: "Iron Shield" - }, - 163: { - special: "Changes [DEX] orbs into [TND] orbs", - specialName: "[DEX] Slot Change [TND]" - }, - 164: { - special: "Changes [QCK] orbs into [TND] orbs", - specialName: "[QCK] Slot Change [TND]" - }, - 165: { - special: "Recovers 5x character's RCV in HP", - specialName: "Light Healing" - }, - 166: { - special: "Recovers 5x character's RCV in HP", - specialName: "Light Healing" - }, - 167: { - special: "Recovers 5x character's RCV in HP", - specialName: "Light Healing" - }, - 168: { - special: "Recovers 5x character's RCV in HP", - specialName: "Light Healing" - }, - 169: { - special: "Recovers 5x character's RCV in HP", - specialName: "Light Healing" - }, - 170: { - special: "Reduces damage received by 20% for 1 turn", - specialName: "Iron Shield" - }, - 171: { - special: "Reduces damage received by 20% for 1 turn", - specialName: "Iron Shield" - }, - 172: { - special: "Reduces damage received by 20% for 1 turn", - specialName: "Iron Shield" - }, - 173: { - special: "Reduces damage received by 20% for 1 turn", - specialName: "Iron Shield" - }, - 174: { - special: "Reduces damage received by 20% for 1 turn", - specialName: "Iron Shield" - }, - 175: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Straight" - }, - 176: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Slash" - }, - 177: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Spiral" - }, - 178: { - special: "Deals 5x character's ATK in character's type damage to all enemies", - specialName: "Hyper Shot" - }, - 179: { - special: "Changes [QCK] orbs into [STR] orbs", - specialName: "[QCK] Slot Change [STR]" - }, - 180: { - special: "Recovers 5x character's RCV in HP", - specialName: "Light Healing" - }, - 181: { - special: "Changes [STR] orbs into [QCK] orbs", - specialName: "[STR] Slot Change [QCK]" - }, - 182: { - special: "Recovers 5x character's RCV in HP", - specialName: "Light Healing" - }, - 183: { - special: "Changes [RCV] orbs into [INT] orbs", - specialName: "[RCV] Slot Change [INT]" - }, - 184: { - special: "Changes [QCK] orbs into [STR] orbs", - specialName: "[QCK] Slot Change [STR]" - }, - 185: { - special: "Recovers 5x character's RCV in HP", - specialName: "Light Healing" - }, - 186: { - special: "Changes [STR] orbs into [QCK] orbs", - specialName: "[STR] Slot Change [QCK]" - }, - 187: { - special: "Recovers 5x character's RCV in HP", - specialName: "Light Healing" - }, - 188: { - special: "Changes [RCV] orbs into [INT] orbs", - specialName: "[RCV] Slot Change [INT]" - }, - 194: { - special: "Changes [QCK] orbs into [STR] orbs", - specialName: "[QCK] Slot Change [STR]", - captain: "Boosts ATK of STR characters by 1.5x" - }, - 195: { - special: "Recovers 5x character's RCV in HP", - specialName: "Light Healing", - captain: "Boosts RCV of DEX characters by 1.5x" - }, - 196: { - special: "Changes [STR] orbs into [QCK] orbs", - specialName: "[STR] Slot Change [QCK]", - captain: "Boosts ATK of QCK characters by 1.5x" - }, - 197: { - special: "Recovers 5x character's RCV in HP", - specialName: "Light Healing", - captain: "Reduces damage received from PSY enemies by 20%" - }, - 198: { - special: "Changes [RCV] orbs into [INT] orbs", - specialName: "[RCV] Slot Change [INT]", - captain: "Boosts ATK of Shooter characters by 1.5x" - }, - 199: { - special: "Deals 15x character's ATK in STR damage to one enemy", - specialName: "Nez-Palm Cannon", - captain: "Boosts ATK of STR characters by 1.5x" - }, - 200: { - special: "Deals 20x character's ATK in STR damage to one enemy", - specialName: "Breeze Breath Bomb", - captain: "Boosts ATK of STR characters by 2x" - }, - 201: { - captain: "Boosts HP of Fighter characters by 1.5x" - }, - 202: { - special: "Changes [RCV] orbs into [QCK] orbs", - specialName: "10,000 Kill-O-Guillotine", - captain: "Boosts HP of Fighter characters by 2x" - }, - 203: { - captain: "Reduces damage received from INT enemies by 10%" - }, - 204: { - special: "Delays all enemies for 1 turn", - specialName: "Extra Special Candelabra", - captain: "Reduces damage received from INT enemies by 10%" - }, - 205: { - captain: "Boosts HP and RCV of DEX characters by 1.2x" - }, - 206: { - special: "Reduces the defense of all enemies by 50% for 2 turns", - specialName: "Colors Trap: Calming Green", - captain: "Boosts HP and RCV of DEX characters by 1.2x" - }, - 207: { - captain: "Reduces damage received from PSY enemies by 10%" - }, - 208: { - special: "Changes [RCV] orbs into [PSY] orbs", - specialName: "Bombardier Arabesque", - captain: "Reduces damage received from PSY enemies by 20%" - }, - 209: { - special: "Boosts ATK of INT characters by 1.5x for 1 turn", - specialName: "Dieciseis Fleur", - captain: "Boosts RCV of INT characters by 1.5x" - }, - 210: { - special: "Boosts ATK of INT characters by 2x for 1 turn", - specialName: "Cien Fleur", - captain: "Boosts RCV of INT characters by 2x" - }, - 211: { - captain: "Boosts ATK of Striker characters by 1.2x" - }, - 212: { - special: "Deals 5x character's ATK in QCK damage to one enemy", - specialName: "Hot Blooded Bat", - captain: "Boosts ATK of Striker characters by 1.5x" - }, - 213: { - special: "Deals 20x character's ATK in STR damage to all enemies", - specialName: "Sorrowful Charge", - captain: "Protects from defeat as long as HP is above 50%", - captainNotes: "#{zombie}" - }, - 214: { - special: "Deals 20x character's ATK in STR damage to all enemies", - specialName: "Sorrowful Charge", - captain: "Protects from defeat as long as HP is above 50%", - captainNotes: "#{zombie}" - }, - 215: { - special: "Poisons all enemies", - specialNotes: "#{poison}", - specialName: "Poison Ink", - captain: "Boosts HP of Striker characters by 1.5x" - }, - 216: { - special: "Reduces damage received by 50% for 3 turns", - specialName: "Gum-Gum Balloon", - captain: "Reduces damage received by 20%" - }, - 217: { - special: "Deals 15x character's ATK in STR damage to all enemies", - specialName: "Gum-Gum Giant Rifle", - captain: "Boosts ATK by 3.5x after scoring 3 Perfects in a row" - }, - 218: { - special: "Reduces damage received from STR enemies by 100% for 1 turn", - specialName: "Streaming Wolf Swords", - captain: "Reduces damage received by 80% if HP is above 99% at the start of the turn" - }, - 219: { - special: "Deals 25x character's ATK in DEX damage to one enemy", - specialName: "Lion's Song", - captain: "Reduces damage received by 80% if HP is above 99% at the start of the turn" - }, - 220: { - special: "Changes [PSY] orbs into [INT] orbs", - specialName: "Fine Tempo", - captain: "Boosts ATK of INT characters by 2x" - }, - 221: { - special: "Changes [PSY] orbs into [INT] orbs", - specialName: "Happiness Punch", - captain: "Boosts ATK of INT characters by 2.5x" - }, - 222: { - special: "Boosts ATK of PSY characters by 1.5x for 1 turn", - specialName: "Usopp Hammer", - captain: "Boosts ATK of PSY characters by 1.2x" - }, - 223: { - special: "Boosts ATK of PSY characters by 2x for 1 turn", - specialName: "Impact", - captain: "Boosts ATK of PSY characters by 1.5x" - }, - 224: { - special: "Deals 15x character's ATK in QCK damage to one enemy", - specialName: "Mutton Shot", - captain: "Boosts ATK by 2x after scoring 2 Perfects in a row" - }, - 225: { - special: "Deals 20x character's ATK in QCK damage to one enemy", - specialName: "Veau Shot", - captain: "Boosts ATK by 2.5x after scoring 2 Perfects in a row" - }, - 226: { - special: "Cuts the current HP of each enemy by 30%", - specialName: "Black Blade Ship Cutter", - captain: "Boosts ATK of Slasher characters by 2x" - }, - 227: { - special: "Cuts the current HP of each enemy by 30%", - specialName: "Black Blade Ship Cutter", - captain: "Boosts ATK of Slasher characters by 2.5x" - }, - 228: { - special: "Reduces Bind duration by 2 turns", - specialName: "Escapee Axe-Hand", - captain: "Boosts HP of Slasher characters by 1.5x" - }, - 229: { - special: "Changes [INT] orbs into [PSY] orbs", - specialName: "Double Cross Dance", - captain: "Reduces damage received by 10%" - }, - 230: { - special: "Deals 200 fixed damage to one enemy", - specialName: "Double Hyper Straight", - specialNotes: "#{fixed}", - captain: "Boosts ATK of STR characters by 1.5x" - }, - 231: { - special: "Locks all orbs for 1 turn", - specialName: "Kimono Sleeve Cage", - captain: "Boosts ATK of QCK characters by 2x" - }, - 232: { - special: "Locks all orbs for 1 turn", - specialName: "Kimono Sleeve Cage", - captain: "Boosts ATK of QCK characters by 2x" - }, - 233: { - captain: "Boosts HP of PSY characters by 1.5x" - }, - 234: { - special: "Deals 5x character's ATK in PSY damage to all enemies", - specialName: "Igarappapa", - captain: "Boosts HP of PSY characters by 2x" - }, - 235: { - captain: "Boosts ATK of Fighter characters by 1.2x" - }, - 236: { - special: "Deals 20x character's ATK in STR damage to one enemy", - specialName: "Superhuman Brass Knuckles", - captain: "Boosts ATK of Fighter characters by 1.5x" - }, - 237: { - special: "Changes [DEX] orbs into [STR] orbs", - specialName: "[DEX] Slot Change [STR]" - }, - 238: { - special: "Changes [TND] orbs into [DEX] orbs", - specialName: "[TND] Slot Change [DEX]" - }, - 239: { - special: "Changes [TND] orbs into [QCK] orbs", - specialName: "[TND] Slot Change [QCK]" - }, - 240: { - special: "Changes [STR] orbs into [PSY] orbs", - specialName: "[STR] Slot Change [PSY]" - }, - 241: { - special: "Changes [QCK] orbs into [INT] orbs", - specialName: "[QCK] Slot Change [INT]" - }, - 242: { - special: "Changes [DEX] orbs into [STR] orbs", - specialName: "[DEX] Slot Change [STR]" - }, - 243: { - special: "Changes [TND] orbs into [DEX] orbs", - specialName: "[TND] Slot Change [DEX]" - }, - 244: { - special: "Changes [TND] orbs into [QCK] orbs", - specialName: "[TND] Slot Change [QCK]" - }, - 245: { - special: "Changes [STR] orbs into [PSY] orbs", - specialName: "[STR] Slot Change [PSY]" - }, - 246: { - special: "Changes [QCK] orbs into [INT] orbs", - specialName: "[QCK] Slot Change [INT]" - }, - 247: { - special: "Recovers 1,224 HP", - specialName: "Kyuun Spark", - captain: "Reduces damage received by 10%" - }, - 248: { - special: "Deals random STR damage to one enemy", - specialName: "Rampage", - specialNotes: "#{random : 2,000 : 200,000}", - captain: "Boosts ATK of STR characters by 2.5x and reduces their HP by 60%" - }, - 249: { - special: "Deals random STR damage to one enemy", - specialName: "Rampage", - specialNotes: "#{random : 2,000 : 200,000}", - captain: "Boosts ATK of STR characters by 3x and reduces their HP by 60%" - }, - 250: { - special: "Recovers all HP", - specialName: "Blue Flame Rebirth", - captain: "Boosts ATK of PSY characters by 3x if HP is above 99% at the start of the turn" - }, - 251: { - special: "Recovers all HP", - specialName: "Blue Flame Rebirth", - captain: "Boosts ATK of PSY characters by 3x if HP is above 99% at the start of the turn" - }, - 252: { - special: "Reduces damage received from DEX enemies by 100% for 1 turn", - specialName: "Brilliant Punk", - captain: "Boosts ATK and HP of QCK characters by 2x" - }, - 253: { - special: "Reduces damage received from DEX enemies by 100% for 1 turn", - specialName: "Brilliant Punk", - captain: "Boosts ATK and HP of QCK characters by 2x" - }, - 254: { - special: "Deals 5,000 fixed damage to all enemies", - specialName: "Rose Rondo", - specialNotes: "#{fixed}", - captain: "Boosts ATK and HP of INT characters by 2x" - }, - 255: { - special: "Deals 5,000 fixed damage to all enemies", - specialName: "Rose Rondo", - specialNotes: "#{fixed}", - captain: "Boosts ATK and HP of INT characters by 2x" - }, - 256: { - special: "Changes [STR] and [QCK] orbs into [DEX] orbs", - specialName: "Beautiful Dual Flintlocks", - captain: "Boosts ATK and RCV of DEX characters by 2x" - }, - 257: { - special: "Changes [STR] and [QCK] orbs into [DEX] orbs", - specialName: "Beautiful Dual Flintlocks", - captain: "Boosts ATK and RCV of DEX characters by 2x" - }, - 258: { - special: "Changes [DEX] and [QCK] orbs into [STR] orbs", - specialName: "Pocket Mallet", - captain: "Boosts ATK and RCV of STR characters by 2x" - }, - 259: { - special: "Changes [DEX] and [QCK] orbs into [STR] orbs", - specialName: "Pocket Mallet", - captain: "Boosts ATK and RCV of STR characters by 2x" - }, - 260: { - special: "Cuts the current HP of each enemy by 30%", - specialName: "Seaquake", - captain: "Boosts ATK of all characters by 3x if HP is below 30% at the start of the turn" - }, - 261: { - special: "Cuts the current HP of each enemy by 30%", - specialName: "Seaquake", - captain: "Boosts ATK of all characters by 3x if HP is below 30% at the start of the turn" - }, - 262: { - captain: "Recovers 2x character's RCV in HP at the end of each turn" - }, - 263: { - special: "Amplifies the effect of orbs by 1.5x for 2 turns", - specialNotes: "#{orb : 1.5x}", - specialName: "Shave", - captain: "Boosts ATK of Fighter characters by 2x" - }, - 264: { - captain: "Reduces damage received from INT enemies by 30%" - }, - 265: { - special: "Reduces Bind duration by 3 turns", - specialName: "Tempered Kukris", - captain: "Boosts ATK and HP of Slasher characters by 1.5x" - }, - 267: { - special: "Reduces the defense of all enemies by 50% for 1 turn", - specialName: "Shield Crusher", - captain: "Boosts ATK of all characters by 1.5x" - }, - 268: { - special: "Reduces damage received by 50% for 3 turns", - specialName: "White Out", - captain: "Reduces damage received by 25%" - }, - 269: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Straight" - }, - 270: { - special: "Reduces damage received by 20% for 1 turn", - specialName: "Iron Shield" - }, - 271: { - special: "Changes [STR] orbs into [DEX] orbs", - specialName: "[STR] Slot Change [DEX]" - }, - 272: { - special: "Reduces damage received by 20% for 1 turn", - specialName: "Iron Shield" - }, - 273: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Straight" - }, - 274: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Slash" - }, - 275: { - special: "Reduces the defense of all enemies by 50% for 1 turn", - specialName: "Shield Crusher" - }, - 276: { - special: "Changes [QCK] orbs into [DEX] orbs", - specialName: "[QCK] Slot Change [DEX]" - }, - 277: { - special: "Changes [INT] orbs into [PSY] orbs", - specialName: "[INT] Slot Change [PSY]" - }, - 278: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Slash" - }, - 279: { - special: "Changes [RCV] orbs into [STR] orbs", - specialName: "[RCV] Slot Change [STR]" - }, - 280: { - special: "Changes [DEX] orbs into [QCK] orbs", - specialName: "[DEX] Slot Change [QCK]" - }, - 281: { - special: "Changes [QCK] orbs into [DEX] orbs", - specialName: "[QCK] Slot Change [DEX]" - }, - 282: { - special: "Changes [QCK] orbs into [RCV] orbs", - specialName: "[QCK] Slot Change [RCV]" - }, - 283: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Spiral" - }, - 284: { - special: "Deals 5x character's ATK in character's type damage to all enemies", - specialName: "Hyper Shot" - }, - 285: { - special: "Reduces the defense of all enemies by 50% for 1 turn", - specialName: "Shield Crusher" - }, - 286: { - special: "Changes [DEX] orbs into [RCV] orbs", - specialName: "[DEX] Slot Change [RCV]" - }, - 287: { - special: "Changes [PSY] orbs into [RCV] orbs", - specialName: "[PSY] Slot Change [RCV]" - }, - 288: { - special: "Deals 5x character's ATK in character's type damage to all enemies", - specialName: "Hyper Shot" - }, - 289: { - special: "Reduces damage received by 20% for 1 turn", - specialName: "Iron Shield" - }, - 290: { - special: "Deals 25x character's ATK in INT damage to one enemy", - specialName: "Judgment Bomb", - captain: "Boosts ATK of Shooter characters by 1.5x" - }, - 291: { - special: "Changes adjacent orbs into [RCV] orbs", - specialName: "[RCV] Slot Storm", - captain: "Reduces damage received from INT enemies by 50%" - }, - 292: { - special: "Changes adjacent orbs into [RCV] orbs", - specialName: "[RCV] Slot Storm", - captain: "Reduces damage received from PSY enemies by 50%" - }, - 293: { - special: "Reduces damage received by 20% for 1 turn", - specialName: "Iron Shield", - captain: "Boosts HP of QCK characters by 2x" - }, - 294: { - special: "Deals 10x character's ATK in character's type damage to one enemy", - specialName: "Hyper Straight", - captain: "Boosts HP of STR characters by 2x" - }, - 295: { - special: "Reduces the defense of all enemies by 50% for 1 turn", - specialName: "Shield Crusher", - captain: "Boosts HP of DEX characters by 2x" - }, - 296: { - special: "Recovers 2,000 HP, randomizes all orbs", - specialName: "Cleansing Wash", - captain: "Boosts ATK of Shooter characters by 2x" - }, - 297: { - special: "Recovers 2,000 HP, randomizes all orbs", - specialName: "Cleansing Wash", - captain: "Boosts ATK of Shooter characters by 2x" - }, - 298: { - special: "Deals 25x character's ATK in PSY damage to one enemy", - specialName: "Moonwalk", - captain: "Boosts HP of PSY characters by 2x" - }, - 299: { - special: "Cuts the current HP of each enemy by 10%", - specialName: "8-Sword Style Onigumo", - captain: "Boosts ATK of DEX characters by 2x" - }, - 305: { - special: "Randomly changes all orbs into either [PSY] or [RCV] orbs", - specialName: "Meteor Fist Shower", - captain: "Boosts ATK and HP of PSY characters by 1.5x" - }, - 306: { - special: "Randomly changes all orbs into either [PSY] or [RCV] orbs", - specialName: "Meteor Fist Shower", - captain: "Boosts ATK and HP of PSY characters by 2x" - }, - 307: { - special: "Randomly changes all orbs other than [DEX] into either [DEX], [RCV] or [TND] orbs", - specialName: "ROOM – Chambres", - captain: "Boosts ATK of DEX characters by 2.5x" - }, - 308: { - special: "Randomly changes all orbs other than [DEX] into either [DEX], [RCV] or [TND] orbs", - specialName: "ROOM – Chambres", - captain: "Boosts ATK of DEX characters by 2.5x" - }, - 309: { - special: "Cuts the current HP of each enemy by 10%, reduces the defense of all enemies by 50% for 3 turns", - specialName: "Demon Face", - captain: "Reduces RCV of all characters by 90%, reduces damage received by 40%" - }, - 310: { - special: "Cuts the current HP of each enemy by 10%, reduces the defense of all enemies by 50% for 3 turns", - specialName: "Demon Face", - captain: "Reduces RCV of all characters by 90%, reduces damage received by 40%" - }, - 311: { - special: "Deals 100x character's ATK in fixed damage to one enemy, reduces crew's HP to 1", - specialName: "Massacre Soldier", - specialNotes: "#{fixed}", - captain: "Boosts ATK by 3.5x after scoring 3 hits below Good in a row" - }, - 312: { - special: "Deals 100x character's ATK in fixed damage to one enemy, reduces crew's HP to 1", - specialName: "Massacre Soldier", - specialNotes: "#{fixed}", - captain: "Boosts ATK by 3.5x after scoring 3 hits below Good in a row" - }, - 313: { - special: "Boosts ATK of Striker characters by 1.5x for 1 turn, deals 25x character's ATK in PSY damage to one enemy", - specialName: "Karmic Punishment", - captain: "Boosts ATK of Striker characters by 2x and their HP by 1.5x" - }, - 314: { - special: "Boosts ATK of Striker characters by 1.5x for 1 turn, deals 25x character's ATK in PSY damage to one enemy", - specialName: "Karmic Punishment", - captain: "Boosts ATK of Striker characters by 2x and their HP by 1.5x" - }, - 315: { - special: "Changes [PSY] and [INT] orbs into [STR] orbs, empties slots with [DEX] and [QCK] orbs", - specialName: "Aye Aye, Captain!", - captain: "Boosts ATK, HP and RCV of Fighter characters by 1.5x" - }, - 316: { - special: "Changes [PSY] and [INT] orbs into [STR] orbs, empties slots with [DEX] and [QCK] orbs", - specialName: "Aye Aye, Captain!", - captain: "Boosts ATK, HP and RCV of Fighter characters by 1.5x" - }, - 317: { - special: "Randomly changes all orbs into either [DEX] or [STR] orbs, deals random DEX damage to all enemies", - specialName: "Beautiful Secretary's Job", - specialNotes: "#{random : 1 : 15,000}", - captain: "Recovers 500 HP at end of turn, reduces damage received by 10%" - }, - 318: { - special: "Randomly changes all orbs into either [DEX] or [STR] orbs, deals random DEX damage to all enemies", - specialName: "Beautiful Secretary's Job", - specialNotes: "#{random : 1 : 15,000}", - captain: "Recovers 1,000 HP at end of turn, reduces damage received by 15%" - }, - 319: { - special: "Locks all orbs for 1 turn", - specialName: "Hook, Line, and Sinker", - captain: "Boosts ATK of Striker characters by 1.5x" - }, - 320: { - special: "Locks all orbs for 1 turn", - specialName: "Hook, Line, and Sinker", - captain: "Boosts ATK of Striker characters by 2x" - }, - 321: { - special: "Deals 25x character's ATK in QCK damage to one enemy", - specialName: "Taciturn Combo", - captain: "Boosts ATK of QCK type characters by 2x" - }, - 322: { - special: "Deals 25x character's ATK in QCK damage to one enemy", - specialName: "Taciturn Combo", - captain: "Boosts ATK of QCK type characters by 2x" - }, - 323: { - special: "Amplifies the effect of orbs by 1.5x for 2 turns", - specialNotes: "#{orb : 1.5x}", - specialName: "Mountain Wind", - captain: "Boosts HP and RCV of QCK characters by 1.5x" - }, - 324: { - special: "Amplifies the effect of orbs by 1.5x for 2 turns", - specialNotes: "#{orb : 1.5x}", - specialName: "Mountain Wind", - captain: "Boosts HP and RCV of QCK characters by 1.5x" - }, - 325: { - special: "Changes [TND] orbs into [RCV] orbs, changes [RCV] orbs into [QCK] orbs", - specialName: "Red-Hot Shipwright Soul" - }, - 326: { - special: "Empties all slots, deals 25x character's ATK in STR damage to one enemy", - specialName: "Munch-Munch Tongue Cannon", - captain: "Recovers 10x character's RCV in HP at the end of each turn" - }, - 327: { - special: "Empties all slots, deals 25x character's ATK in STR damage to one enemy", - specialName: "Munch-Munch Tongue Cannon", - captain: "Recovers 10x character's RCV in HP at the end of each turn" - }, - 328: { - special: "Deals 20x character's ATK in QCK damage to all enemies", - specialName: "Fiddle Banff", - captain: "Boosts RCV of all characters by 5x if HP is below 30% at the start of the turn" - }, - 329: { - special: "Deals 20x character's ATK in QCK damage to all enemies", - specialName: "Fiddle Banff", - captain: "Boosts RCV of all characters by 5x if HP is below 30% at the start of the turn" - }, - 332: { - special: "Changes [STR] orbs into [RCV] orbs, changes [RCV] orbs into [DEX] orbs", - specialName: "Snow-Slicing Blade", - captain: "Boosts ATK, HP and RCV of Striker characters by 1.2x" - }, - 333: { - special: "Recovers a random amount of HP", - specialName: "Doctor Stop", - captain: "Boosts ATK and RCV of PSY and INT characters by 1.5x" - }, - 334: { - special: "Recovers 5x character's RCV in HP", - specialName: "Light Healing" - }, - 335: { - special: "Recovers 5x character's RCV in HP", - specialName: "Light Healing" - }, - 336: { - special: "Switches orbs between slots twice", - specialName: "Franky Centaur", - captain: "Reduces damage received by 10% if HP is above 50% at the start of the turn, boosts ATK of PSY characters by 2x and reduces ATK of every other character by 20% if HP is above 50% at the start of the turn" - }, - 337: { - special: "Switches orbs between slots twice", - specialName: "Franky Centaur", - captain: "Reduces damage received by 10% if HP is above 50% at the start of the turn, boosts ATK of PSY characters by 2.5x and reduces ATK of every other character by 20% if HP is above 50% at the start of the turn" - }, - 338: { - special: "Changes [QCK] orbs into [PSY] orbs", - specialName: "Wavy Square Hair" - }, - 339: { - special: "Changes [INT] orbs into [TND] orbs", - specialName: "Straight Square Hair" - }, - 340: { - special: "Randomly changes all orbs into either [STR] or [QCK] orbs, deals random STR damage to all enemies", - specialName: "Kraken Tentacle Crush", - specialNotes: "#{random : 1 : 15,000}", - captain: "Boosts ATK of Striker characters by 2x" - }, - 341: { - special: "Randomly changes all orbs into either [STR] or [QCK] orbs, deals random STR damage to all enemies", - specialName: "Kraken Tentacle Crush", - specialNotes: "#{random : 1 : 15,000}", - captain: "Boosts ATK of Striker characters by 2x" - }, - 352: { - special: "Boosts ATK of Shooter characters by 1.75x for 2 turns", - specialName: "Smash Buster", - captain: "Boosts ATK of Shooter characters by 2x" - }, - 353: { - special: "Boosts ATK of Shooter characters by 1.75x for 2 turns", - specialName: "Smash Buster", - captain: "Boosts ATK of Shooter characters by 2.5x" - }, - 354: { - special: "Reduces Bind and Silence duration by 3 turns", - specialName: "Two-Sword Dance" - }, - 355: { - special: "Reduces Bind and Silence duration by 3 turns", - specialName: "Two-Sword Dance" - }, - 356: { - special: "Changes own orb into [STR], deals 9x character's ATK in STR damage to all enemies", - specialNotes: "The in-game description is wrong, the special does not deal 7x damage", - specialName: "Steel Magnetic Arm", - captain: "Boosts ATK of Striker characters by 2x" - }, - 357: { - special: "Changes own orb into [STR], deals 9x character's ATK in STR damage to all enemies", - specialNotes: "The in-game description is wrong, the special does not deal 7x damage", - specialName: "Steel Magnetic Arm", - captain: "Boosts ATK of Striker characters by 2.5x" - }, - 358: { - special: "Changes [TND] and [RCV] orbs into [DEX] orbs, deals random DEX damage to all enemies", - specialName: "Scratch Body", - captain: "Boosts ATK of DEX characters by 2.5x if HP is above 99% at the start of the turn", - specialNotes: "#{random : 5,000 : 20,000}" - }, - 359: { - special: "Changes [TND] and [RCV] orbs into [DEX] orbs, deals random DEX damage to all enemies", - specialName: "Scratch Body", - specialNotes: "#{random : 5,000 : 20,000}", - captain: "Boosts ATK of DEX characters by 3x if HP is above 99% at the start of the turn" - }, - 360: { - special: "Deals 10x character's ATK in INT damage to all enemies, protects from defeat as long as HP is above 50% for 1 turn", - specialName: "Prehistoric Power", - specialNotes: "#{zombie}", - captain: "Boosts ATK of INT characters by 3x if HP is below 30% at the start of the turn" - }, - 361: { - special: "Deals 10x character's ATK in INT damage to all enemies, protects from defeat as long as HP is above 50% for 1 turn", - specialName: "Prehistoric Power", - specialNotes: "#{zombie}", - captain: "Boosts ATK of INT characters by 3x if HP is below 30% at the start of the turn" - }, - 362: { - special: "For 2 turns, boosts the amount healed by RCV orbs by 1.5x, then 2x, then 2.5x from the third crew member onward", - specialName: "Big Eater", - captain: "Boosts ATK and RCV of PSY characters by 2x" - }, - 363: { - special: "For 2 turns, boosts the amount healed by RCV orbs by 1.5x, then 2x, then 2.5x from the third crew member onward", - specialName: "Big Eater", - captain: "Boosts ATK and RCV of PSY characters by 2x" - }, - 364: { - special: "Changes [STR] and [DEX] orbs into [QCK] orbs", - specialName: "Gang Fortress", - captain: "Boosts ATK and RCV of QCK characters by 2x" - }, - 365: { - special: "Changes [STR] and [DEX] orbs into [QCK] orbs", - specialName: "Gang Fortress", - captain: "Boosts ATK and RCV of QCK characters by 2x" - }, - 366: { - special: "Deals 20x character's ATK in INT damage to all enemies, reduces Bind duration by 5 turns", - specialName: "Dark King's Aura", - captain: "Boosts chain multiplier by 4x" - }, - 367: { - special: "Deals 20x character's ATK in INT damage to all enemies, reduces Bind duration by 5 turns", - specialName: "Dark King's Aura", - captain: "Boosts chain multiplier by 4x" - }, - 368: { - special: "Reduces damage received from DEX enemies by 50% for 1 turn", - specialName: "Crystal Shield DEX" - }, - 369: { - special: "Reduces damage received from STR enemies by 50% for 1 turn", - specialName: "Crystal Shield STR" - }, - 370: { - special: "Reduces damage received from QCK enemies by 50% for 1 turn", - specialName: "Crystal Shield QCK" - }, - 371: { - special: "Reduces damage received from INT enemies by 50% for 1 turn", - specialName: "Crystal Shield INT" - }, - 372: { - special: "Reduces damage received from PSY enemies by 50% for 1 turn", - specialName: "Crystal Shield PSY" - }, - 373: { - special: "Reduces damage received from DEX enemies by 50% for 1 turn", - specialName: "Crystal Shield DEX", - captain: "Boosts ATK of Slasher characters by 1.5x" - }, - 374: { - special: "Reduces damage received from STR enemies by 50% for 1 turn", - specialName: "Crystal Shield STR", - captain: "Boosts ATK of Shooter characters by 1.5x" - }, - 375: { - special: "Reduces damage received from QCK enemies by 50% for 1 turn", - specialName: "Crystal Shield QCK", - captain: "Boosts HP of Striker characters by 1.5x" - }, - 376: { - special: "Reduces damage received from INT enemies by 50% for 1 turn", - specialName: "Crystal Shield INT", - captain: "Boosts ATK of Fighter characters by 1.5x" - }, - 377: { - special: "Reduces damage received from PSY enemies by 50% for 1 turn", - specialName: "Crystal Shield PSY", - captain: "Boosts ATK of Striker characters by 1.5x" - }, - 378: { - special: "Recovers 3x character's RCV in HP", - specialName: "Quick Healing", - captain: "Boosts RCV of all characters by 1.5x" - }, - 379: { - special: "Removes poison", - specialName: "Dugong Kung Fu Fist of Healing" - }, - 380: { - special: "Removes poison", - specialName: "Dugong Kung Fu Fist of Healing", - captain: "Boosts ATK and RCV of STR characters by 1.5x" - }, - 381: { - special: "Reduces damage received by 20% for 1 turn", - specialName: "Iron Shield" - }, - 382: { - special: "Reduces the defense of all enemies by 50% for 1 turn", - specialName: "Shield Crusher" - }, - 383: { - special: "Strongly poisons one enemy", - specialNotes: "Strong poison deals 5x character's ATK in fixed damage at the end of each turn", - specialName: "Poison Needle", - captain: "Reduces damage received by 10%, boosts ATK of INT characters by 2x" - }, - 384: { - special: "Strongly poisons one enemy", - specialNotes: "Strong poison deals 5x character's ATK in fixed damage at the end of each turn", - specialName: "Poison Needle", - captain: "Reduces damage received by 20%, boosts ATK of INT characters by 2x" - }, - 385: { - special: "Reduces damage received by 50% for 1 turn, boosts ATK of Fighter characters by 1.25x for 1 turn", - specialName: "Zombie Marionette Operation", - captain: "Boosts ATK of INT characters by 2x" - }, - 386: { - special: "Reduces damage received by 50% for 1 turn, boosts ATK of Fighter characters by 1.25x for 1 turn", - specialName: "Zombie Marionette Operation", - captain: "Boosts ATK of INT characters by 2x" - }, - 387: { - special: "Randomly changes all orbs into either [PSY] or [INT] orbs, deals random PSY damage to all enemies", - specialName: "Square Plate Sword", - specialNotes: "#{random : 1 : 10,000}", - captain: "Boosts RCV of PSY characters by 1.5x" - }, - 388: { - special: "Randomly changes all orbs into either [PSY] or [INT] orbs, deals random PSY damage to all enemies", - specialName: "Square Plate Sword", - specialNotes: "#{random : 1 : 10,000}", - captain: "Boosts RCV of PSY characters by 1.5x" - }, - 389: { - special: "Changes own orb into [QCK] and every other orb into either [RCV], [STR], [DEX] or [QCK] orbs", - specialName: "Hell Wink", - captain: "Boosts ATK by 2.25x following a chain of DEX > INT > QCK attacks no lower than Good" - }, - 390: { - special: "Changes own orb into [QCK] and every other orb into either [RCV], [STR], [DEX] or [QCK] orbs", - specialName: "Hell Wink", - captain: "Boosts ATK by 2.75x following a chain of DEX > INT > QCK attacks no lower than Good" - }, - 391: { - special: "Reduces damage received by 90% for 1 turn, reduces the defense of all enemies by 80% for 1 turn, deals 1,000 fixed damage to all enemies at the end of the following turn", - specialName: "Negative Hollow", - specialNotes: "#{fixed}", - captain: "Boosts RCV of DEX characters by 1.5x" - }, - 392: { - special: "Reduces damage received by 90% for 1 turn, reduces the defense of all enemies by 80% for 1 turn, deals 1,000 fixed damage to all enemies at the end of the following turn", - specialName: "Negative Hollow", - specialNotes: "#{fixed}", - captain: "Boosts RCV of DEX characters by 2x" - }, - 393: { - special: "Deals 35x character's ATK in STR damage to one enemy", - specialName: "Kumacy Knuckle" - }, - 394: { - special: "Deals 500 fixed damage to all enemies", - specialName: "The Tempest Called Love", - specialNotes: "#{fixed}" - }, - 395: { - special: "Empties adjacent slots, amplifies the effect of orbs by 1.25x for 1 turn", - specialNotes: "#{orb : 1.25x}", - specialName: "Mole Banana", - captain: "Boosts ATK and RCV of QCK characters by 1.2x" - }, - 396: { - special: "Empties adjacent slots, amplifies the effect of orbs by 1.25x for 1 turn", - specialNotes: "#{orb : 1.25x}", - specialName: "Mole Banana", - captain: "Boosts ATK and RCV of QCK characters by 1.2x" - }, - 397: { - special: "Fills [EMPTY] orbs with [STR] orbs with a 50% probability, deals 15x character's ATK in damage to all enemies", - specialName: "Four Hundred Base Hits", - captain: "Boosts ATK by 3x after scoring 5 Perfects in a row" - }, - 398: { - special: "Fills [EMPTY] orbs with [STR] orbs with a 50% probability, deals 15x character's ATK in damage to all enemies", - specialName: "Four Hundred Base Hits", - captain: "Boosts ATK by 4x after scoring 5 Perfects in a row" - }, - 399: { - special: "Boosts ATK of DEX characters by 1.5x for 1 turn", - specialName: "Spike-U-Puncture", - captain: "Boosts HP of Striker characters by 1.5x" - }, - 400: { - special: "Boosts ATK of DEX characters by 1.5x for 1 turn", - specialName: "Spike-U-Puncture", - captain: "Boosts HP of Striker characters by 2x" - }, - 401: { - special: "Reduces damage received by 50% for 1 turn, boosts ATK of Slasher characters by 1.25x for 1 turn", - specialName: "Iron Guard", - captain: "Reduces damage received by 10%, boosts ATK of Slasher characters by 1.5x" - }, - 402: { - special: "Reduces damage received by 50% for 1 turn, boosts ATK of Slasher characters by 1.25x for 1 turn", - specialName: "Iron Guard", - captain: "Reduces damage received by 10%, boosts ATK of Slasher characters by 2x" - }, - 403: { - special: "Deals several times the character's ATK in QCK damage to all enemies", - specialNotes: "#{specialProportional : lower : 150 * ( 1 - (remaining HP) / (total HP) )}", - specialName: "Backwater Sword Dance", - captain: "Reduces damage received by 50% if HP is low, boosts RCV of all characters by 3x if HP is low" - }, - 404: { - special: "Reduces damage received by 50% for 2 turns, boosts RCV of all characters by 2x for 2 turns", - specialName: "Clear-Clear Fruit", - captain: "Boosts ATK of Shooter characters by 1.5x" - }, - 405: { - special: "Reduces damage received by 50% for 2 turns, boosts RCV of all characters by 2x for 2 turns", - specialName: "Clear-Clear Fruit", - captain: "Boosts ATK of Shooter characters by 2x" - }, - 406: { - special: "Reduces crew's HP to 1, deals 1,000 fixed damage to all enemies, boosts ATK of all characters by 1.2x for 1 turn", - specialName: "Skills of the Ancient Warriors", - specialNotes: "#{fixed}" - }, - 407: { - special: "Randomizes all orbs, deals 7x character's ATK in DEX damage to all enemies", - specialName: "Zombie-Style 36-Pound Phoenix" - }, - 408: { - special: "Changes own orb into [INT] and randomizes every other orb, deals 15x character's ATK in INT damage to all enemies", - specialName: "Ground Death", - captain: "Reduces damage received by 20%, boosts ATK of Slasher characters by 2x" - }, - 409: { - special: "Changes own orb into [QCK], deals 13x character's ATK in QCK damage to one enemy", - specialName: "Ocean Current Shoulder Throw", - captain: "Boosts ATK of Fighter characters by 2x" - }, - 410: { - special: "Changes own orb into [QCK], deals 13x character's ATK in QCK damage to one enemy", - specialName: "Ocean Current Shoulder Throw", - captain: "Boosts ATK of Fighter characters by 2.5x" - }, - 411: { - special: "Changes adjacent orbs into [STR] orbs, deals 1,000 fixed damage to all enemies", - specialName: "Ursa Shock", - specialNotes: "#{fixed}", - captain: "Boosts ATK and HP of STR characters by 2x" - }, - 412: { - special: "Changes adjacent orbs into [STR] orbs, deals 1,000 fixed damage to all enemies", - specialName: "Ursa Shock", - specialNotes: "#{fixed}", - captain: "Boosts ATK and HP of STR characters by 2x" - }, - 413: { - special: "Changes [STR] and [DEX] orbs into [INT] orbs", - specialName: "Doppelman", - captain: "Boosts ATK of INT characters by 2.5x if HP is above 99% at the start of the turn" - }, - 414: { - special: "Changes [STR] and [DEX] orbs into [INT] orbs", - specialName: "Doppelman", - captain: "Boosts ATK of INT characters by 3x if HP is above 99% at the start of the turn" - }, - 415: { - special: "Recovers 15x character's RCV in HP, delays all enemies for 1 turn", - specialName: "Love-Love Mellow", - captain: "Boosts ATK of QCK and PSY characters by 2.75x and their RCV by 1.5x if HP is above 70% at the start of the turn" - }, - 416: { - special: "Recovers 15x character's RCV in HP, delays all enemies for 1 turn", - specialName: "Love-Love Mellow", - captain: "Boosts ATK of QCK and PSY characters by 2.75x and their RCV by 1.5x if HP is above 70% at the start of the turn" - }, - 417: { - special: "Switches orbs between slots twice, amplifies the effect of orbs by 2x for 1 turn", - specialNotes: "#{orb : 2x}", - specialName: "Overheat", - captain: "Boosts ATK of Slasher characters by 2x" - }, - 418: { - special: "Switches orbs between slots twice, amplifies the effect of orbs by 2x for 1 turn", - specialNotes: "#{orb : 2x}", - specialName: "Overheat", - captain: "Boosts ATK and HP of Slasher characters by 2x" - }, - 419: { - special: "Reduces the defense of all enemies by 50% for 2 turns, randomizes all orbs", - specialName: "Parage Shot: The Storm", - captain: "Boosts ATK of QCK characters by 2x" - }, - 420: { - special: "Reduces Silence duration by 3 turns, deals 15x character's ATK in STR damage to one enemy", - specialName: "Gum-Gum Bazooka: Supremacy", - captain: "Boosts ATK, HP and RCV of STR characters by 1.5x" - }, - 421: { - special: "Reduces Bind duration by 2 turns, deals 10x character's ATK in DEX damage to all enemies", - specialName: "Three Thousand Worlds: The Final Stroke", - captain: "Boosts ATK, HP and RCV of DEX characters by 1.5x" - }, - 422: { - special: "Reduces damage received from INT enemies by 100% for 1 turn, recovers a random amount of HP", - specialName: "Mirage Tempo: The Heavens", - specialNotes: "Estimated healing range: between 1,000 HP and 3,000 HP.", - captain: "Boosts ATK, HP and RCV of INT characters by 1.5x" - }, - 423: { - special: "Recovers 4,343 HP, reduces the defense of all enemies by 50% for 2 turns", - specialName: "Lullaby Parry", - captain: "Protects from defeat as long as HP is above 70%", - captainNotes: "#{zombie}" - }, - 424: { - special: "Recovers 4,343 HP, reduces the defense of all enemies by 50% for 2 turns", - specialName: "Lullaby Parry", - captain: "Protects from defeat as long as HP is above 70%", - captainNotes: "#{zombie}" - }, - 425: { - special: "Deals random PSY damage to all enemies", - specialName: "Shusui: Three Verse Arrow Notch Slash", - specialNotes: "#{random : 1 : 100,000}", - captain: "Boosts ATK and HP of Slasher characters by 1.5x" - }, - 426: { - special: "Boosts ATK of STR characters by 1.05x for 5 turns", - specialName: "Barco Grabber Breath", - captain: "Boosts HP of STR characters by 2x" - }, - 427: { - special: "Reduces Bind and Silence duration by 2 turns", - specialName: "Havoc Sonar", - captain: "Boosts HP of DEX characters by 2x" - }, - 428: { - special: "Reduces damage received by 50% for 2 turns", - specialName: "Last Boss – Deep Dive of Dreams", - captain: "Boosts ATK of PSY characters by 2x" - }, - 429: { - special: "Deals 7x character's ATK in DEX damage to all enemies, reduces the defense of all enemies by 50% for 1 turn", - specialName: "South Bird's Fearless Smile" - }, - 430: { - special: "Amplifies the effect of orbs by 1.5x for 1 turn", - specialNotes: "#{orb : 1.5x}", - specialName: "Spring Hopper", - captain: "Boosts ATK of DEX characters by 1.5x" - }, - 431: { - special: "Amplifies the effect of orbs by 1.5x for 1 turn", - specialNotes: "#{orb : 1.5x}", - specialName: "Spring Hopper", - captain: "Boosts ATK and HP of DEX characters by 1.5x" - }, - 432: { - special: "Deals 20x character's ATK in QCK damage to one enemy", - specialName: "Big Chop" - }, - 433: { - special: "Reduces Bind and Silence duration by 1 turn", - specialName: "New Kama Seduction", - captain: "Boosts ATK by 2x following a chain of QCK > STR > DEX attacks no lower than Good" - }, - 434: { - special: "Amplifies the effect of orbs by 1.25x for 3 turns", - specialNotes: "#{orb : 1.25x}", - specialName: "New Kama Karate Maiden's Awakening", - captain: "Boosts ATK by 2x following a chain of PSY > INT > INT attacks no lower than Good" - }, - 435: { - special: "Randomly changes [RCV], [STR] and [DEX] orbs into either [STR] or [QCK] orbs", - specialName: "Maiden's Bloom", - captain: "Boosts ATK by 2x following a chain of INT > PSY > QCK attacks no lower than Good" - }, - 436: { - special: "Randomly changes [RCV], [STR] and [DEX] orbs into either [STR] or [QCK] orbs", - specialName: "Maiden's Bloom", - captain: "Boosts ATK by 2.25x following a chain of INT > PSY > QCK attacks no lower than Good" - }, - 437: { - special: "Recovers 3x character's RCV in HP, reduces damage received by 80% for 1 turn, deals 1,000 fixed damage to all enemies at the end of the following turn", - specialName: "Negative Horo \"Sweet\"", - specialNotes: "#{fixed}", - captain: "Boosts RCV of all characters by 3x if HP is below 30% at the start of the turn" - }, - 438: { - special: "Recovers 3x character's RCV in HP, reduces damage received by 80% for 1 turn, deals 1,000 fixed damage to all enemies at the end of the following turn", - specialName: "Negative Horo \"Sweet\"", - specialNotes: "#{fixed}", - captain: "Boosts RCV of all characters by 5x if HP is below 30% at the start of the turn" - }, - 439: { - special: "Changes adjacent orbs into [RCV] and randomizes every other orb", - specialName: "Charge! Supersonic Duck Squadron! \"Love\"", - captain: "Recovers 5x character's RCV in HP at the end of each turn" - }, - 440: { - special: "Changes adjacent orbs into [RCV] and randomizes every other orb", - specialName: "Charge! Supersonic Duck Squadron! \"Love\"", - captain: "Recovers 7x character's RCV in HP at the end of each turn" - }, - 444: { - captain: "Boosts ATK of Evolver and Booster characters by 2x if HP is above 50% at the start of the turn" - }, - 445: { - special: "Randomly changes all orbs into either [STR], [DEX], [QCK], [PSY] or [INT] orbs, switches orbs between slots 3 times", - specialName: "Support Incoming! Supersonic Duck Squadron!", - captain: "Boosts ATK of Evolver and Booster characters by 2.5x if HP is above 50% at the start of the turn" - }, - 446: { - special: "Deals 10 times the damage received in the previous turn in typeless damage to all enemies", - specialName: "Black Hole", - captain: "Doubles damage received, boosts ATK of STR characters by 2x and their HP by 1.5x" - }, - 447: { - special: "Deals 10 times the damage received in the previous turn in typeless damage to all enemies", - specialName: "Black Hole", - captain: "Doubles damage received, boosts ATK of STR characters by 2.5x and their HP by 2.25x" - }, - 448: { - special: "Boosts chances of getting [QCK] orbs for 3 turns", - specialName: "Pirate King's Sword", - captain: "Boosts ATK of QCK characters by 3x if HP is above 99% at the start of the turn" - }, - 449: { - special: "Boosts chances of getting [QCK] orbs for 3 turns", - specialName: "Pirate King's Sword", - captain: "Boosts ATK of QCK characters by 3x if HP is above 99% at the start of the turn" - }, - 450: { - special: "Boosts ATK of Fighter characters by 1.5x for 1 turn, deals 25x character's ATK in DEX damage to one enemy", - specialName: "Number Eight's One Hit", - captain: "Boosts ATK of Fighter characters by 2x and their HP by 1.5x" - }, - 451: { - special: "Boosts ATK of Fighter characters by 1.5x for 1 turn, deals 25x character's ATK in DEX damage to one enemy", - specialName: "Number Eight's One Hit", - captain: "Boosts ATK of Fighter characters by 2x and their HP by 1.5x" - }, - 452: { - special: "Changes own orb and the captain's orb into [PSY]", - specialName: "Dread Morning Star", - captain: "Reduces cooldown of all specials by 3 turns at the start of the fight, boosts ATK of Striker characters by 2x" - }, - 453: { - special: "Changes own orb and the captain's orb into [PSY]", - specialName: "Dread Morning Star", - captain: "Reduces cooldown of all specials by 3 turns at the start of the fight, boosts ATK of Striker characters by 2x" - }, - 454: { - special: "Boosts ATK of STR characters by 1.5x for 1 turn, deals 15x character's ATK in STR damage to all enemies", - specialName: "Manly Flaming Sword", - captain: "Boosts ATK of STR characters by 2x, boosts damage of STR specials by 2x", - captainNotes: "#{noFixedPerc}" - }, - 455: { - special: "Boosts ATK of STR characters by 1.5x for 1 turn, deals 15x character's ATK in STR damage to all enemies", - specialName: "Manly Flaming Sword", - captain: "Boosts ATK of STR characters by 2x, boosts damage of STR specials by 2x", - captainNotes: "#{noFixedPerc}" - }, - 456: { - special: "Randomly changes the orbs in the middle row into either [STR] or [DEX] orbs, the orbs in the lower row into either [PSY] or [INT] orbs, switches orbs between slots once", - specialName: "Double Cannon", - captain: "Boosts ATK of Shooter characters by 2x and their RCV by 1.5x" - }, - 457: { - special: "Randomly changes the orbs in the middle row into either [STR] or [DEX] orbs, the orbs in the lower row into either [PSY] or [INT] orbs, switches orbs between slots once", - specialName: "Double Cannon", - captain: "Boosts ATK of Shooter characters by 2x and their RCV by 1.5x" - }, - 458: { - special: "Deals random PSY damage to all enemies, boosts ATK of all characters by 1.5x for 1 turn", - specialName: "Zen Shockwave", - specialNotes: "#{random : 30,000 : 150,000}", - captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of characters with cost 20 or less by 3x" - }, - 459: { - special: "Deals random PSY damage to all enemies, boosts ATK of all characters by 1.5x for 1 turn", - specialName: "Zen Shockwave", - specialNotes: "#{random : 30,000 : 150,000}", - captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts own ATK and ATK of characters with cost 20 or less by 3x", - captainNotes: "His captain ability only affects his evolved form, his base form will NOT receive the boost. All evolved Sengoku units in the team are included in the bonus." - }, - 460: { - special: "Recovers 33 HP after the end of each turn for 999 turns, delays all enemies for 1 turn", - specialName: "Extra Large Candle Service Set", - captain: "Reduces damage received by 10%" - }, - 461: { - special: "Changes own orb into [DEX] and randomizes every other orb, boosts ATK of Fighter characters by 1.25x for 2 turns", - specialName: "Swan Arabesque", - captain: "Boosts ATK of Fighter characters by 2x" - }, - 462: { - special: "Changes own orb into [DEX] and randomizes every other orb, boosts ATK of Fighter characters by 1.25x for 2 turns", - specialName: "Swan Arabesque", - captain: "Boosts ATK of Fighter characters by 2x" - }, - 463: { - special: "Empties all slots, deals 25x character's ATK in PSY damage to one enemy", - specialName: "Surprise Ball Dragon", - captain: "Boosts HP of PSY characters by 2x" - }, - 464: { - special: "Deals 20x character's ATK in INT damage to all enemies", - specialName: "Roc Rider Fuza's Flame", - captain: "Boosts ATK and HP of Striker characters by 1.5x" - }, - 465: { - special: "Deals 20x character's ATK in QCK damage to one enemy, amplifies the effect of orbs by 1.25x for 2 turns", - specialNotes: "#{orb : 1.25x}", - specialName: "Jet Punch", - captain: "Boosts ATK by 3x after scoring 4 hits below Good in a row" - }, - 466: { - special: "Delays all enemies for 1 turn", - specialName: "Double Flash Gun", - captain: "Boosts ATK and HP of Shooter characters by 1.5x" - }, - 467: { - special: "Changes [RCV] orbs into [STR] orbs", - specialName: "Mountain Belly", - captain: "Boosts ATK and RCV of STR characters by 1.5x" - }, - 468: { - special: "Boosts RCV of all characters by 1.5x for 1 turn", - specialName: "Healing Power" - }, - 469: { - special: "Switches orbs between slots once", - specialName: "Quick Change" - }, - 470: { - special: "Boosts RCV of all characters by 1.5x for 1 turn", - specialName: "Healing Power", - captain: "Boosts RCV of PSY characters by 1.5x" - }, - 471: { - special: "Switches orbs between slots once", - specialName: "Quick Change" - }, - 472: { - special: "Deals 20x character's ATK in STR damage to one enemy", - specialName: "Milky Power Axe" - }, - 473: { - special: "Deals 10x character's ATK in QCK damage to one enemy", - specialName: "Milky Quick Axe" - }, - 474: { - special: "Deals 5x character's ATK in DEX damage to all enemies, reduces Bind duration by 1 turn", - specialName: "Milky Technique Axe" - }, - 475: { - special: "Deals 5x character's ATK in STR damage to all enemies, recovers 500 HP", - specialName: "Milky Mind Axe" - }, - 476: { - special: "Deals 1,000 fixed damage to one enemy", - specialName: "Milky Intelligence Axe", - specialNotes: "#{fixed}" - }, - 477: { - special: "Changes [DEX] orbs into [STR] orbs", - specialName: "[DEX] Slot Change [STR]" - }, - 478: { - special: "Changes [PSY] orbs into [QCK] orbs", - specialName: "[PSY] Slot Change [QCK]" - }, - 479: { - special: "Changes [INT] orbs into [DEX] orbs", - specialName: "[INT] Slot Change [DEX]" - }, - 480: { - special: "Changes [TND] orbs into [PSY] orbs", - specialName: "[TND] Slot Change [PSY]" - }, - 481: { - special: "Changes [DEX] orbs into [INT] orbs", - specialName: "[DEX] Slot Change [INT]" - }, - 482: { - special: "Changes [DEX] orbs into [STR] orbs", - specialName: "[DEX] Slot Change [STR]", - captain: "Boosts HP of Striker characters by 1.5x" - }, - 483: { - special: "Changes [PSY] orbs into [QCK] orbs", - specialName: "[PSY] Slot Change [QCK]", - captain: "Boosts ATK and RCV of QCK characters by 1.2x" - }, - 484: { - special: "Changes [INT] orbs into [DEX] orbs", - specialName: "[INT] Slot Change [DEX]", - captain: "Reduces damage received by 10%" - }, - 485: { - special: "Changes [TND] orbs into [PSY] orbs", - specialName: "[TND] Slot Change [PSY]", - captain: "Boosts HP and RCV of PSY characters by 1.2x" - }, - 486: { - special: "Changes [DEX] orbs into [INT] orbs", - specialName: "[DEX] Slot Change [INT]", - captain: "Boosts ATK of Striker characters by 1.5x" - }, - 487: { - special: "Boosts ATK of STR characters by 1.2x for 1 turn", - specialName: "Attack Boost STR" - }, - 488: { - special: "Boosts ATK of QCK characters by 1.2x for 1 turn", - specialName: "Attack Boost QCK" - }, - 489: { - special: "Boosts ATK of DEX characters by 1.2x for 1 turn", - specialName: "Attack Boost DEX" - }, - 490: { - special: "Boosts ATK of STR characters by 1.2x for 1 turn", - specialName: "Attack Boost STR", - captain: "Boosts ATK and HP of Striker characters by 1.2x" - }, - 491: { - special: "Boosts ATK of QCK characters by 1.2x for 1 turn", - specialName: "Attack Boost QCK", - captain: "Boosts RCV of Striker characters by 1.5x" - }, - 492: { - special: "Boosts ATK of DEX characters by 1.2x for 1 turn", - specialName: "Attack Boost DEX", - captain: "Boosts ATK of DEX characters by 1.2x" - }, - 493: { - special: "Recovers 7x character's RCV in HP", - specialName: "Moderate Healing" - }, - 494: { - special: "Deals 3x character's ATK in INT damage to all enemies, poisons all enemies", - specialNotes: "#{poison}", - specialName: "Poison Attack" - }, - 495: { - special: "Recovers 7x character's RCV in HP", - specialName: "Moderate Healing", - captain: "Recovers 500 HP at the end of each turn" - }, - 496: { - special: "Deals 3x character's ATK in INT damage to all enemies, poisons all enemies", - specialNotes: "#{poison}", - specialName: "Poison Attack", - captain: "Boosts ATK of Shooter characters by 1.5x" - }, - 497: { - special: "Reduces Bind duration by 4 turns, deals 3x character's ATK in QCK damage to one enemy", - specialName: "Cheeky Punk Kid Kick", - captain: "Boosts ATK of QCK characters by 1.5x" - }, - 498: { - special: "Reduces Bind duration by 4 turns, deals 3x character's ATK in QCK damage to one enemy", - specialName: "Cheeky Punk Kid Kick", - captain: "Boosts ATK of QCK characters by 1.5x" - }, - 499: { - special: "Delays all enemies by 1 turn", - specialName: "Women Are Courageous!", - captain: "Boosts RCV of Shooter characters by 1.5x" - }, - 500: { - special: "Delays all enemies by 1 turn", - specialName: "Women Are Courageous!", - captain: "Boosts RCV of Shooter characters by 2x" - }, - 501: { - special: "Recovers 5x character's RCV in HP at the end of each turn for 4 turns", - specialName: "Studying Medicine", - captain: "Boosts ATK, HP and RCV of PSY characters by 1.2x" - }, - 502: { - special: "Recovers 5x character's RCV in HP at the end of each turn for 4 turns", - specialName: "Studying Medicine", - captain: "Boosts ATK, HP and RCV of PSY characters by 1.5x" - }, - 503: { - special: "Deals 5x character's ATK in INT damage to all enemies, boosts ATK of all characters by 5% for 1 turn, reduces the defense of all enemies by 50% for 1 turn, randomizes all orbs", - specialName: "Surprise Dial Illusion", - captain: "Boosts HP of INT characters by 1.5x" - }, - 504: { - special: "Deals 5x character's ATK in INT damage to all enemies, boosts ATK of all characters by 5% for 1 turn, reduces the defense of all enemies by 50% for 1 turn, randomizes all orbs", - specialName: "Surprise Dial Illusion", - captain: "Boosts HP of INT characters by 2x" - }, - 505: { - special: "Boosts ATK of QCK characters by 1.25x for 3 turns", - specialName: "Flying Claw", - captain: "Protects from defeat as long as HP is above 50%", - captainNotes: "#{zombie}" - }, - 506: { - special: "Boosts ATK of QCK characters by 1.25x for 3 turns", - specialName: "Flying Claw", - captain: "Protects from defeat as long as HP is above 30%", - captainNotes: "#{zombie}" - }, - 507: { - special: "Deals 25x character's ATK in STR damage to one enemy", - specialName: "Ringing Fang", - captain: "Boosts ATK and HP of STR characters by 1.2x" - }, - 508: { - special: "Deals 25x character's ATK in STR damage to one enemy", - specialName: "Ringing Fang", - captain: "Boosts ATK and HP of STR characters by 1.5x" - }, - 509: { - special: "Poisons all enemies, boosts ATK of Striker characters by 1.5x for 1 turn", - specialNotes: "#{poison}", - specialName: "Merciless Ploy: Poison Needle", - captain: "Boosts ATK of Striker characters by 1.5x" - }, - 510: { - special: "Poisons all enemies, boosts ATK of Striker characters by 1.5x for 1 turn", - specialNotes: "#{poison}", - specialName: "Merciless Ploy: Poison Needle", - captain: "Reduces damage received by 10%, boosts ATK of Striker characters by 2x" - }, - 511: { - special: "Reduces damage received by 30% for 2 turns, boosts ATK of Slasher characters by 1.25x for 2 turns", - specialName: "Cruel Blade: Iron Guard", - captain: "Boosts ATK of Slasher characters by 2x" - }, - 512: { - special: "Boosts chances of getting [PSY] orbs and reduces chances of getting [INT] orbs for 3 turns", - specialName: "Sneaky Punk Kid Strike", - captain: "Protects from defeat as long as HP is above 50%", - captainNotes: "#{zombie}" - }, - 513: { - special: "Boosts chances of getting [PSY] orbs and reduces chances of getting [INT] orbs for 3 turns", - specialName: "Sneaky Punk Kid Strike", - captain: "Protects from defeat as long as HP is above 50%, boosts ATK of PSY characters by 1.5x if HP is above 50% at the start of the turn", - captainNotes: "#{zombie}" - }, - 514: { - special: "Boosts ATK of INT characters by 1.5x for 1 turn, reduces the defense of all enemies by 50% for 1 turn", - specialName: "Blooming Flower of Everlasting Summer", - captain: "Boosts ATK of INT characters by 2x" - }, - 515: { - special: "Changes the orbs in the left column into [INT], [PSY] and [RCV], the orbs in the right column into [STR], [DEX] and [QCK], switches orbs between slots 3 times", - specialNotes: "The special is not based on chance, the orbs are always changed with the same pattern. Starting from the top left orb and proceeding clockwise, after the special is used the orbs will be: [INT], [STR], [DEX], [QCK], [RCV] and [PSY]", - specialName: "Pop Green", - captain: "Boosts ATK, HP and RCV of Shooter characters by 1.5x" - }, - 516: { - special: "Changes the orbs in the left column into [INT], [PSY] and [RCV], the orbs in the right column into [STR], [DEX] and [QCK], switches orbs between slots 3 times", - specialNotes: "The special is not based on chance, the orbs are always changed with the same pattern. Starting from the top left orb and proceeding clockwise, after the special is used the orbs will be: [INT], [STR], [DEX], [QCK], [RCV] and [PSY]", - specialName: "Pop Green", - captain: "Boosts ATK, HP and RCV of Shooter characters by 1.5x, recovers 1x character's RCV in HP at the end of each turn" - }, - 517: { - special: "Empties all slots with [RCV] orbs, boosts ATK of all characters by 5% for 2 turns", - specialName: "Overeat! Energy Change", - captain: "Boosts HP of PSY characters by 1.5x" - }, - 518: { - special: "Empties all slots with [RCV] orbs, boosts ATK of all characters by 5% for 2 turns", - specialName: "Overeat! Energy Change", - captain: "Boosts HP of PSY characters by 2x, boosts chances of getting [RCV] orbs" - }, - 519: { - special: "Reduces crew's current HP by 99%, deals 25x character's ATK in fixed damage to all enemies, boosts ATK of STR characters by 2x for 1 turn", - specialName: "Gum-Gum Gigant Thunder Axe", - specialNotes: "#{fixed}", - captain: "Boosts ATK of STR characters by 2x" - }, - 520: { - special: "Reduces crew's current HP by 99%, deals 25x character's ATK in fixed damage to all enemies, boosts ATK of STR characters by 2x for 1 turn", - specialName: "Gum-Gum Gigant Thunder Axe", - specialNotes: "#{fixed}", - captain: "Boosts ATK of STR characters by 2.5x" - }, - 521: { - special: "Deals several times the character's ATK in INT damage to all enemies", - specialNotes: "#{specialProportional : lower : 100 * ( 1 - (remaining HP) / (total HP) )}", - specialName: "Diable Jambe - Venaison Shot", - captain: "Reduces damage received by 80% if HP is above 99% at the start of the turn" - }, - 522: { - special: "Deals several times the character's ATK in INT damage to all enemies", - specialNotes: "#{specialProportional : lower : 100 * ( 1 - (remaining HP) / (total HP) )}", - specialName: "Diable Jambe - Venaison Shot", - captain: "Reduces damage received by 80% if HP is above 99% at the start of the turn" - }, - 523: { - special: "Randomizes all orbs, protects from defeat as long as HP is above 50% for 1 turn", - specialName: "Billy's Electrical Discharge", - specialNotes: "#{zombie}", - captain: "Boosts ATK and RCV of Striker characters by 1.5x" - }, - 524: { - special: "Randomizes all orbs, protects from defeat as long as HP is above 50% for 1 turn", - specialName: "Billy's Electrical Discharge", - specialNotes: "#{zombie}", - captain: "Boosts ATK of Striker characters by 2x and their RCV by 1.5x" - }, - 525: { - special: "Deals random PSY damage to all enemies, randomizes all orbs", - specialName: "Three-Verse Humming: Arrow-Notch Slash", - captain: "Boosts ATK of PSY characters by 2x" - }, - 526: { - special: "Deals random PSY damage to all enemies, randomizes all orbs", - specialName: "Three-Verse Humming: Arrow-Notch Slash", - captain: "Boosts ATK of PSY characters by 2x, reduces damage received from INT enemies by 30%" - }, - 527: { - special: "Removes poison, recovers 15x character's RCV in HP", - specialName: "Devoted Healing - \"I'm Glad You are Safe\"", - captain: "Boosts ATK and RCV of DEX characters by 1.5x" - }, - 528: { - special: "Removes poison, recovers 15x character's RCV in HP", - specialName: "Devoted Healing - \"I'm Glad You are Safe\"", - captain: "Boosts ATK and RCV of DEX characters by 2x" - }, - 529: { - special: "Deals 35x character's ATK in PSY damage to all enemies, reduces the defense of all enemies by 100% for 2 turns", - specialName: "Conqueror's Haki: Emperor", - captain: "Boosts chances of getting [PSY] orbs, boosts ATK of PSY characters proportionally to the crew's current HP", - captainNotes: "#{captainProportional : higher : 2 + 0.75 * (remaining HP) / (total HP) : 2.75 : 2}" - }, - 530: { - special: "Deals 35x character's ATK in PSY damage to all enemies, reduces the defense of all enemies by 100% for 2 turns", - specialName: "Conqueror's Haki: Emperor", - captain: "Boosts chances of getting [PSY] orbs, boosts ATK of PSY characters proportionally to the crew's current HP", - captainNotes: "#{captainProportional : higher : 2 + 0.75 * (remaining HP) / (total HP) : 2.75 : 2}" - }, - 531: { - special: "Reduces damage received by 30% for 4 turns", - specialName: "Veinte Fleur Calendula: Blossom", - captain: "Reduces damage received from STR, DEX and QCK enemies by 30%" - }, - 532: { - special: "Reduces damage received by 30% for 4 turns", - specialName: "Veinte Fleur Calendula: Blossom", - captain: "Reduces damage received from STR, DEX and QCK enemies by 30%" - }, - 533: { - special: "Amplifies the effect of orbs by 1.5x for 1 turn, deals 20x character's ATK in QCK damage to one enemy", - specialNotes: "#{orb : 1.5x}", - specialName: "Swallow Bond En Avant: Blossom", - captain: "Boosts ATK of QCK characters by 2x" - }, - 534: { - special: "Amplifies the effect of orbs by 1.5x for 1 turn, deals 20x character's ATK in QCK damage to one enemy", - specialNotes: "#{orb : 1.5x}", - specialName: "Swallow Bond En Avant: Blossom", - captain: "Boosts ATK of QCK characters by 2x" - }, - 535: { - special: "Reduces damage received by 50% for 2 turns, boosts RCV of all characters by 2x for 2 turns", - specialName: "Mirage Tempo Fata Morgana: Blossom", - captain: "Boosts RCV of DEX characters by 1.5x" - }, - 536: { - special: "Reduces damage received by 50% for 2 turns, boosts RCV of all characters by 2x for 2 turns", - specialName: "Mirage Tempo Fata Morgana: Blossom", - captain: "Boosts RCV of DEX characters by 2x" - }, - 537: { - special: "Reduces Bind and Silence duration by 1 turn, locks all orbs for 1 turn", - specialName: "Sea Stone Handcuffs", - captain: "Boosts chain multiplier by 2x" - }, - 538: { - special: "Reduces Bind and Silence duration by 1 turn, locks all orbs for 1 turn", - specialName: "Sea Stone Handcuffs", - captain: "Boosts chain multiplier by 2x, recovers 2x character's RCV in HP at the end of each turn" - }, - 539: { - special: "Changes own orb into [STR], deals 25x character's ATK in STR damage to one enemy", - specialName: "Bashful Prison Beast's Metal Rod" - }, - 540: { - special: "Boosts chances of getting [DEX] orbs for 2 turns", - specialName: "Deadly Glare" - }, - 541: { - special: "Greatly reduces chances of getting [PSY], [INT], [TND] and [RCV] slots for 5 turns", - specialName: "White Thorn Deathmatch", - captain: "Boosts ATK of STR characters by 2.5x if HP is below 50% at the start of the turn" - }, - 542: { - special: "Boosts RCV of all characters by 2x for 1 turn", - specialName: "Roar of the Ruler of the Sky", - captain: "Boosts HP of all characters by 1.5x" - }, - 543: { - special: "Reduces crew's current HP by 50%, deals 50x character's ATK in DEX damage to one enemy", - specialName: "Reject", - captain: "Boosts ATK and HP of Shooter characters by 1.5x, reduces crew's RCV to 0" - }, - 544: { - special: "Reduces crew's current HP by 50%, deals 50x character's ATK in DEX damage to one enemy", - specialName: "Reject", - captain: "Boosts ATK of Shooter characters by 2.25x and their HP by 1.5x, reduces crew's RCV to 0" - }, - 545: { - special: "Deals 6,000 fixed damage to all enemies, boosts ATK of PSY characters by 1.5x for 1 turn", - specialName: "60,000,000 Volt Jamboule", - specialNotes: "#{fixed}", - captain: "Boosts ATK of PSY characters by 2x" - }, - 546: { - special: "Deals 6,000 fixed damage to all enemies, boosts ATK of PSY characters by 1.5x for 1 turn", - specialName: "60,000,000 Volt Jamboule", - specialNotes: "#{fixed}", - captain: "Boosts ATK of PSY characters by 2x, reduces damage received by 20%" - }, - 547: { - special: "Reduces crew's current HP by 10%, deals 1x character's ATK in STR damage to one enemy, protects from defeat as long as HP is above 50% for 1 turn", - specialName: "Crazy Punk Kid Punch", - specialNotes: "#{zombie}", - captain: "Boosts chances of getting [RCV] orbs" - }, - 548: { - special: "Reduces crew's current HP by 10%, deals 1x character's ATK in STR damage to one enemy, protects from defeat as long as HP is above 50% for 1 turn", - specialName: "Crazy Punk Kid Punch", - specialNotes: "#{zombie}", - captain: "Boosts chances of getting [RCV] orbs, boosts ATK of all characters by 1.2x" - }, - 549: { - special: "Boosts ATK against enemies with reduced defense by 1.3x for 3 turns", - specialName: "Arousal Manifesto - Red Demon Whip", - captain: "Boosts ATK by 2x after scoring 3 Perfects in a row" - }, - 550: { - special: "Boosts ATK against enemies with reduced defense by 1.3x for 3 turns", - specialName: "Arousal Manifesto - Red Demon Whip", - captain: "Boosts ATK by 2.5x after scoring 3 Perfects in a row" - }, - 551: { - special: "Reduces damage received by 50% for 1 turn, deals 15x character's ATK in STR damage to one enemy", - specialName: "Uncompromising Prison Beast's Morning Star" - }, - 552: { - special: "Reduces the defense of all enemies by 100% for 1 turn", - specialName: "Cursed Shout" - }, - 553: { - special: "Changes adjacent orbs into [DEX], deals 1,000 fixed damage to all enemies", - specialName: "Ashura Ugui", - specialNotes: "#{fixed}", - captain: "Boosts ATK of DEX characters by 2.75x if HP is below 30% at the start of the turn" - }, - 554: { - special: "Changes adjacent orbs into [DEX], deals 1,000 fixed damage to all enemies", - specialName: "Ashura Ugui", - specialNotes: "#{fixed}", - captain: "Boosts ATK of DEX characters by 3x if HP is below 30% at the start of the turn" - }, - 555: { - special: "Delays all enemies for 3 turns, cuts the current HP of each enemy by 10%", - specialName: "Heavenly Dragon Star", - captain: "Boosts ATK of Shooter characters by 2x" - }, - 556: { - special: "Delays all enemies for 3 turns, cuts the current HP of each enemy by 10%", - specialName: "Heavenly Dragon Star", - captain: "Boosts ATK of Shooter characters by 2x and their RCV by 1.5x" - }, - 557: { - special: "Boosts chances of getting [INT] orbs for 3 turns", - specialName: "Ochenta Fleur - Cuatro Manus Shock", - captain: "Boosts ATK and RCV of INT characters by 1.5x" - }, - 558: { - special: "Boosts chances of getting [INT] orbs for 3 turns", - specialName: "Ochenta Fleur - Cuatro Manus Shock", - captain: "Boosts ATK and RCV of INT characters by 2x" - }, - 559: { - special: "Changes own orb into [STR], amplifies the effect of orbs by 1.5x for 2 turns", - specialNotes: "#{orb : 1.5x}", - specialName: "Roar! Zarley Davison", - captain: "Boosts ATK of STR characters by 2x, deals 2x character's ATK in STR damage to all enemies at the end of each turn" - }, - 560: { - special: "Changes own orb into [STR], amplifies the effect of orbs by 1.5x for 2 turns", - specialNotes: "#{orb : 1.5x}", - specialName: "Roar! Zarley Davison", - captain: "Boosts ATK of STR characters by 2.25x, deals 2x character's ATK in STR damage to all enemies at the end of each turn" - }, - 561: { - special: "Reduces crew's current HP by 40%, deals 15x the amount of HP subtracted in typeless damage to all enemies, locks all orbs for 1 turn", - specialName: "Great Flame Commandment: Flame Emperor", - captain: "Boosts HP of Shooter characters by 1.5x and their ATK by 3x if they have a matching orb, by 2x otherwise" - }, - 562: { - special: "Reduces crew's current HP by 40%, deals 15x the amount of HP subtracted in typeless damage to all enemies, locks all orbs for 1 turn", - specialName: "Great Flame Commandment: Flame Emperor", - captain: "Boosts HP of Shooter characters by 1.5x and their ATK by 3x if they have a matching orb, by 2x otherwise" - }, - 563: { - special: "Deal 3x character's ATK in PSY damage to one enemy, changes [INT] orbs into [RCV] orbs", - specialName: "Cutie Baton" - }, - 564: { - special: "Reduces Bind duration by 2 turns", - specialName: "Sea Surface Split" - }, - 565: { - special: "Deals 5,000 fixed damage to one enemy", - specialName: "Hamburger Hammer", - specialNotes: "#{fixed}" - }, - 566: { - special: "Empties all slots with [BLOCK] orbs", - specialName: "Wipeout Tackle" - }, - 567: { - special: "Reduces Bind and Silence duration by 1 turn, deals STR damage to all enemies", - specialName: "Mudfish Coaster" - }, - 568: { - special: "Delays all enemies for 2 turns, reduces the defense of all enemies by 50% for 2 turns, switches orbs between slots twice", - specialName: "Slow Slow Beam", - captain: "Boosts ATK, HP and RCV of all characters by 1.25x" - }, - 569: { - special: "Delays all enemies for 2 turns, reduces the defense of all enemies by 50% for 2 turns, switches orbs between slots twice", - specialName: "Slow Slow Beam", - captain: "Boosts ATK, HP and RCV of all characters by 1.5x, reduces cooldown of all specials by 1 turn at the start of the fight" - }, - 570: { - special: "Changes [BLOCK] orbs into [STR], deals 20x character's ATK in STR damage to one enemy", - specialName: "Gum-Gum Flail", - captain: "Boosts ATK of STR and Fighter characters by 1.5x", - captainNotes: "The bonus is cumulative. STR Fighter characters get a 2.25x bonus." - }, - 571: { - special: "Changes [BLOCK] orbs into [STR], deals 20x character's ATK in STR damage to one enemy", - specialName: "Gum-Gum Flail", - captain: "Boosts ATK of STR and Fighter characters by 1.5x, reduces cooldown of all specials by 1 turn at the start of the fight", - captainNotes: "The bonus is cumulative. STR Fighter characters get a 2.25x bonus." - }, - 572: { - special: "Boosts ATK of Fighter characters by 2x for 1 turn, binds himself for 15 turns", - specialName: "Roar of Mettle", - captain: "Boosts ATK of Fighter characters by 2.5x if HP is above 99% at the start of the turn" - }, - 573: { - special: "Reduces Silence duration by 2 turns, recovers 10x character's RCV in HP", - specialName: "Manly Support", - captain: "Boosts RCV of all characters by 1.2x" - }, - 574: { - special: "Boosts ATK of Striker characters by 1.75x for 2 turns, locks all orbs for 2 turns", - specialName: "Ice Block - Pheasant Beak", - captain: "Boosts ATK of Striker characters by 2x" - }, - 575: { - special: "Boosts ATK of Striker characters by 1.75x for 2 turns, locks all orbs for 2 turns", - specialName: "Ice Block - Pheasant Beak", - captain: "Boosts ATK and HP of Striker characters by 2x" - }, - 576: { - special: "Changes [PSY] orbs into [INT] orbs, boosts RCV of all characters by 1.5x for 1 turn", - specialName: "Fine Tempo - Tea Time Show", - captain: "Boosts ATK of all characters by 1.5x, boosts RCV of all characters by 1.2x" - }, - 577: { - special: "Deals random typeless damage to all enemies, changes own orb into [STR]", - specialName: "Gum-Gum Jet Gatling", - specialNotes: "#{random : 70,000 : 200,000}", - captain: "Boosts ATK by 4x following a chain of Good > Great > Perfect hits" - }, - 578: { - special: "Deals random typeless damage to all enemies, changes own orb into [STR]", - specialName: "Gum-Gum Jet Gatling", - specialNotes: "#{random : 70,000 : 200,000}", - captain: "Boosts ATK by 4x following a chain of Good > Great > Perfect hits" - }, - 579: { - special: "Randomly changes [BLOCK] orbs into either [QCK] or [DEX] orbs, deals 15x character's ATK in QCK damage to all enemies", - specialName: "Dragon Twister", - captain: "Boosts ATK of QCK and DEX characters by 1.5x" - }, - 580: { - special: "Randomly changes [BLOCK] orbs into either [QCK] or [DEX] orbs, deals 15x character's ATK in QCK damage to all enemies", - specialName: "Dragon Twister", - captain: "Boosts ATK of QCK and DEX characters by 2x" - }, - 581: { - special: "Cuts the current HP of each enemy by 7%", - specialName: "High-Caliber Bazooka", - captain: "Boosts ATK of STR characters by 1.5x" - }, - 582: { - special: "Deals 10x character's ATK in QCK damage to one enemy, boosts ATK of QCK characters by 1.5x for 1 turn", - specialName: "Burn Blade", - captain: "Boosts ATK and HP of Striker characters by 1.5x" - }, - 583: { - special: "Changes own orb into [INT] and the captain's orb into [DEX], boosts RCV of Shooter characters by 300 units for 3 turns", - specialName: "Disrupting Fire", - captain: "Boosts ATK and RCV of Shooter characters by 1.5x" - }, - 584: { - special: "Reduces damage received from PSY enemies by 100% for 1 turn", - specialName: "Mantra", - captain: "Reduces cooldown of all specials by 3 turns at the start of the fight, reduces ATK, HP and RCV of all characters by 90%" - }, - 585: { - special: "Changes the captain's orb into [PSY], recovers 9x character's RCV in HP", - specialName: "The Bond Bellmere Left Us", - captain: "Boosts RCV of PSY characters by 1.5x" - }, - 586: { - special: "Changes the captain's orb into [PSY], recovers 9x character's RCV in HP", - specialName: "The Bond Bellmere Left Us", - captain: "Boosts HP and RCV of PSY characters by 1.5x" - }, - 587: { - special: "Removes poison, reduces Bind and Seal duration by 2 turns", - specialName: "Merciful Painkiller", - captain: "Recovers 3x character's RCV in HP at the end of each turn" - }, - 588: { - special: "Removes poison, reduces Bind and Seal duration by 2 turns", - specialName: "Merciful Painkiller", - captain: "Recovers 5x character's RCV in HP at the end of each turn" - }, - 589: { - special: "Boosts ATK of Slasher characters by 1.5x for 1 turn", - specialName: "Flag of the Rebellion", - captain: "Boosts ATK of all characters by 1.5x, reduces HP and RCV of all characters by 80%" - }, - 590: { - special: "Boosts ATK of Slasher characters by 1.5x for 1 turn", - specialName: "Flag of the Rebellion", - captain: "Boosts ATK of all characters by 2x, reduces HP and RCV of all characters by 80%" - }, - 596: { - special: "Deals 20x character's ATK in STR damage to one enemy, reduces the defense of all enemies by 50% for 3 turns", - specialName: "Rozeo Michelli", - captain: "Boosts ATK of STR characters by 1.5x, recovers 500 HP at the end of each turn" - }, - 597: { - special: "Deals 20x character's ATK in STR damage to one enemy, reduces the defense of all enemies by 50% for 3 turns", - specialName: "Rozeo Michelli", - captain: "Boosts ATK of STR characters by 1.75x, recovers 750 HP at the end of each turn" - }, - 598: { - special: "Changes own orb into [INT], switches orbs between slots once", - specialName: "Split Split Cannon", - captain: "Boosts ATK of characters with fewer than 3 stars by 2.5x" - }, - 599: { - special: "Changes own orb into [INT], switches orbs between slots once", - specialName: "Split Split Cannon", - captain: "Boosts ATK of characters with fewer than 3 stars by 3x" - }, - 600: { - special: "Deals 15x character's ATK in PSY damage to one enemy, boosts ATK of PSY characters by 1.3x for 2 turns", - specialName: "Sword Draw - Single Flash", - captain: "Boosts ATK of PSY characters by 1.5x" - }, - 601: { - special: "Deals 15x character's ATK in PSY damage to one enemy, boosts ATK of PSY characters by 1.3x for 2 turns", - specialName: "Sword Draw - Single Flash", - captain: "Boosts ATK of PSY characters by 2x" - }, - 602: { - special: "Reduces crew's current HP by 90%, deals 20,000 fixed damage to all enemies, boosts ATK of QCK characters by 2x for 1 turn", - specialName: "200,000,000 Volt Amaru", - specialNotes: "#{fixed}", - captain: "Boosts ATK of QCK characters by 2x" - }, - 603: { - special: "Reduces crew's current HP by 90%, deals 20,000 fixed damage to all enemies, boosts ATK of QCK characters by 2x for 1 turn", - specialName: "200,000,000 Volt Amaru", - specialNotes: "#{fixed}", - captain: "Boosts ATK of QCK characters by 2.25x, recovers 5x character's RCV in HP at the end of each turn" - }, - 604: { - special: "Cuts the current HP of each enemy by 10%, changes [QCK] orbs into [DEX] orbs", - specialName: "Diable Jambe: Extra Hachis Hash", - captain: "Boosts ATK of Fighter characters by 2x" - }, - 605: { - special: "Cuts the current HP of each enemy by 10%, changes [QCK] orbs into [DEX] orbs", - specialName: "Diable Jambe: Extra Hachis Hash", - captain: "Boosts ATK of Fighter characters by 2x, reduces damage received by 20%" - }, - 606: { - special: "Deals 20x character's ATK in DEX damage to one enemy, changes adjacent orbs into [RCV] orbs", - specialName: "Red Leg Kick", - captain: "Boosts ATK of Fighter characters by 2x if HP is above 50% at the start of the turn" - }, - 607: { - special: "Deals 20x character's ATK in DEX damage to one enemy, changes adjacent orbs into [RCV] orbs", - specialName: "Red Leg Kick", - captain: "Boosts ATK of Fighter characters by 2.5x if HP is above 50% at the start of the turn" - }, - 608: { - special: "For 1 turn, boosts the amount healed by RCV orbs by 1.5x, then 2x, then 2.5x from the third crew member onward", - specialName: "Wicked Strength" - }, - 609: { - special: "Changes the captain's orb into [RCV] and randomizes every other orb", - specialName: "Wicked Spirit" - }, - 610: { - special: "Changes [TND] orbs into [RCV] orbs", - specialName: "[TND] Slot Change [RCV]" - }, - 611: { - special: "Changes adjacent orbs into [RCV] orbs", - specialName: "[RCV] Slot Storm" - }, - 612: { - special: "Boosts ATK and RCV of all characters by 45 units for 1 turn, reduces damage received by 45% for 1 turn", - specialName: "45-Degree Joy", - captain: "Boosts ATK of Slasher characters by 1.5x" - }, - 613: { - special: "Boosts ATK and RCV of all characters by 45 units for 1 turn, reduces damage received by 45% for 1 turn", - specialName: "45-Degree Joy", - captain: "Boosts ATK, HP and RCV of Slasher characters by 1.5x" - }, - 614: { - special: "Reduces the defense of all enemies by 50% for 1 turn, deals 10x character's ATK in PSY damage to all enemies", - specialName: "Demolisher Chop", - captain: "Boosts ATK of characters with cost 20 or less by 2.25x if HP is below 30% at the start of the turn" - }, - 615: { - special: "Deals random STR damage to one enemy", - specialName: "Demolisher Axe" - }, - 616: { - special: "Changes the captain's orb into STR", - specialName: "Demolisher Spear" - }, - 617: { - special: "Boosts ATK of Shooter characters by 1.2x for 1 turn", - specialName: "Demolisher Cannon" - }, - 618: { - special: "Deals 20x character's ATK in STR damage to one enemy", - specialName: "Mach Punch" - }, - 619: { - special: "Cuts the current HP of each enemy by 5%", - specialName: "Slight Break" - }, - 620: { - special: "Changes [INT] orbs into [QCK] orbs", - specialName: "[INT] Slot Change [QCK]" - }, - 621: { - special: "Changes [INT] orbs into [STR] orbs", - specialName: "[INT] Slot Change [STR]" - }, - 622: { - special: "Boosts RCV of all characters by 100 units for 3 turns", - specialName: "Patch Job" - }, - 623: { - special: "Recovers 3x character's RCV in HP at the end of each turn for 5 turns", - specialName: "Auto Repair" - }, - 624: { - special: "Slightly boosts chances of getting [PSY] orbs for 3 turns", - specialName: "Slot Rate Up [PSY]" - }, - 625: { - special: "Slightly boosts chances of getting [INT] orbs for 3 turns", - specialName: "Slot Rate Up [INT]" - }, - 626: { - special: "Deals 13x character's ATK in character's type damage to all enemies", - specialName: "Hyper Burst" - }, - 627: { - special: "Randomizes all orbs", - specialName: "Slot Shuffle" - }, - 628: { - special: "Deals 15,000 fixed damage to one enemy", - specialName: "Keel Crusher", - specialNotes: "#{fixed}" - }, - 629: { - special: "Empties all slots including those with [BLOCK] orbs, deals random INT damage to all enemies", - specialName: "Master Nail", - captain: "Boosts ATK of characters with 3 or fewer stars by 2x" - }, - 630: { - special: "Randomly changes all orbs into either [QCK] or [DEX] orbs, deals random QCK damage to all enemies", - specialName: "Tempest Kick: Slaughter", - captain: "Boosts ATK of Slasher characters by 1.5x" - }, - 631: { - special: "Randomly changes all orbs into either [QCK] or [DEX] orbs, deals random QCK damage to all enemies", - specialName: "Tempest Kick: Slaughter", - captain: "Boosts ATK of Slasher characters by 2x" - }, - 632: { - special: "Randomly changes all orbs into either [STR], [PSY] or [INT] orbs, deals random STR damage to all enemies, reduces the defense of all enemies by 50% for 2 turns", - specialName: "Finger Pistol: Yellow Lotus", - captain: "Boosts ATK of Fighter characters by 1.5x" - }, - 633: { - special: "Randomly changes all orbs into either [STR], [PSY] or [INT] orbs, deals random STR damage to all enemies, reduces the defense of all enemies by 50% for 2 turns", - specialName: "Finger Pistol: Yellow Lotus", - captain: "Boosts ATK of Fighter characters by 2x" - }, - 634: { - special: "Boosts chances of getting [QCK] and [PSY] orbs for 3 turns, boosts ATK of QCK and PSY characters by 1.2x for 3 turns", - specialName: "Guiding Mermaid Voice", - captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK and RCV of QCK and PSY characters by 1.25x" - }, - 635: { - special: "Boosts chances of getting [QCK] and [PSY] orbs for 3 turns, boosts ATK of QCK and PSY characters by 1.2x for 3 turns", - specialName: "Guiding Mermaid Voice", - captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK and RCV of QCK and PSY characters by 1.5x" - }, - 636: { - special: "Binds himself for 3 turns, reduces damage received by 50% for 3 turns, recovers 3.5x character's RCV in HP at the end of each turn for 3 turns", - specialName: "Wretched Ballade", - captain: "Boosts ATK of characters with cost 2 or less by 3x" - }, - 637: { - special: "Cuts the current HP of each enemy by 8%, boosts ATK against enemies with increased defense by 1.3x for 1 turn", - specialName: "Hachi Ink Jet", - captain: "Recovers 618 HP at the end of each turn, boosts ATK of Slasher characters by 1.5x" - }, - 638: { - special: "Changes [PSY] and [INT] orbs into [QCK] orbs, reduces Bind duration by 1 turn", - specialName: "Bohemian Reverse Slash", - captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of Slasher characters by 2x" - }, - 639: { - special: "Changes [PSY] and [INT] orbs into [QCK] orbs, reduces Bind duration by 1 turn", - specialName: "Bohemian Reverse Slash", - captain: "Reduces cooldown of all specials by 3 turns at the start of the fight, boosts ATK of Slasher characters by 2x" - }, - 640: { - special: "Changes own orb into [DEX], deals several times the character's ATK in DEX damage to one enemy", - specialNotes: "#{specialProportional : lower : 50 * ( 1 - (remaining HP) / (total HP) )}", - specialName: "Pirate Brothers: Twin Strike", - captain: "Boosts ATK of Fighter characters by 2x, deals 2x character's ATK in DEX damage to all enemies at the end of each turn" - }, - 641: { - special: "Changes own orb into [DEX], deals several times the character's ATK in DEX damage to one enemy", - specialNotes: "#{specialProportional : lower : 50 * ( 1 - (remaining HP) / (total HP) )}", - specialName: "Pirate Brothers: Twin Strike", - captain: "Boosts ATK of Fighter characters by 2.25x, deals 2x character's ATK in DEX damage to all enemies at the end of each turn" - }, - 642: { - special: "Reduces crew's current HP by 30%, deals 10x character's ATK in fixed damage to one enemy, amplifies the effect of orbs by 1.75x for 1 turn", - specialNotes: "#{fixed} #{orb : 1.75x}", - specialName: "Raging Greatsword", - captain: "Boosts ATK of PSY characters by 2.5x if HP is below 30% at the start of the turn" - }, - 643: { - special: "Reduces crew's current HP by 30%, deals 10x character's ATK in fixed damage to one enemy, amplifies the effect of orbs by 1.75x for 1 turn", - specialNotes: "#{fixed} #{orb : 1.75x}", - specialName: "Raging Greatsword", - captain: "Boosts ATK of PSY characters by 3x if HP is below 30% at the start of the turn" - }, - 644: { - special: "Reduces Bind and Silence duration by 2 turns, boosts ATK against delayed enemies by 1.2x for 3 turns", - specialName: "Witch's Icebreaker", - captain: "Boosts ATK of INT characters by 2x" - }, - 645: { - special: "Reduces Bind and Silence duration by 2 turns, boosts ATK against delayed enemies by 1.2x for 3 turns", - specialName: "Witch's Icebreaker", - captain: "Boosts ATK of INT characters by 2.5x" - }, - 646: { - special: "Deals 20x character's ATK in STR damage to all enemies, boosts chances of getting [STR] orbs for 3 turns", - specialName: "Vanguard Breaker", - captain: "Boosts ATK of Shooter characters by 2.5x if HP is below 30% at the start of the turn" - }, - 647: { - special: "Deals 20x character's ATK in STR damage to all enemies, boosts chances of getting [STR] orbs for 3 turns", - specialName: "Vanguard Breaker", - captain: "Boosts ATK of Shooter characters by 2.75x if HP is below 30% at the start of the turn" - }, - 648: { - special: "Recovers 100x character's RCV in HP, amplifies the effect of orbs by 1.5x for 2 turns", - specialNotes: "#{orb : 1.5x}", - specialName: "Blue Flame Kick", - captain: "Reduces damage received by 30% if HP is above 70% at the start of the turn, boosts ATK of QCK and PSY characters by 2.75x if HP is above 70% at the start the turn" - }, - 649: { - special: "Recovers 100x character's RCV in HP, amplifies the effect of orbs by 1.5x for 2 turns", - specialNotes: "#{orb : 1.5x}", - specialName: "Blue Flame Kick", - captain: "Reduces damage received by 30% if HP is above 70% at the start of the turn, boosts ATK of QCK and PSY characters by 2.75x if HP is above 70% at the start the turn" - }, - 650: { - special: "Deals 5,000 fixed damage to one enemy, amplifies the effect of orbs by 1.5x for 1 turn", - specialNotes: "#{fixed} #{orb : 1.5x}", - specialName: "Thunder Lance Tempo", - captain: "Boosts ATK of INT characters by 2x and their RCV by 1.5x" - }, - 651: { - special: "Deals 5,000 fixed damage to one enemy, amplifies the effect of orbs by 1.5x for 1 turn", - specialNotes: "#{fixed} #{orb : 1.5x}", - specialName: "Thunder Lance Tempo", - captain: "Boosts ATK of INT characters by 2x and their RCV by 1.5x" - }, - 652: { - special: "Cuts the current HP of each enemy by 20%, reduces damage received by 50% for 1 turn", - specialName: "Heart-Smashing Horn", - captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of DEX characters by 2x if they have matching orbs" - }, - 653: { - special: "Cuts the current HP of each enemy by 20%, reduces damage received by 50% for 1 turn", - specialName: "Heart-Smashing Horn", - captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of DEX characters by 2.25x if they have matching orbs" - }, - 654: { - special: "Cuts the current HP of each enemy by 20%, reduces damage received by 50% for 1 turn", - specialName: "Heart-Smashing Horn", - captain: "Reduces cooldown of all specials by 3 turns at the start of the fight, boosts ATK of DEX characters by 2.75x if they have matching orbs" - }, - 655: { - special: "Changes [EMPTY] and [TND] orbs into [STR] orbs, deals 10x character's ATK in STR damage to one enemy, amplifies the effect of orbs by 1.25x for 2 turns", - specialNotes: "#{orb : 1.25x}", - specialName: "Tooth Gum", - captain: "Boosts ATK of STR characters by 1.5x" - }, - 656: { - special: "Changes [EMPTY] and [TND] orbs into [STR] orbs, deals 10x character's ATK in STR damage to one enemy, amplifies the effect of orbs by 1.25x for 2 turns", - specialNotes: "#{orb : 1.25x}", - specialName: "Tooth Gum", - captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of STR characters by 2x" - }, - 657: { - special: "Randomly changes [INT] and [PSY] orbs into either [STR] or [EMPTY] orbs", - specialName: "Forearm Sledge", - captain: "Boosts ATK of Fighter characters by 1.5x" - }, - 658: { - special: "Randomly changes all orbs into either [INT] or [PSY] orbs", - specialName: "Lipowertzer", - captain: "Boosts ATK of Shooter characters by 1.5x" - }, - 659: { - special: "Reduces Bind and Silence duration by 2 turns, reduces damage received by 50% for 2 turns", - specialName: "Gum-Gum Balloon Swim", - captain: "Boosts ATK by 2.5x after scoring 3 Perfects in a row" - }, - 660: { - special: "Delays all enemies for 2 turns, reduces the defense of all enemies by 50% for 2 turns", - specialName: "Atlas Comet", - captain: "Boosts ATK of Shooter characters by 2x" - }, - 661: { - special: "Delays all enemies for 2 turns, reduces the defense of all enemies by 50% for 2 turns", - specialName: "Atlas Comet", - captain: "Boosts ATK of Shooter characters by 2x, reduces cooldown of all specials by 1 turn at the start of the fight" - }, - 662: { - special: "Deals 13x character's ATK in PSY damage to one enemy, randomizes all orbs other than [PSY]", - specialName: "Tornado Tempo - Beach Side", - captain: "Boosts ATK of PSY characters by 2x" - }, - 663: { - special: "Deals several times the character's ATK in PSY damage to one enemy, recovers 5x character's RCV in HP at the end of each turn for 5 turns", - specialNotes: "The exact damage is proportional to the crew's remaining HP and is higher the lower the HP is. The formula used is 80000 * (1 - (current HP) / (total HP))", - specialName: "Vivi's Important Security Guard", - captain: "Recovers 2x character's RCV in HP at the end of each turn" - }, - 664: { - special: "Deals several times the character's ATK in PSY damage to one enemy, recovers 5x character's RCV in HP at the end of each turn for 5 turns", - specialNotes: "The exact damage is proportional to the crew's remaining HP and is higher the lower the HP is. The formula used is 80000 * (1 - (current HP) / (total HP))", - specialName: "Vivi's Important Security Guard", - captain: "Recovers 3x character's RCV in HP at the end of each turn" - }, - 665: { - special: "Changes own orb into [QCK], boosts ATK against enemies with reduced defense by 1.3x for 2 turns", - specialName: "Let's Go! Suna Suna Clan!!", - captain: "Boosts ATK of all characters by 1.2x, reduces HP and RCV of all characters by 80%" - }, - 666: { - special: "Changes own orb into [QCK], boosts ATK against enemies with reduced defense by 1.3x for 2 turns", - specialName: "Let's Go! Suna Suna Clan!!", - captain: "Boosts ATK of all characters by 1.75x, reduces HP and RCV of all characters by 80%" - }, - 667: { - special: "Protects from defeat as long as HP is above 50% for 1 turn", - specialName: "King's Chopper", - specialNotes: "#{zombie}", - captain: "Reduces damage received by 10%, boosts ATK of all characters by 1.5x" - }, - 668: { - special: "Boosts ATK of Freedom characters by 1.5x for 1 turn. If during that turn every unit scores a Perfect hit, boosts ATK of Freedom characters by 2x in the following turn.", - specialName: "Dragon's Claw", - captain: "Boosts HP and RCV of all characters by 1.2x, boosts ATK of Freedom characters proportionally to the crew's current HP", - captainNotes: "#{captainProportional : higher : 2 + 0.75 * (remaining HP) / (total HP) : 2.75 : 2}" - }, - 669: { - special: "Boosts ATK of Freedom characters by 1.5x for 1 turn. If during that turn every unit scores a Perfect hit, boosts ATK of Freedom characters by 2x in the following turn.", - specialName: "Dragon's Claw", - captain: "Boosts HP and RCV of all characters by 1.2x, boosts ATK of Freedom characters proportionally to the crew's current HP", - captainNotes: "#{captainProportional : higher : 2 + 0.75 * (remaining HP) / (total HP) : 2.75 : 2}" - }, - 670: { - special: "Boosts ATK of Fighter characters by 1.75x for 1 turn", - specialName: "Fishman Karate! True Fist Thrust of the Revolutionaries", - captain: "Boosts ATK of Fighter characters by 2x" - }, - 671: { - special: "Boosts ATK of Fighter characters by 1.75x for 1 turn", - specialName: "Fishman Karate! True Fist Thrust of the Revolutionaries", - captain: "Boosts ATK of Fighter characters by 2.25x and their RCV by 1.5x" - }, - 672: { - special: "Cuts the current HP of each enemy by 20%, changes own orb into [STR]", - specialName: "Four Thousand Tile True Punch", - captain: "Boosts ATK of Fighter characters by 2x" - }, - 673: { - special: "Cuts the current HP of each enemy by 20%, changes own orb into [STR]", - specialName: "Four Thousand Tile True Punch", - captain: "Reduces cooldown of all specials by 3 turns at the start of the fight, boosts ATK of Fighter characters by 2x" - }, - 674: { - special: "Removes poison, reduces damage received by 50% for 2 turns, recovers 13x character's RCV in HP at the end of each turn for 2 turns", - specialName: "Emporio Healing Hormone", - captain: "Boosts ATK of Freedom characters by 2x" - }, - 675: { - special: "Removes poison, reduces damage received by 50% for 2 turns, recovers 13x character's RCV in HP at the end of each turn for 2 turns", - specialName: "Emporio Healing Hormone", - captain: "Boosts ATK of Freedom characters by 2.5x" - }, - 676: { - special: "Reduces any damage received above 5,000 HP by 97% for 3 turns", - specialNotes: "The exact formula for the damage received is: 5000 + ((total damage) - 5000) * 0.03", - specialName: "KEEP OUT", - captain: "Boosts ATK of Slasher characters by 1.5x, deals 5x character's ATK in QCK damage to all enemies at the end of each turn" - }, - 677: { - special: "Reduces any damage received above 5,000 HP by 97% for 3 turns", - specialNotes: "The exact formula for the damage received is: 5000 + ((total damage) - 5000) * 0.03", - specialName: "KEEP OUT", - captain: "Boosts ATK of Slasher characters by 1.5x, deals 5x character's ATK in QCK damage to all enemies at the end of each turn" - }, - 678: { - special: "Reduces damage received by 50% for 1 turn, locks all orbs for 1 turn", - specialName: "Cien Fleur Spider Net", - captain: "Boosts ATK and RCV of PSY characters by 1.2x, boosts chances of getting [PSY] orbs" - }, - 679: { - special: "Reduces damage received by 50% for 1 turn, locks all orbs for 1 turn", - specialName: "Cien Fleur Spider Net", - captain: "Boosts ATK and RCV of PSY characters by 1.5x, boosts chances of getting [PSY] orbs" - }, - 680: { - special: "Recovers 5x character's RCV in HP, boosts ATK and RCV of DEX characters by 1.25x for 2 turns", - specialName: "Midsummer Relax Time" - }, - 681: { - special: "Recovers 5x character's RCV in HP, boosts ATK and RCV of DEX characters by 1.25x for 2 turns", - specialName: "Midsummer Relax Time", - captain: "Boosts ATK and RCV of Striker characters by 1.5x" - }, - 682: { - special: "Recovers 2,561 HP, reduces damage received by 50% for 2 turns", - specialName: "Transcendental Serenity Healing" - }, - 683: { - special: "Recovers 2,561 HP, reduces damage received by 50% for 2 turns", - specialName: "Transcendental Serenity Healing", - captain: "Boosts ATK and RCV of Fighter characters by 1.5x" - }, - 684: { - special: "Recovers 3x character's RCV in HP, reduces damage received by 80% for 1 turn", - specialName: "Romantic Ghost" - }, - 685: { - special: "Recovers 3x character's RCV in HP, reduces damage received by 80% for 1 turn", - specialName: "Romantic Ghost", - captain: "Boosts ATK and RCV of Shooter characters by 1.5x" - }, - 686: { - special: "Delays all enemies for 1 turn, recovers 3x character's RCV in HP at the end of each turn for 3 turns", - specialName: "Captivating Perfume Dance - Relaxation", - captain: "Boosts ATK and RCV of Slasher characters by 1.5x" - }, - 687: { - special: "Deals 13x character's ATK in STR damage to all enemies, boosts ATK of Freedom characters by 1.3x for 1 turn", - specialName: "First Spear of the Battle", - captain: "Boosts ATK of Freedom characters by 1.5x" - }, - 688: { - special: "Deals 13x character's ATK in STR damage to all enemies, boosts ATK of Freedom characters by 1.3x for 1 turn", - specialName: "First Spear of the Battle", - captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of Freedom characters by 2x" - }, - 689: { - special: "Amplifies the effect of orbs by 1.5x for 2 turns", - specialNotes: "#{orb : 1.5x}", - specialName: "Botanist's Great Discovery", - captain: "Boosts ATK and RCV of Slasher characters by 1.2x" - }, - 690: { - special: "Amplifies the effect of orbs by 1.5x for 2 turns", - specialNotes: "#{orb : 1.5x}", - specialName: "Botanist's Great Discovery", - captain: "Boosts ATK and RCV of Slasher characters by 1.5x" - }, - 691: { - special: "Changes [PSY] orbs into [DEX] orbs", - specialName: "[PSY] Slot Change [DEX]" - }, - 692: { - special: "Changes [PSY] orbs into [QCK] orbs", - specialName: "[PSY] Slot Change [QCK]" - }, - 693: { - special: "Changes [DEX] orbs into [PSY] orbs", - specialName: "[DEX] Slot Change [PSY]" - }, - 694: { - special: "Deals 13x character's ATK in character's type damage to all enemies", - specialName: "Hyper Burst" - }, - 695: { - special: "Cuts the current HP of each enemy by 5%", - specialName: "Slight Break" - }, - 696: { - special: "Changes [PSY] orbs into [DEX] orbs", - specialName: "[PSY] Slot Change [DEX]", - captain: "Boosts ATK of Striker characters by 1.75x" - }, - 697: { - special: "Changes [PSY] orbs into [QCK] orbs", - specialName: "[PSY] Slot Change [QCK]", - captain: "Boosts ATK of Shooter characters by 1.75x" - }, - 698: { - special: "Changes [DEX] orbs into [PSY] orbs", - specialName: "[DEX] Slot Change [PSY]", - captain: "Boosts ATK of Slasher characters by 1.75x" - }, - 699: { - special: "Deals 13x character's ATK in character's type damage to all enemies", - specialName: "Hyper Burst", - captain: "Boosts ATK of Shooter characters by 500 units, reduces damage received by 10%" - }, - 700: { - special: "Cuts the current HP of each enemy by 5%", - specialName: "Slight Break", - captain: "Boosts ATK of Fighter characters by 1.75x" - }, - 701: { - special: "Deals 15x character's ATK in PSY damage to all enemies, changes own orb into [PSY]", - specialName: "Oimo Press", - captain: "Boosts HP of PSY characters by 2.25x" - }, - 702: { - special: "Seals himself for 5 turns, reduces damage received by 30% for 5 turns", - specialName: "Kashi Swing", - captain: "Boosts HP of INT characters by 2.25x" - }, - 703: { - special: "Deals 5x character's ATK in QCK damage to all enemies", - specialName: "Arm Claw of the Watchdog" - }, - 704: { - special: "Deals 9x character's ATK in STR damage to all enemies, reduces the defense of all enemies by 50% for 1 turn", - specialName: "Companion's Guilt" - }, - 705: { - special: "Randomly changes [PSY], [INT], [TND], [RCV] and [EMPTY] orbs into [STR], [DEX] or [QCK] orbs", - specialName: "Guilty Verdict - \"Slow Death Penalty\"", - captain: "Boosts ATK and HP of STR characters, DEX characters and QCK characters by 1.25x" - }, - 706: { - special: "Changes own orb and the captain's orb into [STR]", - specialName: "Air Door", - captain: "Boosts ATK of STR characters by 1.5x" - }, - 707: { - special: "Changes own orb and the captain's orb into [STR]", - specialName: "Air Door", - captain: "Boosts ATK and HP of STR characters by 1.5x" - }, - 708: { - special: "Reduces Bind and Silence duration by 3 turns", - specialName: "Cien Fleur - Wing", - captain: "Boosts ATK and RCV of PSY characters by 1.2x" - }, - 709: { - special: "Reduces Bind and Silence duration by 3 turns", - specialName: "Cien Fleur - Wing", - captain: "Boosts ATK and RCV of PSY characters by 1.5x" - }, - 710: { - special: "Empties all slots with [BLOCK] orbs, boosts ATK of Shooter characters by 1.25x for 3 turns, deals 15x character's ATK in PSY damage to all enemies", - specialName: "Coup de Vent", - captain: "Boosts ATK of Shooter characters by 1.5x" - }, - 711: { - special: "Empties all slots with [BLOCK] orbs, boosts ATK of Shooter characters by 1.25x for 3 turns, deals 15x character's ATK in PSY damage to all enemies", - specialName: "Coup de Vent", - captain: "Boosts ATK of Shooter characters by 2x" - }, - 712: { - special: "Deals 15x character's ATK in QCK damage to one enemy, boosts ATK of the characters in the top row by 1.5x for 2 turns", - specialNotes: "The special boosts the attack of only the crew's captain and the currently selected friend captain.", - specialName: "Sky Knight's Javelin", - captain: "Boosts ATK of Striker characters by 2x if HP is above 50% at the start of the turn" - }, - 713: { - special: "Deals 15x character's ATK in QCK damage to one enemy, boosts ATK of the characters in the top row by 1.5x for 2 turns", - specialNotes: "The special boosts the attack of only the crew's captain and the currently selected friend captain.", - specialName: "Sky Knight's Javelin", - captain: "Boosts ATK of Striker characters by 2.5x if HP is above 50% at the start of the turn" - }, - 714: { - special: "Randomizes slots with [STR], [QCK], [INT] or [PSY] orbs", - specialName: "Pegasus' Neigh" - }, - 715: { - special: "Boosts ATK and RCV of Freedom characters by 1.5x for 2 turns, seals herself for 3 turns", - specialName: "Angel's Harp - Healing", - captain: "Boosts RCV of all characters by 2x if HP is below 30% at the start of the turn" - }, - 716: { - special: "Boosts ATK and RCV of Freedom characters by 1.5x for 2 turns, seals herself for 3 turns", - specialName: "Angel's Harp - Healing", - captain: "Boosts RCV of all characters by 5x if HP is below 30% at the start of the turn" - }, - 717: { - special: "Deals 50% of the damage dealt in the previous turn as typeless damage to all enemies", - specialNotes: "The special only includes the damage inflicted through normal attacks.", - specialName: "Black Sword - Lightning Slash", - captain: "Boosts ATK of Slasher characters by a variable factor between 2x and 2.75x based on the timing of the attack of the previous unit in the chain", - captainNotes: "A hit below Good or a Miss will boost the ATK of the next unit by 2x, a Good hit by 2.25x, a Great hit by 2.5x and a Perfect hit by 2.75x. This bonus is applied only to Slasher characters." - }, - 718: { - special: "Deals 50% of the damage dealt in the previous turn as typeless damage to all enemies", - specialNotes: "The special only includes the damage inflicted through normal attacks.", - specialName: "Black Sword - Lightning Slash", - captain: "Boosts ATK of Slasher characters by a variable factor between 2x and 2.75x based on the timing of the attack of the previous unit in the chain", - captainNotes: "A hit below Good or a Miss will boost the ATK of the next unit by 2x, a Good hit by 2.25x, a Great hit by 2.5x and a Perfect hit by 2.75x. This bonus is applied only to Slasher characters." - }, - 719: { - special: "Boosts ATK of Knowledge characters by a variable factor for 1 turn, deals 20x character's ATK in DEX damage to all enemies", - specialNotes: "The exact multiplier used is chosen based on the crew's current HP at the time the special is activated: above 30% HP, the multiplier used is 1.5x; below 30% HP, it's 2x.", - specialName: "Sables: Pesado", - captain: "Boosts ATK of Knowledge characters proportionally to the crew's current HP", - captainNotes: "#{captainProportional : lower : 1.5 + 1.75 * (1 - (remaining HP) / (total HP)) : 1.5 : 3.25}" - }, - 720: { - special: "Boosts ATK of Knowledge characters by a variable factor for 1 turn, deals 20x character's ATK in DEX damage to all enemies", - specialNotes: "The exact multiplier used is chosen based on the crew's current HP at the time the special is activated: above 30% HP, the multiplier used is 1.5x; below 30% HP, it's 2x.", - specialName: "Sables: Pesado", - captain: "Boosts ATK of Knowledge characters proportionally to the crew's current HP", - captainNotes: "#{captainProportional : lower : 1.5 + 1.75 * (1 - (remaining HP) / (total HP)) : 1.5 : 3.25}" - }, - 721: { - special: "Randomizes all orbs, including [BLOCK] orbs", - specialName: "Screw Drop Kick", - captain: "Boosts ATK of Fighter characters by 1.5x if HP is is above 99% at the start of the turn" - }, - 722: { - special: "Randomizes all orbs, including [BLOCK] orbs", - specialName: "Screw Drop Kick", - captain: "Boosts ATK of Fighter characters by 2x if HP is is above 99% at the start of the turn" - }, - 723: { - special: "Reduces crew's current HP by 80%, deals 5x the amount of HP subtracted in typeless damage to all enemies, reduces damage received by 90% for 1 turn", - specialName: "Right Angle Flying Bird: Bone Phoenix", - captain: "Boosts ATK of Slasher characters by 1.5x, recovers 1.2x character's RCV in HP at the end of each turn" - }, - 724: { - special: "Reduces crew's current HP by 80%, deals 5x the amount of HP subtracted in typeless damage to all enemies, reduces damage received by 90% for 1 turn", - specialName: "Right Angle Flying Bird: Bone Phoenix", - captain: "Boosts ATK of Slasher characters by 1.75x, recovers 1.5x character's RCV in HP at the end of each turn" - }, - 725: { - special: "Changes [TND] orbs into [QCK] orbs, switches orbs between slots twice", - specialName: "Peacock String Slasher", - captain: "Recovers 1,000 HP at the end of each turn" - }, - 726: { - special: "Changes [TND] orbs into [QCK] orbs, switches orbs between slots twice", - specialName: "Peacock String Slasher", - captain: "Recovers 2,000 HP at the end of each turn" - }, - 727: { - special: "Deals 10x character's ATK in DEX damage to all enemies, reduces the defense of all enemies by 50% for 1 turn", - specialName: "Gum-Gum Gatling", - captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of Freedom and Fighter characters by 1.75x" - }, - 728: { - special: "Randomizes all orbs, recovers 6x character's RCV in HP at the end of each turn for 3 turns", - specialName: "Sheep Cloud Relaxing Bubbles", - captain: "Boosts ATK and RCV of DEX characters by 1.2x, slightly boosts chances of getting [DEX] orbs" - }, - 729: { - special: "Randomizes all orbs, recovers 6x character's RCV in HP at the end of each turn for 3 turns", - specialName: "Sheep Cloud Relaxing Bubbles", - captain: "Boosts ATK and RCV of DEX characters by 1.2x, boosts chances of getting [DEX] orbs" - }, - 730: { - special: "Reduces crew's current HP by 99%, deals 2x the amount of HP subtracted in INT damage to all enemies, boosts ATK of INT characters by 1.5x for 1 turn", - specialName: "Rankyaku - Lupus Fall", - captain: "Boosts ATK and HP of INT characters by 1.2x, deals 9 HP as fixed damage to all enemies at the end of each turn", - captainNotes: "#{fixed}" - }, - 731: { - special: "Reduces crew's current HP by 99%, deals 2x the amount of HP subtracted in INT damage to all enemies, boosts ATK of INT characters by 1.5x for 1 turn", - specialName: "Rankyaku - Lupus Fall", - captain: "Boosts ATK and HP of INT characters by 1.5x, deals 9 HP as fixed damage to all enemies at the end of each turn", - captainNotes: "#{fixed}" - }, - 732: { - special: "Deals 13x character's ATK in STR damage to one enemy, reduces damage received by 50% for 1 turn", - specialName: "Tekkai Dama", - captain: "Boosts ATK of STR characters by 1.5x, reduces damage received by 10%" - }, - 733: { - special: "Deals 13x character's ATK in STR damage to one enemy, reduces damage received by 50% for 1 turn", - specialName: "Tekkai Dama", - captain: "Boosts ATK of STR characters by 1.5x, reduces damage received by 20%" - }, - 734: { - special: "For 1 turn, boosts the amount healed by RCV orbs by 1.5x, then 2x, then 2.5x from the third crew member onward", - specialName: "Life Return - Digestion, Absorption", - captain: "Boosts ATK and RCV of PSY characters by 1.2x" - }, - 735: { - special: "For 1 turn, boosts the amount healed by RCV orbs by 1.5x, then 2x, then 2.5x from the third crew member onward", - specialName: "Life Return - Digestion, Absorption", - captain: "Boosts ATK and RCV of PSY characters by 1.5x" - }, - 736: { - special: "Deals 20x character's ATK in STR damage to all enemies, changes [QCK] orbs into [STR] orbs", - specialName: "Fierce Smash", - captain: "Boosts ATK of Slasher characters by 2.5x if HP is above 50% at the start of the turn" - }, - 737: { - special: "Changes [RCV] orbs into [QCK] orbs, changes adjacent orbs into [QCK] orbs", - specialName: "Shigan - Bachi", - captain: "Boosts ATK of Fighter characters by 2.75x if HP is below 30% at the start of the turn" - }, - 738: { - special: "Deals 200x character's ATK in INT damage to one enemy", - specialName: "Ivory Rush", - captain: "Boosts ATK of characters with cost 21 or more by 2x" - }, - 739: { - special: "Reduces Bind duration by 5 turns, randomizes all orbs", - specialName: "Coup de Boo", - captain: "Boosts ATK of Freedom characters by 2x" - }, - 740: { - special: "Deals 10x character's ATK in QCK damage to all enemies, boosts ATK against enemies with increased defense by 1.3x for 2 turns", - specialName: "Rankyaku - Sen", - captain: "Reduces cooldown of all specials by 2 turns at the start of the fight" - }, - 741: { - special: "Deals 10x character's ATK in QCK damage to all enemies, boosts ATK against enemies with increased defense by 1.3x for 2 turns", - specialName: "Rankyaku - Sen", - captain: "Reduces cooldown of all specials by 3 turns at the start of the fight" - }, - 742: { - special: "Amplifies the effect of orbs by 1.25x for 2 turns, reduces the defense of all enemies by 80% for 2 turns", - specialNotes: "#{orb : 1.25x}", - specialName: "Ramen Beam", - captain: "Boosts ATK and RCV of Freedom characters by 1.2x" - }, - 743: { - special: "Amplifies the effect of orbs by 1.25x for 2 turns, reduces the defense of all enemies by 80% for 2 turns", - specialNotes: "#{orb : 1.25x}", - specialName: "Ramen Beam", - captain: "Boosts ATK and RCV of Freedom characters by 1.5x" - }, - 744: { - special: "Reduces damage received by 50% for 3 turns", - specialName: "Flame Fence", - captain: "Boosts ATK of Freedom characters by 2x" - }, - 745: { - special: "Reduces damage received by 50% for 3 turns", - specialName: "Flame Fence", - captain: "Boosts ATK of Freedom characters by 2.5x" - }, - 746: { - special: "Deals 10x character's ATK in QCK damage to all enemies, protects from defeat as long as HP is above 50% for 1 turn", - specialName: "Megalo Assault!", - specialNotes: "#{zombie}", - captain: "Protects from defeat as long as HP is above 30%", - captainNotes: "#{zombie}" - }, - 747: { - special: "Deals 35x character's ATK in STR damage to one enemy, boosts chances of getting matching orbs for 3 turns", - specialName: "Rokuougan", - captain: "Boosts ATK of Tough characters by 3x if they have a matching orb, by 2.5x otherwise, reduces crew's RCV to 0" - }, - 748: { - special: "Deals 35x character's ATK in STR damage to one enemy, boosts chances of getting matching orbs for 3 turns", - specialName: "Rokuougan", - captain: "Boosts ATK of Tough characters by 3x if they have a matching orb, by 2.5x otherwise, reduces crew's RCV to 0" - }, - 749: { - special: "Deals random DEX damage to all enemies, randomizes all orbs", - specialName: "Rankyaku - Amane Dachi", - captain: "Boosts ATK of DEX characters by 1.5x, boosts damage of DEX specials by 1.5x", - captainNotes: "#{noFixedPerc}" - }, - 750: { - special: "Deals random DEX damage to all enemies, randomizes all orbs", - specialName: "Rankyaku - Amane Dachi", - captain: "Boosts ATK of DEX characters by 2x, boosts damage of DEX specials by 2x", - captainNotes: "#{noFixedPerc}" - }, - 751: { - special: "Reduces damage received in the next turn by 50% if the special is activated with more than 50% health remaining, by 80% if activated with less than 50% but more than 10% health remaining, by 100% if activated with less than 10% health remaining", - specialName: "Sheep Cloud Tidal Wave", - captain: "Boosts ATK and RCV of Knowledge characters by 1.5x" - }, - 752: { - special: "Reduces damage received in the next turn by 50% if the special is activated with more than 50% health remaining, by 80% if activated with less than 50% but more than 10% health remaining, by 100% if activated with less than 10% health remaining", - specialName: "Sheep Cloud Tidal Wave", - captain: "Boosts ATK of Knowledge characters by 2.25x and their RCV by 1.5x" - }, - 753: { - special: "Deals 15x character's ATK in QCK damage to one enemy, amplifies the effect of orbs by 1.75x for 1 turn", - specialNotes: "#{orb : 1.75x}", - specialName: "Moonlight Ten Finger Pistol", - captain: "Boosts ATK of Tough characters by 2x" - }, - 754: { - special: "Deals 15x character's ATK in QCK damage to one enemy, amplifies the effect of orbs by 1.75x for 1 turn", - specialNotes: "#{orb : 1.75x}", - specialName: "Moonlight Ten Finger Pistol", - captain: "Boosts ATK of Tough characters by 2.5x" - }, - 755: { - special: "Reduces damage received by 50% for 1 turn, boosts ATK of Tough characters by 1.75x for 1 turn", - specialName: "Tekkai - Rin", - captain: "Boosts ATK of INT characters by 1.5x, reduces damage received from PSY enemies by 20%" - }, - 756: { - special: "Reduces damage received by 50% for 1 turn, boosts ATK of Tough characters by 1.75x for 1 turn", - specialName: "Tekkai - Rin", - captain: "Boosts ATK of INT characters by 2x, reduces damage received from PSY enemies by 30%" - }, - 757: { - special: "Changes [DEX] and [QCK] orbs into [PSY] orbs", - specialName: "Solid Beast Supreme Technique: Owl Strike", - captain: "Boosts ATK of PSY characters by 2x" - }, - 758: { - special: "Changes [DEX] and [QCK] orbs into [PSY] orbs", - specialName: "Solid Beast Supreme Technique: Owl Strike", - captain: "Boosts ATK of PSY characters by 2x, recovers 3x character's RCV in HP at the end of each turn" - }, - 759: { - special: "Switches orbs between slots 3 times, locks all orbs for 1 turn", - specialName: "Life Return: Shishi Finger Pistol", - captain: "Boosts ATK of STR characters by 2.5x if HP is below 30% at the start of the turn" - }, - 760: { - special: "Switches orbs between slots 3 times, locks all orbs for 1 turn", - specialName: "Life Return: Shishi Finger Pistol", - captain: "Boosts ATK of STR characters by 3x if HP is below 30% at the start of the turn" - }, - 761: { - special: "Deals 15x character's ATK in DEX damage to one enemy, boosts ATK of all characters by 1.2x for 1 turn", - specialName: "Gum-Gum Monster Pistol", - captain: "Boosts ATK of Fighter characters by 2x" - }, - 762: { - special: "Boosts ATK of PSY characters by 1.75x for 1 turn", - specialName: "Impact Beast", - captain: "Boosts ATK and RCV of PSY characters by 1.5x" - }, - 763: { - special: "Changes own orb into [STR], switches orbs between slots once", - specialName: "Franken-Franky Centaur", - captain: "Boosts ATK of STR characters by 2x" - }, - 764: { - special: "Recovers 3,000 HP", - specialName: "Cat Burglar Trick", - captain: "Boosts ATK and RCV of Striker characters by 1.5x" - }, - 765: { - special: "Reduces Silence duration by 3 turns", - specialName: "Scope Magic", - captain: "Recovers 2x character's RCV in HP at the end of each turn" - }, - 766: { - special: "Deals 7x character's ATK in QCK damage to all enemies, delays all enemies for 1 turn", - specialName: "108 Pound Phoenix: Reaper", - captain: "Boosts ATK of QCK characters by 2x" - }, - 767: { - special: { - "japan": "Changes the orbs in the top row into [DEX] orbs, removes blindness", - "global": "Changes the orbs in the top row into [DEX] orbs, reduces Silence duration by 1 turn" - }, - specialName: "Ojos Fleur: Thriller", - captain: "Boosts ATK and RCV of DEX characters by 1.5x" - }, - 768: { - special: "Recovers 15x character's RCV in HP, changes [TND] orbs into [RCV] orbs", - specialName: "Hot Rock Stew: Party", - captain: "Boosts ATK of PSY characters by 2x" - }, - 769: { - special: "Recovers 4,343 HP, poisons all enemies", - specialNotes: "#{poison}", - specialName: "Lullaby Parry: Horror", - captain: "Boosts ATK and RCV of INT characters by 1.5x" - }, - 770: { - special: "Deals 15x character's ATK in STR damage to one enemy, boosts ATK against delayed enemies by 1.3x for 2 turns", - specialName: "Shigan: Convergence", - captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of STR characters by 2x" - }, - 771: { - special: "Deals 15x character's ATK in PSY damage to one enemy, boosts ATK of Knowledge characters by 1.75x for 1 turn", - specialName: "Moonwalk: Air Walking", - captain: "Boosts ATK of Knowledge characters by 2.5x" - }, - 772: { - special: "Cuts the current HP of each enemy by 10%, changes [PSY] and [INT] orbs into [DEX] orbs", - specialName: "Eight-Sword Style: Brave Warrior's Continuous Attack", - captain: "Boosts ATK of Slasher characters by 2x, reduces damage received from QCK enemies by 20%" - }, - 773: { - special: "Reduces any damage received above 3,000 HP by 80% for 1 turn", - specialNotes: "The exact formula for the damage received is: 3000 + ((total damage) - 3000) * 0.2", - specialName: "Rust-Rust Fruit", - captain: "Reduces damage received by 20%" - }, - 774: { - special: "Randomly changes [TND], [RCV], [EMPTY], [BLOCK] and [BOMB] orbs into either [STR], [DEX], [QCK], [PSY] or [INT] orbs, switches orbs between slots 3 times", - specialName: "Berry-Berry Fruit", - captain: "Boosts ATK of Freedom characters by 2x" - }, - 775: { - special: "Deals several times the character's ATK in PSY damage to one enemy", - specialNotes: "#{specialProportional : lower : 125 * ( 1 - (remaining HP) / (total HP) )}", - specialName: "Angry Headbutt", - captain: "Boosts ATK and HP of Knowledge characters by 1.5x" - }, - 776: { - specialName: "Boisterous Lucky Shot!!", - special: "Recovers 5,000 HP, deals 15x character's ATK in PSY damage to one enemy, seals himself for 3 turns", - captain: "Boosts ATK and RCV of PSY characters by 1.25x" - }, - 777: { - special: "Recovers 5,000 HP, deals 15x character's ATK in PSY damage to one enemy, seals himself for 3 turns", - specialName: "Boisterous Lucky Shot!!", - captain: "Boosts ATK and RCV of PSY characters by 1.75x" - }, - 778: { - special: "Deals several times the character's ATK in QCK damage to one enemy, changes own orb into [QCK]", - specialNotes: "#{specialProportional : lower : 125 * ( 1 - (remaining HP) / (total HP) )}", - specialName: "Undefeated Sword Technique", - captain: "Reduces damage received by 20%" - }, - 779: { - special: "Deals several times the character's ATK in QCK damage to one enemy, changes own orb into [QCK]", - specialNotes: "#{specialProportional : lower : 125 * ( 1 - (remaining HP) / (total HP) )}", - specialName: "Undefeated Sword Technique", - captain: "Reduces damage received by 25%" - }, - 780: { - special: "Boosts own ATK by a variable factor for 1 turn", - specialNotes: "The exact multiplier used is chosen based on the crew's current HP at the time the special is activated: above 50% HP, the multiplier used is 1.5x; between 20% HP and 50% HP, it's 1.75x; below 20% HP, it's 2x.", - specialName: "Precept Deification", - captain: "Boosts ATK of all characters by 2x if HP is below 30% at the start of the turn" - }, - 781: { - special: "Boosts own ATK by a variable factor for 1 turn", - specialNotes: "The exact multiplier used is chosen based on the crew's current HP at the time the special is activated: above 50% HP, the multiplier used is 1.5x; between 20% HP and 50% HP, it's 1.75x; below 20% HP, it's 2x.", - specialName: "Precept Deification", - captain: "Boosts ATK of all characters by 2.5x if HP is below 30% at the start of the turn" - }, - 782: { - special: "Delays all enemies for 1 turn, recovers a small random amount of HP", - specialName: "Smile of a Natural Beauty", - captain: "Boosts RCV of Slasher characters by 1.5x" - }, - 783: { - special: "Delays all enemies for 1 turn, recovers a small random amount of HP", - specialName: "Smile of a Natural Beauty", - captain: "Boosts ATK of Slasher characters by 2x and their RCV by 1.5x" - }, - 784: { - special: "Reduces Silence duration by 2 turns, removes blindness", - specialName: "Yelling at Lascivious Young Women" - }, - 785: { - special: "Reduces Silence duration by 2 turns, removes blindness", - specialName: "Yelling at Lascivious Young Women", - captain: "Reduces damage received by 20%" - }, - 786: { - special: "Seals himself for 10 turns, delays all enemies for 1 turn, reduces damage received by 50% for 4 turns", - specialName: "The Resolve to Face Death! \"Open Mind\"" - }, - 787: { - special: "Seals himself for 10 turns, delays all enemies for 1 turn, reduces damage received by 50% for 4 turns", - specialName: "The Resolve to Face Death! \"Open Mind\"", - captain: "Reduces damage received by 50%, reduces crew's current HP by 10% at the end of each turn" - }, - 788: { - special: "Following the activation of the special, if every unit scores a Perfect hit, boosts ATK of Slasher characters by 1.75x in the following turn", - specialName: "Real Sword Fight with a Girl Swordsman" - }, - 789: { - special: "Following the activation of the special, if every unit scores a Perfect hit, boosts ATK of Slasher characters by 1.75x in the following turn", - specialName: "Real Sword Fight with a Girl Swordsman", - captain: "Boosts ATK of Slasher characters by 1.5x" - }, - 790: { - special: "Deals 3x character's ATK in QCK damage to one enemy, boosts ATK of STR, DEX and QCK characters by 1.2x for 3 turns", - specialName: "March!! Usopp Pirates" - }, - 791: { - special: "Deals 3x character's ATK in QCK damage to one enemy, boosts ATK of STR, DEX and QCK characters by 1.2x for 3 turns", - specialName: "March!! Usopp Pirates", - captain: "Boosts ATK, HP and RCV of STR, DEX and QCK characters by 1.25x" - }, - 792: { - special: "Randomly changes all orbs into either [STR], [QCK], [DEX], [PSY] or [INT] orbs, switches orbs between slots twice, locks all orbs for 1 turn", - specialName: "The Entushiasm to Keep Skilled Workers in Line" - }, - 793: { - special: "Randomly changes all orbs into either [STR], [QCK], [DEX], [PSY] or [INT] orbs, switches orbs between slots twice, locks all orbs for 1 turn", - specialName: "The Entushiasm to Keep Skilled Workers in Line", - captain: "Boosts ATK and RCV of Knowledge characters by 1.5x" - }, - 794: { - special: "Deals 10 hits of random INT damage to random enemies, delays all enemies for 1 turn", - specialNotes: "#{randomHits : 10}", - specialName: "Gum-Gum Storm", - captain: "Boosts ATK of Tough characters by 3x, reduces crew's current HP by 10% at the end of each turn, reduces his own ATK multiplier by 0.1x at the end of each turn", - captainNotes: "His ATK multiplier will be 3.0x on the first turn, 2.9x on the second, 2.8x on the third and so on. The reduction stops once the multiplier is 1.0x. The multiplier affects all Tough units." - }, - 795: { - special: "Deals 10 hits of random INT damage to random enemies, delays all enemies for 1 turn", - specialNotes: "#{randomHits : 10}", - specialName: "Gum-Gum Storm", - captain: "Boosts ATK of Tough characters by 3.5x, reduces crew's current HP by 10% at the end of each turn, reduces his own ATK multiplier by 0.1x at the end of each turn", - captainNotes: "His ATK multiplier will be 3.5x on the first turn, 3.4x on the second, 3.3x on the third and so on. The reduction stops once the multiplier is 1.0x. The multiplier affects all Tough units." - }, - 796: { - special: "Slightly boosts chances of getting matching orbs for 3 turns, boosts own ATK by 1.75x for 1 turn", - specialName: "Peto-Peto Fruit, The Greatest Power", - captain: "Boosts ATK of Knowledge characters by 2x" - }, - 797: { - special: "Slightly boosts chances of getting matching orbs for 3 turns, boosts own ATK by 1.75x for 1 turn", - specialName: "Peto-Peto Fruit, The Greatest Power", - captain: "Boosts ATK of Knowledge and Tough characters by 2x" - }, - 798: { - special: "Removes poison, following the activation of the special, if every unit scores a Perfect hit, boosts ATK of Fighter characters by 1.75x in the following turn", - specialName: "Dugong Secret! Fist of the Black Fin", - captain: "Boosts ATK by 2.5x after scoring 3 Perfects in a row" - }, - 799: { - special: "Randomizes all orbs, recovers 9x character's RCV in HP", - specialName: "Sea Animal Healing" - }, - 800: { - special: "Randomly changes all orbs into either [STR], [DEX] or [QCK] orbs", - specialName: "Octopus Tentacle Blow" - }, - 801: { - special: "Randomly changes [STR], [QCK], [DEX], [INT], [BOMB] and [BLOCK] orbs into either [STR], [QCK], [DEX], [PSY] or [INT] orbs, changes [TND] and [RCV] orbs into [PSY] orbs", - specialName: "Clone-Clone Montage", - captain: "Boosts ATK of PSY characters by 2x" - }, - 802: { - special: "Randomly changes [STR], [QCK], [DEX], [INT], [BOMB] and [BLOCK] orbs into either [STR], [QCK], [DEX], [PSY] or [INT] orbs, changes [TND] and [RCV] orbs into [PSY] orbs", - specialName: "Clone-Clone Montage", - captain: "Boosts ATK of PSY characters by 2.5x" - }, - 803: { - special: "Deals 8 hits of random DEX damage to random enemies, boosts ATK of all characters by 1.1x for 3 turns", - specialNotes: "#{randomHits : 8}", - specialName: "Black Spear Formation: All-Out Attack!", - captain: "Boosts ATK and RCV of DEX characters by 1.2x" - }, - 804: { - special: "Deals 8 hits of random DEX damage to random enemies, boosts ATK of all characters by 1.1x for 3 turns", - specialNotes: "#{randomHits : 8}", - specialName: "Black Spear Formation: All-Out Attack!", - captain: "Boosts ATK and RCV of DEX characters by 1.5x, deals 1x character's ATK in DEX damage to all enemies at the end of each turn" - }, - 805: { - special: "Reduces crew's current HP by 20%, deals 10x the amount of HP subtracted in INT damage to one enemy, amplifies the effect of orbs by 1.75x for 1 turn", - specialName: "White Vine", - captain: "Boosts ATK of Striker characters by 2x", - specialNotes: "#{orb : 1.75x}" - }, - 806: { - special: "Reduces crew's current HP by 20%, deals 10x the amount of HP subtracted in INT damage to one enemy, amplifies the effect of orbs by 1.75x for 1 turn", - specialName: "White Vine", - captain: "Boosts ATK of Striker characters by 2x, reduces damage received up to 30% depending on the crew's current HP", - specialNotes: "#{orb : 1.75x}" - }, - 807: { - captain: "Boosts ATK and RCV of Knowledge characters by 1.5x", - specialName: "Thunder Charge: Swing Arm", - special: "Deals 15x character's ATK in PSY damage to one enemy, boosts ATK against enemies with reduced defense by 1.3x for 3 turns" - }, - 808: { - captain: "Boosts ATK and RCV of Knowledge characters by 1.5x, recovers 2x character's RCV in HP at the end of each turn", - specialName: "Thunder Charge: Swing Arm", - special: "Deals 15x character's ATK in PSY damage to one enemy, boosts ATK against enemies with reduced defense by 1.3x for 3 turns" - }, - 809: { - captain: "Boosts ATK and RCV of Tough characters by 1.5x", - specialName: "Lola's Attack Chance", - special: "Reduces the defense of all enemies by 80% for 1 turn, amplifies the effect of orbs by 1.5x for 1 turn", - specialNotes: "#{orb : 1.5x}" - }, - 810: { - captain: "Boosts ATK of Tough characters by 2x and their RCV by 1.5x, reduces crew's current HP by 10% at the end of each turn", - specialName: "Lola's Attack Chance", - special: "Reduces the defense of all enemies by 80% for 1 turn, amplifies the effect of orbs by 1.5x for 1 turn", - specialNotes: "#{orb : 1.5x}" - }, - 811: { - specialName: "Birdbrain Present", - special: "Changes own orb into DEX, switches orbs between slots once" - }, - 812: { - specialName: "Hell Howl", - special: "Sharply decreases the defense of all enemies for 1 turn" - }, - 813: { - specialName: "Sticky Spider Net", - special: "Delays all enemies for 1 turn, amplifies the effect of orbs by 1.25x for 1 turn", - specialNotes: "#{orb : 1.25x}" - }, - 814: { - specialName: "Carpet Scratch", - special: "Deals 13x character's ATK in DEX damage to a single enemy, changes captain's orb into [TND]" - }, - 815: { - captain: "Boosts ATK by 2.5x following a chain of STR > INT > DEX attacks no lower than Good", - specialName: "Brick Bat", - special: "Deals 10 hits of 5,000 fixed damage to random enemies", - specialNotes: "#{fixed} #{randomHits : 10}" - }, - 816: { - captain: "Boosts ATK by 2.75x following a chain of STR > INT > DEX attacks no lower than Good", - specialName: "Brick Bat", - special: "Deals 10 hits of 5,000 fixed damage to random enemies", - specialNotes: "#{fixed} #{randomHits : 10}" - }, - 817: { - specialName: "[PSY] Slot Change [STR]", - special: "Changes [PSY] orbs into [STR] orbs" - }, - 818: { - specialName: "Quick Change", - special: "Switches orbs between slots once" - }, - 819: { - specialName: "Hyper Burst", - special: "Deals 13x character's ATK in character's type damage to all enemies" - }, - 820: { - specialName: "[TND] Slot Change [INT]", - special: "Changes [TND] orbs into [INT] orbs" - }, - 821: { - specialName: "Slot Shuffle", - special: "Randomizes all orbs" - }, - 822: { - specialName: "Patch Job", - special: "Boosts RCV of all characters by 100 units for 3 turns" - }, - 823: { - specialName: "Slot Rate Up [INT]", - special: "Slightly boosts chances of getting [INT] orbs for 3 turns" - }, - 824: { - specialName: "Auto Repair", - special: "Recovers 3x character's RCV in HP at the end of each turn for 5 turns" - }, - 825: { - captain: "Boosts ATK and HP of STR characters by 1.5x", - specialName: "Energy of the Ancient Knight", - special: "Boosts ATK of STR characters by 200 units for 1 turn" - }, - 826: { - captain: "Boosts ATK and HP of DEX characters by 1.5x", - specialName: "Weakness of the Ancient Knight", - special: "Delays all enemies for 1 turn, reduces the ATK of all characters by 80% for 2 turns" - }, - 827: { - captain: "Boosts ATK and HP of QCK characters by 1.5x", - specialName: "Poison of the Ancient Knight", - special: "Boosts ATK against poisoned enemies by 1.05x for 999 turns" - }, - 830: { - captain: "Boosts ATK of Knowledge and Striker characters by 1.75x, deals 2 times the damage received in the previous turn in DEX damage to all enemies at the end of each turn", - specialName: "Karma Conviction", - special: "Changes the orbs in the top row into [STR] orbs, changes the orbs in the middle row into [DEX] orbs, changes the orbs in the bottom row into [QCK] orbs" - }, - 831: { - captain: "Boosts ATK of Knowledge and Striker characters by 2x, deals 5 times the damage received in the previous turn in DEX damage to all enemies at the end of each turn", - specialName: "Karma Conviction", - special: "Changes the orbs in the top row into [STR] orbs, changes the orbs in the middle row into [DEX] orbs, changes the orbs in the bottom row into [QCK] orbs" - }, - 832: { - captain: "Boosts ATK of Freedom characters proportionally to the crew's current HP, reduces crew's current HP by 10% at the end of each turn", - specialName: "Burn Bazooka", - special: "Boosts ATK of Freedom characters by 1.5x for 1 turn, deals 15x character's ATK in STR damage to all enemies", - captainNotes: "#{captainProportional : lower : 1 + 1.5 * (1 - (remaining HP) / (total HP)) : 1 : 2.5}" - }, - 833: { - captain: "Boosts ATK of Freedom characters proportionally to the crew's current HP, reduces crew's current HP by 10% at the end of each turn", - specialName: "Burn Bazooka", - special: "Boosts ATK of Freedom characters by 1.5x for 1 turn, deals 15x character's ATK in STR damage to all enemies", - captainNotes: "#{captainProportional : lower : 1 + 1.75 * (1 - (remaining HP) / (total HP)) : 1 : 2.75}" - }, - 834: { - captain: "Boosts ATK and RCV of Shooter characters by 1.5x", - specialName: "Yellow Gun & Gero Gero Gun", - special: "Changes own orb into [QCK] and the captain's orb into [PSY]" - }, - 835: { - captain: "Boosts ATK and HP of Knowledge characters by 2x", - specialName: "Thrust Pad Cannon", - special: "Changes [RCV], [TND], [EMPTY], [BLOCK] and [BOMB] orbs into matching orbs, amplifies the effect of orbs by 1.75x for 1 turn", - specialNotes: "#{orb : 1.75x}" - }, - 836: { - captain: "Boosts ATK and HP of Knowledge characters by 2x, deals 5 times the damage received in the previous turn in STR damage to all enemies at the end of each turn", - specialName: "Thrust Pad Cannon", - special: "Changes [RCV], [TND], [EMPTY], [BLOCK] and [BOMB] orbs into matching orbs, amplifies the effect of orbs by 1.75x for 1 turn", - specialNotes: "#{orb : 1.75x}" - }, - 837: { - captain: "Boosts ATK of Ambition characters by 2x", - specialName: "Gas Robe", - special: "Poisons all enemies, boosts ATK of Ambition characters by 1.75x for 2 turns", - specialNotes: "#{poison}" - }, - 838: { - captain: "Boosts ATK of Ambition characters by 2.5x", - specialName: "Gas Robe", - special: "Poisons all enemies, boosts ATK of Ambition characters by 1.75x for 2 turns" - }, - 839: { - captain: "Boosts ATK of Striker characters by 2x", - specialName: "Demon Bamboo", - special: "Changes own orb into [INT], boosts own ATK by 2x for 1 turn, deals 15x character's ATK in INT damage to one enemy" - }, - 840: { - captain: "Boosts ATK of Striker characters by 2.5x", - specialName: "Demon Bamboo", - special: "Changes own orb into [INT], boosts own ATK by 2x for 1 turn, deals 15x character's ATK in INT damage to one enemy" - }, - 841: { - captain: "Recovers 3x character's RCV in HP at the end of each turns, deals 3x character's ATK in PSY damage to all enemies at the end of each turn", - specialName: "Snow Rabbit", - special: "Delays all enemies for 1 turn, boosts ATK against delayed enemies by 1.25x for 2 turns" - }, - 842: { - captain: "Recovers 5x character's RCV in HP at the end of each turns, deals 5x character's ATK in PSY damage to all enemies at the end of each turn", - specialName: "Snow Rabbit", - special: "Delays all enemies for 1 turn, boosts ATK against delayed enemies by 1.25x for 2 turns" - }, - 843: { - captain: "Boosts ATK of Slasher, Striker and Shooter characters by 1.5x", - specialName: "Arms-Morphosis: Missile Girl", - special: "Deals 15x character's ATK in STR damage to all enemies, boosts ATK of Shooter characters by 1.5x for 1 turn. If during that turn every unit scores a Perfect hit, boosts ATK of Shooter, Striker and Slasher characters by 1.5x in the following turn." - }, - 844: { - captain: "Boosts ATK of Slasher, Striker and Shooter characters by 2x", - specialName: "Arms-Morphosis: Missile Girl", - special: "Deals 15x character's ATK in STR damage to all enemies, boosts ATK of Shooter characters by 1.5x for 1 turn. If during that turn every unit scores a Perfect hit, boosts ATK of Shooter, Striker and Slasher characters by 1.5x in the following turn." - }, - 845: { - captain: "Boosts ATK of all characters by 1.5x after the 11th hit in the chain, by 2.5x after the 22nd hit", - specialName: "Gust: Matasaburo", - special: "Changes own orb into [QCK], randomizes every other orb" - }, - 846: { - captain: "Boosts ATK of all characters by 1.5x after the 11th hit in the chain, by 2.5x after the 22nd hit, by 2.75x after the 30th hit, by 3.5x after the 40th hit", - specialName: "Gust: Matasaburo", - special: "Changes own orb into [QCK], randomizes every other orb" - }, - 847: { - captain: "Boosts ATK of all characters by 1.5x if HP is below 30% at the start of the turn", - specialName: "Sturdy Boat: Launch", - special: "Reduces Silence duration by 5 turns, boosts ATK of all characters by 5% for 3 turns, reduces damage received by 10% for 3 turns, amplifies the effect of orbs by 1.15x for 3 turns, recovers 2x character's RCV in HP at the end of each turn for 3 turns", - specialNotes: "#{orb : 1.15x}" - }, - 848: { - captain: "Boosts ATK of all characters by 2x if HP is below 30% at the start of the turn", - specialName: "Sturdy Boat: Launch", - special: "Reduces Silence duration by 5 turns, boosts ATK of all characters by 5% for 3 turns, reduces damage received by 10% for 3 turns, amplifies the effect of orbs by 1.15x for 3 turns, recovers 2x character's RCV in HP at the end of each turn for 3 turns", - specialNotes: "#{orb : 1.15x}" - }, - 849: { - captain: "Boosts ATK of Shooter characters by 1.75x", - specialName: "Battle Franky 9", - special: "Deals 5 hits of random STR damage to random enemies, reduces the defense of all enemies by 50% for 2 turns" - }, - 850: { - captain: "Boosts ATK of Striker and Knowledge characters by 1.5x", - specialName: "First-class Assistant of the Passionate Worker", - special: "Changes the top right orb into [DEX], the middle right orb into [STR] and the bottom right orb into [QCK], seals himself for 3 turns" - }, - 851: { - captain: "Boosts ATK of Ambition characters by 1.5x", - specialName: "Snow Country Speciality: Snow Powder Makeup", - special: "Deals 20x character's ATK in character's type damage to one enemy, locks all orbs for 1 turn" - }, - 852: { - captain: "Boosts ATK of Ambition characters by 2x", - specialName: "Snow Country Speciality: Snow Powder Makeup", - special: "Deals 20x character's ATK in character's type damage to one enemy, locks all orbs for 1 turn" - }, - 853: { - specialName: "Robson: Serious Mode", - special: "Following the activation of the special, if every unit scores a Perfect hit, boosts ATK of Tough and Fighters characters by 1.2x for 3 turns" - }, - 854: { - captain: "Boosts ATK of DEX chracters by 1.5x, reduces damage received by 10%", - specialName: "Guard Point: Winter Coat", - special: "Redues damage received by 50% for 3 turns, slightly boosts chances of getting [DEX] orbs for 3 turns" - }, - 855: { - captain: "Boosts ATK of Slasher characters by 2x", - specialName: "Shambles: Holiday Toast", - special: "Changes captain's orb into [RCV], recovers 15x character's RCV in HP" - }, - 856: { - captain: "Boosts ATK of Slasher characters by 2.5x", - specialName: "Shambles: Holiday Toast", - special: "Changes captain's orb into [RCV], recovers 15x character's RCV in HP" - }, - 857: { - captain: "Boosts ATK of PSY characters by 2x", - specialName: "Bonney's Holiday Feast", - special: "Changes adjacent orbs into [RCV] orbs, boosts RCV of PSY characters by 1.5x for 1 turn" - }, - 858: { - captain: "Boosts ATK and RCV of PSY characters by 2x", - specialName: "Bonney's Holiday Feast", - special: "Changes adjacent orbs into [RCV] orbs, boosts RCV of PSY characters by 1.5x for 1 turn" - }, - 859: { - captain: "Boosts ATK of Ambition characters by 1.5x, reduces damage received up to 10% depending on the crew's current HP", - specialName: "Pleading at the Risk of One's Life", - special: "Changes adjacent orbs into [RCV] orbs; if the special is activated with more than 50% health remaining, protects from defeat for 1 turn", - specialNotes: "#{zombie}" - }, - 860: { - captain: "Boosts ATK of Ambition characters by 2x, reduces damage received up to 30% depending on the crew's current HP", - specialName: "Pleading at the Risk of One's Life", - special: "Changes adjacent orbs into [RCV] orbs; if the special is activated with more than 50% health remaining, protects from defeat for 1 turn", - specialNotes: "#{zombie}" - }, - 861: { - specialName: "Bewitching Lovely Iron Mace", - special: "Deals 13x character's ATK in QCK damage to one enemy, reduces damage received by 75% for 1 turn, amplifies the effect of orbs by 1.5x for 1 turn", - specialNotes: "#{orb : 1.5x}", - captain: "Reduces damage received by 10%" - }, - 862: { - captain: "Boosts ATK of QCK characters by 2x, reduces damage received by 10%", - specialName: "Bewitching Lovely Iron Mace", - special: "Deals 13x character's ATK in QCK damage to one enemy, reduces damage received by 75% for 1 turn, amplifies the effect of orbs by 1.5x for 1 turn", - specialNotes: "#{orb : 1.5x}" - }, - 863: { - captain: "Boosts ATK of QCK characters by 1.75x, recovers 2x character's RCV in HP at the end of each turn", - specialName: "Snow Crystal Clima-Tact", - special: "Reduces the defense of all enemies by 50% for 2 turns, reduces the ATK of all enemies by 10% for 2 turns" - }, - 864: { - captain: "Boosts ATK of Freedom characters by 2x", - specialName: "Slave Arrow", - special: "Locks the chain multiplier at 2.5x for 2 turns, delays all enemies for 1 turn" - }, - 865: { - captain: "Boosts ATK and HP of Freedom characters by 2x", - specialName: "Slave Arrow", - special: "Locks the chain multiplier at 2.5x for 2 turns, delays all enemies for 1 turn" - }, - 866: { - captain: "Boosts ATK of Knowledge characters by 2x", - specialName: "Cien Fleur Wing: The Storm", - special: "Boosts ATK of Slasher and Knowledge characters by 1.3x for 2 turns, reduces Bind duration by 2 turns" - }, - 867: { - captain: "Boosts ATK of all characters by 1.5x after the 12th hit in the chain", - specialName: "Tabasco Star: The Storm", - special: "Delays all enemies for 2 turns, deals 9x character's ATK in DEX damage to all enemies" - }, - 868: { - captain: "Boosts ATK of all characters by 1.2x, recovers 1,000 HP at the end of the turn", - specialName: "Heavy Gong: The Storm", - special: "Deals 15x character's ATK in STR damage to one enemy, reduces Bind duration by 3 turns" - }, - 869: { - captain: "Boosts ATK of Ambition characters by 3x until the first hit other than Perfect", - specialName: "Black Knight", - special: "Changes adjacent orbs into matching orbs, amplifies the effect of orbs by 2x for 1 turn", - specialNotes: "#{orb : 2x}" - }, - 870: { - captain: "Boosts ATK of Ambition characters by 3x until the first hit other than Perfect", - specialName: "Black Knight", - special: "Changes adjacent orbs into matching orbs, amplifies the effect of orbs by 2x for 1 turn", - specialNotes: "#{orb : 2x}" - }, - 871: { - captain: "Boosts ATK and RCV of QCK characters by 1.5x", - specialName: "Hobby-Hobby Fruit", - special: "Removes all enemies with HP below 20%", - specialNotes: "The special bypasses all known protective buffs. If the enemy can revive after being defeated, however, the special will only reduce the enemy's HP to 0 and trigger their revive effect." - }, - 872: { - captain: "Boosts ATK and RCV of QCK characters by 2x", - specialName: "Hobby-Hobby Fruit", - special: "Removes all enemies with HP below 20%", - specialNotes: "The special bypasses all known protective buffs. If the enemy can revive after being defeated, however, the special will only reduce the enemy's HP to 0 and trigger their revive effect." - }, - 873: { - captain: "Boosts ATK of Fighter characters by 2.5x if HP is below 30% at the start of the turn", - specialName: "Nyan Nyan Swim", - special: [ - { - "description": "Changes own orb into [PSY], amplifies the effect of orbs by 1.5x for 1 turn", - "cooldown": [ - 13, - 8 - ] - }, - { - "description": "Changes own orb into [psy], amplifies the effect of orbs by 1.75x for 1 turn", - "cooldown": [ - 19, - 14 - ] - } - ], - specialNotes: "#{orb: 1.5x or 1.75x} #{stages}" - }, - 874: { - captain: "Boosts ATK of Fighter characters by 3x if HP is below 30% at the start of the turn", - specialName: "Nyan Nyan Swim", - special: [ - { - "description": "Changes own orb into [PSY], amplifies the effect of orbs by 1.5x for 1 turn", - "cooldown": [ - 13, - 8 - ] - }, - { - "description": "Changes own orb into [psy], amplifies the effect of orbs by 1.75x for 1 turn", - "cooldown": [ - 19, - 14 - ] - } - ], - specialNotes: "#{orb: 1.5x or 1.75x} #{stages}" - }, - 875: { - captain: "Boosts ATK of Knowledge and Ambition characters by 2x", - specialName: "Beto Launcher", - special: "Changes the captain's orb into a matching orb, locks all orbs for 1 turn, deals 13x character's ATK in INT damage to all enemies" - }, - 876: { - captain: "Boosts ATK of Knowledge and Ambition characters by 2.25x, makes [TND] and [RCV] orbs \"beneficial\" to Knowledge and Ambition characters", - captainNotes: "\"Beneficial\" orbs grant the same ATK boost as matching orbs while retaining their original function.", - specialName: "Beto Launcher", - special: "Changes the captain's orb into a matching orb, locks all orbs for 1 turn, deals 13x character's ATK in INT damage to all enemies" - }, - 877: { - captain: "Boosts amount of beli received by 2x", - specialName: "Heaven's Do Art", - special: "Reduces any damage received above 2,000 HP by 88% for 1 turn", - specialNotes: "The exact formula for the damage received is: 2000 + ((total damage) - 2000) * 0.12" - }, - 878: { - captain: "Boosts ATK of all characters by 1.5x, boosts amount of beli received by 2x", - specialName: "Heaven's Do Art", - special: "Reduces any damage received above 2,000 HP by 88% for 1 turn", - specialNotes: "The exact formula for the damage received is: 2000 + ((total damage) - 2000) * 0.12" - }, - 879: { - captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of Fighter characters by 1.75x", - specialName: "Battle Preservation Fist: Manki Kayaku", - special: "Changes all orbs including [BLOCK] orbs into [G] orbs, deals random typeless damage to all enemies", - specialNotes: "#{gOrbs}" - }, - 880: { - captain: "Reduces cooldown of all specials by 3 turns at the start of the fight, boosts ATK of Fighter characters by 2x", - specialName: "Battle Preservation Fist: Manki Kayaku", - special: "Changes all orbs including [BLOCK] orbs into [G] orbs, deals random typeless damage to all enemies", - specialNotes: "#{gOrbs}" - }, - 881: { - captain: "Boosts ATK of Shooter and Freedom characters by 2x following a chain of Good > Great > Perfect hits", - specialName: "Fighting Music: Conflict Chekera", - special: "Doubles damage received for 2 turns, reduces RCV by 90% for 2 turns, boosts ATK of Shooter and Freedom characters by 1.75x for 1 turn" - }, - 882: { - captain: "Boosts ATK of Shooter and Freedom characters by 3x following a chain of Good > Great > Perfect hits", - specialName: "Fighting Music: Conflict Chekera", - special: "Doubles damage received for 2 turns, reduces RCV by 90% for 2 turns, boosts ATK of Shooter and Freedom characters by 1.75x for 1 turn" - }, - 883: { - captain: "Boosts ATK and HP of Tough characters by 1.25x", - specialName: "Hakoku Sovereignity", - special: "Deals 20x character's ATK in character's type damage to all enemies, boosts ATK of Tough characters by 1.5x for 1 turn. If \"Hakoku Sovereignity\" is used again in the same turn the special is activated in, boosts ATK of Tough characters by 2x instead." - }, - 884: { - captain: "Boosts ATK and HP of Tough characters by 1.5x", - specialName: "Hakoku Sovereignity", - special: "Deals 20x character's ATK in character's type damage to all enemies, boosts ATK of Tough characters by 1.5x for 1 turn. If \"Hakoku Sovereignity\" is used again in the same turn the special is activated in, boosts ATK of Tough characters by 2x instead." - }, - 885: { - captain: "Boosts ATK of Fighter characters by 2x, reduces damage received by 10%", - specialName: "Arabesque Brick Fist: Sun", - special: "Cuts the current HP of each enemy by 10%, boosts ATK of Fighter characters by 1.5x for 1 turn if HP is below 30% when the special is activated" - }, - 886: { - captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of Slasher characters by 2x", - specialName: "Daisy Blade: First", - special: "Deals 15x character's ATK in STR damage to all enemies, boosts ATK of Slasher characters by 1.5x for 1 turn if HP is below 30% when the special is activated" - }, - 887: { - captain: "Boosts ATK of Ambition characters by 1.5x, boosts amount of beli received by 1.2x", - specialName: "Special Muggy Ball: Flashy", - special: "Reduces the defense of all enemies by 80% for 1 turn, deals 15x character's ATK in QCK damage to all enemies" - }, - 888: { - specialName: "Negative Ghost", - special: "Slightly reduces the ATK of all enemies for 3 turns", - specialNotes: "The reduction does not apply to damage from specials" - }, - 889: { - captain: "Boosts ATK and RCV of DEX characters by 1.2x", - specialName: "Ghost Rap", - special: "Changes [STR] orbs into [DEX] orbs, deals 10x character's ATK in DEX damage to all enemies" - }, - 890: { - captain: "Boosts ATK and RCV of DEX characters by 1.5x", - specialName: "Ghost Rap", - special: "Changes [STR] orbs into [DEX] orbs, deals 10x character's ATK in DEX damage to all enemies" - }, - 891: { - captain: "Boosts ATK and RCV of Tough characters by 1.75x", - specialName: "Resurrection of the Dead", - special: "Reduces damage received by 50% for 1 turn, boosts ATK of Tough characters by 1.25x for 1 turn", - specialNotes: "SPECIALNOTES" - }, - 892: { - captain: "Boosts chain multiplier by 2x", - specialName: "Hands of the Dead", - special: "Switches orbs between slots three times" - }, - 893: { - captain: "Boosts ATK of Tough characters by 3x after scoring 3 Perfects in a row", - specialName: "Oars Ball", - special: "Reduces damage received by 50% for 1 turn, deals 30x character's ATK in STR damage to all enemies" - }, - 894: { - captain: "Boosts ATK of Ambition characters by 3x following a chain of Good > Great > Perfect hits", - specialName: "Brick Bat: Black Box", - special: "Empties all slots with [INT] orbs, deals several times the character's ATK in INT damage to one enemy", - specialNotes: "The exact multiplier used is chosen based on the number of [INT] orbs consumed: 1 orb will give a 10x multiplier, 2 orbs 15x, 3 orbs 20x, 4 orbs 50x, 5 orbs 100x, 6 orbs 200x. It's not possible to activate the special without consuming at least one [INT] orb." - }, - 895: { - captain: "Boosts ATK of Slasher characters by 1.5x", - specialName: "Dying Chorus: Binks' Sake", - special: "Recovers 6x character's RCV in HP at the end of each turn for 3 turns" - }, - 896: { - captain: "Boosts ATK of Slasher characters by 2x", - specialName: "Dying Chorus: Binks' Sake", - special: "Recovers 6x character's RCV in HP at the end of each turn for 3 turns" - }, - 897: { - captain: "Boosts ATK of Knowledge and Ambition characters by 2x", - specialName: "Ground Death: Thirst", - special: "Changes own orb into [STR], randomizes all other orbs, cuts the current HP of all enemies by 10%" - }, - 898: { - captain: "Boosts ATK and HP of Striker and Knowledge characters by 1.5x", - specialName: "Championship Fight: Little Garden Three", - special: "Deals 10x character's ATK in QCK damage to all enemies, changes adjacent orbs into [G] orbs", - specialNotes: "#{gOrbs}" - }, - 899: { - captain: "Boosts ATK of Fighter and Freedom characters by 1.75x and their RCV by 1.25x", - specialName: "Hymn to Friendship: \"Okama Way\" Two", - special: "Reduces Silence duration by 5 turns, recovers 10x character's RCV in HP" - }, - 900: { - captain: "Boosts ATK of Shooter characters by 2x if HP is above 99% at the start of the turn", - specialName: "Franky Destroy Gun", - special: "Deals 6 hits of 2,000 fixed damage to random enemies, randomly changes opposite orbs on Shooter and Freedom characters into either [G] orbs or matching orbs", - specialNotes: "The orb shuffle only applies to Shooter and Freedom characters, other classes are unaffected. #{gOrbs}" - }, - 901: { - captain: "Boosts ATK of Shooter characters by 2.75x if HP is above 99% at the start of the turn", - specialName: "Franky Destroy Gun", - special: "Deals 6 hits of 2,000 fixed damage to random enemies, randomly changes opposite orbs on Shooter and Freedom characters into either [G] orbs or matching orbs", - specialNotes: "The orb shuffle only applies to Shooter and Freedom characters, other classes are unaffected. #{gOrbs}" - }, - 902: { - captain: "Boosts ATK and HP of Tough characters by 1.25x", - specialName: "Hakoku Sovereignity", - special: "Deals 20x character's ATK in character's type damage to all enemies, boosts ATK of Tough characters by 1.5x for 1 turn. If \"Hakoku Sovereignity\" is used again in the same turn the special is activated in, boosts ATK of Tough characters by 2x instead." - }, - 903: { - captain: "Boosts ATK and HP of Tough characters by 1.5x", - specialName: "Hakoku Sovereignity", - special: "Deals 20x character's ATK in character's type damage to all enemies, boosts ATK of Tough characters by 1.5x for 1 turn. If \"Hakoku Sovereignity\" is used again in the same turn the special is activated in, boosts ATK of Tough characters by 2x instead." - }, - 904: { - captain: "Protects from defeat as long as HP is above 50%", - captainNotes: "#{zombie}", - specialName: "Yokozuna Slap!", - special: "Deals 20x character's ATK in STR damage to one enemy, delays all enemies for 1 turn" - }, - 905: { - captain: "Boosts ATK of Slasher characters by 2.5x if HP is below 30% at the start of the turn", - specialName: "Two Gorilla Cut", - special: [ - { - "description": "Changes own orb into [STR], boosts his own ATK by 1.5x for 2 turns", - "cooldown": 17 - }, - { - "description": "Changes own orb into [STR], boosts ATK of Slasher characters by 1.5x for 2 turns", - "cooldown": 21 - }, - { - "description": "Changes own orb into [STR], boosts ATK of Slasher characters by 1.75x for 2 turns", - "cooldown": 24 - } - ], - specialNotes: "#{stages}" - }, - 906: { - captain: "Boosts ATK of Slasher characters by 2.75x if HP is below 30% at the start of the turn", - specialName: "Two Gorilla Cut", - special: [ - { - "description": "Changes own orb into [STR], boosts his own ATK by 1.5x for 2 turns", - "cooldown": 17 - }, - { - "description": "Changes own orb into [STR], boosts ATK of Slasher characters by 1.5x for 2 turns", - "cooldown": 21 - }, - { - "description": "Changes own orb into [STR], boosts ATK of Slasher characters by 1.75x for 2 turns", - "cooldown": 24 - } - ], - specialNotes: "#{stages}" - }, - 907: { - specialName: "Cien Fleur: Big Tree", - special: "Delays all enemies for 1 turn, locks all orbs for 1 turn, deals 5,000 fixed damage to all enemies, reduces crew's HP to 1", - captain: "Boosts ATK and RCV of Knowledge characters by 1.5x if HP is below 30% at the start of the turn" - }, - 908: { - specialName: "Cien Fleur: Big Tree", - special: "Delays all enemies for 1 turn, locks all orbs for 1 turn, deals 5,000 fixed damage to all enemies, reduces crew's HP to 1", - captain: "Boosts ATK of Knowledge characters by 2.5x and their RCV by 1.75x if HP is below 30% at the start of the turn" - }, - 909: { - captain: "Boosts ATK and RCV of PSY characters by 1.5x", - specialName: "Hero of Justice! Chopper Mask!!", - special: "Recovers 5,000 HP, boosts ATK of PSY characters by 1.5x for 2 turns" - }, - 910: { - specialName: "Hero of Justice! Chopper Mask!!", - special: "Recovers 5,000 HP, boosts ATK of PSY characters by 1.5x for 2 turns", - captain: "Boosts ATK of PSY characters by 2x, their RCV by 1.5x, makes [INT] orbs \"beneficial\" to PSY characters", - captainNotes: "\"Beneficial\" orbs grant the same ATK boost as matching orbs." - }, - 911: { - specialName: "Diable Jambe: Premier Hachis", - special: [ - { - "description": "Deals 13x character's ATK in DEX damage to one enemy, boosts ATK of Tough characters by 1.2x for 1 turn", - "cooldown": 15 - }, - { - "description": "Deals 20x character's ATK in DEX damage to one enemy, boosts ATK of Tough characters by 2x for 1 turn", - "cooldown": 25 - } - ], - captain: "Boosts ATK and HP of Tough characters by 1.5x", - specialNotes: "#{stages}" - }, - 912: { - specialName: "Diable Jambe: Premier Hachis", - special: [ - { - "description": "Deals 13x character's ATK in DEX damage to one enemy, boosts ATK of Tough characters by 1.2x for 1 turn", - "cooldown": 15 - }, - { - "description": "Deals 20x character's ATK in DEX damage to one enemy, boosts ATK of Tough characters by 2x for 1 turn", - "cooldown": 25 - } - ], - captain: "Boosts ATK of Tough characters by 2.25x, their HP by 1.5x, recovers 4x character's RCV in HP at the end of each turn", - specialNotes: "#{stages}" - }, - 913: { - captain: "Boosts ATK of QCK characters by 2.5x if they have a matching orb", - specialName: "Black Magic Summoning: Advent of the Demon Lord Satan", - special: "Seals himself for 1 turn, changes [BLOCK] orbs into matching orbs, randomly changes opposite orbs into either [STR], [QCK], [DEX], [PSY] or [INT] orbs" - }, - 914: { - captain: "Boosts ATK of QCK characters by 3x if they have a matching orb, by 1.2x otherwise", - specialName: "Black Magic Summoning: Advent of the Demon Lord Satan", - special: "Seals himself for 1 turn, changes [BLOCK] orbs into matching orbs, randomly changes opposite orbs into either [STR], [QCK], [DEX], [PSY] or [INT] orbs" - }, - 915: { - captain: "Boosts ATK and RCV of Knowledge characters by 1.2x", - specialName: "Feeling of Mutual Love", - special: "Boosts ATK and RCV of Knowledge characters by 1.5x for 1 turn" - }, - 916: { - captain: "Boosts ATK and RCV of Knowledge characters by 1.75x", - specialName: "Feeling of Mutual Love", - special: "Boosts ATK and RCV of Knowledge characters by 1.5x for 1 turn" - }, - 917: { - captain: "Boosts ATK of Shooter characters by 1.5x", - specialName: "Kuja's Haki Arrow", - special: "Deals 5,000 fixed damage to one enemy, delays all enemies for 1 turn, changes [RCV] orbs on Shooter characters into matching orbs", - specialNotes: "The orb shuffle only applies to Shooter characters, other classes are unaffected." - }, - 918: { - captain: "Boosts ATK of Shooter characters by 1.75x, recovers a small amount of health at the end of each turn", - specialName: "Kuja's Haki Arrow", - special: "Deals 5,000 fixed damage to one enemy, delays all enemies for 1 turn, changes [RCV] orbs on Shooter characters into matching orbs", - specialNotes: "The orb shuffle only applies to Shooter characters, other classes are unaffected." - }, - 919: { - specialName: "Spike of the Warrior Defending Her Country", - special: "Reduces damage received from STR enemies by 50% for 2 turns" - }, - 920: { - specialName: "Snake Bow of the Warrior Defending Her Country", - special: "Changes the orbs in the middle row into [RCV] orbs, changes the orbs in the bottom row into [TND] orbs" - } -}; \ No newline at end of file + 1: { + special: "Deals 5x character's ATK in STR damage to one enemy", + specialName: "Spinning Gum Punch" + }, + 2: { + special: "Deals 7x character's ATK in STR damage to one enemy", + specialName: "Gum-Gum Pistol", + captain: "Boosts ATK of all characters by 1.5x" + }, + 3: { + special: "Deals 15x character's ATK in STR damage to one enemy", + specialName: "Gum-Gum Bazooka", + captain: "Boosts ATK of all characters by 1.5x" + }, + 4: { + captain: "Boosts ATK of STR characters by 2x, and ATK of all others by 1.5x", + special: "Deals 25x character's ATK in STR damage to one enemy", + specialName: "Gum-Gum Twin Jet Pistol", + limit: [ + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Aquire Potential 1: Enrage" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base HP by 50" }, + { "description": "Aquire Sailor Ability 1: Boosts own base ATK by 100 if this character is the last in the chain to attack" }, + { "description": "Boosts base HP by 50" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Aquire Sailor Ability 2: Makes [QCK] orbs \"beneficial\" for this unit" }, + { "description": "Aquire Potential 2: Reduce No Healing duration" }, + ], + potential: [ + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 20", + "Level 2: Boosts base ATK by 30", + "Level 3: Boosts base ATK by 40", + "Level 4: Boosts base ATK by 50", + "Level 5: Boosts base ATK by 100" + ] + }, + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: Reduces No Healing duration by 1 turn", + "Level 2: Reduces No Healing duration by 1 turn", + "Level 3: Reduces No Healing duration by 2 turns", + "Level 4: Reduces No Healing duration by 3 turns", + "Level 5: Reduces No Healing duration by 4 turns" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 5: { + special: "Deals 7x character's ATK in DEX damage to one enemy", + specialName: "Oni Giri", + captain: "Boosts ATK of DEX characters by 1.5x" + }, + 6: { + special: "Deals 10x character's ATK in DEX damage to all enemies", + specialName: "Three Thousand Worlds", + captain: "Boosts ATK of DEX characters by 1.5x" + }, + 7: { + special: "Deals 10x character's ATK in DEX damage to all enemies", + specialName: "108 Pound Phoenix", + captain: "Boosts ATK of DEX characters by 1.5x" + }, + 8: { + special: "Deals 15x character's ATK in DEX damage to all enemies", + specialName: "Ashura Ichibugin", + captain: "Boosts ATK and HP of DEX characters by 2x", + limit: [ + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 40" }, + { "description": "Aquire Potential 1: [QCK] Damage Reduction" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Aquire Sailor Ability 1: Restores his own special by 1 turn when it is rewinded" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Aquire Sailor Ability 2: Boosts base ATK of [DEX] characters by 40" }, + { "description": "Boosts base HP by 70" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Critical Hit" }, + ], + potential: [ + { + "Name": "[QCK] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [QCK] characters by ?%", + "Level 2: Reduce damage taken from [QCK] characters by ?%", + "Level 3: Reduce damage taken from [QCK] characters by ?%", + "Level 4: Reduce damage taken from [QCK] characters by ?%", + "Level 5: Reduce damage taken from [QCK] characters by ?%" + ] + }, + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage" + ] + }, + ] + }, + 9: { + special: "Recovers 1,000 HP", + specialName: "Cat Burglar", + captain: "Reduces damage received from INT enemies by 20%" + }, + 10: { + special: "Deals 15x character's ATK in INT damage to one enemy", + specialName: "Tornado Tempo", + captain: "Boosts ATK of INT characters by 1.5x" + }, + 11: { + special: "Reduces damage received from INT enemies by 100% for 1 turn", + specialName: "Mirage Tempo", + captain: "Boosts ATK of INT characters by 1.5x" + }, + 12: { + special: "Deals 15x character's ATK in INT damage to all enemies", + specialName: "Thunderbolt Tempo", + captain: "Boosts ATK and HP of INT characters by 1.5x" + }, + 13: { + special: "Delays all enemies for 1 turn", + specialName: "Liar", + captain: "Boosts ATK of Shooter characters by 1.2x" + }, + 14: { + special: "Delays all enemies for 2 turns", + specialName: "Tabasco Star", + captain: "Boosts ATK of PSY characters by 1.5x" + }, + 15: { + special: "Delays all enemies for 3 turns", + specialName: "Usopp Golden Pound", + captain: "Boosts ATK of PSY characters by 1.5x" + }, + 16: { + special: "Delays all enemies for 3 turns, deals 15x character's ATK in PSY damage to all enemies", + specialName: "Fire Bird Star", + captain: "Boosts ATK and HP of PSY characters by 1.5x", + limit: "This character has a limit break path", + }, + 17: { + special: "Recovers 10x character's RCV in HP", + specialName: "Special Fried Rice", + captain: "Boosts ATK of QCK characters by 1.5x" + }, + 18: { + special: "Reduces the defense of all enemies by 50% for 2 turns", + specialName: "Plastic Surgery Shot", + captain: "Boosts HP of QCK characters by 1.5x" + }, + 19: { + special: "Recovers 10x character's RCV in HP", + specialName: "Hot Rock Stew", + captain: "Boosts ATK of QCK characters by 1.5x" + }, + 20: { + special: "Deals 5,000 fixed damage to all enemies", + specialName: "Diable Jambe", + specialNotes: "#{fixed}", + captain: "Boosts ATK and HP of QCK characters by 1.5x" + }, + 21: { + special: "Changes adjacent orbs into [RCV] orbs", + specialName: "Hearty Yell", + captain: "Boosts RCV of PSY characters by 1.2x" + }, + 22: { + special: "Deals 15x character's ATK in PSY damage to one enemy", + specialName: "Heavy Gong", + captain: "Boosts RCV of PSY characters by 1.5x" + }, + 23: { + special: "Changes adjacent orbs into [RCV] orbs", + specialName: "Scope", + captain: "Boosts RCV of INT characters by 1.5x" + }, + 24: { + special: "Reduces the defense of all enemies by 50% for 2 turns", + specialName: "Hoofprint Roseo", + captain: "Boosts RCV of STR characters by 1.5x" + }, + 25: { + special: "Deals 7x character's ATK in QCK damage to all enemies", + specialName: "Horn Point Roseo Colonnade", + captain: "Boosts RCV of QCK characters by 1.5x" + }, + 26: { + special: "Reduces damage received by 50% for 3 turns", + specialName: "Guard Point", + captain: "Boosts RCV of DEX characters by 1.5x" + }, + 27: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Slash", + captain: "Boosts HP of QCK characters by 1.2x" + }, + 28: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Straight", + captain: "Boosts ATK of Fighter characters by 1.2x" + }, + 29: { + special: "Deals 7x character's ATK in STR damage to one enemy", + specialName: "Iron Mace Beauty", + captain: "Reduces damage received from STR enemies by 30%" + }, + 30: { + special: "Reduces damage received by 80% for 1 turn", + specialName: "Slip-Slip Tracks", + captain: "Reduces damage received from STR enemies by 50%" + }, + 31: { + captain: "Recovers 2x character's RCV in HP at the end of each turn" + }, + 32: { + special: "Changes [RCV] orbs into [TND] orbs", + specialName: "Shooting Spree", + captain: "Recovers 2x character's RCV in HP at the end of each turn" + }, + 33: { + captain: "Reduces damage received from INT enemies by 30%" + }, + 34: { + special: "Reduces the defense of all enemies by 100% for 1 turn", + specialName: "Straw Doll Of Resentment", + captain: "Reduces damage received from INT enemies by 30%" + }, + 35: { + special: "Deals 5x character's ATK in STR damage to one enemy", + specialName: "Execution Axe-Hand", + captain: "Boosts HP of Slasher characters by 1.2x" + }, + 36: { + special: "Deals 5x character's ATK in PSY damage to one enemy", + specialName: "Fierce Bite", + captain: "Boosts ATK of PSY characters by 1.5x" + }, + 37: { + special: "Deals 5x character's ATK in DEX damage to one enemy", + specialName: "The Dance Of A Hundred Kamikaze Tops", + captain: "Boosts ATK of DEX characters by 1.5x" + }, + 38: { + special: "Changes [RCV] orbs into [INT] orbs", + specialName: "Chop-Chop Festival", + captain: "Boosts ATK of INT characters by 1.5x" + }, + 39: { + special: "Changes [RCV] orbs into [INT] orbs", + specialName: "Chop-Chop Festival", + captain: "Boosts ATK of INT characters by 2x" + }, + 40: { + special: "Changes adjacent orbs into [RCV] orbs", + specialName: "[RCV] Slot Storm", + captain: "Reduces damage received from Shooter enemies by 30%" + }, + 41: { + special: "Changes [RCV] orbs into [INT] orbs", + specialName: "Cat Snatch", + captain: "Boosts RCV of INT characters by 1.2x" + }, + 42: { + special: "Deals 3x character's ATK in STR damage to all enemies", + specialName: "Cat-A-Pult Cat-Astrophe", + captain: "Boosts ATK of STR characters by 1.2x" + }, + 43: { + special: "Changes [RCV] orbs into [DEX] orbs", + specialName: "One, Two, Django", + captain: "Reduces damage received by 10%" + }, + 44: { + special: "Changes [RCV] orbs into [DEX] orbs", + specialName: "Dance Heaven", + captain: "Reduces damage received by 10%" + }, + 45: { + special: "Deals 5x character's ATK in QCK damage to all enemies", + specialName: "Death Scoop", + captain: "Boosts ATK of QCK characters by 1.2x" + }, + 46: { + special: "Deals 5x character's ATK in QCK damage to all enemies", + specialName: "Death Scoop", + captain: "Boosts ATK of QCK characters by 1.5x" + }, + 47: { + special: "Changes [TND] orbs into [RCV] orbs", + specialName: "[TND] Slot Change [RCV]" + }, + 48: { + special: "Changes adjacent orbs into [RCV] orbs", + specialName: "[RCV] Slot Storm" + }, + 49: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Straight", + captain: "Boosts ATK of STR characters by 1.5x" + }, + 50: { + special: "Deals 5x character's ATK in STR damage to one enemy", + specialName: "The Meatball Of Doom", + captain: "Recovers 3x character's RCV in HP at the end of each turn" + }, + 51: { + captain: "Recovers 3x character's RCV in HP at the end of each turn" + }, + 52: { + special: "Changes [STR] orbs into [DEX] orbs", + specialName: "Chef Drop", + captain: "Boosts ATK of Fighter characters by 2.5x" + }, + 53: { + captain: "Reduces damage received from QCK enemies by 30%" + }, + 54: { + special: "Deals 7x character's ATK in QCK damage to one enemy", + specialName: "Demonic Dance", + captain: "Reduces damage received from QCK enemies by 50%" + }, + 55: { + captain: "Reduces damage received from STR enemies by 30%" + }, + 56: { + special: "Changes [RCV] orbs into [STR] orbs", + specialName: "Fire Pearl Privilege", + captain: "Reduces damage received from STR enemies by 50%" + }, + 57: { + special: "Deals 7x character's ATK in INT damage to one enemy", + specialName: "Chain Hammer", + captain: "Reduces damage received by 10%" + }, + 58: { + special: "Poisons all enemies", + specialNotes: "#{poison}", + specialName: "MH5", + captain: "Reduces damage received by 20%" + }, + 59: { + special: "Changes [PSY] orbs into [INT] orbs", + specialName: "[PSY] Slot Change [INT]", + captain: "Boosts ATK of INT characters by 1.2x" + }, + 60: { + special: "Changes [TND] orbs into [STR] orbs", + specialName: "[TND] Slot Change [STR]", + captain: "Boosts ATK of STR characters by 1.5x" + }, + 61: { + special: "Deals 5x character's ATK in INT damage to all enemies", + specialName: "Lip-O-Cannon", + captain: "Boosts HP of Shooter characters by 1.5x" + }, + 62: { + special: "Deals 7x character's ATK in STR damage to one enemy", + specialName: "Guffaw Palm Bomb", + captain: "Boosts HP of Fighter characters by 1.5x" + }, + 63: { + captain: "Reduces damage received from DEX enemies by 30%" + }, + 64: { + special: "Deals 10x character's ATK in DEX damage to all enemies", + specialName: "New Year's Open Body Slam", + captain: "Reduces damage received from DEX enemies by 50%" + }, + 65: { + special: "Deals 7x character's ATK in STR damage to one enemy", + specialName: "Shark On Darts", + captain: "Boosts ATK of Slasher characters by 2x" + }, + 66: { + special: "Deals 15x character's ATK in STR damage to one enemy", + specialName: "Shark On Tooth", + captain: "Boosts ATK of Slasher characters by 2x" + }, + 67: { + special: "Deals 25x character's ATK in QCK damage to one enemy", + specialName: "Quick Draw", + captain: "Boosts RCV of Slasher characters by 1.5x" + }, + 68: { + special: "Deals 25x character's ATK in QCK damage to one enemy", + specialName: "Quick Draw", + captain: "Boosts RCV of Slasher characters by 2x" + }, + 69: { + special: "Reduces damage received by 50% for 3 turns", + specialName: "White Out", + captain: "Reduces damage received by 20%" + }, + 70: { + special: "Reduces damage received by 50% for 3 turns", + specialName: "White Out", + captain: "Reduces damage received by 20%" + }, + 71: { + special: "Reduces damage received by 50% for 1 turn", + specialName: "Enchanting Vertigo Dance", + captain: "Recovers 2x character's RCV in HP at the end of each turn" + }, + 72: { + special: "Randomizes all orbs", + specialName: "Charge! Supersonic Duck Squadron!", + captain: "Recovers 3x character's RCV in HP at the end of each turn" + }, + 73: { + special: "Randomizes all orbs", + specialName: "Charge! Supersonic Duck Squadron!", + captain: "Recovers 5x character's RCV in HP at the end of each turn" + }, + 74: { + special: "Deals 25x character's ATK in QCK damage to one enemy", + specialName: "Flame Fist", + captain: "Boosts ATK of QCK characters by 2x" + }, + 75: { + special: "Deals 15x character's ATK in QCK to all enemies", + specialName: "Flame Mirror", + captain: "Boosts ATK of QCK characters by 2.5x" + }, + 76: { + special: "Deals 15x character's ATK in PSY damage to all enemies", + specialName: "Conqueror's Haki", + captain: "Boosts ATK of PSY characters by 2x" + }, + 77: { + special: "Deals 15x character's ATK in PSY damage to all enemies", + specialName: "Conqueror's Haki", + captain: "Boosts ATK of PSY characters by 2.5x" + }, + 119: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Slash" + }, + 120: { + special: "Deals 5x character's ATK in character's type damage to all enemies", + specialName: "Hyper Shot" + }, + 121: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Straight" + }, + 122: { + special: "Reduces damage received by 20% for 1 turn", + specialName: "Iron Shield" + }, + 123: { + special: "Changes [STR] orbs into [DEX] orbs", + specialName: "[STR] Slot Change [DEX]" + }, + 124: { + special: "Reduces damage received by 20% for 1 turn", + specialName: "Iron Shield" + }, + 125: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Straight" + }, + 126: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Slash" + }, + 127: { + special: "Reduces the defense of all enemies by 50% for 1 turn", + specialName: "Shield Crusher" + }, + 128: { + special: "Changes [QCK] orbs into [DEX] orbs", + specialName: "[QCK] Slot Change [DEX]" + }, + 129: { + special: "Changes [INT] orbs into [PSY] orbs", + specialName: "[INT] Slot Change [PSY]" + }, + 130: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Slash" + }, + 131: { + special: "Changes [RCV] orbs into [STR] orbs", + specialName: "[RCV] Slot Change [STR]" + }, + 132: { + special: "Changes [DEX] orbs into [QCK] orbs", + specialName: "[DEX] Slot Change [QCK]" + }, + 133: { + special: "Changes [QCK] orbs into [DEX] orbs", + specialName: "[QCK] Slot Change [DEX]" + }, + 134: { + special: "Changes [QCK] orbs into [RCV] orbs", + specialName: "[QCK] Slot Change [RCV]" + }, + 135: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Spiral" + }, + 136: { + special: "Deals 5x character's ATK in character's type damage to all enemies", + specialName: "Hyper Shot" + }, + 137: { + special: "Reduces the defense of all enemies by 50% for 1 turn", + specialName: "Shield Crusher" + }, + 138: { + special: "Changes [DEX] orbs into [RCV] orbs", + specialName: "[DEX] Slot Change [RCV]" + }, + 139: { + special: "Changes [PSY] orbs into [RCV] orbs", + specialName: "[PSY] Slot Change [RCV]" + }, + 140: { + special: "Deals 5x character's ATK in character's type damage to all enemies", + specialName: "Hyper Shot" + }, + 141: { + special: "Reduces damage received by 20% for 1 turn", + specialName: "Iron Shield" + }, + 142: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Straight" + }, + 143: { + special: "Reduces damage received by 20% for 1 turn", + specialName: "Iron Shield" + }, + 144: { + special: "Changes [STR] orbs into [DEX] orbs", + specialName: "[STR] Slot Change [DEX]" + }, + 145: { + special: "Reduces damage received by 20% for 1 turn", + specialName: "Iron Shield" + }, + 146: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Straight" + }, + 147: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Slash" + }, + 148: { + special: "Reduces the defense of all enemies by 50% for 1 turn", + specialName: "Shield Crusher" + }, + 149: { + special: "Changes [QCK] orbs into [DEX] orbs", + specialName: "[QCK] Slot Change [DEX]" + }, + 150: { + special: "Changes [INT] orbs into [PSY] orbs", + specialName: "[INT] Slot Change [PSY]" + }, + 151: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Slash" + }, + 152: { + special: "Changes [RCV] orbs into [STR] orbs", + specialName: "[RCV] Slot Change [STR]" + }, + 153: { + special: "Changes [DEX] orbs into [QCK] orbs", + specialName: "[DEX] Slot Change [QCK]" + }, + 154: { + special: "Changes [QCK] orbs into [DEX] orbs", + specialName: "[QCK] Slot Change [DEX]" + }, + 155: { + special: "Changes [QCK] orbs into [RCV] orbs", + specialName: "[QCK] Slot Change [RCV]" + }, + 156: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Spiral" + }, + 157: { + special: "Deals 5x character's ATK in character's type damage to all enemies", + specialName: "Hyper Shot" + }, + 158: { + special: "Reduces the defense of all enemies by 50% for 1 turn", + specialName: "Shield Crusher" + }, + 159: { + special: "Changes [DEX] orbs into [RCV] orbs", + specialName: "[DEX] Slot Change [RCV]" + }, + 160: { + special: "Changes [PSY] orbs into [RCV] orbs", + specialName: "[PSY] Slot Change [RCV]" + }, + 161: { + special: "Deals 5x character's ATK in character's type damage to all enemies", + specialName: "Hyper Shot" + }, + 162: { + special: "Reduces damage received by 20% for 1 turn", + specialName: "Iron Shield" + }, + 163: { + special: "Changes [DEX] orbs into [TND] orbs", + specialName: "[DEX] Slot Change [TND]" + }, + 164: { + special: "Changes [QCK] orbs into [TND] orbs", + specialName: "[QCK] Slot Change [TND]" + }, + 165: { + special: "Recovers 5x character's RCV in HP", + specialName: "Light Healing" + }, + 166: { + special: "Recovers 5x character's RCV in HP", + specialName: "Light Healing" + }, + 167: { + special: "Recovers 5x character's RCV in HP", + specialName: "Light Healing" + }, + 168: { + special: "Recovers 5x character's RCV in HP", + specialName: "Light Healing" + }, + 169: { + special: "Recovers 5x character's RCV in HP", + specialName: "Light Healing" + }, + 170: { + special: "Reduces damage received by 20% for 1 turn", + specialName: "Iron Shield" + }, + 171: { + special: "Reduces damage received by 20% for 1 turn", + specialName: "Iron Shield" + }, + 172: { + special: "Reduces damage received by 20% for 1 turn", + specialName: "Iron Shield" + }, + 173: { + special: "Reduces damage received by 20% for 1 turn", + specialName: "Iron Shield" + }, + 174: { + special: "Reduces damage received by 20% for 1 turn", + specialName: "Iron Shield" + }, + 175: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Straight" + }, + 176: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Slash" + }, + 177: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Spiral" + }, + 178: { + special: "Deals 5x character's ATK in character's type damage to all enemies", + specialName: "Hyper Shot" + }, + 179: { + special: "Changes [QCK] orbs into [STR] orbs", + specialName: "[QCK] Slot Change [STR]" + }, + 180: { + special: "Recovers 5x character's RCV in HP", + specialName: "Light Healing" + }, + 181: { + special: "Changes [STR] orbs into [QCK] orbs", + specialName: "[STR] Slot Change [QCK]" + }, + 182: { + special: "Recovers 5x character's RCV in HP", + specialName: "Light Healing" + }, + 183: { + special: "Changes [RCV] orbs into [INT] orbs", + specialName: "[RCV] Slot Change [INT]" + }, + 184: { + special: "Changes [QCK] orbs into [STR] orbs", + specialName: "[QCK] Slot Change [STR]" + }, + 185: { + special: "Recovers 5x character's RCV in HP", + specialName: "Light Healing" + }, + 186: { + special: "Changes [STR] orbs into [QCK] orbs", + specialName: "[STR] Slot Change [QCK]" + }, + 187: { + special: "Recovers 5x character's RCV in HP", + specialName: "Light Healing" + }, + 188: { + special: "Changes [RCV] orbs into [INT] orbs", + specialName: "[RCV] Slot Change [INT]" + }, + 194: { + special: "Changes [QCK] orbs into [STR] orbs", + specialName: "[QCK] Slot Change [STR]", + captain: "Boosts ATK of STR characters by 1.5x" + }, + 195: { + special: "Recovers 5x character's RCV in HP", + specialName: "Light Healing", + captain: "Boosts RCV of DEX characters by 1.5x" + }, + 196: { + special: "Changes [STR] orbs into [QCK] orbs", + specialName: "[STR] Slot Change [QCK]", + captain: "Boosts ATK of QCK characters by 1.5x" + }, + 197: { + special: "Recovers 5x character's RCV in HP", + specialName: "Light Healing", + captain: "Reduces damage received from PSY enemies by 20%" + }, + 198: { + special: "Changes [RCV] orbs into [INT] orbs", + specialName: "[RCV] Slot Change [INT]", + captain: "Boosts ATK of Shooter characters by 1.5x" + }, + 199: { + special: "Deals 15x character's ATK in STR damage to one enemy", + specialName: "Nez-Palm Cannon", + captain: "Boosts ATK of STR characters by 1.5x" + }, + 200: { + special: "Deals 20x character's ATK in STR damage to one enemy", + specialName: "Breeze Breath Bomb", + captain: "Boosts ATK of STR characters by 2x" + }, + 201: { + captain: "Boosts HP of Fighter characters by 1.5x" + }, + 202: { + special: "Changes [RCV] orbs into [QCK] orbs", + specialName: "10,000 Kill-O-Guillotine", + captain: "Boosts HP of Fighter characters by 2x" + }, + 203: { + captain: "Reduces damage received from INT enemies by 10%" + }, + 204: { + special: "Delays all enemies for 1 turn", + specialName: "Extra Special Candelabra", + captain: "Reduces damage received from INT enemies by 10%" + }, + 205: { + captain: "Boosts HP and RCV of DEX characters by 1.2x" + }, + 206: { + special: "Reduces the defense of all enemies by 50% for 2 turns", + specialName: "Colors Trap: Calming Green", + captain: "Boosts HP and RCV of DEX characters by 1.2x" + }, + 207: { + captain: "Reduces damage received from PSY enemies by 10%" + }, + 208: { + special: "Changes [RCV] orbs into [PSY] orbs", + specialName: "Bombardier Arabesque", + captain: "Reduces damage received from PSY enemies by 20%" + }, + 209: { + special: "Boosts ATK of INT characters by 1.5x for 1 turn", + specialName: "Dieciseis Fleur", + captain: "Boosts RCV of INT characters by 1.5x" + }, + 210: { + special: "Boosts ATK of INT characters by 2x for 1 turn", + specialName: "Cien Fleur", + captain: "Boosts RCV of INT characters by 2x" + }, + 211: { + captain: "Boosts ATK of Striker characters by 1.2x" + }, + 212: { + special: "Deals 5x character's ATK in QCK damage to one enemy", + specialName: "Hot Blooded Bat", + captain: "Boosts ATK of Striker characters by 1.5x" + }, + 213: { + special: "Deals 20x character's ATK in STR damage to all enemies", + specialName: "Sorrowful Charge", + captain: "Protects from defeat as long as HP is above 50%", + captainNotes: "#{zombie}" + }, + 214: { + special: "Deals 20x character's ATK in STR damage to all enemies", + specialName: "Sorrowful Charge", + captain: "Protects from defeat as long as HP is above 50%", + captainNotes: "#{zombie}" + }, + 215: { + special: "Poisons all enemies", + specialNotes: "#{poison}", + specialName: "Poison Ink", + captain: "Boosts HP of Striker characters by 1.5x" + }, + 216: { + special: "Reduces damage received by 50% for 3 turns", + specialName: "Gum-Gum Balloon", + captain: "Reduces damage received by 20%" + }, + 217: { + special: "Deals 15x character's ATK in STR damage to all enemies", + specialName: "Gum-Gum Giant Rifle", + captain: "Boosts ATK by 3.5x after scoring 3 Perfects in a row" + }, + 218: { + special: "Reduces damage received from STR enemies by 100% for 1 turn", + specialName: "Streaming Wolf Swords", + captain: "Reduces damage received by 80% if HP is above 99% at the start of the turn" + }, + 219: { + special: "Deals 25x character's ATK in DEX damage to one enemy", + specialName: "Lion's Song", + captain: "Reduces damage received by 80% if HP is above 99% at the start of the turn" + }, + 220: { + special: "Changes [PSY] orbs into [INT] orbs", + specialName: "Fine Tempo", + captain: "Boosts ATK of INT characters by 2x" + }, + 221: { + special: "Changes [PSY] orbs into [INT] orbs", + specialName: "Happiness Punch", + captain: "Boosts ATK of INT characters by 2.5x", + limit: [ + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Aquire Potential 1: [INT] Damage Reduction" }, + { "description": "Boosts base RCV by 40" }, + { "description": "Aquire new Captain Ability: Boosts ATK of [INT] characters by 2.5x and their RCV by 1.2x" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK, HP and RCV of [INT] characters by 30" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Reduce base Special Cooldown by 2 turns" }, + { "description": "Aquire Sailor Ability 2: Makes [TND] orbs \"beneficial\" for [INT] characters" }, + { "description": "Boosts base HP by 60" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: [PSY] Damage Reduction" }, + ], + potential: [ + { + "Name": "[INT] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [INT] characters by 1%", + "Level 2: Reduce damage taken from [INT] characters by ?%", + "Level 3: Reduce damage taken from [INT] characters by ?%", + "Level 4: Reduce damage taken from [INT] characters by ?%", + "Level 5: Reduce damage taken from [INT] characters by ?%" + ] + }, + { + "Name": "[PSY] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [PSY] characters by 1%", + "Level 2: Reduce damage taken from [PSY] characters by ?%", + "Level 3: Reduce damage taken from [PSY] characters by ?%", + "Level 4: Reduce damage taken from [PSY] characters by ?%", + "Level 5: Reduce damage taken from [PSY] characters by ?%" + ] + }, + ] + }, + 222: { + special: "Boosts ATK of PSY characters by 1.5x for 1 turn", + specialName: "Usopp Hammer", + captain: "Boosts ATK of PSY characters by 1.2x" + }, + 223: { + special: "Boosts ATK of PSY characters by 2x for 1 turn", + specialName: "Impact", + captain: "Boosts ATK of PSY characters by 1.5x" + }, + 224: { + special: "Deals 15x character's ATK in QCK damage to one enemy", + specialName: "Mutton Shot", + captain: "Boosts ATK by 2x after scoring 2 Perfects in a row" + }, + 225: { + special: "Deals 20x character's ATK in QCK damage to one enemy", + specialName: "Veau Shot", + captain: "Boosts ATK by 2.5x after scoring 2 Perfects in a row" + }, + 226: { + special: "Cuts the current HP of each enemy by 30%", + specialName: "Black Blade Ship Cutter", + captain: "Boosts ATK of Slasher characters by 2x" + }, + 227: { + special: "Cuts the current HP of each enemy by 30%", + specialName: "Black Blade Ship Cutter", + captain: "Boosts ATK of Slasher characters by 2.5x", + limit: [ + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Aquire Sailor Ability 1: Makes [RCV] and [TND] orbs \"beneficial\" for this unit" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire new Captain Ability: Boosts ATK of Slasher characters by 2.5x and their HP by 1.3x" }, + { "description": "Aquire Potential 2: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 10% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 15% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 20% chance to deal 10% of this character's attack in extra damage" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 1 turn on this character", + "Level 2: Reduces Slot Bind duration by 2 turns on this character", + "Level 3: Reduces Slot Bind duration by 3 turns on this character", + "Level 4: Reduces Slot Bind duration by 4 turns on this character", + "Level 5: Reduces Slot Bind duration by 5 turns on this character" + ] + }, + ] + }, + 228: { + special: "Reduces Bind duration by 2 turns", + specialName: "Escapee Axe-Hand", + captain: "Boosts HP of Slasher characters by 1.5x" + }, + 229: { + special: "Changes [INT] orbs into [PSY] orbs", + specialName: "Double Cross Dance", + captain: "Reduces damage received by 10%" + }, + 230: { + special: "Deals 200 fixed damage to one enemy", + specialName: "Double Hyper Straight", + specialNotes: "#{fixed}", + captain: "Boosts ATK of STR characters by 1.5x" + }, + 231: { + special: "Locks all orbs for 1 turn", + specialName: "Kimono Sleeve Cage", + captain: "Boosts ATK of QCK characters by 2x" + }, + 232: { + special: "Locks all orbs for 1 turn", + specialName: "Kimono Sleeve Cage", + captain: "Boosts ATK of QCK characters by 2x" + }, + 233: { + captain: "Boosts HP of PSY characters by 1.5x" + }, + 234: { + special: "Deals 5x character's ATK in PSY damage to all enemies", + specialName: "Igarappapa", + captain: "Boosts HP of PSY characters by 2x" + }, + 235: { + captain: "Boosts ATK of Fighter characters by 1.2x" + }, + 236: { + special: "Deals 20x character's ATK in STR damage to one enemy", + specialName: "Superhuman Brass Knuckles", + captain: "Boosts ATK of Fighter characters by 1.5x" + }, + 237: { + special: "Changes [DEX] orbs into [STR] orbs", + specialName: "[DEX] Slot Change [STR]" + }, + 238: { + special: "Changes [TND] orbs into [DEX] orbs", + specialName: "[TND] Slot Change [DEX]" + }, + 239: { + special: "Changes [TND] orbs into [QCK] orbs", + specialName: "[TND] Slot Change [QCK]" + }, + 240: { + special: "Changes [STR] orbs into [PSY] orbs", + specialName: "[STR] Slot Change [PSY]" + }, + 241: { + special: "Changes [QCK] orbs into [INT] orbs", + specialName: "[QCK] Slot Change [INT]" + }, + 242: { + special: "Changes [DEX] orbs into [STR] orbs", + specialName: "[DEX] Slot Change [STR]" + }, + 243: { + special: "Changes [TND] orbs into [DEX] orbs", + specialName: "[TND] Slot Change [DEX]" + }, + 244: { + special: "Changes [TND] orbs into [QCK] orbs", + specialName: "[TND] Slot Change [QCK]" + }, + 245: { + special: "Changes [STR] orbs into [PSY] orbs", + specialName: "[STR] Slot Change [PSY]" + }, + 246: { + special: "Changes [QCK] orbs into [INT] orbs", + specialName: "[QCK] Slot Change [INT]" + }, + 247: { + special: "Recovers 1,224 HP", + specialName: "Kyuun Spark", + captain: "Reduces damage received by 10%" + }, + 248: { + special: "Deals random STR damage to one enemy", + specialName: "Rampage", + specialNotes: "#{random : 2,000 : 200,000}", + captain: "Boosts ATK of STR characters by 2.5x and reduces their HP by 60%" + }, + 249: { + special: "Deals random STR damage to one enemy", + specialName: "Rampage", + specialNotes: "#{random : 2,000 : 200,000}", + captain: "Boosts ATK of STR characters by 3x and reduces their HP by 60%", + limit: "This character has a limit break path", + }, + 250: { + special: "Recovers all missing HP", + specialName: "Blue Flame Rebirth", + captain: "Boosts ATK of PSY characters by 3x if HP is above 99% at the start of the turn" + }, + 251: { + special: "Recovers all missing HP", + specialName: "Blue Flame Rebirth", + captain: "Boosts ATK of PSY characters by 3x if HP is above 99% at the start of the turn", + limit: "This character has a limit break path", + }, + 252: { + special: "Reduces damage received from DEX enemies by 100% for 1 turn", + specialName: "Brilliant Punk", + captain: "Boosts ATK and HP of QCK characters by 2x" + }, + 253: { + special: "Reduces damage received from DEX enemies by 100% for 1 turn", + specialName: "Brilliant Punk", + captain: "Boosts ATK and HP of QCK characters by 2x", + limit: "This character has a limit break path", + }, + 254: { + special: "Deals 5,000 fixed damage to all enemies", + specialName: "Rose Rondo", + specialNotes: "#{fixed}", + captain: "Boosts ATK and HP of INT characters by 2x" + }, + 255: { + special: "Deals 5,000 fixed damage to all enemies", + specialName: "Rose Rondo", + specialNotes: "#{fixed}", + captain: "Boosts ATK and HP of INT characters by 2x" + }, + 256: { + special: "Changes [STR] and [QCK] orbs into [DEX] orbs", + specialName: "Beautiful Dual Flintlocks", + captain: "Boosts ATK and RCV of DEX characters by 2x" + }, + 257: { + special: "Changes [STR] and [QCK] orbs into [DEX] orbs", + specialName: "Beautiful Dual Flintlocks", + captain: "Boosts ATK and RCV of DEX characters by 2x", + limit: [ + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base HP by 90" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Reduce base Special Cooldown by 2 turns" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base RCV by 40" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK, HP and RCV of [DEX] characters by 50" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Boosts base HP by 150" }, + { "description": "Aquire new Captain Ability: Boosts ATK and RCV of DEX characters by 2x and boosts ATK of Shooter characters by 1.2x" }, + { "description": "Reduce base Special Cooldown by 2 turns" }, + { "description": "Boosts base ATK by 60" }, + { "description": "Aquire Sailor Ability 2: Boosts base ATK of Shooter characters by 50" }, + { "description": "Aquire Potential 2: Reduce No Healing duration" }, + ], + limitnotes: "Captain boosts stack, so [DEX] and Shooter character's ATK will be boosted by 2.4x", + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 10% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 15% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 20% chance to deal 10% of this character's attack in extra damage" + ] + }, + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: Reduces No Healing duration by 1 turn", + "Level 2: Reduces No Healing duration by 1 turn", + "Level 3: Reduces No Healing duration by 1 turn", + "Level 4: Reduces No Healing duration by 2 turns", + "Level 5: Reduces No Healing duration by 3 turns" + ] + }, + ] + }, + 258: { + special: "Changes [DEX] and [QCK] orbs into [STR] orbs", + specialName: "Pocket Mallet", + captain: "Boosts ATK and RCV of STR characters by 2x" + }, + 259: { + special: "Changes [DEX] and [QCK] orbs into [STR] orbs", + specialName: "Pocket Mallet", + captain: "Boosts ATK and RCV of STR characters by 2x", + limit: [ + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base HP by 50" }, + { "description": "Aquire Potential 1: [QCK] Damage Reduction" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Aquire Sailor Ability 1: Makes [PSY] orbs \"beneficial\" for this unit" }, + { "description": "Reduce base Special Cooldown by 2 turns" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Aquire Sailor Ability 2: Makes [INT] orbs \"beneficial\" for this unit" }, + { "description": "Boosts base ATK by 60" }, + { "description": "Boosts base HP by 30" }, + { "description": "Reduce base Special Cooldown by 2 turns" }, + { "description": "Boosts base HP by 80" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: [DEX] Damage Reduction" }, + ], + potential: [ + { + "Name": "[QCK] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [QCK] characters by ?%", + "Level 2: Reduce damage taken from [QCK] characters by ?%", + "Level 3: Reduce damage taken from [QCK] characters by ?%", + "Level 4: Reduce damage taken from [QCK] characters by ?%", + "Level 5: Reduce damage taken from [QCK] characters by ?%" + ] + }, + { + "Name": "[DEX] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [DEX] characters by ?%", + "Level 2: Reduce damage taken from [DEX] characters by ?%", + "Level 3: Reduce damage taken from [DEX] characters by ?%", + "Level 4: Reduce damage taken from [DEX] characters by ?%", + "Level 5: Reduce damage taken from [DEX] characters by ?%" + ] + }, + ] + }, + 260: { + special: "Cuts the current HP of each enemy by 30%", + specialName: "Seaquake", + captain: "Boosts ATK of all characters by 3x if HP is below 30% at the start of the turn" + }, + 261: { + special: "Cuts the current HP of each enemy by 30%", + specialName: "Seaquake", + captain: "Boosts ATK of all characters by 3x if HP is below 30% at the start of the turn", + limit: [ + { "description": "Boosts base ATK by 5" }, + { "description": "Boosts base HP by 5" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Aquire Potential 1: [DEX] Damage Reduction" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK of Striker and Powerhouse characters by 60" }, + { "description": "Boosts base ATK by 10" }, + { "description": "Boosts base HP by 15" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 35" }, + { "description": "Boosts base HP by 40" }, + { "description": "Aquire Potential 2: Critical Hit" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 45" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base HP by 65" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base HP by 70" }, + { "description": "Boosts base HP by 80" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base RCV by 40" }, + { "description": "Aquire Sailor Ability 2: Completely resists Paralysis on this character" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Aquire Potential 3: Enrage" }, + ], + potential: [ + { + "Name": "[DEX] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [DEX] characters by 2%", + "Level 2: Reduce damage taken from [DEX] characters by 3%", + "Level 3: Reduce damage taken from [DEX] characters by 4%", + "Level 4: Reduce damage taken from [DEX] characters by 5%", + "Level 5: Reduce damage taken from [DEX] characters by 7%" + ] + }, + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 20% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage" + ] + }, + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 25", + "Level 2: Boosts base ATK by ??", + "Level 3: Boosts base ATK by ??", + "Level 4: Boosts base ATK by ??", + "Level 5: Boosts base ATK by ??" + ] + }, + ] + }, + 262: { + captain: "Recovers 2x character's RCV in HP at the end of each turn" + }, + 263: { + special: "Amplifies the effect of orbs by 1.5x for 2 turns", + specialNotes: "#{orb : 1.5x}", + specialName: "Shave", + captain: "Boosts ATK of Fighter characters by 2x" + }, + 264: { + captain: "Reduces damage received from INT enemies by 30%" + }, + 265: { + special: "Reduces Bind duration by 3 turns", + specialName: "Tempered Kukris", + captain: "Boosts ATK and HP of Slasher characters by 1.5x" + }, + 267: { + special: "Reduces the defense of all enemies by 50% for 1 turn", + specialName: "Shield Crusher", + captain: "Boosts ATK of all characters by 1.5x" + }, + 268: { + special: "Reduces damage received by 50% for 3 turns", + specialName: "White Out", + captain: "Reduces damage received by 25%" + }, + 269: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Straight" + }, + 270: { + special: "Reduces damage received by 20% for 1 turn", + specialName: "Iron Shield" + }, + 271: { + special: "Changes [STR] orbs into [DEX] orbs", + specialName: "[STR] Slot Change [DEX]" + }, + 272: { + special: "Reduces damage received by 20% for 1 turn", + specialName: "Iron Shield" + }, + 273: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Straight" + }, + 274: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Slash" + }, + 275: { + special: "Reduces the defense of all enemies by 50% for 1 turn", + specialName: "Shield Crusher" + }, + 276: { + special: "Changes [QCK] orbs into [DEX] orbs", + specialName: "[QCK] Slot Change [DEX]" + }, + 277: { + special: "Changes [INT] orbs into [PSY] orbs", + specialName: "[INT] Slot Change [PSY]" + }, + 278: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Slash" + }, + 279: { + special: "Changes [RCV] orbs into [STR] orbs", + specialName: "[RCV] Slot Change [STR]" + }, + 280: { + special: "Changes [DEX] orbs into [QCK] orbs", + specialName: "[DEX] Slot Change [QCK]" + }, + 281: { + special: "Changes [QCK] orbs into [DEX] orbs", + specialName: "[QCK] Slot Change [DEX]" + }, + 282: { + special: "Changes [QCK] orbs into [RCV] orbs", + specialName: "[QCK] Slot Change [RCV]" + }, + 283: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Spiral" + }, + 284: { + special: "Deals 5x character's ATK in character's type damage to all enemies", + specialName: "Hyper Shot" + }, + 285: { + special: "Reduces the defense of all enemies by 50% for 1 turn", + specialName: "Shield Crusher" + }, + 286: { + special: "Changes [DEX] orbs into [RCV] orbs", + specialName: "[DEX] Slot Change [RCV]" + }, + 287: { + special: "Changes [PSY] orbs into [RCV] orbs", + specialName: "[PSY] Slot Change [RCV]" + }, + 288: { + special: "Deals 5x character's ATK in character's type damage to all enemies", + specialName: "Hyper Shot" + }, + 289: { + special: "Reduces damage received by 20% for 1 turn", + specialName: "Iron Shield" + }, + 290: { + special: "Deals 25x character's ATK in INT damage to one enemy", + specialName: "Judgment Bomb", + captain: "Boosts ATK of Shooter characters by 1.5x" + }, + 291: { + special: "Changes adjacent orbs into [RCV] orbs", + specialName: "[RCV] Slot Storm", + captain: "Reduces damage received from INT enemies by 50%" + }, + 292: { + special: "Changes adjacent orbs into [RCV] orbs", + specialName: "[RCV] Slot Storm", + captain: "Reduces damage received from PSY enemies by 50%" + }, + 293: { + special: "Reduces damage received by 20% for 1 turn", + specialName: "Iron Shield", + captain: "Boosts HP of QCK characters by 2x" + }, + 294: { + special: "Deals 10x character's ATK in character's type damage to one enemy", + specialName: "Hyper Straight", + captain: "Boosts HP of STR characters by 2x" + }, + 295: { + special: "Reduces the defense of all enemies by 50% for 1 turn", + specialName: "Shield Crusher", + captain: "Boosts HP of DEX characters by 2x" + }, + 296: { + special: "Recovers 2,000 HP, randomizes all orbs", + specialName: "Cleansing Wash", + captain: "Boosts ATK of Shooter characters by 2x" + }, + 297: { + special: "Recovers 2,000 HP, randomizes all orbs", + specialName: "Cleansing Wash", + captain: "Boosts ATK of Shooter characters by 2x" + }, + 298: { + special: "Deals 25x character's ATK in PSY damage to one enemy", + specialName: "Moonwalk", + captain: "Boosts HP of PSY characters by 2x" + }, + 299: { + special: "Cuts the current HP of each enemy by 10%", + specialName: "8-Sword Style Onigumo", + captain: "Boosts ATK of DEX characters by 2x" + }, + 305: { + special: "Randomly changes all orbs into either [PSY] or [RCV] orbs", + specialName: "Meteor Fist Shower", + captain: "Boosts ATK and HP of PSY characters by 1.5x" + }, + 306: { + special: "Randomly changes all orbs into either [PSY] or [RCV] orbs", + specialName: "Meteor Fist Shower", + captain: "Boosts ATK and HP of PSY characters by 2x", + limit: "This character has a limit break path", + }, + 307: { + special: "Randomly changes all orbs other than [DEX] into either [DEX], [RCV] or [TND] orbs", + specialName: "ROOM – Chambres", + captain: "Boosts ATK of DEX characters by 2.5x" + }, + 308: { + special: "Randomly changes all orbs other than [DEX] into either [DEX], [RCV] or [TND] orbs", + specialName: "ROOM – Chambres", + captain: "Boosts ATK of DEX characters by 2.5x" + }, + 309: { + special: "Cuts the current HP of each enemy by 10%, reduces the defense of all enemies by 50% for 3 turns", + specialName: "Demon Face", + captain: "Reduces RCV of all characters by 90%, reduces damage received by 40%" + }, + 310: { + special: "Cuts the current HP of each enemy by 10%, reduces the defense of all enemies by 50% for 3 turns", + specialName: "Demon Face", + captain: "Reduces RCV of all characters by 90%, reduces damage received by 40%", + limit: "This character has a limit break path", + }, + 311: { + special: "Deals 100x character's ATK in fixed damage to one enemy, reduces crew's HP to 1", + specialName: "Massacre Soldier", + specialNotes: "#{fixed}", + captain: "Boosts ATK by 3.5x after scoring 3 hits below Good in a row", + sailor: "When HP is below 30% at the start of the turn, boosts ATK of Cerebral characters by 50" + }, + 312: { + special: "Deals 100x character's ATK in fixed damage to one enemy, reduces crew's HP to 1", + specialName: "Massacre Soldier", + specialNotes: "#{fixed}", + captain: "Boosts ATK by 3.5x after scoring 3 hits below Good in a row", + sailor: "When HP is below 30% at the start of the turn, boosts ATK of Cerebral characters by 50" + }, + 313: { + special: "Boosts ATK of Striker characters by 1.5x for 1 turn, deals 25x character's ATK in PSY damage to one enemy", + specialName: "Karmic Punishment", + captain: "Boosts ATK of Striker characters by 2x and their HP by 1.5x" + }, + 314: { + special: "Boosts ATK of Striker characters by 1.5x for 1 turn, deals 25x character's ATK in PSY damage to one enemy", + specialName: "Karmic Punishment", + captain: "Boosts ATK of Striker characters by 2x and their HP by 1.5x", + limit: [ + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base RCV by 25" }, + { "description": "Aquire Potential 1: [INT] Damage Reduction" }, + { "description": "Reduce base Special Cooldown by 3 turns" }, + { "description": "Aquire new Captain Ability: Boosts ATK of all Striker characters proportionally to the crew's current HP and their HP by 1.5x" }, + { "description": "Reduce base Special Cooldown by 3 turns" }, + { "description": "Boosts base HP by 70" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK, HP and RCV of Striker characters by 30" }, + { "description": "Boosts base ATK by 60" }, + { "description": "Boosts base RCV by 25" }, + { "description": "Reduce base Special Cooldown by 3 turns" }, + { "description": "Boosts base HP by 80" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Enrage" }, + ], + potential: [ + { + "Name": "[INT] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [INT] characters by 1%", + "Level 2: Reduce damage taken from [INT] characters by ?%", + "Level 3: Reduce damage taken from [INT] characters by ?%", + "Level 4: Reduce damage taken from [INT] characters by ?%", + "Level 5: Reduce damage taken from [INT] characters by ?%" + ] + }, + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 30", + "Level 2: Boosts base ATK by ??", + "Level 3: Boosts base ATK by ??", + "Level 4: Boosts base ATK by ??", + "Level 5: Boosts base ATK by ??" + ] + }, + ] + }, + 315: { + special: "Changes [PSY] and [INT] orbs into [STR] orbs, empties slots with [DEX] and [QCK] orbs", + specialName: "Aye Aye, Captain!", + captain: "Boosts ATK, HP and RCV of Fighter characters by 1.5x", + sailor: "Reduces Paralysis for 2 turns for himself" + }, + 316: { + special: "Changes [PSY] and [INT] orbs into [STR] orbs, empties slots with [DEX] and [QCK] orbs", + specialName: "Aye Aye, Captain!", + captain: "Boosts ATK, HP and RCV of Fighter characters by 1.5x", + sailor: "Reduces Paralysis for 2 turns for himself", + limit: "This character has a limit break path", + }, + 317: { + special: "Randomly changes all orbs into either [DEX] or [STR] orbs, deals random DEX damage to all enemies", + specialName: "Beautiful Secretary's Job", + specialNotes: "#{random : 1 : 15,000}", + captain: "Recovers 500 HP at end of each turn, reduces damage received by 10%" + }, + 318: { + special: "Randomly changes all orbs into either [DEX] or [STR] orbs, deals random DEX damage to all enemies", + specialName: "Beautiful Secretary's Job", + specialNotes: "#{random : 1 : 15,000}", + captain: "Recovers 1,000 HP at end of each turn, reduces damage received by 15%" + }, + 319: { + special: "Locks all orbs for 1 turn", + specialName: "Hook, Line, and Sinker", + captain: "Boosts ATK of Striker characters by 1.5x" + }, + 320: { + special: "Locks all orbs for 1 turn", + specialName: "Hook, Line, and Sinker", + captain: "Boosts ATK of Striker characters by 2x" + }, + 321: { + special: "Deals 25x character's ATK in QCK damage to one enemy", + specialName: "Taciturn Combo", + captain: "Boosts ATK of QCK type characters by 2x" + }, + 322: { + special: "Deals 25x character's ATK in QCK damage to one enemy", + specialName: "Taciturn Combo", + captain: "Boosts ATK of QCK type characters by 2x" + }, + 323: { + special: "Amplifies the effect of orbs by 1.5x for 2 turns", + specialNotes: "#{orb : 1.5x}", + specialName: "Mountain Wind", + captain: "Boosts HP and RCV of QCK characters by 1.5x" + }, + 324: { + special: "Amplifies the effect of orbs by 1.5x for 2 turns", + specialNotes: "#{orb : 1.5x}", + specialName: "Mountain Wind", + captain: "Boosts HP and RCV of QCK characters by 1.5x" + }, + 325: { + special: "Changes [TND] orbs into [RCV] orbs, changes [RCV] orbs into [QCK] orbs", + specialName: "Red-Hot Shipwright Soul" + }, + 326: { + special: "Empties all slots, deals 25x character's ATK in STR damage to one enemy", + specialName: "Munch-Munch Tongue Cannon", + captain: "Recovers 10x character's RCV in HP at the end of each turn" + }, + 327: { + special: "Empties all slots, deals 25x character's ATK in STR damage to one enemy", + specialName: "Munch-Munch Tongue Cannon", + captain: "Recovers 10x character's RCV in HP at the end of each turn" + }, + 328: { + special: "Deals 20x character's ATK in QCK damage to all enemies", + specialName: "Fiddle Banff", + captain: "Boosts RCV of all characters by 5x if HP is below 30% at the start of the turn" + }, + 329: { + special: "Deals 20x character's ATK in QCK damage to all enemies", + specialName: "Fiddle Banff", + captain: "Boosts RCV of all characters by 5x if HP is below 30% at the start of the turn" + }, + 332: { + special: "Changes [STR] orbs into [RCV] orbs, changes [RCV] orbs into [DEX] orbs", + specialName: "Snow-Slicing Blade", + captain: "Boosts ATK, HP and RCV of Striker characters by 1.2x" + }, + 333: { + special: "Recovers a random amount of HP", + specialName: "Doctor Stop", + specialNotes: "#{randomHeal : 2,000 : 5,000}", + captain: "Boosts ATK and RCV of PSY and INT characters by 1.5x" + }, + 334: { + special: "Recovers 5x character's RCV in HP", + specialName: "Light Healing" + }, + 335: { + special: "Recovers 5x character's RCV in HP", + specialName: "Light Healing" + }, + 336: { + special: "Switches orbs between slots twice", + specialName: "Franky Centaur", + captain: "Reduces damage received by 10% if HP is above 50% at the start of the turn, boosts ATK of PSY characters by 2x and reduces ATK of every other character by 20% if HP is above 50% at the start of the turn" + }, + 337: { + special: "Switches orbs between slots twice", + specialName: "Franky Centaur", + captain: "Reduces damage received by 10% if HP is above 50% at the start of the turn, boosts ATK of PSY characters by 2.5x and reduces ATK of every other character by 20% if HP is above 50% at the start of the turn" + }, + 338: { + special: "Changes [QCK] orbs into [PSY] orbs", + specialName: "Wavy Square Hair" + }, + 339: { + special: "Changes [INT] orbs into [TND] orbs", + specialName: "Straight Square Hair" + }, + 340: { + special: "Randomly changes all orbs into either [STR] or [QCK] orbs, deals random STR damage to all enemies", + specialName: "Kraken Tentacle Crush", + specialNotes: "#{random : 1 : 15,000}", + captain: "Boosts ATK of Striker characters by 2x" + }, + 341: { + special: "Randomly changes all orbs into either [STR] or [QCK] orbs, deals random STR damage to all enemies", + specialName: "Kraken Tentacle Crush", + specialNotes: "#{random : 1 : 15,000}", + captain: "Boosts ATK of Striker characters by 2x" + }, + 352: { + special: "Boosts ATK of Shooter characters by 1.75x for 2 turns", + specialName: "Smash Buster", + captain: "Boosts ATK of Shooter characters by 2x" + }, + 353: { + special: "Boosts ATK of Shooter characters by 1.75x for 2 turns", + specialName: "Smash Buster", + captain: "Boosts ATK of Shooter characters by 2.5x", + limit: [ + { "description": "Boosts base ATK by 10" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Aquire Potential 1: Enrage" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK, HP and RCV of Shooter characters by 20" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base RCV by 40" }, + { "description": "Aquire new Captain Ability: Boosts ATK of Shooter characters by 2.5x and their HP by 1.2x and recovers 300 HP at end of each turn" }, + { "description": "Boosts base HP by 50" }, + { "description": "Aquire Potential 2: Barrier Penetration" }, + ], + potential: [ + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 20", + "Level 2: Boosts base ATK by 30", + "Level 3: Boosts base ATK by 40", + "Level 4: Boosts base ATK by 50", + "Level 5: Boosts base ATK by 100" + ] + }, + { + "Name": "Barrier Penetration", + "description": [ + "Level 1: This character's attack will ignore barriers if HP is above 99%", + "Level 2: This character's attack will ignore barriers if HP is above 99%", + "Level 3: This character's attack will ignore barriers if HP is above 99%", + "Level 4: This character's attack will ignore barriers if HP is above 80%", + "Level 5: This character's attack will ignore barriers if HP is above 50%" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 354: { + special: "Reduces Bind and Despair duration by 3 turns", + specialName: "Two-Sword Dance" + }, + 355: { + special: "Reduces Bind and Despair duration by 3 turns", + specialName: "Two-Sword Dance" + }, + 356: { + special: "Changes own orb into [STR], deals 9x character's ATK in STR damage to all enemies", + specialName: "Steel Magnetic Arm", + captain: "Boosts ATK of Striker characters by 2x" + }, + 357: { + special: "Changes own orb into [STR], deals 9x character's ATK in STR damage to all enemies", + specialName: "Steel Magnetic Arm", + captain: "Boosts ATK of Striker characters by 2.5x", + limit: [ + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Aquire Potential 1: [DEX] Damage Reduction" }, + { "description": "Boosts base HP by 40" }, + { "description": "Aquire new Captain Ability: Boosts ATK of Striker characters by 2.5x and reduces damage received by 7%" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK of Striker characters by 75" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base RCV by 50" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Enrage" }, + ], + potential: [ + { + "Name": "[DEX] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [DEX] characters by ?%", + "Level 2: Reduce damage taken from [DEX] characters by ?%", + "Level 3: Reduce damage taken from [DEX] characters by ?%", + "Level 4: Reduce damage taken from [DEX] characters by ?%", + "Level 5: Reduce damage taken from [DEX] characters by ?%" + ] + }, + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 30", + "Level 2: Boosts base ATK by ??", + "Level 3: Boosts base ATK by ??", + "Level 4: Boosts base ATK by ??", + "Level 5: Boosts base ATK by ??" + ] + }, + ] + }, + 358: { + special: "Changes [TND] and [RCV] orbs into [DEX] orbs, deals random DEX damage to all enemies", + specialName: "Scratch Body", + captain: "Boosts ATK of DEX characters by 2.5x if HP is above 99% at the start of the turn", + specialNotes: "#{random : 5,000 : 20,000}" + }, + 359: { + special: "Changes [TND] and [RCV] orbs into [DEX] orbs, deals random DEX damage to all enemies", + specialName: "Scratch Body", + specialNotes: "#{random : 5,000 : 20,000}", + captain: "Boosts ATK of DEX characters by 3x if HP is above 99% at the start of the turn", + limit: [ + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Aquire Potential 1: Pinch Healing" }, + { "description": "Boosts base HP by 80" }, + { "description": "Boosts base RCV by 40" }, + { "description": "Boosts base ATK by 100" }, + { "description": "Reduce base Special Cooldown by 2 turns" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK, HP and RCV of [DEX] characters by 30" }, + { "description": "Boosts base HP by 150" }, + { "description": "Aquire Sailor Ability 2: Boosts base ATK of Shooter characters by 50" }, + { "description": "Reduce base Special Cooldown by 2 turns" }, + { "description": "Aquire new Captain Ability: Boosts ATK of [DEX] characters by 3x if HP is above 99% at the start of the turn, 2x otherwise" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Barrier Penetration" }, + ], + potential: [ + { + "Name": "Pinch Healing", + "description": [ + "Level 1: If HP is below 10% at the start of the turn, heals for .5x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 2: If HP is below 15% at the start of the turn, heals for .5x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 3: If HP is below 20% at the start of the turn, heals for .5x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 4: If HP is below 30% at the start of the turn, heals for 1x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 5: If HP is below 50% at the start of the turn, heals for 1x this character's RCV at the end of the turn each time you hit a Perfect" + ] + }, + { + "Name": "Barrier Penetration", + "description": [ + "Level 1: This character's attack will ignore barriers if HP is above 99%", + "Level 2: This character's attack will ignore barriers if HP is above 99%", + "Level 3: This character's attack will ignore barriers if HP is above 99%", + "Level 4: This character's attack will ignore barriers if HP is above 80%", + "Level 5: This character's attack will ignore barriers if HP is above 50%" + ] + }, + ] + }, + 360: { + special: "Deals 10x character's ATK in INT damage to all enemies, protects from defeat as long as HP is above 50% for 1 turn", + specialName: "Prehistoric Power", + specialNotes: "#{zombie}", + captain: "Boosts ATK of INT characters by 3x if HP is below 30% at the start of the turn", + sailor: "Boosts base HP of Powerhouse characters by 100" + }, + 361: { + special: "Deals 10x character's ATK in INT damage to all enemies, protects from defeat as long as HP is above 50% for 1 turn", + specialName: "Prehistoric Power", + specialNotes: "#{zombie}", + captain: "Boosts ATK of INT characters by 3x if HP is below 30% at the start of the turn", + sailor: "Boosts base HP of Powerhouse characters by 100" + }, + 362: { + special: "For 2 turns, boosts the amount healed by RCV orbs by 1.5x, then 2x, then 2.5x from the third crew member onward", + specialName: "Big Eater", + captain: "Boosts ATK and RCV of PSY characters by 2x" + }, + 363: { + special: "For 2 turns, boosts the amount healed by RCV orbs by 1.5x, then 2x, then 2.5x from the third crew member onward", + specialName: "Big Eater", + captain: "Boosts ATK and RCV of PSY characters by 2x" + }, + 364: { + special: "Changes [STR] and [DEX] orbs into [QCK] orbs", + specialName: "Gang Fortress", + captain: "Boosts ATK and RCV of QCK characters by 2x", + sailor: "Boosts base RCV of all characters by 10" + }, + 365: { + special: "Changes [STR] and [DEX] orbs into [QCK] orbs", + specialName: "Gang Fortress", + captain: "Boosts ATK and RCV of QCK characters by 2x", + sailor: "Boosts base RCV of all characters by 10" + }, + 366: { + special: "Deals 20x character's ATK in INT damage to all enemies, reduces Bind duration by 5 turns", + specialName: "Dark King's Aura", + captain: "Boosts chain multiplier by 4x" + }, + 367: { + special: "Deals 20x character's ATK in INT damage to all enemies, reduces Bind duration by 5 turns", + specialName: "Dark King's Aura", + captain: "Boosts chain multiplier by 4x" + }, + 368: { + special: "Reduces damage received from DEX enemies by 50% for 1 turn", + specialName: "Crystal Shield DEX" + }, + 369: { + special: "Reduces damage received from STR enemies by 50% for 1 turn", + specialName: "Crystal Shield STR" + }, + 370: { + special: "Reduces damage received from QCK enemies by 50% for 1 turn", + specialName: "Crystal Shield QCK" + }, + 371: { + special: "Reduces damage received from INT enemies by 50% for 1 turn", + specialName: "Crystal Shield INT" + }, + 372: { + special: "Reduces damage received from PSY enemies by 50% for 1 turn", + specialName: "Crystal Shield PSY" + }, + 373: { + special: "Reduces damage received from DEX enemies by 50% for 1 turn", + specialName: "Crystal Shield DEX", + captain: "Boosts ATK of Slasher characters by 1.5x" + }, + 374: { + special: "Reduces damage received from STR enemies by 50% for 1 turn", + specialName: "Crystal Shield STR", + captain: "Boosts ATK of Shooter characters by 1.5x" + }, + 375: { + special: "Reduces damage received from QCK enemies by 50% for 1 turn", + specialName: "Crystal Shield QCK", + captain: "Boosts HP of Striker characters by 1.5x" + }, + 376: { + special: "Reduces damage received from INT enemies by 50% for 1 turn", + specialName: "Crystal Shield INT", + captain: "Boosts ATK of Fighter characters by 1.5x" + }, + 377: { + special: "Reduces damage received from PSY enemies by 50% for 1 turn", + specialName: "Crystal Shield PSY", + captain: "Boosts ATK of Striker characters by 1.5x" + }, + 378: { + special: "Recovers 3x character's RCV in HP", + specialName: "Quick Healing", + captain: "Boosts RCV of all characters by 1.5x" + }, + 379: { + special: "Removes Poison", + specialName: "Dugong Kung Fu Fist of Healing" + }, + 380: { + special: "Removes Poison", + specialName: "Dugong Kung Fu Fist of Healing", + captain: "Boosts ATK and RCV of STR characters by 1.5x" + }, + 381: { + special: "Reduces damage received by 20% for 1 turn", + specialName: "Iron Shield" + }, + 382: { + special: "Reduces the defense of all enemies by 50% for 1 turn", + specialName: "Shield Crusher" + }, + 383: { + special: "Strongly Poisons one enemy", + specialNotes: "Strong Poison deals 5x character's ATK in fixed damage at the end of each turn", + specialName: "Poison Needle", + captain: "Reduces damage received by 10%, boosts ATK of INT characters by 2x" + }, + 384: { + special: "Strongly Poisons one enemy", + specialNotes: "Strong Poison deals 5x character's ATK in fixed damage at the end of each turn", + specialName: "Poison Needle", + captain: "Reduces damage received by 20%, boosts ATK of INT characters by 2x" + }, + 385: { + special: "Reduces damage received by 50% for 1 turn, boosts ATK of Fighter characters by 1.25x for 1 turn", + specialName: "Zombie Marionette Operation", + captain: "Boosts ATK of INT characters by 2x" + }, + 386: { + special: "Reduces damage received by 50% for 1 turn, boosts ATK of Fighter characters by 1.25x for 1 turn", + specialName: "Zombie Marionette Operation", + captain: "Boosts ATK of INT characters by 2x" + }, + 387: { + special: "Randomly changes all orbs into either [PSY] or [INT] orbs, deals random PSY damage to all enemies", + specialName: "Square Plate Sword", + specialNotes: "#{random : 1 : 10,000}", + captain: "Boosts RCV of PSY characters by 1.5x" + }, + 388: { + special: "Randomly changes all orbs into either [PSY] or [INT] orbs, deals random PSY damage to all enemies", + specialName: "Square Plate Sword", + specialNotes: "#{random : 1 : 10,000}", + captain: "Boosts RCV of PSY characters by 1.5x" + }, + 389: { + special: "Randomly changes all orbs into either [RCV], [STR], [DEX] or [QCK] orbs and changes own orb into [QCK]", + specialName: "Hell Wink", + captain: "Boosts ATK by 2.25x following a chain of DEX > INT > QCK attacks no lower than Good" + }, + 390: { + special: "Randomly changes all orbs into either [RCV], [STR], [DEX] or [QCK] orbs and changes own orb into [QCK]", + specialName: "Hell Wink", + captain: "Boosts ATK by 2.75x following a chain of DEX > INT > QCK attacks no lower than Good" + }, + 391: { + special: "Reduces damage received by 90% for 1 turn, reduces the defense of all enemies by 80% for 1 turn, Poisons enemies for 1,000 damage for a single turn", + specialName: "Negative Hollow", + specialNotes: "Poison damage deals 1,000 damage exactly and will ignore enemy armor at the end of your turn", + captain: "Boosts RCV of DEX characters by 1.5x" + }, + 392: { + special: "Reduces damage received by 90% for 1 turn, reduces the defense of all enemies by 80% for 1 turn, Poisons enemies for 1,000 damage for a single turn", + specialName: "Negative Hollow", + specialNotes: "Poison damage deals 1,000 damage exactly and will ignore enemy armor at the end of your turn", + captain: "Boosts RCV of DEX characters by 2x" + }, + 393: { + special: "Deals 35x character's ATK in STR damage to one enemy", + specialName: "Kumacy Knuckle" + }, + 394: { + special: "Deals 500 fixed damage to all enemies", + specialName: "The Tempest Called Love", + specialNotes: "#{fixed}" + }, + 395: { + special: "Empties adjacent slots, amplifies the effect of orbs by 1.25x for 1 turn", + specialNotes: "#{orb : 1.25x}", + specialName: "Mole Banana", + captain: "Boosts ATK and RCV of QCK characters by 1.2x" + }, + 396: { + special: "Empties adjacent slots, amplifies the effect of orbs by 1.25x for 1 turn", + specialNotes: "#{orb : 1.25x}", + specialName: "Mole Banana", + captain: "Boosts ATK and RCV of QCK characters by 1.2x" + }, + 397: { + special: "Changes [EMPTY] orbs into [STR] orbs with a 50% probability, deals 15x character's ATK in damage to all enemies", + specialName: "Four Hundred Base Hits", + captain: "Boosts ATK by 3x after scoring 5 Perfects in a row" + }, + 398: { + special: "Changes [EMPTY] orbs into [STR] orbs with a 50% probability, deals 15x character's ATK in damage to all enemies", + specialName: "Four Hundred Base Hits", + captain: "Boosts ATK by 4x after scoring 5 Perfects in a row" + }, + 399: { + special: "Boosts ATK of DEX characters by 1.5x for 1 turn", + specialName: "Spike-U-Puncture", + captain: "Boosts HP of Striker characters by 1.5x" + }, + 400: { + special: "Boosts ATK of DEX characters by 1.5x for 1 turn", + specialName: "Spike-U-Puncture", + captain: "Boosts HP of Striker characters by 2x" + }, + 401: { + special: "Reduces damage received by 50% for 1 turn, boosts ATK of Slasher characters by 1.25x for 1 turn", + specialName: "Iron Guard", + captain: "Reduces damage received by 10%, boosts ATK of Slasher characters by 1.5x" + }, + 402: { + special: "Reduces damage received by 50% for 1 turn, boosts ATK of Slasher characters by 1.25x for 1 turn", + specialName: "Iron Guard", + captain: "Reduces damage received by 10%, boosts ATK of Slasher characters by 2x" + }, + 403: { + special: "Deals several times the character's ATK in QCK damage to all enemies", + specialNotes: "#{specialProportional : lower : 150 * ( 1 - (remaining HP) / (total HP) )}", + specialName: "Backwater Sword Dance", + captain: "Reduces damage received by 50% if HP is low, boosts RCV of all characters by 3x if HP is low" + }, + 404: { + special: "Reduces damage received by 50% for 2 turns, boosts RCV of all characters by 2x for 2 turns", + specialName: "Clear-Clear Fruit", + captain: "Boosts ATK of Shooter characters by 1.5x" + }, + 405: { + special: "Reduces damage received by 50% for 2 turns, boosts RCV of all characters by 2x for 2 turns", + specialName: "Clear-Clear Fruit", + captain: "Boosts ATK of Shooter characters by 2x" + }, + 406: { + special: "Reduces crew's HP to 1, deals 1,000 fixed damage to all enemies, boosts ATK of all characters by 1.2x for 1 turn", + specialName: "Skills of the Ancient Warriors", + specialNotes: "#{fixed}" + }, + 407: { + special: "Randomizes all orbs, deals 7x character's ATK in [DEX] damage to all enemies", + specialName: "Zombie-Style 36-Pound Phoenix" + }, + 408: { + special: "Randomizes all orbs and changes own orb into [INT], deals 15x character's ATK in [INT] damage to all enemies", + specialName: "Ground Death", + captain: "Reduces damage received by 20%, boosts ATK of Slasher characters by 2x" + }, + 409: { + special: "Changes own orb into [QCK], deals 13x character's ATK in QCK damage to one enemy", + specialName: "Ocean Current Shoulder Throw", + captain: "Boosts ATK of Fighter characters by 2x" + }, + 410: { + special: "Changes own orb into [QCK], deals 13x character's ATK in QCK damage to one enemy", + specialName: "Ocean Current Shoulder Throw", + captain: "Boosts ATK of Fighter characters by 2.5x" + }, + 411: { + special: "Changes adjacent orbs into [STR] orbs, deals 1,000 fixed damage to all enemies", + specialName: "Ursa Shock", + specialNotes: "#{fixed}", + captain: "Boosts ATK and HP of STR characters by 2x" + }, + 412: { + special: "Changes adjacent orbs into [STR] orbs, deals 1,000 fixed damage to all enemies", + specialName: "Ursa Shock", + specialNotes: "#{fixed}", + captain: "Boosts ATK and HP of STR characters by 2x" + }, + 413: { + special: "Changes [STR] and [DEX] orbs into [INT] orbs", + specialName: "Doppelman", + captain: "Boosts ATK of INT characters by 2.5x if HP is above 99% at the start of the turn" + }, + 414: { + special: "Changes [STR] and [DEX] orbs into [INT] orbs", + specialName: "Doppelman", + captain: "Boosts ATK of INT characters by 3x if HP is above 99% at the start of the turn" + }, + 415: { + special: "Recovers 15x character's RCV in HP, delays all enemies for 1 turn", + specialName: "Love-Love Mellow", + captain: "Boosts ATK of QCK and PSY characters by 2.75x and their RCV by 1.5x if HP is above 70% at the start of the turn" + }, + 416: { + special: "Recovers 15x character's RCV in HP, delays all enemies for 1 turn", + specialName: "Love-Love Mellow", + captain: "Boosts ATK of QCK and PSY characters by 2.75x and their RCV by 1.5x if HP is above 70% at the start of the turn" + }, + 417: { + special: "Switches orbs between slots twice, amplifies the effect of orbs by 2x for 1 turn", + specialNotes: "#{orb : 2x}", + specialName: "Overheat", + captain: "Boosts ATK of Slasher characters by 2x" + }, + 418: { + special: "Switches orbs between slots twice, amplifies the effect of orbs by 2x for 1 turn", + specialNotes: "#{orb : 2x}", + specialName: "Overheat", + captain: "Boosts ATK and HP of Slasher characters by 2x" + }, + 419: { + special: "Reduces the defense of all enemies by 50% for 2 turns, randomizes all orbs", + specialName: "Parage Shot: The Storm", + captain: "Boosts ATK of QCK characters by 2x" + }, + 420: { + special: "Reduces Despair duration by 3 turns, deals 15x character's ATK in STR damage to one enemy", + specialName: "Gum-Gum Bazooka: Supremacy", + captain: "Boosts ATK, HP and RCV of STR characters by 1.5x" + }, + 421: { + special: "Reduces Bind duration by 2 turns, deals 10x character's ATK in DEX damage to all enemies", + specialName: "Three Thousand Worlds: The Final Stroke", + captain: "Boosts ATK, HP and RCV of DEX characters by 1.5x" + }, + 422: { + special: "Reduces damage received from INT enemies by 100% for 1 turn, recovers a random amount of HP", + specialName: "Mirage Tempo: The Heavens", + specialNotes: "#{randomHeal : 1,000 : 3,000}", + captain: "Boosts ATK, HP and RCV of INT characters by 1.5x" + }, + 423: { + special: "Recovers 4,343 HP, reduces the defense of all enemies by 50% for 2 turns", + specialName: "Lullaby Parry", + captain: "Protects from defeat as long as HP is above 70%", + captainNotes: "#{zombie}" + }, + 424: { + special: "Recovers 4,343 HP, reduces the defense of all enemies by 50% for 2 turns", + specialName: "Lullaby Parry", + captain: "Boosts ATK of the whole crew by 1.5x and protects from defeat as long as HP is above 70%", + captainNotes: "#{zombie}" + }, + 425: { + special: "Deals random PSY damage to all enemies", + specialName: "Shusui: Three Verse Arrow Notch Slash", + specialNotes: "#{random : 1 : 100,000}", + captain: "Boosts ATK and HP of Slasher characters by 1.5x" + }, + 426: { + special: "Boosts ATK of STR characters by 1.05x for 5 turns", + specialName: "Barco Grabber Breath", + captain: "Boosts HP of STR characters by 2x" + }, + 427: { + special: "Reduces Bind and Despair duration by 2 turns", + specialName: "Havoc Sonar", + captain: "Boosts HP of DEX characters by 2x" + }, + 428: { + special: "Reduces damage received by 50% for 2 turns", + specialName: "Last Boss – Deep Dive of Dreams", + captain: "Boosts ATK of PSY characters by 2x" + }, + 429: { + special: "Deals 7x character's ATK in DEX damage to all enemies, reduces the defense of all enemies by 50% for 1 turn", + specialName: "South Bird's Fearless Smile" + }, + 430: { + special: "Amplifies the effect of orbs by 1.5x for 1 turn", + specialNotes: "#{orb : 1.5x}", + specialName: "Spring Hopper", + captain: "Boosts ATK of DEX characters by 1.5x" + }, + 431: { + special: "Amplifies the effect of orbs by 1.5x for 1 turn", + specialNotes: "#{orb : 1.5x}", + specialName: "Spring Hopper", + captain: "Boosts ATK and HP of DEX characters by 1.5x" + }, + 432: { + special: "Deals 20x character's ATK in QCK damage to one enemy", + specialName: "Big Chop" + }, + 433: { + special: "Reduces Bind and Despair duration by 1 turn", + specialName: "New Kama Seduction", + captain: "Boosts ATK by 2x following a chain of QCK > STR > DEX attacks no lower than Good" + }, + 434: { + special: "Amplifies the effect of orbs by 1.25x for 3 turns", + specialNotes: "#{orb : 1.25x}", + specialName: "New Kama Karate Maiden's Awakening", + captain: "Boosts ATK by 2x following a chain of PSY > INT > INT attacks no lower than Good" + }, + 435: { + special: "Randomly changes [RCV], [STR] and [DEX] orbs into either [STR] or [QCK] orbs", + specialName: "Maiden's Bloom", + captain: "Boosts ATK by 2x following a chain of INT > PSY > QCK attacks no lower than Good" + }, + 436: { + special: "Randomly changes [RCV], [STR] and [DEX] orbs into either [STR] or [QCK] orbs", + specialName: "Maiden's Bloom", + captain: "Boosts ATK by 2.25x following a chain of INT > PSY > QCK attacks no lower than Good" + }, + 437: { + special: "Recovers 3x character's RCV in HP, reduces damage received by 80% for 1 turn, Poisons enemies for 1,000 for a single turn", + specialName: "Negative Horo \"Sweet\"", + specialNotes: "Poison damage deals 1,000 damage exactly and will ignore enemy armor at the end of your turn", + captain: "Boosts RCV of [DEX] characters by 3x if HP is below 30% at the start of the turn" + }, + 438: { + special: "Recovers 3x character's RCV in HP, reduces damage received by 80% for 1 turn, Poisons enemies for 1,000 for a single turn", + specialName: "Negative Horo \"Sweet\"", + specialNotes: "Poison damage deals 1,000 damage exactly and will ignore enemy armor at the end of your turn", + captain: "Boosts RCV of [DEX] characters by 5x if HP is below 30% at the start of the turn" + }, + 439: { + special: "Changes adjacent orbs into [RCV] and randomizes every other orb", + specialName: "Charge! Supersonic Duck Squadron! \"Love\"", + captain: "Recovers 5x character's RCV in HP at the end of each turn" + }, + 440: { + special: "Changes adjacent orbs into [RCV] and randomizes every other orb", + specialName: "Charge! Supersonic Duck Squadron! \"Love\"", + captain: "Recovers 7x character's RCV in HP at the end of each turn" + }, + 444: { + captain: "Boosts ATK of Evolver and Booster characters by 2x if HP is above 50% at the start of the turn" + }, + 445: { + special: "Randomly changes all orbs into either [STR], [DEX], [QCK], [PSY] or [INT] orbs, switches orbs between slots 3 times", + specialName: "Support Incoming! Supersonic Duck Squadron!", + captain: "Boosts ATK of Evolver and Booster characters by 2.5x if HP is above 50% at the start of the turn" + }, + 446: { + special: "Deals 10 times the damage received in the previous turn in typeless damage to all enemies", + specialName: "Black Hole", + captain: "Increases damage received by 2x, boosts ATK of STR characters by 2x and their HP by 1.5x" + }, + 447: { + special: "Deals 10 times the damage received in the previous turn in typeless damage to all enemies", + specialName: "Black Hole", + captain: "Increases damage received by 2x, boosts ATK of STR characters by 2.5x and their HP by 2.25x", + limit: [ + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 10" }, + { "description": "Boosts base HP by 20" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Boosts base HP by 30" }, + { "description": "Aquire Sailor Ability 1: Boosts base HP of [STR] characters by 120" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base HP by 60" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Aquire Potential 2: Barrier Penetration" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 10% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 15% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 20% chance to deal 10% of this character's attack in extra damage" + ] + }, + { + "Name": "Barrier Penetration", + "description": [ + "Level 1: This character's attack will ignore barriers if HP is above 99%", + "Level 2: This character's attack will ignore barriers if HP is above 99%", + "Level 3: This character's attack will ignore barriers if HP is above 99%", + "Level 4: This character's attack will ignore barriers if HP is above 80%", + "Level 5: This character's attack will ignore barriers if HP is above 50%" + ] + }, + ] + }, + 448: { + special: "Boosts chances of getting [QCK] orbs for 3 turns", + specialName: "Pirate King's Sword", + captain: "Boosts ATK of QCK characters by 3x if HP is above 99% at the start of the turn" + }, + 449: { + special: "Boosts chances of getting [QCK] orbs for 3 turns", + specialName: "Pirate King's Sword", + captain: "Boosts ATK of QCK characters by 3x if HP is above 99% at the start of the turn" + }, + 450: { + special: "Boosts ATK of Fighter characters by 1.5x for 1 turn, deals 25x character's ATK in DEX damage to one enemy", + specialName: "Number Eight's One Hit", + captain: "Boosts ATK of Fighter characters by 2x and their HP by 1.5x", + sailor: "Boosts base ATK of Fighter characters by 20" + }, + 451: { + special: "Boosts ATK of Fighter characters by 1.5x for 1 turn, deals 25x character's ATK in DEX damage to one enemy", + specialName: "Number Eight's One Hit", + captain: "Boosts ATK of Fighter characters by 2x and their HP by 1.5x", + sailor: "Boosts base ATK of Fighter characters by 20" + }, + 452: { + special: "Changes own orb and the captain's orb into [PSY]", + specialName: "Dread Morning Star", + captain: "Reduces cooldown of all specials by 3 turns at the start of the fight, boosts ATK of Striker characters by 2x" + }, + 453: { + special: "Changes own orb and the captain's orb into [PSY]", + specialName: "Dread Morning Star", + captain: "Reduces cooldown of all specials by 3 turns at the start of the fight, boosts ATK of Striker characters by 2x" + }, + 454: { + special: "Boosts ATK of STR characters by 1.5x for 1 turn, deals 15x character's ATK in STR damage to all enemies", + specialName: "Manly Flaming Sword", + captain: "Boosts ATK of STR characters by 2x, boosts damage of STR specials by 2x", + captainNotes: "#{noFixedPerc}" + }, + 455: { + special: "Boosts ATK of STR characters by 1.5x for 1 turn, deals 15x character's ATK in STR damage to all enemies", + specialName: "Manly Flaming Sword", + captain: "Boosts ATK of STR characters by 2x, boosts damage of STR specials by 2x", + captainNotes: "#{noFixedPerc}" + }, + 456: { + special: "Randomly changes the orbs in the middle row into either [STR] or [DEX] orbs, the orbs in the lower row into either [PSY] or [INT] orbs, switches orbs between slots once", + specialName: "Double Cannon", + captain: "Boosts ATK of Shooter characters by 2x and their RCV by 1.5x", + sailor: "Makes [PSY] orbs \"beneficial\" for this unit" + }, + 457: { + special: "Randomly changes the orbs in the middle row into either [STR] or [DEX] orbs, the orbs in the lower row into either [PSY] or [INT] orbs, switches orbs between slots once", + specialName: "Double Cannon", + captain: "Boosts ATK of Shooter characters by 2x and their RCV by 1.5x", + sailor: "Makes [PSY] orbs \"beneficial\" for this unit" + }, + 458: { + special: "Deals random PSY damage to all enemies, boosts ATK of all characters by 1.5x for 1 turn", + specialName: "Zen Shockwave", + specialNotes: "#{random : 30,000 : 150,000}", + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of characters with cost 20 or less by 3x" + }, + 459: { + special: "Deals random PSY damage to all enemies, boosts ATK of all characters by 1.5x for 1 turn", + specialName: "Zen Shockwave", + specialNotes: "#{random : 30,000 : 150,000}", + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of characters with cost 20 or less or 54 cost exactly by 3x", + captainNotes: "His captain ability also affects his evolved forms, his base form will NOT receive the boost. All evolved and plus evolved Sengoku characters in the team are included in the bonus." + }, + 460: { + special: "Recovers 33 HP after the end of each turn for 999 turns, delays all enemies for 1 turn", + specialName: "Extra Large Candle Service Set", + captain: "Reduces damage received by 10%" + }, + 461: { + special: "Randomizes all orbs and changes own orb into [DEX], boosts ATK of Fighter characters by 1.25x for 2 turns", + specialName: "Escape Dance: White Swan Arabesque", + captain: "Boosts ATK of Fighter characters by 2x" + }, + 462: { + special: "Randomizes all orbs and changes own orb into [DEX], boosts ATK of Fighter characters by 1.25x for 2 turns", + specialName: "Escape Dance: White Swan Arabesque", + captain: "Boosts ATK of Fighter characters by 2x" + }, + 463: { + special: "Empties all slots, deals 25x character's ATK in PSY damage to one enemy", + specialName: "Surprise Ball Dragon", + captain: "Boosts HP of PSY characters by 2x" + }, + 464: { + special: "Deals 20x character's ATK in INT damage to all enemies", + specialName: "Roc Rider Fuza's Flame", + captain: "Boosts ATK and HP of Striker characters by 1.5x" + }, + 465: { + special: "Deals 20x character's ATK in QCK damage to one enemy, amplifies the effect of orbs by 1.25x for 2 turns", + specialNotes: "#{orb : 1.25x}", + specialName: "Jet Punch", + captain: "Boosts ATK by 3x after scoring 4 hits below Good in a row" + }, + 466: { + special: "Delays all enemies for 1 turn", + specialName: "Double Flash Gun", + captain: "Boosts ATK and HP of Shooter characters by 1.5x" + }, + 467: { + special: "Changes [RCV] orbs into [STR] orbs", + specialName: "Mountain Belly", + captain: "Boosts ATK and RCV of STR characters by 1.5x" + }, + 468: { + special: "Boosts RCV of all characters by 1.5x for 1 turn", + specialName: "Healing Power" + }, + 469: { + special: "Switches orbs between slots once", + specialName: "Quick Change" + }, + 470: { + special: "Boosts RCV of all characters by 1.5x for 1 turn", + specialName: "Healing Power", + captain: "Boosts RCV of PSY characters by 1.5x" + }, + 471: { + special: "Switches orbs between slots once", + specialName: "Quick Change" + }, + 472: { + special: "Deals 20x character's ATK in STR damage to one enemy", + specialName: "Milky Power Axe" + }, + 473: { + special: "Deals 10x character's ATK in QCK damage to one enemy", + specialName: "Milky Quick Axe" + }, + 474: { + special: "Deals 5x character's ATK in DEX damage to all enemies, reduces Bind duration by 1 turn", + specialName: "Milky Technique Axe" + }, + 475: { + special: "Deals 5x character's ATK in STR damage to all enemies, recovers 500 HP", + specialName: "Milky Mind Axe" + }, + 476: { + special: "Deals 1,000 fixed damage to one enemy", + specialName: "Milky Intelligence Axe", + specialNotes: "#{fixed}" + }, + 477: { + special: "Changes [DEX] orbs into [STR] orbs", + specialName: "[DEX] Slot Change [STR]" + }, + 478: { + special: "Changes [PSY] orbs into [QCK] orbs", + specialName: "[PSY] Slot Change [QCK]" + }, + 479: { + special: "Changes [INT] orbs into [DEX] orbs", + specialName: "[INT] Slot Change [DEX]" + }, + 480: { + special: "Changes [TND] orbs into [PSY] orbs", + specialName: "[TND] Slot Change [PSY]" + }, + 481: { + special: "Changes [DEX] orbs into [INT] orbs", + specialName: "[DEX] Slot Change [INT]" + }, + 482: { + special: "Changes [DEX] orbs into [STR] orbs", + specialName: "[DEX] Slot Change [STR]", + captain: "Boosts HP of Striker characters by 1.5x" + }, + 483: { + special: "Changes [PSY] orbs into [QCK] orbs", + specialName: "[PSY] Slot Change [QCK]", + captain: "Boosts ATK and RCV of QCK characters by 1.2x" + }, + 484: { + special: "Changes [INT] orbs into [DEX] orbs", + specialName: "[INT] Slot Change [DEX]", + captain: "Reduces damage received by 10%" + }, + 485: { + special: "Changes [TND] orbs into [PSY] orbs", + specialName: "[TND] Slot Change [PSY]", + captain: "Boosts HP and RCV of PSY characters by 1.2x" + }, + 486: { + special: "Changes [DEX] orbs into [INT] orbs", + specialName: "[DEX] Slot Change [INT]", + captain: "Boosts ATK of Striker characters by 1.5x" + }, + 487: { + special: "Boosts ATK of STR characters by 1.2x for 1 turn", + specialName: "Attack Boost STR" + }, + 488: { + special: "Boosts ATK of QCK characters by 1.2x for 1 turn", + specialName: "Attack Boost QCK" + }, + 489: { + special: "Boosts ATK of DEX characters by 1.2x for 1 turn", + specialName: "Attack Boost DEX" + }, + 490: { + special: "Boosts ATK of STR characters by 1.2x for 1 turn", + specialName: "Attack Boost STR", + captain: "Boosts ATK and HP of Striker characters by 1.2x" + }, + 491: { + special: "Boosts ATK of QCK characters by 1.2x for 1 turn", + specialName: "Attack Boost QCK", + captain: "Boosts RCV of Striker characters by 1.5x" + }, + 492: { + special: "Boosts ATK of DEX characters by 1.2x for 1 turn", + specialName: "Attack Boost DEX", + captain: "Boosts ATK of DEX characters by 1.2x" + }, + 493: { + special: "Recovers 7x character's RCV in HP", + specialName: "Moderate Healing" + }, + 494: { + special: "Deals 3x character's ATK in INT damage to all enemies, Poisons all enemies", + specialNotes: "#{poison}", + specialName: "Poison Attack" + }, + 495: { + special: "Recovers 7x character's RCV in HP", + specialName: "Moderate Healing", + captain: "Recovers 500 HP at the end of each turn" + }, + 496: { + special: "Deals 3x character's ATK in INT damage to all enemies, Poisons all enemies", + specialNotes: "#{poison}", + specialName: "Poison Attack", + captain: "Boosts ATK of Shooter characters by 1.5x" + }, + 497: { + special: "Reduces Bind duration by 4 turns, deals 3x character's ATK in QCK damage to one enemy", + specialName: "Cheeky Punk Kid Kick", + captain: "Boosts ATK of QCK characters by 1.5x" + }, + 498: { + special: "Reduces Bind duration by 4 turns, deals 3x character's ATK in QCK damage to one enemy", + specialName: "Cheeky Punk Kid Kick", + captain: "Boosts ATK of QCK characters by 1.5x" + }, + 499: { + special: "Delays all enemies by 1 turn", + specialName: "Women Are Courageous!", + captain: "Boosts RCV of Shooter characters by 1.5x" + }, + 500: { + special: "Delays all enemies by 1 turn", + specialName: "Women Are Courageous!", + captain: "Boosts RCV of Shooter characters by 2x" + }, + 501: { + special: "Recovers 5x character's RCV in HP at the end of each turn for 4 turns", + specialName: "Studying Medicine", + captain: "Boosts ATK, HP and RCV of PSY characters by 1.2x" + }, + 502: { + special: "Recovers 5x character's RCV in HP at the end of each turn for 4 turns", + specialName: "Studying Medicine", + captain: "Boosts ATK, HP and RCV of PSY characters by 1.5x" + }, + 503: { + special: "Deals 5x character's ATK in INT damage to all enemies, boosts ATK of all characters by 5% for 1 turn, reduces the defense of all enemies by 50% for 1 turn, randomizes all orbs", + specialName: "Surprise Dial Illusion", + captain: "Boosts HP of INT characters by 1.5x" + }, + 504: { + special: "Deals 5x character's ATK in INT damage to all enemies, boosts ATK of all characters by 5% for 1 turn, reduces the defense of all enemies by 50% for 1 turn, randomizes all orbs", + specialName: "Surprise Dial Illusion", + captain: "Boosts HP of INT characters by 2x" + }, + 505: { + special: "Boosts ATK of QCK characters by 1.25x for 3 turns", + specialName: "Flying Claw", + captain: "Protects from defeat as long as HP is above 50%", + captainNotes: "#{zombie}" + }, + 506: { + special: "Boosts ATK of QCK characters by 1.25x for 3 turns", + specialName: "Flying Claw", + captain: "Protects from defeat as long as HP is above 30%", + captainNotes: "#{zombie}" + }, + 507: { + special: "Deals 25x character's ATK in STR damage to one enemy", + specialName: "Ringing Fang", + captain: "Boosts ATK and HP of STR characters by 1.2x" + }, + 508: { + special: "Deals 25x character's ATK in STR damage to one enemy", + specialName: "Ringing Fang", + captain: "Boosts ATK and HP of STR characters by 1.5x" + }, + 509: { + special: "Poisons all enemies, boosts ATK of Striker characters by 1.5x for 1 turn", + specialNotes: "#{poison}", + specialName: "Merciless Ploy: Poison Needle", + captain: "Boosts ATK of Striker characters by 2x" + }, + 510: { + special: "Poisons all enemies, boosts ATK of Striker characters by 1.5x for 1 turn", + specialNotes: "#{poison}", + specialName: "Merciless Ploy: Poison Needle", + captain: "Reduces damage received by 10%, boosts ATK of Striker characters by 2x" + }, + 511: { + special: "Reduces damage received by 30% for 2 turns, boosts ATK of Slasher characters by 1.25x for 2 turns", + specialName: "Cruel Blade: Iron Guard", + captain: "Boosts ATK of Slasher characters by 2x" + }, + 512: { + special: "Boosts chances of getting [PSY] orbs and reduces chances of getting [INT] orbs for 3 turns", + specialName: "Sneaky Punk Kid Strike", + captain: "Protects from defeat as long as HP is above 50%", + captainNotes: "#{zombie}" + }, + 513: { + special: "Boosts chances of getting [PSY] orbs and reduces chances of getting [INT] orbs for 3 turns", + specialName: "Sneaky Punk Kid Strike", + captain: "Protects from defeat as long as HP is above 50%, boosts ATK of PSY characters by 1.5x if HP is above 50% at the start of the turn", + captainNotes: "#{zombie}" + }, + 514: { + special: "Boosts ATK of INT characters by 1.5x for 1 turn, reduces the defense of all enemies by 50% for 1 turn", + specialName: "Blooming Flower of Everlasting Summer", + captain: "Boosts ATK of INT characters by 2x" + }, + 515: { + special: "Changes the orbs in the left column into [INT], [PSY] and [RCV], the orbs in the right column into [STR], [DEX] and [QCK], switches orbs between slots 3 times", + specialNotes: "The special is not based on chance, the orbs are always changed with the same pattern. Starting from the top left orb and proceeding clockwise, after the special is used the orbs will be: [INT], [STR], [DEX], [QCK], [RCV] and [PSY]", + specialName: "Pop Green", + captain: "Boosts ATK, HP and RCV of Shooter characters by 1.5x" + }, + 516: { + special: "Changes the orbs in the left column into [INT], [PSY] and [RCV], the orbs in the right column into [STR], [DEX] and [QCK], switches orbs between slots 3 times", + specialNotes: "The special is not based on chance, the orbs are always changed with the same pattern. Starting from the top left orb and proceeding clockwise, after the special is used the orbs will be: [INT], [STR], [DEX], [QCK], [RCV] and [PSY]", + specialName: "Pop Green", + captain: "Boosts ATK, HP and RCV of Shooter characters by 1.5x, recovers 1x character's RCV in HP at the end of each turn" + }, + 517: { + special: "Empties all slots with [RCV] orbs, boosts ATK of all characters by 5% for 2 turns", + specialName: "Overeat! Energy Change", + captain: "Boosts HP of PSY characters by 1.5x" + }, + 518: { + special: "Empties all slots with [RCV] orbs, boosts ATK of all characters by 5% for 2 turns", + specialName: "Overeat! Energy Change", + captain: "Boosts HP of PSY characters by 2x, boosts chances of getting [RCV] orbs" + }, + 519: { + special: "Reduces crew's current HP by 99%, deals 25x character's ATK in fixed damage to all enemies, boosts ATK of STR characters by 2x for 1 turn", + specialName: "Gum-Gum Gigant Thor Axe", + specialNotes: "#{fixed}", + captain: "Boosts ATK of STR characters by 2x" + }, + 520: { + special: "Reduces crew's current HP by 99%, deals 25x character's ATK in fixed damage to all enemies, boosts ATK of STR characters by 2x for 1 turn", + specialName: "Gum-Gum Gigant Thor Axe", + specialNotes: "#{fixed}", + captain: "Boosts ATK of STR characters by 2.5x" + }, + 521: { + special: "Deals several times the character's ATK in INT damage to all enemies", + specialNotes: "#{specialProportional : lower : 100 * ( 1 - (remaining HP) / (total HP) )}", + specialName: "Diable Jambe - Venaison Shot", + captain: "Reduces damage received by 80% if HP is above 99% at the start of the turn", + sailor: "Reduces Paralysis by 3 turns for self" + }, + 522: { + special: "Deals several times the character's ATK in INT damage to all enemies", + specialNotes: "#{specialProportional : lower : 100 * ( 1 - (remaining HP) / (total HP) )}", + specialName: "Diable Jambe - Venaison Shot", + captain: "Reduces damage received by 80% if HP is above 99% at the start of the turn", + sailor: "Reduces Paralysis by 3 turns for self" + }, + 523: { + special: "Randomizes all orbs, protects from defeat as long as HP is above 50% for 1 turn", + specialName: "Billy's Electrical Discharge", + specialNotes: "#{zombie}", + captain: "Boosts ATK and RCV of Striker characters by 1.5x", + sailor: "Makes [DEX] orbs \"beneficial\" for this unit" + }, + 524: { + special: "Randomizes all orbs, protects from defeat as long as HP is above 50% for 1 turn", + specialName: "Billy's Electrical Discharge", + specialNotes: "#{zombie}", + captain: "Boosts ATK of Striker characters by 2x and their RCV by 1.5x", + sailor: "Makes [DEX] orbs \"beneficial\" for this unit" + }, + 525: { + special: "Deals random PSY damage to all enemies, randomizes all orbs", + specialName: "Three-Verse Humming: Arrow-Notch Slash", + captain: "Boosts ATK of PSY characters by 2x", + sailor: "Boosts base RCV of PSY characters by 15" + }, + 526: { + special: "Deals random PSY damage to all enemies, randomizes all orbs", + specialName: "Three-Verse Humming: Arrow-Notch Slash", + captain: "Boosts ATK of PSY characters by 2x, reduces damage received from INT enemies by 30%", + sailor: "Boosts base RCV of PSY characters by 15" + }, + 527: { + special: "Removes Poison, recovers 15x character's RCV in HP", + specialName: "Devoted Healing - \"I'm Glad You are Safe\"", + captain: "Boosts ATK and RCV of DEX characters by 1.5x", + sailor: "When HP is below 30% at the start of the turn, boosts own RCV by 50" + }, + 528: { + special: "Removes Poison, recovers 15x character's RCV in HP", + specialName: "Devoted Healing - \"I'm Glad You are Safe\"", + captain: "Boosts ATK and RCV of DEX characters by 2x", + sailor: "When HP is below 30% at the start of the turn, boosts own RCV by 50" + }, + 529: { + special: "Deals 35x character's ATK in PSY damage to all enemies, reduces the defense of all enemies by 100% for 2 turns", + specialName: "Conqueror's Haki: Emperor", + captain: "Boosts chances of getting [PSY] orbs, boosts ATK of PSY characters proportionally to the crew's current HP", + captainNotes: "#{captainProportional : higher : 2 + 0.75 * (remaining HP) / (total HP) : 2.75 : 2}" + }, + 530: { + special: "Deals 35x character's ATK in PSY damage to all enemies, reduces the defense of all enemies by 100% for 2 turns", + specialName: "Conqueror's Haki: Emperor", + captain: "Boosts chances of getting [PSY] orbs, boosts ATK of PSY characters proportionally to the crew's current HP", + captainNotes: "#{captainProportional : higher : 2 + 0.75 * (remaining HP) / (total HP) : 2.75 : 2}" + }, + 531: { + special: "Reduces damage received by 30% for 4 turns", + specialName: "Veinte Fleur Calendula: Blossom", + captain: "Reduces damage received from STR, DEX and QCK enemies by 30%" + }, + 532: { + special: "Reduces damage received by 30% for 4 turns", + specialName: "Veinte Fleur Calendula: Blossom", + captain: "Reduces damage received from STR, DEX and QCK enemies by 30%" + }, + 533: { + special: "Amplifies the effect of orbs by 1.5x for 1 turn, deals 20x character's ATK in QCK damage to one enemy", + specialNotes: "#{orb : 1.5x}", + specialName: "Swallow Bond En Avant: Blossom", + captain: "Boosts ATK of QCK characters by 2x" + }, + 534: { + special: "Amplifies the effect of orbs by 1.5x for 1 turn, deals 20x character's ATK in QCK damage to one enemy", + specialNotes: "#{orb : 1.5x}", + specialName: "Swallow Bond En Avant: Blossom", + captain: "Boosts ATK of QCK characters by 2x" + }, + 535: { + special: "Reduces damage received by 50% for 2 turns, boosts RCV of all characters by 2x for 2 turns", + specialName: "Mirage Tempo Fata Morgana: Blossom", + captain: "Boosts RCV of DEX characters by 1.5x" + }, + 536: { + special: "Reduces damage received by 50% for 2 turns, boosts RCV of all characters by 2x for 2 turns", + specialName: "Mirage Tempo Fata Morgana: Blossom", + captain: "Boosts RCV of DEX characters by 2x" + }, + 537: { + special: "Reduces Bind and Despair duration by 1 turn, locks all orbs for 1 turn", + specialName: "Sea Stone Handcuffs", + captain: "Boosts chain multiplier by 2x" + }, + 538: { + special: "Reduces Bind and Despair duration by 1 turn, locks all orbs for 1 turn", + specialName: "Sea Stone Handcuffs", + captain: "Boosts chain multiplier by 2x, recovers 2x character's RCV in HP at the end of each turn" + }, + 539: { + special: "Changes own orb into [STR], deals 25x character's ATK in STR damage to one enemy", + specialName: "Bashful Prison Beast's Metal Rod" + }, + 540: { + special: "Boosts chances of getting [DEX] orbs for 2 turns", + specialName: "Deadly Glare" + }, + 541: { + special: "Greatly reduces chances of getting [PSY], [INT], [TND] and [RCV] slots for 5 turns", + specialName: "White Thorn Deathmatch", + captain: "Boosts ATK of STR characters by 2.5x if HP is below 50% at the start of the turn" + }, + 542: { + special: "Boosts RCV of all characters by 2x for 1 turn", + specialName: "Roar of the Ruler of the Sky", + captain: "Boosts HP of all characters by 1.5x" + }, + 543: { + special: "Reduces crew's current HP by 50%, deals 50x character's ATK in DEX damage to one enemy", + specialName: "Reject", + captain: "Boosts ATK and HP of Shooter characters by 1.5x, reduces crew's RCV to 0" + }, + 544: { + special: "Reduces crew's current HP by 50%, deals 50x character's ATK in DEX damage to one enemy", + specialName: "Reject", + captain: "Boosts ATK of Shooter characters by 2.25x and their HP by 1.5x, reduces crew's RCV to 0" + }, + 545: { + special: "Deals 6,000 fixed damage to all enemies, boosts ATK of PSY characters by 1.5x for 1 turn", + specialName: "60,000,000 Volt Jamboule", + specialNotes: "#{fixed}", + captain: "Boosts ATK of PSY characters by 2x" + }, + 546: { + special: "Deals 6,000 fixed damage to all enemies, boosts ATK of PSY characters by 1.5x for 1 turn", + specialName: "60,000,000 Volt Jamboule", + specialNotes: "#{fixed}", + captain: "Boosts ATK of PSY characters by 2x, reduces damage received by 20%" + }, + 547: { + special: "Reduces crew's current HP by 10%, deals 1x character's ATK in STR damage to one enemy, protects from defeat as long as HP is above 50% for 1 turn", + specialName: "Crazy Punk Kid Punch", + specialNotes: "#{zombie}", + captain: "Boosts chances of getting [RCV] orbs" + }, + 548: { + special: "Reduces crew's current HP by 10%, deals 1x character's ATK in STR damage to one enemy, protects from defeat as long as HP is above 50% for 1 turn", + specialName: "Crazy Punk Kid Punch", + specialNotes: "#{zombie}", + captain: "Boosts chances of getting [RCV] orbs, boosts ATK of all characters by 1.2x" + }, + 549: { + special: "Boosts ATK against enemies with reduced defense by 1.3x for 3 turns", + specialName: "Arousal Manifesto - Red Demon Whip", + captain: "Boosts ATK by 2x after scoring 3 Perfects in a row" + }, + 550: { + special: "Boosts ATK against enemies with reduced defense by 1.3x for 3 turns", + specialName: "Arousal Manifesto - Red Demon Whip", + captain: "Boosts ATK by 2.5x after scoring 3 Perfects in a row" + }, + 551: { + special: "Reduces damage received by 50% for 1 turn, deals 15x character's ATK in STR damage to one enemy", + specialName: "Uncompromising Prison Beast's Morning Star" + }, + 552: { + special: "Reduces the defense of all enemies by 100% for 1 turn", + specialName: "Cursed Shout" + }, + 553: { + special: "Changes adjacent orbs into [DEX], deals 1,000 fixed damage to all enemies", + specialName: "Ashura Ugui", + specialNotes: "#{fixed}", + captain: "Boosts ATK of DEX characters by 2.75x if HP is below 30% at the start of the turn", + sailor: "Boosts base ATK of Slasher characters by 20" + }, + 554: { + special: "Changes adjacent orbs into [DEX], deals 1,000 fixed damage to all enemies", + specialName: "Ashura Ugui", + specialNotes: "#{fixed}", + captain: "Boosts ATK of DEX characters by 3x if HP is below 30% at the start of the turn", + sailor: "Boosts base ATK of Slasher characters by 20" + }, + 555: { + special: "Delays all enemies for 3 turns, cuts the current HP of each enemy by 10%", + specialName: "Heavenly Dragon Star", + captain: "Boosts ATK of Shooter characters by 2x", + sailor: "Boosts base RCV of Shooter characters by 10" + }, + 556: { + special: "Delays all enemies for 3 turns, cuts the current HP of each enemy by 10%", + specialName: "Heavenly Dragon Star", + captain: "Boosts ATK of Shooter characters by 2x and their RCV by 1.5x", + sailor: "Boosts base RCV of Shooter characters by 10", + limit: [ + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Boosts base HP by 80" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base HP by 120" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK of Shooter characters by 50" }, + { "description": "Aquire Potential 2: Reduce No Healing duration" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 10% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 15% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 20% chance to deal 10% of this character's attack in extra damage" + ] + }, + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: If there are 6 Shooter characters in your crew, reduces No Healing duration by 1 turn", + "Level 2: If there are 5 Shooter characters in your crew, reduces No Healing duration by 1 turn", + "Level 3: If there are 4 Shooter characters in your crew, reduces No Healing duration by 1 turn", + "Level 4: If there are 4 Shooter characters in your crew, reduces No Healing duration by 2 turns", + "Level 5: If there are 4 Shooter characters in your crew, reduces No Healing duration by 3 turns" + ] + }, + ] + }, + 557: { + special: "Boosts chances of getting [INT] orbs for 3 turns", + specialName: "Ochenta Fleur - Cuatro Manus Shock", + captain: "Boosts ATK and RCV of INT characters by 1.5x", + sailor: "Reduces Blindness duration by 3 turns" + }, + 558: { + special: "Boosts chances of getting [INT] orbs for 3 turns", + specialName: "Ochenta Fleur - Cuatro Manus Shock", + captain: "Boosts ATK and RCV of INT characters by 2x", + sailor: "Reduces Blindness duration by 3 turns" + }, + 559: { + special: "Changes own orb into [STR], amplifies the effect of orbs by 1.5x for 2 turns", + specialNotes: "#{orb : 1.5x}", + specialName: "Roar! Zarley Davison", + captain: "Boosts ATK of STR characters by 2x, deals 2x character's ATK in STR damage to all enemies at the end of each turn", + sailor: "Boosts base ATK of Shooter characters by 20" + }, + 560: { + special: "Changes own orb into [STR], amplifies the effect of orbs by 1.5x for 2 turns", + specialNotes: "#{orb : 1.5x}", + specialName: "Roar! Zarley Davison", + captain: "Boosts ATK of STR characters by 2.25x, deals 2x character's ATK in STR damage to all enemies at the end of each turn", + sailor: "Boosts base ATK of Shooter characters by 20" + }, + 561: { + special: "Reduces crew's current HP by 40%, deals 15x the amount of HP subtracted in typeless damage to all enemies, locks all orbs for 1 turn", + specialName: "Great Flame Commandment: Flame Emperor", + captain: "Boosts HP of Shooter characters by 1.5x and boosts ATK by 3x if they have a matching orb, by 2x otherwise" + }, + 562: { + special: "Reduces crew's current HP by 40%, deals 15x the amount of HP subtracted in typeless damage to all enemies, locks all orbs for 1 turn", + specialName: "Great Flame Commandment: Flame Emperor", + captain: "Boosts HP of Shooter characters by 1.5x and boosts ATK by 3x if they have a matching orb, by 2x otherwise" + }, + 563: { + special: "Deal 3x character's ATK in PSY damage to one enemy, changes [INT] orbs into [RCV] orbs", + specialName: "Cutie Baton" + }, + 564: { + special: "Reduces Bind duration by 2 turns", + specialName: "Sea Surface Split" + }, + 565: { + special: "Deals 5,000 fixed damage to one enemy", + specialName: "Hamburger Hammer", + specialNotes: "#{fixed}" + }, + 566: { + special: "Empties all slots with [BLOCK] orbs", + specialName: "Wipeout Tackle" + }, + 567: { + special: "Reduces Bind and Despair duration by 1 turn, deals 15x the character's ATK as STR damage to all enemies", + specialName: "Mudfish Coaster" + }, + 568: { + special: "Delays all enemies for 2 turns, reduces the defense of all enemies by 50% for 2 turns, switches orbs between slots twice", + specialName: "Slow Slow Beam", + captain: "Boosts ATK, HP and RCV of all characters by 1.25x" + }, + 569: { + special: "Delays all enemies for 2 turns, reduces the defense of all enemies by 50% for 2 turns, switches orbs between slots twice", + specialName: "Slow Slow Beam", + captain: "Boosts ATK, HP and RCV of all characters by 1.5x, reduces cooldown of all specials by 1 turn at the start of the fight" + }, + 570: { + special: "Changes [BLOCK] orbs into [STR], deals 20x character's ATK in STR damage to one enemy", + specialName: "Gum-Gum Flail", + captain: "Boosts ATK of STR and Fighter characters by 1.5x", + captainNotes: "The bonus is cumulative. STR Fighter characters get a 2.25x bonus." + }, + 571: { + special: "Changes [BLOCK] orbs into [STR], deals 20x character's ATK in STR damage to one enemy", + specialName: "Gum-Gum Flail", + captain: "Boosts ATK of STR and Fighter characters by 1.5x, reduces cooldown of all specials by 1 turn at the start of the fight", + captainNotes: "The bonus is cumulative. STR Fighter characters get a 2.25x bonus." + }, + 572: { + special: "Boosts ATK of Fighter characters by 2x for 1 turn, binds himself for 15 turns", + specialName: "Roar of Mettle", + captain: "Boosts ATK of Fighter characters by 2.5x if HP is above 99% at the start of the turn" + }, + 573: { + special: "Reduces Despair duration by 2 turns, recovers 10x character's RCV in HP", + specialName: "Manly Support", + captain: "Boosts RCV of all characters by 1.2x" + }, + 574: { + special: "Boosts ATK of Striker characters by 1.75x for 2 turns, locks all orbs for 2 turns", + specialName: "Ice Block - Pheasant Beak", + captain: "Boosts ATK of Striker characters by 2x" + }, + 575: { + special: "Boosts ATK of Striker characters by 1.75x for 2 turns, locks all orbs for 2 turns", + specialName: "Ice Block - Pheasant Beak", + captain: "Boosts ATK and HP of Striker characters by 2x", + limit: [ + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base HP by 20" }, + { "description": "Aquire Potential 1: Slot Bind Self-reduction" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base HP by 30" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base HP by 60" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK, HP and RCV of Striker characters by 50" }, + { "description": "Boosts base HP by 70" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: [PSY] Damage Reduction" }, + ], + potential: [ + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 1 turn on this character", + "Level 2: Reduces Slot Bind duration by ? turns on this character", + "Level 3: Reduces Slot Bind duration by ? turns on this character", + "Level 4: Reduces Slot Bind duration by ? turns on this character", + "Level 5: Reduces Slot Bind duration by ? turns on this character" + ] + }, + { + "Name": "[PSY] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [PSY] characters by 1%", + "Level 2: Reduce damage taken from [PSY] characters by ?%", + "Level 3: Reduce damage taken from [PSY] characters by ?%", + "Level 4: Reduce damage taken from [PSY] characters by ?%", + "Level 5: Reduce damage taken from [PSY] characters by ?%" + ] + }, + ] + }, + 576: { + special: "Changes [PSY] orbs into [INT] orbs, boosts RCV of all characters by 1.5x for 1 turn", + specialName: "Fine Tempo - Tea Time Show", + captain: "Boosts ATK of all characters by 1.5x, boosts RCV of all characters by 1.2x" + }, + 577: { + special: "Deals random typeless damage to all enemies, changes own orb into [STR]", + specialName: "Gum-Gum Jet Gatling", + specialNotes: "#{random : 70,000 : 200,000}", + captain: "Boosts ATK by 4x following a chain of Good > Great > Perfect hits" + }, + 578: { + special: "Deals random typeless damage to all enemies, changes own orb into [STR]", + specialName: "Gum-Gum Jet Gatling", + specialNotes: "#{random : 70,000 : 200,000}", + captain: "Boosts ATK by 4x following a chain of Good > Great > Perfect hits" + }, + 579: { + special: "Randomly changes [BLOCK] orbs into either [QCK] or [DEX] orbs, deals 15x character's ATK in QCK damage to all enemies", + specialName: "Dragon Twister", + captain: "Boosts ATK of QCK and DEX characters by 1.5x" + }, + 580: { + special: "Randomly changes [BLOCK] orbs into either [QCK] or [DEX] orbs, deals 15x character's ATK in QCK damage to all enemies", + specialName: "Dragon Twister", + captain: "Boosts ATK of QCK and DEX characters by 2x" + }, + 581: { + special: "Cuts the current HP of each enemy by 7%", + specialName: "High-Caliber Bazooka", + captain: "Boosts ATK of STR characters by 1.5x" + }, + 582: { + special: "Deals 10x character's ATK in QCK damage to one enemy, boosts ATK of QCK characters by 1.5x for 1 turn", + specialName: "Burn Blade", + captain: "Boosts ATK and HP of Striker characters by 1.5x" + }, + 583: { + special: "Changes own orb into [INT] and the captain's orb into [DEX], boosts RCV of Shooter characters by 300 for 3 turns", + specialName: "Disrupting Fire", + captain: "Boosts ATK and RCV of Shooter characters by 1.5x" + }, + 584: { + special: "Reduces damage received from PSY enemies by 100% for 1 turn", + specialName: "Mantra", + captain: "Reduces cooldown of all specials by 3 turns at the start of the fight, reduces ATK, HP and RCV of all characters by 90%" + }, + 585: { + special: "Changes the captain's orb into [PSY], recovers 9x character's RCV in HP", + specialName: "The Bond Bellmere Left Us", + captain: "Boosts RCV of PSY characters by 1.5x" + }, + 586: { + special: "Changes the captain's orb into [PSY], recovers 9x character's RCV in HP", + specialName: "The Bond Bellmere Left Us", + captain: "Boosts HP and RCV of PSY characters by 1.5x" + }, + 587: { + special: "Removes Poison, reduces Bind and Despair duration by 2 turns", + specialName: "Merciful Painkiller", + captain: "Recovers 3x character's RCV in HP at the end of each turn" + }, + 588: { + special: "Removes Poison, reduces Bind and Despair duration by 2 turns", + specialName: "Merciful Painkiller", + captain: "Recovers 5x character's RCV in HP at the end of each turn" + }, + 589: { + special: "Boosts ATK of Slasher characters by 1.5x for 1 turn", + specialName: "Flag of the Rebellion", + captain: "Boosts ATK of all characters by 1.5x, reduces HP and RCV of all characters by 80%" + }, + 590: { + special: "Boosts ATK of Slasher characters by 1.5x for 1 turn", + specialName: "Flag of the Rebellion", + captain: "Boosts ATK of all characters by 2x, reduces HP and RCV of all characters by 80%" + }, + 596: { + special: "Deals 20x character's ATK in STR damage to one enemy, reduces the defense of all enemies by 50% for 3 turns", + specialName: "Rozeo Michelli", + captain: "Boosts ATK of STR characters by 1.5x, recovers 500 HP at the end of each turn" + }, + 597: { + special: "Deals 20x character's ATK in STR damage to one enemy, reduces the defense of all enemies by 50% for 3 turns", + specialName: "Rozeo Michelli", + captain: "Boosts ATK of STR characters by 1.75x, recovers 750 HP at the end of each turn" + }, + 598: { + special: "Changes own orb into [INT], switches orbs between slots once", + specialName: "Split Split Cannon", + captain: "Boosts ATK of characters with fewer than 3 stars by 2.5x" + }, + 599: { + special: "Changes own orb into [INT], switches orbs between slots once", + specialName: "Split Split Cannon", + captain: "Boosts ATK of characters with fewer than 3 stars by 3x" + }, + 600: { + special: "Deals 15x character's ATK in PSY damage to one enemy, boosts ATK of PSY characters by 1.3x for 2 turns", + specialName: "Sword Draw - Single Flash", + captain: "Boosts ATK of PSY characters by 1.5x" + }, + 601: { + special: "Deals 15x character's ATK in PSY damage to one enemy, boosts ATK of PSY characters by 1.3x for 2 turns", + specialName: "Sword Draw - Single Flash", + captain: "Boosts ATK of PSY characters by 2x" + }, + 602: { + special: "Reduces crew's current HP by 90%, deals 20,000 fixed damage to all enemies, boosts ATK of QCK characters by 2x for 1 turn", + specialName: "200,000,000 Volt Amaru", + specialNotes: "#{fixed}", + captain: "Boosts ATK of QCK characters by 2x" + }, + 603: { + special: "Reduces crew's current HP by 90%, deals 20,000 fixed damage to all enemies, boosts ATK of QCK characters by 2x for 1 turn", + specialName: "200,000,000 Volt Amaru", + specialNotes: "#{fixed}", + captain: "Boosts ATK of QCK characters by 2.25x, recovers 5x character's RCV in HP at the end of each turn" + }, + 604: { + special: "Cuts the current HP of each enemy by 10%, changes [QCK] orbs into [DEX] orbs", + specialName: "Diable Jambe: Extra Hachis Hash", + captain: "Boosts ATK of Fighter characters by 2x" + }, + 605: { + special: "Cuts the current HP of each enemy by 10%, changes [QCK] orbs into [DEX] orbs", + specialName: "Diable Jambe: Extra Hachis Hash", + captain: "Boosts ATK of Fighter characters by 2x, reduces damage received by 20%" + }, + 606: { + special: "Deals 20x character's ATK in DEX damage to one enemy, changes adjacent orbs into [RCV] orbs", + specialName: "Red Leg Kick", + captain: "Boosts ATK of Fighter characters by 2x if HP is above 50% at the start of the turn" + }, + 607: { + special: "Deals 20x character's ATK in DEX damage to one enemy, changes adjacent orbs into [RCV] orbs", + specialName: "Red Leg Kick", + captain: "Boosts ATK of Fighter characters by 2.5x if HP is above 50% at the start of the turn" + }, + 608: { + special: "For 1 turn, boosts the amount healed by RCV orbs by 1.5x, then 2x, then 2.5x from the third crew member onward", + specialName: "Wicked Strength" + }, + 609: { + special: "Changes the captain's orb into [RCV] and randomizes every other orb", + specialName: "Wicked Spirit" + }, + 610: { + special: "Changes [TND] orbs into [RCV] orbs", + specialName: "[TND] Slot Change [RCV]" + }, + 611: { + special: "Changes adjacent orbs into [RCV] orbs", + specialName: "[RCV] Slot Storm" + }, + 612: { + special: "Boosts ATK and RCV of all characters by 45 for 1 turn, reduces damage received by 45% for 1 turn", + specialName: "45-Degree Joy", + captain: "Boosts ATK of Slasher characters by 1.5x" + }, + 613: { + special: "Boosts ATK and RCV of all characters by 45 for 1 turn, reduces damage received by 45% for 1 turn", + specialName: "45-Degree Joy", + captain: "Boosts ATK, HP and RCV of Slasher characters by 1.5x" + }, + 614: { + special: "Reduces the defense of all enemies by 50% for 1 turn, deals 10x character's ATK in PSY damage to all enemies", + specialName: "Demolisher Chop", + captain: "Boosts ATK of characters with cost 20 or less by 2.25x if HP is below 30% at the start of the turn" + }, + 615: { + special: "Deals random STR damage to one enemy", + specialName: "Demolisher Axe" + }, + 616: { + special: "Changes the captain's orb into STR", + specialName: "Demolisher Spear" + }, + 617: { + special: "Boosts ATK of Shooter characters by 1.2x for 1 turn", + specialName: "Demolisher Cannon" + }, + 618: { + special: "Deals 20x character's ATK in STR damage to one enemy", + specialName: "Mach Punch" + }, + 619: { + special: "Cuts the current HP of each enemy by 5%", + specialName: "Slight Break" + }, + 620: { + special: "Changes [INT] orbs into [QCK] orbs", + specialName: "[INT] Slot Change [QCK]" + }, + 621: { + special: "Changes [INT] orbs into [STR] orbs", + specialName: "[INT] Slot Change [STR]" + }, + 622: { + special: "Boosts RCV of all characters by 100 for 3 turns", + specialName: "Patch Job" + }, + 623: { + special: "Recovers 3x character's RCV in HP at the end of each turn for 5 turns", + specialName: "Auto Repair" + }, + 624: { + special: "Slightly boosts chances of getting [PSY] orbs for 3 turns", + specialName: "Slot Rate Up [PSY]" + }, + 625: { + special: "Slightly boosts chances of getting [INT] orbs for 3 turns", + specialName: "Slot Rate Up [INT]" + }, + 626: { + special: "Deals 13x character's ATK in character's type damage to all enemies", + specialName: "Hyper Burst" + }, + 627: { + special: "Randomizes all orbs", + specialName: "Slot Shuffle" + }, + 628: { + special: "Deals 15,000 fixed damage to one enemy", + specialName: "Keel Crusher", + specialNotes: "#{fixed}" + }, + 629: { + special: "Empties all slots including those with [BLOCK] orbs, deals random INT damage to all enemies", + specialName: "Master Nail", + captain: "Boosts ATK of characters with 3 or fewer stars by 2x" + }, + 630: { + special: "Randomly changes all orbs into either [QCK] or [DEX] orbs, deals random QCK damage to all enemies", + specialName: "Tempest Kick: Slaughter", + specialNotes: "#{random : 5,000 : 15,000}", + captain: "Boosts ATK of Slasher characters by 1.5x" + }, + 631: { + special: "Randomly changes all orbs into either [QCK] or [DEX] orbs, deals random QCK damage to all enemies", + specialName: "Tempest Kick: Slaughter", + specialNotes: "#{random : 5,000 : 15,000}", + captain: "Boosts ATK of Slasher characters by 2x" + }, + 632: { + special: "Randomly changes all orbs into either [STR], [PSY] or [INT] orbs, deals random STR damage to all enemies, reduces the defense of all enemies by 50% for 2 turns", + specialName: "Finger Pistol: Yellow Lotus", + captain: "Boosts ATK of Fighter characters by 1.5x", + specialNotes: "#{random : 2,000 : 20,000}" + }, + 633: { + special: "Randomly changes all orbs into either [STR], [PSY] or [INT] orbs, deals random STR damage to all enemies, reduces the defense of all enemies by 50% for 2 turns", + specialName: "Finger Pistol: Yellow Lotus", + captain: "Boosts ATK of Fighter characters by 2x", + specialNotes: "#{random : 2,000 : 20,000}" + }, + 634: { + special: "Boosts chances of getting [QCK] and [PSY] orbs for 3 turns, boosts ATK of QCK and PSY characters by 1.2x for 3 turns", + specialName: "Guiding Mermaid Voice", + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK and RCV of QCK and PSY characters by 1.25x" + }, + 635: { + special: "Boosts chances of getting [QCK] and [PSY] orbs for 3 turns, boosts ATK of QCK and PSY characters by 1.2x for 3 turns", + specialName: "Guiding Mermaid Voice", + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK and RCV of QCK and PSY characters by 1.5x" + }, + 636: { + special: "Binds himself for 3 turns, reduces damage received by 50% for 3 turns, recovers 3.5x character's RCV in HP at the end of each turn for 3 turns", + specialName: "Wretched Ballade", + captain: "Boosts ATK of characters with cost 2 or less by 3x" + }, + 637: { + special: "Cuts the current HP of each enemy by 8%, boosts ATK against enemies with increased defense by 1.3x for 1 turn", + specialName: "Hachi Ink Jet", + captain: "Recovers 618 HP at the end of each turn, boosts ATK of Slasher characters by 1.5x" + }, + 638: { + special: "Changes [PSY] and [INT] orbs into [QCK] orbs, reduces Bind duration by 1 turn", + specialName: "Bohemian Reverse Slash", + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of Slasher characters by 2x", + sailor: "Restores his own special by 1 turn when it is rewinded", + sailorNotes: "#{rewind : 1}", + }, + 639: { + special: "Changes [PSY] and [INT] orbs into [QCK] orbs, reduces Bind duration by 1 turn", + specialName: "Bohemian Reverse Slash", + captain: "Reduces cooldown of all specials by 3 turns at the start of the fight, boosts ATK of Slasher characters by 2x", + sailor: "Restores his own special by 1 turn when it is rewinded", + sailorNotes: "#{rewind : 1}", + }, + 640: { + special: "Changes own orb into [DEX], deals several times the character's ATK in DEX damage to one enemy", + specialNotes: "#{specialProportional : lower : 50 * ( 1 - (remaining HP) / (total HP) )}", + specialName: "Pirate Brothers: Twin Strike", + captain: "Boosts ATK of Fighter characters by 2x, deals 2x character's ATK in DEX damage to all enemies at the end of each turn", + sailor: "When HP is below 30% at the start of the turn, boosts ATK of Fighter characters by 100" + }, + 641: { + special: "Changes own orb into [DEX], deals several times the character's ATK in DEX damage to one enemy", + specialNotes: "#{specialProportional : lower : 50 * ( 1 - (remaining HP) / (total HP) )}", + specialName: "Pirate Brothers: Twin Strike", + captain: "Boosts ATK of Fighter characters by 2.25x, deals 2x character's ATK in DEX damage to all enemies at the end of each turn", + sailor: "When HP is below 30% at the start of the turn, boosts ATK of Fighter characters by 100" + }, + 642: { + special: "Reduces crew's current HP by 30%, deals 10x character's ATK in fixed damage to one enemy, amplifies the effect of orbs by 1.75x for 1 turn", + specialNotes: "#{fixed} #{orb : 1.75x}", + specialName: "Raging Greatsword", + captain: "Boosts ATK of PSY characters by 2.5x if HP is below 30% at the start of the turn", + sailor: "Recovers 2 turns of Paralysis on self" + }, + 643: { + special: "Reduces crew's current HP by 30%, deals 10x character's ATK in fixed damage to one enemy, amplifies the effect of orbs by 1.75x for 1 turn", + specialNotes: "#{fixed} #{orb : 1.75x}", + specialName: "Raging Greatsword", + captain: "Boosts ATK of PSY characters by 3x if HP is below 30% at the start of the turn", + sailor: "Recovers 2 turns of Paralysis on self", + limit: [ + { "description": "Boosts base RCV by 25" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base RCV by 35" }, + { "description": "Aquire Potential 1: [STR] Damage Reduction" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base HP by 40" }, + { "description": "Reduce base Special Cooldown by 2 turns" }, + { "description": "Boosts base HP by 60" }, + { "description": "Aquire Sailor Ability 1: Reduces Blindness duration by 2 turns" }, + { "description": "Boosts base ATK by 60" }, + { "description": "Boosts base RCV by 40" }, + { "description": "Reduce base Special Cooldown by 2 turns" }, + { "description": "Boosts base RCV by 50" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: [INT] Damage Reduction" }, + ], + potential: [ + { + "Name": "[STR] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [STR] characters by 1%", + "Level 2: Reduce damage taken from [STR] characters by ?%", + "Level 3: Reduce damage taken from [STR] characters by ?%", + "Level 4: Reduce damage taken from [STR] characters by ?%", + "Level 5: Reduce damage taken from [STR] characters by ?%" + ] + }, + { + "Name": "[INT] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [INT] characters by 1%", + "Level 2: Reduce damage taken from [INT] characters by ?%", + "Level 3: Reduce damage taken from [INT] characters by ?%", + "Level 4: Reduce damage taken from [INT] characters by ?%", + "Level 5: Reduce damage taken from [INT] characters by ?%" + ] + }, + ] + }, + 644: { + special: "Reduces Bind and Despair duration by 2 turns, boosts ATK against delayed enemies by 1.2x for 3 turns", + specialName: "Witch's Icebreaker", + captain: "Boosts ATK of INT characters by 2x", + sailor: "Boosts base ATK and RCV of INT characters by 20" + }, + 645: { + special: "Reduces Bind and Despair duration by 2 turns, boosts ATK against delayed enemies by 1.2x for 3 turns", + specialName: "Witch's Icebreaker", + captain: "Boosts ATK of INT characters by 2.5x", + sailor: "Boosts base ATK and RCV of INT characters by 20" + }, + 646: { + special: "Deals 20x character's ATK in STR damage to all enemies, boosts chances of getting [STR] orbs for 3 turns", + specialName: "Vanguard Breaker", + captain: "Boosts ATK of Shooter characters by 2.5x if HP is below 30% at the start of the turn", + sailor: "Boosts base HP of STR characters by 30" + }, + 647: { + special: "Deals 20x character's ATK in STR damage to all enemies, boosts chances of getting [STR] orbs for 3 turns", + specialName: "Vanguard Breaker", + captain: "Boosts ATK of Shooter characters by 2.75x if HP is below 30% at the start of the turn", + sailor: "Boosts base HP of STR characters by 30" + }, + 648: { + special: "Recovers 100x character's RCV in HP, amplifies the effect of orbs by 1.5x for 2 turns", + specialNotes: "#{orb : 1.5x}", + specialName: "Blue Flame Kick", + captain: "Reduces damage received by 30% if HP is above 70% at the start of the turn, boosts ATK of QCK and PSY characters by 2.75x if HP is above 70% at the start the turn" + }, + 649: { + special: "Recovers 100x character's RCV in HP, amplifies the effect of orbs by 1.5x for 2 turns", + specialNotes: "#{orb : 1.5x}", + specialName: "Blue Flame Kick", + captain: "Reduces damage received by 30% if HP is above 70% at the start of the turn, boosts ATK of QCK and PSY characters by 2.75x if HP is above 70% at the start the turn" + }, + 650: { + special: "Deals 5,000 fixed damage to one enemy, amplifies the effect of orbs by 1.5x for 1 turn", + specialNotes: "#{fixed} #{orb : 1.5x}", + specialName: "Thunder Lance Tempo", + captain: "Boosts ATK of INT characters by 2x and their RCV by 1.5x" + }, + 651: { + special: "Deals 5,000 fixed damage to one enemy, amplifies the effect of orbs by 1.5x for 1 turn", + specialNotes: "#{fixed} #{orb : 1.5x}", + specialName: "Thunder Lance Tempo", + captain: "Boosts ATK of INT characters by 2x and their RCV by 1.5x" + }, + 652: { + special: "Cuts the current HP of each enemy by 20%, reduces damage received by 50% for 1 turn", + specialName: "Heart-Smashing Horn", + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of DEX characters by 2x if they have matching orbs" + }, + 653: { + special: "Cuts the current HP of each enemy by 20%, reduces damage received by 50% for 1 turn", + specialName: "Heart-Smashing Horn", + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of DEX characters by 2.25x if they have matching orbs" + }, + 654: { + special: "Cuts the current HP of each enemy by 20%, reduces damage received by 50% for 1 turn", + specialName: "Heart-Smashing Horn", + captain: "Reduces cooldown of all specials by 3 turns at the start of the fight, boosts ATK of DEX characters by 2.75x if they have matching orbs" + }, + 655: { + special: "Changes [EMPTY] and [TND] orbs into [STR] orbs, deals 10x character's ATK in STR damage to one enemy, amplifies the effect of orbs by 1.25x for 2 turns", + specialNotes: "#{orb : 1.25x}", + specialName: "Tooth Gum", + captain: "Boosts ATK of STR characters by 1.5x" + }, + 656: { + special: "Changes [EMPTY] and [TND] orbs into [STR] orbs, deals 10x character's ATK in STR damage to one enemy, amplifies the effect of orbs by 1.25x for 2 turns", + specialNotes: "#{orb : 1.25x}", + specialName: "Tooth Gum", + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of STR characters by 2x" + }, + 657: { + special: "Randomly changes [INT] and [PSY] orbs into either [STR] or [EMPTY] orbs", + specialName: "Forearm Sledge", + captain: "Boosts ATK of Fighter characters by 1.5x" + }, + 658: { + special: "Randomly changes all orbs into either [INT] or [PSY] orbs", + specialName: "Lipowertzer", + captain: "Boosts ATK of Shooter characters by 1.5x" + }, + 659: { + special: "Reduces Bind and Despair duration by 2 turns, reduces damage received by 50% for 2 turns", + specialName: "Gum-Gum Balloon Swim", + captain: "Boosts ATK by 2.5x after scoring 3 Perfects in a row" + }, + 660: { + special: "Delays all enemies for 2 turns, reduces the defense of all enemies by 50% for 2 turns", + specialName: "Atlas Comet", + captain: "Boosts ATK of Shooter characters by 2x" + }, + 661: { + special: "Delays all enemies for 2 turns, reduces the defense of all enemies by 50% for 2 turns", + specialName: "Atlas Comet", + captain: "Boosts ATK of Shooter characters by 2x, reduces cooldown of all specials by 1 turn at the start of the fight" + }, + 662: { + special: "Deals 13x character's ATK in PSY damage to one enemy, randomizes all orbs other than [PSY]", + specialName: "Tornado Tempo - Beach Side", + captain: "Boosts ATK of PSY characters by 2x" + }, + 663: { + special: "Deals PSY damage to one enemy according to HP, recovers 5x character's RCV in HP at the end of each turn for 5 turns", + specialNotes: "The exact damage is proportional to the crew's remaining HP and is higher the lower the HP is. The formula used is 80000 * (1 - (current HP) / (total HP))", + specialName: "Vivi's Important Security Guard", + captain: "Recovers 2x character's RCV in HP at the end of each turn" + }, + 664: { + special: "Deals PSY damage to one enemy according to HP, recovers 5x character's RCV in HP at the end of each turn for 5 turns", + specialNotes: "The exact damage is proportional to the crew's remaining HP and is higher the lower the HP is. The formula used is 80000 * (1 - (current HP) / (total HP))", + specialName: "Vivi's Important Security Guard", + captain: "Recovers 3x character's RCV in HP at the end of each turn" + }, + 665: { + special: "Changes own orb into [QCK], boosts ATK against enemies with reduced defense by 1.3x for 2 turns", + specialName: "Let's Go! Suna Suna Clan!!", + captain: "Boosts ATK of all characters by 1.2x, reduces HP and RCV of all characters by 80%" + }, + 666: { + special: "Changes own orb into [QCK], boosts ATK against enemies with reduced defense by 1.3x for 2 turns", + specialName: "Let's Go! Suna Suna Clan!!", + captain: "Boosts ATK of all characters by 1.75x, reduces HP and RCV of all characters by 80%" + }, + 667: { + special: "Protects from defeat as long as HP is above 50% for 1 turn", + specialName: "King's Chopper", + specialNotes: "#{zombie}", + captain: "Reduces damage received by 10%, boosts ATK of all characters by 1.5x" + }, + 668: { + special: "Boosts ATK of Free Spirit characters by 1.5x for 1 turn. If during that turn every unit scores a Perfect hit, boosts ATK of Free Spirit characters by 2x in the following turn.", + specialName: "Dragon's Claw", + captain: "Boosts HP and RCV of all characters by 1.2x, boosts ATK of Free Spirit characters proportionally to the crew's current HP", + captainNotes: "#{captainProportional : higher : 2 + 0.75 * (remaining HP) / (total HP) : 2.75 : 2}" + }, + 669: { + special: "Boosts ATK of Free Spirit characters by 1.5x for 1 turn. If during that turn every unit scores a Perfect hit, boosts ATK of Free Spirit characters by 2x in the following turn.", + specialName: "Dragon's Claw", + captain: "Boosts HP and RCV of all characters by 1.2x, boosts ATK of Free Spirit characters proportionally to the crew's current HP", + captainNotes: "#{captainProportional : higher : 2 + 0.75 * (remaining HP) / (total HP) : 2.75 : 2}" + }, + 670: { + special: "Boosts ATK of Fighter characters by 1.75x for 1 turn", + specialName: "Fishman Karate! True Fist Thrust of the Revolutionaries", + captain: "Boosts ATK of Fighter characters by 2x" + }, + 671: { + special: "Boosts ATK of Fighter characters by 1.75x for 1 turn", + specialName: "Fishman Karate! True Fist Thrust of the Revolutionaries", + captain: "Boosts ATK of Fighter characters by 2.25x and their RCV by 1.5x" + }, + 672: { + special: "Cuts the current HP of each enemy by 20%, changes own orb into [STR]", + specialName: "Four Thousand Tile True Punch", + captain: "Boosts ATK of Fighter characters by 2x" + }, + 673: { + special: "Cuts the current HP of each enemy by 20%, changes own orb into [STR]", + specialName: "Four Thousand Tile True Punch", + captain: "Reduces cooldown of all specials by 3 turns at the start of the fight, boosts ATK of Fighter characters by 2x" + }, + 674: { + special: "Removes Poison, reduces damage received by 50% for 2 turns, recovers 13x character's RCV in HP at the end of each turn for 2 turns", + specialName: "Emporio Healing Hormone", + captain: "Boosts ATK of Free Spirit characters by 2x" + }, + 675: { + special: "Removes Poison, reduces damage received by 50% for 2 turns, recovers 13x character's RCV in HP at the end of each turn for 2 turns", + specialName: "Emporio Healing Hormone", + captain: "Boosts ATK of Free Spirit characters by 2.5x" + }, + 676: { + special: "Reduces any damage received above 5,000 HP by 97% for 3 turns", + specialNotes: "The exact formula for the damage received is: 5000 + ((total damage) - 5000) * 0.03", + specialName: "KEEP OUT", + captain: "Boosts ATK of Slasher characters by 1.5x, deals 5x character's ATK in QCK damage to all enemies at the end of each turn" + }, + 677: { + special: "Reduces any damage received above 5,000 HP by 97% for 3 turns", + specialNotes: "The exact formula for the damage received is: 5000 + ((total damage) - 5000) * 0.03", + specialName: "KEEP OUT", + captain: "Boosts ATK of Slasher characters by 1.5x, deals 5x character's ATK in QCK damage to all enemies at the end of each turn" + }, + 678: { + special: "Reduces damage received by 50% for 1 turn, locks all orbs for 1 turn", + specialName: "Cien Fleur Spider Net", + captain: "Boosts ATK and RCV of PSY characters by 1.2x, boosts chances of getting [PSY] orbs" + }, + 679: { + special: "Reduces damage received by 50% for 1 turn, locks all orbs for 1 turn", + specialName: "Cien Fleur Spider Net", + captain: "Boosts ATK and RCV of PSY characters by 1.5x, boosts chances of getting [PSY] orbs" + }, + 680: { + special: "Recovers 5x character's RCV in HP, boosts ATK and RCV of DEX characters by 1.25x for 2 turns", + specialName: "Midsummer Relax Time" + }, + 681: { + special: "Recovers 5x character's RCV in HP, boosts ATK and RCV of DEX characters by 1.25x for 2 turns", + specialName: "Midsummer Relax Time", + captain: "Boosts ATK and RCV of Striker characters by 1.5x" + }, + 682: { + special: "Recovers a random amount of HP, reduces damage received by 50% for 2 turns", + specialName: "Transcendental Serenity Healing" + }, + 683: { + special: "Recovers a random amount of HP, reduces damage received by 50% for 2 turns", + specialName: "Transcendental Serenity Healing", + captain: "Boosts ATK and RCV of Fighter characters by 1.5x" + }, + 684: { + special: "Recovers 3x character's RCV in HP, reduces damage received by 80% for 1 turn", + specialName: "Romantic Ghost" + }, + 685: { + special: "Recovers 3x character's RCV in HP, reduces damage received by 80% for 1 turn", + specialName: "Romantic Ghost", + captain: "Boosts ATK and RCV of Shooter characters by 1.5x" + }, + 686: { + special: "Delays all enemies for 1 turn, recovers 3x character's RCV in HP at the end of each turn for 3 turns", + specialName: "Captivating Perfume Dance - Relaxation", + captain: "Boosts ATK and RCV of Slasher characters by 1.5x" + }, + 687: { + special: "Deals 13x character's ATK in STR damage to all enemies, boosts ATK of Free Spirit characters by 1.3x for 1 turn", + specialName: "First Spear of the Battle", + captain: "Boosts ATK of Free Spirit characters by 1.5x" + }, + 688: { + special: "Deals 13x character's ATK in STR damage to all enemies, boosts ATK of Free Spirit characters by 1.3x for 1 turn", + specialName: "First Spear of the Battle", + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of Free Spirit characters by 2x" + }, + 689: { + special: "Amplifies the effect of orbs by 1.5x for 2 turns", + specialNotes: "#{orb : 1.5x}", + specialName: "Botanist's Great Discovery", + captain: "Boosts ATK and RCV of Slasher characters by 1.2x" + }, + 690: { + special: "Amplifies the effect of orbs by 1.5x for 2 turns", + specialNotes: "#{orb : 1.5x}", + specialName: "Botanist's Great Discovery", + captain: "Boosts ATK and RCV of Slasher characters by 1.5x" + }, + 691: { + special: "Changes [PSY] orbs into [DEX] orbs", + specialName: "[PSY] Slot Change [DEX]" + }, + 692: { + special: "Changes [PSY] orbs into [QCK] orbs", + specialName: "[PSY] Slot Change [QCK]" + }, + 693: { + special: "Changes [DEX] orbs into [PSY] orbs", + specialName: "[DEX] Slot Change [PSY]" + }, + 694: { + special: "Deals 13x character's ATK in character's type damage to all enemies", + specialName: "Hyper Burst" + }, + 695: { + special: "Cuts the current HP of each enemy by 5%", + specialName: "Slight Break" + }, + 696: { + special: "Changes [PSY] orbs into [DEX] orbs", + specialName: "[PSY] Slot Change [DEX]", + captain: "Boosts ATK of Striker characters by 1.75x" + }, + 697: { + special: "Changes [PSY] orbs into [QCK] orbs", + specialName: "[PSY] Slot Change [QCK]", + captain: "Boosts ATK of Shooter characters by 1.75x" + }, + 698: { + special: "Changes [DEX] orbs into [PSY] orbs", + specialName: "[DEX] Slot Change [PSY]", + captain: "Boosts ATK of Slasher characters by 1.75x" + }, + 699: { + special: "Deals 13x character's ATK in character's type damage to all enemies", + specialName: "Hyper Burst", + captain: "Boosts ATK of Shooter characters by 500, reduces damage received by 10%" + }, + 700: { + special: "Cuts the current HP of each enemy by 5%", + specialName: "Slight Break", + captain: "Boosts ATK of Fighter characters by 1.75x" + }, + 701: { + special: "Deals 15x character's ATK in PSY damage to all enemies, changes own orb into [PSY]", + specialName: "Oimo Press", + captain: "Boosts HP of PSY characters by 2.25x" + }, + 702: { + special: "Seals himself for 5 turns, reduces damage received by 30% for 5 turns", + specialName: "Kashi Swing", + captain: "Boosts HP of INT characters by 2.25x" + }, + 703: { + special: "Deals 5x character's ATK in QCK damage to all enemies", + specialName: "Arm Claw of the Watchdog" + }, + 704: { + special: "Deals 9x character's ATK in STR damage to all enemies, reduces the defense of all enemies by 50% for 1 turn", + specialName: "Companion's Guilt" + }, + 705: { + special: "Randomly changes [PSY], [INT], [TND], [RCV] and [EMPTY] orbs into [STR], [DEX] or [QCK] orbs", + specialName: "Guilty Verdict - \"Slow Death Penalty\"", + captain: "Boosts ATK and HP of STR characters, DEX characters and QCK characters by 1.25x" + }, + 706: { + special: "Changes own orb and the captain's orb into [STR]", + specialName: "Air Door", + captain: "Boosts ATK of STR characters by 1.5x" + }, + 707: { + special: "Changes own orb and the captain's orb into [STR]", + specialName: "Air Door", + captain: "Boosts ATK and HP of STR characters by 1.5x" + }, + 708: { + special: "Reduces Bind and Despair duration by 3 turns", + specialName: "Cien Fleur - Wing", + captain: "Boosts ATK and RCV of PSY characters by 1.2x" + }, + 709: { + special: "Reduces Bind and Despair duration by 3 turns", + specialName: "Cien Fleur - Wing", + captain: "Boosts ATK and RCV of PSY characters by 1.5x" + }, + 710: { + special: "Empties all slots with [BLOCK] orbs, boosts ATK of Shooter characters by 1.25x for 3 turns, deals 15x character's ATK in PSY damage to all enemies", + specialName: "Coup de Vent", + captain: "Boosts ATK of Shooter characters by 1.5x" + }, + 711: { + special: "Empties all slots with [BLOCK] orbs, boosts ATK of Shooter characters by 1.25x for 3 turns, deals 15x character's ATK in PSY damage to all enemies", + specialName: "Coup de Vent", + captain: "Boosts ATK of Shooter characters by 2x" + }, + 712: { + special: "Deals 15x character's ATK in QCK damage to one enemy, boosts ATK of the characters in the top row by 1.5x for 2 turns", + specialNotes: "The special boosts the attack of only the crew's captain and the currently selected friend captain.", + specialName: "Sky Knight's Javelin", + captain: "Boosts ATK of Striker characters by 2x if HP is above 50% at the start of the turn" + }, + 713: { + special: "Deals 15x character's ATK in QCK damage to one enemy, boosts ATK of the characters in the top row by 1.5x for 2 turns", + specialNotes: "The special boosts the attack of only the crew's captain and the currently selected friend captain.", + specialName: "Sky Knight's Javelin", + captain: "Boosts ATK of Striker characters by 2.5x if HP is above 50% at the start of the turn" + }, + 714: { + special: "Randomizes slots with [STR], [QCK], [INT] or [PSY] orbs", + specialName: "Pegasus' Neigh" + }, + 715: { + special: "Boosts ATK and RCV of Free Spirit characters by 1.5x for 2 turns, seals herself for 3 turns", + specialName: "Angel's Harp - Healing", + captain: "Boosts RCV of all characters by 2x if HP is below 30% at the start of the turn" + }, + 716: { + special: "Boosts ATK and RCV of Free Spirit characters by 1.5x for 2 turns, seals herself for 3 turns", + specialName: "Angel's Harp - Healing", + captain: "Boosts RCV of all characters by 5x if HP is below 30% at the start of the turn" + }, + 717: { + special: "Deals 50% of the damage dealt in the previous turn as typeless damage to all enemies", + specialNotes: "The special only includes the damage inflicted through normal attacks.", + specialName: "Black Sword - Lightning Slash", + captain: "Boosts ATK of Slasher characters by a variable factor between 2x and 2.75x based on the timing of the attack of the previous unit in the chain", + captainNotes: "A hit below Good or a Miss will boost the ATK of the next unit by 2x, a Good hit by 2.25x, a Great hit by 2.5x and a Perfect hit by 2.75x. This bonus is applied only to Slasher characters." + }, + 718: { + special: "Deals 50% of the damage dealt in the previous turn as typeless damage to all enemies", + specialNotes: "The special only includes the damage inflicted through normal attacks.", + specialName: "Black Sword - Lightning Slash", + captain: "Boosts ATK of Slasher characters by a variable factor between 2x and 2.75x based on the timing of the attack of the previous unit in the chain", + captainNotes: "A hit below Good or a Miss will boost the ATK of the next unit by 2x, a Good hit by 2.25x, a Great hit by 2.5x and a Perfect hit by 2.75x. This bonus is applied only to Slasher characters." + }, + 719: { + special: "Boosts ATK of Cerebral characters by 2x if HP is below 30% when the special is activated, otherwise boosts ATK of Cerebral characters by 1.5x, deals 20x character's ATK in DEX damage to all enemies", + specialName: "Sables: Pesado", + captain: "Boosts ATK of Cerebral characters proportionally to the crew's current HP", + captainNotes: "#{captainProportional : lower : 1.5 + 1.75 * (1 - (remaining HP) / (total HP)) : 1.5 : 3.25}" + }, + 720: { + special: "Boosts ATK of Cerebral characters by 2x if HP is below 30% when the special is activated, otherwise boosts ATK of Cerebral characters by 1.5x, deals 20x character's ATK in DEX damage to all enemies", + specialName: "Sables: Pesado", + captain: "Boosts ATK of Cerebral characters proportionally to the crew's current HP", + captainNotes: "#{captainProportional : lower : 1.5 + 1.75 * (1 - (remaining HP) / (total HP)) : 1.5 : 3.25}" + }, + 721: { + special: "Randomizes all orbs, including [BLOCK] orbs", + specialName: "Screw Drop Kick", + captain: "Boosts ATK of Fighter characters by 1.5x if HP is is above 99% at the start of the turn" + }, + 722: { + special: "Randomizes all orbs, including [BLOCK] orbs", + specialName: "Screw Drop Kick", + captain: "Boosts ATK of Fighter characters by 2x if HP is is above 99% at the start of the turn" + }, + 723: { + special: "Reduces crew's current HP by 80%, deals 5x the amount of HP subtracted in typeless damage to all enemies, reduces damage received by 90% for 1 turn", + specialName: "Right Angle Flying Bird: Bone Phoenix", + captain: "Boosts ATK of Slasher characters by 1.5x, recovers 1.2x character's RCV in HP at the end of each turn" + }, + 724: { + special: "Reduces crew's current HP by 80%, deals 5x the amount of HP subtracted in typeless damage to all enemies, reduces damage received by 90% for 1 turn", + specialName: "Right Angle Flying Bird: Bone Phoenix", + captain: "Boosts ATK of Slasher characters by 1.75x, recovers 1.5x character's RCV in HP at the end of each turn" + }, + 725: { + special: "Changes [TND] orbs into [QCK] orbs, switches orbs between slots twice", + specialName: "Peacock String Slasher", + captain: "Recovers 1,000 HP at the end of each turn" + }, + 726: { + special: "Changes [TND] orbs into [QCK] orbs, switches orbs between slots twice", + specialName: "Peacock String Slasher", + captain: "Recovers 2,000 HP at the end of each turn" + }, + 727: { + special: "Deals 10x character's ATK in DEX damage to all enemies, reduces the defense of all enemies by 50% for 1 turn", + specialName: "Gum-Gum Gatling", + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of Free Spirit and Fighter characters by 1.75x" + }, + 728: { + special: "Randomizes all orbs, recovers 6x character's RCV in HP at the end of each turn for 3 turns", + specialName: "Sheep Cloud Relaxing Bubbles", + captain: "Boosts ATK and RCV of DEX characters by 1.2x, slightly boosts chances of getting [DEX] orbs" + }, + 729: { + special: "Randomizes all orbs, recovers 6x character's RCV in HP at the end of each turn for 3 turns", + specialName: "Sheep Cloud Relaxing Bubbles", + captain: "Boosts ATK and RCV of DEX characters by 1.2x, boosts chances of getting [DEX] orbs" + }, + 730: { + special: "Reduces crew's current HP by 99%, deals 2x the amount of HP subtracted in INT damage to all enemies, boosts ATK of INT characters by 1.5x for 1 turn", + specialName: "Rankyaku - Lupus Fall", + captain: "Boosts ATK and HP of INT characters by 1.2x, deals 9 HP as fixed damage to all enemies at the end of each turn", + captainNotes: "#{fixed}" + }, + 731: { + special: "Reduces crew's current HP by 99%, deals 2x the amount of HP subtracted in INT damage to all enemies, boosts ATK of INT characters by 1.5x for 1 turn", + specialName: "Rankyaku - Lupus Fall", + captain: "Boosts ATK and HP of INT characters by 1.5x, deals 9 HP as fixed damage to all enemies at the end of each turn", + captainNotes: "#{fixed}" + }, + 732: { + special: "Deals 13x character's ATK in STR damage to one enemy, reduces damage received by 50% for 1 turn", + specialName: "Tekkai Dama", + captain: "Boosts ATK of STR characters by 1.5x, reduces damage received by 10%" + }, + 733: { + special: "Deals 13x character's ATK in STR damage to one enemy, reduces damage received by 50% for 1 turn", + specialName: "Tekkai Dama", + captain: "Boosts ATK of STR characters by 1.5x, reduces damage received by 20%" + }, + 734: { + special: "For 1 turn, boosts the amount healed by RCV orbs by 1.5x, then 2x, then 2.5x from the third crew member onward", + specialName: "Life Return - Digestion, Absorption", + captain: "Boosts ATK and RCV of PSY characters by 1.2x" + }, + 735: { + special: "For 1 turn, boosts the amount healed by RCV orbs by 1.5x, then 2x, then 2.5x from the third crew member onward", + specialName: "Life Return - Digestion, Absorption", + captain: "Boosts ATK and RCV of PSY characters by 1.5x" + }, + 736: { + special: "Deals 20x character's ATK in STR damage to all enemies, changes [QCK] orbs into [STR] orbs", + specialName: "Fierce Smash", + captain: "Boosts ATK of Slasher characters by 2.5x if HP is above 50% at the start of the turn" + }, + 737: { + special: "Changes [RCV] orbs into [QCK] orbs, changes adjacent orbs into [QCK] orbs", + specialName: "Shigan - Bachi", + captain: "Boosts ATK of Fighter characters by 2.75x if HP is below 30% at the start of the turn" + }, + 738: { + special: "Deals 200x character's ATK in INT damage to one enemy", + specialName: "Ivory Rush", + captain: "Boosts ATK of characters with cost 21 or more by 2x" + }, + 739: { + special: "Reduces Bind duration by 5 turns, randomizes all orbs", + specialName: "Coup de Boo", + captain: "Boosts ATK of Free Spirit characters by 2x" + }, + 740: { + special: "Deals 10x character's ATK in QCK damage to all enemies, boosts ATK against enemies with increased defense by 1.3x for 2 turns", + specialName: "Rankyaku - Sen", + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight" + }, + 741: { + special: "Deals 10x character's ATK in QCK damage to all enemies, boosts ATK against enemies with increased defense by 1.3x for 2 turns", + specialName: "Rankyaku - Sen", + captain: "Reduces cooldown of all specials by 3 turns at the start of the fight" + }, + 742: { + special: "Amplifies the effect of orbs by 1.25x for 2 turns, reduces the defense of all enemies by 80% for 2 turns", + specialNotes: "#{orb : 1.25x}", + specialName: "Ramen Beam", + captain: "Boosts ATK and RCV of Free Spirit characters by 1.2x" + }, + 743: { + special: "Amplifies the effect of orbs by 1.25x for 2 turns, reduces the defense of all enemies by 80% for 2 turns", + specialNotes: "#{orb : 1.25x}", + specialName: "Ramen Beam", + captain: "Boosts ATK and RCV of Free Spirit characters by 1.5x" + }, + 744: { + special: "Reduces damage received by 50% for 3 turns", + specialName: "Flame Fence", + captain: "Boosts ATK of Free Spirit characters by 2x" + }, + 745: { + special: "Reduces damage received by 50% for 3 turns", + specialName: "Flame Fence", + captain: "Boosts ATK of Free Spirit characters by 2.5x" + }, + 746: { + special: "Deals 10x character's ATK in QCK damage to all enemies, protects from defeat as long as HP is above 50% for 1 turn", + specialName: "Megalo Assault!", + specialNotes: "#{zombie}", + captain: "Protects from defeat as long as HP is above 30%", + captainNotes: "#{zombie}" + }, + 747: { + special: "Deals 35x character's ATK in STR damage to one enemy, boosts chances of getting matching orbs for 3 turns", + specialName: "Rokuougan", + captain: "Boosts ATK of Powerhouse characters by 3x if they have a matching orb, by 2.5x otherwise, reduces crew's RCV to 0" + }, + 748: { + special: "Deals 35x character's ATK in STR damage to one enemy, boosts chances of getting matching orbs for 3 turns", + specialName: "Rokuougan", + captain: "Boosts ATK of Powerhouse characters by 3x if they have a matching orb, by 2.5x otherwise, reduces crew's RCV to 0", + limit: "This character has a limit break path", + }, + 749: { + special: "Deals random DEX damage to all enemies, randomizes all orbs", + specialName: "Tempest Kick: Sky Slicer", + specialNotes: "#{random : 10,000 : 90,000}", + captain: "Boosts ATK of DEX characters by 1.5x, boosts damage of DEX specials by 1.5x", + captainNotes: "#{noFixedPerc}" + }, + 750: { + special: "Deals random DEX damage to all enemies, randomizes all orbs", + specialName: "Tempest Kick: Sky Slicer", + specialNotes: "#{random : 10,000 : 90,000}", + captain: "Boosts ATK of DEX characters by 2x, boosts damage of DEX specials by 2x", + captainNotes: "#{noFixedPerc}", + limit: "This character has a limit break path", + }, + 751: { + special: "Reduces damage received in the next turn by 50% if the special is activated with more than 50% health remaining, by 80% if activated with less than 50% but more than 10% health remaining, by 100% if activated with less than 10% health remaining", + specialName: "Sheep Cloud Tidal Wave", + captain: "Boosts ATK and RCV of Cerebral characters by 1.5x" + }, + 752: { + special: "Reduces damage received in the next turn by 50% if the special is activated with more than 50% health remaining, by 80% if activated with less than 50% but more than 10% health remaining, by 100% if activated with less than 10% health remaining", + specialName: "Sheep Cloud Tidal Wave", + captain: "Boosts ATK of Cerebral characters by 2.25x and their RCV by 1.5x" + }, + 753: { + special: "Deals 15x character's ATK in QCK damage to one enemy, amplifies the effect of orbs by 1.75x for 1 turn", + specialNotes: "#{orb : 1.75x}", + specialName: "Moonlight Ten Finger Pistol", + captain: "Boosts ATK of Powerhouse characters by 2x" + }, + 754: { + special: "Deals 15x character's ATK in QCK damage to one enemy, amplifies the effect of orbs by 1.75x for 1 turn", + specialNotes: "#{orb : 1.75x}", + specialName: "Moonlight Ten Finger Pistol", + captain: "Boosts ATK of Powerhouse characters by 2.5x", + limit: "This character has a limit break path", + }, + 755: { + special: "Reduces damage received by 50% for 1 turn, boosts ATK of Powerhouse characters by 1.75x for 1 turn", + specialName: "Tekkai - Rin", + captain: "Boosts ATK of INT characters by 1.5x, reduces damage received from PSY enemies by 20%" + }, + 756: { + special: "Reduces damage received by 50% for 1 turn, boosts ATK of Powerhouse characters by 1.75x for 1 turn", + specialName: "Tekkai - Rin", + captain: "Boosts ATK of INT characters by 2x, reduces damage received from PSY enemies by 30%", + limit: "This character has a limit break path", + }, + 757: { + special: "Changes [DEX] and [QCK] orbs into [PSY] orbs", + specialName: "Solid Beast Supreme Technique: Owl Strike", + captain: "Boosts ATK of PSY characters by 2x" + }, + 758: { + special: "Changes [DEX] and [QCK] orbs into [PSY] orbs", + specialName: "Solid Beast Supreme Technique: Owl Strike", + captain: "Boosts ATK of PSY characters by 2x, recovers 3x character's RCV in HP at the end of each turn" + }, + 759: { + special: "Switches orbs between slots 3 times, locks all orbs for 1 turn", + specialName: "Life Return: Shishi Finger Pistol", + captain: "Boosts ATK of STR characters by 2.5x if HP is below 30% at the start of the turn" + }, + 760: { + special: "Switches orbs between slots 3 times, locks all orbs for 1 turn", + specialName: "Life Return: Shishi Finger Pistol", + captain: "Boosts ATK of STR characters by 3x if HP is below 30% at the start of the turn", + limit: "This character has a limit break path", + }, + 761: { + special: "Deals 15x character's ATK in DEX damage to one enemy, boosts ATK of all characters by 1.2x for 1 turn", + specialName: "Gum-Gum Monster Pistol", + captain: "Boosts ATK of Fighter characters by 2x" + }, + 762: { + special: "Boosts ATK of PSY characters by 1.75x for 1 turn", + specialName: "Impact Beast", + captain: "Boosts ATK and RCV of PSY characters by 1.5x" + }, + 763: { + special: "Changes own orb into [STR], switches orbs between slots once", + specialName: "Franken-Franky Centaur", + captain: "Boosts ATK of STR characters by 2x" + }, + 764: { + special: "Recovers 3,000 HP", + specialName: "Cat Burglar Trick", + captain: "Boosts ATK and RCV of Striker characters by 1.5x" + }, + 765: { + special: "Reduces Despair duration by 3 turns", + specialName: "Scope Magic", + captain: "Recovers 2x character's RCV in HP at the end of each turn" + }, + 766: { + special: "Deals 7x character's ATK in QCK damage to all enemies, delays all enemies for 1 turn", + specialName: "108 Pound Phoenix: Reaper", + captain: "Boosts ATK of QCK characters by 2x" + }, + 767: { + special: { + "japan": "Changes top row orbs into [DEX] orbs, removes blindness", + "global": "Changes top row orbs into [DEX] orbs, reduces Despair duration by 1 turn" + }, + specialName: "Ojos Fleur: Thriller", + captain: "Boosts ATK and RCV of DEX characters by 1.5x" + }, + 768: { + special: "Recovers 15x character's RCV in HP, changes [TND] orbs into [RCV] orbs", + specialName: "Hot Rock Stew: Party", + captain: "Boosts ATK of PSY characters by 2x" + }, + 769: { + special: "Recovers 4,343 HP, Poisons all enemies", + specialNotes: "#{poison}", + specialName: "Lullaby Parry: Horror", + captain: "Boosts ATK and RCV of INT characters by 1.5x" + }, + 770: { + special: "Deals 15x character's ATK in STR damage to one enemy, boosts ATK against delayed enemies by 1.3x for 2 turns", + specialName: "Shigan: Convergence", + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of STR characters by 2x" + }, + 771: { + special: "Deals 15x character's ATK in PSY damage to one enemy, boosts ATK of Cerebral characters by 1.75x for 1 turn", + specialName: "Moonwalk: Air Walking", + captain: "Boosts ATK of Cerebral characters by 2.5x" + }, + 772: { + special: "Cuts the current HP of each enemy by 10%, changes [PSY] and [INT] orbs into [DEX] orbs", + specialName: "Eight-Sword Style: Brave Warrior's Continuous Attack", + captain: "Boosts ATK of Slasher characters by 2x, reduces damage received from QCK enemies by 20%" + }, + 773: { + special: "Reduces any damage received above 3,000 HP by 80% for 1 turn", + specialNotes: "The exact formula for the damage received is: 3000 + ((total damage) - 3000) * 0.2", + specialName: "Rust-Rust Fruit", + captain: "Reduces damage received by 20%" + }, + 774: { + special: "Randomly changes [TND], [RCV], [EMPTY], [BLOCK] and [BOMB] orbs into either [STR], [DEX], [QCK], [PSY] or [INT] orbs, switches orbs between slots 3 times", + specialName: "Berry-Berry Fruit", + captain: "Boosts ATK of Free Spirit characters by 2x" + }, + 775: { + special: "Deals several times the character's ATK in PSY damage to one enemy", + specialNotes: "#{specialProportional : lower : 125 * ( 1 - (remaining HP) / (total HP) )}", + specialName: "Angry Headbutt", + captain: "Boosts ATK and HP of Cerebral characters by 1.5x" + }, + 776: { + specialName: "Boisterous Lucky Shot!!", + special: "Recovers 5,000 HP, deals 15x character's ATK in PSY damage to one enemy, seals himself for 3 turns", + captain: "Boosts ATK and RCV of PSY characters by 1.25x" + }, + 777: { + special: "Recovers 5,000 HP, deals 15x character's ATK in PSY damage to one enemy, seals himself for 3 turns", + specialName: "Boisterous Lucky Shot!!", + captain: "Boosts ATK and RCV of PSY characters by 1.75x" + }, + 778: { + special: "Deals several times the character's ATK in QCK damage to one enemy, changes own orb into [QCK]", + specialNotes: "#{specialProportional : lower : 125 * ( 1 - (remaining HP) / (total HP) )}", + specialName: "Undefeated Sword Technique", + captain: "Reduces damage received by 20%" + }, + 779: { + special: "Deals several times the character's ATK in QCK damage to one enemy, changes own orb into [QCK]", + specialNotes: "#{specialProportional : lower : 125 * ( 1 - (remaining HP) / (total HP) )}", + specialName: "Undefeated Sword Technique", + captain: "Reduces damage received by 25%" + }, + 780: { + special: "Boosts own ATK by a variable factor for 1 turn", + specialNotes: "The exact multiplier used is chosen based on the crew's current HP at the time the special is activated: above 50% HP, the multiplier used is 1.5x; between 20% HP and 50% HP, it's 1.75x; below 20% HP, it's 2x.", + specialName: "Precept Deification", + captain: "Boosts ATK of all characters by 2x if HP is below 30% at the start of the turn" + }, + 781: { + special: "Boosts own ATK by a variable factor for 1 turn", + specialNotes: "The exact multiplier used is chosen based on the crew's current HP at the time the special is activated: above 50% HP, the multiplier used is 1.5x; between 20% HP and 50% HP, it's 1.75x; below 20% HP, it's 2x.", + specialName: "Precept Deification", + captain: "Boosts ATK of all characters by 2.5x if HP is below 30% at the start of the turn", + limit: "This character has a limit break path", + }, + 782: { + special: "Delays all enemies for 1 turn, recovers a small random amount of HP", + specialName: "Smile of a Natural Beauty", + specialNotes: "#{randomHeal : ??? : ???}", + captain: "Boosts RCV of Slasher characters by 1.5x" + }, + 783: { + special: "Delays all enemies for 1 turn, recovers a small random amount of HP", + specialName: "Smile of a Natural Beauty", + specialNotes: "#{randomHeal : ??? : ???}", + captain: "Boosts ATK of Slasher characters by 2x and their RCV by 1.5x" + }, + 784: { + special: "Reduces Despair duration by 2 turns, removes blindness", + specialName: "Yelling at Lascivious Young Women" + }, + 785: { + special: "Reduces Despair duration by 2 turns, removes blindness", + specialName: "Yelling at Lascivious Young Women", + captain: "Reduces damage received by 20%" + }, + 786: { + special: "Seals himself for 10 turns, delays all enemies for 1 turn, reduces damage received by 50% for 4 turns", + specialName: "The Resolve to Face Death! \"Open Mind\"" + }, + 787: { + special: "Seals himself for 10 turns, delays all enemies for 1 turn, reduces damage received by 50% for 4 turns", + specialName: "The Resolve to Face Death! \"Open Mind\"", + captain: "Reduces damage received by 50%, reduces crew's current HP by 10% at the end of each turn" + }, + 788: { + special: "Following the activation of the special, if every unit scores a Perfect hit, boosts ATK of Slasher characters by 1.75x in the following turn", + specialName: "Real Sword Fight with a Girl Swordsman" + }, + 789: { + special: "Following the activation of the special, if every unit scores a Perfect hit, boosts ATK of Slasher characters by 1.75x in the following turn", + specialName: "Real Sword Fight with a Girl Swordsman", + captain: "Boosts ATK of Slasher characters by 1.5x" + }, + 790: { + special: "Deals 3x character's ATK in QCK damage to one enemy, boosts ATK of STR, DEX and QCK characters by 1.2x for 3 turns", + specialName: "March!! Usopp Pirates" + }, + 791: { + special: "Deals 3x character's ATK in QCK damage to one enemy, boosts ATK of STR, DEX and QCK characters by 1.2x for 3 turns", + specialName: "March!! Usopp Pirates", + captain: "Boosts ATK, HP and RCV of STR, DEX and QCK characters by 1.25x" + }, + 792: { + special: "Randomly changes all orbs into either [STR], [QCK], [DEX], [PSY] or [INT] orbs, switches orbs between slots twice, locks all orbs for 1 turn", + specialName: "The Entushiasm to Keep Skilled Workers in Line" + }, + 793: { + special: "Randomly changes all orbs into either [STR], [QCK], [DEX], [PSY] or [INT] orbs, switches orbs between slots twice, locks all orbs for 1 turn", + specialName: "The Entushiasm to Keep Skilled Workers in Line", + captain: "Boosts ATK and RCV of Cerebral characters by 1.5x" + }, + 794: { + special: "Deals 10 hits of random INT damage to random enemies, delays all enemies for 1 turn", + specialNotes: "#{randomHits : 10}
    #{random : 1,000 : 30,000 : for each hit}", + specialName: "Gum-Gum Storm", + captain: "Boosts ATK of Powerhouse characters by 3x, reduces crew's current HP by 10% at the end of each turn, reduces his own ATK multiplier by 0.1x at the end of each turn", + captainNotes: "His ATK multiplier will be 3.0x on the first turn, 2.9x on the second, 2.8x on the third and so on. The reduction stops once the multiplier is 1.0x. The multiplier affects all Powerhouse characters. You will not die to the HP reduction" + }, + 795: { + special: "Deals 10 hits of random INT damage to random enemies, delays all enemies for 1 turn", + specialNotes: "#{randomHits : 10}
    #{random : 1,000 : 30,000 : for each hit}", + specialName: "Gum-Gum Storm", + captain: "Boosts ATK of Powerhouse characters by 3.5x, reduces crew's current HP by 10% at the end of each turn, reduces his own ATK multiplier by 0.1x at the end of each turn", + captainNotes: "His ATK multiplier will be 3.5x on the first turn, 3.4x on the second, 3.3x on the third and so on. The reduction stops once the multiplier is 1.0x. The multiplier affects all Powerhouse characters. You will not die to the HP reduction" + }, + 796: { + special: "Slightly boosts chances of getting matching orbs for 3 turns, boosts own ATK by 1.75x for 1 turn", + specialName: "Peto-Peto Fruit, The Greatest Power", + captain: "Boosts ATK of Cerebral characters by 2x" + }, + 797: { + special: "Slightly boosts chances of getting matching orbs for 3 turns, boosts own ATK by 1.75x for 1 turn", + specialName: "Peto-Peto Fruit, The Greatest Power", + captain: "Boosts ATK of Cerebral and Powerhouse characters by 2x" + }, + 798: { + special: "Removes Poison, following the activation of the special, if every unit scores a Perfect hit, boosts ATK of Fighter characters by 1.75x in the following turn", + specialName: "Dugong Secret! Fist of the Black Fin", + captain: "Boosts ATK by 2.5x after scoring 3 Perfects in a row" + }, + 799: { + special: "Randomizes all orbs, recovers 9x character's RCV in HP", + specialName: "Sea Animal Healing" + }, + 800: { + special: "Randomly changes all orbs into either [STR], [DEX] or [QCK] orbs", + specialName: "Octopus Tentacle Blow" + }, + 801: { + special: "Randomly changes [STR], [QCK], [DEX], [INT], [BOMB] and [BLOCK] orbs into either [STR], [QCK], [DEX], [PSY] or [INT] orbs, changes [TND] and [RCV] orbs into [PSY] orbs", + specialName: "Clone-Clone Montage", + captain: "Boosts ATK of PSY characters by 2x" + }, + 802: { + special: "Randomly changes [STR], [QCK], [DEX], [INT], [BOMB] and [BLOCK] orbs into either [STR], [QCK], [DEX], [PSY] or [INT] orbs, changes [TND] and [RCV] orbs into [PSY] orbs", + specialName: "Clone-Clone Montage", + captain: "Boosts ATK of PSY characters by 2.5x" + }, + 803: { + special: "Deals 8 hits of random DEX damage to random enemies, boosts ATK of all characters by 1.1x for 3 turns", + specialNotes: "#{randomHits : 8}", + specialName: "Black Spear Formation: All-Out Attack!", + captain: "Boosts ATK and RCV of DEX characters by 1.2x" + }, + 804: { + special: "Deals 8 hits of random DEX damage to random enemies, boosts ATK of all characters by 1.1x for 3 turns", + specialNotes: "#{randomHits : 8}", + specialName: "Black Spear Formation: All-Out Attack!", + captain: "Boosts ATK and RCV of DEX characters by 1.5x, deals 1x character's ATK in DEX damage to all enemies at the end of each turn" + }, + 805: { + special: "Reduces crew's current HP by 20%, deals 10x the amount of HP subtracted in INT damage to one enemy, amplifies the effect of orbs by 1.75x for 1 turn", + specialName: "White Vine", + captain: "Boosts ATK of Striker characters by 2x", + specialNotes: "#{orb : 1.75x}" + }, + 806: { + special: "Reduces crew's current HP by 20%, deals 10x the amount of HP subtracted in INT damage to one enemy, amplifies the effect of orbs by 1.75x for 1 turn", + specialName: "White Vine", + captain: "Boosts ATK of Striker characters by 2x, reduces damage received up to 30% depending on the crew's current HP", + specialNotes: "#{orb : 1.75x}" + }, + 807: { + captain: "Boosts ATK and RCV of Cerebral characters by 1.5x", + specialName: "Thunder Charge: Swing Arm", + special: "Deals 15x character's ATK in PSY damage to one enemy, boosts ATK against enemies with reduced defense by 1.3x for 3 turns" + }, + 808: { + captain: "Boosts ATK and RCV of Cerebral characters by 1.5x, recovers 2x character's RCV in HP at the end of each turn", + specialName: "Thunder Charge: Swing Arm", + special: "Deals 15x character's ATK in PSY damage to one enemy, boosts ATK against enemies with reduced defense by 1.3x for 3 turns" + }, + 809: { + captain: "Boosts ATK and RCV of Powerhouse characters by 1.5x", + specialName: "Lola's Attack Chance", + special: "Reduces the defense of all enemies by 80% for 1 turn, amplifies the effect of orbs by 1.5x for 1 turn", + specialNotes: "#{orb : 1.5x}" + }, + 810: { + captain: "Boosts ATK of Powerhouse characters by 2x and their RCV by 1.5x, reduces crew's current HP by 10% at the end of each turn", + specialName: "Lola's Attack Chance", + special: "Reduces the defense of all enemies by 80% for 1 turn, amplifies the effect of orbs by 1.5x for 1 turn", + specialNotes: "#{orb : 1.5x}" + }, + 811: { + specialName: "Birdbrain Present", + special: "Changes own orb into DEX, switches orbs between slots once" + }, + 812: { + specialName: "Hell Howl", + special: "Sharply reduces the defense of all enemies for 1 turn" + }, + 813: { + specialName: "Sticky Spider Net", + special: "Delays all enemies for 1 turn, amplifies the effect of orbs by 1.25x for 1 turn", + specialNotes: "#{orb : 1.25x}" + }, + 814: { + specialName: "Carpet Scratch", + special: "Deals 13x character's ATK in DEX damage to a single enemy, changes captain's orb into [TND]" + }, + 815: { + captain: "Boosts ATK by 2.5x following a chain of STR > INT > DEX attacks no lower than Good", + specialName: "Brick Bat", + special: "Deals 10 hits of 5,000 fixed damage to random enemies", + specialNotes: "#{fixed} #{randomHits : 10}" + }, + 816: { + captain: "Boosts ATK by 2.75x following a chain of STR > INT > DEX attacks no lower than Good", + specialName: "Brick Bat", + special: "Deals 10 hits of 5,000 fixed damage to random enemies", + specialNotes: "#{fixed} #{randomHits : 10}" + }, + 817: { + specialName: "[PSY] Slot Change [STR]", + special: "Changes [PSY] orbs into [STR] orbs" + }, + 818: { + specialName: "Quick Change", + special: "Switches orbs between slots once" + }, + 819: { + specialName: "Hyper Burst", + special: "Deals 13x character's ATK in character's type damage to all enemies" + }, + 820: { + specialName: "[TND] Slot Change [INT]", + special: "Changes [TND] orbs into [INT] orbs" + }, + 821: { + specialName: "Slot Shuffle", + special: "Randomizes all orbs" + }, + 822: { + specialName: "Patch Job", + special: "Boosts RCV of all characters by 100 for 3 turns" + }, + 823: { + specialName: "Slot Rate Up [INT]", + special: "Slightly boosts chances of getting [INT] orbs for 3 turns" + }, + 824: { + specialName: "Auto Repair", + special: "Recovers 3x character's RCV in HP at the end of each turn for 5 turns" + }, + 825: { + captain: "Boosts ATK and HP of STR characters by 1.5x", + specialName: "Energy of the Ancient Knight", + special: "Boosts ATK of STR characters by 200 for 1 turn" + }, + 826: { + captain: "Boosts ATK and HP of DEX characters by 1.5x", + specialName: "Weakness of the Ancient Knight", + special: "Delays all enemies for 1 turn, reduces the ATK of all characters by 80% for 2 turns" + }, + 827: { + captain: "Boosts ATK and HP of QCK characters by 1.5x", + specialName: "Poison of the Ancient Knight", + special: "Boosts ATK against Poisoned and Strongly Poisoned enemies by 1.05x for 999 turns" + }, + 828: { + specialName: "Surprise Stab", + special: "Deals 3x character's ATK in [PSY] damage to one enemy, Boosts ATK of Slasher and Driven characters by 1.75x for 1 turn if used below 20% HP", + captain: "Protects from defeat as long as HP is above 50%", + captainNotes: "#{zombie}" + }, + 829: { + specialName: "Surprise Stab", + special: "Deals 3x character's ATK in [PSY] damage to one enemy, Boosts ATK of Slasher and Driven characters by 1.75x for 1 turn if used below 20% HP", + captain: "Protects from defeat as long as HP is above 30%", + captainNotes: "#{zombie}" + }, + 830: { + captain: "Boosts ATK of Cerebral and Striker characters by 1.75x, deals 2 times the damage received in the previous turn in DEX damage to all enemies at the end of each turn", + specialName: "Karma Conviction", + special: "Changes the orbs in the top row into [STR] orbs, changes the orbs in the middle row into [DEX] orbs, changes the orbs in the bottom row into [QCK] orbs" + }, + 831: { + captain: "Boosts ATK of Cerebral and Striker characters by 2x, deals 5 times the damage received in the previous turn in DEX damage to all enemies at the end of each turn", + specialName: "Karma Conviction", + special: "Changes the orbs in the top row into [STR] orbs, changes the orbs in the middle row into [DEX] orbs, changes the orbs in the bottom row into [QCK] orbs" + }, + 832: { + captain: "Boosts ATK of Free Spirit characters proportionally to the crew's current HP, reduces crew's current HP by 10% at the end of each turn", + specialName: "Burn Bazooka", + special: "Boosts ATK of Free Spirit characters by 1.5x for 1 turn, deals 15x character's ATK in STR damage to all enemies", + captainNotes: "#{captainProportional : lower : 1 + 1.5 * (1 - (remaining HP) / (total HP)) : 1 : 2.5}" + }, + 833: { + captain: "Boosts ATK of Free Spirit characters proportionally to the crew's current HP, reduces crew's current HP by 10% at the end of each turn", + specialName: "Burn Bazooka", + special: "Boosts ATK of Free Spirit characters by 1.5x for 1 turn, deals 15x character's ATK in STR damage to all enemies", + captainNotes: "#{captainProportional : lower : 1 + 1.75 * (1 - (remaining HP) / (total HP)) : 1 : 2.75}" + }, + 834: { + captain: "Boosts ATK and RCV of Shooter characters by 1.5x", + specialName: "Yellow Gun & Gero Gero Gun", + special: "Changes own orb into [QCK] and the captain's orb into [PSY]" + }, + 835: { + captain: "Boosts ATK and HP of Cerebral characters by 2x", + specialName: "Thrust Pad Cannon", + special: "Changes [RCV], [TND], [EMPTY], [BLOCK] and [BOMB] orbs into Matching orbs, amplifies the effect of orbs by 1.75x for 1 turn", + specialNotes: "#{orb : 1.75x}" + }, + 836: { + captain: "Boosts ATK and HP of Cerebral characters by 2x, deals 5 times the damage received in the previous turn in STR damage to all enemies at the end of each turn", + specialName: "Thrust Pad Cannon", + special: "Changes [RCV], [TND], [EMPTY], [BLOCK] and [BOMB] orbs into Matching orbs, amplifies the effect of orbs by 1.75x for 1 turn", + specialNotes: "#{orb : 1.75x}" + }, + 837: { + captain: "Boosts ATK of Driven characters by 2x", + specialName: "Gas Robe", + special: "Poisons all enemies, boosts ATK of Driven characters by 1.75x for 2 turns", + specialNotes: "#{poison}" + }, + 838: { + captain: "Boosts ATK of Driven characters by 2.5x", + specialName: "Gas Robe", + special: "Poisons all enemies, boosts ATK of Driven characters by 1.75x for 2 turns" + }, + 839: { + captain: "Boosts ATK of Striker characters by 2x", + specialName: "Demon Bamboo", + special: "Changes own orb into [INT], boosts own ATK by 2x for 1 turn, deals 15x character's ATK in INT damage to one enemy" + }, + 840: { + captain: "Boosts ATK of Striker characters by 2.5x", + specialName: "Demon Bamboo", + special: "Changes own orb into [INT], boosts own ATK by 2x for 1 turn, deals 15x character's ATK in INT damage to one enemy", + limit: [ + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Aquire Potential 1: [PSY] Damage Reduction" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Aquire new Captain Ability: Boosts ATK of Striker characters by 2.5x and reduces damage received by 7%" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base HP by 50" }, + { "description": "Aquire Sailor Ability 1: If Vergo has a [INT] orb and you hit a Perfect with him, keep his [INT] orb for the next turn" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base RCV by 40" }, + { "description": "Reduce base Special Cooldown by 2 turns" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Enrage" }, + ], + potential: [ + { + "Name": "[PSY] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [PSY] characters by 1%", + "Level 2: Reduce damage taken from [PSY] characters by ?%", + "Level 3: Reduce damage taken from [PSY] characters by ?%", + "Level 4: Reduce damage taken from [PSY] characters by ?%", + "Level 5: Reduce damage taken from [PSY] characters by ?%" + ] + }, + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 30", + "Level 2: Boosts base ATK by ??", + "Level 3: Boosts base ATK by ??", + "Level 4: Boosts base ATK by ??", + "Level 5: Boosts base ATK by ??" + ] + }, + ] + }, + 841: { + captain: "Recovers 3x character's RCV in HP at the end of each turn, deals 3x character's ATK in PSY damage to all enemies at the end of each turn", + specialName: "Snow Rabbit", + special: "Delays all enemies for 1 turn, boosts ATK against delayed enemies by 1.25x for 2 turns" + }, + 842: { + captain: "Recovers 5x character's RCV in HP at the end of each turn, deals 5x character's ATK in PSY damage to all enemies at the end of each turn", + specialName: "Snow Rabbit", + special: "Delays all enemies for 1 turn, boosts ATK against delayed enemies by 1.25x for 2 turns" + }, + 843: { + captain: "Boosts ATK of Slasher, Striker and Shooter characters by 1.5x", + specialName: "Arms-Morphosis: Missile Girl", + special: "Deals 15x character's ATK in STR damage to all enemies, boosts ATK of Shooter characters by 1.5x for 1 turn. If during that turn every unit scores a Perfect hit, boosts ATK of Shooter, Striker and Slasher characters by 1.5x in the following turn." + }, + 844: { + captain: "Boosts ATK of Slasher, Striker and Shooter characters by 2x", + specialName: "Arms-Morphosis: Missile Girl", + special: "Deals 15x character's ATK in STR damage to all enemies, boosts ATK of Shooter characters by 1.5x for 1 turn. If during that turn every unit scores a Perfect hit, boosts ATK of Shooter, Striker and Slasher characters by 1.5x in the following turn." + }, + 845: { + captain: "Boosts ATK of all characters by 1.5x after the 11th hit in the chain, by 2.5x after the 22nd hit", + specialName: "Gust: Matasaburo", + special: "Randomizes all orbs and changes own orb into [QCK]" + }, + 846: { + captain: "Boosts ATK of all characters by 1.5x after the 11th hit in the chain, by 2.5x after the 22nd hit, by 2.75x after the 30th hit, by 3.5x after the 40th hit", + specialName: "Gust: Matasaburo", + special: "Randomizes all orbs and changes own orb into [QCK]", + limit: [ + { "description": "Boosts base HP by 10" }, + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base HP by 70" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK of all characters by 30" }, + { "description": "Boosts base HP by 80" }, + { "description": "Boosts base ATK by 100" }, + { "description": "Aquire Sailor Ability 2: Boosts this character's attack against [DEX] characters by 2x" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 10% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 15% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 20% chance to deal 10% of this character's attack in extra damage" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 1 turn on this character", + "Level 2: Reduces Slot Bind duration by 2 turns on this character", + "Level 3: Reduces Slot Bind duration by 3 turns on this character", + "Level 4: Reduces Slot Bind duration by 4 turns on this character", + "Level 5: Reduces Slot Bind duration by 5 turns on this character" + ] + }, + ] + }, + 847: { + captain: "Boosts ATK of all characters by 1.5x if HP is below 30% at the start of the turn", + specialName: "Sturdy Boat: Launch", + special: "Reduces Despair duration by 5 turns, boosts ATK of all characters by 5% for 3 turns, reduces damage received by 10% for 3 turns, amplifies the effect of orbs by 1.15x for 3 turns, recovers 2x character's RCV in HP at the end of each turn for 3 turns", + specialNotes: "#{orb : 1.15x}" + }, + 848: { + captain: "Boosts ATK of all characters by 2x if HP is below 30% at the start of the turn", + specialName: "Sturdy Boat: Launch", + special: "Reduces Despair duration by 5 turns, boosts ATK of all characters by 5% for 3 turns, reduces damage received by 10% for 3 turns, amplifies the effect of orbs by 1.15x for 3 turns, recovers 2x character's RCV in HP at the end of each turn for 3 turns", + specialNotes: "#{orb : 1.15x}" + }, + 849: { + captain: "Boosts ATK of Shooter characters by 1.75x", + specialName: "Battle Franky 9", + special: "Deals 5 hits of random STR damage to random enemies, reduces the defense of all enemies by 50% for 2 turns" + }, + 850: { + captain: "Boosts ATK of Striker and Cerebral characters by 1.5x", + specialName: "First-class Assistant of the Passionate Worker", + special: "Changes the top right orb into [DEX], the middle right orb into [STR] and the bottom right orb into [QCK], seals himself for 3 turns" + }, + 851: { + captain: "Boosts ATK of Driven characters by 1.5x", + specialName: "Snow Country Speciality: Snow Powder Makeup", + special: "Deals 20x character's ATK in character's type damage to one enemy, locks all orbs for 1 turn" + }, + 852: { + captain: "Boosts ATK of Driven characters by 2x", + specialName: "Snow Country Speciality: Snow Powder Makeup", + special: "Deals 20x character's ATK in character's type damage to one enemy, locks all orbs for 1 turn" + }, + 853: { + specialName: "Robson: Serious Mode", + special: "Following the activation of the special, if every unit scores a Perfect hit, boosts ATK of Powerhouse and Fighter characters by 1.2x for 3 turns" + }, + 854: { + captain: "Boosts ATK of DEX chracters by 1.5x, reduces damage received by 10%", + specialName: "Guard Point: Winter Coat", + special: "Reduces damage received by 50% for 3 turns, slightly boosts chances of getting [DEX] orbs for 3 turns" + }, + 855: { + captain: "Boosts ATK of Slasher characters by 2x", + specialName: "Shambles: Holiday Toast", + special: "Changes captain's orb into [RCV], recovers 15x character's RCV in HP" + }, + 856: { + captain: "Boosts ATK of Slasher characters by 2.5x", + specialName: "Shambles: Holiday Toast", + special: "Changes captain's orb into [RCV], recovers 15x character's RCV in HP" + }, + 857: { + captain: "Boosts ATK of PSY characters by 2x", + specialName: "Bonney's Holiday Feast", + special: "Changes adjacent orbs into [RCV] orbs, boosts RCV of PSY characters by 1.5x for 1 turn" + }, + 858: { + captain: "Boosts ATK and RCV of PSY characters by 2x", + specialName: "Bonney's Holiday Feast", + special: "Changes adjacent orbs into [RCV] orbs, boosts RCV of PSY characters by 1.5x for 1 turn" + }, + 859: { + captain: "Boosts ATK of Driven characters by 1.5x, reduces damage received up to 10% depending on the crew's current HP", + specialName: "Pleading at the Risk of One's Life", + special: "Changes adjacent orbs into [RCV] orbs; if the special is activated with more than 50% health remaining, protects from defeat for 1 turn", + specialNotes: "#{zombie}" + }, + 860: { + captain: "Boosts ATK of Driven characters by 2x, reduces damage received up to 30% depending on the crew's current HP", + specialName: "Pleading at the Risk of One's Life", + special: "Changes adjacent orbs into [RCV] orbs; if the special is activated with more than 50% health remaining, protects from defeat for 1 turn", + specialNotes: "#{zombie}" + }, + 861: { + specialName: "Bewitching Lovely Iron Mace", + special: "Deals 13x character's ATK in QCK damage to one enemy, reduces damage received by 75% for 1 turn, amplifies the effect of orbs by 1.5x for 1 turn", + specialNotes: "#{orb : 1.5x}", + captain: "Reduces damage received by 10%" + }, + 862: { + captain: "Boosts ATK of QCK characters by 2x, reduces damage received by 10%", + specialName: "Bewitching Lovely Iron Mace", + special: "Deals 13x character's ATK in QCK damage to one enemy, reduces damage received by 75% for 1 turn, amplifies the effect of orbs by 1.5x for 1 turn", + specialNotes: "#{orb : 1.5x}" + }, + 863: { + captain: "Boosts ATK of QCK characters by 1.75x, recovers 2x character's RCV in HP at the end of each turn", + specialName: "Snow Crystal Clima-Tact", + special: "Reduces the defense of all enemies by 50% for 2 turns, reduces the ATK of all enemies by 10% for 2 turns" + }, + 864: { + captain: "Boosts ATK of Free Spirit characters by 2x", + specialName: "Slave Arrow", + special: "Locks the chain multiplier at 2.5x for 2 turns, delays all enemies for 1 turn" + }, + 865: { + captain: "Boosts ATK and HP of Free Spirit characters by 2x", + specialName: "Slave Arrow", + special: "Locks the chain multiplier at 2.5x for 2 turns, delays all enemies for 1 turn" + }, + 866: { + captain: "Boosts ATK of Cerebral characters by 2x", + specialName: "Cien Fleur Wing: The Storm", + special: "Boosts ATK of Slasher and Cerebral characters by 1.3x for 2 turns, reduces Bind duration by 2 turns" + }, + 867: { + captain: "Boosts ATK of all characters by 1.5x after the 12th hit in the chain", + specialName: "Tabasco Star: The Storm", + special: "Delays all enemies for 2 turns, deals 9x character's ATK in DEX damage to all enemies" + }, + 868: { + captain: "Boosts ATK of all characters by 1.2x, recovers 1,000 HP at the end of the turn", + specialName: "Heavy Gong: The Storm", + special: "Deals 15x character's ATK in STR damage to one enemy, reduces Bind duration by 3 turns" + }, + 869: { + captain: "Boosts ATK of Driven characters by 3x until the first hit other than Perfect", + specialName: "Black Knight", + special: "Changes adjacent orbs into matching orbs, amplifies the effect of orbs by 2x for 1 turn", + specialNotes: "#{orb : 2x}" + }, + 870: { + captain: "Boosts ATK of Driven characters by 3x until the first hit other than Perfect", + specialName: "Black Knight", + special: "Changes adjacent orbs into matching orbs, amplifies the effect of orbs by 2x for 1 turn", + specialNotes: "#{orb : 2x}" + }, + 871: { + captain: "Boosts ATK and RCV of QCK characters by 1.5x", + specialName: "Hobby-Hobby Fruit", + special: "Removes all enemies with HP below 20%", + specialNotes: "The special bypasses all known protective buffs. If the enemy can revive after being defeated, however, the special will only reduce the enemy's HP to 0 and trigger their revive effect." + }, + 872: { + captain: "Boosts ATK and RCV of QCK characters by 2x", + specialName: "Hobby-Hobby Fruit", + special: "Removes all enemies with HP below 20%", + specialNotes: "The special bypasses all known protective buffs. If the enemy can revive after being defeated, however, the special will only reduce the enemy's HP to 0 and trigger their revive effect." + }, + 873: { + captain: "Boosts ATK of Fighter characters by 2.5x if HP is below 30% at the start of the turn", + specialName: "Nyan Nyan Swim", + special: [ + { + "description": "Changes own orb into [PSY], amplifies the effect of orbs by 1.5x for 1 turn", + "cooldown": [ + 13, + 8 + ] + }, + { + "description": "Changes own orb into [PSY], amplifies the effect of orbs by 1.75x for 1 turn", + "cooldown": [ + 19, + 14 + ] + } + ], + specialNotes: "#{orb: 1.5x or 1.75x} #{stages}" + }, + 874: { + captain: "Boosts ATK of Fighter characters by 3x if HP is below 30% at the start of the turn", + specialName: "Nyan Nyan Swim", + special: [ + { + "description": "Changes own orb into [PSY], amplifies the effect of orbs by 1.5x for 1 turn", + "cooldown": [ + 13, + 8 + ] + }, + { + "description": "Changes own orb into [PSY], amplifies the effect of orbs by 1.75x for 1 turn", + "cooldown": [ + 19, + 14 + ] + } + ], + specialNotes: "#{orb: 1.5x or 1.75x} #{stages}" + }, + 875: { + captain: "Boosts ATK of Cerebral and Driven characters by 2x", + specialName: "Beto Launcher", + special: "Changes the captain's orb into a matching orb, locks all orbs for 1 turn, deals 13x character's ATK in INT damage to all enemies" + }, + 876: { + captain: "Boosts ATK of Cerebral and Driven characters by 2.25x, makes [TND] and [RCV] orbs \"beneficial\" to Cerebral and Driven characters", + captainNotes: "\"Beneficial\" orbs grant the same ATK boost as matching orbs while retaining their original function.", + specialName: "Beto Launcher", + special: "Changes the captain's orb into a matching orb, locks all orbs for 1 turn, deals 13x character's ATK in INT damage to all enemies" + }, + 877: { + captain: "Boosts amount of Beli received by 2x", + specialName: "Heaven's Do Art", + special: "Reduces any damage received above 2,000 HP by 88% for 2 turns", + specialNotes: "The exact formula for the damage received is: 2000 + ((total damage) - 2000) * 0.12" + }, + 878: { + captain: "Boosts ATK of all characters by 1.5x, boosts amount of Beli received by 2x", + specialName: "Heaven's Do Art", + special: "Reduces any damage received above 2,000 HP by 88% for 2 turns", + specialNotes: "The exact formula for the damage received is: 2000 + ((total damage) - 2000) * 0.12" + }, + 879: { + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of Fighter characters by 1.75x", + specialName: "Battle Preservation Fist: Manki Kayaku", + special: "Randomly changes all orbs including [BLOCK] orbs into [G] orbs, deals random typeless damage to all enemies", + specialNotes: "#{gOrbs}
    #{random : 5,000 : 100,000}" + }, + 880: { + captain: "Reduces cooldown of all specials by 3 turns at the start of the fight, boosts ATK of Fighter characters by 2x", + specialName: "Battle Preservation Fist: Manki Kayaku", + special: "Randomly changes all orbs including [BLOCK] orbs into [G] orbs, deals random typeless damage to all enemies", + specialNotes: "#{gOrbs}
    #{random : 5,000 : 100,000}" + }, + 881: { + captain: "Boosts ATK of Shooter and Free Spirit characters by 2x following a chain of Good > Great > Perfect hits", + specialName: "Fighting Music: Conflict Chekera", + special: "Increases damage received by 2x for 2 turns, reduces RCV by 90% for 2 turns, boosts ATK of Shooter and Free Spirit characters by 1.75x for 1 turn" + }, + 882: { + captain: "Boosts ATK of Shooter and Free Spirit characters by 3x following a chain of Good > Great > Perfect hits", + specialName: "Fighting Music: Conflict Chekera", + special: "Increases damage received by 2x for 2 turns, reduces RCV by 90% for 2 turns, boosts ATK of Shooter and Free Spirit characters by 1.75x for 1 turn" + }, + 883: { + captain: "Boosts ATK and HP of Powerhouse characters by 1.25x", + specialName: "Hakoku Sovereignity", + special: "Deals 20x character's ATK in character's type damage to all enemies, boosts ATK of Powerhouse characters by 1.5x for 1 turn. If \"Hakoku Sovereignity\" is used again in the same turn the special is activated in, boosts ATK of Powerhouse characters by 2x instead." + }, + 884: { + captain: "Boosts ATK and HP of Powerhouse characters by 1.5x", + specialName: "Hakoku Sovereignity", + special: "Deals 20x character's ATK in character's type damage to all enemies, boosts ATK of Powerhouse characters by 1.5x for 1 turn. If \"Hakoku Sovereignity\" is used again in the same turn the special is activated in, boosts ATK of Powerhouse characters by 2x instead." + }, + 885: { + captain: "Boosts ATK of Fighter characters by 2x, reduces damage received by 10%", + specialName: "Arabesque Brick Fist: Sun", + special: "Cuts the current HP of each enemy by 10%, boosts ATK of Fighter characters by 1.5x for 1 turn if HP is below 30% when the special is activated" + }, + 886: { + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of Slasher characters by 2x", + specialName: "Daisy Blade: First", + special: "Deals 15x character's ATK in STR damage to all enemies, boosts ATK of Slasher characters by 1.5x for 1 turn if HP is below 30% when the special is activated" + }, + 887: { + captain: "Boosts ATK of Driven characters by 1.5x, boosts amount of Beli received by 1.2x", + specialName: "Special Muggy Ball: Flashy", + special: "Reduces the defense of all enemies by 80% for 1 turn, deals 15x character's ATK in QCK damage to all enemies" + }, + 888: { + specialName: "Negative Ghost", + special: "Slightly reduces the ATK of all enemies by 10% for 3 turns", + specialNotes: "The reduction does not apply to damage from specials" + }, + 889: { + captain: "Boosts ATK and RCV of DEX characters by 1.2x", + specialName: "Ghost Rap", + special: "Changes [STR] orbs into [DEX] orbs, deals 10x character's ATK in DEX damage to all enemies" + }, + 890: { + captain: "Boosts ATK and RCV of DEX characters by 1.5x", + specialName: "Ghost Rap", + special: "Changes [STR] orbs into [DEX] orbs, deals 10x character's ATK in DEX damage to all enemies" + }, + 891: { + captain: "Boosts ATK and RCV of Powerhouse characters by 1.75x", + specialName: "Resurrection of the Dead", + special: "Reduces damage received by 50% for 1 turn, boosts ATK of Powerhouse characters by 1.25x for 1 turn" + }, + 892: { + captain: "Boosts chain multiplier by 2x", + specialName: "Hands of the Dead", + special: "Switches orbs between slots three times" + }, + 893: { + captain: "Boosts ATK of Powerhouse characters by 3x after scoring 3 Perfects in a row", + specialName: "Oars Ball", + special: "Reduces damage received by 50% for 1 turn, deals 30x character's ATK in STR damage to all enemies" + }, + 894: { + captain: "Boosts ATK of Driven characters by 3x following a chain of Good > Great > Perfect hits", + specialName: "Brick Bat: Black Box", + special: "Empties all slots with [INT] orbs, deals several times the character's ATK in INT damage to one enemy", + specialNotes: "The exact multiplier used is chosen based on the number of [INT] orbs consumed: 1 orb will give a 10x multiplier, 2 orbs 15x, 3 orbs 20x, 4 orbs 50x, 5 orbs 100x, 6 orbs 200x. It's not possible to activate the special without consuming at least one [INT] orb." + }, + 895: { + captain: "Boosts ATK of Slasher characters by 1.5x", + specialName: "Dying Chorus: Binks' Sake", + special: "Recovers 6x character's RCV in HP at the end of each turn for 3 turns" + }, + 896: { + captain: "Boosts ATK of Slasher characters by 2x", + specialName: "Dying Chorus: Binks' Sake", + special: "Recovers 6x character's RCV in HP at the end of each turn for 3 turns" + }, + 897: { + captain: "Boosts ATK of Cerebral and Driven characters by 2x", + specialName: "Ground Death: Thirst", + special: "Cuts the current HP of all enemies by 10%, randomizes all orbs and changes own orb into [STR]" + }, + 898: { + captain: "Boosts ATK and HP of Striker and Cerebral characters by 1.5x", + specialName: "Championship Fight: Little Garden Three", + special: "Deals 10x character's ATK in QCK damage to all enemies, changes adjacent orbs into [G] orbs", + specialNotes: "#{gOrbs}" + }, + 899: { + captain: "Boosts ATK of Fighter and Free Spirit characters by 1.75x and their RCV by 1.25x", + specialName: "Hymn to Friendship: \"Okama Way\" Two", + special: "Reduces Despair duration by 5 turns, recovers 10x character's RCV in HP" + }, + 900: { + captain: "Boosts ATK of Shooter characters by 2x if HP is above 99% at the start of the turn", + specialName: "Franky Destroy Gun", + special: "Deals 6 hits of 2,000 fixed damage to random enemies and for Shooter and Free Spirit characters, randomly changes Badly Matching orbs into [G] orbs or Matching orbs", + specialNotes: "The orb shuffle only applies to Shooter and Free Spirit characters, other classes are unaffected. #{gOrbs}" + }, + 901: { + captain: "Boosts ATK of Shooter characters by 2.75x if HP is above 99% at the start of the turn", + specialName: "Franky Destroy Gun", + special: "Deals 6 hits of 2,000 fixed damage to random enemies and for Shooter and Free Spirit characters, randomly changes Badly Matching orbs into [G] orbs or Matching orbs", + specialNotes: "The orb shuffle only applies to Shooter and Free Spirit characters, other classes are unaffected. #{gOrbs}" + }, + 902: { + captain: "Boosts ATK and HP of Powerhouse characters by 1.25x", + specialName: "Hakoku Sovereignity", + special: "Deals 20x character's ATK in character's type damage to all enemies, boosts ATK of Powerhouse characters by 1.5x for 1 turn. If \"Hakoku Sovereignity\" is used again in the same turn the special is activated in, boosts ATK of Powerhouse characters by 2x instead." + }, + 903: { + captain: "Boosts ATK and HP of Powerhouse characters by 1.5x", + specialName: "Hakoku Sovereignity", + special: "Deals 20x character's ATK in character's type damage to all enemies, boosts ATK of Powerhouse characters by 1.5x for 1 turn. If \"Hakoku Sovereignity\" is used again in the same turn the special is activated in, boosts ATK of Powerhouse characters by 2x instead." + }, + 904: { + captain: "Protects from defeat as long as HP is above 50%", + captainNotes: "#{zombie}", + specialName: "Yokozuna Slap!", + special: "Deals 20x character's ATK in STR damage to one enemy, delays all enemies for 1 turn" + }, + 905: { + captain: "Boosts ATK of Slasher characters by 2.5x if HP is below 30% at the start of the turn", + specialName: "Two Gorilla Cut", + special: [ + { + "description": "Changes own orb into [STR], boosts his own ATK by 1.5x for 2 turns", + "cooldown": [ 17, 11 ] + }, + { + "description": "Changes own orb into [STR], boosts ATK of Slasher characters by 1.5x for 2 turns", + "cooldown": [ 21, 15 ] + }, + { + "description": "Changes own orb into [STR], boosts ATK of Slasher characters by 1.75x for 2 turns", + "cooldown": [ 24, 18 ] + } + ], + specialNotes: "#{stages}" + }, + 906: { + captain: "Boosts ATK of Slasher characters by 2.75x if HP is below 30% at the start of the turn", + specialName: "Two Gorilla Cut", + special: [ + { + "description": "Changes own orb into [STR], boosts his own ATK by 1.5x for 2 turns", + "cooldown": [ 17, 11 ] + }, + { + "description": "Changes own orb into [STR], boosts ATK of Slasher characters by 1.5x for 2 turns", + "cooldown": [ 21, 15 ] + }, + { + "description": "Changes own orb into [STR], boosts ATK of Slasher characters by 1.75x for 2 turns", + "cooldown": [ 24, 18 ] + } + ], + specialNotes: "#{stages}" + }, + 907: { + specialName: "Cien Fleur: Big Tree", + special: "Delays all enemies for 1 turn, locks all orbs for 1 turn, deals 5,000 fixed damage to all enemies, reduces crew's HP to 1", + captain: "Boosts ATK and RCV of Cerebral characters by 1.5x if HP is below 30% at the start of the turn" + }, + 908: { + specialName: "Cien Fleur: Big Tree", + special: "Delays all enemies for 1 turn, locks all orbs for 1 turn, deals 5,000 fixed damage to all enemies, reduces crew's HP to 1", + captain: "Boosts ATK of Cerebral characters by 2.5x and their RCV by 1.75x if HP is below 30% at the start of the turn" + }, + 909: { + captain: "Boosts ATK and RCV of PSY characters by 1.5x", + specialName: "Hero of Justice! Chopper Mask!!", + special: "Recovers 5,000 HP, boosts ATK of PSY characters by 1.5x for 2 turns" + }, + 910: { + specialName: "Hero of Justice! Chopper Mask!!", + special: "Recovers 5,000 HP, boosts ATK of PSY characters by 1.5x for 2 turns", + captain: "Boosts ATK of PSY characters by 2x, their RCV by 1.5x, makes INT orbs \"beneficial\" to PSY characters", + captainNotes: "#{beneficial}" + }, + 911: { + specialName: "Diable Jambe: Premier Hachis", + special: [ + { + "description": "Deals 13x character's ATK in DEX damage to one enemy, boosts ATK of Powerhouse characters by 1.2x for 1 turn", + "cooldown": [ 15, 8 ] + }, + { + "description": "Deals 20x character's ATK in DEX damage to one enemy, boosts ATK of Powerhouse characters by 2x for 1 turn", + "cooldown": [ 25, 18 ] + } + ], + captain: "Boosts ATK and HP of Powerhouse characters by 1.5x", + specialNotes: "#{stages}" + }, + 912: { + specialName: "Diable Jambe: Premier Hachis", + special: [ + { + "description": "Deals 13x character's ATK in DEX damage to one enemy, boosts ATK of Powerhouse characters by 1.2x for 1 turn", + "cooldown": [ 15, 8 ] + }, + { + "description": "Deals 20x character's ATK in DEX damage to one enemy, boosts ATK of Powerhouse characters by 2x for 1 turn", + "cooldown": [ 25, 18 ] + } + ], + captain: "Boosts ATK of Powerhouse characters by 2.25x, and their HP by 1.5x. Recovers 2x character's RCV in HP at the end of each turn", + specialNotes: "#{stages}" + }, + 913: { + captain: "Boosts ATK of QCK characters by 2.5x if they have a matching orb", + specialName: "Black Magic Summoning: Advent of the Demon Lord Satan", + special: "Seals himself for 1 turn, changes [BLOCK] orbs into matching orbs, randomly changes Badly Matching orbs into either [STR], [QCK], [DEX], [PSY] or [INT] orbs" + }, + 914: { + captain: "Boosts ATK of QCK characters by 3x if they have a matching orb, by 1.2x otherwise", + specialName: "Black Magic Summoning: Advent of the Demon Lord Satan", + special: "Seals himself for 1 turn, changes [BLOCK] orbs into matching orbs, randomly changes Badly Matching orbs into either [STR], [QCK], [DEX], [PSY] or [INT] orbs" + }, + 915: { + captain: "Boosts ATK and RCV of Cerebral characters by 1.2x", + specialName: "Feeling of Mutual Love", + special: "Boosts ATK and RCV of Cerebral characters by 1.5x for 1 turn" + }, + 916: { + captain: "Boosts ATK and RCV of Cerebral characters by 1.75x", + specialName: "Feeling of Mutual Love", + special: "Boosts ATK and RCV of Cerebral characters by 1.5x for 1 turn" + }, + 917: { + captain: "Boosts ATK of Shooter characters by 1.5x", + specialName: "Kuja's Haki Arrow", + special: "Deals 5,000 fixed damage to one enemy, delays all enemies for 1 turn, changes [RCV] orbs on Shooter characters into matching orbs", + specialNotes: "The orb shuffle only applies to Shooter characters, other classes are unaffected." + }, + 918: { + captain: "Boosts ATK of Shooter characters by 1.75x, recovers a small amount of health at the end of each turn", + specialName: "Kuja's Haki Arrow", + special: "Deals 5,000 fixed damage to one enemy, delays all enemies for 1 turn, changes [RCV] orbs on Shooter characters into matching orbs", + specialNotes: "The orb shuffle only applies to Shooter characters, other classes are unaffected." + }, + 919: { + specialName: "Spike of the Warrior Defending Her Country", + special: "Reduces damage received from STR enemies by 50% for 2 turns" + }, + 920: { + specialName: "Snake Bow of the Warrior Defending Her Country", + special: "Changes the orbs in the middle row into [RCV] orbs, changes the orbs in the bottom row into [TND] orbs" + }, + 921: { + captain: "Boosts ATK and RCV of Free Spirit characters by 1.2x", + specialName: "Pure and Beautiful Shyness", + special: "Recovers 5000 HP and amplifies the effect of orbs by 1.5x for 2 turns" + }, + 922: { + captain: "Boosts ATK and RCV of Free Spirit characters by 1.75x", + specialName: "Pure and Beautiful Shyness", + special: "Recovers 5000 HP and amplifies the effect of orbs by 1.5x for 2 turns" + }, + 923: { + captain: "Boosts ATK of Driven Characters by 2.5x if HP is below 30% at the start of the turn, 2x otherwise", + specialName: "Repel: Weapons Reflect", + special: "Empties all slots, deals [STR] damage based on number of [STR] slots emptied to all enemies", + specialNotes: "The exact multiplier used is chosen based on the number of [STR] orbs consumed: 0 orbs - 3.5x ATK; 1 orb - 7x ATK; 2 orbs - 14x ATK; 3 orbs - 21x ATK; 4 orbs - 35x ATK; 5 orbs - 91x ATK; 6 orbs - 140x ATK." + }, + 924: { + captain: "Boosts ATK of Driven Characters by 2.75x if HP is below 30% at the start of the turn, 2x otherwise", + specialName: "Repel: Weapons Reflect", + special: "Empties all slots, deals [STR] damage based on number of [STR] slots emptied to all enemies", + specialNotes: "The exact multiplier used is chosen based on the number of [STR] orbs consumed: 0 orbs - 3.5x ATK; 1 orb - 7x ATK; 2 orbs - 14x ATK; 3 orbs - 21x ATK; 4 orbs - 35x ATK; 5 orbs - 91x ATK; 6 orbs - 140x ATK." + }, + 925: { + captain: "Boosts ATK of Powerhouse characters by 2x", + specialName: "Let's go, Jailer Beasts!", + special: "Deals 15x ATK to 1 enemy in [QCK] damage, boosts ATK against enemies with reduced defense by 1.3x for 3 turns" + }, + 926: { + captain: "Boosts ATK of Powerhouse characters by 2.5x", + specialName: "Let's go, Jailer Beasts!", + special: "Deals 15x ATK to 1 enemy in [QCK] damage, boosts ATK against enemies with reduced defense by 1.3x for 3 turns" + }, + 927: { + captain: "Boosts ATK and HP of Driven characters by 1.5x", + specialName: "Unwavering Hammer of Justice", + special: "Increases damage received by 1.5x and boosts ATK of Slasher and Driven characters by 1.2x for 3 turns" + }, + 928: { + captain: "Boosts ATK of Driven characters by 1.75x while above 30% HP and boosts ATK of Striker characters by 1.75x while below 30% HP", + special: "Deals 7x his ATK in [DEX] damage to all enemies, and boosts ATK against Poisoned and Strongly Poisoned enemies by 1.3x for 3 turns", + specialName: "Hell Wisdom Rush" + }, + 929: { + captain: "Boosts ATK of Driven characters by 2.25x while above 30% HP and boosts ATK of Striker characters by 2.25x while below 30% HP", + special: "Deals 7x his ATK in [DEX] damage to all enemies, and boosts ATK against Poisoned and Strongly Poisoned enemies by 1.3x for 3 turns", + specialName: "Hell Wisdom Rush" + }, + 930: { + captain: "Boosts chain multiplier by 2x", + specialName: "Blugori Manipulation Song", + special: "Changes orbs in left column to [DEX], then [QCK], then [INT]. Locks himself for 3 turns." + }, + 931: { + specialName: "Large Axe of Punishment", + special: "Deals 13x ATK to 1 enemy in [DEX] Damage. Turns [BLOCK] orbs into [RCV] orbs" + }, + 932: { + captain: "Boosts ATK of Powerhouse characters by 1.5x, and their HP by 1.5x", + specialName: "Rock Domination Wall", + special: [ + { + "description": "For Driven and Powerhouse characters, changes [EMPTY] and Badly Matching orbs into Matching orbs. Cuts the current HP of all enemies by 10%", + "cooldown": [ 25, 11 ] + }, + { + "description": "Changes [EMPTY] and Badly Matching orbs into Matching orbs. Cuts the current HP of all enemies by 20%", + "cooldown": [ 31, 17 ] + } + ], + specialNotes: "#{stages}" + }, + 933: { + captain: "Boosts ATK of Powerhouse characters by 2.25x, and their HP by 1.5x", + specialName: "Rock Domination Wall", + special: [ + { + "description": "For Driven and Powerhouse characters, changes [EMPTY] and Badly Matching orbs into Matching orbs. Cuts the current HP of all enemies by 10%", + "cooldown": [ 25, 11 ] + }, + { + "description": "Changes [EMPTY] and Badly Matching orbs into Matching orbs. Cuts the current HP of all enemies by 20%", + "cooldown": [ 31, 17 ] + } + ], + specialNotes: "#{stages}", + limit: "This character has a limit break path", + }, + 934: { + captain: "Boosts ATK of Fighter characters by 2x, and their HP by 1.5x. If HP is above 70% or below 30%, boosts ATK of Fighter characters by 2.75 instead", + specialName: "Fishman Karate!! Shark Fist Tile Breaker", + special: "Makes Perfects harder to hit for 1 turn. Deals 20x character's ATK in [INT] damage to all enemies. Changes all Fighter Character orbs into Matching", + specialNotes: "Decreases timing window to hit a Perfect. (Animation remains the same)" + }, + 935: { + captain: "Boosts ATK of Fighter characters by 2x, and their HP by 1.5x. If HP is above 70% or below 30%, boosts ATK of Fighter characters by 2.75 instead", + specialName: "Fishman Karate!! Shark Fist Tile Breaker", + special: "Makes Perfects harder to hit for 1 turn. Deals 20x character's ATK in [INT] damage to all enemies. Changes all Fighter Character orbs into matching", + specialNotes: "Decreases timing window to hit a Perfect. (Animation remains the same)" + }, + 936: { + captain: "Boosts Chain Multiplier by 3x", + specialName: "Gum-Gum Giant Jet Shell", + special: "Deals 20x ATK as [QCK] damage, and makes Perfects easier to hit for 3 turns", + specialNotes: "Increases timing window to hit a Perfect. (Animation remains the same)" + }, + 937: { + captain: "Boosts Chain Multiplier by 3.5x and boosts HP by 1.25x", + specialName: "Gum-Gum Giant Jet Shell", + special: "Deals 20x ATK as [QCK] damage, and makes Perfects easier to hit for 3 turns", + specialNotes: "Increases timing window to hit a Perfect. (Animation remains the same)" + }, + 938: { + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of Cerebral characters by 1.5x", + specialName: "Cyclone Burst", + special: "Reduces Bind duration for one character completely. For Striker and Cerebral characters, changes Badly Matching orbs into Matching orbs" + }, + 939: { + captain: "Reduces cooldown of all specials by 3 turns at the start of the fight, boosts ATK of Cerebral characters by 2x", + specialName: "Cyclone Burst", + special: "Reduces Bind duration for one character completely. For Striker and Cerebral characters, changes Badly Matching orbs into Matching orbs", + limit: "This character has a limit break path", + }, + 940: { + captain: "Boosts ATK and HP of [DEX] characters by 1.5x", + specialName: "Sure Kill! Exploding Star!!", + special: "Deals 13x ATK as [DEX] damage to all enemies, and boosts ATK of [DEX] characters by 1.75x for 1 turn" + }, + 941: { + captain: "Boosts ATK of [DEX] characters by 1.75x and their HP by 2.25x", + specialName: "Sure Kill! Exploding Star!!", + special: "Deals 13x ATK as [DEX] damage to all enemies, and boosts ATK of [DEX] characters by 1.75x for 1 turn" + }, + 942: { + captain: "Boosts ATK and HP of [STR] characters by 1.5x", + specialName: "Future Country's Big Incident: The Nightmare of Baldimore", + special: "Reduces damage received from [QCK] enemies by 100% for 1 turn" + }, + 943: { + captain: "Boosts ATK of [STR] characters by 2.25x and their HP by 1.75x", + specialName: "Future Country's Big Incident: The Nightmare of Baldimore", + special: "Reduces damage received from [QCK] enemies by 100% for 1 turn" + }, + 944: { + captain: "Boosts ATK and RCV of Driven characters by 1.2x", + specialName: "Spiritual Bouquet", + special: "Boosts ATK and RCV of Driven characters by 1.5x for 1 turn" + }, + 945: { + captain: "Boosts ATK and RCV of Driven characters by 1.75x", + specialName: "Spiritual Bouquet", + special: "Boosts ATK and RCV of Driven characters by 1.5x for 1 turn" + }, + 946: { + specialName: "Lock-on Iron Ball", + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of Striker characters by 1.75x", + special: "Change Friend Captain and changes own orb into [INT]" + }, + 947: { + captain: "Boosts ATK of [INT] characters by 1.5x, Boosts damage of [INT] specials by 1.5x", + specialName: "Flame Flash", + special: "[STR] and [INT] characters gain 1.3x ATK for 1 turn. Deals 10x character's ATK in [INT] damage to all enemies", + captainNotes: "#{noFixedPerc}" + }, + 948: { + captain: "Boosts ATK of Shooter characters by 1.5x and their RCV by 1.2x", + specialName: "Twin Cannons", + special: "Randomly changes all orbs to either [STR] or [INT]. Deals random [STR] damage", + specialNotes: "#{random : 7,000 : 18,000}", + }, + 949: { + captain: "Boosts ATK of Slasher characters by 2x, recovers 2x character's RCV in HP at the end of each turn", + specialName: "Ties with Ace", + special: "Reduces Silence duration by 3 turns, and recovers 4,000 HP", + specialNotes: "#{silence}", + }, + 950: { + captain: "Boosts ATK of Fighter and Free Spirit characters by 2.5x after scoring 3 Perfects in a row", + specialName: "Flame Commandment: Fire Pillar", + special: "Reduces Special Cooldown of Fighter and Free Spirit characters by 1 turn. Reduces damage received by 50% for 1 turn.", + specialNotes: "Reducing Special Cooldown works as if you took an extra turn" + }, + 951: { + captain: "Boosts ATK of Fighter and Free Spirit characters by 2.75x after scoring 3 Perfects in a row", + specialName: "Flame Commandment: Fire Pillar", + special: "Reduces Special Cooldown of Fighter and Free Spirit characters by 1 turn. Reduces damage received by 50% for 1 turn.", + specialNotes: "Reducing Special Cooldown works as if you took an extra turn" + }, + 952: { + captain: "Boosts ATK and HP of Shooter and Striker characters by 1.2x", + specialName: "Life-saving Gunstock Blow", + special: "Deals 13x ATK in [DEX] Damage to one enemy. Changes Captain's orb into matching." + }, + 953: { + captain: "Boosts ATK and HP of Shooter and Striker characters by 1.5x", + specialName: "Life-saving Gunstock Blow", + special: "Deals 13x ATK in [DEX] Damage to one enemy. Changes Captain's orb into matching." + }, + 954:{ + captain: "Boosts ATK and HP of [QCK] characters by 1.5x", + specialName: "Goldfish Fencing! I'll Dye the Sea Red with Your Blood", + special: "Reduces the defense of all enemies by 80% for 2 turns" + }, + 955:{ + captain: "Boosts ATK and HP of [PSY] characters by 1.5x", + specialName: "Get Rich Quick Scheme! We're All Gonna Be Rich", + special: "Boosts ATK against enemies with reduced defense by 1.2x for 2 turns" + }, + 956:{ + captain: "Boosts ATK and HP of [INT] characters by 1.5x", + specialName: "Fishman karate! I'll Finish You", + special: "Boosts ATK of Powerhouse characters by 1.2x for 2 turns" + }, + 957:{ + specialName: "First Aid", + special: "Recover 2,000 HP" + }, + 958:{ + specialName: "Bind Purge", + special: "Reduces Bind duration by 2 turns" + }, + 959:{ + specialName: "Captain Soul Recovery", + special: "Reduces Despair duration by 2 turns" + }, + 960:{ + specialName: "Slot Color Shuffle", + special: "Randomly changes all orbs into either [STR], [DEX], [QCK], [PSY] or [INT] orbs" + }, + 961:{ + specialName: "Slot Power Light", + special: "Amplifies the effect of orbs by 1.25x for 1 turn" + }, + 962:{ + specialName: "Captain Slot Change RCV", + special: "Changes captain's orb into [RCV]" + }, + 963:{ + captain: "Boosts ATK of characters with cost between 50 and 55 by 2x", + specialName: "Saint Charloss' Stroll", + special: "Reduces the defense of all enemies by 100% for 1 turn and randomizes all orbs" + }, + 964:{ + captain: "Boosts ATK, HP, and RCV of characters with cost between 50 and 55 by 1.5x", + specialName: "Wrath of the Creator Bloodline", + special: "Boosts ATK of all characters by 1.1x for 1 turn. If \"Wrath of the Creator Bloodline\" is used again in the same turn the special is activated in, boosts ATK of all characters by 1.5x instead." + }, + 965:{ + captain: "Boosts ATK of characters with cost between 50 and 55 by 1.5x, recovers 500 HP at the end of each turn", + specialName: "Wrath of the Creator Bloodline", + special: "Boosts ATK of all characters by 1.1x for 1 turn. If \"Wrath of the Creator Bloodline\" is used again in the same turn the special is activated in, boosts ATK of all characters by 1.5x instead." + }, + 966:{ + captain: "Boosts ATK of Driven characters by 2.25x", + specialName: "Repel", + special: "Empties slots with [QCK] orbs, deals [QCK] damage based on number of [QCK] slots emptied to all enemies", + specialNotes: "The exact multiplier used is chosen based on the number of [QCK] orbs consumed: 0 orbs - Can't activate; 1 orb - 14x ATK; 2 orbs - 21x ATK; 3 orbs - 35x ATK; 4 orbs - 49x ATK; 5 orbs - 91x ATK; 6 orbs - 140x ATK." + }, + 967:{ + captain: "Boosts ATK of Free Spirit characters by 2.25x", + specialName: "Surgeon of Death's First Aid Surgery", + special: "Recovers 20x character's RCV in HP. Switches orbs between slots twice" + }, + 968:{ + specialName: "High Heat Ray Laser", + special: "Deals 25x ATK to one enemy. Changes own orb into matching orb" + }, + 969:{ + specialName: "High Heat Ray Laser", + special: "Deals 25x ATK to one enemy. Changes own orb into matching orb" + }, + 970:{ + specialName: "High Heat Ray Laser", + special: "Deals 25x ATK to one enemy. Changes own orb into matching orb" + }, + 971:{ + specialName: "High Heat Ray Laser", + special: "Deals 25x ATK to one enemy. Changes own orb into matching orb" + }, + 972:{ + specialName: "High Heat Ray Laser", + special: "Deals 25x ATK to one enemy. Changes own orb into matching orb" + }, + 973:{ + captain: "Boosts ATK of Powerhouse characters by 2x if HP is above 99% at the start of the turn", + specialName: "Ironclad Thrust: Dwarf Guard of the World", + special: "Deals 20,000 fixed damage to one enemy. Changes friend captain's orb into Matching orb" + }, + 974:{ + captain: "Boosts ATK of Powerhouse characters by 2.5x if HP is above 99% at the start of the turn", + specialName: "Ironclad Thrust: Dwarf Guard of the World", + special: "Deals 20,000 fixed damage to one enemy. Changes friend captain's orb into Matching orb" + }, + 975:{ + captain: "Reduces damage received by 10%", + specialName: "A Threat That Puts Adults to Shame", + special: "Boosts ATK of Striker and Driven characters by 1.3x for 1 turn. Protects from defeat as long as HP is above 50% for 1 turn", + specialNotes: "#{zombie}" + }, + 976:{ + captain: "Boosts ATK of Driven characters by 2x. Reduces damage received by 10%", + specialName: "A Threat That Puts Adults to Shame", + special: "Boosts ATK of Striker and Driven characters by 1.3x for 1 turn. Protects from defeat as long as HP is above 50% for 1 turn", + specialNotes: "#{zombie}" + }, + 977:{ + captain: "Boosts ATK of Shooter characters by 2x", + specialName: "Yata no Kagami (Sacred Mirror)", + special: [ + { + "description": "Changes own orb into [QCK]. Reduces Special Cooldown of Shooter and Fighter specials by 1 turn", + "cooldown": [ 19, 5 ] + }, + { + "description": "Changes own orb into [QCK]. Reduces Special Cooldown of Shooter and Fighter specials by 1 turn. Adds .5x to Chain multiplier for 2 turns", + "cooldown": [ 25, 11 ] + } + ], + specialNotes: "#{stages}" + }, + 978:{ + captain: "Reduces cooldown of Shooter specials by 2 turns at the start of the fight, boosts ATK of Shooter characters by 2.25x and boosts HP of Shooter characters by 1.5x", + specialName: "Yata no Kagami (Sacred Mirror)", + special: [ + { + "description": "Changes own orb into [QCK]. Reduces Special Cooldown of Shooter and Fighter specials by 1 turn", + "cooldown": [ 19, 5 ] + }, + { + "description": "Changes own orb into [QCK]. Reduces Special Cooldown of Shooter and Fighter specials by 1 turn. Adds .5x to Chain multiplier for 2 turns", + "cooldown": [ 25, 11 ] + } + ], + specialNotes: "#{stages}", + limit: [ + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 20" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Aquire Sailor Ability 1: Boosts ATK, HP and RCV of Shooter characters by 20" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Boosts base HP by 60" }, + { "description": "Aquire new Captain Ability: Reduces cooldown of Shooter specials by 3 turns at the start of the fight, boosts ATK of Shooter characters by 2.35x and boosts HP of Shooter characters by 1.5x" }, + { "description": "Aquire Potential 2: Barrier Penetration" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 10% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 15% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 20% chance to deal 10% of this character's attack in extra damage" + ] + }, + { + "Name": "Barrier Penetration", + "description": [ + "Level 1: This character's attack will ignore barriers if HP is above 99%", + "Level 2: This character's attack will ignore barriers if HP is above 99%", + "Level 3: This character's attack will ignore barriers if HP is above 99%", + "Level 4: This character's attack will ignore barriers if HP is above 80%", + "Level 5: This character's attack will ignore barriers if HP is above 50%" + ] + }, + ] + }, + 979: { + captain: "Boosts ATK of [PSY] and [DEX] characters by 1.75x and their RCV by 1.2x", + specialName: "Flintlock Barrage", + special: "Randomly changes all orbs into either [PSY] or [DEX] orbs, deals random PSY damage to all enemies", + }, + 980: { + captain: "Boosts ATK of [DEX] and [STR] characters by 1.75x and their RCV by 1.2x", + specialName: "Hidden King Mallet", + special: "Randomizes all orbs and changes own orb into [DEX]" + }, + 981: { + captain: "Boosts ATK of Fighter and Powerhouse characters by 2x and sharply reduces their RCV", + captainNotes: "The RCV Reduction is around 90%", + specialName: "Martial Art Diving Fist", + special: "Boosts own ATK by 1.75x for 1 turn and deals 800 fixed damage to one enemy", + specialNotes: "#{fixed}" + }, + 982: { + captain: "Boosts ATK of Slasher characters by 2x", + specialName: "Flower Sword Straight Cut", + special: "Deals 25x character's ATK to one enemy, changes bottom row orbs into matching orbs" + }, + 983: { + captain: "Boosts ATK of Slasher characters by 2.25x, makes [RCV] and [TND] orbs \"beneficial\" to Slasher characters", + captainNotes: "\"Beneficial\" orbs grant the same ATK boost as matching orbs.", + specialName: "Flower Sword Straight Cut", + special: "Deals 25x character's ATK to one enemy, changes bottom row orbs into matching orbs" + }, + 984: { + captain: "Boosts ATK of Striker characters by 2.25x", + specialName: "Shrouds and Rattling Knot", + special: "Delays all enemies for 1 turn and locks all orbs for 1 turn" + }, + 985:{ + captainNotes: "Acts as a Daimyo Turtle and thus gives 15k EXP" + }, + 986:{ + captainNotes: "Acts as a Daimyo Turtle and thus gives 15k EXP" + }, + 987:{ + captainNotes: "Acts as a Daimyo Turtle and thus gives 15k EXP" + }, + 988:{ + captainNotes: "Acts as a Daimyo Turtle and thus gives 15k EXP" + }, + 989:{ + captain: "Boosts ATK of characters with cost above 20 and below 30 by 2.5x, but reduces the HP of every character by 90%", + special: "Changes the orbs in the left column into [G], [QCK] and [DEX], the orbs in the right column into [STR], [PSY] and [INT]", + specialName: "Bluff Piracy" + }, + 990: { + captain: "Boosts ATK of Free Spirit characters by 2.5x if HP is above 99% at the start of the turn", + specialName: "10,000 Ton Vise of Hell", + special: "Changes [RCV] orbs into matching orbs" + }, + 991: { + captain: "Boosts ATK of Free Spirit characters by 2.75x if HP is above 99% at the start of the turn", + specialName: "10,000 Ton Vise of Hell", + special: "Changes [RCV] orbs into matching orbs" + }, + 992: { + captain: "Boosts ATK of [QCK] characters by 2x", + special: "Cuts the current HP of each enemy by 20% and changes own orb into [QCK]", + specialName: "Punc Rock Fest" + }, + 993: { + captain: "Boosts ATK of [QCK] characters by 2.5x", + special: "Cuts the current HP of each enemy by 20% and changes own orb into [QCK]", + specialName: "Punc Rock Fest", + limit: [ + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Aquire new Captain Ability: Boosts ATK of [QCK] characters by 2.75x" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base HP by 60" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base HP by 60" }, + { "description": "Aquire Sailor Ability 1: Boosts HP, RCV, and ATK of [QCK] characters by 30" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Barrier Penetration" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 10% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 15% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 20% chance to deal 10% of this character's attack in extra damage" + ] + }, + { + "Name": "Barrier Penetration", + "description": [ + "Level 1: This character's attack will ignore barriers if HP is above 99%", + "Level 2: This character's attack will ignore barriers if HP is above 99%", + "Level 3: This character's attack will ignore barriers if HP is above 99%", + "Level 4: This character's attack will ignore barriers if HP is above 80%", + "Level 5: This character's attack will ignore barriers if HP is above 50%" + ] + }, + ] + }, + 994: { + captain: "Boosts amount of Beli received by 2x", + special: "Reduces Special Cooldown of Cerebral and Fighter characters, and shows the stats of enemies", + specialName: "Peeping Mind", + special: [ + { + "description": "Reduces Special Cooldown of Cerebral and Fighter specials by 1 turn. Displays the status of all enemies.", + "cooldown": [ 13, 7 ] + }, + { + "description": "Reduces Special Cooldown of Cerebral and Fighter specials by 2 turn. Displays the status of all enemies.", + "cooldown": [ 20, 14 ] + } + ], + specialNotes: "Status includes Enemy Attack, Defense, Combo Hits, Current / Total HP, Attack Interval, 'Specials based on turns', and 'Effect after Death'
    #{stages}", + sailor: "Restores her own special by 1 turn when it is rewinded", + sailorNotes: "#{rewind : 1}", + }, + 995:{ + captain: "Boosts amount of Beli received by 3x", + special: "Reduces Special Cooldown of Cerebral and Fighter characters, and shows the stats of enemies", + specialName: "Peeping Mind", + special: [ + { + "description": "Reduces Special Cooldown of Cerebral and Fighter specials by 1 turn. Displays the status of all enemies.", + "cooldown": [ 13, 7 ] + }, + { + "description": "Reduces Special Cooldown of Cerebral and Fighter specials by 2 turn. Displays the status of all enemies.", + "cooldown": [ 20, 14 ] + } + ], + specialNotes: "Status includes Enemy Attack, Defense, Combo Hits, Current / Total HP, Attack Interval, 'Specials based on turns', and 'Effect after Death'
    #{stages}", + sailor: "Restores her own special by 1 turn when it is rewinded", + sailorNotes: "#{rewind : 1}", + }, + 996: { + captain: "Boosts ATK of Powerhouse characters by 2x", + special: [ + { + "description": "For Powerhouse characters, changes Badly Matching orbs into Matching orbs.", + "cooldown": [ 11, 5 ] + }, + { + "description": "For all characters, changes Badly Matching orbs into Matching orbs.", + "cooldown": [ 20, 14 ] + } + ], + specialName: "Decapitation High Heel", + specialNotes: "#{stages}" + }, + 997: { + captain: "Boosts ATK of Powerhouse characters by 2.25x, makes [TND] and [RCV] orbs \"beneficial\" to Powerhouse characters", + captainNotes: "\"Beneficial\" orbs grant the same ATK boost as matching orbs while retaining their original function.", + special: [ + { + "description": "For Powerhouse characters, changes Badly Matching orbs into Matching orbs.", + "cooldown": [ 11, 5 ] + }, + { + "description": "For all characters, changes Badly Matching orbs into Matching orbs.", + "cooldown": [ 20, 14 ] + } + ], + specialName: "Decapitation High Heel", + specialNotes: "#{stages}", + limit: "This character has a limit break path", + }, + 998: { + captain: "Boosts ATK of Driven characters by 2x and reduces cooldown of all specials by 1 turn at the start of the fight", + specialName: "Hira Release: Death Enjambre", + special: "Delays all enemies for 2 turns, deals 50x character's ATK as typeless damage to all enemies at the end of the turn for 5 turns" + }, + 999: { + captain: "Boosts ATK of Driven characters by 2.25x and reduces cooldown of all specials by 2 turns at the start of the fight", + specialName: "Hira Release: Death Enjambre", + special: "Delays all enemies for 2 turns, deals 50x character's ATK as typeless damage to all enemies at the end of the turn for 5 turns", + limit: [ + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base HP by 50" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Aquire Sailor Ability 1: Makes [RCV] and [TND] orbs \"beneficial\" for this unit" }, + { "description": "Boosts base HP by 50" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base HP by 60" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: [DEX] Damage Reduction" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a ??% chance to deal ??% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a ??% chance to deal ??% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a ??% chance to deal ??% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a ??% chance to deal ??% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a ??% chance to deal ??% of this character's attack in extra damage" + ] + }, + { + "Name": "[DEX] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [DEX] characters by ?%", + "Level 2: Reduce damage taken from [DEX] characters by ?%", + "Level 3: Reduce damage taken from [DEX] characters by ?%", + "Level 4: Reduce damage taken from [DEX] characters by ?%", + "Level 5: Reduce damage taken from [DEX] characters by ?%" + ] + }, + ] + }, + 1000: { + captain: "Boosts ATK of all characters proportionally to the crew's current HP. Heals for 1.5x his RCV at the end of the turn each time you hit a Good. Heals for .5x his RCV at the end of the turn each time you hit a Great", + captainNotes: "#{captainProportional : higher : 1 + 1 * (remaining HP) / (total HP) : 2 : 1 }", + special: "Recovers 25x character's RCV in HP. Reduces Bind and Despair duration by 3 turns", + specialName: "Love Sacrifice" + }, + 1001: { + captain: "Boosts ATK of all characters proportionally to the crew's current HP. Heals for 1.5x his RCV at the end of the turn each time you hit a Good. Heals for .5x his RCV at the end of the turn each time you hit a Great", + captainNotes: "#{captainProportional : higher : 1 + 1 * (remaining HP) / (total HP) : 2 : 1 }", + special: "Recovers 25x character's RCV in HP. Reduces Bind and Despair duration by 3 turns", + specialName: "Love Sacrifice" + }, + 1002: { + captain: "Boosts ATK of Fighter characters by 1.5x", + special: "Reduces Paralysis duration by 3 turns and deals 7x ATK as [STR] damage to one enemy", + specialName: "Bepo's Ultimate Fist!!", + specialNotes: "Paralysis causes that unit to have a chance of not attacking and breaking chain" + }, + 1003: { + captain: "Boosts ATK of Fighter characters by 2x", + special: "Reduces Paralysis duration by 3 turns and deals 7x ATK as [STR] damage to one enemy", + specialName: "Bepo's Ultimate Fist!!", + specialNotes: "Paralysis causes that unit to have a chance of not attacking and breaking chain" + }, + 1004: { + captain: "Boosts RCV of all characters by 1.5x", + specialName: "Hilarious Combination", + special: "Changes the orbs in the left column into [RCV] orbs" + }, + 1005: { + captain: "Boosts ATK of Powerhouse characters by 1.5x", + specialName: "Rush to Freedom", + special: "Boosts own ATK by 1.75x for 1 turn" + }, + 1006: { + captain: "Boosts ATK and HP of Powerhouse characters by 1.5x", + specialName: "Rush to Freedom", + special: "Boosts own ATK by 1.75x for 1 turn" + }, + 1007: { + captain: "Boosts ATK of Cerebral and Free Spirit characters by 1.5x", + specialName: "Cherry Blossom Storm: Spring Pattern", + special: "Changes adjacent orbs into [RCV] and recovers 3,000 HP" + }, + 1008: { + captain: "Boosts ATK of Cerebral and Free Spirit characters by 2x. Recovers 3x character's RCV in HP at the end of each turn", + specialName: "Cherry Blossom Storm: Spring Pattern", + special: "Changes adjacent orbs into [RCV] and recovers 3,000 HP" + }, + 1009: { + special: "Changes [BLOCK] orbs into [STR], deals 20x character's ATK in STR damage to one enemy", + specialName: "Gum-Gum Flail", + captain: "Boosts ATK of [STR] and Fighter characters by 1.5x, reduces cooldown of all specials by 1 turn at the start of the fight", + captainNotes: "The bonus is cumulative. STR Fighter characters get a 2.25x bonus." + }, + 1010:{ + captain: "Boosts ATK of Driven characters by 1.5x", + special: "Boosts own ATK by 1.3x for 5 turns, reduces damage received by 20% for 5 turns, deals 13x character's ATK as [INT] damage to one enemy", + specialName: "Evil Beast's Horn Pierce" + }, + 1011:{ + captain: "Boosts ATK of Driven characters by 1.75x, and boosts ATK of Powerhouse characters by 1.5x", + captainNotes: "The bonus is cumulative. Driven Powerhouse characters get a 2.625x bonus.", + special: "Boosts own ATK by 1.3x for 5 turns, reduces damage received by 20% for 5 turns, deals 13x character's ATK as [INT] damage to one enemy", + specialName: "Evil Beast's Horn Pierce" + }, + 1012: { + specialName: "Phantom Snake Sword", + special: "Changes the orbs in the left column into [RCV], [QCK] and [DEX], binds himself for 2 turns" + }, + 1013: { + specialName: "Binding Iron Chain", + special: "Boosts ATK against delayed enemies by 1.2x for 1 turn" + }, + 1014: { + special: "Binds himself for 1 turn and makes Perfects easier to hit for 2 turns", + specialName: "Scapegoat Substitute", + captain: "Boosts ATK of Powerhouse characters by 2x, and Recovers 2x character's RCV in HP at the end of each turn" + }, + 1015: { + captain: "Boosts ATK of [INT] characters by 2.75x if they have a matching orb", + special: "Randomizes all orbs. Boosts ATK of [INT] characters by 1.5x for 1 turn. If during that turn every unit scores a Perfect hit, boosts ATK of [INT] characters by 1.5x for the next 2 turns", + specialName: "Hollow Eye Killing Shot" + }, + 1016: { + captain: "Boosts ATK of [INT] characters by 3x if they have a matching orb, by 1.5x otherwise", + special: "Randomizes all orbs. Boosts ATK of [INT] characters by 1.5x for 1 turn. If during that turn every unit scores a Perfect hit, boosts ATK of [INT] characters by 1.5x for the next 2 turns", + specialName: "Hollow Eye Killing Shot" + }, + 1017: { + captain: "Boosts HP of Slasher characters by 1.5x", + special: "Changes own orb into [PSY]. Deals several times the character's ATK in [PSY] damage to one enemy. Boosts ATK of Slasher characters by 1.5x for 1 turn", + specialName: "Ravaging Cutlass Dance", + specialNotes: "#{specialProportional : lower : 75 * ( 1 - (remaining HP) / (total HP) )}", + }, + 1018: { + captain: "Boosts ATK of Slasher characters by 1.5x and their HP by 2x", + special: "Changes own orb into [PSY]. Deals several times the character's ATK in [PSY] damage to one enemy. Boosts ATK of Slasher characters by 1.5x for 1 turn", + specialName: "Ravaging Cutlass Dance", + specialNotes: "#{specialProportional : lower : 75 * ( 1 - (remaining HP) / (total HP) )}", + }, + 1019: { + captain: "Reduces damage received from [QCK] enemies by 50%", + special: "Switches orbs between slots 2 times and deals 2000 fixed damage to one enemy", + specialName: "Blacksmithing Measurement: Double Slash", + specialNotes: "#{fixed}" + }, + 1020: { + captain: "Boosts ATK and RCV of Shooter and Cerebral characters by 1.5x.", + captainNotes: "This effect does not stack for characters that have both classes.", + specialName: "Sweet Fruit Trap", + special: "Recovers 9x characters RCV in HP. Changes captain's orb into Matching orb" + }, + 1021: { + captain: "Boosts ATK and RCV of Shooter and Cerebral characters by 1.75x.", + captainNotes: "This effect does not stack for characters that have both classes.", + specialName: "Sweet Fruit Trap", + special: "Recovers 9x characters RCV in HP. Changes captain's orb into Matching orb" + }, + 1022: { + captain: "Boosts ATK of all characters by 2x and boosts amount of Beli received by 1.2x", + special: "Deals 13x character's ATK as [PSY] damage to all enemies. Changes [BOMB], [EMPTY], and [TND] orbs to [PSY]", + specialName: "Gum-Gum Gigant Rifle: New Star" + }, + 1023: { + captain: "Boosts ATK of Free Spirit characters by 2.25x", + special: "Deals 13x characters ATK in INT damage to all enemies, boosts atk of Free Spirit characters by 1.75x for one turn.", + specialName: "Flame Mirror: Dawn" + }, + 1024: { + captain: "Boosts ATK of Powerhouse characters by 2x", + special: "Amplifies the effect of orbs for 2 turns, the exact multiplier changes depending on the current HP at the time the special was activated. ", + specialNotes: "Below 30% -> 1.75x orb boost, between 30% and 70% -> 1.5x, above 70% -> 1.25x", + specialName: "Eight-Impact Fist! Blow of Resentment" + }, + 1025: { + captain: "Boosts ATK of Powerhouse characters by 2x and boosts the HP of Striker characters by 2x", + captainNotes: "A character with both classes will get both boosts", + special: "Amplifies the effect of orbs for 2 turns, the exact multiplier changes depending on the current HP at the time the special was activated. ", + specialNotes: "Below 30% -> 1.75x orb boost, between 30% and 70% -> 1.5x, above 70% -> 1.25x", + specialName: "Eight-Impact Fist! Blow of Resentment", + limit: [ + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base RCV by 40" }, + { "description": "Boosts base RCV by 40" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Aquire Sailor Ability 1: Boosts ATK and HP of Powerhouse and Striker characters by 50" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Aquire new Captain Ability: Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of Powerhouse characters by 2.25x and boosts the HP of Striker characters by 2x" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Enrage" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 10% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 15% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 20% chance to deal 10% of this character's attack in extra damage" + ] + }, + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 30", + "Level 2: Boosts base ATK by 60", + "Level 3: Boosts base ATK by 90", + "Level 4: Boosts base ATK by 100", + "Level 5: Boosts base ATK by 150" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1026: { + captain: "Boosts ATK and RCV of Fighter characters by 1.5x", + specialName: "Shooting Moon", + special: "Changes Captain orb into Matching orb, and switches orbs between slots three times" + }, + 1027: { + captain: "Boosts ATK and RCV of Fighter characters by 2x", + specialName: "Shooting Moon", + special: "Changes Captain orb into Matching orb, and switches orbs between slots three times" + }, + 1028: { + captain: "Boosts ATK of all characters by 2.5x after the 21st hit in the chain", + specialName: "Rah-Rah-Rah Rampage", + special: "Deals random damage to all enemies, boosts ATK of all characters by 1.75x after 30th hit in the chain for 3 turns.", + specialNotes: "Buffalo's Captain as a Special essentially" + }, + 1029: { + captain: "Boosts ATK of all characters by 2.5x after the 21st hit in the chain and by 3.5x after the 36th hit", + specialName: "Rah-Rah-Rah Rampage", + special: "Deals random damage to all enemies, boosts ATK of all characters by 1.75x after 30th hit in the chain for 3 turns.", + specialNotes: "Buffalo's Captain as a Special essentially" + }, + 1030: { + captain: "Boosts ATK of Powerhouse characters by 2.5x if HP is above 99% at the start of the turn", + specialName: "Hero's Gungnir", + special: "Reduces crew's HP to 1, deals 10x the removed HP as damage to one enemy. Boosts own ATK by 2.25x for 1 turn." + }, + 1031: { + captain: "Boosts ATK of Powerhouse characters by 2.75x if HP is above 99% at the start of the turn", + specialName: "Hero's Gungnir", + special: "Reduces crew's HP to 1, deals 10x the removed HP as damage to one enemy. Boosts own ATK by 2.25x for 1 turn." + }, + 1032: { + captain: "Boosts ATK of Striker and Slasher characters by 1.5x and reduces cooldown of Slasher and Striker characters by 1 turn at the start of the fight", + special: "Reduces Special Cooldown of Slasher and Striker specials by 1 turn. For Slasher and Striker characters, changes Badly Matching orbs into [RCV] orbs.", + specialName: "Surprise Pincer Attack" + }, + 1033: { + captain: "Boosts ATK of Striker and Slasher characters by 2.25x and reduces cooldown of Slasher and Striker characters by 2 turns at the start of the fight", + special: "Reduces Special Cooldown of Slasher and Striker specials by 1 turn. For Slasher and Striker characters, changes Badly Matching orbs into [RCV] orbs.", + specialName: "Surprise Pincer Attack", + limit: [ + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Aquire Potential 1: Enrage" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Aquire Sailor Ability 1: Boosts ATK and HP of Slasher and Striker characters by 50" }, + { "description": "Boosts base HP by 70" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Boosts base HP by 60" }, + { "description": "Aquire Sailor Ability 2: Restores his own special by 1 turn when it is rewinded" }, + { "description": "Aquire Potential #: Critical Hit" }, + ], + potential: [ + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 20", + "Level 2: Boosts base ATK by 40", + "Level 3: Boosts base ATK by 60", + "Level 4: Boosts base ATK by 80", + "Level 5: Boosts base ATK by 100" + ] + }, + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 25% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 30% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 40% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 50% chance to deal 7% of this character's attack in extra damage" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1034: { + captain: "Boosts ATK of Striker characters by a variable amount depending on how many Strikers are on your team. If you don't attack with Bartolomeo, reduces damage received by 30% for that turn.", + captainNotes: "ATK boost with 1 Striker is 1.25x. With 2 Strikers: 1.5x. With 3 Strikers: 1.75x. With 4 Strikers: 2x. With 5 Stikers: 2.5x. With 6 Strikers: 2.75x", + special: "Protects from defeat for 1 turn, and deals several times character's ATK in Typeless damage to one enemy", + specialNotes: "#{specialProportional : lower : 150 * ( 1 - (remaining HP) / (total HP) )}
    #{zombie}", + specialName: "Bari Bari No Pistol" + }, + 1035: { + captain: "Boosts ATK of Striker characters by a variable amount depending on how many Strikers are on your team. If you don't attack with Bartolomeo, reduces damage received by 30% for that turn.", + captainNotes: "ATK boost with 1 Striker is 1.25x. With 2 Strikers: 1.5x. With 3 Strikers: 1.75x. With 4 Strikers: 2x. With 5 Stikers: 2.5x. With 6 Strikers: 2.75x", + special: "Protects from defeat for 1 turn, and deals several times character's ATK in Typeless damage to one enemy", + specialNotes: "#{specialProportional : lower : 150 * ( 1 - (remaining HP) / (total HP) )}
    #{zombie}", + specialName: "Bari Bari No Pistol", + limit: [ + { "description": "Boosts base ATK by 10" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Aquire Potential 1: [DEX] Damage Reduction" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Boosts base HP by 35" }, + { "description": "Boosts base ATK by 15" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK of STR characters by 60" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Boosts base HP by 45" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base HP by 50" }, + { "description": "Aquire Potential 2: Enrage" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base HP by 55" }, + { "description": "Boosts base HP by 65" }, + { "description": "Boosts base ATK by 35" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base HP by 70" }, + { "description": "Boosts base HP by 80" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base RCV by 40" }, + { "description": "Aquire Sailor Ability 2: Completely resists Paralysis on this character" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base ATK by 45" }, + { "description": "Aquire Potential 3: Reduce No Healing duration" }, + ], + potential: [ + { + "Name": "[DEX] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [DEX] characters by 2%", + "Level 2: Reduce damage taken from [DEX] characters by ?%", + "Level 3: Reduce damage taken from [DEX] characters by ?%", + "Level 4: Reduce damage taken from [DEX] characters by ?%", + "Level 5: Reduce damage taken from [DEX] characters by ?%" + ] + }, + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 30", + "Level 2: Boosts base ATK by ??", + "Level 3: Boosts base ATK by ??", + "Level 4: Boosts base ATK by ??", + "Level 5: Boosts base ATK by ??" + ] + }, + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: Reduces No Healing duration by ? turn", + "Level 2: Reduces No Healing duration by ? turn", + "Level 3: Reduces No Healing duration by ? turn", + "Level 4: Reduces No Healing duration by ? turns", + "Level 5: Reduces No Healing duration by ? turns" + ] + }, + ] + }, + 1036: { + captain: "Boosts ATK of Free Spirit characters by 2x after scoring 3 Perfects in a row", + special: "Deals 13x ATK in QCK Damage to one Enemy, Changes Orbs depending on the current HP", + specialName: "Kenpo: Kick Thrust Drop", + specialNotes: "HP>99%: Middle Left and Bottom Left Orbs into matching
    99%>HP>30%: Left Column to [G] orbs
    HP<30%: Left Column to [RCV]" + }, + 1037: { + captain: "Boosts ATK of Free Spirit characters by 2.5x after scoring 3 Perfects in a row", + special: "Deals 13x ATK in QCK Damage to one Enemy, Changes Orbs depending on the current HP", + specialName: "Kenpo: Kick Thrust Drop", + specialNotes: "HP>99%: Middle Left and Bottom Left Orbs into matching
    99%>HP>30%: Left Column to [G] orbs
    HP<30%: Left Column to [RCV]" + }, + 1038: { + captain: "Boosts ATK and RCV of [DEX] and [QCK] characters by 1.2x", + special: "Switches orbs between slots once, recovers 0.3x character's RCV in HP", + specialName: "Great Scissors" + }, + 1039: { + captain: "Boosts ATK and RCV of [DEX] and [QCK] characters by 1.5x", + special: "Switches orbs between slots once, recovers 0.3x character's RCV in HP", + specialName: "Great Scissors" + }, + 1040: { + captain: "Boosts ATK and HP of [STR] characters by 1.5x", + special: "Deals 30x the character's ATK as STR damage to all enemies. Boosts ATK of everyone by 1.5x if HP is below 30% at the time the special is activated", + specialName: "Ice Throw" + }, + 1041: { + captain: "Boosts ATK and HP of [STR] characters by 2x", + special: "Deals 30x the character's ATK as STR damage to all enemies. Boosts ATK of everyone by 1.5x if HP is below 30% at the time the special is activated", + specialName: "Ice Throw" + }, + 1042: { + captain: "Boosts ATK of Striker and Slasher characters by 2x, reduces crew's RCV to 0.", + special: "Changes [STR] and [QCK] orbs on Striker and Slasher characters into matching orbs, cuts the current HP of one enemy by 7%", + specialName: "Hitting Size" + }, + 1043: { + captain: "Boosts ATK of Striker and Slasher characters by 2.75x if they have a matching Orb, by 2x otherwise, reduces crew's RCV to 0.", + special: "Changes [STR] and [QCK] orbs on Striker and Slasher characters into matching orbs, cuts the current HP of one enemy by 7%", + specialName: "Hitting Size" + }, + 1044: { + captain: "Boosts ATK of Slasher and Free Spirit characters by 2x at the start of the chain, by 3x after the 3rd Perfect in a row and by 4x after the 5th Perfect in a row.", + specialName: "Gamma Knife", + special: [ + { + "description": "Makes Damage and Health Cutting Specials of Slasher and Free Spirit characters bypass all defensive Buffs, deals 20x character's ATK in fixed PSY damage to one enemy.", + "cooldown": [ 18, 13 ] + }, + { + "description": "Makes Damage and Health Cutting Specials of all characters bypass all defensive Buffs, deals 50x character's ATK in fixed PSY damage to one enemy.", + "cooldown": [ 25, 20 ] + } + ], + specialNotes: "#{stages}" + }, + 1045: { + captain: "Boosts ATK of Slasher and Free Spirit characters by 2x at the start of the chain, by 3x after the 3rd Perfect in a row and by 4x after the 5th Perfect in a row.", + specialName: "Gamma Knife", + special: [ + { + "description": "Makes Damage and Health Cutting Specials of Slasher and Free Spirit characters bypass all defensive Buffs, deals 20x character's ATK in fixed PSY damage to one enemy.", + "cooldown": [ 18, 13 ] + }, + { + "description": "Makes Damage and Health Cutting Specials of all characters bypass all defensive Buffs, deals 50x character's ATK in fixed PSY damage to one enemy.", + "cooldown": [ 25, 20 ] + } + ], + specialNotes: "#{stages}" + }, + 1046: { + captain: "Boosts ATK of Free Spirit characters by 2.75x following a chain of Good > Great > Perfect hits", + specialName: "Dragon Claw Fist: Dragon's Breath", + special: "Deals random typeless damage to all enemies. Adds 55x character's ATK as Additional Typeless Damage for 2 turns", + specialNotes: "#{random : 10,000 : 30,000}
    Extra Damage can only be boosted by conditional Boosters" + }, + 1047: { + captain: "Boosts ATK of Free Spirit characters by 3.5x following a chain of Good > Great > Perfect hits", + specialName: "Dragon Claw Fist: Dragon's Breath", + special: "Deals random typeless damage to all enemies. Adds 55x character's ATK as Additional Typeless Damage for 2 turns", + specialNotes: "#{random : 10,000 : 30,000}
    Extra Damage can only be boosted by conditional Boosters" + }, + 1048: { + captain: "Boosts ATK and RCV of [PSY] characters by 1.2x", + special: "Reduces Paralysis duration by 3 turns and Recovers 4x character's RCV in HP at the end of each turn for 3 turns", + specialName: "Mother's Wish to Fight The World" + }, + 1049: { + captain: "Boosts ATK and RCV of [PSY] characters by 1.5x, when HP is low the ATK multiplier becomes 2.25x", + captainNotes: "The low HP threshold is estimated to be 30%", + special: "Reduces Paralysis duration by 3 turns and Recovers 4x character's RCV in HP at the end of each turn for 3 turns", + specialName: "Mother's Wish to Fight The World" + }, + 1050: { + captain: "Boosts ATK of [PSY] characters by 1.5x", + special: "Reduces Bind duration by 4 turns, and Reduces damage received by 50% for 2 turns", + specialName: "Dereshishishi Towards Hope" + }, + 1051: { + captain: "Boosts ATK of [PSY] characters by 2x", + special: "Reduces Bind duration by 4 turns, and Reduces damage received by 50% for 2 turns", + specialName: "Dereshishishi Towards Hope" + }, + 1052: { + captain: "Recovers 1,000 HP at the end of each turn", + special: "Reduces Silence duration by 2 turns", + specialName: "Knowledge the World is Afraid of", + specialNotes: "#{silence}", + }, + 1053: { + captain: "Boosts RCV of Cerebral characters by 1.5x", + special: "Reduces Paralysis and Despair duration by 3 turns, removes Blindness", + specialName: "Precocious Provocation" + }, + 1054: { + captain: "Boosts RCV of Cerebral characters by 2x", + special: "Reduces Paralysis and Despair duration by 3 turns, removes Blindness", + specialName: "Precocious Provocation" + }, + 1055: { + special: "Deals 20x character's ATK in [DEX] damage to one enemy. Boosts ATK against Strongly Poisoned enemies by 1.4x for 2 turns ", + specialName: "Snake Press" + }, + 1056: { + captain: "Boosts ATK of Powerhouse characters by 2x and their RCV by 1.25x", + special: "Deals 20x character's ATK in [DEX] damage to one enemy. Boosts ATK against Strongly Poisoned enemies by 1.4x for 2 turns ", + specialName: "Snake Press" + }, + 1057: { + special: "Strongly Poisons one enemy", + specialNotes: "Strong Poison deals 5x character's ATK in fixed damage at the end of each turn", + specialName: "Deadly Poisonous Corrosive Liquid" + }, + 1058: { + captain: "Boosts ATK of Powerhouse characters by 2x and their HP by 1.25x", + special: "Strongly Poisons one enemy", + specialNotes: "Strong Poison deals 5x character's ATK in fixed damage at the end of each turn", + specialName: "Deadly Poisonous Corrosive Liquid" + }, + 1059: { + captain: "Boosts ATK and RCV of Shooter characters by 1.2x", + special: "Deals 5,000 fixed damage to one enemy. Amplifies the effect of orbs by 1.5x for 1 turn", + specialNotes: "#{orb : 1.5x}", + specialName: "Strong Bow of Rejection" + }, + 1060: { + captain: "Boosts ATK and RCV of Shooter characters by 1.5x", + special: "Deals 5,000 fixed damage to one enemy. Amplifies the effect of orbs by 1.5x for 1 turn", + specialNotes: "#{orb : 1.5x}", + specialName: "Strong Bow of Rejection" + }, + 1061: { + captain: "Boosts ATK of Shooter characters by 2x", + special: "Locks the chain multiplier at 2x for 2 turns", + specialName: "Instructions to the Warriors" + }, + 1062: { + captain: "Boosts ATK of Cerebral characters by 2x and Recovers 2x character's RCV in HP at the end of each turn", + special: "Recovers 13x character's RCV in HP", + specialName: "Timeless Art of Self-Defense" + }, + 1063: { + captain: "Boosts ATK and HP of Shooter characters by 1.2x", + special: "Boosts ATK of Shooter characters by 1.3x for 1 turn", + specialName: "Shooting Power Light" + }, + 1064: { + captain: "Boosts ATK and HP of [INT] characters by 1.2x", + special: "Recovers 3x character's RCV in HP at the end of each turn for 5 turns", + specialName: "Auto Repair" + }, + 1065: { + captain: "Boosts ATK of Slasher characters by 1.5x", + special: "Amplifies the effect of orbs by 1.25x for 1 turn", + specialNotes: "#{orb : 1.25x}", + specialName: "Slot Power Light" + }, + 1066: { + captain: "Boosts ATK and HP of [PSY] characters by 1.2x", + special: "Adds .1x to Chain multiplier for 1 turn", + specialName: "Chain Plus Light" + }, + 1067: { + captain: "Boosts ATK of Fighter characters by 1.5x", + special: "Boosts own ATK by 1.5x for 1 turn", + specialName: "Attack Boost Light" + }, + 1068: { + captain: "Boosts chain multiplier by 1.5x", + special: "Changes captain's orb into [QCK]", + specialName: "Captain Slot Change QCK" + }, + 1069: { + captain: "Boosts ATK of Driven characters by 1.5x", + special: "Deals 9x ATK in [DEX] damage to one enemy. Changes own orb into [DEX]", + specialName: "Fighting Method of the Pirate Executioner" + }, + 1070: { + captain: "Boosts ATK of Driven characters by 2.25x", + special: "Deals 9x ATK in [DEX] damage to one enemy. Changes own orb into [DEX]", + specialName: "Fighting Method of the Pirate Executioner" + }, + 1071: { + captain: "Boosts ATK of characters with cost 20 or less by 1.5x", + special: "Deals 20x ATK in [STR] damage to one enemy. Boosts ATK of Powerhouse characters by 1.5x for 1 turn.", + specialName: "Emerald Porcupine Robe" + }, + 1072: { + captain: "Boosts ATK of characters with cost 20 or less by 2x and boosts the HP of Powerhouse characters by 1.2x", + special: "Deals 20x ATK in [STR] damage to one enemy. Boosts ATK of Powerhouse characters by 1.5x for 1 turn.", + specialName: "Emerald Porcupine Robe" + }, + 1073: { + captain: "Boosts ATK of Slasher characters by 1.5x", + special: "Deals 5x ATK in [QCK] damage to all enemies and randomizes all orbs", + specialName: "Drilling Hooks" + }, + 1074: { + captain: "Boosts ATK of [INT] characters by 2x", + special: "Changes [QCK] and [PSY] orbs into [INT] orbs.", + specialName: "Tenacious Sword of Destruction" + }, + 1075: { + captain: "Boosts ATK and HP of [INT] characters by 2x", + special: "Changes [QCK] and [PSY] orbs into [INT] orbs.", + specialName: "Tenacious Sword of Destruction", + limit: "This character has a limit break path", + }, + 1076:{ + captain: "Boosts ATK of Striker and Free Spirit characters by 1.75x", + special: [ + { + "description": "Delays all enemies for 1 turn. Locks all orbs for 1 turn. Cuts the current HP of all enemies by 10%", + "cooldown": [ 16, 12 ] + }, + { + "description": "Delays all enemies for 1 turn. Locks all orbs for 1 turn. Cuts the current HP of all enemies by 20%", + "cooldown": [ 20, 16 ] + } + ], + specialNotes: "#{stages}", + specialName: "Haute Couture: Patchwork" + }, + 1077:{ + captain: "Boosts ATK of Striker and Free Spirit characters by 2.25x and their RCV by 1.5x", + special: [ + { + "description": "Delays all enemies for 1 turn. Locks all orbs for 1 turn. Cuts the current HP of all enemies by 10%", + "cooldown": [ 16, 12 ] + }, + { + "description": "Delays all enemies for 1 turn. Locks all orbs for 1 turn. Cuts the current HP of all enemies by 20%", + "cooldown": [ 20, 16 ] + } + ], + specialNotes: "#{stages}", + specialName: "Haute Couture: Patchwork", + limit: [ + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 40" }, + { "description": "Aquire Potential 1: Pinch Healing" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base RCV by 50" }, + { "description": "Aquire Sailor Ability 1: Boosts ATK of Striker characters by 30" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base HP by 100" }, + { "description": "Aquire new Captain Ability: Boosts ATK of Striker and Free Spirit characters by 2.45x and their RCV by 1.5x" }, + { "description": "Aquire Sailor Ability 2: Boosts this character's attack against DEX characters by 2x" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "Pinch Healing", + "description": [ + "Level 1: If HP is below 10% at the start of the turn, heals for .5x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 2: If HP is below 15% at the start of the turn, heals for .5x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 3: If HP is below 20% at the start of the turn, heals for .5x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 4: If HP is below 30% at the start of the turn, heals for .5x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 5: If HP is below 30% at the start of the turn, heals for 1x this character's RCV at the end of the turn each time you hit a Perfect" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 1 turn on this character", + "Level 2: Reduces Slot Bind duration by 2 turns on this character", + "Level 3: Reduces Slot Bind duration by 3 turns on this character", + "Level 4: Reduces Slot Bind duration by 4 turns on this character", + "Level 5: Reduces Slot Bind duration by 5 turns on this character" + ] + }, + ] + }, + 1078: { + captain: "Recovers 3x character's RCV in HP at the end of each turn", + special: [ + { + "description": "Recovers 6x character's RCV in HP. Reduces Paralysis duration by 3 turns", + "cooldown": [ 14, 8 ] + }, + { + "description": "Recovers 15x character's RCV in HP. Removes Paralysis, Poison, RCV Down, and Blindness", + "cooldown": [ 19, 13 ] + }, + { + "description": "Recovers 50x character's RCV in HP. Removes Paralysis, Poison, RCV Down, and Blindness", + "cooldown": [ 24, 18 ] + }, + ], + specialNotes: "#{stages}", + specialName: "Chiyupopo" + }, + 1079: { + captain: "Recovers 4x character's RCV in HP at the end of each turn", + special: [ + { + "description": "Recovers 6x character's RCV in HP. Reduces Paralysis duration by 3 turns", + "cooldown": [ 14, 8 ] + }, + { + "description": "Recovers 15x character's RCV in HP. Removes Paralysis, Poison, RCV Down, and Blindness", + "cooldown": [ 19, 13 ] + }, + { + "description": "Recovers 50x character's RCV in HP. Removes Paralysis, Poison, RCV Down, and Blindness", + "cooldown": [ 24, 18 ] + }, + ], + specialNotes: "#{stages}", + specialName: "Chiyupopo", + limit: [ + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Aquire Potential 1: [INT] Damage Reduction" }, + { "description": "Boosts base HP by 50" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Aquire Sailor Ability 1: Reduces Paralysis for 1 turn for herself" }, + { "description": "Boosts base HP by 55" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base ATK by 45" }, + { "description": "Aquire Sailor Ability 2: Reduces Silence duration against this unit by 2 turns" }, + { "description": "Boosts base HP by 65" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Reduce No Healing duration" }, + ], + potential: [ + { + "Name": "[INT] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [INT] characters by 1%", + "Level 2: Reduce damage taken from [INT] characters by ?%", + "Level 3: Reduce damage taken from [INT] characters by ?%", + "Level 4: Reduce damage taken from [INT] characters by ?%", + "Level 5: Reduce damage taken from [INT] characters by ?%" + ] + }, + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: Reduces No Healing duration by 1 turn", + "Level 2: Reduces No Healing duration by ? turn", + "Level 3: Reduces No Healing duration by ? turns", + "Level 4: Reduces No Healing duration by ? turns", + "Level 5: Reduces No Healing duration by ? turns" + ] + }, + ] + }, + 1080: { + captain: "Boosts ATK of characters with cost 20 or less by 2.5x", + special: "Deals [DEX] damage to one enemy, changes own orb to [DEX] and boosts own ATK by 2x for 1 turn", + specialName: "Trueno Bastardo" + }, + 1081: { + captain: "Boosts ATK of characters with cost 30 or less by 2.5x", + special: "Deals [DEX] damage to one enemy, changes own orb to [DEX] and boosts own ATK by 2x for 1 turn", + specialName: "Trueno Bastardo", + limit: "This character has a limit break path", + }, + 1082: { + captain: "Boosts ATK of Striker and Fighter characters by 1.2x", + special: "Deals 20x ATK in [STR] damage to all enemies. For 2 turns, boosts ATK of Striker and Fighter characters by a variable amount depending on the current HP at the time the special was activated.", + specialNotes: "Below 30% -> 1.75 boost, between 30% and 70% -> 1.5, above 70% -> 1.2", + specialName: "Drill Dragon: Drill Nail" + }, + 1083: { + captain: "Boosts ATK of Striker and Fighter characters by 1.5x at the start of the chain, and by 3x after the 3rd Perfect in a row", + special: "Deals 20x ATK in [STR] damage to all enemies. For 2 turns, boosts ATK of Striker and Fighter characters by a variable amount depending on the current HP at the time the special was activated.", + specialNotes: "Below 30% -> 1.75 boost, between 30% and 70% -> 1.5, above 70% -> 1.2", + specialName: "Drill Dragon: Drill Nail", + limit: [ + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base RCV by 40" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base HP by 10" }, + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Aquire Sailor Ability 1: Restores his own special by 2 turns when it is rewinded" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Reduce base Special Cooldown by 2 turns" }, + { "description": "Boosts base ATK by 100" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Reduce base Special Cooldown by 2 turns" }, + { "description": "Aquire Sailor Ability 2: Makes [QCK] orbs \"beneficial\" for this unit" }, + { "description": "Aquire Potential 2: Enrage" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 5% chance to deal 5% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 5% chance to deal 7% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 5% chance to deal 10% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 10% chance to deal 10% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 15% chance to deal 15% of this character's attack in extra damage" + ] + }, + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 30", + "Level 2: Boosts base ATK by 60", + "Level 3: Boosts base ATK by 90", + "Level 4: Boosts base ATK by 100", + "Level 5: Boosts base ATK by 150" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1084: { + captain: "Boosts HP of Driven characters by 1.5x and boosts ATK by 3x if they have a matching orb, by 1.5x otherwise. Makes [TND] and [RCV] orbs \"beneficial\" to Driven characters", + special: "Cuts the current HP of each enemy by 20%. At the end of the turn, cuts the current HP of each enemy by 20% for 3 turns", + specialNotes: "Does not stack with other 'end of turn damage' abilities", + specialName: "Gravito: Heavens Fall" + }, + 1085: { + captain: "Boosts HP of Driven characters by 1.5x and boosts ATK by 3x if they have a matching orb, by 1.5x otherwise. Makes [TND] and [RCV] orbs \"beneficial\" to Driven characters", + special: "Cuts the current HP of each enemy by 20%. At the end of the turn, cuts the current HP of each enemy by 20% for 3 turns", + specialNotes: "Does not stack with other 'end of turn damage' abilities", + specialName: "Gravito: Heavens Fall", + limit: [ + { "description": "Boosts base HP by 25" }, + { "description": "Boosts base HP by 25" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Aquire Potential 1: Enrage" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Aquire Sailor Ability 1: Cannot be Blown Away" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Aquire Potential 2: Critical Hit" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base HP by 60" }, + { "description": "Aquire Sailor Ability 2: Boosts ATK, HP and RCV of Powerhouse and Driven characters by 50" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Boosts base HP by 60" }, + { "description": "Reduce base Special Cooldown by 1" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Boosts base HP by 70" }, + { "description": "Boosts base HP by 80" }, + { "description": "Boosts base HP by 100" }, + { "description": "Aquire Potential 3: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 20", + "Level 2: Boosts base ATK by 40", + "Level 3: Boosts base ATK by 60", + "Level 4: Boosts base ATK by 80", + "Level 5: Boosts base ATK by 100" + ] + }, + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 30% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 40% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 50% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 50% chance to deal 10% of this character's attack in extra damage" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 3 turn on this character", + "Level 2: Reduces Slot Bind duration by 5 turns on this character", + "Level 3: Reduces Slot Bind duration by 7 turns on this character", + "Level 4: Reduces Slot Bind duration by 10 turns on this character", + "Level 5: Reduces Slot Bind completely on this character" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1086: { + captain: "Boosts ATK and RCV of Driven characters by 1.5x", + specialNotes: "#{orb : 1.5x}", + special: "Randomizes all orbs including [BLOCK] orbs. Amplifies the effect of orbs by 1.5x for 2 turns", + specialName: "Lot Stiffen" + }, + 1087: { + captain: "Boosts ATK of Driven characters by 2x and their RCV by 1.5x", + specialNotes: "#{orb : 1.5x}", + special: "Randomizes all orbs including [BLOCK] orbs. Amplifies the effect of orbs by 1.5x for 2 turns", + specialName: "Lot Stiffen" + }, + 1088: { + captain: "Boosts ATK of Slasher characters by 2x", + special: "Reduces crew's HP by 70%, deals 15x ATK in [QCK] damage to all enemies. Boosts ATK of Slasher and Driven characters by 1.5x for 1 turn.", + specialName: "Seven Stars Sword of Darkness" + }, + 1089: { + captain: "Boosts ATK of Slasher characters by 2x and boosts HP of Driven characters by 1.75x", + captainNotes: "Slasher + Driven characters gain ATK AND HP", + special: "Reduces crew's HP by 70%, deals 15x ATK in [QCK] damage to all enemies. Boosts ATK of Slasher and Driven characters by 1.5x for 1 turn.", + specialName: "Seven Stars Sword of Darkness" + }, + 1090: { + captain: "Boosts ATK of all characters by 2x if HP is below 30% at the start of the turn", + special: "Deals 25x ATK in [PSY] damage to one enemy. If HP < 30% then changes adjacent orbs into matching orbs", + specialName: "Double Edge of Revolt" + }, + 1091: { + captain: "Boosts ATK of all characters by 2.5x if HP is below 30% at the start of the turn", + special: "Deals 25x ATK in [PSY] damage to one enemy. If HP < 30% then changes adjacent orbs into matching orbs", + specialName: "Double Edge of Revolt" + }, + 1092: { + captain: "Boosts RCV of all characters depending on the current Health.", + captainNotes: "The Lower the Health the Higher the Bonus, at 1HP the multiplier is 1.5x", + special: "Changes the Friend Captains orb into a matching Orb, recovers 3.000HP", + specialName: "Present After the Rain" + }, + 1093: { + captain: "Boosts RCV of all characters depending on the current Health.", + captainNotes: "The Lower the Health the Higher the Bonus, at 1HP the multiplier is 2x", + special: "Changes the Friend Captains orb into a matching Orb, recovers 3.000HP", + specialName: "Present After the Rain" + }, + 1094: { + captain: "Boosts ATK of Cerebral characters by 2x.", + special: "Reduces crew's current HP by 80%, deals 6x the removed HP as damage to all enemies. Reduces damage received by 80% for 1 turn.", + specialName: "Mass Juggling" + }, + 1095: { + captain: "Boosts ATK of Cerebral characters by 2x.", + special: "Reduces crew's current HP by 80%, deals 6x the removed HP as damage to all enemies. Reduces damage received by 80% for 1 turn.", + specialName: "Mass Juggling" + }, + 1096: { + captain: "Boosts ATK of Powerhouse characters by 3x after the 5th Perfect in a row.", + special: "Deals [INT] damage to one enemy. Boosts own ATK by 1.75x for 1 turn.", + specialName: "Crash Drumming" + }, + 1097: { + captain: "Boosts ATK of Powerhouse characters by 3.5x after the 5th Perfect in a row.", + special: "Deals [INT] damage to one enemy. Boosts own ATK by 1.75x for 1 turn.", + specialName: "Crash Drumming" + }, + 1098: { + captain: "Boosts chain multiplier by 2x", + special: "Randomizes all orbs including [BLOCK] orbs and switches orbs between slots once.", + specialName: "Mutation-Induced Thunder" + }, + 1099: { + captain: "Boosts ATK of Fighter characters by 2x", + special: "Changes Badly Matching orbs into [EMPTY] orbs, amplifies the effect of orbs by 1.5x for 2 turns", + specialName: "\"To the End of the Clouds\"" + }, + 1100: { + captain: "Boosts ATK of Fighter characters by 2.25x and their RCV by 1.2x", + special: "Changes Badly Matching orbs into [EMPTY] orbs, amplifies the effect of orbs by 1.5x for 2 turns", + specialName: "\"To the End of the Clouds\"" + }, + 1101: { + captain: "Boosts ATK of all characters by 2.25x until the first hit other than Perfect. Reduces crew's current HP by 10% at the end of each turn", + special: "Reduces crew's current HP by 80%, deals 10x the amount of HP subtracted in typeless damage to one enemy. Boosts ATK of [STR] and [INT] characters by 1.75x for 1 turn", + specialName: "Black Arm's Last Impact" + }, + 1102: { + captain: "Boosts ATK of all characters by 2.75x until the first hit other than Perfect. Reduces crew's current HP by 10% at the end of each turn", + special: "Reduces crew's current HP by 80%, deals 10x the amount of HP subtracted in typeless damage to one enemy. Boosts ATK of [STR] and [INT] characters by 1.75x for 1 turn", + specialName: "Black Arm's Last Impact" + }, + 1103: { + captain: "Boosts ATK and RCV of Cerebral characters by 1.5x", + special: [ + { + "description": "Recovers 12% of crew's MAX HP and randomizes all orbs including [BLOCK] orbs", + "cooldown": [ 21, 11 ] + }, + { + "description": "Recovers 24% of crew's MAX HP and randomizes all orbs including [BLOCK] orbs", + "cooldown": [ 24, 14 ] + }, + { + "description": "Recovers 36% of crew's MAX HP and randomizes all orbs including [BLOCK] orbs", + "cooldown": [ 27, 17 ] + }, + ], + specialNotes: "#{stages}", + specialName: "Return Return Fruit" + }, + 1104: { + captain: "Boosts ATK and RCV of Cerebral characters by 1.75x", + special: [ + { + "description": "Recovers 12% of crew's MAX HP and randomizes all orbs including [BLOCK] orbs", + "cooldown": [ 21, 11 ] + }, + { + "description": "Recovers 24% of crew's MAX HP and randomizes all orbs including [BLOCK] orbs", + "cooldown": [ 24, 14 ] + }, + { + "description": "Recovers 36% of crew's MAX HP and randomizes all orbs including [BLOCK] orbs", + "cooldown": [ 27, 17 ] + }, + ], + specialNotes: "#{stages}", + specialName: "Return Return Fruit" + }, + 1105: { + captain: "Boosts ATK of Striker and Free Spirit characters by 1.5x, deals 2x character's ATK in typeless damage to all enemies at the end of each turn", + special: "Delays all enemies for 1 turn. Adds .2x to Chain multiplier for 2 turns. Makes Perfects easier to hit for 2 turns.", + specialName: "Mosa Mosa Dance" + }, + 1106: { + captain: "Boosts ATK of Striker and Free Spirit characters by 2x, deals 2x character's ATK in typeless damage to all enemies at the end of each turn", + special: "Delays all enemies for 1 turn. Adds .2x to Chain multiplier for 2 turns. Makes Perfects easier to hit for 2 turns.", + specialName: "Mosa Mosa Dance" + }, + 1107: { + captain: "Boosts ATK and HP of Driven characters by 1.5x", + special: "Deals 30x the character's ATK as Typeless damage to all enemies. Changes [BLOCK], [G], and [BOMB] orbs into Matching orbs for Driven characters. Boosts ATK of Driven characters by 1.75x for 1 turn.", + specialName: "Lion's Threat: Imperial Earth Bind" + }, + 1108: { + captain: "Boosts ATK and HP of Driven characters by 2x", + special: "Deals 30x the character's ATK as Typeless damage to all enemies. Changes [BLOCK], [G], and [BOMB] orbs into Matching orbs for Driven characters. Boosts ATK of Driven characters by 1.75x for 1 turn.", + specialName: "Lion's Threat: Imperial Earth Bind" + }, + 1109: { + captain: "Boosts amount of Beli received by 1.5x", + special: "Changes [BLOCK] orbs into [PSY] orbs for [PSY] characters", + specialName: "Cat Burglar's Undercover Investigation" + }, + 1110: { + captain: "Boosts ATK and RCV of [PSY] characters by 1.25x and the amount of Beli received by 1.5x", + special: "Changes [BLOCK] orbs into [PSY] orbs for [PSY] characters", + specialName: "Cat Burglar's Undercover Investigation" + }, + 1111: { + captain: "Boosts ATK and RCV of Cerebral characters by 1.25x", + special: "Amplifies the effect of orbs by 1.25x for 3 turns, recovers 8x character's RCV at the end of the turn for 3 turns.", + specialName: "Impish Sultry Dance" + }, + 1112: { + captain: "Boosts ATK and RCV of Cerebral characters by 1.5x", + special: "Amplifies the effect of orbs by 1.25x for 3 turns, recovers 8x character's RCV at the end of the turn for 3 turns.", + specialName: "Impish Sultry Dance" + }, + 1113: { + captain: "Boosts ATK of [INT] characters by 2x", + special: "Boosts ATK of all characters by 1.2x for 1 turn", + specialName: "Fury of the Little Monster: \"This is War!!!\"" + }, + 1114: { + special: "Reduces crew's current HP by 99%, deals 25x character's ATK in fixed damage to all enemies, boosts ATK of STR characters by 2x for 1 turn", + specialName: "Gum-Gum Gigant Axe", + specialNotes: "#{fixed}", + captain: "Boosts ATK of STR characters by 2x" + }, + 1115: { + special: "Reduces crew's current HP by 99%, deals 25x character's ATK in fixed damage to all enemies, boosts ATK of STR characters by 2x for 1 turn", + specialName: "Gum-Gum Gigant Axe", + specialNotes: "#{fixed}", + captain: "Boosts ATK of STR characters by 2.5x" + }, + 1116: { + special: "Deals several times the character's ATK in INT damage to all enemies", + specialNotes: "#{specialProportional : lower : 100 * ( 1 - (remaining HP) / (total HP) )}", + specialName: "Diable Jambe: Concassé", + captain: "Reduces damage received by 80% if HP is above 99% at the start of the turn", + sailor: "Reduces Paralysis by 3 turns for self" + }, + 1117: { + special: "Deals several times the character's ATK in INT damage to all enemies", + specialNotes: "#{specialProportional : lower : 100 * ( 1 - (remaining HP) / (total HP) )}", + specialName: "Diable Jambe: Concassé", + captain: "Reduces damage received by 80% if HP is above 99% at the start of the turn", + sailor: "Reduces Paralysis by 3 turns for self" + }, + 1118: { + special: "Randomizes all orbs, protects from defeat as long as HP is above 50% for 1 turn", + specialName: "10,000-Carat Smile", + specialNotes: "#{zombie}", + captain: "Boosts ATK and RCV of Striker characters by 1.5x", + sailor: "Makes [DEX] orbs \"beneficial\" for this unit" + }, + 1119: { + special: "Randomizes all orbs, protects from defeat as long as HP is above 50% for 1 turn", + specialName: "10,000-Carat Smile", + specialNotes: "#{zombie}", + captain: "Boosts ATK of Striker characters by 2x and their RCV by 1.5x", + sailor: "Makes [DEX] orbs \"beneficial\" for this unit" + }, + 1120: { + special: "Deals random typeless damage to all enemies, changes own orb into [STR]", + specialName: "Gum-Gum JET Gatling", + specialNotes: "#{random : 70,000 : 200,000}", + captain: "Boosts ATK by 4x following a chain of Good > Great > Perfect hits" + }, + 1121: { + special: "Deals random typeless damage to all enemies, changes own orb into [STR]", + specialName: "Gum-Gum JET Gatling", + specialNotes: "#{random : 70,000 : 200,000}", + captain: "Boosts ATK by 4x following a chain of Good > Great > Perfect hits" + }, + 1122: { + captain: "Boosts ATK of [STR], [DEX], and [QCK] characters by 2.5x, but boosts his OWN attack by 4x", + captainNotes: "Cavendish only boosts Friend or Sub Cavendish by 2.5x for a total of 10x boost with two Cavendish captains", + special: "Removes all positive buffs on your team. Deals 15x the character's ATK as Typeless damage to all enemies. Boosts own ATK by 2.25x for 2 turns, amplifies the effect of own orb by 1.5x for 2 turns, locks his orb for 2 turns, and changes own orb to [QCK].", + specialNotes: "Boosted ATK and Orb Effectivess only works for the character who uses their own Special.", + specialName: "Slicing Winds of Rommel" + }, + 1123: { + captain: "Boosts ATK of [STR], [DEX], and [QCK] characters by 2.5x, but boosts his OWN attack by 4x", + captainNotes: "Cavendish only boosts Friend or Sub Cavendish by 2.5x for a total of 10x boost with two Cavendish captains", + special: "Removes all positive buffs on your team. Deals 15x the character's ATK as Typeless damage to all enemies. Boosts own ATK by 2.25x for 2 turns, amplifies the effect of own orb by 1.5x for 2 turns, locks his orb for 2 turns, and changes own orb to [QCK].", + specialNotes: "Boosted ATK and Orb Effectivess only works for the character who uses their own Special.", + specialName: "Slicing Winds of Rommel" + }, + 1124: { + captain: "Boosts ATK of Slasher characters by 3x, reduces his own ATK multiplier by 0.1x at the end of each turn", + captainNotes: "His ATK multiplier will be 3x on the first turn, 2.9x on the second, 2.8x on the third and so on. The reduction stops once the multiplier is 1.0x. The multiplier affects all Slasher characters.", + special: "Deals 13x character's ATK in [PSY] damage to all enemies, changes own orb and captain's orb into Matching orbs.", + specialName: "Idle Execution" + }, + 1125: { + captain: "Boosts ATK of Slasher characters by 3.5x, reduces his own ATK multiplier by 0.1x at the end of each turn", + captainNotes: "His ATK multiplier will be 3.5x on the first turn, 3.4x on the second, 3.3x on the third and so on. The reduction stops once the multiplier is 1.0x. The multiplier affects all Slasher characters.", + special: "Deals 13x character's ATK in [PSY] damage to all enemies, changes own orb and captain's orb into Matching orbs.", + specialName: "Idle Execution" + }, + 1126: { + captain: "Boosts ATK and HP of [DEX] characters by 1.5x", + special: "Empties all slots with [BLOCK] orbs, deals severe typeless damage based on number of [BLOCK] slots emptied to all enemies. Changes [EMPTY] orbs into Matching orbs", + specialNotes: "The exact multiplier used is chosen based on the number of [BLOCK] orbs consumed: 0 orbs - Cannot Activate; 1 orb - 20x ATK; 2 orbs - 40x ATK; 3 orbs - 100x ATK; 4 orbs - 200x ATK; 5 orbs - 300x ATK; 6 orbs - 500x ATK.", + specialName: "Admiral Killer Bowling" + }, + 1127: {//orlumbus + captain: "Boosts ATK of [DEX] characters by 2.25x and their HP by 1.5x", + special: "Empties all slots with [BLOCK] orbs, deals severe typeless damage based on number of [BLOCK] slots emptied to all enemies. Changes [EMPTY] orbs into Matching orbs", + specialNotes: "The exact multiplier used is chosen based on the number of [BLOCK] orbs consumed: 0 orbs - Cannot Activate; 1 orb - 20x ATK; 2 orbs - 40x ATK; 3 orbs - 100x ATK; 4 orbs - 200x ATK; 5 orbs - 300x ATK; 6 orbs - 500x ATK.", + specialName: "Admiral Killer Bowling" + }, + 1128: { + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of all characters by 1.75x", + special: "Reduces Paralysis and Despair duration by 5 turns. Cuts the current HP of one enemy by 10%", + specialName: "Tactician's Savage Cut" + }, + 1129: { + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of all characters by 2x", + special: "Reduces Paralysis and Despair duration by 5 turns. Cuts the current HP of one enemy by 10%", + specialName: "Tactician's Savage Cut" + }, + 1130: { + captain: "Boosts ATK and HP of Fighter and Powerhouse characters by 1.5x", + special: [ + { + "description": "Deals 7x character's ATK in typeless damage to all enemies", + "cooldown": [ 12, 6 ] + }, + { + "description": "Deals 15x character's ATK in typeless damage to all enemies", + "cooldown": [ 20, 14 ] + }, + { + "description": "Deals 25x character's ATK in typeless damage to all enemies", + "cooldown": [ 26, 20 ] + }, + ], + specialNotes: "For each turn AFTER Elizabello's special reaches stage 3, damage is boosted by 23.75x per turn for an additional 20 turns, for a max damage of 500x character's ATK to all enemies.
    #{stages}", + specialName: "King Punch" + }, + 1131: { + captain: "Boosts ATK of Fighter and Powerhouse characters by 1.5x and their HP by 2x", + special: [ + { + "description": "Deals 7x character's ATK in typeless damage to all enemies", + "cooldown": [ 12, 6 ] + }, + { + "description": "Deals 15x character's ATK in typeless damage to all enemies", + "cooldown": [ 20, 14 ] + }, + { + "description": "Deals 25x character's ATK in typeless damage to all enemies", + "cooldown": [ 26, 20 ] + }, + ], + specialNotes: "For each turn AFTER Elizabello's special reaches stage 3, damage is boosted by 23.75x per turn for an additional 20 turns, for a max damage of 500x character's ATK to all enemies.
    #{stages}", + specialName: "King Punch" + }, + 1132: { + captain: "Boosts ATK and HP of Fighter characters by 1.5x", + special: [ + { + "description": "Deals severe [QCK] damage to all enemies, boosts ATK of Fighter characters by 1.5x for 1 turn", + "cooldown": [ 18, 12 ] + }, + { + "description": "Deals severe [QCK] damage to all enemies, boosts ATK of Fighter characters by 1.75x for 1 turn", + "cooldown": [ 23, 17 ] + } + ], + specialNotes: "#{stages}", + specialName: "Destruction Cannon" + }, + 1133: { + captain: "Boosts ATK of Fighter characters by 2.25x and their HP by 1.5x. Recovers 2x character's RCV in HP at the end of each turn", + special: [ + { + "description": "Deals severe [QCK] damage to all enemies, boosts ATK of Fighter characters by 1.5x for 1 turn", + "cooldown": [ 18, 12 ] + }, + { + "description": "Deals severe [QCK] damage to all enemies, boosts ATK of Fighter and Shooter characters by 1.75x for 1 turn", + "cooldown": [ 23, 17 ] + } + ], + specialNotes: "#{stages}", + specialName: "Destruction Cannon" + }, + 1134: { + captain: "Boosts ATK and RCV for Striker and Slasher characters by 1.2x", + special: "Reduces Special Cooldown of [INT] characters by 1 turn.", + specialName: "Non-Negotiable Quest", + }, + 1135: { + captain: "Boosts ATK and RCV for Striker and Slasher characters by 1.5x", + special: "Reduces Special Cooldown of [INT] characters by 1 turn.", + specialName: "Non-Negotiable Quest", + }, + 1136: { //Fortnight Fukuro + captain: "Boosts ATK and HP of [QCK] characters by 1.5x", + special: "For [QCK] characters, changes [TND] and [RCV] orbs into [QCK] orbs", + specialName: "Stern Beast: Secret Technique: 'Owl Thrasher' Sneak Attack" + }, + 1137: { //Fortnight Jabra + captain: "Boosts ATK of Powerhouse characters by 2.25x", + special: "Deals 13x character's ATK in [STR] damage to one enemy. For Free Spirit characters, amplifies the effects of orbs by 1.5x for 2 turns", + specialName: "Fatal Sneak Attack", + }, + 1138: { + captain: "Reduces damage received by 25%", + special: "Reduces damage received by 60%, and boosts ATK of Powerhouse and Fighter characters by 1.3x for 1 turn", + specialName: "Iron Mass: Ring Sneak Attack" + }, + 1139: { + captain: "Boosts ATK and RCV of Striker characters by 1.5x", + special: "Randomly changes all orbs, including [BLOCK] orbs, into either [STR], [DEX], [QCK], [PSY], or [INT] orbs", + specialName: "Lack of Pure Chi: Lion Finger Gun Sneak Attack" + }, + 1140: {// Coliseum Moria + captain: "Boosts ATK of Driven characters by 2x", + special: "Changes own orb into [DEX] and deals 300,000 Fixed damage to one enemy", + specialName: "Horn Blade Shadow" + }, + 1141: {// Coliseum Moria + captain: "Boosts ATK of Driven characters by 2.25x, recovers 3x character's RCV in HP at the end of each turn", + special: "Changes own orb into [DEX] and deals 300,000 Fixed damage to one enemy", + specialName: "Horn Blade Shadow" + }, + 1142: {// Coliseum Foxy + captain: "Boosts ATK of Free Spirit characters by 1.5x", + special: "Deals 15 hits of random [STR] damage to random enemies. Delays all enemies for 1 turn", + specialNotes: "#{randomHits : 15}", + specialName: "Gorilla Punch: Golden Strike" + }, + 1143: {// Coliseum Foxy + captain: "Boosts ATK of Free Spirit characters by 2x. Reduces cooldown of Free Spirit characters by 2 turns at the start of the fight", + special: "Deals 15 hits of random [STR] damage to random enemies. Delays all enemies for 1 turn", + specialNotes: "#{randomHits : 15}", + specialName: "Gorilla Punch: Golden Strike" + }, + 1144: {// Coliseum Porche + captain: "Boosts ATK of [PSY] characters by 1.75x", + special: "Deals 5x character's ATK in [PSY] damage to all enemies. Recovers 15x character's RCV in HP", + specialName: "Cutie Baton: Flower Shuriken" + }, + 1145: {// Coliseum Porche + captain: "Boosts ATK of [PSY] characters by 1.75x and their RCV by 1.5x", + special: "Deals 5x character's ATK in [PSY] damage to all enemies. Recovers 15x character's RCV in HP", + specialName: "Cutie Baton: Flower Shuriken" + }, + 1146:{ + specialName: "Bind Purge", + special: "Reduces Bind duration by 2 turns" + }, + 1147:{ + special: "Recovers 7x character's RCV in HP", + specialName: "Moderate Healing", + }, + 1148:{ + specialName: "Paralysis Recovery - Light", + special: "Reduces Paralysis by 1 turn" + }, + 1149:{ + special: "Deals 3x character's ATK in INT damage to all enemies, Poisons all enemies", + specialNotes: "#{poison}", + specialName: "Poison Attack", + }, + 1150:{ + special: "Changes Captain orb into Matching orb", + specialName: "Captain Orb Change", + }, + 1151: {//Minotaur + special: "Cuts the current HP of one enemy by 10%", + specialName: "Tough Jailer Beast: Spiked Club" + }, + 1152: { + special: "Deals 3 hits of 7x character's ATK in [INT] damage to random enemies.", + specialNotes: "#{randomHits : 3}", + specialName: "Shy Jailer Beast: Spiked Mace", + }, + 1153: { + special: "Reduces the defense of all enemies by 100% and boosts ATK of Powerhouse characters by 1.25x for 1 turn", + specialName: "Demon Lord's Roar" + }, + 1154: { + captain: "Boosts ATK of Powerhouse characters by 2x and their HP by 1.3x", + special: "Reduces crew's current HP by 30%. Boosts ATK of Powerhouse characters by 1.5x", + specialName: "Leader of the Jailers", + }, + 1155: { + special: "Deals 7x character's ATK in QCK damage to all enemies", + specialName: "Monsterous Appetite" + }, + 1156: { + captain: "Boosts ATK of Driven characters by 1.2x if HP is above 50% at the start of the turn", + special: "Removes Poison. Protects from defeat as long as HP is above 50% for 1 turn", + specialName: "Abyss Road", + specialNotes: "#{zombie}", + }, + 1157: { + captain: "Boosts ATK of Driven and Striker characters by 1.75x and protects from defeat as long as HP is above 50% at the start of the turn", + special: "Removes Poison. Protects from defeat as long as HP is above 50% for 1 turn", + specialName: "Abyss Road", + specialNotes: "#{zombie}", + }, + 1158: { + captain: "Boosts ATK of Shooter, Striker, and Powerhouse characters by 1.75x", + special: "Cuts the current HP of all enemies by 20%. Strongly Poisons one enemy, and Poisons all other enemies.", + specialNotes: "Strong Poison deals 5x character's ATK in fixed damage at the end of each turn. Regular Poison deals .5x character's ATK in fixed damage at the end of each turn.", + specialName: "Poison Puffer Fish" + }, + 1159: { + captain: "Boosts ATK of Shooter, Striker, and Powerhouse characters by 2.25x", + special: "Cuts the current HP of all enemies by 20%. Strongly Poisons one enemy, and Poisons all other enemies.", + specialNotes: "Strong Poison deals 5x character's ATK in fixed damage at the end of each turn. Regular Poison deals .5x character's ATK in fixed damage at the end of each turn.", + specialName: "Poison Puffer Fish" + }, + 1160: { + captain: "Boosts ATK and RCV of Free Spirit characters by 1.5x", + special: "Reduces Bind, Despair, and Silence duration by 3 turns, and recovers 2,000 HP", + specialNotes: "#{silence}", + specialName: "Open Sun" + }, + 1161: { + captain: "Boosts ATK of Free Spirit characters by 2x and their RCV by 1.5x", + special: "Reduces Bind, Despair, and Silence duration by 3 turns, and recovers 2,000 HP", + specialNotes: "#{silence}", + specialName: "Open Sun" + }, + 1162: {//Tesoro + captain: "Boosts ATK of [PSY] characters by 1.75x and boosts amount of Beli received by 1.5x", + special: "Deals large [PSY] damage to all enemies, and if HP is above 50%, changes all orbs to [PSY] orbs", + specialName: "Gold-Gold Fruit", + }, + 1163: {//Tesoro Evolved + captain: "Boosts ATK of PSY characters by 1.75x. Also boosts ATK of Driven and Cerebral characters by 1.5x. Boosts amount of Beli received by 2x", + captainNotes: "The two Boosts stack with each other so a PSY Driven or a PSY Cerebral Unit will be boosted by 2.625", + special: "Deals large [PSY] damage to all enemies, and if HP is above 50%, changes all orbs to [PSY] orbs", + specialName: "Gold-Gold Fruit", + }, + 1164: {//Carina + captain: "Boosts RCV of all characters by 1.2x", + special: "Boosts RCV by 1.5x for 1 turn and amplifies the effects of orbs by 1.5x for 1 turn", + specialName: "Sexy Diva", + }, + 1165: {//Carina Evolved + captain: "Boosts RCV of all characters by 1.5x", + special: "Boosts RCV by 1.5x for 1 turn and amplifies the effects of orbs by 1.5x for 1 turn", + specialName: "Sexy Diva", + }, + 1166: {//Baccarat + captain: "Gives chance of duplicating a drop upon completion of the island.", + captainNotes: "Does not work if she was not your captain upon starting the island. Stacks with other addional drop captains, giving you two chances of getting an extra drop.", + special: "Boosts chance of matching orbs and reduces the ATK of enemies for 1 turn", + specialName: "Lucky-Lucky Fruit", + }, + 1167: {//Baccarat Evolved + captain: "Boosts ATK of all characters by 1.2x. Gives chance of duplicating a drop upon completion of the island.", + captainNotes: "Does not work if she was not your captain upon starting the island. Stacks with other addional drop captains, giving you two chances of getting an extra drop.", + special: "Boosts chance of matching orbs and reduces the ATK of enemies for 1 turn", + specialName: "Lucky-Lucky Fruit", + }, + 1168: {//Dice + captain: "Boosts ATK of [STR] characters by 2x if HP is below 30% at the start of the turn", + special: "Boosts ATK of [STR] characters by a variable factor for 1 turn", + specialNotes: "The exact multiplier used is chosen based on the crew's current HP at the time the special is activated
    HP > 50%: 1.1x
    50% > HP > 30%: 1.25x
    30% > HP > 10%: 1.5x
    HP < 10%: 1.75x", + specialName: "Trump Card Dealer", + }, + 1169: {//Dice Evolved + captain: "Boosts ATK of [STR] characters proportionally to the crew's current HP", + captainNotes: "#{captainProportional : lower : 1 + 1.5 * (1 - (remaining HP) / (total HP)) : 1 : 2.5}", + special: "Boosts ATK of [STR] characters by a variable factor for 1 turn", + specialNotes: "The exact multiplier used is chosen based on the crew's current HP at the time the special is activated
    HP > 50%: 1.1x
    50% > HP > 30%: 1.25x
    30% > HP > 10%: 1.5x
    HP < 10%: 1.75x", + specialName: "Trump Card Dealer", + }, + 1170: {//Tanaka + captain: "Boosts ATK of [QCK] characters by 1.5x", + special: "Reduces Bind duration by 3 turns and swaps Badly Matching, [BLOCK], and [BOMB] orbs to [EMPTY]", + specialName: "Escape-Escape Fruit", + }, + 1171: {//Tanaka Evolved + captain: "Boosts ATK of [QCK] characters by 2x", + special: "Reduces Bind duration by 3 turns and swaps Badly Matching, [BLOCK], and [BOMB] orbs to [EMPTY]", + specialName: "Escape-Escape Fruit", + }, + 1172: { + special: "Deals random PSY damage to all enemies, randomizes all orbs", + specialName: "Three-Verse Humming: Arrow-Notch Slash", + captain: "Boosts ATK of PSY characters by 2x", + sailor: "Boosts base base RCV of PSY characters by 15" + }, + 1173: { + special: "Deals random PSY damage to all enemies, randomizes all orbs", + specialName: "Three-Verse Humming: Arrow-Notch Slash", + captain: "Boosts ATK of PSY characters by 2x, reduces damage received from INT enemies by 30%", + sailor: "Boosts base RCV of PSY characters by 15" + }, + 1174: { + special: "Changes adjacent orbs into [DEX], deals 1,000 fixed damage to all enemies", + specialName: "Ashura Ugui", + specialNotes: "#{fixed}", + captain: "Boosts ATK of DEX characters by 2.75x if HP is below 30% at the start of the turn", + sailor: "Boosts base ATK of Slasher characters by 20" + }, + 1175: { + special: "Changes adjacent orbs into [DEX], deals 1,000 fixed damage to all enemies", + specialName: "Ashura Ugui", + specialNotes: "#{fixed}", + captain: "Boosts ATK of DEX characters by 3x if HP is below 30% at the start of the turn", + sailor: "Boosts base ATK of Slasher characters by 20" + }, + 1176: { + special: "Removes Poison, recovers 15x character's RCV in HP", + specialName: "Devoted Healing - \"I'm Glad You are Safe\"", + captain: "Boosts ATK and RCV of DEX characters by 1.5x", + sailor: "When HP is below 30% at the start of the turn, boosts own RCV by 50" + }, + 1177: { + special: "Removes Poison, recovers 15x character's RCV in HP", + specialName: "Devoted Healing - \"I'm Glad You are Safe\"", + captain: "Boosts ATK and RCV of DEX characters by 2x", + sailor: "When HP is below 30% at the start of the turn, boosts own RCV by 50" + }, + 1178: { + captain: "Boosts ATK of [STR] characters by 2x if HP is above 99% at the start of the turn. Reduces damage received by 50%", + special: "Deals random typeless damage to all enemies. Randomizes all orbs including [BLOCK] orbs.", + specialName: "Not Rubber Gum-Gum Jet Gatling", + specialNotes: "#{random : 30,000 : 150,000}", + }, + 1179: { + captain: "Boosts ATK of [STR] characters by 2.75x if HP is above 99% at the start of the turn. Reduces damage received by 50%", + special: "Deals random typeless damage to all enemies. Randomizes all orbs including [BLOCK] orbs.", + specialName: "Not Rubber Gum-Gum Jet Gatling", + specialNotes: "#{random : 30,000 : 150,000}", + }, + 1181: { //Blenheim + captain: "Boosts ATK of [DEX] characters by 2.5x", + special: "Deals 15x character's ATK in [DEX] damage to all enemies. Makes [RCV] and [TND] orbs \"beneficial\" to Slasher characters for 3 turns", + specialName: "Anger of the Ki Sword", + sailor: "Makes [STR] orbs \"beneficial\" for this unit" + }, + 1182: { //Blenheim + captain: "Boosts ATK of [DEX] characters by 2.5x", + special: "Deals 15x character's ATK in [DEX] damage to all enemies. Makes [RCV] and [TND] orbs \"beneficial\" to Slasher characters for 3 turns", + specialName: "Anger of the Ki Sword", + sailor: "Makes [STR] orbs \"beneficial\" for this unit" + }, + 1183: { + captain: "Boosts ATK of [PSY] characters by 2.5x", + special: "Empties all slots with [PSY] orbs, deals several times the character's ATK in [PSY] damage to one enemy", + specialNotes: "The exact multiplier used is chosen based on the number of [PSY] orbs consumed: 1 orb will give a 13x multiplier, 2 orbs 19x, 3 orbs 26x, 4 orbs 65x, 5 orbs 130x, 6 orbs 230x. It's not possible to activate the special without consuming at least one [PSY] orb.", + specialName: "Brass Knuckle Destruction", + sailor: "If HP is above 99% at the start of the turn, boosts ATK of [PSY] characters by 75" + }, + 1184: { + captain: "Boosts ATK of [PSY] characters by 2.5x", + special: "Empties all slots with [PSY] orbs, deals several times the character's ATK in [PSY] damage to one enemy", + specialNotes: "The exact multiplier used is chosen based on the number of [PSY] orbs consumed: 1 orb will give a 13x multiplier, 2 orbs 19x, 3 orbs 26x, 4 orbs 65x, 5 orbs 130x, 6 orbs 230x. It's not possible to activate the special without consuming at least one [PSY] orb.", + specialName: "Brass Knuckle Destruction", + sailor: "If HP is above 99% at the start of the turn, boosts ATK of [PSY] characters by 75" + }, + 1185: { + captain: "Boosts ATK of Slasher and Cerebral characters by 1.75x. Gives chance of duplicating a drop upon completion of the island.", + captainNotes: "Does not work if he was not your captain upon starting the island. Stacks with other addional drop captains, giving you two chances of getting an extra drop.", + special: [ + { + "description": "Deals 4x character's ATK in [INT] damage to all enemies. Changes own orb into [INT].", + "cooldown": [ 8, 3 ], + }, + { + "description": "Deals 15x character's ATK in [INT] damage to all enemies. Changes own orb into [INT]. Reduces Special Cooldown of Slasher and Cerebral characters by 1 turn", + "cooldown": [ 17, 12 ], + } + ], + specialNotes : "#{stages}", + specialName: "Extreme Speed - One Sword Style, Ten Slashes", + sailor: "Restores his own special by 1 turn when it is rewinded", + sailorNotes: "#{rewind : 1}", + }, + 1186: { + captain: "Boosts ATK of Slasher and Cerebral characters by 1.75x. Gives chance of duplicating a drop upon completion of the island.", + captainNotes: "Does not work if he was not your captain upon starting the island. Stacks with other addional drop captains, giving you two chances of getting an extra drop.", + special: [ + { + "description": "Deals 4x character's ATK in [INT] damage to all enemies. Changes own orb into [INT].", + "cooldown": [ 8, 3 ], + }, + { + "description": "Deals 15x character's ATK in [INT] damage to all enemies. Changes own orb into [INT]. Reduces Special Cooldown of Slasher and Cerebral characters by 1 turn", + "cooldown": [ 17, 12 ], + } + ], + specialNotes : "#{stages}", + specialName: "Extreme Speed - One Sword Style, Ten Slashes", + sailor: "Restores his own special by 1 turn when it is rewinded", + sailorNotes: "#{rewind : 1}", + }, + 1187: { + captain: "Boosts ATK of [STR] characters by 2.5x", + special: "Deals 7 hits of random damage to random enemies. Reduces Bind and Despair duration by 3 turns", + specialNotes: "#{randomHits : 7}
    #{random : 5000 : 20000 : for each hit}", + specialName: "Advancing Continuous Sword Attack", + sailor: "Boosts base ATK, HP, and RCV of all characters by 20" + }, + 1188: { + captain: "Boosts ATK of [STR] characters by 2.5x", + special: "Deals 7 hits of random damage to random enemies. Reduces Bind and Despair duration by 3 turns", + specialNotes: "#{randomHits : 7}
    #{random : 5000 : 20000 : for each hit}", + specialName: "Advancing Continuous Sword Attack", + sailor: "Boosts base ATK, HP, and RCV of all characters by 20" + }, + 1189: { + captain: "Boosts ATK of [QCK] characters by 2.25x, makes [DEX] orbs \"beneficial\" to [QCK] characters", + captainNotes: "\"Beneficial\" orbs grant the same ATK boost as matching orbs.", + special: "Reduces enemy Barrier duration by 1 turn", + specialNotes: "Does not affect DEF Boost or % Damage reduction buffs. Reduces timers for Barriers such as Perfect/Great/Good Barriers, Combo Hit Barriers and Orb Hit Barriers", + specialName: "Break Bullet", + sailor: "Boosts base ATK of [QCK] characters by 40" + }, + 1190: { + captain: "Boosts ATK of [QCK] characters by 2.25x, makes [DEX] orbs \"beneficial\" to [QCK] characters", + captainNotes: "\"Beneficial\" orbs grant the same ATK boost as matching orbs.", + special: "Reduces enemy Barrier duration by 1 turn", + specialNotes: "Does not affect DEF Boost or % Damage reduction buffs. Reduces timers for Barriers such as Perfect/Great/Good Barriers, Combo Hit Barriers and Orb Hit Barriers", + specialName: "Break Bullet", + sailor: "Boosts base ATK of [QCK] characters by 40", + limit: "This character has a limit break path", + }, + 1191: { + captain: "Boosts ATK of all characters by 2x and their HP by 1.2x. If you defeat an enemy, increases ATK boost slighty. Stacks up to 8 times to a maximum of 3.5x.", + captainNotes: "If a character dies and revives, it counts as killing a character. If you did not defeat an enemy, lose all ATK boost stacks.", + special: "Increases duration of any Class/Type boosting buffs and Orb Amplification buffs by 1 turn", + specialName: "Ice Age", + }, + 1192: { + captain: "Boosts ATK of all characters by 2x and their HP by 1.2x. If you defeat an enemy, increases ATK boost slighty. Stacks up to 8 times to a maximum of 3.5x.", + captainNotes: "If a character dies and revives, it counts as killing a character. If you did not defeat an enemy, lose all ATK boost stacks.", + special: "Increases duration of any Class/Type boosting buffs and Orb Amplification buffs by 1 turn", + specialName: "Ice Age", + }, + 1193: { + captain: "Boosts ATK of Free Spirit characters by 2x", + special: "Recovers 13x character's RCV in HP and locks the chain multiplier at 2.5x for 1 turn", + specialName: "Sweet Style Petrification", + }, + 1194: { + captain: "Boosts ATK of Free Spirit characters by 2.5x", + special: "Recovers 13x character's RCV in HP and locks the chain multiplier at 2.5x for 1 turn", + specialName: "Sweet Style Petrification", + }, + 1195: { + captain: "Boosts ATK of Striker characters by 1.75x. Recovers 2x character's RCV in HP at the end of each turn", + special: "Reduces crew's current HP by 60%, deals 8x the amount of HP subtracted in typeless damage to all enemies. Boosts ATK of Striker characters by 1.75x for 1 turn", + specialName: "Split Air Hole", + }, + 1196: { + captain: "Boosts ATK of Striker characters by 2x. Recovers 5x character's RCV in HP at the end of each turn", + special: "Reduces crew's current HP by 60%, deals 8x the amount of HP subtracted in typeless damage to all enemies. Boosts ATK of Striker characters by 1.75x for 1 turn", + specialName: "Split Air Hole", + limit: "This character has a limit break path", + }, + 1197: { + captain: "Boosts ATK of Cerebral and Powerhouse characters by 2.5x if they have a matching orb, by 1x otherwise, reduces crew's RCV to 0", + special: "For Cerebral and Powerhouse characters, changes all orbs including [BLOCK] orbs to Badly Matching. Deals [INT] damage to all enemies", + specialName: "Investigator of Sorrow", + }, + 1198: { + captain: "Boosts ATK and RCV of Free Spirit characters by 1.5x", + special: "Empties all slots with [RCV] orbs, recovers 20% of crew's MAX HP", + specialName: "Appetite Or Sex Appeal - Has it Switched Yet!?", + }, + 1199: { + captain: "Boosts ATK and RCV of Free Spirit characters by 1.5x", + special: "Empties all slots with [RCV] orbs, recovers 20% of crew's MAX HP", + specialName: "Appetite Or Sex Appeal - Has it Switched Yet!?", + }, + 1200: { + captain: "Boosts ATK and RCV of Cerebral characters by 1.5x", + special: "Reduces Silence duration by 2 turns. If your HP is below 30%, changes top row into Matching Orbs", + specialName: "Passionate Look, 'I'm a Bad Guy...'", + specialNotes: "#{silence}", + sailor: "Reduces Silence duration against this unit by 2 turns", + sailorNotes: "#{silence}", + }, + 1201: { + captain: "Boosts ATK and RCV of Cerebral characters by 1.5x", + special: "Reduces Silence duration by 2 turns. If your HP is below 30%, changes top row into Matching Orbs", + specialName: "Passionate Look, 'I'm a Bad Guy...'", + specialNotes: "#{silence}", + sailor: "Reduces Silence duration against this unit by 2 turns", + sailorNotes: "#{silence}", + }, + 1202: { + captain: "Boosts ATK of Free Spirit characters by 1.5x", + specialName: "Session of Pirates", + special: "Changes [PSY] orbs on Free Spirit characters into matching orbs" + }, + 1203: { + captain: "Boosts ATK of Free Spirit characters by 2.25x", + specialName: "Session of Pirates", + special: "Changes [PSY] orbs on Free Spirit characters into matching orbs" + }, + 1204: { + captain: "Boosts ATK and RCV of Free Spirit characters by 1.2x", + specialName: "Awakening Tune Power", + special: "Deals 500 fixed damage to all enemies, changes [RCV] orbs into [QCK] and [TND] into [PSY] orbs" + }, + 1205: { + captain: "Boosts ATK and RCV of Free Spirit characters by 1.5x", + specialName: "Awakening Tune Power", + special: "Deals 500 fixed damage to all enemies, changes [RCV] orbs into [QCK] and [TND] into [PSY] orbs" + }, + 1206: { + captain: "Boosts HP by 1.3x", + specialName: "Chorus echoing in the sea", + special: "Protects from defeat as long as HP is above 50%", + specialNotes: "#{zombie}" + }, + 1207: { + special: "Boosts chances of getting [INT] orbs for 3 turns", + specialName: "Ochenta Fleur - Cuatro Manus Shock", + captain: "Boosts ATK and RCV of INT characters by 1.5x", + sailor: "Reduces Blindness duration by 3 turn" + }, + 1208: { + special: "Boosts chances of getting [INT] orbs for 3 turns", + specialName: "Ochenta Fleur - Cuatro Manus Shock", + captain: "Boosts ATK and RCV of INT characters by 2x", + sailor: "Reduces Blindness duration by 3 turn" + }, + 1209: { + special: "Delays all enemies for 3 turns, cuts the current HP of each enemy by 10%", + specialName: "Heavenly Dragon Star", + captain: "Boosts ATK of Shooter characters by 2x", + sailor: "Boosts base RCV of Shooter characters by 10" + }, + 1210: { + special: "Delays all enemies for 3 turns, cuts the current HP of each enemy by 10%", + specialName: "Heavenly Dragon Star", + captain: "Boosts ATK of Shooter characters by 2x and their RCV by 1.5x", + sailor: "Boosts base RCV of Shooter characters by 10", + limit: [ + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Boosts base HP by 80" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base HP by 120" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK of Shooter characters by 50" }, + { "description": "Aquire Potential 2: Reduce No Healing duration" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 10% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 15% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 20% chance to deal 10% of this character's attack in extra damage" + ] + }, + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: If there are 6 Shooter characters in your crew, reduces No Healing duration by 1 turn", + "Level 2: If there are 5 Shooter characters in your crew, reduces No Healing duration by 1 turn", + "Level 3: If there are 4 Shooter characters in your crew, reduces No Healing duration by 1 turn", + "Level 4: If there are 4 Shooter characters in your crew, reduces No Healing duration by 2 turns", + "Level 5: If there are 4 Shooter characters in your crew, reduces No Healing duration by 3 turns" + ] + }, + ] + }, + 1211: { + special: "Changes own orb into [STR], amplifies the effect of orbs by 1.5x for 2 turns", + specialNotes: "#{orb : 1.5x}", + specialName: "Roar! Zarley Davison", + captain: "Boosts ATK of STR characters by 2x, deals 2x character's ATK in STR damage to all enemies at the end of each turn", + sailor: "Boosts base ATK of Shooter characters by 20" + }, + 1212: { + special: "Changes own orb into [STR], amplifies the effect of orbs by 1.5x for 2 turns", + specialNotes: "#{orb : 1.5x}", + specialName: "Roar! Zarley Davison", + captain: "Boosts ATK of STR characters by 2.25x, deals 2x character's ATK in STR damage to all enemies at the end of each turn", + sailor: "Boosts base ATK of Shooter characters by 20" + }, + 1213: { + captain: "Boosts ATK of Slasher characters by 1.5x, the HP of Striker characters by 1.2x, and the RCV of Shooter characters by 1.2x", + specialName: "Exciting Transfiguration", + special: "Recovers 10x character's RCV in HP. For 4 turns, makes [BOMB] orbs \"beneficial\"", + specialNotes: "\"Beneficial\" orbs grant the same ATK boost as matching orbs while retaining their original function." + }, + 1214: { + captain: "Boosts ATK of Slasher characters by 2x, the HP of Striker characters by 1.25x, and the RCV of Shooter characters by 1.25x", + specialName: "Exciting Transfiguration", + special: "Recovers 10x character's RCV in HP. For 4 turns, makes [BOMB] orbs \"beneficial\"", + specialNotes: "\"Beneficial\" orbs grant the same ATK boost as matching orbs while retaining their original function." + }, + 1215: {//Gairam + captain: "Boosts ATK by 2.5x following a chain of [QCK] > [PSY] > [DEX] attacks no lower than Good", + special: "Deals 5 hits of 2,000 fixed damage to random enemies and reduces any damage received above 5,000 HP by 80% for 1 turn", + specialNotes: "#{randomHits : 5}", + specialName: "Totem Cube" + }, + 1216: {//Sebastian + captain: "Boosts ATK of Powerhouse characters by 2x and reduces damage received based on current HP by up to 20%", + captainNotes: "The lower the HP, the larger the damage reduction. At 50% HP you take 10% reduced damage", + special: "Reduces damage received by 50% for 1 turn, and changes own orb into [QCK]", + specialName: "Camouflage Air", + }, + 1217: {//Nightin + captain: "Boosts ATK and RCV of Cerebral characters by 1.5x", + special: "Reduces Paralysis and Bind duration by 2 turns. Deal 10x her ATK in [PSY] damage to one enemy", + specialName: "Catepillar Soul Shot", + }, + 1218: {//Hancock + captain: "Boosts ATK by 2.5x after scoring 3 Perfects in a row", + special: "Locks all orbs for 1 turn. If HP is below 30%, changes own orb and the captain's orb into matching. ", + specialName: "Everybody Confusing Fragrance", + }, + 1219: {//Byrnndi World Coliseum + captain: "Boosts ATK of Shooter characters by 1x. If you defeat an enemy, increases ATK boost slighty. Stacks up to 16 times to a maximum of 3x.", + captainNotes: "If a character dies and revives, it counts as killing a character. If you did not defeat an enemy, lose all ATK boost stacks.", + special: [ + { + "description": "Deals 7x character's ATK in [INT] damage to one enemy. Reduces crew's current HP by 50%. Boosts ATK of Shooter characters by 1.2x for 1 turn", + "cooldown": [ 22, 6 ], + }, + { + "description": "Deals 15x character's ATK in [INT] damage to one enemy. Reduces crew's current HP by 50%. Boosts ATK of Shooter characters by 1.5x for 1 turn", + "cooldown": [ 28, 12 ], + }, + { + "description": "Deals 25x character's ATK in [INT] damage to one enemy. Reduces crew's current HP by 50%. Boosts ATK of Shooter characters by 2x for 1 turn", + "cooldown": [ 34, 18 ], + }, + ], + specialNotes: "#{stages}", + specialName: "More More, 10 Times \"Iron Hammer\"", + }, + 1220: {//Byrnndi World Coliseum + captain: "Boosts ATK of Shooter characters by 1x. If you defeat an enemy, increases ATK boost slighty. Stacks up to 10 times to a maximum of 3.25x.", + captainNotes: "If a character dies and revives, it counts as killing a character. If you did not defeat an enemy, lose all ATK boost stacks.", + special: [ + { + "description": "Deals 7x character's ATK in [INT] damage to one enemy. Reduces crew's current HP by 50%. Boosts ATK of Shooter characters by 1.2x for 1 turn", + "cooldown": [ 22, 6 ], + }, + { + "description": "Deals 15x character's ATK in [INT] damage to one enemy. Reduces crew's current HP by 50%. Boosts ATK of Shooter characters by 1.5x for 1 turn", + "cooldown": [ 28, 12 ], + }, + { + "description": "Deals 25x character's ATK in [INT] damage to one enemy. Reduces crew's current HP by 50%. Boosts ATK of Shooter characters by 2x for 1 turn", + "cooldown": [ 34, 18 ], + }, + ], + specialNotes: "#{stages}", + specialName: "More More, 10 Times \"Iron Hammer\"", + limit: [ + { "description": "Boosts base HP by 10" }, + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Aquire Potential 1: Enrage" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base HP by 60" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Sailor Ability 1: Boosts own ATK by 100 if this character is the last in the chain to attack" }, + { "description": "Aquire Potential 2: Barrier Penetration" }, + ], + potential: [ + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 20", + "Level 2: Boosts base ATK by 30", + "Level 3: Boosts base ATK by 40", + "Level 4: Boosts base ATK by 50", + "Level 5: Boosts base ATK by 100" + ] + }, + { + "Name": "Barrier Penetration", + "description": [ + "Level 1: This character's attack will ignore barriers if HP is above 99%", + "Level 2: This character's attack will ignore barriers if HP is above 99%", + "Level 3: This character's attack will ignore barriers if HP is above 99%", + "Level 4: This character's attack will ignore barriers if HP is above 80%", + "Level 5: This character's attack will ignore barriers if HP is above 50%" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1221: {//Coliseum Oars Jr + captain: "Boosts ATK of Slasher characters by 1.75x and the HP of Powerhouse characters by 1.2x", + special: "Deals 25x character's ATK in [STR] damage to one enemy. For 1 turn, makes [STR] orb \"beneficial\" for all characters", + specialNotes: "\"Beneficial\" orbs grant the same ATK boost as matching orbs.", + specialName: "Blood of the Devil Warrior", + }, + 1222: {//Coliseum Oars Jr + captain: "Boosts ATK of Slasher characters by 2x and the HP of Powerhouse characters by 1.75x", + special: "Deals 25x character's ATK in [STR] damage to one enemy. For 1 turn, makes [STR] orb \"beneficial\" for all characters", + specialNotes: "\"Beneficial\" orbs grant the same ATK boost as matching orbs.", + specialName: "Blood of the Devil Warrior", + }, + 1223: { // Story Bastille + captain: "Boosts ATK of [INT] characters by 2x", + special: "Deals 25x character's ATK in [INT] damage to all enemies", + specialName: "Shark Knife - Flash", + }, + 1224: { // Story Yamakaji + captain: "Boosts ATK of Slasher characters by 2x", + special: "Reduces damage received by 60% for 1 turn", + specialName: "Appreciation For The Great Men", + }, + 1225: { // Story Hina + captain: "Boosts ATK and RCV of [INT] characters by 1.5x", + special: "Delays all enemies for 1 turn, and locks own orb for 1 turn", + specialName: "Binding Iron Tablet", + }, + 1226: { // Story Smoker + captain: "Boosts ATK of Driven characters by 2x", + special: "Cuts the current HP of one enemy by 10% and changes own orb into [PSY]", + specialName: "Seastone Truncheon", + }, + 1227: { //Story Mihawk + captain: "Reduces cooldown of Slasher specials by 2 turns at the start of the fight. Boosts ATK of Slasher characters by 2.25x", + special: "Deals 100,000 fixed damage to one enemy, and boosts own ATK by 1.75x for 1 turn ", + specialName: "Black Blade - Slashing Burial Drop", + }, + 1228: { // Story Kizaru + captain: "Boosts ATK of Shooter characters by 2.5x", + special: "For Shooter characters, changes [BLOCK] orbs into Matching, and deals large [DEX] damage to all enemies", + specialName: "The Cave of the Sun Goddess", + }, + 1229: {//Sentomaru + captain: "Boosts ATK of Powerhouse characters by 2x, and his OWN ATK by 2x.", + special: [ + { + "description": "Deals 500 fixed damage to one enemy. Reduces Special Cooldown of your top row by 1 turn", + "cooldown": [ 11, 4 ], + }, + { + "description": "Deals 5,000 fixed damage to one enemy. Reduces Special Cooldown of your top row by 1 turn", + "cooldown": [ 15, 8 ], + }, + { + "description": "Deals 100,000 fixed damage to one enemy. Reduces Special Cooldown of your top row by 2 turns", + "cooldown": [ 22, 15 ], + }, + ], + specialNotes: "#{stages}", + sailor: "Cannot be Blown Away (Such as Raid Boss Kuma)", + specialName: "Leg-Locked Heave-Ho", + }, + 1230: {//Sentomaru + captain: "Boosts ATK of Powerhouse characters by 2.5x, but boost his OWN ATK by 2.75x. Reduces damage received by 10%", + special: [ + { + "description": "Deals 500 fixed damage to one enemy. Reduces Special Cooldown of your top row by 1 turn", + "cooldown": [ 11, 4 ], + }, + { + "description": "Deals 5,000 fixed damage to one enemy. Reduces Special Cooldown of your top row by 1 turn", + "cooldown": [ 15, 8 ], + }, + { + "description": "Deals 100,000 fixed damage to one enemy. Reduces Special Cooldown of your top row by 2 turns", + "cooldown": [ 22, 15 ], + }, + ], + specialNotes: "#{stages}", + sailor: "Cannot be Blown Away (Such as Raid Boss Kuma)", + specialName: "Leg-Locked Heave-Ho", + }, + 1231: {//Smoker + captain: "Boosts ATK of Striker and Driven characters by 1.75x and reduces RCV of all characters by 50%. If this character becomes your captain in the middle of an island, reduces damage received by 30% and further boosts ATK of Striker and Driven characters by 1.25x", + captainNotes: "If Smoker uses his special ability to swap to your captain, his effective captain boost will be 2.1875x", + special: "Deals large [DEX] damage to one enemy. Swaps this unit with your captain for 2 turns", + specialNotes: "This is the same type of ability as raid boss Shiki's swap.", + specialName: "Armed - White Launcher", + sailor: "Boosts base ATK of Striker characters by 50", + }, + 1232: {//Smoker + captain: "Boosts ATK of Striker and Driven characters by 2.25x and reduces RCV of all characters by 50%. If this character becomes your captain in the middle of an island, reduces damage received by 30% and further boosts ATK of Striker and Driven characters by 1.3x", + captainNotes: "If Smoker uses his special ability to swap to your captain, his effective captain boost will be 2.925x", + special: "Deals large [DEX] damage to one enemy. Swaps this unit with your captain for 2 turns", + specialNotes: "This is the same type of ability as raid boss Shiki's swap. You cannot use it if another effect swaps your captain. (Such as if Shiki swaps first)", + specialName: "Armed - White Launcher", + sailor: "Boosts base ATK of Striker characters by 50", + limit: "This character has a limit break path", + }, + 1233: {//Tashigi + captain: "Boosts ATK of Slasher and Cerebral characters by 1.5x, and their RCV by 1.2x", + captainNotes: "Attack boost stacks, so a Slasher Cerebral unit has 2.25x ATK", + special: "Deals 15x character's ATK in [QCK] damage to all enemies. Boosts the Color Affinity of Slasher and Cerebral characters by 1.5x for 2 turns", + specialNotes: "#{colorAffinity : 1.5}", + specialName: "Cutting Drizzle", + sailor: "Boosts base RCV of Slasher characters by 30", + }, + 1234: {//Tashigi + captain: "Boosts ATK of Slasher and Cerebral characters by 1.6x, and their RCV by 1.3x", + captainNotes: "Attack boost stacks, so a Slasher Cerebral unit has 2.56x ATK", + special: "Deals 15x character's ATK in [QCK] damage to all enemies. Boosts the Color Affinity of Slasher and Cerebral characters by 1.5x for 2 turns", + specialNotes: "#{colorAffinity : 1.5}", + specialName: "Cutting Drizzle", + sailor: "Boosts base RCV of Slasher characters by 30", + }, + 1235: {//Maynard + captain: "Boosts ATK of [PSY] characters by 1.75x, deals 3x character's ATK to all enemies at the end of each turn", + special: "Deals several times the character's ATK in [PSY] damage to one enemy. Delays all enemies for 1 turn", + specialNotes: "#{specialProportional : higher : 10x + (25x * (remaining HP) / (total HP)) }", + specialName: "Sword of Silence", + sailor: "Reduces Blindness duration for 3 turns", + }, + 1236: {//Maynard + captain: "Boosts ATK of [PSY] characters by 2x, deals 5x character's ATK to all enemies at the end of each turn", + special: "Deals several times the character's ATK in [PSY] damage to one enemy. Delays all enemies for 1 turn", + specialNotes: "#{specialProportional : higher : 10x + (25x * (remaining HP) / (total HP)) }", + specialName: "Sword of Silence", + sailor: "Reduces Blindness duration for 3 turns", + }, + 1237: {//Bastille + captain: "Boosts ATK of all characters by 2x after the 15th hit in the chain", + special: "Deals 20x character's ATK in [STR] damage to all enemies. Boosts ATK of all characters by 2x after 30th hit in the chain for 1 turn.", + specialName: "Shark Cutter - Flash", + sailor: "Makes [QCK] orbs \"beneficial\" for this unit" + }, + 1238: {//Bastille + captain: "Boosts ATK of all characters by 2x after the 15th hit in the chain and by 3x after the 30th hit", + special: "Deals 20x character's ATK in [STR] damage to all enemies. Boosts ATK of all characters by 2x after 30th hit in the chain for 1 turn.", + specialName: "Shark Cutter - Flash", + sailor: "Makes [QCK] orbs \"beneficial\" for this unit" + }, + 1239: {//6* Kizaru + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of all characters by 2x, and boosts RCV of all characters by 1.3x. If you use \"Yasakani no Magatama\" boosts ATK of all characters by 3x instead.", + specialName: "Yasakani no Magatama", + special: [ + { + "description": "For Shooter and Slasher characters, randomizes all non-matching orbs. Deals 10 hits of small random typeless damage to random enemies.", + "cooldown": [ 6, 3 ], + }, + { + "description": "For Shooter and Slasher characters, randomizes all non-matching orbs. Recovers 5x character's RCV in HP. Deals 10 hits of random typeless damage to random enemies.", + "cooldown": [ 12, 9 ], + }, + { + "description": "Changes all orbs on Shooter and Slasher characters into Matching orbs. Recovers 10x character's RCV in HP. Deals 10 hits of large random typeless damage to random enemies.", + "cooldown": [ 20, 17 ], + }, + ], + specialNotes: "#{randomHits : 10}
    #{random : 1,000 : 3,000 : for each hit on Stage 1}
    #{random : 3,000 : 6,000 : for each hit on Stage 2}
    #{random : 10,000 : 16,000 : for each hit on Stage 3}
    #{stages}", + }, + 1240: {//6* Kizaru + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of all characters by 2x, and boosts RCV of all characters by 1.3x. If you use \"Yasakani no Magatama\" boosts ATK of all characters by 3x instead.", + specialName: "Yasakani no Magatama", + special: [ + { + "description": "For Shooter and Slasher characters,randomizes all non-matching orbs. Deals 10 hits of small random typeless damage to random enemies.", + "cooldown": [ 6, 3 ], + }, + { + "description": "For Shooter and Slasher characters, randomizes all non-matching orbs. Recovers 5x character's RCV in HP. Deals 10 hits of random typeless damage to random enemies.", + "cooldown": [ 12, 9 ], + }, + { + "description": "Changes all orbs on Shooter and Slasher characters into Matching orbs. Recovers 10x character's RCV in HP. Deals 10 hits of large random typeless damage to random enemies.", + "cooldown": [ 20, 17 ], + }, + ], + specialNotes: "#{randomHits : 10}
    #{random : 1,000 : 3,000 : for each hit on Stage 1}
    #{random : 3,000 : 6,000 : for each hit on Stage 2}
    #{random : 10,000 : 16,000 : for each hit on Stage 3}
    #{stages}", + }, + 1241: {//Fortnight Koala + captain: "Boosts chain multiplier by 1.5x. Recovers 1x character's RCV in HP at the end of each turn", + special: "Deals 11x character's ATK in [STR] damage to one enemy. Adds 15x character's ATK as Additional Typeless Damage for 1 turn", + specialNotes: "#{additionalDamage : 15x}", + specialName: "Fishman Karate, Midair Upwards Kick", + }, + 1242: {//Fortnight Koala + captain: "Boosts chain multiplier by 2x. Recovers 2x character's RCV in HP at the end of each turn", + special: "Deals 11x character's ATK in [STR] damage to one enemy. Adds 15x character's ATK as Additional Typeless Damage for 1 turn", + specialNotes: "#{additionalDamage : 15x}", + specialName: "Fishman Karate, Midair Upwards Kick", + }, + 1243: {// Fortnight Hack + captain: "Boosts ATK of Fighter and Powerhouse characters by 1.3x", + captainNotes: "Effect stacks, so Fighter/Powerhouse characters get 1.69x ATK", + special: "Deals 15x character's ATK in [INT] damage to all enemies. Changes own orb into [INT] and changes adjacent orbs into [G] orbs", + specialName:"Fishman karate, KO blow", + specialNotes: "#{gOrbs}" + }, + 1244: {// Fortnight Hack + captain: "Boosts ATK of Fighter characters by 1.75x and the ATK of Powerhouse characters by 1.3x", + captainNotes: "Effect stacks, so Fighter/Powerhouse characters get 2.275x ATK", + special: "Deals 15x character's ATK in [INT] damage to all enemies. Changes own orb into [INT] and changes adjacent orbs into [G] orbs", + specialName:"Fishman karate, KO blow", + specialNotes: "#{gOrbs}" + }, + 1245: {// Event Luffy + captain: "Boosts ATK of Fighter characters by 1.75x. If HP is below 10%, boosts ATK of Fighter characters by 3x instead.", + special: "Deals random [QCK] damage to all enemies, and boosts ATK of Fighter characters by 1.3x for 1 turn. If \"Firefly Light, Fiery Doll\" is used again in the same turn the special is activated in, boosts ATK of Fighter characters by 2x instead.", + specialName:"Gomu Gomu no Stamp Gatling", + specialNotes: "Firefly Light, Fiery Doll is Event Ace's special ability.", + }, + 1246: {// Event Ace + captain: "Boosts ATK of Fighter characters by 1.2x", + special: "Reduces crew's current HP by 90%, deals 55x character's ATK in typeless damage to all enemies, and boosts ATK of Fighter characters by 1.3x for 1 turn. If \"Gomu Gomu no Stamp Gatling\" is used again in the same turn the special is activated in, boosts ATK of Fighter characters by 2x instead.", + specialName:"Firefly Light, Fiery Doll", + }, + 1247: {// Event Ace + captain: "Boosts HP of Fighter characters by 1.2x and their ATK by 2.75x if they have a matching orb, by 2x otherwise", + special: "Reduces crew's current HP by 90%, deals 55x character's ATK in typeless damage to all enemies, and boosts ATK of Fighter characters by 1.3x for 1 turn. If \"Gomu Gomu no Stamp Gatling\" is used again in the same turn the special is activated in, boosts ATK of Fighter characters by 2x instead.", + specialName:"Firefly Light, Fiery Doll", + }, + 1248: {// Kimono Marco + captain: "Boosts ATK of Fighter and Powerhouse characters by 1.3x", + captainNotes: "Ability stacks, so Fighter/Powerhouse characters gets ATK boosted by 1.69x", + special: "Recovers 3,000 HP and reduces damage received by 50% for 1 turn", + specialName:"Shining Daylight - Dayflower", + }, + 1249: {// Kimono Marco + captain: "Boosts ATK of Fighter and Powerhouse characters by 1.6x", + captainNotes: "Ability stacks, so Fighter/Powerhouse characters gets ATK boosted by 2.56x", + special: "Recovers 3,000 HP and reduces damage received by 50% for 1 turn", + specialName:"Shining Daylight - Dayflower", + }, + 1250: {// Coliseum Marco + captain: "Boosts ATK of Powerhouse characters by 1.5x and Recovers a variable amount of character's RCV in HP at the end of each turn depending on how many Powerhouse characters are on your team", + captainNotes: "1x Powerhouse: .5x RCV | 2x Powerhouse: .75x RCV | 3x Powerhouse: 1x RCV | 4x Powerhouse: 1.5x RCV | 5x Powerhouse: 2x RCV | 6x Powerhouse: 3.5x RCV", + special: [ + { + "description": "Randomizes all orbs, and boosts ATK of Powerhouse characters by 1.5x for 1 turn", + "cooldown": [ 21, 6 ], + }, + { + "description": "Randomizes non-matching orbs, and boosts ATK of Powerhouse characters by 1.5x for 1 turn", + "cooldown": [ 24, 9 ], + }, + ], + specialNotes: "#{stages}", + specialName: "Burning Vanguard", + }, + 1251: {// Coliseum Marco + captain: "Boosts ATK of Powerhouse characters by 2x and Recovers a variable amount of character's RCV in HP at the end of each turn depending on how many Powerhouse characters are on your team", + captainNotes: "1x Powerhouse: .5x RCV | 2x Powerhouse: .75x RCV | 3x Powerhouse: 1x RCV | 4x Powerhouse: 1.5x RCV | 5x Powerhouse: 2x RCV | 6x Powerhouse: 2.5x RCV", + special: [ + { + "description": "Randomizes all orbs, and boosts ATK of Powerhouse characters by 1.5x for 1 turn", + "cooldown": [ 21, 6 ], + }, + { + "description": "Randomizes non-matching orbs, and boosts ATK of Powerhouse characters by 1.5x for 1 turn", + "cooldown": [ 24, 9 ], + }, + ], + specialNotes: "#{stages}", + specialName: "Burning Vanguard", + limit: "This character has a limit break path", + }, + 1252: {// Coliseum Doma + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of [INT] characters by 2x", + special: "Changes adjacent orbs into [INT] orbs. Deals 20x character's ATK in [INT] damage to all enemies.", + specialName: "Reversed Twin Blades - Surprise Thrust", + sailor: "Reduces own Silence by 1 turn", + sailorNotes: "#{silence}", + }, + 1253: {// Coliseum Shura + captain: "Boosts ATK of [DEX] characters by 2.25x if HP is above 99% at the start of the turn", + special: "Makes Perfects harder to hit for 1 turn. If during that turn every unit scores a Perfect hit, boosts ATK of [DEX] characters by 1.75x in the following turn.", + specialName: "Angry Instigator", + }, + 1254: {//FN Squard + captain: "Boosts ATK of Striker characters by 2.5x until the first hit other than Perfect. Reduce crew's current HP by 5% at the end of each turn.", + special: "Deals 10x character's ATK in fixed damage to one enemy, reduces crews current HP by 30% and reduces enemies defense by 80% for one turn", + specialName: "Sword Attack Without Hesitation", + sailor: "Reduces his own Numbness by 1 turn" + }, + 1255: {//FN DeCalvan + captain: "Boosts ATK of all characters by 1.5x after the 11th hit in the chain, by 2x after the 16th hit, by 2.5x after the 22nd hit", + special: "For 1 turn, makes Perfects slightly easier to hit and amplifies the effect of orbs by 1.5x", + sailor: "When HP is below 30% at the start of the turn, boost base ATK of Fighter characters by 40", + specialName: "Large Fleet Commander", + }, + 1256: {//FN Whitey Bay + captain: "Boosts ATK of Slasher and Driven characters by 2x and reduces their RCV by 90%", + special: "For Slasher and Driven characters, randomizes non-matching orbs, boosts ATK against enemies with increased defense by 1.3x for 1 turn", + sailor: "Boosts base ATK and RCV of Driven characters by 10", + specialName: "Icebreaker Breakthrough Force", + }, + 1257: {//Young Whitebeard + captain: "Boosts ATK of all characters by 2x if HP is below 50% at the start of the turn", + special: [ + { + "description": "Cuts the current HP of each enemy by 10%", + "cooldown": [ 23, 11 ], + }, + { + "description": "Cuts the current HP of each enemy by 20%", + "cooldown": [ 28, 16 ], + }, + { + "description": "Cuts the current HP of each enemy by 40%", + "cooldown": [ 36, 24 ], + }, + ], + specialNotes: "#{stages}", + specialName: "Earth Shattering Fist", + }, + 1258: {//Young Whitebeard Evolved + captain: "Boosts ATK of all characters by 2.5x if HP is below 50% at the start of the turn", + special: [ + { + "description": "Cuts the current HP of each enemy by 10%", + "cooldown": [ 23, 11 ], + }, + { + "description": "Cuts the current HP of each enemy by 20%", + "cooldown": [ 28, 16 ], + }, + { + "description": "Cuts the current HP of each enemy by 40%", + "cooldown": [ 36, 24 ], + }, + ], + specialNotes: "#{stages}", + specialName: "Earth Shattering Fist", + }, + 1259: {//Young Doflamingo + captain: "Boosts ATK of Driven characters by 2.5x", + special: "Deals 25x character's ATK in typeless damage to all enemies. For 3 turns, makes [STR], [DEX], [QCK], [PSY], and [INT] orbs \"beneficial\" for Driven characters", + specialNotes: "\"Beneficial\" orbs grant the same ATK boost as matching orbs while retaining their original function.", + specialName: "Five Color Strings (Goshikito)", + }, + 1260: {//Young Doflamingo + captain: "Reduces cooldown of Driven specials by 1 turn at the start of the fight. Boosts ATK of Driven characters by 2.5x", + special: "Deals 25x character's ATK in typeless damage to all enemies. For 3 turns, makes [STR], [DEX], [QCK], [PSY], and [INT] orbs \"beneficial\" for Driven characters", + specialNotes: "\"Beneficial\" orbs grant the same ATK boost as matching orbs while retaining their original function.", + specialName: "Five Color Strings (Goshikito)", + }, + 1261: {//Young Senor Pink + captain: "Boosts ATK of Free Spirit characters by 1.5x. Heals for .75x his RCV at the end of the turn each time you hit a Perfect.", + special: "Randomizes all orbs. Boosts the Color Affinity of Free Spirit and Shooter characters by 1.5x for 1 turn", + specialNotes: "#{colorAffinity : 1.5}", + specialName: "Blood and Gunpowder of the Underground Family", + }, + 1262: {//Young Senor Pink + captain: "Boosts ATK of Free Spirit characters by 1.75x. Heals for .75x his RCV at the end of the turn each time you hit a Perfect.", + special: "Randomizes all orbs. Boosts the Color Affinity of Free Spirit and Shooter characters by 1.5x for 1 turn", + specialNotes: "#{colorAffinity : 1.5}", + specialName: "Blood and Gunpowder of the Underground Family", + }, + 1263: {//Young Vergo + captain: "Boosts ATK of characters with cost 20 or less by 2.5x", + special: "Deals 20,000 fixed damage to one enemy. Boosts own ATK by 2x for 2 turns", + specialName: "Iron Leg Sanctions", + }, + 1264: {//Young Vergo + captain: "Boosts ATK of characters with cost 30 or less by 2.5x", + special: "Deals 20,000 fixed damage to one enemy. Boosts own ATK by 2x for 2 turns", + specialName: "Iron Leg Sanctions", + }, + 1265: {//Kimono Ace + captain: "Boosts ATK of Shooter characters by 2x", + special: "Recovers 3,000 HP and boosts ATK of Free Spirit characters by 1.75x for 1 turn", + specialName: "Looking to the Full Moon", + }, + 1266: {//Kimono Ace Evo + captain: "Boosts ATK of Shooter characters by 2.5x", + special: "Recovers 3,000 HP and boosts ATK of Free Spirit characters by 1.75x for 1 turn", + specialName: "Looking to the Full Moon", + }, + 1267: {//Legend Blackbeard + captain: "Boosts ATK of all characters by 2.75x and their HP by 1.5x if you have a Striker, Shooter, Fighter, and Slasher on your crew. Attacks will ignore defensive barriers and buffs.", + captainNotes: "Attacks are still affected by DEF value. DEF boost buffs (Blue shield) still reduce your damage, but Damage Negating (Yellow shield) and % Damage Reduction (Rainbow shield) are ignored). Multiple class characters count as a character of each class. Enemy attacks will go through YOUR defensive buffs.", + special: "Cuts the current HP of each enemy by 30%. If Blackbeard is a captain, this ability will ignore damage negating abilities and barriers", + specialNotes: "If Blackbeard is not a captain, the effect works exactly like Whitebeard special and is affected by barriers.", + specialName: "World Shaking Impact", + }, + 1268: {//Legend Blackbeard + captain: "Boosts ATK of all characters by 2.75x and their HP by 1.5x if you have a Striker, Shooter, Fighter, and Slasher on your crew. Attacks will ignore defensive barriers and buffs.", + captainNotes: "Attacks are still affected by DEF value. DEF boost buffs (Blue shield) still reduce your damage, but Damage Negating (Yellow shield) and % Damage Reduction (Rainbow shield) are ignored). Multiple class characters count as a character of each class. Enemy attacks will go through YOUR defensive buffs.", + special: "Cuts the current HP of each enemy by 30%. If Blackbeard is a captain, this ability will ignore damage negating abilities and barriers", + specialNotes: "If Blackbeard is not a captain, the effect works exactly like Whitebeard special and is affected by barriers.", + specialName: "World Shaking Impact", + }, + 1269: {//Laffitte + captain: "Recovers 3x character's RCV in HP at the end of each turn. Deals 3x character's ATK in [DEX] damage to all enemies at the end of each turn.", + special: "Reduces Bind and Despair duration by 2 turns. Makes Badly Matching and [BLOCK] orbs not reduce damage for 4 turns", + specialNotes: "Ex. A STR character with a QCK orb will still deal regular damage", + sailor: "Boosts base ATK of all characters by 100 if your captain is a Driven character", + specialName: "Horrifying Suggestion", + }, + 1270: {//Laffitte + captain: "Recovers 3x character's RCV in HP at the end of each turn. Deals 7x character's ATK in [DEX] damage to all enemies at the end of each turn.", + special: "Reduces Bind and Despair duration by 2 turns. Makes Badly Matching and [BLOCK] orbs not reduce damage for 4 turns", + specialNotes: "Ex. A STR character with a QCK orb will still deal regular damage", + sailor: "Boosts base ATK of all characters by 100 if your captain is a Driven character", + specialName: "Horrifying Suggestion", + }, + 1271: {//Van Augur + captain: "Boosts ATK of Shooter characters by 2x", + special: "Changes orbs in the top row into Matching orbs. For Shooter characters, amplifies the effect of orbs by 1.75x for 1 turn", + sailor: "Reduces Blindness duration by 5 turns", + specialName: "Other Side of Fate", + }, + 1272: {//Van Augur + captain: "Reduces cooldown of Shooter specials by 1 turn at the start of the fight. Boosts ATK of Shooter characters by 2.5x.", + special: "Changes orbs in the top row into Matching orbs. For Shooter characters, amplifies the effect of orbs by 1.75x for 1 turn", + sailor: "Reduces Blindness duration by 5 turns", + specialName: "Other Side of Fate", + limit: [ + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Aquire Potential 1: Pinch Healing" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base HP by 90" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK of Shooter characters by 60" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Barrier Penetration" }, + ], + potential: [ + { + "Name": "Pinch Healing", + "description": [ + "Level 1: If HP is below 10% at the start of the turn, heals for .5x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 2: If HP is below 15% at the start of the turn, heals for .5x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 3: If HP is below 20% at the start of the turn, heals for .5x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 4: If HP is below 30% at the start of the turn, heals for 1x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 5: If HP is below 50% at the start of the turn, heals for 1x this character's RCV at the end of the turn each time you hit a Perfect" + ] + }, + { + "Name": "Barrier Penetration", + "description": [ + "Level 1: This character's attack will ignore barriers if HP is above 99%", + "Level 2: This character's attack will ignore barriers if HP is above 99%", + "Level 3: This character's attack will ignore barriers if HP is above 99%", + "Level 4: This character's attack will ignore barriers if HP is above 80%", + "Level 5: This character's attack will ignore barriers if HP is above 50%" + ] + }, + ] + }, + 1273: {//Jesus Burgess + captain: "Boosts ATK of Fighter and Powerhouse characters by 1.5x and their HP by 1.2", + captainNotes: "Boosts stack, so a Fighter/Powerhouse character gets 2.25x ATK and 1.44x HP", + special: "Deals 20x character's ATK in [STR] damage to all enemies. Boosts ATK of Fighter characters by 1.5x for 5 turns", + sailor: "Boosts base HP of all characters by 75", + specialName: "Champion of the Wild Roar", + }, + 1274: {//Jesus Burgess + captain: "Boosts ATK of Fighter and Powerhouse characters by 1.6x and their HP by 1.2x", + captainNotes: "Boosts stack, so a Fighter/Powerhouse character gets 2.56x ATK and 1.44x HP", + special: "Deals 20x character's ATK in [STR] damage to all enemies. Boosts ATK of Fighter characters by 1.5x for 5 turns", + sailor: "Boosts base HP of all characters by 75", + specialName: "Champion of the Wild Roar", + }, + 1275: {//Shiliew + captain: "Boosts ATK and HP of Slasher characters by 1.5x", + special: "For each enemy, has a small chance to instantly defeat that enemy.", + specialNotes: "#{instantKill : 25%}", + sailor: "Completely resists Silence on this character", + sailorNotes: "#{silence}", + specialName: "Handling Hell", + }, + 1276: {//Shiliew + captain: "Boosts ATK and HP of Slasher characters by 2x", + special: "For each enemy, has a small chance to instantly defeat that enemy.", + specialNotes: "#{instantKill : 25%}", + sailor: "Completely resists Silence on this character", + sailorNotes: "#{silence}", + specialName: "Handling Hell", + }, + 1277: {//Doc Q + captain: "Reduces RCV of all characters by 99%. Boosts ATK of Slasher and Striker characters by 2.25x if HP is above 99% at the start of the turn", + special: "Reduces crew's current HP by 10%. Changes [BLOCK], [TND], and [RCV] orbs on Slasher and Striker characters into Matching Orbs.", + sailor: "Boosts amount healed from [RCV] orbs by 150 each", + specialName: "Reaping of Desperate Lives", + }, + 1278: {//Doc Q + captain: "Reduces RCV of all characters by 99%. Boosts ATK of Slasher and Striker characters by 2.75x if HP is above 99% at the start of the turn", + special: "Reduces crew's current HP by 10%. Changes [BLOCK], [TND], and [RCV] orbs on Slasher and Striker characters into Matching Orbs.", + sailor: "Boosts amount healed from [RCV] orbs by 150 each", + specialName: "Reaping of Desperate Lives", + limit: "This character has a limit break path", + }, + 1279: {//John Giant + captain: "Boosts ATK and HP of Slasher characters by 1.5x", + special: "Reduces damage received in the next turn by 50% if the special is activated with less than 50% health remaining", + specialName: "Manifesto to the Weak", + }, + 1280: {//Marineford Aokiji + captain: "Boosts ATK of [PSY] characters by 2.5x", + special: "Deals 10,000 fixed damage to all enemies and locks all orbs for 1 turn", + specialName: "Ice Chunks - Trident", + }, + 1281: {//Marineford Garp + captain: "Boosts ATK of Fighter characters by 2.25x and reduces damage received by 10%", + special: "Deals 25x character's ATK in [STR] damage to one enemy that will ignore damage negating abilities and barriers.", + specialNotes: "#{ignoreBarrier}", + specialName: "Fist of Love - Falling Fortress", + }, + 1282: {//Marineford Sengoku + captain: "Boosts ATK of Cerebral characters by 2.5x", + special: "Reduces cooldown of all specials by 1 turn. Boosts ATK of all characters by 1.2x and amplifies the effect of orbs by 1.2x for 1 turn", + specialName: "Encircling Wall around Marineford Bay", + }, + 1283: {//Marineford Akainu + captain: "Boosts ATK of Driven characters by 2.5x", + special: "Deals 35x character's ATK in [INT] damage to one enemy. Boosts ATK of Driven characters by 1.5x for 1 turn", + specialName: "Dark Dog", + }, + 1284: {//Wild Luffy + captain: "Boosts ATK of Striker characters by 1.5x and their HP by 1.2x", + special: "Reduces Bind and Silence duration by 3 turns. Randomizes non-matching orbs including [BLOCK] orbs", + specialNotes: "#{silence}", + sailor: "Reduces Silence duration against this character by 3 turns", + sailorNotes: "#{silence}", + specialName: "Wild Hunt", + }, + 1285: {//Wild Luffy Evolved + captain: "Boosts ATK of Striker characters by 1.5x and their HP by 1.25x. Boosts ATK of Striker characters by 3.375x after scoring 3 Perfects in a row.", + special: "Reduces Bind and Silence duration by 3 turns. Randomizes non-matching orbs including [BLOCK] orbs", + specialNotes: "#{silence}", + sailor: "Reduces Silence duration against this character by 3 turns", + sailorNotes: "#{silence}", + specialName: "Wild Hunt", + }, + 1286: {//Kid Baby 5 + captain: "Boosts ATK and RCV of [PSY] characters by 1.3x", + special: "Cuts the current HP of each enemy by 10%. Boosts ATK of Shooter characters by 1.5x for 1 turn", + specialName: "Handgun Legs", + }, + 1287: {//Kid Baby 5 + captain: "Boosts ATK and RCV of [PSY] characters by 1.5x", + special: "Cuts the current HP of each enemy by 10%. Boosts ATK of Shooter characters by 1.5x for 1 turn", + specialName: "Handgun Legs", + }, + 1288: {//Kid Law + captain: "Boosts ATK of Driven characters by 2.5x, reduces crew's current HP by 10% at the end of each turn, reduces his own ATK multiplier by 0.1x at the end of each turn", + captainNotes: "His ATK multiplier will be 2.5x on the first turn, 2.4x on the second, 2.3x on the third and so on. The reduction stops once the multiplier is 1.0x. The multiplier affects all Driven characters. You will not die to the HP reduction", + special: "Reduces Special Cooldown of Driven specials by 1 turn. If during that turn every unit scores a Perfect hit, reduces Special Cooldown of Driven specials by 1 turn.", + specialName: "Outcome of Sparta", + }, + 1289: {//Kid Law + captain: "Boosts ATK of Driven characters by 2.75x, reduces crew's current HP by 10% at the end of each turn, reduces his own ATK multiplier by 0.1x at the end of each turn", + captainNotes: "His ATK multiplier will be 2.75x on the first turn, 2.65x on the second, 2.55x on the third and so on. The reduction stops once the multiplier is 1.0x. The multiplier affects all Driven characters. You will not die to the HP reduction", + special: "Reduces Special Cooldown of Driven specials by 1 turn. If during that turn every unit scores a Perfect hit, reduces Special Cooldown of Driven specials by 1 turn.", + specialName: "Outcome of Sparta", + }, + 1290: {//Kid Buffalo + captain: "Recovers 500 HP at the end of each turn", + special: "Changes own orb into [INT], and Captain orb into [BOMB]", + specialName: "Rude Prank", + }, + 1291: {//Lao G, Coliseum + captain: "Boosts ATK of Driven characters by 1.75x", + special: "Changes [PSY], [INT], [RCV], and [TND] orbs into [G] orbs. Locks orbs for 1 turn. If during that turn every unit scores a Perfect hit, changes [G] orbs into Matching Orbs", + specialName: "Lower Back Pain Stance - The Eyes of Blight Impact", + }, + 1292: {//Lao G, Coliseum + captain: "Boosts ATK of Driven characters by 2.5x if they have a matching orb, by 2x otherwise", + special: "Changes [PSY], [INT], [RCV], and [TND] orbs into [G] orbs. Locks orbs for 1 turn. If during that turn every unit scores a Perfect hit, changes [G] orbs into Matching Orbs", + specialName: "Lower Back Pain Stance - The Eyes of Blight Impact", + }, + 1293: {//Coliseum Sandersonia + captain: "Boosts ATK of Fighter characters by 1.75x, deals 2 times the damage received in the previous turn in [PSY] damage to all enemies at the end of each turn", + special: [ + { + "description": "Changes Captain orb into Matching, and reduces damage received from [PSY] enemies by 40%", + "cooldown": [ 21, 11 ], + }, + { + "description": "Changes Captain orb into Matching, and reduces damage received from [PSY] enemies by a variable factor.", + "cooldown": [ 26, 16 ], + }, + ], + specialNotes: "The exact multiplier used is chosen based on the crew's current HP at the time the special is activated: above 50% HP, the multiplier used is 50%; between 50% and 10%, it's 80%; below 10% HP, it's 100%.
    #{stages}", + specialName: "Snake Dance", + }, + 1294: {//Coliseum Sandersonia + captain: "Boosts ATK of Powerhouse characters by 2x, deals 4 times the damage received in the previous turn in [PSY] damage to all enemies at the end of each turn", + special: [ + { + "description": "Changes Captain orb into Matching, and reduces damage received from [PSY] enemies by 40%", + "cooldown": [ 21, 11 ], + }, + { + "description": "Changes Captain orb into Matching, and reduces damage received from [PSY] enemies by a variable factor.", + "cooldown": [ 26, 16 ], + }, + ], + specialNotes: "The exact multiplier used is chosen based on the crew's current HP at the time the special is activated: above 50% HP, the multiplier used is 50%; between 50% and 10%, it's 80%; below 10% HP, it's 100%.
    #{stages}", + specialName: "Snake Dance", + }, + 1295: {//Halloween Kalifa + captain: "Boosts ATK and RCV of [STR] characters by 1.5x", + special: "Reduces Paralysis duration by 3 turns, removes Poison, and reduces the defense of all enemies by 100% for 1 turn", + specialName: "Mysterious Hour of the Dark Night", + }, + 1296: {//Halloween Kalifa + captain: "Boosts ATK of [STR] characters by 2x and their RCV by 1.5x", + special: "Reduces Paralysis duration by 3 turns, removes Poison, and reduces the defense of all enemies by 100% for 1 turn", + specialName: "Mysterious Hour of the Dark Night", + }, + 1297: {//Akainu + captain: "Boosts ATK by 2.5x following a chain of [STR] > [STR] > [STR] attacks no lower than Good", + special: "Deals 50x character's ATK in [STR] damage to all enemies. Changes orbs for [STR] characters into [STR] orbs. Boosts the Color Affinity of [STR] characters by 1.75x for 1 turn", + specialNotes: "#{colorAffinity : 1.75}", + specialName: "Great Eruption", + }, + 1298: {//Akainu + captain: "Boosts ATK by 3x following a chain of [STR] > [STR] > [STR] attacks no lower than Good", + special: "Deals 50x character's ATK in [STR] damage to all enemies. Changes orbs for [STR] characters into [STR] orbs. Boosts the Color Affinity of [STR] characters by 1.75x for 1 turn", + specialNotes: "#{colorAffinity : 1.75}", + specialName: "Great Eruption", + }, + 1299: {//Halloween Rebecca + captain: "Boosts ATK and RCV of [INT] characters by 1.2x", + special: "Recovers 3,000 HP and boosts ATK of [INT] characters by 1.75x for 1 turn", + specialName: "Driving Away Evil Spirits of Sin - Cat Pose", + }, + 1300: {//Halloween Rebecca + captain: "Boosts ATK and RCV of [INT] characters by 1.5x", + special: "Recovers 3,000 HP and boosts ATK of [INT] characters by 1.75x for 1 turn", + specialName: "Driving Away Evil Spirits of Sin - Cat Pose", + }, + 1301: {//Jailbreak Buggy + captain: "Boosts ATK of Slasher characters by 1.75x", + special: "Reduces crew's HP to 1, empties all slots, and deals 30x character's ATK in [QCK] damage to all enemies", + specialName: "Special Muggy Ball", + }, + 1302: {//Jailbreak Buggy + captain: "Boosts ATK of Slasher characters by 1.75x and boosts ATK of Driven characters by 1.5x", + captainNotes: "The bonus is cumulative. Slasher Driven characters get a 2.625x bonus.", + special: "Reduces crew's HP to 1, empties all slots, and deals 30x character's ATK in [QCK] damage to all enemies", + specialName: "Special Muggy Ball", + }, + 1303: {//Jailbreak Mr. 3 + captain: "Boosts ATK of Cerebral characters by 1.5x. If you don't attack with Mr. 3, reduces damage received by 10% for that turn.", + special: "Reduces damage received by 60% for 2 turns", + specialName: "Extra Large Candle Wall", + }, + 1304: {//Jailbreak Mr. 3 + captain: "Boosts ATK of Cerebral characters by 2x. If you don't attack with Mr. 3, reduces damage received by 10% for that turn.", + special: "Reduces damage received by 60% for 2 turns", + specialName: "Extra Large Candle Wall", + }, + 1305: {//Halloween Sugar + captain: "Boosts ATK of Cerebral characters by 1.3x and recovers 500 HP at the end of each turn", + special: "Changes Badly Matching, [BLOCK], and [BOMB] orbs into [G] orbs. Reduces Special Cooldown of 1 character by 1 turn", + specialName: "Aggressive 'Trick-Or-Treat'", + }, + 1306: {//Halloween Sugar + captain: "Boosts ATK of Cerebral characters by 1.75x and recovers 1,000 HP at the end of each turn", + special: "Changes Badly Matching, [BLOCK], and [BOMB] orbs into [G] orbs. Reduces Special Cooldown of 1 character by 1 turn", + specialName: "Aggressive 'Trick-Or-Treat'", + }, + 1307: {//Halloween Bartolomeo + captain: "Boosts ATK of Driven characters by 1.75x. If you don't attack with Bartolomeo, reduces damage received by 10% for that turn.", + special: "Reduces damage received by 50% for 1 turn. If during that turn every unit scores a Perfect hit, reduces damage received by 80% in the following turn", + specialName: "Vulgar Provocation", + }, + 1308: {//Halloween Bartolomeo + captain: "Boosts ATK of Driven characters by 2x. If you don't attack with Bartolomeo, reduces damage received by 20% for that turn.", + special: "Reduces damage received by 50% for 1 turn. If during that turn every unit scores a Perfect hit, reduces damage received by 80% in the following turn", + specialName: "Vulgar Provocation", + }, + 1309: {//Coliseum Kinemon + captain: "Boosts ATK of Free Spirit characters by 2x, recovers 1x character's RCV in HP at the end of each turn", + special: "Reduces Special Cooldown of Slasher and Free Spirit characters by 1 turn and if HP is above 70%, changes adjacent orbs into Matching Orbs", + specialName: "Poof", + }, + 1310: {//Coliseum Kinemon + captain: "Boosts ATK of Free Spirit characters by 2.5x, recovers 2x character's RCV in HP at the end of each turn", + special: "Reduces Special Cooldown of Slasher and Free Spirit characters by 1 turn and if HP is above 70%, changes adjacent orbs into Matching Orbs", + specialName: "Poof", + }, + 1311: {//Coliseum Marigold + captain: "Boosts ATK and HP of Powerhouse characters by 1.5x", + special: "Deals 20x character's ATK in [INT] damage to all enemies. Reduces enemy Damage Threshold timers by 1 turn", + specialNotes: "Damage Threshold is the buff enemies gain that grealy reduces damage received over a certain amount", + specialName: "King Cobra Machetes", + }, + 1312: {//Coliseum Marigold + captain: "Boosts ATK and HP of Powerhouse characters by 1.75x", + special: "Deals 20x character's ATK in [INT] damage to all enemies. Reduces enemy Damage Threshold timers by 1 turn", + specialNotes: "Damage Threshold is the buff enemies gain that grealy reduces damage received over a certain amount", + specialName: "King Cobra Machetes", + }, + 1313: {//Akainu + captain: "If any character has a [STR] orb, boosts ATK by 3.9375x, boosts ATK by 2.25x otherwise. Boosts chances of getting [STR] orbs", + captainNotes: "If a character has a [STR] orb, regardless of type, they will have a 3.9375x ATK boost", + special: "Deals 125x character's ATK typeless damage to all enemies and randomizes non-[STR] orbs. Boosts ATK of characters with cost 50 or higher by 1.75x for 2 turns", + specialName: "Meteor Volcano", + }, + 1314: {//Akainu + captain: "If any character has a [STR] orb, boosts ATK by 3.9375x, boosts ATK by 2.25x otherwise. Boosts chances of getting [STR] orbs", + captainNotes: "If a character has a [STR] orb, regardless of type, they will have a 3.9375x ATK boost", + special: "Deals 125x character's ATK typeless damage to all enemies and randomizes non-[STR] orbs. Boosts ATK of characters with cost 50 or higher by 1.75x for 2 turns", + specialName: "Meteor Volcano", + limit: [ + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base HP by 40" }, + { "description": "Aquire Sailor Ability 1: Boosts this character's attack against [QCK] characters by 2x" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base HP by 50" }, + { "description": "Aquire Potential 2: Enrage" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Aquire Potential 3: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 30% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 40% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 50% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 50% chance to deal 10% of this character's attack in extra damage" + ] + }, + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 20", + "Level 2: Boosts base ATK by 40", + "Level 3: Boosts base ATK by 60", + "Level 4: Boosts base ATK by 80", + "Level 5: Boosts base ATK by 100" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 3 turn on this character", + "Level 2: Reduces Slot Bind duration by 5 turns on this character", + "Level 3: Reduces Slot Bind duration by 7 turns on this character", + "Level 4: Reduces Slot Bind duration by 10 turns on this character", + "Level 5: Reduces Slot Bind completely on this character" + ] + }, + ], + + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1315: {//Coby + captain: "Boosts ATK of all characters by 2x after the 2nd Perfect in a row and by 3x after the 5th Perfect in a row.", + special: [ + { + "description": "If HP is below 3,000 when the special is activated, reduces No Healing debuff by 1 turn. Recovers 3x character's RCV in HP", + "cooldown": [ 15, 9 ], + }, + { + "description": "If HP is below 3,000 when the special is activated, reduces No Healing debuff by 3 turns. Recovers 6x character's RCV in HP", + "cooldown": [ 20, 14 ], + }, + { + "description": "If HP is below 3,000 when the special is activated, removes No Healing debuff. Recovers 13x character's RCV in HP", + "cooldown": [ 24, 18 ], + }, + ], + specialNotes: "No Healing debuff completely stops healing abilities. This is the debuff used in Akainu raid
    #{stages}", + sailor: "Reduces Blindness duration by 5 turns", + specialName: "Echoing Cry of the Soul", + }, + 1316: {//Coby + captain: "Boosts ATK of all characters by 2.5x after the 2nd Perfect in a row and by 3.5x after the 5th Perfect in a row.", + special: [ + { + "description": "If HP is below 3,000 when the special is activated, reduces No Healing debuff by 1 turn. Recovers 3x character's RCV in HP", + "cooldown": [ 15, 9 ], + }, + { + "description": "If HP is below 3,000 when the special is activated, reduces No Healing debuff by 3 turns. Recovers 6x character's RCV in HP", + "cooldown": [ 20, 14 ], + }, + { + "description": "If HP is below 3,000 when the special is activated, removes No Healing debuff. Recovers 13x character's RCV in HP", + "cooldown": [ 24, 18 ], + }, + ], + specialNotes: "No Healing debuff completely stops healing abilities. This is the debuff used in Akainu raid
    #{stages}", + sailor: "Reduces Blindness duration by 5 turns", + specialName: "Echoing Cry of the Soul", + }, + 1317: {//Garp + captain: "Boosts ATK of [STR] and [PSY] characters by 2x", + special: "Deals 30x character's ATK in [STR] damage to all enemies that will ignore damage negating abilities and barriers. Delays all enemies for 1 turn. Reduces the defense of all enemies by 80% for 1 turn.", + specialNotes: "#{ignoreBarrier}", + sailor: "Boosts base HP of all characters by 75", + specialName: "Super Large Iron Ball", + }, + 1318: {//Garp + captain: "Boosts ATK of [STR] and [PSY] characters by 2.5x", + special: "Deals 30x character's ATK in [STR] damage to all enemies that will ignore damage negating abilities and barriers. Delays all enemies for 1 turn. Reduces the defense of all enemies by 80% for 1 turn.", + specialNotes: "#{ignoreBarrier}", + sailor: "Boosts base HP of all characters by 75", + specialName: "Super Large Iron Ball", + }, + 1319: {//Lady Tsuru + captain: "Heals for 1x her RCV at the end of the turn each time you hit a Good. Heals for .1x her RCV at the end of the turn each time you hit a Perfect", + special: "Deals 10 hits of random [QCK] damage to random enemies. Boosts ATK of all characters by 1.5x for 1 turn", + specialNotes: "#{randomHits : 10}
    #{random : 1,000 : 32,000 : for each hit}", + sailor: "Reduces Paralysis duration by 1 turn", + specialName: "A Decree of the Veteran", + }, + 1320: {//Lady Tsuru + captain: "Heals for 1.5x her RCV at the end of the turn each time you hit a Good. Heals for .1x her RCV at the end of the turn each time you hit a Perfect", + special: "Deals 10 hits of random [QCK] damage to random enemies. Boosts ATK of all characters by 1.5x for 1 turn", + specialNotes: "#{randomHits : 10}
    #{random : 1,000 : 32,000 : for each hit}", + sailor: "Reduces Paralysis duration by 1 turn", + specialName: "A Decree of the Veteran", + limit: [ + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base HP by 60" }, + { "description": "Aquire Potential 1: Pinch Healing" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base HP by 80" }, + { "description": "Reduce base Special Cooldown by 1" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 80" }, + { "description": "Boosts base ATK by 60" }, + { "description": "Aquire Sailor Ability 1: Reduces Blindness duration by 3 turn" }, + { "description": "Aquire new Captain Ability: Boosts ATK of all characters by 1.2x, heals for 1.5x her RCV at the end of the turn each time you hit a Good. Heals for .3x her RCV at the end of the turn each time you hit a Perfect" }, + { "description": "Reduce base Special Cooldown by 2 turns" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Reduce No Healing duration" }, + ], + potential: [ + { + "Name": "Pinch Healing", + "description": [ + "Level 1: If HP is below 10% at the start of the turn, heals for .5x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 2: If HP is below 15% at the start of the turn, heals for .5x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 3: If HP is below 20% at the start of the turn, heals for .5x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 4: If HP is below 30% at the start of the turn, heals for 1x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 5: If HP is below 50% at the start of the turn, heals for 1x this character's RCV at the end of the turn each time you hit a Perfect" + ] + }, + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: Reduces No Healing duration by 1 turn", + "Level 2: Reduces No Healing duration by 1 turn", + "Level 3: Reduces No Healing duration by 1 turn", + "Level 4: Reduces No Healing duration by 2 turns", + "Level 5: Reduces No Healing duration by 3 turns" + ] + }, + ] + }, + 1321: {//Momonga + captain: "Boosts ATK of Cerebral and Slasher characters by 2.25x and reduces damage received by 10% if there's a [STR], [DEX], [QCK], [INT], and [PSY] character on your crew.", + special: "Deals 15x character's ATK as [DEX] damage to all enemies. Boosts ATK against delayed enemies by 1.5x for 2 turns", + specialName: "Front Line Dissection", + sailor: "Boosts base ATK of Slasher and Cerebral characters by 75 if your captain is a Cerebral character", + }, + 1322: {//Momonga + captain: "Boosts ATK of Cerebral and Slasher characters by 2.5x and reduces damage received by 10% if there's a [STR], [DEX], [QCK], [INT], and [PSY] character on your crew.", + special: "Deals 15x character's ATK as [DEX] damage to all enemies. Boosts ATK against delayed enemies by 1.5x for 2 turns", + specialName: "Front Line Dissection", + sailor: "Boosts base ATK of Slasher and Cerebral characters by 75 if your captain is a Cerebral character", + }, + 1323: {//Onigumo + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of Slasher and Driven characters by 1.3x", + captainNotes: "The bonus is cumulative. Slasher + Driven characters get a 1.69x bonus.", + special: "Randomize [RCV], [TND], and [BLOCK] orbs. Makes [STR], [DEX], and [QCK] orbs \"beneficial\" to Driven and Slasher characters for 2 turns", + specialNotes: "\"Beneficial\" orbs grant the same ATK boost as matching orbs while retaining their original function.", + specialName: "Onigumo of Dismantling Swordsmanship", + sailor: "Reduces Paralysis for 5 turns for himself" + }, + 1324: {//Onigumo + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of Slasher and Driven characters by 1.6x", + captainNotes: "The bonus is cumulative. Slasher + Driven characters get a 2.56x bonus.", + special: "Randomize [RCV], [TND], and [BLOCK] orbs. Makes [STR], [DEX], and [QCK] orbs \"beneficial\" to Driven and Slasher characters for 2 turns", + specialNotes: "\"Beneficial\" orbs grant the same ATK boost as matching orbs while retaining their original function.", + specialName: "Onigumo of Dismantling Swordsmanship", + sailor: "Reduces Paralysis for 5 turns for himself" + }, + 1325: {//Halloween Corazon + captain: "Recovers 3x character's RCV in HP at the end of each turn", + special: "If HP is above 99%, changes [STR], [DEX], and [QCK] orbs into Matching orbs for Cerebral and Free Spirit characters", + specialName: "Amulet Flame", + }, + 1326: {//Halloween Corazon + captain: "Boosts ATK by 1.3x and recovers 4x character's RCV in HP at the end of each turn", + special: "If HP is above 99%, changes [STR], [DEX], and [QCK] orbs into Matching orbs for Cerebral and Free Spirit characters", + specialName: "Amulet Flame", + }, + 1327: {//Fornight Leo + captain: "Boosts ATK of characters with cost 20 or less by 2x", + special: [ + { + "description": "Deals 3x character's ATK as [DEX] damage to one enemy, change own orb into [DEX]", + "cooldown": [ 11, 4 ], + }, + { + "description": "Deal 15x character's ATK as [DEX] damage to one enemy, changes own and friend's orb into Matching orbs", + "cooldown": [ 19, 12 ], + } + ], + specialNotes: "#{stages}", + specialName: "Tail Hammer", + }, + 1328: {//Fornight Leo + captain: "Boosts ATK of characters with cost 20 or less by 2.5x", + special: [ + { + "description": "Deals 3x character's ATK as [DEX] damage to one enemy, change own orb into [DEX]", + "cooldown": [ 11, 4 ], + }, + { + "description": "Deal 15x character's ATK as [DEX] damage to one enemy, changes own and friend's orb into Matching orbs", + "cooldown": [ 19, 12 ], + } + ], + specialNotes: "#{stages}", + specialName: "Tail Hammer", + }, + 1329: {//Wicca + captain: "Reduces cooldown of Fighter and Free Spirit specials by 1 turn at the start of the fight. Gives chance of duplicating a drop upon completion of the island.", + captainNotes: "Does not work if she was not your captain upon starting the island. Stacks with other addional drop captains, giving you two chances of getting an extra drop.", + special: [ + { + "description": "Deals 6 fixed damage to all enemies. Randomizes orbs of upper row characters", + "cooldown": [ 9, 3 ], + }, + { + "description": "Deals 15 fixed damage to all enemies. Recovers 3x character's RCV in HP", + "cooldown": [ 11, 5 ], + }, + { + "description": "Deals 300 fixed damage to all enemies. Boosts the Color Affinity of Fighter and Free Spirit characters by 1.25x", + "cooldown": [ 16, 10 ], + }, + ], + specialName: "The Work of Fairies", + specialNotes: "#{colorAffinity : 1.25}
    #{stages}", + }, + 1330: {//Gancho + captain: "Boosts ATK of Striker characters by 1.5x and recovers 2x character's RCV in HP at the end of each turn", + special: "Switches orbs between slots twice. Makes Badly Matching and [BLOCK] orbs not reduce damage for 2 turns", + specialName: "Tonta Knowledge", + }, + 1331: {//Mansherry + captain: "Recovers 2x character's RCV in HP at the end of each turn", + special: [ + { + "description": "Reduces Bind duration for one character by 4 turns. Recovers 7x character's RCV in HP.", + "cooldown": [ 18, 11 ], + }, + { + "description": "Reduces Bind duration for one character by 7 turns. Recovers 15x character's RCV in HP.", + "cooldown": [ 24, 17 ], + }, + ], + specialNotes: "#{stages}", + specialName: "Tears of Healing", + }, + 1332: {//Mansherry + captain: "Recovers 3x character's RCV in HP at the end of each turn", + special: [ + { + "description": "Reduces Bind duration for one character by 4 turns. Recovers 7x character's RCV in HP.", + "cooldown": [ 18, 11 ], + }, + { + "description": "Reduces Bind duration for one character by 7 turns. Recovers 15x character's RCV in HP.", + "cooldown": [ 24, 17 ], + }, + ], + specialNotes: "#{stages}", + specialName: "Tears of Healing", + }, + 1333: {//Kabu + captain: "Boosts ATK of [STR] and Powerhouse characters by 1.4x", + captainNotes: "The bonus is cumulative. [STR] Powerhouse characters get a 1.96x bonus.", + special: "Slightly boosts chances of getting [STR] orbs and boosts own ATK by 1.2x for 2 turns", + specialName: "Yellow Kabu Squad", + }, + 1334: {//Bian + captain: "Boosts ATK of [DEX] and Free Spirit characters by 1.4x", + captainNotes: "The bonus is cumulative. [DEX] Free Spirit characters get a 1.96x bonus.", + special: "Poisons all enemies and randomizes all orbs", + specialName: "Pink Bee Squad", + }, + 1335: {//Wedding Sabo + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight. Boosts ATK of Free Spirit characters by 1.5x.", + special: "Changes Friend Captain orb into matching. Adds .5x to Chain multiplier for 1 turn", + specialName: "Gentleman's Welcome", + }, + 1336: {//Wedding Sabo + captain: "Reduces cooldown of all specials by 3 turns at the start of the fight. Boosts ATK of Free Spirit characters by 2x.", + special: "Changes Friend Captain orb into matching. Adds .5x to Chain multiplier for 1 turn", + specialName: "Gentleman's Welcome", + }, + 1337: {//Kanjuro + captain: "Boosts ATK of Striker and Free Spirit characters by 2x", + special: "Changes [RCV], [TND], [EMPTY], [G] and [BOMB] orbs into Badly Matching orbs and [STR], [QCK], [DEX], [PSY] and [INT] orbs into Matching orbs for Free Spirit and Striker characters.", + specialName: "Brushman's Brush", + }, + 1338: {//Kanjuro + captain: "Boosts ATK of Striker and Free Spirit characters by 2.25x, reduces damage received by 10%", + special: "Changes [RCV], [TND], [EMPTY], [G] and [BOMB] orbs into Badly Matching orbs and [STR], [QCK], [DEX], [PSY] and [INT] orbs into Matching orbs for Free Spirit and Striker characters.", + specialName: "Brushman's Brush", + limit: [ + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 40" }, + { "description": "Aquire Potential 1: [INT] Damage Reduction" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Aquire Sailor Ability 1: Restores his own special by 2 turns when it is rewinded" }, + { "description": "Boosts base HP by 60" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Aquire Potential 2: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "[INT] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [INT] characters by 1%", + "Level 2: Reduce damage taken from [INT] characters by ?%", + "Level 3: Reduce damage taken from [INT] characters by ?%", + "Level 4: Reduce damage taken from [INT] characters by ?%", + "Level 5: Reduce damage taken from [INT] characters by ?%" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 1 turn on this character", + "Level 2: Reduces Slot Bind duration by ? turns on this character", + "Level 3: Reduces Slot Bind duration by ? turns on this character", + "Level 4: Reduces Slot Bind duration by ? turns on this character", + "Level 5: Reduces Slot Bind duration by ? turns on this character" + ] + }, + ] + }, + 1339: {//Chopper Jump Point + captain: "Boosts ATK of [DEX] characters by 2.25x", + special: [ + { + "description": "Reduces Paralysis duration by 1 turn. Adds .2x to Chain multiplier for 1 turn", + "cooldown": [ 18, 8 ], + }, + { + "description": "Reduces Paralysis duration by 2 turn. Adds .3x to Chain multiplier for 1 turn", + "cooldown": [ 23, 13 ], + }, + { + "description": "Reduces Paralysis duration by 2 turn. Adds .5x to Chain multiplier for 1 turn", + "cooldown": [ 25, 15 ], + }, + ], + specialNotes: "#{stages}", + specialName: "Flight Power Strengthening - Jump Point", + }, + 1340: {//Gedatsu + captain: "Boosts ATK of [QCK] characters by 1.5x", + special: "Delays all enemies for 1 turn. Cuts the current HP of all enemies by 10%", + specialName: "Swamp Cloud Burger", + }, + 1341: {//Getdatsu + captain: "Boosts ATK of [QCK] characters by 1.75x. After scoring 3 hits below Good in a row, boosts ATK of [QCK] characters by 2.625x instead.", + special: "Delays all enemies for 1 turn. Cuts the current HP of all enemies by 10%", + specialName: "Swamp Cloud Burger", + }, + 1342: {//Dadan + captain: "Boosts HP of [PSY] characters by 1.75x", + special: "Reduces Silence duration by 2 turns", + specialNotes: "#{silence}", + specialName: "Rogue Threat", + }, + 1343: {//Porchemy + captain: "Reduces crew's current HP by 50%. Boosts ATK of Driven characters by 2x.", + special: "Deals 13x character's ATK in [DEX] damage to one enemy, and boosts ATK against enemies with reduced defense by 1.3x for 1 turn", + specialName: "Spiked Glove of Punishment", + }, + 1344: {//Bluejam + captain: "Reduces crew's current HP by 50%. Boosts ATK of Driven characters by 2.25x.", + special: "Deals 20x character's ATK in [STR] damage to all enemies, and boosts ATK of Driven characters by 1.3x for 1 turn", + specialName: "Bullet Purge", + }, + 1345: {//Jimbe + captain: "Boosts ATK of Fighter characters by 2.5x", + special: "Reduces Despair duration by 5 turns. Reduces Special Cooldown of your top row by 1 turn", + specialName: "Gathering Strength for a Counter Attack", + }, + 1346: {//Heracles'n + captain: "Boosts ATK, HP and RCV of Shooter and Cerebral characters by 1.5x", + special: "Randomizes all orbs, including [BLOCK] orbs, switches orbs between slots 3 times", + specialName: "Survival Techniques of the Hungry Baron", + }, + 1347: {//Torino Kingdom Monsters + special: "Change own orb into [PSY], and deals 25x character's attack in [PSY] damage to one enemy", + specialName: "Tsubami Behemoth", + }, + 1348: {//Humandrills + special: "Boosts ATK of all characters by 1.2x for 2 turns and amplifies the effect of orbs by 1.2x for 2 turns", + specialName: "Imitation Tactics", + }, + 1349: {//Haredas + captain: "Boosts ATK of Cerebral characters by 1.5x and their RCV by 1.75x", + special: "Empty all slots including [BLOCK] orbs, and boosts ATK of Cerebral characters by 1.2x for 1 turn", + specialName: "Gust 'Wind Knot'", + }, + 1350: {//Longarm Tribe Theives + special: "Switches orbs between slots 3 times", + specialName: "Longarm Tribe of Tehna Gehna", + }, + 1351: {//Tequila Wolf Guard + special: "Reduces the defense of all by 50% and delays all enemies for 1 turn", + specialName: "Covering Fire", + }, + 1352: {//Ivankov + captain: "Boosts ATK of Fighter characters by 2x at the start of the chain, boosts ATK of Fighter characters by 3.5x after the 5th Perfect in a row", + special: "Following the activation of the special, if every unit scores a Perfect hit, reduces damage received by 90% in the following turn", + specialName: "Rolling Beauty", + }, + 1353: {//Rayleigh + captain: "Boosts ATK of Cerebral characters by 2.5x", + special: "Deals 50,000 Fixed damage to one enemy, adds 0.5 to Chain multiplier for 1 turn", + specialName: "Guidence to Control Haki", + }, + 1354: {//Secret Rayleigh + captain: "Boosts chain multiplier by 2x, recovers 1.5x character's RCV in HP at the end of each turn", + special: "Recovers 15x character's RCV in HP, amplifies the effect of orbs by 1.5x for 1 turn", + specialName: "Straight Stimultaion", + specialNotes: "#{orb : 1.5x}", + }, + 1355: {//Secret Rayleigh + captain: "Boosts chain multiplier by 3x, recovers 1.5x character's RCV in HP at the end of each turn", + special: "Recovers 15x character's RCV in HP, amplifies the effect of orbs by 1.5x for 1 turn", + specialName: "Straight Stimultaion", + specialNotes: "#{orb : 1.5x}", + }, + 1356: {//Pekoms + captain: "Boosts ATK of Powerhouse characters by 1.5x", + special: "Changes [RCV] and [EMPTY] orbs into Matching orbs on Fighter characters. Makes Perfects easier to hit for 1 turn.", + specialName: "Serious Threat", + specialNotes: "Increases timing window to hit a Perfect. (Animation remains the same)" + }, + 1357: {//Pekoms + captain: "Boosts ATK, HP and RCV of Powerhouse characters by 1.5x", + special: "Changes [RCV] and [EMPTY] orbs into Matching orbs on Fighter characters. Makes Perfects easier to hit for 1 turn.", + specialName: "Serious Threat", + specialNotes: "Increases timing window to hit a Perfect. (Animation remains the same)" + }, + 1358: {//Tamago + captain: "Boosts ATK of Cerebral characters by 1.5x and the HP of Striker characters by 1.5x", + special: "Boosts RCV of all characters by 1.75x and delays all enemies by 1 turn.", + specialName: "The Long Legged Gentleman's Resolution", + }, + 1359: {//Tamago + captain: "Boosts ATK of Cerebral characters by 1.75x and the HP of Striker characters by 1.75x", + special: "Boosts RCV of all characters by 1.75x and delays all enemies by 1 turn.", + specialName: "The Long Legged Gentleman's Resolution", + }, + 1360: {//Winter Luffy + captain: "Boosts ATK characters with cost 30 or less by 2x and their HP by 1.2x", + special: "Changes own orb into [QCK], deals 15x character's ATK in [QCK] damage to one enemy", + specialName: "Gum-Gum Twin Jet Pistol: Snowflake", + }, + 1361: {//6* Zoro + captain: "If you have 5 or more Slashers in your crew, boosts ATK of Slasher characters by 2.5x and their HP by 1.5x. If you defeated an enemy last turn, boosts ATK of Slasher characters by 3x instead and boosts ATK of all other characters by 1.2x", + captainNotes: "You only need to kill at least 1 character in the last turn to gain his 3x ATK boost. If a character dies and revives, you will retain the 3x ATK boost", + special: "Deals 60x character's ATK as typeless damage to all enemies. If Zoro is your Captain or Friend/Guest Captain, boosts ATK of Slasher characters by 2x for 1 turn. If he is a Sailor, boosts ATK of Slasher characters by 1.75x for 1 turn instead", + specialName: "Three Blade Style Secret Skill: Crossroad of Six Paths", + }, + 1362: {//6* Zoro + captain: "If you have 5 or more Slashers in your crew, boosts ATK of Slasher characters by 2.5x and their HP by 1.5x. If you defeated an enemy last turn, boosts ATK of Slasher characters by 3x instead and boosts ATK of all other characters by 1.2x", + captainNotes: "You only need to kill at least 1 character in the last turn to gain his 3x ATK boost. If a character dies and revives, you will retain the 3x ATK boost", + special: "Deals 60x character's ATK as typeless damage to all enemies. If Zoro is your Captain or Friend/Guest Captain, boosts ATK of Slasher characters by 2x for 1 turn. If he is a Sailor, boosts ATK of Slasher characters by 1.75x for 1 turn instead", + specialName: "Three Blade Style Secret Skill: Crossroad of Six Paths", + }, + 1363: {//Timeskip Franky + captain: "Boosts ATK of [PSY] characters by 2x, reduces damage received by 10%", + special: "Deals 25x character's ATK in [PSY] damage to all enemies, amplifies the effect of orbs for [PSY] characters by 2x for 1 turn", + specialNotes: "#{orb : 2x}", + sailor: "Boosts base HP of [PSY] characters by 100", + specialName: "Franky Fireball", + }, + 1364: {//Timeskip Franky + captain: "Boosts ATK of [PSY] characters by 2.5x, reduces damage received by 10%", + special: "Deals 25x character's ATK in [PSY] damage to all enemies, amplifies the effect of orbs for [PSY] characters by 2x for 1 turn", + specialNotes: "#{orb : 2x}", + sailor: "Boosts base HP of [PSY] characters by 100", + specialName: "Franky Fireball", + }, + 1365: {//Timeskip Nami + captain: "Boosts ATK and RCV of Cerebral characters by 1.5x", + special: [ + { + "description": "Reduces Paralysis and Silence duration by 1 turn. Delays all enemies for 1 turn", + "cooldown": [ 13, 8 ], + }, + { + "description": "Reduces Paralysis and Silence duration by 2 turns. Delays all enemies for 1 turn", + "cooldown": [ 15, 10 ], + }, + { + "description": "Reduces Paralysis and Silence duration by 5 turns. Delays all enemies for 2 turns", + "cooldown": [ 18, 13 ], + }, + ], + sailorNotes: "#{silence}", + sailor: "Completely resists Silence on this character", + specialNotes: "#{silence}
    #{stages}", + specialName: "Black Ball - Thundercloud Rod", + }, + 1366: {//Timeskip Nami + captain: "Boosts RCV of Cerebral characters by 1.5x and their ATK by 2.75x if they have a matching orb, by 1.5x otherwise", + special: [ + { + "description": "Reduces Paralysis and Silence duration by 1 turn. Delays all enemies for 1 turn", + "cooldown": [ 13, 8 ], + }, + { + "description": "Reduces Paralysis and Silence duration by 2 turns. Delays all enemies for 1 turn", + "cooldown": [ 15, 10 ], + }, + { + "description": "Reduces Paralysis and Silence duration by 5 turns. Delays all enemies for 2 turns", + "cooldown": [ 18, 13 ], + }, + ], + sailorNotes: "#{silence}
    #{stages}", + sailor: "Completely resists Silence on this character", + specialNotes: "#{silence}", + specialName: "Black Ball - Thundercloud Rod", + }, + 1367: {//Timeskip Sanji + captain: "Boosts ATK of [STR] characters by 2x", + special: [ + { + "description": "Reduces damage received by 50% and amplifies the effect of orbs by 1.5x for 1 turn.", + "cooldown": [ 11, 6 ], + }, + { + "description": "Reduces damage received by 70% and amplifies the effect of orbs by 1.75x for 1 turn.", + "cooldown": [ 20, 15 ], + }, + ], + specialNotes: "#{orb : 1.75x}
    #{stages}", + sailor: "Boosts base ATK, HP and RCV of all characters by 50", + specialName: "Sky Walk", + }, + 1368: {//Timeskip Sanji + captain: "Boosts ATK of [STR] characters by 3x if HP is below 30% at the start of the turn, by 2.5x otherwise", + special: [ + { + "description": "Reduces damage received by 50% and amplifies the effect of orbs by 1.5x for 1 turn.", + "cooldown": [ 11, 6 ], + }, + { + "description": "Reduces damage received by 70% and amplifies the effect of orbs by 1.75x for 1 turn.", + "cooldown": [ 20, 15 ], + }, + ], + specialNotes: "#{orb : 1.75x}
    #{stages}", + sailor: "Boosts base ATK, HP and RCV of all characters by 50", + specialName: "Sky Walk", + }, + 1369: {//Timeskip Chopper + captain: "Boosts ATK of [QCK] characters by 1.5x and their HP and RCV by 1.2x", + special: "Changes [DEX] and [RCV] on [QCK] characters into [QCK], cuts the current HP of one enemy by 15%", + sailor: "Makes [STR] orbs \"beneficial\" for this unit", + specialName: "Kakuho: Elf", + }, + 1370: {//Timeskip Chopper + captain: "Boosts ATK of [QCK] characters by 2x and their HP and RCV by 1.2x", + special: "Changes [DEX] and [RCV] on [QCK] characters into [QCK], cuts the current HP of one enemy by 15%", + sailor: "Makes [STR] orbs \"beneficial\" for this unit", + specialName: "Kakuho: Elf", + }, + 1371: {//Wild Zoro + captain: "Boosts ATK of Slasher and Powerhouse characters by 2x at the start of the chain, by 2.25x after the 2nd Perfect in a row and by 2.5x after the 4th Perfect in a row.", + special: "Reduces Despair duration by 3 turns. Reduces Special Cooldown of Slasher and Powerhouse characters by 2 turns", + sailor: "Restores his own special by 2 turns when it is rewinded", + sailorNotes: "#{rewind : 2}", + specialName: "Wild Plan", + }, + 1372: {//Wild Zoro + captain: "Boosts ATK of Slasher and Powerhouse characters by 2x at the start of the chain, by 2.5x after the 2nd Perfect in a row and by 3x after the 4th Perfect in a row.", + special: "Reduces Despair duration by 3 turns. Reduces Special Cooldown of Slasher and Powerhouse characters by 2 turns", + sailor: "Restores his own special by 2 turns when it is rewinded", + sailorNotes: "#{rewind : 2}", + specialName: "Wild Plan", + }, + 1373: {//Magellan + captain: "Boosts ATK of INT characters by 1.5x and their HP by 1.2x, deals 5 times the damage received in the previous turn in [INT] damage to all enemies at the end of each turn", + special: [ + { + "description": "Poisons all enemies and delays all enemies for 1 turn.", + "cooldown": [ 25, 10 ], + }, + { + "description": "Inflicts Toxic to all enemies and delays all enemies for 1 turn.", + "cooldown": [ 31, 16 ], + }, + ], + specialName: "Poison Dragon", + specialNotes: "Toxic starts at 0.5x character's attack and increases by 3x at the end of every turn until 1,500,000 damage per turn.
    #{stages}", + }, + 1374: {//Magellan + captain: "Boosts ATK of INT characters by 2.25x and their HP by 1.5x, deals 5 times the damage received in the previous turn in [INT] damage to all enemies at the end of each turn", + special: [ + { + "description": "Poisons all enemies and delays all enemies for 1 turn.", + "cooldown": [ 25, 10 ], + }, + { + "description": "Inflicts Toxic to all enemies and delays all enemies for 1 turn.", + "cooldown": [ 31, 16 ], + }, + ], + specialName: "Poison Dragon", + specialNotes: "Toxic starts at 0.5x character's attack and increases by 3x at the end of every turn until 1,500,000 damage per turn.
    #{stages}", + }, + 1375: {//Dellinger + captain: "Boosts ATK of Powerhouse characters by 2.5x, reduces crew's HP by 50%, Increases damage received by 2x", + special: "Deals 20x character's ATK in [QCK] damage to one enemy, Boosts Dellinger's ATK by 1.5x for 1 turn, amplifies the effect of Dellinger's orb by 1.5x for 1 turn, and changes own orb to [QCK].", + specialNotes: "Boosted ATK and Orb Effectivess only works for the Dellinger who uses his Special.", + specialName: "Deadly Fangs of Rage", + }, + 1376: {//Dellinger + captain: "Boosts ATK of Powerhouse characters by 2.75x, reduces crew's HP by 20%, Increases damage received by 2x", + special: "Deals 20x character's ATK in [QCK] damage to one enemy, Boosts Dellinger's ATK by 1.5x for 1 turn, amplifies the effect of Dellinger's orb by 1.5x for 1 turn, and changes own orb to [QCK].", + specialNotes: "Boosted ATK and Orb Effectivess only works for the Dellinger who uses his Special.", + specialName: "Deadly Fangs of Rage", + }, + 1377: {//Marguerite + captain: "Boosts ATK and RCV of Slasher and Shooter characters by 1.3x", + special: "Recovers 18x character's RCV in HP. Reduces damage received by 50% for 1 turn", + sailor: "Boosts amount healed from [RCV] orbs by 125 each", + specialName: "Sincere Devotion", + }, + 1378: {//Marguerite + captain: "Boosts ATK and RCV of Slasher and Shooter characters by 1.75x", + special: "Recovers 18x character's RCV in HP. Reduces damage received by 50% for 1 turn", + sailor: "Boosts amount healed from [RCV] orbs by 125 each", + specialName: "Sincere Devotion", + }, + 1379: {//Shanks + captain: "Boosts chances of getting Matching orbs, boosts ATK of Cerebral characters by 2x", + special: "Reduces Paralysis duration by 3 turns. For Cerebral and Free Spirit characters, amplifies the effects of orbs by 2x for 1 turn. Makes [RCV] and [TND] orbs \"beneficial\" to Cerebral and Free Spirit characters for 1 turn.", + specialName: "A Decision Made over Sake", + specialNotes: "#{orb : 2x}", + }, + 1380: {//Shanks + captain: "Boosts chances of getting Matching orbs, boosts ATK of Cerebral characters by 2.5x", + special: "Reduces Paralysis duration by 3 turns. For Cerebral and Free Spirit characters, amplifies the effects of orbs by 2x for 1 turn. Makes [RCV] and [TND] orbs \"beneficial\" to Cerebral and Free Spirit characters for 1 turn.", + specialName: "A Decision Made over Sake", + specialNotes: "#{orb : 2x}", + }, + 1381: {//Christmas Tashigi + captain: "Boosts ATK and RCV of Slasher and Cerebral characters by 1.2x", + special: "Reduces Silence duration by 1 turn, and recovers 12,240 HP", + specialNotes: "Silence will refer to effects that prevent you from activating Special Abilities", + specialName: "Strawberry Smile", + specialNotes: "#{silence}", + }, + 1382: {//Christmas Tashigi + captain: "Boosts ATK and RCV of Slasher and Cerebral characters by 1.75x", + special: "Reduces Silence duration by 1 turn, and recovers 12,240 HP", + specialNotes: "Silence will refer to effects that prevent you from activating Special Abilities", + specialName: "Strawberry Smile", + specialNotes: "#{silence}", + }, + 1383: {//Soldier-San + captain: "Boosts ATK of Striker characters by 2x. Increases damage received by 1.5x", + special: "Reduces Paralysis, Bind, Despair, and Silence duration by 1 turn. Randomizes all Badly Matching, [BLOCK], or [EMPTY] orbs", + specialNotes: "#{silence}", + specialName: "Angry Extermination of Bugs", + }, + 1384: {//Soldier-San + captain: "Boosts ATK of Striker characters by 2.5x. Increases damage received by 1.5x", + special: "Reduces Paralysis, Bind, Despair, and Silence duration by 1 turn. Randomizes all Badly Matching, [BLOCK], or [EMPTY] orbs", + specialNotes: "#{silence}", + specialName: "Angry Extermination of Bugs", + }, + 1385: {//Rebecca + captain: "Reduces damage received by 20%", + special: "Removes blindness", + specialName: "Mother's Promise", + }, + 1386: {//Rebecca + captain: "Reduces damage received by 25%", + special: "Removes blindness", + specialName: "Mother's Promise", + }, + 1387: {//Luffy 5+ + captain: "Boosts ATK of all characters by 2.25x and their HP by 1.25x, boosts ATK by 2.8125x after scoring 4 Perfects in a row", + special: "Deals 40x character's ATK in [STR] damage to all enemies, and delays all enemies for 1 turn", + specialName: "Gum Gum: Elephant Gun", + limit: [ + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Aquire Potential 1: Enrage" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base HP by 50" }, + { "description": "Aquire Sailor Ability 1: Boosts own base ATK by 100 if this character is the last in the chain to attack" }, + { "description": "Boosts base HP by 50" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Aquire Sailor Ability 2: Makes [QCK] orbs \"beneficial\" for this unit" }, + { "description": "Aquire Potential 2: Reduce No Healing duration" }, + ], + potential: [ + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 20", + "Level 2: Boosts base ATK by 30", + "Level 3: Boosts base ATK by 40", + "Level 4: Boosts base ATK by 50", + "Level 5: Boosts base ATK by 100" + ] + }, + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: Reduces No Healing duration by 1 turn", + "Level 2: Reduces No Healing duration by 1 turn", + "Level 3: Reduces No Healing duration by 2 turns", + "Level 4: Reduces No Healing duration by 3 turns", + "Level 5: Reduces No Healing duration by 4 turns" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1388: {//Zoro 5+ + captain: "Boosts ATK of [DEX] characters by 2.5x", + special: "Cuts the current HP of each enemy by 10%. Reduces special cooldown of [DEX] specials by 1 turn.", + specialName: "Ittoriyu: Unfortunate Port Bird", + limit: [ + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 40" }, + { "description": "Aquire Potential 1: [QCK] Damage Reduction" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Aquire Sailor Ability 1: Restores his own special by 1 turn when it is rewinded" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Aquire Sailor Ability 2: Boosts base ATK of [DEX] characters by 40" }, + { "description": "Boosts base HP by 70" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Critical Hit" }, + ], + potential: [ + { + "Name": "[QCK] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [QCK] characters by ?%", + "Level 2: Reduce damage taken from [QCK] characters by ?%", + "Level 3: Reduce damage taken from [QCK] characters by ?%", + "Level 4: Reduce damage taken from [QCK] characters by ?%", + "Level 5: Reduce damage taken from [QCK] characters by ?%" + ] + }, + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage" + ] + }, + ] + }, + 1389: {//Nami 5+ + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, Boosts ATK of [INT] characters by 2x and their RCV by 1.5x.", + special: "Deals 20x character's ATK in [INT] damage to all enemies. Amplifies the effect of orbs for [INT] characters by 1.75x for 1 turn", + specialName: "Weather Egg: Thunder Breed Tempo", + specialNotes: "#{orb : 1.75x}", + }, + 1390: {//Buggy Legend + captain: "Boosts ATK of characters with cost 40 or less by 1.5x and boosts the HP and ATK of characters with cost 41 or greater by 0.5x. Guarantees duplicating a drop upon completion of the island.", + captainNotes: "Does not work if he was not your captain upon starting the island. Stacks with other addional drop captains, giving you two chances of getting an extra drop.", + special: "Randomizes all orbs. Boosts ATK of characters with cost 40 or less by 1.75x for 2 turns", + specialName: "Chop-Chop Clown Car", + }, + 1391: {//Buggy Legend + captain: "Boosts ATK of characters with cost 40 or less by 1.5x and reduces the HP and ATK of characters with cost 41 and greater by 0.5x. Guarantees duplicating a drop upon completion of the island.", + captainNotes: "Does not work if he was not your captain upon starting the island. Stacks with other addional drop captains, giving you two chances of getting an extra drop.", + special: "Randomizes all orbs. Boosts ATK of characters with cost 40 or less by 1.75x for 2 turns", + specialName: "Chop-Chop Clown Car", + }, + 1392: {//Sentomaru + captain: "Boosts ATK of Striker characters by 2x and boosts the HP of [PSY] characters by 1.25x", + captainNotes: "A character with both classes will get both boosts", + special: "Deals 25x character's ATK in [PSY] damage to all enemies. If during that turn every unit scores a Perfect hit, boosts ATK of [PSY] characters by 1.75x in the following turn.", + specialName: "Large Cutting Axe", + }, + 1393: {//Demaro Black + captain: "Boosts ATK of characters with cost 30 or less by 2x", + special: "Boosts ATK of all characters by 1.1x, slightly boosts chances of getting matching orbs and amplifies the effect of orbs by 1.1x for 7 turns", + specialName: "Three Forked Tongue", + }, + 1394: {//Kimono Baby 5 + captain: "Boosts ATK of [STR] and [QCK] characters by 1.5x and their RCV by 1.1x", + special: "Recovers 7x character's RCV in HP. Boosts ATK of Fighter and Striker characters by 1.5x for 1 turn", + specialName: "Nation's Ambition", + }, + 1395: {//Kimono Baby 5 + captain: "Boosts ATK of [STR] and [QCK] characters by 2.25x and their RCV by 1.2x", + special: "Recovers 7x character's RCV in HP. Boosts ATK of Fighter and Striker characters by 1.5x for 1 turn", + specialName: "Nation's Ambition", + }, + 1396: {//Tashigi Shambles + captain: "Boosts ATK of Driven characters by 1.75x and the HP of Striker Characters by 1.25x", + special: "Deals 7 hits of random [DEX] damage to random enemies. Reduces the defense of all enemies by 80% and delays all enemies for 1 turn", + specialName: "Surprise Jitte Onslaught", + specialNotes: "#{randomHits : 7}", + }, + 1397: {//Tashigi Shambles + captain: "Boosts ATK of Driven characters by 2x and the HP of Striker Characters by 1.5x", + special: "Deals 7 hits of random [DEX] damage to random enemies. Reduces the defense of all enemies by 80% and delays all enemies for 1 turn", + specialName: "Surprise Jitte Onslaught", + specialNotes: "#{randomHits : 7}", + }, + 1398: {//Smoker Shambles + captain: "Boosts ATK of Slasher and Cerebral characters by 1.5x", + special: "For Slasher characters, randomizes all non-matching orbs. Swaps this unit with your captain for 2 turns", + specialName: "Out-of-Control White Smoke", + }, + 1399: {//Smoker Shambles + captain: "Boosts ATK of Slasher and Cerebral characters by 1.5x, reduces damage received by 15%", + special: "For Slasher characters, randomizes all non-matching orbs. Swaps this unit with your captain for 2 turns", + specialName: "Out-of-Control White Smoke", + }, + 1400: {//Colo Gladius + captain: "Boosts ATK of Shooter characters by 1.75x and boosts ATK of Driven characters by 1.3x", + captainNotes: "The bonus is cumulative. Shooter Driven characters get a 2.275x bonus.", + special: [ + { + "description": "Deals 13x character's ATK in [STR] damage to all enemies, reduces Bind and Despair duration by 1 turn and boosts the Color Affinity of Shooter characters by 1.5x for 1 turn", + "cooldown": [ 26, 11 ], + }, + { + "description": "Deals 30x character's ATK in [STR] damage to all enemies, reduces Bind and Despair duration by 2 turns and boosts the Color Affinity of Shooter characters by 1.75x for 1 turn", + "cooldown": [ 33, 18 ], + }, + ], + specialName: "Stonewall Punk", + specialNotes: "#{colorAffinity : 1.75}
    #{stages}", + }, + 1401: {//Colo Gladius + captain: "Boosts ATK of Shooter characters by 1.75x and boosts ATK of Driven characters by 1.5x", + captainNotes: "The bonus is cumulative. Shooter Driven characters get a 2.625x bonus.", + special: [ + { + "description": "Deals 13x character's ATK in [STR] damage to all enemies, reduces Bind and Despair duration by 1 turn and boosts the Color Affinity of Shooter characters by 1.5x for 1 turn", + "cooldown": [ 26, 11 ], + }, + { + "description": "Deals 30x character's ATK in [STR] damage to all enemies, reduces Bind and Despair duration by 2 turns and boosts the Color Affinity of Shooter characters by 1.75x for 1 turn", + "cooldown": [ 33, 18 ], + }, + ], + specialName: "Stonewall Punk", + specialNotes: "#{colorAffinity : 1.75}
    #{stages}", + limit: [ + { "description": "Boosts base HP by 10" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 20" }, + { "description": "Aquire Potential 1: Enrage" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base RCV by 40" }, + { "description": "Aquire Sailor Ability 1: Reduces Silence duration against this unit by 2 turns" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base HP by 70" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Reduce base Special Cooldown by 2 turns" }, + { "description": "Aquire Potential 2: Barrier Penetration" }, + ], + potential: [ + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 20", + "Level 2: Boosts base ATK by 30", + "Level 3: Boosts base ATK by 40", + "Level 4: Boosts base ATK by 50", + "Level 5: Boosts base ATK by 100" + ] + }, + { + "Name": "Barrier Penetration", + "description": [ + "Level 1: This character's attack will ignore barriers if HP is above 99%", + "Level 2: This character's attack will ignore barriers if HP is above 99%", + "Level 3: This character's attack will ignore barriers if HP is above 99%", + "Level 4: This character's attack will ignore barriers if HP is above 80%", + "Level 5: This character's attack will ignore barriers if HP is above 50%" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1402: {//Colo Dalton + captain: "Boosts ATK of [PSY] and [QCK] characters by 2x", + special: [ + { + "description": "Deals 3x character's ATK in [PSY] damage to one enemy, boosts ATK of [PSY] characters by 1.3x for 1 turn", + "cooldown": [ 14, 4 ], + }, + { + "description": "Deals 13x character's ATK in [PSY] damage to one enemy, boosts ATK of [PSY] characters by 1.5x for 1 turn", + "cooldown": [ 18, 8 ], + }, + ], + specialNotes: "#{stages}", + specialName: "Offense Battle Axe", + }, + 1403: {//Timeskip Luffy + captain: "Boosts ATK of Free Spirit characters by 2.5x and reduce damage received by 15%. If you use \"Gomu Gomu no Red Hawk\" THIS LUFFY boosts ATK of Free Spirit characters by 4x instead for 3 turns.", + captainNotes: "Using Luffy's special will change his own captain boost to 4x. If both Luffy's specials are used, the total ATK boost will be 16x", + special: [ + { + "description": "Deals 25x character's ATK in [QCK] damage to one enemy, and makes [QCK], [DEX], and [PSY] orbs \"beneficial\" to Fighter and Free Spirit characters for 1 turn", + "cooldown": [ 13, 8 ], + }, + { + "description": "Deals 60x character's ATK in [QCK] damage to one enemy, and makes [QCK], [DEX], and [PSY] orbs \"beneficial\" for 3 turns", + "cooldown": [ 18, 13 ], + }, + ], + specialNotes: "#{stages}", + specialName: "Gomu Gomu no Red Hawk", + }, + 1404: {//Timeskip Luffy + captain: "Boosts ATK of Free Spirit characters by 2.5x and reduce damage received by 15%. If you use \"Gomu Gomu no Red Hawk\" THIS LUFFY boosts ATK of Free Spirit characters by 4x instead for 3 turns.", + captainNotes: "Using Luffy's special will change his own captain boost to 4x. If both Luffy's specials are used, the total ATK boost will be 16x", + special: [ + { + "description": "Deals 25x character's ATK in [QCK] damage to one enemy, and makes [QCK], [DEX], and [PSY] orbs \"beneficial\" to Fighter and Free Spirit characters for 1 turn", + "cooldown": [ 13, 8 ], + }, + { + "description": "Deals 60x character's ATK in [QCK] damage to one enemy, and makes [QCK], [DEX], and [PSY] orbs \"beneficial\" for 3 turns", + "cooldown": [ 18, 13 ], + }, + ], + specialNotes: "#{stages}", + specialName: "Gomu Gomu no Red Hawk", + }, + 1405: {//Timeskip Usopp + captain: "Boosts ATK of Shooter characters by 1.75x, and their RCV by 1.25x", + special: "Deals 10 hits of 2,000 fixed damage to random enemies, and if enemies have delay protection at the time the special was activated, boosts ATK of Shooter characters by 1.75x and amplifies the effect of orbs for Shooter characters by 1.75x for 1 turn", + specialNotes: "#{randomHits : 10}", + specialName: "Assault Meteor Shower", + sailor: "When HP is below 30% at the start of the turn, boosts ATK and RCV of Shooter characters by 100", + }, + 1406: {//Timeskip Usopp + captain: "Boosts ATK of Shooter characters by 2.25x, and their RCV by 1.5x", + special: "Deals 10 hits of 2,000 fixed damage to random enemies, and if enemies have delay protection at the time the special was activated, boosts ATK of Shooter characters by 1.75x and amplifies the effect of orbs for Shooter characters by 1.75x for 1 turn", + specialNotes: "#{randomHits : 10}", + specialName: "Assault Meteor Shower", + sailor: "When HP is below 30% at the start of the turn, boosts ATK and RCV of Shooter characters by 100", + }, + 1407: {//Timeskip Robin + captain: "Boosts ATK of [DEX] and [PSY] characters by 1.75x and their RCV by 1.25x", + special: "Reduces Despair duration by 3 turns and boosts ATK of [DEX] and [PSY] characters by 2x for 1 turn", + specialName: "Mil Fleur: Gigantesco Mano Stomp", + sailor: "Reduces Blindness duration by 3 turns", + }, + 1408: {//Timeskip Robin + captain: "Boosts ATK of [DEX] and [PSY] characters by 2.25x and their RCV by 1.5x", + special: "Reduces Despair duration by 3 turns and boosts ATK of [DEX] and [PSY] characters by 2x for 1 turn", + specialName: "Mil Fleur: Gigantesco Mano Stomp", + sailor: "Reduces Blindness duration by 3 turns", + }, + 1409: {//Timeskip Brook + captain: "Protects from defeat as long as HP is above 50%", + captainNotes: "#{zombie}", + special: "Delays all enemies by 1 turn, and boosts ATK of Slasher and Free Spirit characters by 1.75x for 1 turn", + specialName: "Soul's Murder Soul: Soul Solid", + sailor: "Completely resists Paralysis on this character", + }, + 1410: {//Timeskip Brook + captain: "Boosts chain multiplier by 2.5x. Protects from defeat as long as HP is above 50%", + captainNotes: "#{zombie}", + special: "Delays all enemies by 1 turn, and boosts ATK of Slasher and Free Spirit characters by 1.75x for 1 turn", + specialName: "Soul's Murder Soul: Soul Solid", + sailor: "Completely resists Paralysis on this character", + }, + 1411: {//Timeskip Chopper Again + captain: "Boosts ATK of Powerhouse characters by 2.25x, reduces crew's RCV to 0", + special: "Reduces enemies Percent Damage Reduction and Increased Defense duration by 3 turns and deals 60x character's ATK in typeless damage to all enemies", + specialNotes: "This does not affect threshold damage reduction. Damage Reduction is the rainbow shield buff enemies have, and Increased Defense is the blue shiled buff enemies have", + specialName: "Carving Hoof Palm: Coconut", + sailor: "If Chopper has a [STR] orb and you hit a Perfect with him, keep his [STR] orb for the next turn", + }, + 1412: {//Timeskip Chopper Again + captain: "Boosts ATK of Powerhouse characters by 2.75x, reduces crew's RCV to 0", + special: "Reduces enemies Percent Damage Reduction and Increased Defense duration by 3 turns and deals 60x character's ATK in typeless damage to all enemies", + specialNotes: "This does not affect threshold damage reduction. Damage Reduction is the rainbow shield buff enemies have, and Increased Defense is the blue shield buff enemies have", + specialName: "Carving Hoof Palm: Coconut", + sailor: "If Chopper has a [STR] orb and you hit a Perfect with him, keep his [STR] orb for the next turn", + }, + 1413: {//6+ Whitebeard + captain: "Boosts ATK of all characters by 3x if HP is below 30% at the start of the turn, 1.75x otherwise and boosts the HP of all characters by 1.2x", + special: "Cuts the current HP of each enemy by 30%, reduces special cooldown of all non-Captain specials by 1 turn, and randomizes non-matching orbs including [BLOCK] orbs.", + specialName: "Emperor's Pride", + limit: [ + { "description": "Boosts base ATK by 5" }, + { "description": "Boosts base HP by 5" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Aquire Potential 1: [DEX] Damage Reduction" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK of Striker and Powerhouse characters by 60" }, + { "description": "Boosts base ATK by 10" }, + { "description": "Boosts base HP by 15" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 35" }, + { "description": "Boosts base HP by 40" }, + { "description": "Aquire Potential 2: Critical Hit" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 45" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base HP by 65" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base HP by 70" }, + { "description": "Boosts base HP by 80" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base RCV by 40" }, + { "description": "Aquire Sailor Ability 2: Completely resists Paralysis on this character" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Aquire Potential 3: Enrage" }, + ], + potential: [ + { + "Name": "[DEX] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [DEX] characters by 2%", + "Level 2: Reduce damage taken from [DEX] characters by 3%", + "Level 3: Reduce damage taken from [DEX] characters by 4%", + "Level 4: Reduce damage taken from [DEX] characters by 5%", + "Level 5: Reduce damage taken from [DEX] characters by 7%" + ] + }, + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 20% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage" + ] + }, + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 25", + "Level 2: Boosts base ATK by ??", + "Level 3: Boosts base ATK by ??", + "Level 4: Boosts base ATK by ??", + "Level 5: Boosts base ATK by ??" + ] + }, + ] + }, + 1414: {//Shop Sanji + captain: "Boosts ATK of Powerhouse characters by 2.5x", + special: "Changes own orb into [INT] and reduces Special Cooldown of Powerhouse characters by 1 turn.", + specialName: "Are you ready?", + }, + 1415: {//Fortnight Sengoku + captain: "Boosts ATK of characters with cost 30 or less by 1.5x", + special: "Reduces Special Cooldown of all characters with cost 30 or less by 1 turn and boosts ATK of characters with cost 30 or less by 1.5x for 1 turn", + specialName: "Unshakeable Resolution of the Wise Master", + }, + 1416: {//Fortnight Sengoku + captain: "Boosts ATK of characters with cost 30 or less by 2.25x and their HP by 1.2x", + special: "Reduces Special Cooldown of all characters with cost 30 or less by 1 turn and boosts ATK of characters with cost 30 or less by 1.5x for 1 turn", + specialName: "Unshakeable Resolution of the Wise Master", + }, + 1417: {//Ronse + captain: "Boosts ATK and HP of [STR] characters by 1.5x", + special: "Cuts the current HP of all enemies by 10%, changes [BLOCK] orbs into [STR] orbs for Slasher characters", + specialName: "Raid Battle-Axe: One Flash", + }, + 1418: {//Stainless + captain: "Boosts ATK and RCV of INT characters by 1.5x", + special: "Reduces any damage received above 5,000 HP by 99% for 1 turn", + specialName: "Defence of the Command Line", + }, + 1419: {//Kimono Lucci + captain: "Boosts ATK of Powerhouse characters by 2x, reduce damage received by 10%", + special: "Recovers 5,000 HP and boosts ATK against enemies with reduced defense by 1.5x for 1 turn", + specialName: "Demonic Style", + }, + 1420: {//Kimono Lucci + captain: "Boosts ATK of Powerhouse characters by 2.5x, reduce damage received by 10%", + special: "Recovers 5,000 HP and boosts ATK against enemies with reduced defense by 1.5x for 1 turn", + specialName: "Demonic Style", + }, + 1421: {//Coliseum Diamante + captain: "Boosts ATK of Driven characters by 2x", + special: "Deals 20x Character's ATK in [INT] damage to all enemies. If HP is full at the time the special was activated, boosts ATK of Driven characters by 2x for 1 turn, 1.5x otherwise", + specialName: "Half Moon Glaive", + }, + 1422: {//Coliseum Diamante + captain: "Boosts ATK of Driven characters by 2.25x and boosts HP of Striker and Slasher characters by 1.5x", + special: "Deals 20x Character's ATK in [INT] damage to all enemies. If HP is full at the time the special was activated, boosts ATK of Driven characters by 2x for 1 turn, 1.5x otherwise", + specialName: "Half Moon Glaive", + }, + 1423: {//Coliseum T-Bone + captain: "Boosts ATK of the whole crew by 1.75x and recovers 918 HP at end of each turn,", + special: "If HP is below 500, reduces damage received by 99% for 1 turn", + specialName: "For the Sake of Justice", + }, + 1424: {//Coliseum Gin + captain: "Boosts ATK of Striker characters proportionally to the crew's current HP", + captainNotes: "#{captainProportional : higher : 1 + 1.25 * (remaining HP) / (total HP) : 2.25 : 1}", + special: "Deals 500 fixed damage to all enemies and reduces Special Cooldown of Striker characters by 1 turn.", + specialName: "General Commander's Fight", + }, + 1425: {//Don Sai + captain: "Boosts ATK of Fighter and Striker characters by 1.75x", + special: "Deals 25x character's ATK in QCK damage to one enemy. If a character is locked at the time the special was activated, amplifies the effect of orbs by 1.5x for 3 turns", + specialName: "Military Leg Heel", + }, + 1426: {//Don Sai + captain: "Boosts ATK of Fighter and Striker characters by 2x and their HP by 1.25x", + special: "Deals 25x character's ATK in QCK damage to one enemy. If a character is locked at the time the special was activated, amplifies the effect of orbs by 1.5x for 3 turns", + specialName: "Military Leg Heel", + }, + 1427: {//Boo + captain: "Boosts ATK of QCK characters by 2x", + special: "Deals 15x character's ATK in QCK damage to one enemy that will ignore damage negating abilities and barriers.", + specialNotes: "#{ignoreBarrier}", + specialName: "Unblockable Eight Fists", + }, + 1428: {//Jean Ango + captain: "Boosts amount of Beli received by 1.5x, and gives chance of duplicating a drop upon completion of the island", + captainNotes: "Does not work if he was not your captain upon starting the island. Stacks with other addional drop captains, giving you two chances of getting an extra drop.", + special: "If the enemy is delayed at the time the special is activated, reduces Special Cooldown of all characters by 1 turn and boosts own attack by 1.75x for 1 turn", + specialName: "Looting the Losers", + }, + 1429: {//Valentines Mansherry + captain: "Boosts the RCV of Striker and Free Spirit characters by 1.5x", + special: "Reduces Bind, Despair, and Paralysis duration by 3 turns and recovers 2000 HP at the end of each turn for 3 turns", + specialName: "Boy's Unknown Taste of Hard Work", + }, + 1430: {//Valentines Mansherry + captain: "Boosts the RCV of Striker and Free Spirit characters by 2x", + special: "Reduces Bind, Despair, and Paralysis duration by 3 turns and recovers 2000 HP at the end of each turn for 3 turns", + specialName: "Boy's Unknown Taste of Hard Work", + }, + 1431: {//Raid Franky + captain: "Boosts ATK of all characters by 2x if there's a [STR], [DEX], [QCK], [PSY], and [INT] character in your crew, and boosts their HP by 1.2x if there's a Fighter, Slasher, Shooter, Driven, Free Spirit, and Powerhouse character in your crew", + special: "Deals 100x character's ATK in typeless damage to all enemies, removes enemies' ATK Up, Enrage, End of Turn Damage/Percent Cut, and End of Turn Heal Buffs, and boosts ATK of all characters by 1.5x for 1 turn", + specialName: "General Cannon", + }, + 1432: {//Raid Franky + captain: "Boosts ATK of all characters by 2.5x if there's a [STR], [DEX], [QCK], [PSY], and [INT] character in your crew, and boosts their HP by 1.5x if there's a Fighter, Slasher, Shooter, Driven, Free Spirit, and Powerhouse character in your crew", + special: "Deals 100x character's ATK in typeless damage to all enemies, removes enemies' ATK Up, Enrage, End of Turn Damage/Percent Cut, and End of Turn Heal Buffs, and boosts ATK of all characters by 1.5x for 1 turn", + specialName: "General Cannon", + }, + 1433: {//Hody Jones + captain: "Reduces cooldown of Powerhouse specials by 1 turn at the start of the fight, reduces crew's current HP by 10% at the end of each turn, and boosts ATK of Powerhouse characters by 3x if there are 6 Powerhouse characters in your crew and boosts HP of Powerhouse characters by up to 2x depending on how many Powerhouse characters are in your crew.", + captainNotes: "Hody's HP boost is dependent on how many Powerhouse characters are in your crew. With 6 Powerhouse characters, the boost is 2x, with 5 the boost is 1.5x, with 4 the boost is 1.4x, with 3 the boost is 1.3x, with 2 the boost is 1.2x, and with 1 the boost is 1.1x.", + special: [ + { + "description": "Deals 10x character's ATK in [INT] damage to one enemy that will ignore damage negating abilities and barriers, reduces Special Cooldown of Powerhouse characters by 1 turn, reduces damage received by 60% for 1 turn", + "cooldown": [ 12, 7 ], + }, + { + "description": "Deals 60x character's ATK in [INT] damage to one enemy that will ignore damage negating abilities and barriers, reduces Special Cooldown of Powerhouse characters by 2 turns, reduces damage received by 90% for 1 turn", + "cooldown": [ 22, 17 ], + }, + ], + specialNotes: "#{ignoreBarrier}
    #{stages}", + specialName: "Water Bullets", + }, + 1434: {//Hody Jones + captain: "Reduces cooldown of Powerhouse specials by 1 turn at the start of the fight, reduces crew's current HP by 10% at the end of each turn, and boosts ATK of Powerhouse characters by 3x if there are 6 Powerhouse characters in your crew and boosts HP of Powerhouse characters by up to 2x depending on how many Powerhouse characters are in your crew.", + captainNotes: "Hody's HP boost is dependent on how many Powerhouse characters are in your crew. With 6 Powerhouse characters, the boost is 2x, with 5 the boost is 1.5x, with 4 the boost is 1.4x, with 3 the boost is 1.3x, with 2 the boost is 1.2x, and with 1 the boost is 1.1x.", + special: [ + { + "description": "Deals 10x character's ATK in [INT] damage to one enemy that will ignore damage negating abilities and barriers, reduces Special Cooldown of Powerhouse characters by 1 turn, reduces damage received by 60% for 1 turn", + "cooldown": [ 12, 7 ], + }, + { + "description": "Deals 60x character's ATK in [INT] damage to one enemy that will ignore damage negating abilities and barriers, reduces Special Cooldown of Powerhouse characters by 2 turns, reduces damage received by 90% for 1 turn", + "cooldown": [ 22, 17 ], + }, + ], + specialNotes: "#{ignoreBarrier}
    #{stages}", + specialName: "Water Bullets", + limit: "This character has a limit break path", + }, + 1435: {//Hyouzou + captain: "Boosts ATK of Slasher characters by 2x and HP of Powerhouse characters by 1.2x", + special: "Makes Perfects harder to hit for 1 turn, changes [STR], [QCK], [DEX], [PSY] and [INT] orbs into Matching orbs for Powerhouse characters, delays all enemies for 1 turn, recovers 20% of crew's MAX HP.", + specialName: "Staggering Slash", + specialNotes: "Decreases timing window to hit a Perfect. (Animation remains the same)", + sailor: "Boosts base ATK of all characters by 150 if there are 6 Powerhouse characters in your crew", + }, + 1436: {//Hyouzou + captain: "Boosts ATK of Slasher characters by 2.5x and HP of Powerhouse characters by 1.25x", + special: "Makes Perfects harder to hit for 1 turn, changes [STR], [QCK], [DEX], [PSY] and [INT] orbs into Matching orbs for Powerhouse characters, delays all enemies for 1 turn, recovers 20% of crew's MAX HP.", + specialName: "Staggering Slash", + specialNotes: "Decreases timing window to hit a Perfect. (Animation remains the same)", + sailor: "Boosts base ATK of all characters by 150 if there are 6 Powerhouse characters in your crew", + limit: "This character has a limit break path", + }, + 1437: {//Ikaros Much + captain: "Boosts ATK of Powerhouse and Striker characters by 1.3x", + captainNotes: "The bonus is cumulative. Powerhouse + Striker characters get a 1.69x bonus.", + special: "Reduce crew's current HP by 50%, amplifies the effect of orbs for Powerhouse characters by 1.75x and boosts ATK against delayed enemies by 1.5x for 1 turn", + specialName: "Squid Spear", + sailor: "Makes [STR], [QCK], [DEX], [PSY] and [INT] orbs \"beneficial\" for this unit if there are 6 Powerhouse characters in your crew", + }, + 1438: {//Ikaros Much + captain: "Boosts ATK of Powerhouse and Striker characters by 1.6x", + captainNotes: "The bonus is cumulative. Powerhouse + Striker characters get a 2.56x bonus.", + special: "Reduce crew's current HP by 50%, amplifies the effect of orbs for Powerhouse characters by 1.75x and boosts ATK against delayed enemies by 1.5x for 1 turn", + specialName: "Squid Spear", + sailor: "Makes [STR], [QCK], [DEX], [PSY] and [INT] orbs \"beneficial\" for this unit if there are 6 Powerhouse characters in your crew", + }, + 1439: {//Daruma + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of Powerhouse and Fighter characters by 1.2x", + special: "Reduces Paralysis and Silence duration by 2 turns, cuts the current HP of one enemy by 10%, boosts ATK of Powerhouse characters by 1.75x for 1 turn", + specialNotes: "#{silence}", + specialName: "Fire Daruma Cutter", + sailor: "Completely resists Silence on this character", + sailorNotes: "#{silence}", + }, + 1440: {//Daruma + captain: "Reduces cooldown of all specials by 4 turns at the start of the fight, boosts ATK of Powerhouse and Fighter characters by 1.5x", + special: "Reduces Paralysis and Silence duration by 2 turns, cuts the current HP of one enemy by 10%, boosts ATK of Powerhouse characters by 1.75x for 1 turn", + specialNotes: "#{silence}", + specialName: "Fire Daruma Cutter", + sailor: "Completely resists Silence on this character", + sailorNotes: "#{silence}", + limit: "This character has a limit break path", + }, + 1441: {//Zeo + captain: "Boosts ATK of [INT] characters by 1.5x, and reduces damage received by 10%", + special: "Makes Perfects easier to hit, locks all orbs, and locks the chain multiplier at 2.5x for 1 turn", + specialNotes: "Increases timing window to hit a Perfect. (Animation remains the same)", + specialName: "Flail Hidden From God", + sailor: "Completely resists Blindness if your Captain is a Powerhouse character", + }, + 1442: {//Zeo + captain: "Boosts ATK of [INT] characters by 2.25x and reduces damage received by 20%", + special: "Makes Perfects easier to hit, locks all orbs, and locks the chain multiplier at 2.5x for 1 turn", + specialNotes: "Increases timing window to hit a Perfect. (Animation remains the same)", + specialName: "Flail Hidden From God", + sailor: "Completely resists Blindness if your Captain is a Powerhouse character", + limit: "This character has a limit break path", + }, + 1443: {//Dosun + captain: "Boosts ATK of Powerhouse characters by 2.75x following a chain of Good > Great > Perfect hits", + special: "Changes [RCV], [TND], [EMPTY], [BLOCK] and [BOMB] orbs into [STR], [QCK], [DEX], [PSY] or [INT] orbs, boosts ATK of Powerhouse characters by 1.5x and amplifies the effect of orbs by 1.5x for 1 turn", + specialName: "Papara Hammer", + sailor: "Boost HP of all characters by 150 and also ATK of all characters by 50 if there are 6 Powerhouse characters in your crew", + }, + 1444: {//Dosun + captain: "Boosts ATK of Powerhouse characters by 3.25x following a chain of Good > Great > Perfect hits", + special: "Changes [RCV], [TND], [EMPTY], [BLOCK] and [BOMB] orbs into [STR], [QCK], [DEX], [PSY] or [INT] orbs, boosts ATK of Powerhouse characters by 1.5x and amplifies the effect of orbs by 1.5x for 1 turn", + specialName: "Papara Hammer", + sailor: "Boost HP of all characters by 150 and also ATK of all characters by 50 if there are 6 Powerhouse characters in your crew", + limit: "This character has a limit break path", + }, + 1445: {//Boa Hancock+ + captain: "Boosts ATK of [QCK] and [PSY] characters proportionally to the crew's current HP. If HP is below 50%, Boosts RCV of [QCK] and [PSY] units by 1.5x.", + special: "Boosts ATK and RCV of [QCK] and [PSY] characters by 1.75x for 1 turn, and delays all enemies for 1 turn. Changes your Captain orb to [RCV]. If HP is above 50%, changes left column into Matching orbs.", + specialName: "Perfume Femur", + captainNotes: "#{captainProportional : higher : 2.25 + 0.5 * (remaining HP) / (total HP) : 2.75 : 2.25}" + }, + 1446: {//Sogeking 5+ + captain: "Boosts ATK of Shooter characters by 2x and RCV of Shooter characters by 1.25x.", + special: "Deals random PSY damage to all enemies and delays enemies by 3 turns.", + specialName: "Green Star: Platanus Shuriken", + limit: "This character has a limit break path", + }, + 1447: {//Sanji 5+ + captain: "Boosts ATK of Powerhouse characters by 2.5x and reduces damage take by 10%.", + special: [ + { + "description": "Deals 5,000 fixed damage to all enemies and boosts own ATK by 1.2x for 1 turn.", + "cooldown": [ 15, 10 ], + }, + { + "description": "Deals 50,000 fixed damage to all enemies and boosts own ATK by 1.5x for 1 turn.", + "cooldown": [ 20, 15 ], + }, + ], + specialNotes: "#{stages}", + specialName: "Grill Shot", + }, + 1448: {//Chopper 5+ + captain: "Boosts ATK of Fighter characters by 2.5x.", + special: "Deals PSY damage according to HP. For Fighter characters, Changes [BLOCK] orbs into matching orbs.", + specialNotes: "The exact damage is proportional to the crew's remaining HP and is higher the higher the HP is. The formula used is ???? * (current HP) / (total HP)", + specialName: "Weight Gain: Heavy Gong", + }, + 1449: {//Violet + captain: "Boosts ATK of Cerebral characters by 1.5x. Heals for .3x character's RCV at the end of the turn each time you hit a Great.", + special: "Reduces the defense of all enemies by 50% for 1 turn, and if HP is below 50%, randomly changes all orbs to either [RCV] or [TND] orbs", + specialName: "Clairvoyance", + }, + 1450: {//Violet + captain: "Boosts ATK of Cerebral characters by 1.75x. Heals for .5x character's RCV at the end of the turn each time you hit a Great.", + special: "Reduces the defense of all enemies by 50% for 1 turn, and if HP is below 50%, randomly changes all orbs to either [RCV] or [TND] orbs", + specialName: "Clairvoyance", + }, + 1451: {//Moustache Sanji + captain: "Boosts ATK of [DEX] characters by 2.25x if they have a matching orb, by 1.5x otherwise. Slightly boosts chances of getting [DEX] orbs", + special: "Deals 15x character's ATK in DEX damage to one enemy, and boosts chances of getting DEX orbs for 2 turns", + specialName: "Diable Jambe: Love Shot", + }, + 1452: {//Moustache Sanji + captain: "Boosts ATK of [DEX] characters by 2.5x if they have a matching orb, by 2x otherwise. Slightly boosts chances of getting [DEX] orbs", + special: "Deals 15x character's ATK in DEX damage to one enemy, and boosts chances of getting DEX orbs for 2 turns", + specialName: "Diable Jambe: Love Shot", + }, + 1453: {//Valentines Margeurite + captain: "Boosts ATK of [STR], [DEX] and [QCK] characters by 1.5x", + special: "Changes all orbs depending on the current HP", + specialNotes: "
    HP>70%: Top row to [QCK], middle row to [STR]
    HP<30%: Top row to [RCV], middle row to [QCK], bottom row to [STR]", + specialName: "Doki Doki Heart", + }, + 1454: {//Valentines Margeurite + captain: "Boosts ATK of [STR], [DEX] and [QCK] characters by 1.75x and their RCV by 1.5x", + special: "Changes all orbs depending on the current HP", + specialNotes: "
    HP>70%: Top row to [QCK], middle row to [DEX], bottom row to [STR]
    HP<30%: Top row to [RCV], middle row to [QCK], bottom row to [STR]", + specialName: "Doki Doki Heart", + }, + 1455: {//Coliseum Don Chinjao + captain: "Boosts ATK of Driven characters by 2.5x until the first hit other than Perfect and recovers 120 HP at end of each turn", + special: [ + { + "description": "Cuts the current HP of one enemy by 20%, reduces damage received by 50% for 1 turn", + "cooldown": [ 25, 10 ], + }, + { + "description": "Cuts the current HP of one enemy by 25%, reduces damage received by 70% for 1 turn", + "cooldown": [ 30, 15 ], + }, + ], + specialNotes: "#{stages}", + specialName: "Legend told to the Grandchild", + }, + 1456: {//Coliseum Don Chinjao + captain: "Boosts ATK of Powerhouse characters by 2.75x until the first hit other than Perfect and recovers 120 HP at end of each turn", + special: [ + { + "description": "Cuts the current HP of one enemy by 20%, reduces damage received by 50% for 1 turn", + "cooldown": [ 25, 10 ], + }, + { + "description": "Cuts the current HP of one enemy by 25%, reduces damage received by 70% for 1 turn", + "cooldown": [ 30, 15 ], + }, + ], + specialNotes: "#{stages}", + specialName: "Legend told to the Grandchild", + }, + 1457: {//Coliseum Kuro + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of [QCK] and [INT] characters by 1.75x", + special: "Reduces Bind and Despair duration by 2 turns, for Slasher and Cerebral characters, randomizes non-matching orbs and changes own orb into [INT]", + specialName: "Pussyfoot Maneuver", + }, + 1458: {//Coliseum Kuro + captain: "Reduces cooldown of all specials by 2 turn at the start of the fight, boosts ATK of [QCK] and [INT] characters by 2x", + special: "Reduces Bind and Despair duration by 2 turns, for Slasher and Cerebral characters, randomizes non-matching orbs and changes own orb into [INT]", + specialName: "Pussyfoot Maneuver", + }, + 1459: {//Coliseum Miss Valentine + captain: "Boosts ATK by 1.75x following a chain of Good > Good > Great > Perfect hits", + special: "Binds self for 2 turns, makes [BOMB] orbs \"beneficial\" and boosts ATK against enemies with reduced defense by 1.5x for 1 turn.", + specialName: "Crescendo Stone", + }, + 1460: {//Coliseum Miss Valentine + captain: "Boosts ATK by 2.14x following a chain of Good > Good > Great > Perfect hits", + special: "Binds self for 2 turns, makes [BOMB] orbs \"beneficial\" and boosts ATK against enemies with reduced defense by 1.5x for 1 turn.", + specialName: "Crescendo Stone", + }, + 1461: {//Snow Zoro + captain: "Boosts ATK of [QCK] characters by 2x at the start of the chain, by 2.6x after the 3rd Perfect in a row.", + special: "Deals 11x character's ATK in [QCK] damage to one enemy, boosts ATK of [QCK] characters by 1.5x for 1 turn", + specialName: "Demoltion: Ice Crush", + }, + 1462: {//White Day Luffy + captain: "Boosts chain multiplier by 2x", + special: "Reduces crew's current HP by 50%, cuts the current HP of each enemy by 20%, and makes [PSY] and [STR] orbs \"beneficial\" to Fighter characters for 1 turn", + sailor: "Reduces Paralysis for 2 turns for himself", + specialName: "Gum-Gum Gigant Axe - Sweets", + }, + 1463: {//White Day Luffy + captain: "Boosts chain multiplier by 2.5x, recovers 1.5x character's RCV in HP at the end of each turn", + special: "Reduces crew's current HP by 50%, cuts the current HP of each enemy by 20%, and makes [PSY] and [STR] orbs \"beneficial\" to Fighter characters for 1 turn", + sailor: "Reduces Paralysis for 2 turns for himself", + specialName: "Gum-Gum Gigant Axe - Sweets", + }, + 1464: {//White Day Chopper + captain: "Protects from defeat as long as HP is above 50%", + captainNotes: "#{zombie}", + special: "Recovers 6x character's RCV in HP and reduces Paralysis duration by 2 turns", + sailor: "Boosts amount healed from [RCV] orbs by 100 each", + specialName: "Devoted Healing - \"Instant Recovery\"", + }, + 1465: {//White Day Chopper + captain: "Boosts ATK and RCV of all characters by 1.25x, protects from defeat as long as HP is above 50%", + captainNotes: "#{zombie}", + special: "Recovers 6x character's RCV in HP and reduces Paralysis duration by 2 turns", + sailor: "Boosts amount healed from [RCV] orbs by 100 each", + specialName: "Devoted Healing - \"Instant Recovery\"", + }, + 1466: {//White Day Cavendish + captain: "Boosts ATK of [QCK] and [PSY] characters by 2x", + special: "Reduces the defense of all enemies by 100% for 1 turn and changes own orb into [PSY] and friend captain's orb into [STR]", + specialName: "Rosy Pleasure", + }, + 1467: {//White Day Cavendish + captain: "Boosts ATK of [QCK] and [PSY] characters by 2.25x and their RCV by 1.3x", + special: "Reduces the defense of all enemies by 100% for 1 turn and changes own orb into [PSY] and friend captain's orb into [STR]", + specialName: "Rosy Pleasure", + }, + 1468: {//Fortnight Sentomaru + captain: "Boosts ATK of [STR] characters by 1.75x and the HP of Powerhouse characters by 1.2x", + captainNotes: "Captain ability stacks, so a [STR] Powerhouse character benefits from both parts", + special: "Delays all enemies for 1 turn. Changes own orb into Matching orb", + specialName: "Warning of the New World", + }, + 1469: {//Fortnight Sentomaru Evolved + captain: "Boosts ATK of [STR] characters by 2x and the HP of Powerhouse characters by 1.25x", + captainNotes: "Captain ability stacks, so a [STR] Powerhouse character benefits from both parts", + special: "Delays all enemies for 1 turn. Changes own orb into Matching orb", + specialName: "Warning of the New World", + }, + 1470: {//Lip Service Doughty + captain: "Boosts ATK of Slasher and Powerhouse characters by 1.5x, but boost his OWN ATK by 3x", + captainNotes: "Captain ability does not stack with itself (Will not boost another Doughty by 3x)", + special: "Deals 8x character's ATK as [STR] damage to one enemy. Changes captain orb into [RCV]", + specialName: "Meat Grinder Blade", + }, + 1471: {//Albion + captain: "Boosts ATK of Slasher and Driven characters proportionally to the crew's current HP", + captainNotes: "#{captainProportional : lower : 1 + 1 * (1 - (remaining HP) / (total HP)) : 1 : 2}", + special: "Reduces crew's HP by 90%, deals 1x the removed HP as damage to all enemies.", + specialName: "Deep Claw Stab", + }, + 1472: {//Shirahoshi + captain: "Boosts ATK of all characters by 2.25x, but boosts her OWN attack by 1.125x, recovers 5x character's RCV in HP at the end of each turn and if you don't attack with her, reduces damage received by 10% for that turn.", + special: [ + { + "description": "Changes adjacent orbs, including [BLOCK] orbs, into [RAINBOW] orbs, recovers 9x character's RCV in HP.", + "cooldown": [ 13, 9 ], + }, + { + "description": "Changes all orbs, including [BLOCK] orbs, into [RAINBOW] orbs, recovers 100x character's RCV in HP.", + "cooldown": [ 22, 18 ], + }, + ], + specialNotes: "Rainbow orbs are the beneficial form of [BLOCK] orbs. They can not be shuffled by you or your opponent. They count as beneficial orbs to any character. They do not count as STR orbs for Sakazuki but do act like Matching orbs for Black Clad Ace or Fujitora captain abilities.
    #{stages}", + sailor: "Changes all orbs into [RAINBOW] orbs at the start of the fight.", + specialName: "Tears of Courage", + }, + 1473: {//Shirahoshi + captain: "Boosts ATK of all characters by 2.25x, but boosts her OWN attack by 1.125x, recovers 5x character's RCV in HP at the end of each turn and if you don't attack with her, reduces damage received by 10% for that turn.", + special: [ + { + "description": "Changes adjacent orbs, including [BLOCK] orbs into [RAINBOW] orbs, recovers 9x character's RCV in HP.", + "cooldown": [ 13, 9 ], + }, + { + "description": "Changes all orbs, including [BLOCK] orbs into [RAINBOW] orbs, recovers 100x character's RCV in HP.", + "cooldown": [ 22, 18 ], + }, + ], + specialNotes: "Rainbow orbs are the benefittial form of [BLOCK] orbs. They can not be shuffled or swapped by you or your opponent. They count as benefittial orbs to any character. They do not count as STR orbs for Sakazuki but do act like Matching orbs for Black Clad Ace or Fujitora captain abilities.
    #{stages}", + sailor: "Changes all orbs into [RAINBOW] orbs at the start of the fight.", + specialName: "Tears of Courage", + limit: "This character has a limit break path", + }, + 1474: {//King Neptune + captain: "Boosts ATK of all characters by 1.5x and EXP gained by 1.5x", + special: "Locks all orbs for 1 turn. If the HP of the enemy with the highest HP percentage is above 50%, cuts the current HP of all enemies by 20%, otherwise, deals 140x character's ATK in typeless damage to all enemies.", + sailor: "Makes [INT], [PSY], and [TND] orbs \"beneficial\" for this unit", + specialName: "Merman Gujutsu - Ultramarine", + }, + 1475: {//King Neptune + captain: "Boosts ATK of all characters by 2.25x and EXP gained by 1.5x", + captainNotes: "EXP boost does not take effect if he becomes your capatin in the middle of the adventure.", + special: "Locks all orbs for 1 turn. If the HP of the enemy with the highest HP percentage is above 50%, cuts the current HP of all enemies by 20%, otherwise, deals 140x character's ATK in typeless damage to all enemies.", + sailor: "Makes [INT], [PSY], and [TND] orbs \"beneficial\" for this unit", + specialName: "Merman Gujutsu - Ultramarine", + }, + 1476: {//Fukaboshi + captain: "Boosts ATK of Striker characters by 2x", + special: "Delays all enemies by 1 turn, and boosts ATK of Striker and Powerhouse characters by 1.75x for 1 turn", + sailor: "Boosts base HP, RCV and ATK of all characters by 50", + specialName: "Merman Gujutsu - Spear of the Ages", + }, + 1477: {//Fukaboshi + captain: "Boosts ATK of Striker characters by 2.5x and boosts HP of Powerhouse characters by 1.25x", + captainNotes: "This effect does stack for characters that have both classes, so Striker/Powerhouse characters will have 2.5x ATK and 1.25x HP", + special: "Delays all enemies by 1 turn, and boosts ATK of Striker and Powerhouse characters by 1.75x for 1 turn", + sailor: "Boosts base HP, RCV and ATK of all characters by 50", + specialName: "Merman Gujutsu - Spear of the Ages", + limit: "This character has a limit break path", + }, + 1478: {//Caribou + captain: "Boosts ATK of all characters by 1.5x after the 11th hit in the chain, by 1.75x after the 22nd hit, by 2x after the 33th hit, by 3x after the 44th hit", + special: "Deals 15 hits of 12x character's ATK in typeless damage to random enemies and boosts ATK of [QCK] and [INT] characters by 2x for 1 turn", + specialNotes: "#{randomHits : 15}", + sailor: "Completely resists Paralysis on this character", + specialName: "Swamp-Swamp Gatling Gun", + }, + 1479: {//Caribou + captain: "Boosts ATK of all characters by 1.75x after the 11th hit in the chain, by 2.5x after the 22nd hit, by 2.75x after the 33th hit, by 3.5x after the 44th hit", + special: "Deals 15 hits of 12x character's ATK in typeless damage to random enemies and boosts ATK of [QCK] and [INT] characters by 2x for 1 turn", + specialNotes: "#{randomHits : 15}", + sailor: "Completely resists Paralysis on this character", + specialName: "Swamp-Swamp Gatling Gun", + limit: [ + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Aquire Potential 1: Enrage" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Aquire Sailor Ability 1: Makes [RCV] and [TND] orbs \"beneficial\" for this unit" }, + { "description": "Boosts base HP by 70" }, + { "description": "Boosts base HP by 90" }, + { "description": "Boosts base RCV by 40" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Barrier Penetration" }, + ], + potential: [ + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 20", + "Level 2: Boosts base ATK by 40", + "Level 3: Boosts base ATK by 60", + "Level 4: Boosts base ATK by 80", + "Level 5: Boosts base ATK by 100" + ] + }, + { + "Name": "Barrier Penetration", + "description": [ + "Level 1: This character's attack will ignore barriers if HP is above 99%", + "Level 2: This character's attack will ignore barriers if HP is above 99%", + "Level 3: This character's attack will ignore barriers if HP is above 99%", + "Level 4: This character's attack will ignore barriers if HP is above 80%", + "Level 5: This character's attack will ignore barriers if HP is above 50%" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1480: {//Vander Decken IX + captain: "Boosts ATK by 2.5x after scoring 2 Perfects in a row", + special: "Deals 200,000 fixed damage to one enemy that will ignore damage negating abilities and barriers, reduces Bind and Silence duration by 2 turns", + specialNotes: "#{ignoreBarrier}
    #{silence}", + sailor: "Restores his own special by 1 turn when it is rewinded and reduces Silence for 3 turns for himself", + sailorNotes: "#{rewind : 1}
    #{silence}", + specialName: "Stalking Rose Axe", + }, + 1481: {//Vander Decken IX + captain: "Boosts ATK by 2.5x after the 2nd Perfect in a row and by 3.5x after the 5th Perfect in a row.", + special: "Deals 200,000 fixed damage to one enemy that will ignore damage negating abilities and barriers, reduces Bind and Silence duration by 2 turns", + specialNotes: "#{ignoreBarrier}
    #{silence}", + sailor: "Restores his own special by 1 turn when it is rewinded and reduces Silence for 3 turns for himself", + sailorNotes: "#{rewind : 1}
    #{silence}", + specialName: "Stalking Rose Axe", + }, + 1482: {//Madame Shyarly + captain: "Boosts ATK of INT characters by 2x and their RCV by 1.2x", + special: "Randomizes all non-matching orbs, switches orbs between slots twice, and if enemies have a barrier at the time the special was activated, boosts ATK of all characters by 1.75x, 1.25x otherwise.", + sailor: "[INT] characters will deal an extra 1.1x to non [PSY] enemies", + specialName: "Foretold Catastrophe", + }, + 1483: {//Madame Shyarly + captain: "Boosts ATK of INT characters by 2.5x and their RCV by 1.2x", + special: "Randomizes all non-matching orbs, switches orbs between slots twice, and if enemies have a barrier at the time the special was activated, boosts ATK of all characters by 1.75x, 1.25x otherwise.", + sailor: "[INT] characters will deal an extra 1.1x to non [PSY] enemies", + specialName: "Foretold Catastrophe", + }, + 1484: {//Wild Sanji + captain: "Boosts ATK by 2.5x after scoring 3 Perfects in a row", + special: "Locks the chain multiplier at 2.5x for 1 turn, reduces Bind duration by 5 turns", + sailor: "Changes all orbs into [RCV] orbs at the start of the fight.", + specialName: "Wild Shot", + }, + 1485: {//Wild Sanji + captain: "Boosts HP and RCV of all characters by 1.2x and boosts ATK by 3.25x after scoring 3 Perfects in a row", + special: "Locks the chain multiplier at 2.5x for 1 turn, reduces Bind duration by 5 turns", + sailor: "Changes all orbs into [RCV] orbs at the start of the fight.", + specialName: "Wild Shot", + }, + 1486: {//Coliseum Ideo + captain: "Boosts ATK of Fighter characters by 2.5x if they have a matching orb.", + special: "Increases damage received by 2x for 2 turns, deals 15x character's ATK in [DEX] damage to one enemy, amplifies the effect of orbs for Fighter characters by 2x for 1 turn", + specialNotes: "#{orb : 2x}", + specialName: "Destruction Cannon: Hidden Bullet", + }, + 1487: {//Coliseum Ideo + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of Fighter characters by 3x if they have a matching orb.", + special: "Increases damage received by 2x for 2 turns, deals 15x character's ATK in [DEX] damage to one enemy, amplifies the effect of orbs for Fighter characters by 2x for 1 turn", + specialNotes: "#{orb : 2x}", + specialName: "Destruction Cannon: Hidden Bullet", + }, + 1488: {//Coliseum Don Krieg + captain: "Boosts ATK of Driven characters by 1.5x, reduces damage received by 20%", + special: "Deals 20x character's ATK in STR damage to one enemy and removes any Orb Rate Up and Orb Rate Down Buffs", + specialName: "Great Battle Spear", + }, + 1489: {//Coliseum Don Krieg + captain: "Boosts ATK of Driven characters by 2x, reduces damage received by 20%", + special: "Deals 20x character's ATK in STR damage to one enemy and removes any Orb Rate Up and Orb Rate Down Buffs", + specialName: "Great Battle Spear", + }, + 1490: {//Coliseum Mr. 5 + captain: "Boosts ATK by 1.75x following a chain of Good > Good > Great hits", + special: "Changes orbs on the top row to [BOMB], reduces Bind duration by 2 turns, and reduces the defense of all enemies by 50% for one turn.", + specialName: "Explosion Blocking Escape", + }, + 1491: {//Coliseum Mr. 5 + captain: "Boosts ATK by 2x following a chain of Good > Good > Great hits", + special: "Changes orbs on the top row to [BOMB], reduces Bind duration by 2 turns, and reduces the defense of all enemies by 50% for one turn.", + specialName: "Explosion Blocking Escape", + }, + 1492: {//6+ Sabo + captain: "Boosts HP and RCV of all characters by 1.2x, boosts ATK of Free Spirit characters by 2.75x", + captainNotes: "HP and RCV boost are not known yet, but are assumed to be for anyone and is a 1.2x boost for both in the calculator.", + special: [ + { + "description": "Boosts ATK of Free Spirit characters by 1.5x for 1 turn. If during that turn you score 5 Perfect hits, boosts ATK of Free Spirit characters by 2x in the following turn.", + "cooldown": [ 18, 12 ], + }, + { + "description": "Boosts ATK of Free Spirit characters by 1.75x for 1 turn. If during that turn you score 4 Perfect hits, boosts ATK of Free Spirit characters by 2x in the following turn.", + "cooldown": [ 23, 17 ], + }, + ], + specialNotes: "#{stages}", + specialName: "Reborn - Fire", + }, + 1493: {//STR Fishman Outlaw + captain: "Boosts ATK of [STR] characters by 1.5x", + special: "Deals 5 hits of random typeless damage to random enemies", + specialNotes: "#{randomHits : 5}", + specialName: "Random Light Blows", + }, + 1494: {//QCK Fishman Outlaw + captain: "Boosts ATK of [QCK] characters by 1.5x", + special: "Locks captain's orb for 1 turn", + specialName: "Captain Slot Hold: Light", + }, + 1495: {//DEX Fishman Outlaw + captain: "Boosts ATK of [DEX] characters by 1.5x", + special: "Reduces Silence duration by 1 turn", + specialNotes: "#{silence}", + specialName: "Special Seal Recovery: Light", + }, + 1496: {//INT Fishman Outlaw + captain: "Boosts ATK of Powerhouse characters by 1.5x", + special: "Reduces Despair duration by 2 turns", + specialName: "Captain Soul Recovery", + }, + 1497: {//PSY Fishman Outlaw + captain: "Boosts ATK of Shooter characters by 1.5x", + special: "Boosts own ATK by 1.5x for 1 turn", + specialName: "Light Attack Boost", + }, + 1498: {//STR Fishman Guard + captain: "Boosts ATK, HP and RCV of [STR] characters by 1.2x", + special: "Changes Captain's orb into [STR]", + specialName: "Captain Slot Change - [STR]", + }, + 1499: {//QCK Fishman Guard + captain: "Boosts ATK, HP and RCV of [QCK] characters by 1.2x", + special: "Changes Captain's [BLOCK] orbs into Matching orbs", + specialName: "Captain [BLOCK] Slot Change - Matching", + }, + 1500: {//DEX Fishman Guard + captain: "Boosts ATK, HP and RCV of [DEX] characters by 1.2x", + special: "Recovers 2000 HP", + specialName: "First Aid", + }, + 1501: {//Caribou + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of characters with cost 15 or less by 2x", + special: "Reduces crew's current HP by 50%, boosts ATK of all characters by 1.3x for 1 turn", + specialName: "Conviction of God's Will", + }, + 1502: {//Coribou + captain: "Reduces damage received from [PSY] and [INT] enemies by 30%", + special: "For Driven characters, randomizes non-matching orbs", + specialName: "Confession Burial", + }, + 1503: {//Hammond + captain: "Boosts ATK of Powerhouse characters proportionally to the crew's current HP", + captainNotes: "#{captainProportional : lower : ??? + ??? * (1 - (remaining HP) / (total HP)) : ??? : 2.25}", + special: "Changes own orb into [QCK] and changes adjacent orbs into [EMPTY] orbs", + specialName: "Absurd Invitation", + }, + 1504: {//Vander Decken IX + captain: "Boosts ATK of Driven characters by 2x. After scoring 3 Perfects in a row, boosts ATK of Driven characters by 2.4x instead.", + special: "Changes the orbs in the middle row into [EMPTY] orbs and deals 20x character's ATK as [DEX] damage to all enemies at the end of the turn for 2 turns", + specialName: "Inescapable Pursuit", + }, + 1505: {//Hody Jones + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of Powerhouse characters by 2.25x if HP is below 30% at the start of the turn", + special: "Deals 15x character's ATK in [STR] damage to all enemies that will ignore damage negating abilities and barriers, makes Perfects harder to hit for 1 turn, reduces crew's current HP by 90%, boosts own ATK by 2.25x for 1 turn.", + specialName: "Shark Arrows", + }, + 1506: {//Hody Jones + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of Powerhouse characters by 2.5x if HP is below 30% at the start of the turn, 2.25x otherwise", + special: "Deals 15x character's ATK in [STR] damage to all enemies that will ignore damage negating abilities and barriers, makes Perfects harder to hit for 1 turn, reduces crew's current HP by 90%, boosts own ATK by 2.25x for 1 turn.", + specialName: "Shark Arrows", + }, + 1507: {//White Day Sanji + captain: "Boosts ATK of Fighter and Powerhouse characters by 1.3x", + captainNotes: "Boosts stack, so a Fighter/Powerhouse character gets 1.69x ATK", + special: "Deals 15x character's ATK in [QCK] damage to one enemy, boosts ATK of Fighter characters by 1.75x for 1 turn", + sailor: "Boosts base ATK of all characters by 15", + specialName: "Diable Jambe - Concassé Baked", + }, + 1508: {//White Day Sanji + captain: "Boosts ATK of Fighter and Powerhouse characters by 1.5x. Recovers 2x character's RCV in HP at the end of each turn", + captainNotes: "Boosts stack, so a Fighter/Powerhouse character gets 2.25x ATK", + special: "Deals 15x character's ATK in [QCK] damage to one enemy, boosts ATK of Fighter characters by 1.75x for 1 turn", + sailor: "Boosts base ATK of all characters by 15", + specialName: "Diable Jambe - Concassé Baked", + }, + 1509: {//Haruta + captain: "Reduces cooldown of Slasher and Cerebral specials by 1 turn at the start of the fight. Boosts ATK of [INT] characters by 2x.", + special: "Deals 12x character's ATK in INT damage to one enemy and reduces damage received from PSY enemies by 80%.", + specialName: "Honorable Blade", + sailor: "Reduces Silence duration against this unit by 2 turns", + sailorNotes: "#{silence}", + }, + 1510: {//Speed Jiru + captain: "Boosts ATK of Driven and Striker characters by 2x", + special: "Deals 12,500 fixed damage to one enemy", + specialName: "Acceleration Lance", + sailor: "When HP is above 70% at the start of the turn, boosts ATK of Striker characters by 20", + }, + 1511: {//Atmos + captain: "Boosts ATK of PSY characters by 2x", + special: "Reduces Despair duration by 3 turns, boosts own ATK by 1.5x for 1 turn", + specialName: "Buffalo Roar", + sailor: "Boosts base ATK of Powerhouse characters by 20 if your captain is a Powerhouse character", + }, + 1512: {//Kingdew + captain: "Boosts ATK of Fighter and Powerhouse characters by 2x", + special: "Removes Poison, boosts ATK of Powerhouse characters by 1.5x for 1 turn if HP is below 30% when the special is activated", + specialName: "Enlightened Spirit", + sailor: "Makes [RCV] orbs \"beneficial\" for this unit if your captain is a Powerhouse character", + }, + 1513: {//Anniversary Sanji + captain: "Boosts ATK of Fighter characters by 1.75x and RCV of Powerhouse characters by 1.2x", + special: "Randomizes all orbs, including [BLOCK] orbs, reduces Special Cooldown of 1 character by 1 turn", + specialName: "Unfamiliar Escort", + }, + 1514: {//Anniversary Sanji + captain: "Boosts ATK of Fighter characters by 2.5x and RCV of Powerhouse characters by 1.2x", + special: "Randomizes all orbs, including [BLOCK] orbs, reduces Special Cooldown of 1 character by 1 turn", + specialName: "Unfamiliar Escort", + }, + 1515: {//White Day Brook + captain: "Boosts ATK of [STR] and [QCK] characters by 1.5x", + special: "Cuts the current HP of each enemy by 10% and makes [RCV] orbs \"beneficial\" for all characters for 1 turn", + specialName: "Three-Verse Humming: Arrow-Notch Slash - Hail", + sailor: "Makes [RCV] orbs \"beneficial\" for this unit", + }, + 1516: {//White Day Brook + captain: "Boosts ATK of [STR] and [QCK] characters by 2x, recovers 2x character's RCV in HP at the end of each turn", + special: "Cuts the current HP of each enemy by 10% and makes [RCV] orbs \"beneficial\" for all characters for 1 turn", + specialName: "Three-Verse Humming: Arrow-Notch Slash - Hail", + sailor: "Makes [RCV] orbs \"beneficial\" for this unit", + }, + 1517: {//Raid Bellamy + captain: "Boosts ATK of Driven characters by 2x", + special: "Cuts the current HP of one enemy by 10%, makes [PSY] and [INT] orbs \"beneficial\" for 1 turn and amplifies the effect of orbs by 1.75x for 1 turn", + specialName: "Spring Hopper - Bullet", + }, + 1518: {//Raid Bellamy + captain: "Boosts ATK of Driven characters by 2.5x", + special: "Cuts the current HP of one enemy by 10%, makes [PSY] and [INT] orbs \"beneficial\" for 1 turn and amplifies the effect of orbs by 1.75x for 1 turn", + specialName: "Spring Hopper - Bullet", + }, + 1519: {//Dadan + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight. Boosts ATK of Slasher characters by 1.5x", + special: "Cuts the current HP of one enemy by 10%, if HP is full at the time the special was activated, changes top row orbs into matching orbs", + specialName: "Break by the Fireplace", + }, + 1520: {//Dadan + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight. Boosts ATK of Slasher characters by 2x", + special: "Cuts the current HP of one enemy by 10%, if HP is full at the time the special was activated, changes top row orbs into matching orbs", + specialName: "Break by the Fireplace", + }, + 1521: {//Dogra + captain: "Boosts ATK of [QCK] and Slasher characters by 1.2x", + captainNotes: "The bonus is cumulative. [QCK] Slasher characters get a 1.44x bonus.", + special: "Reduces Despair duration by 1 turn, recovers 1000 HP at the end of each turn for 2 turns", + specialName: "Affectionate Circumstances", + }, + 1522: {//Ace + captain: "Boosts ATK of [DEX] characters by 1.75x and their HP by 1.2x", + special: "Removes blindness, boosts own ATK by 1.75x for 1 turn", + specialName: "Demon's Temper", + }, + 1523: {//Spring Chopper + captain: "Boosts ATK of [PSY] characters by 1.75x and recovers 1,000 HP at end of each turn", + special: "Changes top row orbs into matching orbs, changes any other [BLOCK] or Badly Matching orbs into [G] orbs", + specialName: "The Life Risked for the 'Sakura' Miracle", + sailor: "Boosts amount healed from [RCV] orbs by 124 each", + }, + 1524: {//Spring Chopper + captain: "Boosts ATK of [PSY] characters by 2.25x and recovers 1,224 HP at end of each turn", + special: "Changes top row orbs into matching orbs, changes any other [BLOCK] or Badly Matching orbs into [G] orbs", + specialName: "The Life Risked for the 'Sakura' Miracle", + sailor: "Boosts amount healed from [RCV] orbs by 124 each", + }, + 1525: {//Sulieman + captain: "Boosts ATK of Slasher characters by 3.25x, reduces his own ATK multiplier by 0.0625x at the end of each turn until it is 2x", + special: "Deals 3 hits of random typeless damage to random enemies, delays all enemies for 1 turn, boosts ATK against delayed enemies by 1.3x for 2 turns", + specialNotes: "#{randomHits : 3}
    #{random : 50,000 : 150,000 : per hit}", + specialName: "Sorrowful Execution", + }, + 1526: {//Arlong + captain: "Boosts ATK of [INT] characters by 1.75x", + special: [ + { + "description": "Reduces Special Cooldown of your top row by 1 turn, boosts ATK of the characters in the top row by 1.5x for 1 turn", + "cooldown": [ 16, 7 ], + }, + { + "description": "Reduces Special Cooldown of your top row by 1 turn, boosts ATK of the characters in the top row by 1.75x for 1 turn", + "cooldown": [ 21, 12 ], + }, + ], + specialNotes: "#{stages}", + specialName: "Just 'Water Play'", + }, + 1527: {//Arlong + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight. Boosts ATK of [INT] characters by 2x", + special: [ + { + "description": "Reduces Special Cooldown of your top row by 1 turn, boosts ATK of the characters in the top row by 1.5x for 1 turn", + "cooldown": [ 16, 7 ], + }, + { + "description": "Reduces Special Cooldown of your top row by 1 turn, boosts ATK of the characters in the top row by 1.75x for 1 turn", + "cooldown": [ 21, 12 ], + }, + ], + specialNotes: "#{stages}", + specialName: "Just 'Water Play'", + }, + 1528: {//Blenheim + captain: "Boosts ATK of Powerhouse characters by 2.25x", + special: "Reduces Despair duration by 2 turns, makes STR, DEX, and QCK orbs \"beneficial\" to Powerhouse characters for 1 turn if HP is below 30% at the start of the turn", + sailor: "Makes [TND] orbs \"beneficial\" for this unit", + specialName: "Australian Army Aid Blade", + }, + 1529: {//Cavendish + captain: "Boosts ATK of all characters by 1.5x, but boosts his OWN attack by 3x", + special: "For Slasher characters, if HP is above 50% at the time the special was activated, amplifies the effects of orbs by 2.25x for 1 turn, 2x otherwise", + sailor: "Reduces ATK of all characters by .5x if your captain is a [STR] or [QCK] character", + specialName: "Blue Bird Sword", + }, + 1530: {//Cavendish + captain: "Boosts ATK of all characters by 1.75x, but boosts his OWN attack by 3.5x", + special: "For Slasher characters, if HP is above 50% at the time the special was activated, amplifies the effects of orbs by 2.25x for 1 turn, 2x otherwise", + sailor: "Reduces ATK of all characters by .5x if your captain is a [STR] or [QCK] character", + specialName: "Blue Bird Sword", + }, + 1531: {//Legend Usopp + captain: "Boosts ATK of all characters by 1.5x if HP is below 50% or by 1.75x if HP is below 30% at the start of the turn. Makes [STR], [DEX], [QCK], [PSY], [INT], [RCV], and [TND] orbs \"beneficial\" to all characters.", + special: [ + { + "description": "Delays all enemies for 3 turns", + "cooldown": [ 13, 10 ], + }, + { + "description": "Delays all enemies for 4 turns, adds 0.2x to Chain multiplier for 4 turns", + "cooldown": [ 18, 15 ], + }, + { + "description": "Delays all enemies for 5 turns, adds 0.3x to Chain multiplier for 4 turns", + "cooldown": [ 24, 21 ], + }, + ], + specialNotes: "#{stages}", + sailor: "Completely resists Blindness", + specialName: "Long-Range Attack: Bagworm", + }, + 1532: {//Legend Usopp + captain: "Boosts ATK of all characters by 1.5x if HP is below 50% or by 1.75x if HP is below 30% at the start of the turn. Makes [STR], [DEX], [QCK], [PSY], [INT], [RCV], and [TND] orbs \"beneficial\" to all characters.", + special: [ + { + "description": "Delays all enemies for 3 turns", + "cooldown": [ 13, 10 ], + }, + { + "description": "Delays all enemies for 4 turns, adds 0.2x to Chain multiplier for 4 turns", + "cooldown": [ 18, 15 ], + }, + { + "description": "Delays all enemies for 5 turns, adds 0.3x to Chain multiplier for 4 turns", + "cooldown": [ 24, 21 ], + }, + ], + specialNotes: "#{stages}", + sailor: "Completely resists Blindness", + specialName: "Long-Range Attack: Bagworm", + limit: [ + { "description": "Boosts base ATK by 15" }, + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Aquire Potential 1: Reduce No Healing duration" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base ATK by 15" }, + { "description": "Aquire Sailor Ability 1: Boosts base HP of Shooter characters by 100" }, + { "description": "Boosts base ATK by 15" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Aquire Potential 2: Critical Hit" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base RCV by 25" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Boosts base HP by 70" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base HP by 80" }, + { "description": "Boosts base RCV by 25" }, + { "description": "Boosts base HP by 100" }, + { "description": "Aquire Potential 3: Barrier Penetration" }, + ], + potential: [ + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: Reduces No Healing duration by 1 turn", + "Level 2: Reduces No Healing duration by 1 turn", + "Level 3: Reduces No Healing duration by 1 turn", + "Level 4: Reduces No Healing duration by 2 turns", + "Level 5: Reduces No Healing duration by 3 turns" + ] + }, + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 30% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 40% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 50% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 50% chance to deal 10% of this character's attack in extra damage" + ] + }, + { + "Name": "Barrier Penetration", + "description": [ + "Level 1: This character's attack will ignore barriers if HP is above 99%", + "Level 2: This character's attack will ignore barriers if HP is above 90%", + "Level 3: This character's attack will ignore barriers if HP is above 70%", + "Level 4: This character's attack will ignore barriers if HP is above 50%", + "Level 5: This character's attack will ignore barriers if HP is above 30%" + ] + }, + ] + }, + 1533: {//Rayleigh + captain: "Boosts ATK of [QCK] characters by 2x and their HP by 1.2x at the start of the chain, by 2.5x after the 4th Perfect in a row.", + special: "Changes all orbs, including [BLOCK] orbs, to [QCK] orbs", + sailor: "Makes [STR], [INT], and [DEX] orbs \"beneficial\" for this unit", + specialName: "The Teacher's Final Ordeal", + }, + 1534: {//Rayleigh + captain: "Boosts ATK of [QCK] characters by 2.5x and their HP by 1.2x at the start of the chain, by 3x after the 4th Perfect in a row.", + special: "Changes all orbs, including [BLOCK] orbs, to [QCK] orbs", + sailor: "Makes [STR], [INT], and [DEX] orbs \"beneficial\" for this unit", + specialName: "The Teacher's Final Ordeal", + }, + 1535: {//Duval + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of [PSY] characters by 2.5x if they have matching orbs", + special: "Reduces damage received by 50% for 1 turn, boosts ATK of PSY characters by 1.75x for 1 turn", + sailor: "Makes [INT] orbs \"beneficial\" for [PSY] characters", + specialName: "Prideful Memories", + }, + 1536: {//Duval + captain: "Reduces cooldown of all specials by 3 turns at the start of the fight, boosts ATK of [PSY] characters by 3x if they have matching orbs", + special: "Reduces damage received by 50% for 1 turn, boosts ATK of PSY characters by 1.75x for 1 turn", + sailor: "Makes [INT] orbs \"beneficial\" for [PSY] characters", + specialName: "Prideful Memories", + }, + 1537: {//Heracles'n + captain: "Boosts ATK of [STR] characters by 2x and boosts HP of Shooter and Striker characters by 1.2x", + special: "Cuts the current HP of each enemy by 20%, changes right column [STR], [QCK], [DEX], [PSY] and [INT] orbs into Matching orbs for Shooter and Striker characters", + sailor: "Boosts base HP of STR characters by 150", + specialName: "Greenstone Threat", + }, + 1538: {//Heracles'n + captain: "Boosts ATK of [STR] characters by 2.5x and boosts HP of Shooter and Striker characters by 1.25x", + special: "Cuts the current HP of each enemy by 20%, changes right column [STR], [QCK], [DEX], [PSY] and [INT] orbs into Matching orbs for Shooter and Striker characters", + sailor: "Boosts base HP of STR characters by 150", + specialName: "Greenstone Threat", + }, + 1539: {//Perona + captain: "Boosts ATK and RCV of characters with cost 20 or less by 1.5x", + special: "Reduces damage received by 90% for 1 turn, reduces the defense of all enemies by 90% for 1 turn, reduces enemy's Threshold Damage Reduction and Percent Damage Reduction duration by 2 turns", + sailor: "Boosts base ATK of INT characters by 50", + specialName: "Negative Hollow: You're All Rotten Imbeciles", + }, + 1540: {//Perona + captain: "Boosts ATK of characters with cost 30 or less by 2.25x and their RCV by 1.5x", + special: "Reduces damage received by 90% for 1 turn, reduces the defense of all enemies by 90% for 1 turn, reduces enemy's Threshold Damage Reduction and Percent Damage Reduction duration by 2 turns", + sailor: "Boosts base ATK of INT characters by 50", + specialName: "Negative Hollow: You're All Rotten Imbeciles", + }, + 1541: {//Elizabeth + captain: "Boosts ATK by 2x following a chain of [STR] > [DEX] > [QCK] attacks no lower than Good", + special: "Recovers 13x character's RCV in HP, adds .5x to Chain multiplier, and reduces the defense of all enemies by 100% for 1 turn", + sailor: "Restores her own special by 2 turns when it is rewinded", + sailorNotes: "#{rewind : 1}", + specialName: "Soft and Gentle Fluffy Kisses", + }, + 1542: {//Elizabeth + captain: "Boosts RCV and HP by 1.2x, boosts ATK by 2.5x following a chain of [STR] > [DEX] > [QCK] attacks no lower than Good", + special: "Recovers 13x character's RCV in HP, adds .5x to Chain multiplier, and reduces the defense of all enemies by 100% for 1 turn", + sailor: "Restores her own special by 2 turns when it is rewinded", + sailorNotes: "#{rewind : 1}", + specialName: "Soft and Gentle Fluffy Kisses", + }, + 1543: {//6+ Usopp + captain: "Boosts ATK of Shooter characters by 1.5x if HP is below 50% or by 1.75x if HP is below 30% at the start of the turn. Makes [STR], [DEX], [QCK], [PSY], [INT], [RCV], and [TND] orbs \"beneficial\" to Shooter characters. At the beginning of each Stage, increases the Attack Timer of all enemies by 1 turn", + captainNotes: "The Attack Timer increase is NOT a delay, so the enemies can still be delayed. Attack Timer increase ignores Debuff Prevention barriers", + special: "Cuts the current HP of each enemy by 10%. If enemies have Delay Prevention, ignores it and Delays all enemies for 1 turn. Otherwise, Delays all enemies for 3 turns", + sailor: "Completely resists Blindness", + specialName: "Green Star, Impact Wolf", + limit: [ + { "description": "Boosts base ATK by 15" }, + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Aquire Potential 1: Reduce No Healing duration" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base ATK by 15" }, + { "description": "Aquire Sailor Ability 1: Boosts base HP of Shooter characters by 100" }, + { "description": "Boosts base ATK by 15" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Aquire Potential 2: Critical Hit" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base RCV by 25" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Boosts base HP by 70" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base HP by 80" }, + { "description": "Boosts base RCV by 25" }, + { "description": "Boosts base HP by 100" }, + { "description": "Aquire Potential 3: Barrier Penetration" }, + ], + potential: [ + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: Reduces No Healing duration by 1 turn", + "Level 2: Reduces No Healing duration by 1 turn", + "Level 3: Reduces No Healing duration by 1 turn", + "Level 4: Reduces No Healing duration by 2 turns", + "Level 5: Reduces No Healing duration by 3 turns" + ] + }, + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 30% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 40% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 50% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 50% chance to deal 10% of this character's attack in extra damage" + ] + }, + { + "Name": "Barrier Penetration", + "description": [ + "Level 1: This character's attack will ignore barriers if HP is above 99%", + "Level 2: This character's attack will ignore barriers if HP is above 90%", + "Level 3: This character's attack will ignore barriers if HP is above 70%", + "Level 4: This character's attack will ignore barriers if HP is above 50%", + "Level 5: This character's attack will ignore barriers if HP is above 30%" + ] + }, + ] + }, + 1544: {//Sakura Koala + captain: "Boosts ATK of Fighter characters by 1.75x and heals for .3x her RCV at the end of the turn each time you hit a Perfect", + special: "Changes Captain orb into matching and boosts ATK of Fighter characters by 1.5x for 1 turn", + specialName: "Bean Paste under the Petal Snow", + }, + 1545: {//Sakura Koala + captain: "Boosts ATK of Fighter characters by 2.25x and heals for .5x her RCV at the end of the turn each time you hit a Perfect", + special: "Changes Captain orb into matching and boosts ATK of Fighter characters by 1.5x for 1 turn", + specialName: "Bean Paste under the Petal Snow", + }, + 1546: {//Soul King Brook + captain: "Boosts ATK of [QCK] characters by 1.5x and boosts HP of Free Spirit characters by 1.2x", + special: "Boosts ATK of Free Spirit characters by 1.5x and makes Badly Matching and [BLOCK] orbs not reduce damage for 1 turn", + specialName: "Dawn of A Big Star", + }, + 1547: {//Soul King Brook + captain: "Boosts ATK of [QCK] characters by 2x and boosts HP of Free Spirit characters by 1.3x", + special: "Boosts ATK of Free Spirit characters by 1.5x and makes Badly Matching and [BLOCK] orbs not reduce damage for 1 turn", + specialName: "Dawn of A Big Star", + }, + 1548: {//Soul King Managers + captain: "Boosts ATK of Driven characters by 1.5x", + special: "Delays all enemies for 1 turn. Adds .2x to Chain multiplier for 1 turn", + specialName: "Former Thief's Box Office", + }, + 1549: {//5+ Robin + captain: "Boosts ATK of [PSY] characters by 2.25x and recovers 3x character's RCV in HP at the end of each turn", + special: "Reduces Bind, Despair and Silence duration by 3 turns, and reduces Special Cooldown of all characters by 1 turn", + specialName: "Mil Fluer: Campo de Flores", + specialNotes: "#{silence}", + }, + 1550: {//5+ Franky + captain: "Boosts ATK of [INT] characters by 2.5x, reduces damage received by 10%", + special: "Deals 35x character's ATK in [INT] damage to all enemies. Changes [TND] and [RCV] orbs on Shooter and Free Spirit characters into Matching Orbs.", + specialName: "Franky's Rocket Launcher", + }, + 1551: {//5+ Brook + captain: "Boosts ATK of Free Spirit characters by 2.5x and recovers 430 HP at end of each turn", + special: "Delays all enemies for 1 turn and locks all orbs for 1 turn", + specialName: "Song of Scratches: Blizzard Slash", + }, + 1552: {//Coliseum Hajrudin + captain: "Boosts ATK of characters with 40 cost by 2.5x", + special: "Deals 300,000 Fixed damage to one enemy, boosts ATK of characters with 40 cost by 1.75x, reduces enemy Barrier duration by 1 turn", + specialName: "Thunder Giant", + }, + 1553: {//Coliseum Hajrudin + captain: "Boosts ATK of characters with 40 cost by 2.75x", + special: "Deals 300,000 Fixed damage to one enemy, boosts ATK of characters with 40 cost by 1.75x, reduces enemy Barrier duration by 1 turn", + specialName: "Thunder Giant", + limit: "This character has a limit break path", + }, + 1554: {//Coliseum Ryuma + captain: "Boosts ATK of [DEX] characters by 2x", + special: "Boosts ATK of [DEX] characters and amplifies the effect of orbs for [DEX] characters by 1.35x for 1 turn", + specialName: "Pure Body and Soul", + }, + 1555: {//Coliseum Ryuma + captain: "Boosts ATK of [DEX] characters by 2.25x, recovers 2x character's RCV in HP at the end of each turn", + special: "Boosts ATK of [DEX] characters and amplifies the effect of orbs for [DEX] characters by 1.35x for 1 turn", + specialName: "Pure Body and Soul", + }, + 1556: {//Wadatsumi + captain: "Boosts HP of STR characters by 2x", + special: "If the HP of the enemy with the highest HP percentage is above 3,000,000 HP, boosts own ATK by 2x for 1 turn", + specialName: "Sailboat Sinking Fist", + }, + 1557: {//Zeo + captain: "Boosts ATK of Striker characters by 3x, reduces own ATK multiplier by 0.1x at the end of each turn, reduces crew's current HP by 10% at the end of each turn", + special: "Makes Badly Matching and [BLOCK] orbs not reduce damage for 2 turns", + specialName: "Super Sole Headbutt", + }, + 1558: {//Ikaros + captain: "Boosts ATK of Shooter characters by 3x, reduces own ATK multiplier by 0.1x at the end of each turn, reduces crew's current HP by 10% at the end of each turn", + special: "Cuts the current HP of each enemy by 15%", + specialName: "Stamping Press", + }, + 1559: {//Hyouzou + captain: "Boosts ATK of Slasher characters by 3x, reduces own ATK multiplier by 0.1x at the end of each turn, reduces crew's current HP by 10% at the end of each turn", + special: "Reduces crew's HP by 50%, deals 55x ATK in Typeless damage to all enemies", + specialName: "Disorderly Drunken Frenzy Killing", + }, + 1560: {//Daruma + captain: "Boosts ATK of Fighter characters by 3x, reduces own ATK multiplier by 0.1x at the end of each turn, reduces crew's current HP by 10% at the end of each turn", + special: "Empties all slots including those with [BLOCK] orbs", + specialName: "Daruma Drop", + }, + 1561: {//Dosun + captain: "Boosts ATK of [INT] characters by 3x, reduces own ATK multiplier by 0.1x at the end of each turn, reduces crew's current HP by 10% at the end of each turn", + special: "Boosts ATK of Striker characters by 1.5x for 1 turn, deals 25x character's ATK in [INT] damage to one enemy", + specialName: "Explosive Nail Hammer", + }, + 1562: {//Hody Jones + captain: "Boosts ATK of Powerhouse characters by 3.5x, reduces own ATK multiplier by 0.1x at the end of each turn until it is 1.5x, reduces crew's current HP by 10% at the end of each turn", + special: "Deals 60x character's ATK in [QCK] damage to one enemy, increases damage received by 2x for 2 turns, boosts ATK of Powerhouse characters by 1.75x for 1 turn", + specialName: "Drugs From Heaven", + }, + 1563: {//Elizabello + captain: "Boosts ATK of Fighter and Powerhouse characters by 1.75x at the start of the chain and by 2.1875x after the 5th Perfect in a row", + special: [ + { + "description": "Changes own orb into [STR], deals 10 hits of 3x character's ATK in typeless damage to random enemies", + "cooldown": [ 17, 9 ], + }, + { + "description": "Changes own orb into [STR], deals 10 hits of 15x character's ATK in typeless damage to random enemies and adds .3x to Chain multiplier for 1 turn", + "cooldown": [ 24, 16 ], + }, + ], + specialNotes: "#{stages}", + specialName: "Battle Royale Rush", + sailor: "Boosts own base ATK by 350 if this character is the last in the chain to attack", + }, + 1564: {//Elizabello + captain: "Boosts ATK of Fighter and Powerhouse characters by 2x at the start of the chain and by 3x after the 5th Perfect in a row", + special: [ + { + "description": "Changes own orb into [STR], deals 10 hits of 3x character's ATK in typeless damage to random enemies", + "cooldown": [ 17, 9 ], + }, + { + "description": "Changes own orb into [STR], deals 10 hits of 15x character's ATK in typeless damage to random enemies and adds .3x to Chain multiplier for 1 turn", + "cooldown": [ 24, 16 ], + }, + ], + specialNotes: "#{stages}", + specialName: "Battle Royale Rush", + sailor: "Boosts own base ATK by 350 if this character is the last in the chain to attack", + }, + 1565: {//Dagama + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of all characters by 1.75x", + special: "Reduces Special Cooldown of all characters by 1 turn and reduces crew's current HP by 10%", + specialName: "War of Mislead Order", + }, + 1566: {//Dagama + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of all characters by 2x", + special: "Reduces Special Cooldown of all characters by 1 turn and reduces crew's current HP by 10%", + specialName: "War of Mislead Order", + }, + 1567: {//Kid Boa + captain: "Boosts ATK and RCV of [QCK] characters by 1.5x", + special: "Recovers 13x character's RCV in HP, amplifies the effect of orbs by 1.5x for 3 turns", + specialName: "The Princess' Principle", + }, + 1568: {//Kid Boa + captain: "Boosts ATK and RCV of [QCK] characters by 2x", + special: "Recovers 13x character's RCV in HP, amplifies the effect of orbs by 1.5x for 3 turns", + specialName: "The Princess' Principle", + }, + 1569: {//Anniversary Law + captain: "Boosts ATK of all characters by 2.25x and boosts EXP and amount of Beli recieved by 1.2x", + special: "Randomizes all non-matching orbs, including [BLOCK] orbs and switches orbs between slots three times", + specialName: "ROOM Shambles・Junction", + }, + 1570: {//Inuarashi + captain: "Boosts ATK of Cerebral characters by 2.75x and chain by 1.5x if HP is below 30% at the start of the turn, boosts ATK of Cerebral characters by 2.5x otherwise", + special: "Reduces crew's current HP by 80%, deals 60x character's ATK in STR damage to one enemy. Adds 80x character's ATK as Additional Typeless Damage for 1 turn", + specialNotes: "#{additionalDamage : 80x}", + specialName: "King Sword Shine", + }, + 1571: {//Inuarashi + captain: "Boosts ATK of Cerebral characters by 2.75x and chain by 1.5x if HP is below 30% at the start of the turn, boosts ATK of Cerebral characters by 2.5x otherwise", + special: "Reduces crew's current HP by 80%, deals 60x character's ATK in STR damage to one enemy. Adds 80x character's ATK as Additional Typeless Damage for 1 turn", + specialNotes: "#{additionalDamage : 80x}", + specialName: "King Sword Shine", + }, + 1572: {//Wanda + captain: "Boosts ATK of Cerebral characters by 2x, and their RCV by 1.2x", + special: "Randomly changes all orbs, including [BLOCK] orbs into [STR], [DEX], [QCK], [INT], or [PSY] orbs, boosts ATK of Cerebral characters by 1.75x for 3 turns", + sailor: "Reduces Paralysis duration by 1 turn", + specialName: "Ruler's Aide Flight", + }, + 1573: {//Wanda + captain: "Boosts ATK of Cerebral characters by 2.5x, and their RCV by 1.2x", + special: "Randomly changes all orbs, including [BLOCK] orbs into [STR], [DEX], [QCK], [INT], or [PSY] orbs, boosts ATK of Cerebral characters by 1.75x for 3 turns", + sailor: "Reduces Paralysis duration by 1 turn", + specialName: "Ruler's Aide Flight", + }, + 1574: {//Sicilian + captain: "Boosts ATK of [INT] characters by 2.25x", + special: "Delays all enemies for 1 turn, deals 25x character's ATK [INT] damage to all enemies, and changes [STR], [DEX], [QCK], [INT], or [PSY] orbs on Cerebral characters into Matching orbs.", + sailor: "When HP is below 30% at the start of the turn, boosts own ATK by 200", + specialName: "Dash - Dive - Destroy", + }, + 1575: {//Sicilian + captain: "Boosts ATK of [INT] characters by 2.5x and their HP by 1.25x", + special: "Delays all enemies for 1 turn, deals 25x character's ATK [INT] damage to all enemies, and changes [STR], [DEX], [QCK], [INT], or [PSY] orbs on Cerebral characters into Matching orbs.", + sailor: "When HP is below 30% at the start of the turn, boosts own ATK by 200", + specialName: "Dash - Dive - Destroy", + }, + 1576: {//Kin'emon + captain: "Boosts ATK by 2.5x following a chain of Good > Great > Perfect hits", + special: "Deals 60x character's ATK in typeless damage to all enemies, and changes all orbs on all characters into Kinemon's orb.", + specialNotes: "Upon activating the special, all orbs will be changed to the orb Kinemon has, including [RAINBOW] and [BLOCK] orbs. This will not override other [BLOCK] orbs.", + sailor: "Makes [STR] and [QCK] orbs \"beneficial\" for this unit", + specialName: "Flaming Flash", + }, + 1577: {//Kin'emon + captain: "Recovers 3x character's RCV in HP at the end of each turn. Boosts ATK by 3.5x following a chain of Good > Great > Perfect hits", + special: "Deals 60x character's ATK in typeless damage to all enemies, and changes all orbs on all characters into Kinemon's orb.", + specialNotes: "Upon activating the special, all orbs will be changed to the orb Kinemon has, including [RAINBOW] and [BLOCK] orbs. This will not override other [BLOCK] orbs.", + sailor: "Makes [STR] and [QCK] orbs \"beneficial\" for this unit", + specialName: "Flaming Flash", + }, + 1578: {//Momonosuke + captain: "Protects from defeat as long as HP is above 50%", + special: [ + { + "description": "Adds .2x to Chain multiplier for 1 turn", + "cooldown": [ 8, 3 ], + }, + { + "description": "Switches orbs between slots once, and adds .3x to Chain multiplier for 1 turn", + "cooldown": [ 11, 6 ], + }, + { + "description": "Switches orbs between slots once, and adds .5x to Chain multiplier for 1 turn", + "cooldown": [ 14, 9 ], + }, + ], + specialNotes: "#{stages}", + sailor: "Makes [STR], [QCK], [DEX], and [INT] orbs \"beneficial\" for this unit", + specialName: "Miraculous Flying Dragon", + }, + 1579: {//Momonosuke + captain: "Boosts ATK, HP and RCV of all characters by 1.25x, protects from defeat as long as HP is above 50%", + special: [ + { + "description": "Adds .2x to Chain multiplier for 1 turn", + "cooldown": [ 8, 3 ], + }, + { + "description": "Switches orbs between slots once, and adds .3x to Chain multiplier for 1 turn", + "cooldown": [ 11, 6 ], + }, + { + "description": "Switches orbs between slots once, and adds .5x to Chain multiplier for 1 turn", + "cooldown": [ 14, 9 ], + }, + ], + specialNotes: "#{stages}", + sailor: "Makes [STR], [QCK], [DEX], and [INT] orbs \"beneficial\" for this unit", + specialName: "Miraculous Flying Dragon", + }, + 1580: {//Fortnight Law + captain: "Boosts ATK of Free Spirit characters by 1.5x and boosts RCV of DEX characters by 1.2x", + special: "Changes orbs in right column to [DEX], [PSY], [INT] from top to bottom, switches orbs between slots twice, amplifies the effect of orbs by 1.5x for 1 turn", + specialName: "ROOM Tact", + }, + 1581: {//Fortnight Law + captain: "Boosts ATK of Free Spirit characters by 2x and boosts RCV of DEX characters by 1.5x", + special: "Changes orbs in right column to [DEX], [PSY], [INT] from top to bottom, switches orbs between slots twice, amplifies the effect of orbs by 1.5x for 1 turn", + specialName: "ROOM Tact", + }, + 1582: {//Fortnight Monet + captain: "Boosts ATK and RCV of Cerebral characters by 1.2x", + special: "Recovers 10x character's RCV in HP. Boosts ATK and RCV of Cerebral characters by 1.5x for 1 turn", + specialName: "Observing within the Snow Storm", + }, + 1583: {//Coliseum Orlumbus + captain: "Boosts ATK of Striker characters by 2x", + special: "Locks all orbs for 1 turn. If there are 4 enemies or more on the stage, amplifies the effect of orbs for Striker characters by 2x for 1 turn, otherwise amplifies the effect of orbs for Striker characters by 1.5x for 1 turn", + specialName: "Admiral Hug", + }, + 1584: {//Coliseum Orlumbus + captain: "Boosts ATK of Striker characters by 3x if HP is below 30% at the start of the turn, by 2.5x otherwise", + special: "Locks all orbs for 1 turn. If there are 4 enemies or more on the stage, amplifies the effect of orbs for Striker characters by 2x for 1 turn, otherwise amplifies the effect of orbs for Striker characters by 1.5x for 1 turn", + specialName: "Admiral Hug", + limit: [ + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 40" }, + { "description": "Aquire Potential 1: [INT] Damage Reduction" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Aquire Sailor Ability 1: Makes [TND] orbs \"beneficial\" for this unit" }, + { "description": "Boosts base HP by 60" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Aquire Potential 2: Critical Hit" }, + ], + potential: [ + { + "Name": "[INT] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [INT] characters by 1%", + "Level 2: Reduce damage taken from [INT] characters by ?%", + "Level 3: Reduce damage taken from [INT] characters by ?%", + "Level 4: Reduce damage taken from [INT] characters by ?%", + "Level 5: Reduce damage taken from [INT] characters by ?%" + ] + }, + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a ??% chance to deal ?% of this character's attack in extra damage" + ] + }, + ] + }, + 1585: {//Coliseum Helmeppo + captain: "Boosts ATK and RCV of Slasher and Driven characters by 1.5x", + special: "If HP is below 5,000 when the special is activated, boosts ATK of Driven and Slasher characters by 1.75x for 1 turn and recovers 10x character's RCV in HP", + specialName: "Firey Morale", + }, + 1586: {//Coliseum Helmeppo + captain: "Boosts ATK of Slasher and Driven characters by 2x and their RCV by 1.5x", + special: "If HP is below 5,000 when the special is activated, boosts ATK of Driven and Slasher characters by 1.75x for 1 turn and recovers 10x character's RCV in HP", + specialName: "Firey Morale", + }, + 1587: {//Legend Sanji + captain: "Boosts ATK of all characters by 2.5x and their HP by 1.3x
    Action: Sanji Sky Walks into the air for 1 turn, preventing all debuffs to himself. This does not remove the his own Captain boost while he is unable to attack. (Including, but not limited to, Bind, Despair, and Silence) Next turn, boosts own ATK by 6.25x instead", + captainNotes: "Multiple Sanjis can Sky Walk at the same time. Even while Sky Walking, will still boost all characters by 2.5x. Sky Walk is not a type boost, and will stack with other boosts", + special: "Deals 100,000 fixed damage to all enemies. Changes [BLOCK], [TND], adjacent orbs, and own orb into Matching orbs. Boosts own attack by 2x for 1 turn", + sailor: "Makes [RCV] orbs \"beneficial\" for all characters", + specialName: "Hell Memories", + }, + 1588: {//Legend Sanji + captain: "Boosts ATK of all characters by 2.5x and their HP by 1.3x
    Action: Sanji Sky Walks into the air for 1 turn, preventing all debuffs to himself. This does not remove the his own Captain boost while he is unable to attack. (Including, but not limited to, Bind, Despair, and Silence) Next turn, boosts own ATK by 6.25x instead", + captainNotes: "Multiple Sanjis can Sky Walk at the same time. Even while Sky Walking, will still boost all characters by 2.5x. Sky Walk is not a type boost, and will stack with other boosts", + special: "Deals 100,000 fixed damage to all enemies. Changes [BLOCK], [TND], adjacent orbs, and own orb into Matching orbs. Boosts own attack by 2x for 1 turn", + sailor: "Makes [RCV] orbs \"beneficial\" for all characters", + specialName: "Hell Memories", + }, + 1589: {//Anniversary Shanks + captain: "Boosts Chain Multiplier by 3x", + special: "Recovers 50% of crew's MAX HP, changes bottom row orbs into matching orbs", + specialName: "Sharing a Cup Filled with Emotions", + }, + 1590: {//Anniversary Shanks + captain: "Boosts Chain Multiplier by 3.5x, Boosts HP and RCV of all characters by 1.2x", + special: "Recovers 50% of crew's MAX HP, changes bottom row orbs into matching orbs", + specialName: "Sharing a Cup Filled with Emotions", + }, + 1591: {//Anniversary Boa + captain: "Boosts ATK and RCV of Fighter and Free Spirit characters by 1.5x", + special: "Recovers 3,000 HP and boosts ATK of Free Spirit and Fighter characters by 1.75x for 1 turn", + specialName: "Immoral Gaze", + }, + 1592: {//Anniversary Boa + captain: "Boosts ATK of Fighter and Free Spirit characters by 2.25x and their RCV by 1.75x", + special: "Recovers 3,000 HP and boosts ATK of Free Spirit and Fighter characters by 1.75x for 1 turn", + specialName: "Immoral Gaze", + }, + 1593: {//Gear 4 Luffy + captain: "Boosts ATK of Fighter characters by 2.5x. If you use \"King Kong Gun\" THIS LUFFY boosts ATK of Fighter characters by 4x instead for 3 turns and reduces damage taken by 56% for 3 turns.", + special: [ + { + "description": "Deals 100x character's ATK in typeless damage to one enemy, and makes [STR], [DEX], [PSY], [INT], [TND], and [RCV] orbs \"beneficial\" for Fighter characters for 1 turn. After 3 turns, Binds and Despairs himself for 7 turns.", + "cooldown": [ 13, 8 ], + }, + { + "description": "Deals 200x character's ATK in typeless damage to one enemy, and makes [STR], [DEX], [PSY], [INT], [TND], and [RCV] orbs \"beneficial\" for Fighter and Free Spirit characters for 3 turns. After 3 turns, Binds and Despairs himself for 7 turns.", + "cooldown": [ 18, 13 ], + }, + ], + specialNotes: "#{stages}", + sailor: "Completely resists Paralysis on this character", + specialName: "King Kong Gun", + }, + 1594: {//Fujitora + captain: "Cuts the current HP of each enemy by 10% at the end of each turn", + special: "Deals 50x character's ATK in [PSY] damage to all enemies that will ignore damage negating abilities and barriers, changes adjacent orbs into Matching Orbs, amplifies the effect of orbs for Powerhouse characters by 2x for 1 turn", + specialNotes: "#{ignoreBarrier}", + specialName: "Gravity Blade: Fierce Tiger", + }, + 1595: {//Fujitora + captain: "Boosts ATK of Powerhouse characters by 2.25x, and their HP by 1.2x, cuts the current HP of each enemy by 10% at the end of each turn", + special: "Deals 50x character's ATK in [PSY] damage to all enemies that will ignore damage negating abilities and barriers, changes adjacent orbs into Matching Orbs, amplifies the effect of orbs for Powerhouse characters by 2x for 1 turn", + specialNotes: "#{ignoreBarrier}", + specialName: "Gravity Blade: Fierce Tiger", + }, + 1596: {//Shirahoshi + captain: "Boosts ATK and RCV of [INT] characters by 1.5x", + special: "Reduces Bind, Despair and Paralysis duration by 2 turns, reduces damage received by 70% for 1 turn", + specialName: "Great Dinner Buffet", + }, + 1597: {//Shirahoshi + captain: "Boosts ATK and RCV of [INT] characters by 1.75x", + special: "Reduces Bind, Despair and Paralysis duration by 2 turns, reduces damage received by 70% for 1 turn", + specialName: "Great Dinner Buffet", + }, + 1598: {//Ryuboshi + captain: "Boosts HP of Powerhouse characters by 1.5x", + special: "Boosts ATK of all characters by 1.2x and recovers 5x character's RCV in HP at the end of each turn for 3 turns", + specialName: "Musical Scale", + }, + 1599: {//Manboshi + captain: "Boosts ATK of Powerhouse characters by 1.75x", + special: "Reduces the defense of all enemies by 50% for 1 turn. Changes own orb into [QCK]", + specialName: "Happy Dance", + }, + 1600: {//3rd Anniversary Luffy + captain: "Boosts ATK of [PSY] and [INT] characters by 2.5x", + special: "Deals 20x character's ATK in [PSY] damage to one enemy, locks orbs for 1 turn, and amplifies the effect of orbs on [PSY] and [INT] characters by 1.75x for 1 turn", + specialName: "Right Leg Armament: Gum-Gum Battle Axe", + }, + 1601: {//Power Creep Shiryu + captain: "Boosts ATK of Slasher characters by 2x", + special: "Instantly defeats all enemies with HP equal to or below 75x character's ATK, removes Poison and reduces damage received by 50% for 3 turns,", + specialName: "Blood Stained 'Iron Wall'", + sailor: "Boosts own base ATK by 100 if this character is the last in the chain to attack", + }, + 1602: {//Power Creep Shiryu + captain: "Boosts ATK of Slasher characters by 2x at the start of the chain, by 3x after the 3rd Perfect in a row", + special: "Instantly defeats all enemies with HP equal to or below 75x character's ATK, removes Poison and reduces damage received by 50% for 3 turns,", + specialName: "Blood Stained 'Iron Wall'", + sailor: "Boosts own base ATK by 100 if this character is the last in the chain to attack", + }, + 1603: {//McGuy + captain: "Boosts ATK of [STR] characters by 2.25x and their RCV by 1.25x", + special: "Delays all enemies for 2 turns", + specialName: "Numb Crosscut", + }, + 1604: {//Training Forest Ace + captain: "Boosts ATK of [STR] characters by 1.5x", + special: "Randomizes all non-matching orbs and deals 13x character's ATK in [STR] damage to all enemies", + specialName: "Fist of the Demon's Child 'Fire'", + }, + 1605: {//Training Forest Ace + captain: "Boosts ATK of [STR] characters by 2x and recovers 500 HP at end of each turn", + special: "Randomizes all non-matching orbs and deals 13x character's ATK in [STR] damage to all enemies", + specialName: "Fist of the Demon's Child 'Fire'", + }, + 1606: {//Lafitte + captain: "Boosts ATK and RCV of [PSY] characters by 1.75x", + special: "Randomly shuffles non-matching orbs on Shooter characters, reduces enemies defense by 50% for 1 turn and delays all enemies for 1 turn", + specialName: "Deprivation of Self-Consciousness", + }, + 1607: {//Van augur + captain: "Boosts ATK of Shooters by 2x", + special: "Deals 10x character's ATK in [DEX] damage to one enemy, locks orbs for 1 turn, and boosts ATK of Shooter characters by 1.5x for 1 turn", + specialName: "Painless Bullet", + }, + 1608: {//Doc Q + captain: "Boosts ATK and RCV of [INT] characters by 1.5x", + special: "For each enemy, has an extremely small chance to instantly defeat that enemy.", + specialNotes: "#{instantKill : <1%}", + specialName: "Vile Fruit", + }, + 1609: {//Legend Enel + captain: "Reduces HP of all characters by 20%, boosts chances of getting [RCV] orbs, makes [RCV] orbs \"beneficial\" to all characters, boosts ATK of all characters proportionally to the amount healed in the last turn.", + captainNotes: "The range of ATK boost is from 2x to 3.25x. The exact boost is calculated as 2 + * 0.000125 and maxes at 10k HP healed. This ignores your max HP, so it doesn't stop counting if you over-heal.", + special: "Deals typeless damage to all enemies equal to 10x how much excess healing done before the special is activated.", + specialNotes: "The excess healing is counted from the last time the special is used and accumulates when you heal more than your maximum HP. For example, if you are at max HP, and you heal 1,000 HP, you will add 10k damage to the special. The amount of damage possible caps at 2,000,000 damage.", + specialName: "Heavy Thunder", + }, + 1610: {//Legend Enel + captain: "Reduces HP of all characters by 20%, boosts chances of getting [RCV] orbs, makes [RCV] orbs \"beneficial\" to all characters, boosts ATK of all characters proportionally to the amount healed in the last turn.", + captainNotes: "The range of ATK boost is from 2x to 3.25x. The exact boost is calculated as 2 + * 0.000125 and maxes at 10k HP healed. This ignores your max HP, so it doesn't stop counting if you over-heal.", + special: "Deals typeless damage to all enemies equal to 10x how much excess healing done before the special is activated.", + specialNotes: "The excess healing is counted from the last time the special is used and accumulates when you heal more than your maximum HP. For example, if you are at max HP, and you heal 1,000 HP, you will add 10k damage to the special. The amount of damage possible caps at 2,000,000 damage.", + specialName: "Heavy Thunder", + }, + 1611: {//Kuma + captain: "Boosts ATK of Shooter characters by 1.75x and their HP by 1.2x", + special: "Reduces the duration of Bind and Despair by 7 turns. Recovers 20% of crew's MAX HP, and has low chance to eliminate all enemies", + specialNotes: "#{instantKill : 10%}", + specialName: "Paw Paw Fruit: Scatter and Fly Away", + sailor: "If Kuma has a [PSY] orb, and you hit a Perfect with him, keep his [PSY] orb for the next turn", + }, + 1612: {//Kuma + captain: "Boosts ATK of Shooter characters by 2.5x and their HP by 1.2x", + special: "Reduces the duration of Bind and Despair by 7 turns. Recovers 20% of crew's MAX HP, and has low chance to eliminate all enemies", + specialNotes: "#{instantKill : 10%}", + specialName: "Paw Paw Fruit: Scatter and Fly Away", + sailor: "If Kuma has a [PSY] orb, and you hit a Perfect with him, keep his [PSY] orb for the next turn", + }, + 1613: {//Rob Lucci + captain: "Boosts ATK of Fighter characters by 2.25x", + special: "Cuts the current HP of each enemy by 10%, reduces the defense of all enemies by 50% and amplifies the effects of orbs by 1.75x for 1 turn", + specialName: "4000 Power Level Technique: Tempest Kick", + sailor: "Adds 2x character's ATK as Additional Typeless Damage", + sailorNotes: "#{additionalDamage : 2x}", + }, + 1614: {//Rob Lucci + captain: "Boosts ATK of Fighter characters by 2.5x and their HP by 1.25x", + special: "Cuts the current HP of each enemy by 10%, reduces the defense of all enemies by 50% and amplifies the effects of orbs by 1.75x for 1 turn", + specialName: "4000 Power Level Technique: Tempest Kick", + sailor: "Adds 2x character's ATK as Additional Typeless Damage", + sailorNotes: "#{additionalDamage : 2x}", + }, + 1615: {//Crocodile + captain: "Boosts ATK of Striker characters by 2x", + special: "Deals 20x character's ATK in [INT] damage to all enemies, reduces Special Cooldown of Striker characters by 1 turn and boosts ATK of Striker characters and amplifies orbs of Striker characters by 1.5x for 1 turn", + specialName: "Desert Spada", + sailor: "Restores his own special by 2 turns when it is rewinded", + sailorNotes: "#{rewind : 2}", + }, + 1616: {//Crocodile + captain: "Boosts ATK of Striker characters by 2.5x and recovers 1.5x character's RCV in HP at the end of each turn", + special: "Deals 20x character's ATK in [INT] damage to all enemies, reduces Special Cooldown of Striker characters by 1 turn and boosts ATK of Striker characters and amplifies orbs of Striker characters by 1.5x for 1 turn", + specialName: "Desert Spada", + sailor: "Restores his own special by 2 turns when it is rewinded", + sailorNotes: "#{rewind : 2}", + limit: [ + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Aquire Potential 1: [INT] Damage Reduction" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base RCV by 40" }, + { "description": "Aquire Sailor Ability 1: Reduces Silence duration against this character by 3 turns" }, + { "description": "Boosts base ATK by 45" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: [PSY] Damage Reduction" }, + ], + potential: [ + { + "Name": "[INT] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [INT] characters by 1%", + "Level 2: Reduce damage taken from [INT] characters by ?%", + "Level 3: Reduce damage taken from [INT] characters by ?%", + "Level 4: Reduce damage taken from [INT] characters by ?%", + "Level 5: Reduce damage taken from [INT] characters by ?%" + ] + }, + { + "Name": "[PSY] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [PSY] characters by 1%", + "Level 2: Reduce damage taken from [PSY] characters by ?%", + "Level 3: Reduce damage taken from [PSY] characters by ?%", + "Level 4: Reduce damage taken from [PSY] characters by ?%", + "Level 5: Reduce damage taken from [PSY] characters by ?%" + ] + }, + ] + }, + 1617: {//Moria + captain: "Boosts ATK of [STR], [INT], and [DEX] characters by 2x", + special: "For [STR], [INT] and [DEX] characters, randomizes all non-matching orbs and boosts ATK of [STR], [INT], [DEX] characters by 1.75x for 2 turns", + specialName: "Shadow Asgard: \"Baptism\" from the Royal Shichibukai", + sailor: "When any other character uses a special, reduces own cooldown by 1 turn", + }, + 1618: {//Moria + captain: "Boosts ATK of [STR], [INT], and [DEX] characters by 2.5x", + special: "For [STR], [INT] and [DEX] characters, randomizes all non-matching orbs and boosts ATK of [STR], [INT], [DEX] characters by 1.75x for 2 turns", + specialName: "Shadow Asgard: \"Baptism\" from the Royal Shichibukai", + sailor: "When any other character uses a special, reduces own cooldown by 1 turn", + }, + 1619: {//6+ Raybae/Rayleigh + captain: "Boosts chain multiplier by 4x and boosts HP and RCV of all characters by 1.2x", + special: "Reduces Bind, Despair, and Paralysis duration by 7 turns, delays all enemies for 1 turn, and makes Perfects easier to hit for 1 turn", + specialName: "Netherworld Conqueror", + }, + 1620: {//Log Kid + captain: "Boosts ATK of Strikers characters by 2.5x if HP is below 30% at the start of the turn", + special: "Reduces crew's current HP by 80%, boosts ATK of Striker characters by 2x for 1 turn", + specialName: "Double Steel Magnetic Arm", + }, + 1621: {//Log Kid + captain: "Boosts ATK of Striker characters by 3x if HP is below 30% at the start of the turn, by 2.5x otherwise and boosts HP of Striker characters by 1.2x", + special: "Reduces crew's current HP by 80%, boosts ATK of Striker characters by 2x for 1 turn", + specialName: "Double Steel Magnetic Arm", + limit: [ + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Aquire Potential 1: Enrage" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Aquire Sailor Ability #: Boosts base ATK of Striker characters by 75" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base HP by 50" }, + { "description": "Aquire Sailor Ability #: Boosts base HP of Driven characters by 75" }, + { "description": "Boosts base HP by 60" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 20", + "Level 2: Boosts base ATK by 30", + "Level 3: Boosts base ATK by 40", + "Level 4: Boosts base ATK by 50", + "Level 5: Boosts base ATK by 100" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 1 turn on this character", + "Level 2: Reduces Slot Bind duration by 2 turns on this character", + "Level 3: Reduces Slot Bind duration by 3 turns on this character", + "Level 4: Reduces Slot Bind duration by 4 turns on this character", + "Level 5: Reduces Slot Bind duration by 5 turns on this character" + ] + }, + ] + }, + 1622: {//Reborn Doffy + special: "Switches orbs between slots twice, amplifies the effect of orbs by 2x for 1 turn", + specialNotes: "#{orb : 2x}", + specialName: "Overheat [Neo]", + captain: "Boosts ATK of Slasher characters by 2x" + }, + 1623: {//Reborn Doffy + special: "Switches orbs between slots twice, amplifies the effect of orbs by 2x for 1 turn", + specialNotes: "#{orb : 2x}", + specialName: "Overheat [Neo]", + captain: "Boosts ATK and HP of Slasher characters by 2x" + }, + 1624: {//Hyouzou + captain: "Boosts ATK of Slasher characters by 1.5x and boosts HP of Powerhouse characters by 1.25x", + special: "Randomizes all orbs, cuts the current HP of all enemies by 10%, and Poisons all enemies.", + specialName: "Flexible Six Swords", + }, + 1625: {//Daruma + captain: "Boosts ATK of Powerhouse and Fighter characters by 1.75x", + special: "Randomizes all orbs, including [BLOCK] orbs, and reduces damage received by 50% for 1 turn.", + specialName: "Arching Fangs", + }, + 1626: {//Dosun + captain: "Boosts ATK of Powerhouse characters by 2.5x following a chain of Good > Great > Perfect hits", + special: "Deals 20x character's ATK in [PSY] damage to one enemy, boosts ATK of [PSY] characters by 1.5x for 1 turn", + specialName: "The Calm Before The Storm", + }, + 1627: {//Mach Vise + captain: "Boosts ATK Free Spirit characters by 2x", + special: [ + { + "description": "Reduces Chain Multiplier Limit duration by 1 turn and boosts the Color Affinity of Striker characters by 1.25x for 1 turn", + "cooldown": [ 23, 9 ] + }, + { + "description": "Reduces Chain Multiplier Limit duration by 3 turns and boosts the Color Affinity of Striker characters by 1.5x for 1 turn", + "cooldown": [ 27, 13 ] + }, + { + "description": "Reduces Chain Multiplier Limit duration by 5 turns and boosts the Color Affinity of Striker characters by 1.75x for 1 turn", + "cooldown": [ 31, 17 ] + }, + ], + specialNotes: "#{stages}", + specialName: "Thousand Ton Destruction", + }, + 1628: {//Mach Vise + captain: "Boosts ATK Free Spirit and Striker characters by 2.25x and their RCV by 1.5x", + special: [ + { + "description": "Reduces Chain Multiplier Limit duration by 1 turn and boosts the Color Affinity of Striker characters by 1.25x for 1 turn", + "cooldown": [ 23, 9 ] + }, + { + "description": "Reduces Chain Multiplier Limit duration by 3 turns and boosts the Color Affinity of Striker characters by 1.5x for 1 turn", + "cooldown": [ 27, 13 ] + }, + { + "description": "Reduces Chain Multiplier Limit duration by 5 turns and boosts the Color Affinity of Striker characters by 1.75x for 1 turn", + "cooldown": [ 31, 17 ] + }, + ], + specialNotes: "#{stages}", + specialName: "Thousand Ton Destruction", + }, + 1629: {//Ikaros Much + captain: "Boosts ATK and HP of Striker characters by 1.5x", + special: "Randomly changes all orbs, including [BLOCK] orbs, into [STR], [DEX], [QCK], [INT], or [PSY] orbs and changes own orb into [INT]", + specialName: "The Spear that Penetrated the Undersea Mountain", + }, + 1630: {//Ikaros Much + captain: "Boosts ATK of Striker characters by 2x and their HP by 1.5x", + special: "Randomly changes all orbs, including [BLOCK] orbs, into [STR], [DEX], [QCK], [INT], or [PSY] orbs and changes own orb into [INT]", + specialName: "The Spear that Penetrated the Undersea Mountain", + }, + 1631: {//Fisher Tiger + captain: "Boosts ATK of Powerhouse characters by 2.25x", + special: "Boosts ATK of Powerhouse characters by 1.75x for 3 turns", + specialName: "Rebellion against the \"Prohibition\" - Taboo", + sailor: "When any other Powerhouse character uses a special, reduces own cooldown by 1 turn", + }, + 1632: {//Fisher Tiger + captain: "Boosts ATK of Powerhouse characters by 2.75x", + special: "Boosts ATK of Powerhouse characters by 1.75x for 3 turns", + specialName: "Rebellion against the \"Prohibition\" - Taboo", + sailor: "When any other Powerhouse character uses a special, reduces own cooldown by 1 turn", + limit: [ + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base ATK by 10" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Aquire Potential 1: Enrage" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK of Powerhouse characters by 50" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base HP by 60" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 20", + "Level 2: Boosts base ATK by 30", + "Level 3: Boosts base ATK by 40", + "Level 4: Boosts base ATK by 50", + "Level 5: Boosts base ATK by 100" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 1 turn on this character", + "Level 2: Reduces Slot Bind duration by 2 turns on this character", + "Level 3: Reduces Slot Bind duration by 3 turns on this character", + "Level 4: Reduces Slot Bind duration by 4 turns on this character", + "Level 5: Reduces Slot Bind duration by 5 turns on this character" + ] + }, + ] + }, + 1633: {//Punk Hazard Dragon + captain: "Boosts ATK of [STR] characters by 1.75x and the HP of Powerhouse characters by 1.2x", + special: "Deals 15x character's ATK in [STR] damage to all enemies and amplifies the effect of orbs by 1.25x for 1 turn", + specialName: "Flame Breath", + }, + 1634: {//Rock and Scotch + captain: "Boosts HP of [INT] characters by 2x", + special: "Reduces damage received by 50% for 1 turn", + specialName: "COOL Ambush", + }, + 1635: {//Brownbeard + captain: "Boosts OWN ATK by 1.5x and the ATK of Cerebral characters by 2x", + special: "Cuts the HP of all enemies by 20% and binds himself for 5 turns", + specialName: "Crocodile Thrust", + }, + 1636: {//Caesar Clown + captain: "Boosts ATK of Cerebral characters by 2x", + special: "Boosts ATK against Poisoned and Strongly Poisoned enemies by 1.3x for 3 turns and changes [BOMB] orbs into matching orbs", + specialName: "Gastanet", + }, + 1637: {//Caesar Clown Evolved + captain: "Boosts ATK of Cerebral characters by 2.25x and reduces damage received by 15%", + special: "Boosts ATK against Poisoned and Strongly Poisoned enemies by 1.3x for 3 turns and changes [BOMB] orbs into matching orbs", + specialName: "Gastanet", + }, + 1638: {//STR Gas Mask Fodder + special: "Boosts chances of getting [RCV] orbs for 2 turns", + specialName: "Meat for Meat", + }, + 1639: {//QCK Gas Mask Fodder + special: "Reduces Paralysis duration by 1 turn", + specialName: "Shock Recovery: Light", + }, + 1640: {//DEX Gas Mask Fodder + special: "For 1 turn, makes STR orb \"beneficial\" for Shooter characters", + specialName: "Shooter Beneficial Slot: STR", + }, + 1641: {//INT Gas Mask Fodder + special: "Boosts ATK against Poisoned and Strongly Poisoned enemies by 1.2x for 1 turn", + specialName: "Rising Damage: Poison", + }, + 1642: {//PSY Gas Mask Fodder + special: "Deals 3x character's ATK in typeless damage to all enemies, Poisons all enemies", + specialNotes: "#{poison}", + specialName: "Poison Attack", + }, + 1643: {//STR Centaur Fodder + captain: "Reduces cooldown of Slasher specials by 2 turns at the start of the fight", + special: "Boosts ATK of Slasher characters for 1 turn", + specialName: "Attack Boost: Slasher", + }, + 1644: {//QCK Centaur Fodder + captain: "Boosts ATK of [QCK] characters by 2x, reduces crew's current HP by ???% at the end of each turn", + special: "Reduces Silence duration by 1 turn", + specialNotes: "#{silence}", + specialName: "Special Seal Recovery: Light", + }, + 1645: {//DEX Centaur Fodder + captain: "Boosts ATK of [DEX] characters by 1.5x and Slasher characters by 1.3x", + captainNotes: "The bonus is cumulative. [DEX] Slasher characters get a 1.95x bonus.", + special: "Deals 5 hits of random typeless damage to random enemies", + specialNotes: "#{randomHits : 5}", + specialName: "Random Light Blows", + }, + 1646: {//Reborn Pica + captain: "Boosts ATK of Powerhouse characters by 1.5x, and their HP by 1.5x", + specialName: "Rock Domination Wall [Neo]", + special: [ + { + "description": "For Driven and Powerhouse characters, changes [EMPTY] and Badly Matching orbs into Matching orbs. Cuts the current HP of all enemies by 10%", + "cooldown": [ 20, 11 ] + }, + { + "description": "Changes [EMPTY] and Badly Matching orbs into Matching orbs. Cuts the current HP of all enemies by 20%", + "cooldown": [ 26, 17 ] + } + ], + specialNotes: "#{stages}" + }, + 1647: {//Reborn Pica + captain: "Boosts ATK of Powerhouse characters by 2.25x, and their HP by 1.5x", + specialName: "Rock Domination Wall [Neo]", + special: [ + { + "description": "For Driven and Powerhouse characters, changes [EMPTY] and Badly Matching orbs into Matching orbs. Cuts the current HP of all enemies by 10%", + "cooldown": [ 20, 11 ] + }, + { + "description": "Changes [EMPTY] and Badly Matching orbs into Matching orbs. Cuts the current HP of all enemies by 20%", + "cooldown": [ 26, 17 ] + } + ], + specialNotes: "#{stages}" + }, + 1648: {//Giolla + captain: "Boosts ATK of all characters by 1.2x. Boosts ATK by 2.4x after scoring 4 Perfects in a row", + special: "Reduces damage received by 90% for 1 turn and randomly changes all orbs, including [BLOCK] orbs, into either [STR], [DEX] or [QCK] orbs", + specialName: "Sprouting with Beautiful Passion", + }, + 1649: {//Giolla + captain: "Boosts ATK of all characters by 1.2x. Boosts ATK by 3x after scoring 4 Perfects in a row", + special: "Reduces damage received by 90% for 1 turn and randomly changes all orbs, including [BLOCK] orbs, into either [STR], [DEX] or [QCK] orbs", + specialName: "Sprouting with Beautiful Passion", + }, + 1650: {//Brook x5 + captain: "Boosts RCV of [DEX] characters by 1.5x and boosts ATK by 3x if they have a matching orb, by 1.5x otherwise.", + special: "Changes [BLOCK], [TND], [EMPTY], and [BOMB] orbs into [DEX] orbs and amplifies the effect of orbs by 1.5x for 1 turn", + specialName: "Eyes Blinded by True Beauty", + }, + 1651: {//Nekomamushi + captain: "Boosts HP of Striker characters by 1.25x and boosts ATK by 3.75x if they have a [STR], [QCK], [DEX], [INT], [PSY] or [RAINBOW] orb", + special: "Deals 60x character's ATK in [PSY] damage to one enemy and makes [STR], [DEX], [QCK], [PSY] and [INT] orbs \"beneficial\" for Striker characters for 1 turn", + specialName: "Daybreak Ruler's Spear", + }, + 1652: {//Nekomamushi + captain: "Boosts HP of Striker characters by 1.25x and boosts ATK by 3.75x if they have a [STR], [QCK], [DEX], [INT], [PSY] or [RAINBOW] orb", + special: "Deals 60x character's ATK in [PSY] damage to one enemy and makes [STR], [DEX], [QCK], [PSY] and [INT] orbs \"beneficial\" for Striker characters for 1 turn", + specialName: "Daybreak Ruler's Spear", + limit: [ + { "description": "Boosts base RCV by 5" }, + { "description": "Boosts base RCV by 5" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Aquire Potential 1: [STR] Damage Reduction" }, + { "description": "Boosts base HP by 15" }, + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base HP by 25" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK, HP and RCV of Striker characters by 70" }, + { "description": "Boosts base ATK by 10" }, + { "description": "Boosts base ATK by 15" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 35" }, + { "description": "Boosts base HP by 40" }, + { "description": "Aquire Potential 2: [PSY] Damage Reduction" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base HP by 45" }, + { "description": "Boosts base HP by 55" }, + { "description": "Boosts base HP by 65" }, + { "description": "Boosts base ATK by 35" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base HP by 70" }, + { "description": "Boosts base HP by 80" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base RCV by 40" }, + { "description": "Aquire Sailor Ability 2: Makes [INT] orbs \"beneficial\" for this unit" }, + { "description": "Boosts base ATK by 45" }, + { "description": "Boosts base ATK by 55" }, + { "description": "Aquire Potential 3: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "[STR] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [STR] characters by ?%", + "Level 2: Reduce damage taken from [STR] characters by ?%", + "Level 3: Reduce damage taken from [STR] characters by ?%", + "Level 4: Reduce damage taken from [STR] characters by ?%", + "Level 5: Reduce damage taken from [STR] characters by ?%" + ] + }, + { + "Name": "[PSY] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [PSY] characters by ?%", + "Level 2: Reduce damage taken from [PSY] characters by ?%", + "Level 3: Reduce damage taken from [PSY] characters by ?%", + "Level 4: Reduce damage taken from [PSY] characters by ?%", + "Level 5: Reduce damage taken from [PSY] characters by ?%" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by ? turn on this character", + "Level 2: Reduces Slot Bind duration by ? turns on this character", + "Level 3: Reduces Slot Bind duration by ? turns on this character", + "Level 4: Reduces Slot Bind duration by ? turns on this character", + "Level 5: Reduces Slot Bind duration by ? turns on this character" + ] + }, + ] + }, + 1653: {//Pedro + captain: "Boosts ATK of [INT] characters by 2x", + special: "Reduces crew's HP to 1, deals 7x the amount of HP subtracted in typeless damage to all enemies, amplifies the effect of orbs by 1.75x for 1 turn", + sailor: "Makes INT orbs \"beneficial\" for Slasher and Cerebral characters", + specialName: "Charge Drive", + }, + 1654: {//Pedro + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of [INT] characters by 2.5x", + special: "Reduces crew's HP to 1, deals 7x the amount of HP subtracted in typeless damage to all enemies, amplifies the effect of orbs by 1.75x for 1 turn", + sailor: "Makes INT orbs \"beneficial\" for Slasher and Cerebral characters", + specialName: "Charge Drive", + }, + 1655: {//Carrot + captain: "Boosts ATK and RCV of [QCK] characters by 1.5x", + special: "Boosts ATK of QCK characters by 2x for 1 turn", + sailor: "Boosts base ATK and RCV of [QCK] characters by 75", + specialName: "Electric Fist", + }, + 1656: {//Carrot + captain: "Boosts ATK of [QCK] characters by 2.25x and their RCV by 1.5x", + special: "Boosts ATK of QCK characters by 2x for 1 turn", + sailor: "Boosts base ATK and RCV of [QCK] characters by 75", + specialName: "Electric Fist", + }, + 1657: {//Kanjuro + captain: "Boosts ATK of Striker and Free Spirit characters by 2x", + special: "Reduces Bind and Despair duration by 5 turns. If your Captain is a Striker character, locks the chain multiplier at 2.75x for 1 turn", + sailor: "Makes [DEX] orbs \"beneficial\" for Striker characters if your Captain is a Striker character", + specialName: "Summon Dragon", + }, + 1658: {//Kanjuro + captain: "Boosts ATK of Striker and Free Spirit characters by 2.5x", + special: "Reduces Bind and Despair duration by 5 turns. If your Captain is a Striker character, locks the chain multiplier at 2.75x for 1 turn", + sailor: "Makes [DEX] orbs \"beneficial\" for Striker characters if your Captain is a Striker character", + specialName: "Summon Dragon", + }, + 1659: {//Raizo + captain: "Boosts ATK of Shooter characters by 2x", + special: "Reduces Paralysis and Silence duration by 3 turns, switches orbs between slots 3 times", + sailorNotes: "#{silence}", + sailor: "Completely resists Silence on this character", + specialNotes: "#{silence}", + specialName: "Ninja Arts - Bunshin no Jutsu", + }, + 1660: {//Raizo + captain: "Boosts ATK of Shooter characters by 2.5x and makes [TND] and [RCV] orbs \"beneficial\" to Shooter characters", + special: "Reduces Paralysis and Silence duration by 3 turns, switches orbs between slots 3 times", + sailorNotes: "#{silence}", + sailor: "Completely resists Silence on this character", + specialNotes: "#{silence}", + specialName: "Ninja Arts - Bunshin no Jutsu", + }, + 1661: {//Corazon + captain: "Boosts ATK of [PSY], [QCK], and [DEX] characters by 2x and recovers 300 HP at end of each turn", + special: [ + { + "description": "Reduces Special Cooldown of Cerebral and Free Spirit characters by 1 turn.", + "cooldown": [ 6, 6 ] + }, + { + "description": "Locks the chain multiplier at 2.5x for 1 turn and reduces Special Cooldown of Cerebral and Free Spirit characters by 1 turn.", + "cooldown": [ 10, 10 ] + } + ], + specialName: "The Sun under the Rain", + }, + 1662: {//Corazon + captain: "Boosts ATK of [PSY], [QCK], and [DEX] characters by 2.5x and recovers 500 HP at end of each turn", + special: [ + { + "description": "Reduces Special Cooldown of Cerebral and Free Spirit characters by 1 turn.", + "cooldown": [ 6, 6 ] + }, + { + "description": "Locks the chain multiplier at 2.5x for 1 turn and reduces Special Cooldown of Cerebral and Free Spirit characters by 1 turn.", + "cooldown": [ 10, 10 ] + } + ], + specialName: "The Sun under the Rain", + }, + 1663: {//6+ Rob Lucci + special: "Deals 75x character's ATK in typeless damage to one enemy, greatly boosts chances of getting matching orbs for 3 turns", + specialName: "Six Powers Supreme: Six King Gun", + captain: "Boosts ATK of Powerhouse characters by 3.5x if they have a matching orb, by 2.5x otherwise, reduces crew's RCV to 0", + limit: "This character has a limit break path", + }, + 1664: {//STR Aokiji + captain: "Boosts ATK of Shooter characters by 2.5x", + special: "Locks all orbs for 1 turn. If during that turn, you hit 2 PERFECTS and your Captain is a Shooter character, boosts ATK of Shooter characters by 2x for 1 turn in the following turn.", + specialName: "Ice Saber", + }, + 1665: {//STR Aokiji + captain: "Boosts ATK of Shooter characters by 2.5x and boosts ATK of Shooters by 3.25x after scoring 3 PERFECTS in a row", + special: "Locks all orbs for 1 turn. If during that turn, you hit 2 PERFECTS and your Captain is a Shooter character, boosts ATK of Shooter characters by 2x for 1 turn in the following turn.", + specialName: "Ice Saber", + limit: [ + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 40" }, + { "description": "Aquire Potential 1: Reduce No Healing duration" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Aquire Sailor Ability 1: Boosts base HP of Shooter characters by 50" }, + { "description": "Boosts base HP by 60" }, + { "description": "Aquire Sailor Ability 2: Boosts base ATK of Shooter characters by 50" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Barrier Penetration" }, + ], + potential: [ + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: If there are 6 Shooter characters in your crew, reduces No Healing duration by 1 turn", + "Level 2: If there are 6 Shooter characters in your crew, reduces No Healing duration by 1 turn", + "Level 3: If there are 6 Shooter characters in your crew, reduces No Healing duration by 1 turn", + "Level 4: If there are 6 Shooter characters in your crew, reduces No Healing duration by 2 turns", + "Level 5: If there are 6 Shooter characters in your crew, reduces No Healing duration by 3 turns" + ] + }, + { + "Name": "Barrier Penetration", + "description": [ + "Level 1: This character's attack will ignore barriers if HP is above 99%", + "Level 2: This character's attack will ignore barriers if HP is above 99%", + "Level 3: This character's attack will ignore barriers if HP is above 99%", + "Level 4: This character's attack will ignore barriers if HP is above 80%", + "Level 5: This character's attack will ignore barriers if HP is above 50%" + ] + }, + ] + }, + 1666: {//Kyros + captain: "Boosts ATK of Striker characters by 2x", + special: "Changes adjacent orbs into Matching Orbs and if HP is above 70%, amplifies the effect of orbs for Striker and Powerhouse characters by 1.5x for 1 turn", + specialName: "Trueno Bastardo", + }, + 1667: {//Kyros + captain: "Boosts HP of Striker characters by 1.2x and boosts ATK of Striker characters by 2.75x if HP is below 30% at the start of the turn, 2.25x otherwise", + special: "Changes adjacent orbs into Matching Orbs and if HP is above 70%, amplifies the effect of orbs for Striker and Powerhouse characters by 1.5x for 1 turn", + specialName: "Trueno Bastardo", + }, + 1668: {//Reborn Aokiji + special: "Boosts ATK of Striker characters by 1.75x for 2 turns, locks all orbs for 2 turns", + specialName: "Ice Block - Pheasant Beak [Neo]", + captain: "Boosts ATK of Striker characters by 2x" + }, + 1669: {//Reborn Aokiji + special: "Boosts ATK of Striker characters by 1.75x for 2 turns, locks all orbs for 2 turns", + specialName: "Ice Block - Pheasant Beak [Neo]", + captain: "Boosts ATK and HP of Striker characters by 2x" + }, + 1670: {//Shyarly + captain: "Boosts ATK of [DEX] characters by 1.75x and their RCV by 1.2x", + special: "Randomizes all non-matching orbs, switches orbs between slots two times, and delays all enemies for 1 turn", + specialName: "A Warning to the Fool", + }, + 1671: {//Camie + captain: "Boosts RCV of Free Spirit characters by 1.5x", + special: "Recovers 15% of crew's MAX HP and amplifies the effect of orbs by 1.5x for 1 turn", + specialName: "Cheerfulness that Shines in the Deep Sea", + }, + 1672: {//Pappagu + captain: "Boosts ATK and HP of Powerhouse characters by 1.5x", + special: "Binds himself for 2 turns and reduces Despair and Silence duration by 3 turns", + specialName: "A Starfish Reaching for His Beliefs", + }, + 1673: {//Swinsuit Perona + captain: "Boosts ATK of all characters by 1.75x and boosts EXP gained by 1.2x", + special: "Reduces damage received by 70% for 1 turn, reduces the defense of all enemies by 90% for 1 turn and reduces Silence duration by 2 turns.", + specialNotes: "#{silence}", + sailor: "Completely resists Silence on this character", + sailorNotes: "#{silence}", + specialName: "Romantic Princess", + }, + 1674: {//Swinsuit Perona + captain: "Boosts ATK of all characters by 2.25x and boosts EXP gained by 1.5x", + special: "Reduces damage received by 70% for 1 turn, reduces the defense of all enemies by 90% for 1 turn and reduces Silence duration by 2 turns.", + specialNotes: "#{silence}", + sailor: "Completely resists Silence on this character", + sailorNotes: "#{silence}", + specialName: "Romantic Princess", + }, + 1675: {//Kimono Zoro + captain: "Boosts chain multiplier by 2x", + special: "Boosts ATK of Slasher and Driven characters by 1.5x for 1 turn. If your Captain is a Slasher or Driven character, changes adjacent orbs into matching orbs and reduces Paralysis and Despair duration by 2 turns", + sailor: "Reduces Blindness duration by 1 turn", + specialName: "Great Swordsman Under the Umbrella", + }, + 1676: {//Kimono Zoro + captain: "Boosts chain multiplier by 3.25 and reduce damage received by 10%", + special: "Boosts ATK of Slasher and Driven characters by 1.5x for 1 turn. If your Captain is a Slasher or Driven character, changes adjacent orbs into matching orbs and reduces Paralysis and Despair duration by 2 turns", + sailor: "Reduces Blindness duration by 1 turn", + specialName: "Great Swordsman Under the Umbrella", + }, + 1677: {//Log Law + captain: "Boosts ATK of Slasher characters by 2.5x", + special: "Boosts the Color Affinity of Slasher by 1.5x for 1 turn, changes middle row orbs into matching orbs and switches orbs between slots three times", + specialName: "ROOM: Kikoku", + }, + 1678: {//Log Law + captain: "Boosts ATK of Slasher characters by 2.5x at the start of the chain, by 3.25x after the 3rd Perfect in a row", + special: "Boosts the Color Affinity of Slasher by 1.5x for 1 turn, changes middle row orbs into matching orbs and switches orbs between slots three times", + specialName: "ROOM: Kikoku", + limit: [ + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 25" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 35" }, + { "description": "Boosts base RCV by 35" }, + { "description": "Aquire Sailor Ability 1: Completely resists Silence on this character" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Boosts base HP by 85" }, + { "description": "Aquire Sailor Ability 2: Reduces Paralysis duration by 1 turn" }, + { "description": "Aquire Potential 2: Barrier Penetration" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 10% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 15% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 20% chance to deal 10% of this character's attack in extra damage" + ] + }, + { + "Name": "Barrier Penetration", + "description": [ + "Level 1: This character's attack will ignore barriers if HP is above 99%", + "Level 2: This character's attack will ignore barriers if HP is above 99%", + "Level 3: This character's attack will ignore barriers if HP is above 99%", + "Level 4: This character's attack will ignore barriers if HP is above 80%", + "Level 5: This character's attack will ignore barriers if HP is above 50%" + ] + }, + ] + }, + 1679: {//Kai Mihawk + special: "Cuts the current HP of each enemy by 30%", + specialName: "Black Blade Ship Cutter [Neo]", + captain: "Boosts ATK of Slasher characters by 2x" + }, + 1680: {//Kai Mihawk + special: "Cuts the current HP of each enemy by 30%", + specialName: "Black Blade Ship Cutter [Neo]", + captain: "Boosts ATK of Slasher characters by 2.5x" + }, + 1681: {//20th Anni Luffy + captain: "Boosts ATK of characters with cost 30 or less by 2.5x", + special: "Cuts the current HP of each enemy by 20%, if Luffy is your Captain or Friend/Guest Captain, changes left column into Matching orbs, otherwise, adds .5x to Chain multiplier for 1 turn.", + specialName: "Gomu Gomu no Tako Stamp", + sailor: "Boosts base HP and ATK of all characters by 56", + }, + 1682: {//20th Anni Luffy + captain: "Boosts HP of characters with cost 30 or less by 1.3x and boosts ATK of characters with cost 30 or less by 2.5x at the start of the chain, 3.5x after the 3rd Perfect in a row", + special: "Cuts the current HP of each enemy by 20%, if Luffy is your Captain or Friend/Guest Captain, changes left column into Matching orbs, otherwise, adds .5x to Chain multiplier for 1 turn.", + specialName: "Gomu Gomu no Tako Stamp", + sailor: "Boosts base HP and ATK of all characters by 56", + }, + 1683: {//20th Anni Robin + captain: "Boosts ATK of Cerebral characters by 2x, and their RCV by 1.3x", + special: "Binds self for 1 turn, empties all slots with [BLOCK] orbs, deals several times the character's ATK in typeless damage to one enemy and boosts ATK against enemies with reduced defense by 1.5x for 2 turns", + specialName: "Mil Fleur: Gigantesco Mano", + specialNotes: "The exact multiplier used is chosen based on the number of [BLOCK] orbs consumed: 0 orbs - Unknown; 1 orb - ???x ATK; 2 orbs - ???x ATK; 3 orbs - ???x ATK; 4 orbs - ???x ATK; 5 orbs - ???x ATK; 6 orbs - ???x ATK.", + sailor: "Makes [TND] orbs \"beneficial\" for all characters if your Captain is a Fighter character", + }, + 1684: {//20th Anni Robin + captain: "Boosts ATK of Cerebral characters by 2.5x, and their RCV by 1.3x", + special: "Binds self for 1 turn, empties all slots with [BLOCK] orbs, deals several times the character's ATK in typeless damage to one enemy and boosts ATK against enemies with reduced defense by 1.5x for 2 turns", + specialName: "Mil Fleur: Gigantesco Mano", + specialNotes: "The exact multiplier used is chosen based on the number of [BLOCK] orbs consumed: 0 orbs - Unknown; 1 orb - ???x ATK; 2 orbs - ???x ATK; 3 orbs - ???x ATK; 4 orbs - ???x ATK; 5 orbs - ???x ATK; 6 orbs - ???x ATK.", + sailor: "Makes [TND] orbs \"beneficial\" for all characters if your Captain is a Fighter character", + }, + 1685: {//20th Anni Usopp + captain: "Boosts ATK of Shooter characters by 2.75x following a chain of Good > Great > Perfect hits", + special: "Changes [EMPTY] orbs into Matching orbs, changes Badly Matching orbs into [RCV] orbs and delays all enemies for 1 turn", + specialName: "Green Star: Bamboo Javelin-Grove", + sailor: "Reduces Silence duration on this character by 4 turns", + sailorNotes: "#{silence}", + }, + 1686: {//20th Anni Usopp + captain: "Boosts ATK of Shooter characters by 3.25x following a chain of Good > Great > Perfect hits", + special: "Changes [EMPTY] orbs into Matching orbs, changes Badly Matching orbs into [RCV] orbs and delays all enemies for 1 turn", + specialName: "Green Star: Bamboo Javelin-Grove", + sailor: "Reduces Silence duration on this character by 4 turns", + sailorNotes: "#{silence}", + }, + 1687: {//20th Anni Franky + captain: "Boosts ATK of Fighter characters by 2x and reduce damage received by 10%", + special: "Changes own orb into [DEX], deals 15 hits of random typeless damage to random enemies, and reduces the defense of all enemies by 100% for 2 turns", + specialNotes: "#{randomHits : 15}
    #{random : ??? : ??? : for each hit}", + specialName: "Franky Iron BOXING", + sailor: "Restores his own special by 3 turns when it is rewinded", + sailorNotes: "#{rewind : 3}", + }, + 1688: {//20th Anni Franky + captain: "Boosts ATK of Fighter characters by 2.5x and reduce damage received by 15%", + special: "Changes own orb into [DEX], deals 15 hits of random typeless damage to random enemies, and reduces the defense of all enemies by 100% for 2 turns", + specialNotes: "#{randomHits : 15}
    #{random : ??? : ??? : for each hit}", + specialName: "Franky Iron BOXING", + sailor: "Restores his own special by 3 turns when it is rewinded", + sailorNotes: "#{rewind : 3}", + }, + 1689: {//Fortnight Kid + captain: "Boosts ATK of all characters by 1.5x at the start of the chain, by 2.25x following a chain of STR > DEX > INT attacks no lower than Good", + special: "Cuts the current HP of one enemy by 20% and and boosts own ATK by 2x for 1 turn", + specialName: "Iron Giant Palm Slam", + }, + 1690: {//Fortnight Kid + captain: "Boosts ATK of all characters by 2x at the start of the chain, by 3x following a chain of STR > DEX > INT attacks no lower than Good", + special: "Cuts the current HP of one enemy by 20% and and boosts own ATK by 2x for 1 turn", + specialName: "Iron Giant Palm Slam", + }, + 1691: {//Heat + captain: "Boosts ATK of Shooter characters by 1.75x", + special: "Boosts ATK against enemies with reduced defense by 1.3x for 1 turn, changes the captain's [STR], [DEX], [QCK], [INT], or [PSY] orbs into Matching orbs.", + specialName: "Aim and Burn", + }, + 1692: {//Wire + captain: "Boosts HP of Driven characters by 1.5x", + special: "Adds .3x to Chain multiplier, and reduces the defense of all enemies by 50% for 1 turn", + specialName: "Three Wind Tunnels", + }, + 1693: {//Inuarashi + captain: "Boosts ATK of [PSY] characters by 2x", + special: "Reduces crew's current HP by 50%, deals 50000 Fixed damage to one enemy, boosts own ATK by 1.75x for 1 turn, amplifies the effect of own orb by 1.75x for 1 turn and changes own orb to [PSY].", + specialNotes: "Boosted ATK and Orb Effectivess only works for the character who uses their own Special.", + specialName: "King's Lightning Burial", + }, + 1694: {//Inuarashi + captain: "Boosts ATK of [PSY] characters by 2.75x", + special: "Reduces crew's current HP by 50%, deals 50000 Fixed damage to one enemy, boosts own ATK by 1.75x for 1 turn, amplifies the effect of own orb by 1.75x for 1 turn and changes own orb to [PSY].", + specialNotes: "Boosted ATK and Orb Effectivess only works for the character who uses their own Special.", + specialName: "King's Lightning Burial", + }, + 1695: {//Vergo + captain: "Boosts ATK of Striker characters by 2x", + special: "Deals 50x character's ATK in [DEX] damage to one enemy, amplifies the effect of orbs for Striker characters by 1.75x for 1 turn and reduces damage received by 50% for 1 turn", + specialName: "The Darkest Demon", + }, + 1696: {//Vergo + captain: "Boosts ATK of Striker characters by 2.5x and reduces damage received by 10%", + special: "Deals 50x character's ATK in [DEX] damage to one enemy, amplifies the effect of orbs for Striker characters by 1.75x for 1 turn and reduces damage received by 50% for 1 turn", + specialName: "The Darkest Demon", + limit: [ + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base HP by 20" }, + { "description": "Aquire Potential 1: [DEX] Damage Reduction" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base HP by 30" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base HP by 60" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK, HP and RCV of Striker characters by 25" }, + { "description": "Boosts base HP by 70" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: [QCK] Damage Reduction" }, + ], + potential: [ + { + "Name": "[DEX] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [DEX] characters by 1%", + "Level 2: Reduce damage taken from [DEX] characters by ?%", + "Level 3: Reduce damage taken from [DEX] characters by ?%", + "Level 4: Reduce damage taken from [DEX] characters by ?%", + "Level 5: Reduce damage taken from [DEX] characters by ?%" + ] + }, + { + "Name": "[QCK] Damage Reduction", + "description": [ + "Level 1: Reduce damage taken from [QCK] characters by 1%", + "Level 2: Reduce damage taken from [QCK] characters by ?%", + "Level 3: Reduce damage taken from [QCK] characters by ?%", + "Level 4: Reduce damage taken from [QCK] characters by ?%", + "Level 5: Reduce damage taken from [QCK] characters by ?%" + ] + }, + ] + }, + 1697: {//Magellan + captain: "Boosts ATK of all characters by 2.25x and their HP by 1.5x if there's a [STR], [DEX], [QCK], [PSY], and [INT] character in your crew. Cuts the current HP of each enemy by 15% at the end of each turn", + special: "Inflicts Toxic to all enemies, recovers 13x character's RCV in HP at the end of each turn for 3 turns", + specialNotes: "Toxic starts at 50x character's attack and increases by 2x at the end of every turn until 2,000,000 damage per turn.", + specialName: "Venom Cloud", + }, + 1698: {//Magellan + captain: "Boosts ATK of all characters by 2.25x and their HP by 1.5x if there's a [STR], [DEX], [QCK], [PSY], and [INT] character in your crew. Cuts the current HP of each enemy by 15% at the end of each turn", + special: "Inflicts Toxic to all enemies, recovers 13x character's RCV in HP at the end of each turn for 3 turns", + specialNotes: "Toxic starts at 50x character's attack and increases by 2x at the end of every turn until 2,000,000 damage per turn.", + specialName: "Venom Cloud", + limit: [ + { "description": "Boosts base ATK by 15" }, + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Aquire Potential 1: Pinch Healing" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base ATK by 15" }, + { "description": "Aquire Sailor Ability 1: Cannot be blown away" }, + { "description": "Boosts base ATK by 15" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Aquire Potential 2: Barrier Penetration" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Boosts base HP by 90" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base ATK by 45" }, + { "description": "Boosts base HP by 90" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base HP by 100" }, + { "description": "Aquire Potential 3: Reduce No Healing duration" }, + ], + potential: [ + { + "Name": "Pinch Healing", + "description": [ + "Level 1: If HP is below 10% at the start of the turn, heals for 2x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 2: If HP is below 15% at the start of the turn, heals for 2x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 3: If HP is below 20% at the start of the turn, heals for 2x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 4: If HP is below 30% at the start of the turn, heals for 2x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 5: If HP is below 30% at the start of the turn, heals for 3x this character's RCV at the end of the turn each time you hit a Perfect" + ] + }, + { + "Name": "Barrier Penetration", + "description": [ + "Level 1: This character's attack will ignore barriers if HP is above 99%", + "Level 2: This character's attack will ignore barriers if HP is above 90%", + "Level 3: This character's attack will ignore barriers if HP is above 70%", + "Level 4: This character's attack will ignore barriers if HP is above 50%", + "Level 5: This character's attack will ignore barriers" + ] + }, + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: Reduces No Healing duration by 1 turn", + "Level 2: Reduces No Healing duration by 2 turns", + "Level 3: Reduces No Healing duration by 3 turns", + "Level 4: Reduces No Healing duration by 4 turns", + "Level 5: Reduces No Healing duration by 5 turns" + ] + }, + ] + }, + 1699: {//Jinbe + captain: "Boosts ATK of Fighter characters by 2x, and their HP by 1.2x", + special: "Adds .3x to Chain multiplier for 2 turns, reduces Chain Multiplier Limit and Chain Coeffiecient Reduction duration by 3 turns", + specialName: "Gentle Ultrasound Wave", + specialNotes: "This is most likely the effect that prevents your chain from exceeding a certain value.", + sailor: "Boosts base ATK of Fighter characters by 75", + }, + 1700: {//Jinbe + captain: "Boosts ATK of Fighter characters by 2.5x, and their HP by 1.3x", + special: "Adds .3x to Chain multiplier for 2 turns, reduces Chain Multiplier Limit and Chain Coeffiecient Reduction duration by 3 turns", + specialName: "Gentle Ultrasound Wave", + specialNotes: "This is most likely the effect that prevents your chain from exceeding a certain value.", + sailor: "Boosts base ATK of Fighter characters by 75", + limit: [ + { "description": "Boosts base ATK by 25" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base HP by 70" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Sailor Ability 1: Boost HP of all characters by 40 if your Captain is a Fighter character" }, + { "description": "Boosts base HP by 90" }, + { "description": "Aquire Potential 2: Enrage" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 10% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 15% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 20% chance to deal 10% of this character's attack in extra damage" + ] + }, + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 30", + "Level 2: Boosts base ATK by 60", + "Level 3: Boosts base ATK by 90", + "Level 4: Boosts base ATK by 100", + "Level 5: Boosts base ATK by 150" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1701: {//Ivankov + captain: "Boosts ATK of Free Spirit characters by 2x", + special: [ + { + "description": "Randomizes all orbs", + "cooldown": [ 9, 4 ] + }, + { + "description": "Changes [BLOCK] orbs into Matching orbs", + "cooldown": [ 12, 7 ] + }, + { + "description": "Changes [BLOCK] and Badly Matching orbs into Matching orbs", + "cooldown": [ 15, 10 ] + } + ], + specialName: "Hair Removal Fist", + specialNotes: "#{stages}", + sailor: "Completely resists Paralysis on this character", + }, + 1702: {//Ivankov + captain: "Boosts ATK of Free Spirit characters by 2.5x, recovers 2x character's RCV in HP at the end of each turn", + special: [ + { + "description": "Randomizes all orbs", + "cooldown": [ 9, 4 ] + }, + { + "description": "Changes [BLOCK] orbs into Matching orbs", + "cooldown": [ 12, 7 ] + }, + { + "description": "Changes [BLOCK] and Badly Matching orbs into Matching orbs", + "cooldown": [ 15, 10 ] + } + ], + specialName: "Hair Removal Fist", + specialNotes: "#{stages}", + sailor: "Completely resists Paralysis on this character", + limit: [ + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base ATK by 10" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base HP by 90" }, + { "description": "Boosts base RCV by 25" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Aquire Sailor Ability 1: When any other Free Spirit character uses a special, reduces own cooldown by 1 turn" }, + { "description": "Aquire Potential 2: Reduce No Healing duration" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 10% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 15% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 30% chance to deal 7% of this character's attack in extra damage" + ] + }, + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: Reduces No Healing duration by 1 turn", + "Level 2: Reduces No Healing duration by 1 turn", + "Level 3: Reduces No Healing duration by 1 turn", + "Level 4: Reduces No Healing duration by 2 turns", + "Level 5: Reduces No Healing duration by 3 turns" + ] + }, + ] + }, + 1703: {//Hannyabal + captain: "Boosts ATK of [INT] characters by 2x", + special: "Reduces damage received by 50% for 2 turns and boosts ATK against enemies inflicted with Toxic by 1.75x for 2 turns", + specialName: "Inferno Hell Wheel", + sailor: "Makes [STR], [QCK], [DEX], [PSY] and [INT] orbs \"beneficial\" for this unit if your Captain is a Striker character", + }, + 1704: {//Hannyabal + captain: "Boosts ATK of [INT] characters by 2.5x, recovers 2x character's RCV in HP at the end of each turn", + special: "Reduces damage received by 50% for 2 turns and boosts ATK against enemies inflicted with Toxic by 1.75x for 2 turns", + specialName: "Inferno Hell Wheel", + sailor: "Makes [STR], [QCK], [DEX], [PSY] and [INT] orbs \"beneficial\" for this unit if your Captain is a Striker character", + limit: [ + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 50" }, + { "description": "Aquire Potential 1: Pinch Healing" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Aquire Sailor Ability 1: Makes [RCV] and [TND] orbs \"beneficial\" for this unit if your Captain is a Driven character" }, + { "description": "Boosts base HP by 200" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Enrage" }, + ], + potential: [ + { + "Name": "Pinch Healing", + "description": [ + "Level 1: If HP is below 5% at the start of the turn, heals for 1x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 2: If HP is below 5% at the start of the turn, heals for 1.25x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 3: If HP is below 5% at the start of the turn, heals for 1.5x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 4: If HP is below 10% at the start of the turn, heals for 1.5x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 5: If HP is below 20% at the start of the turn, heals for 1.5x this character's RCV at the end of the turn each time you hit a Perfect" + ] + }, + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 30", + "Level 2: Boosts base ATK by 60", + "Level 3: Boosts base ATK by 90", + "Level 4: Boosts base ATK by 100", + "Level 5: Boosts base ATK by 150" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1705: {//Bon Clay + captain: "Boosts ATK of [STR] characters by 2x", + special: "Removes all positive buffs on your team. If the special is activated with more than 50% health remaining, protects from defeat for 1 turn", + specialName: "A Speech Left in Hell", + sailor: "Boosts base ATK, HP and RCV of all characters by 50", + }, + 1706: {//Bon Clay + captain: "Boosts ATK of [STR] characters by 2.5x at the start of the chain, and boosts ATK of [STR] characters by 3.125x after scoring 3 Perfects in a row", + special: "Removes all positive buffs on your team. If the special is activated with more than 50% health remaining, protects from defeat for 1 turn", + specialName: "A Speech Left in Hell", + sailor: "Boosts base ATK, HP and RCV of all characters by 50", + limit: [ + { "description": "Boosts base ATK by 15" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Boosts base HP by 50" }, + { "description": "Aquire Potential 1: Pinch Healing" }, + { "description": "Boosts base HP by 70" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Boosts base ATK by 15" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 130" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Aquire Sailor Ability 1: Restores his own special by 2 turns when it is rewinded" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential #: Enrage" }, + ], + potential: [ + { + "Name": "Pinch Healing", + "description": [ + "Level 1: If HP is below 10% at the start of the turn, heals for .5x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 2: If HP is below 15% at the start of the turn, heals for .5x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 3: If HP is below 20% at the start of the turn, heals for .5x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 4: If HP is below 30% at the start of the turn, heals for .5x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 5: If HP is below 50% at the start of the turn, heals for 1x this character's RCV at the end of the turn each time you hit a Perfect" + ] + }, + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 30", + "Level 2: Boosts base ATK by 60", + "Level 3: Boosts base ATK by 90", + "Level 4: Boosts base ATK by 100", + "Level 5: Boosts base ATK by 150" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1707: {//Shanks 6+ + captain: "Boosts ATK of [PSY] characters by 2.75x and their HP by 1.3x. Boosts chances of getting [PSY] orbs proportionally to the crew's current HP.", + captainNotes: "At 1 HP, the rate of [PSY] orbs is ???% and at full HP, the rate of [PSY] orbs is ???%", + special: "Reduces the defense of all enemies by 100% for 1 turn, deals 75x character's ATK in typeless damage to one enemy and changes all orbs to [PSY] orbs", + specialName: "One-Armed Man that Splits the Heavens", + }, + 1708: {//Summer Nami + captain: "Recovers 3x character's RCV in HP at the end of each turn", + special: "Reduces Special Cooldown of Striker and Cerebral characters by 1 turn, reduces Paralysis duration by 2 turns, and randomizes all non-matching orbs", + specialName: "Cat Burglar's Eye Contact", + sailor: "Makes [TND] orbs \"beneficial\" for this unit", + }, + 1709: {//Summer Nami + captain: "Boosts ATK of all characters by 1.5x, recovers 4x character's RCV in HP at the end of each turn", + special: "Reduces Special Cooldown of Striker and Cerebral characters by 1 turn, reduces Paralysis duration by 2 turns, and randomizes all non-matching orbs", + specialName: "Cat Burglar's Eye Contact", + sailor: "Makes [TND] orbs \"beneficial\" for this unit", + }, + 1710: {//Summer Robin + captain: "Boosts ATK and RCV of Cerebral characters by 1.2x", + special: "Amplifies the effect of orbs for Cerebral characters by 1.75x for 1 turn and reduces damage received by 30% for 2 turns", + specialName: "Charmed by a Lovely Adult", + sailor: "Reduces Blindness duration by 2 turns", + }, + 1711: {//Summer Robin + captain: "Boosts RCV of Cerebral characters by 1.2x and boosts ATK by 3x if they have a matching orb, by 1.5x otherwise.", + special: "Amplifies the effect of orbs for Cerebral characters by 1.75x for 1 turn and reduces damage received by 30% for 2 turns", + specialName: "Charmed by a Lovely Adult", + sailor: "Reduces Blindness duration by 2 turns", + }, + 1712: {//Akainu + captain: "Boosts ATK of Driven characters by 2.5x.", + special: "Deals 50x character's ATK as typeless damage to all enemies. Amplifies the effect of orbs for Driven characters by 2x for 1 turn.", + specialName: "Blazing Hound Crimson Lotus", + }, + 1713: {//Akainu + captain: "Boosts ATK of Driven characters by 2.5x. If you defeat an enemy last turn, increases ATK boost slighty. Stacks up to 3 times to a maximum of 3.25x.", + captainNotes: "If a character dies and revives, it counts as killing a character. If you did not defeat an enemy, lose all ATK boost stacks.", + special: "Deals 50x character's ATK as typeless damage to all enemies. Amplifies the effect of orbs for Driven characters by 2x for 1 turn.", + specialName: "Blazing Hound Crimson Lotus", + limit: [ + { "description": "Boosts base ATK by 10" }, + { "description": "Boosts base ATK by 10" }, + { "description": "Boosts base ATK by 10" }, + { "description": "Aquire Potential 1: Enrage" }, + { "description": "Boosts base ATK by 10" }, + { "description": "Boosts base HP by 80" }, + { "description": "Boosts base ATK by 10" }, + { "description": "Boosts base ATK by 10" }, + { "description": "Aquire Sailor Ability 1: Makes [STR] orbs \"beneficial\" for this unit" }, + { "description": "Boosts base ATK by 10" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Boosts base HP by 100" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Aquire Sailor Ability 2: Makes [INT] orbs \"beneficial\" for Driven characters" }, + { "description": "Aquire Potential 2: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 20", + "Level 2: Boosts base ATK by 30", + "Level 3: Boosts base ATK by 40", + "Level 4: Boosts base ATK by 50", + "Level 5: Boosts base ATK by 100" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 1 turn on this character", + "Level 2: Reduces Slot Bind duration by 2 turns on this character", + "Level 3: Reduces Slot Bind duration by 3 turns on this character", + "Level 4: Reduces Slot Bind duration by 4 turns on this character", + "Level 5: Reduces Slot Bind duration by 5 turns on this character" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1714: {//Monet + captain: "Boosts ATK of INT characters by 2x. Recovers 2x character's RCV in HP at the end of each turn", + special: "Deals 10x character's ATK in [INT] damage to all enemies. Randomly changes all orbs into either [TND], [BOMB] or [RCV] orbs.", + specialName: "Devouring Blizzard", + }, + 1715: {//Vergo + captain: "Boosts ATK of Striker characters by 2.5x if they have a matching orb, by 2x otherwise", + special: "Changes own orb into [QCK], locks all orbs for 1 turn", + specialName: "Sealed Mouth Exterminator", + }, + 1716: {//Caesar + captain: "Reduces HP of all characters by 50%, boosts ATK of Driven characters by 1.2x, increases his own ATK multiplier by 0.1x at the end of each turn until it reaches 3x", + special: "Delays all enemies for 1 turn. For Driven characters, Changes [EMPTY] orbs into Matching orbs. Boosts ATK of Driven characters by 1.75x if HP is below 30% when the special is activated.", + specialName: "Massacre GAS", + }, + 1717: {//Vegapunk Dragon + captain: "Reduces cooldown of Shooter specials by 2 turns at the start of the fight", + special: "Deals 3x character's ATK in [QCK] damage to all enemies", + specialName: "High Maneuverable Fireball Blast", + }, + 1718: {//Buffalo + captain: "Boosts ATK of Driven characters by 2.5x until the first hit other than Perfect", + special: "Boosts ATK of Driven characters by 1.25x for 5 turns", + specialName: "Rolling Rotation", + }, + 1719: {//Baby 5 + captain: "Boosts ATK of [PSY] characters by 2x if they have matching orbs, makes INT orbs \"beneficial\" to PSY characters", + captainNotes: "#{beneficial}", + special: "Changes adjacent orbs into [G] orbs", + specialName: "Phantasmagoric \"Weapon-Morphosis\"", + }, + 1720: {//Secret Jinbe + captain: "Boosts ATK of Fighter characters by 2.5x", + special: "If your Captain is a Fighter character, changes adjacent orbs into matching orbs and locks the chain multiplier at 2.5x for 1 turn", + specialName: "Passive Agressive Boss" + }, + 1721: {//Secret Jinbe + captain: "Boosts HP of Fighter characters by 1.4x and boosts ATK by 2.75x if they have a matching orb, by 2.5x otherwise.", + special: "If your Captain is a Fighter character, changes adjacent orbs into matching orbs and locks the chain multiplier at 2.5x for 1 turn", + specialName: "Passive Agressive Boss", + limit: [ + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 40" }, + { "description": "Aquire Potential 1: Enrage" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base ATK by 15" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Boosts base HP by 80" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Aquire Sailor Ability 1: Makes [STR] and [DEX] orbs \"beneficial\" for this unit" }, + { "description": "Aquire Potential 2: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 20", + "Level 2: Boosts base ATK by 30", + "Level 3: Boosts base ATK by 40", + "Level 4: Boosts base ATK by 50", + "Level 5: Boosts base ATK by 100" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 1 turn on this character", + "Level 2: Reduces Slot Bind duration by 2 turns on this character", + "Level 3: Reduces Slot Bind duration by 3 turns on this character", + "Level 4: Reduces Slot Bind duration by 4 turns on this character", + "Level 5: Reduces Slot Bind duration by 5 turns on this character" + ] + }, + ] + + }, + 1722: {//Neptune + captain: "Boosts ATK of Striker characters by 2x.", + special: "Boosts ATK of Striker characters by 1.5x for 1 turn and Changes own orb into [PSY] if HP is below 30% when the special is activated and deals 20,000 Fixed damage to one enemy.", + specialName: "Sea God's Strike" + }, + 1723: {//Neptune + captain: "Boosts ATK of Striker characters by 2x and their RCV by 1.2x.", + special: "Boosts ATK of Striker characters by 1.5x for 1 turn and Changes own orb into [PSY] if HP is below 30% when the special is activated and deals 20,000 Fixed damage to one enemy.", + specialName: "Sea God's Strike" + }, + 1724: {//Fukaboshi + captain: "Boosts ATK of Powerhouse characters by 1.5x", + special: "Reduces crew's current HP by 50%, adds 25x character's ATK as Additional Typeless Damage for 1 turn", + specialNotes: "#{additionalDamage : 25x}", + specialName: "Sun's Hope" + }, + 1725: {//Fukaboshi + captain: "Slightly boosts chances Powerhouse characters of getting Matching orbs, boosts ATK of Powerhouse characters by 1.5x", + special: "Reduces crew's current HP by 50%, adds 25x character's ATK as Additional Typeless Damage for 1 turn", + specialNotes: "#{additionalDamage : 25x}", + specialName: "Sun's Hope" + }, + 1726: {//Sabo + captain: "Boosts ATK of Free Spirit characters by 2.75x following a chain of Good > Great > Perfect hits", + specialName: "Dragon Claw Fist: Dragon's Breath [Neo]", + special: "Deals random typeless damage to all enemies. Adds 55x character's ATK as Additional Typeless Damage for 2 turns", + specialNotes: "#{random : 10,000 : 30,000}
    Extra Damage can only be boosted by conditional Boosters" + }, + 1727: {//Sabo + captain: "Boosts ATK of Free Spirit characters by 3.5x following a chain of Good > Great > Perfect hits", + specialName: "Dragon Claw Fist: Dragon's Breath [Neo]", + special: "Deals random typeless damage to all enemies. Adds 55x character's ATK as Additional Typeless Damage for 2 turns", + specialNotes: "#{random : 10,000 : 30,000}
    Extra Damage can only be boosted by conditional Boosters" + }, + 1728: {//Tashigi + captain: "Boosts ATK of [STR], [DEX], and [QCK] characters by 2x", + special: "Randomly changes all orbs, includiong [BLOCK] orbs, into either [STR], [DEX] or [QCK] orbs, removes enemies' ATK Up Buffs, and recovers 2,000 HP", + sailor: "Boosts base ATK, HP and RCV of [STR], [DEX], and [QCK] characters by 30", + specialName: "Destructive Water Splash", + }, + 1729: {//Tashigi + captain: "Boosts ATK of [STR], [DEX], and [QCK] characters by 2.25x and their HP by 1.25x. Recovers 3x character's RCV in HP at the end of each turn", + special: "Randomly changes all orbs, includiong [BLOCK] orbs, into either [STR], [DEX] or [QCK] orbs, removes enemies' ATK Up Buffs, and recovers 2,000 HP", + sailor: "Boosts base ATK, HP and RCV of [STR], [DEX], and [QCK] characters by 30", + specialName: "Destructive Water Splash", + }, + 1730: {//Vivi + captain: "Boosts ATK of all characters by 2x", + special: "Reduces Special Cooldown of all characters by 2 turns, reduces Paralysis duration by 3 turns, reduces damage received by 60% for 2 turns", + sailor: "Restores her own special by 3 turns when it is rewinded", + sailorNotes: "#{rewind : 3}", + specialName: "Shining Brightly Upon the Oasis", + }, + 1731: {//Vivi + captain: "Boosts amount of Beli received by 2.5x and boosts ATK of all characters by 2x", + special: "Reduces Special Cooldown of all characters by 2 turns, reduces Paralysis duration by 3 turns, reduces damage received by 60% for 2 turns", + sailor: "Restores her own special by 3 turns when it is rewinded", + sailorNotes: "#{rewind : 3}", + specialName: "Shining Brightly Upon the Oasis", + }, + 1732: {//Nekomamushi + captain: "Boosts ATK of [STR] characters by 2x, boosts HP of Striker and Powerhouse characters by 1.1x", + special: "Deals 50x character's ATK in typeless damage to one enemy that will ignore damage negating abilities and barriers. If enemies have All Debuff Protection or Delay Debuff Protection at the time the special was activated, boosts ATK of Striker and Powerhouse characters by 1.75x for 1 turn and changes all orbs, including [BLOCK] orbs, into Matching orbs", + specialNotes: "#{ignoreBarrier}", + specialName: "Battle Guardian", + }, + 1733: {//Nekomamushi + captain: "Boosts ATK of [STR] characters by 2.5x, boosts HP of Striker and Powerhouse characters by 1.25x", + special: "Deals 50x character's ATK in typeless damage to one enemy that will ignore damage negating abilities and barriers. If enemies have All Debuff Protection or Delay Debuff Protection at the time the special was activated, boosts ATK of Striker and Powerhouse characters by 1.75x for 1 turn and changes all orbs, including [BLOCK] orbs, into Matching orbs", + specialNotes: "#{ignoreBarrier}", + specialName: "Battle Guardian", + }, + 1734: {//Sugar + captain: "Boosts ATK of Cerebral and Fighter characters by 1.5x and recovers 3x character's RCV in HP at the end of each turn", + special: "Changes bottom right orb to [STR] and bottom left orb to [INT]. Switches orbs between slots twice.", + specialName: "Toy's Close Combat", + }, + 1735: {//Sugar + captain: "Boosts ATK of Cerebral and Fighter characters by 1.75x and recovers 3x character's RCV in HP at the end of each turn", + special: "Changes bottom right orb to [STR] and bottom left orb to [INT]. Switches orbs between slots twice.", + specialName: "Toy's Close Combat", + }, + 1736: {//Trebol + captain: "Boosts ATK of [INT] characters by 2.25x. Reduces damage received by 10%", + special: "Delays all enemies for 1 turn and deals 20x character's ATK as [INT] damage to all enemies at the end of the turn for 2 turns", + specialName: "Sticky Sticky Burning Explosion", + }, + 1737: {//Trebol + captain: "Boosts ATK of [INT] characters by 2.25x and their HP by 1.2x. Reduces damage received by 10%", + special: "Delays all enemies for 1 turn and deals 20x character's ATK as [INT] damage to all enemies at the end of the turn for 2 turns", + specialName: "Sticky Sticky Burning Explosion", + }, + 1738: {//Raid Bellamy + captain: "Boosts ATK of Driven characters by 2x", + special: "Cuts the current HP of one enemy by 10%, makes [PSY] and [INT] orbs \"beneficial\" for 1 turn and amplifies the effect of orbs by 1.75x for 1 turn", + specialName: "Spring Hopper - Bullet [Neo]", + }, + 1739: {//Raid Bellamy + captain: "Boosts ATK of Driven characters by 2.5x", + special: "Cuts the current HP of one enemy by 10%, makes [PSY] and [INT] orbs \"beneficial\" for 1 turn and amplifies the effect of orbs by 1.75x for 1 turn", + specialName: "Spring Hopper - Bullet [Neo]", + }, + 1740: {//Sandersonia + captain: "Boosts ATK of Striker and Powerhouse characters by 2x and boosts HP of [DEX] characters by 1.1x", + special: "Changes all orbs to [DEX] orbs, reduces the defense of all enemies by 80% for 2 turns, and boosts ATK of Striker and Powerhouse characters by 1.75x for 2 turns", + sailor: "Makes [STR] orbs \"beneficial\" for this unit", + specialName: "Snake Hair Possession: Eight-Headed Serpent", + }, + 1741: {//Sandersonia + captain: "Boosts ATK of Striker and Powerhouse characters by 2.5x and boosts HP of [DEX] characters by 1.3x", + special: "Changes all orbs to [DEX] orbs, reduces the defense of all enemies by 80% for 2 turns, and boosts ATK of Striker and Powerhouse characters by 1.75x for 2 turns", + sailor: "Makes [STR] orbs \"beneficial\" for this unit", + specialName: "Snake Hair Possession: Eight-Headed Serpent", + limit: [ + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Aquire Potential 1: Enrage" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base HP by 70" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Aquire Sailor Ability 1: Boosts this character's attack against [STR] characters by 2x" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base HP by 90" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Reduce No Healing duration" }, + ], + potential: [ + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 20", + "Level 2: Boosts base ATK by 40", + "Level 3: Boosts base ATK by 60", + "Level 4: Boosts base ATK by 80", + "Level 5: Boosts base ATK by 100" + ] + }, + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: Reduces No Healing duration by 1 turn", + "Level 2: Reduces No Healing duration by 1 turn", + "Level 3: Reduces No Healing duration by 1 turn", + "Level 4: Reduces No Healing duration by 2 turns", + "Level 5: Reduces No Healing duration by 3 turns" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1742: {//Marigold + captain: "Boosts ATK of Striker and Powerhouse characters by 2x and boosts HP of [STR] characters by 1.1x", + special: "Changes [QCK] and [DEX] orbs into Matching orbs, boosts ATK against enemies with reduced defense by 1.75x for 2 turns and reduces damage received by 60% for 1 turn", + sailor: "Makes [DEX] orbs \"beneficial\" for this unit", + specialName: "Snake Hair Possession: Salamander", + }, + 1743: {//Marigold + captain: "Boosts ATK of Striker and Powerhouse characters by 2.5x and boosts HP of [STR] characters by 1.3x", + special: "Changes [QCK] and [DEX] orbs into Matching orbs, boosts ATK against enemies with reduced defense by 1.75x for 2 turns and reduces damage received by 60% for 1 turn", + sailor: "Makes [DEX] orbs \"beneficial\" for this unit", + specialName: "Snake Hair Possession: Salamander", + limit: [ + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Aquire Potential 1: Enrage" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base HP by 70" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Aquire Sailor Ability 1: Boosts this character's attack against [QCK] characters by 2x" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base HP by 90" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Reduce No Healing duration" }, + ], + potential: [ + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 20", + "Level 2: Boosts base ATK by 40", + "Level 3: Boosts base ATK by 60", + "Level 4: Boosts base ATK by 80", + "Level 5: Boosts base ATK by 100" + ] + }, + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: Reduces No Healing duration by 1 turn", + "Level 2: Reduces No Healing duration by 1 turn", + "Level 3: Reduces No Healing duration by 1 turn", + "Level 4: Reduces No Healing duration by 2 turns", + "Level 5: Reduces No Healing duration by 3 turns" + ] + }, + ] + }, + 1744: {//Marguerite + captain: "Boosts ATK of Shooter characters by 2x", + special: "Cuts the current HP of one enemy by 7% and amplifies the effect of orbs for Shooter characters by 1.75x for 3 turns", + sailor: "Boosts base ATK, HP and RCV of Shooter characters by 30", + specialName: "Defender's Spade-Shaped Arrow", + }, + 1745: {//Marguerite + captain: "Boosts ATK of Shooter characters by 2x and recovers 2x character's RCV in HP at the end of each turn", + special: "Cuts the current HP of one enemy by 7% and amplifies the effect of orbs for Shooter characters by 1.75x for 3 turns", + sailor: "Boosts base ATK, HP and RCV of Shooter characters by 30", + specialName: "Defender's Spade-Shaped Arrow", + limit: [ + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Aquire Potential 1: Reduce No Healing duration" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Aquire Sailor Ability 1: Reduces Blindness duration by 3 turns" }, + { "description": "Boosts base HP by 70" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Barrier Penetration" }, + ], + potential: [ + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: If there are 6 Shooter characters in your crew, reduces No Healing duration by 1 turn", + "Level 2: If there are 5 Shooter characters in your crew, reduces No Healing duration by 1 turn", + "Level 3: If there are 4 Shooter characters in your crew, reduces No Healing duration by 1 turn", + "Level 4: If there are 4 Shooter characters in your crew, reduces No Healing duration by 2 turns", + "Level 5: If there are 4 Shooter characters in your crew, reduces No Healing duration by 3 turns" + ] + }, + { + "Name": "Barrier Penetration", + "description": [ + "Level 1: This character's attack will ignore barriers if HP is above 99%", + "Level 2: This character's attack will ignore barriers if HP is above 99%", + "Level 3: This character's attack will ignore barriers if HP is above 99%", + "Level 4: This character's attack will ignore barriers if HP is above 80%", + "Level 5: This character's attack will ignore barriers if HP is above 50%" + ] + }, + ] + }, + 1746: {//Boa Hancock + captain: "Boosts ATK of Shooter characters by a variable factor between 2.5x and 3.25x based on the timing of the attack of the previous unit in the chain and recovers 1,000 HP at end of each turn. Greatly reduces chances of getting [TND] / [RCV] orbs", + special: "Deals 6 hits of 20,000 fixed damage to random enemies, delays all enemies for 1 turn and makes [STR], [DEX], [QCK], [PSY] and [INT] orbs \"beneficial\" for Shooter characters for 2 turns", + specialName: "Pistol Kisses", + }, + 1747: {//Boa Hancock + captain: "Boosts ATK of Shooter characters by a variable factor between 2.5x and 3.25x based on the timing of the attack of the previous unit in the chain and recovers 1,000 HP at end of each turn. Greatly reduces chances of getting [TND] / [RCV] orbs", + special: "Deals 6 hits of 20,000 fixed damage to random enemies, delays all enemies for 1 turn and makes [STR], [DEX], [QCK], [PSY] and [INT] orbs \"beneficial\" for Shooter characters for 2 turns", + specialName: "Pistol Kisses", + limit: [ + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Aquire Potential 1: Pinch Healing" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Aquire Sailor Ability 1: Makes [STR], [QCK], [DEX], [PSY] and [INT] orbs \"beneficial\" for this unit if your Captain is a Free Spirit character" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Aquire Potential 2: Barrier Penetration" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Boosts base HP by 70" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base HP by 80" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base HP by 90" }, + { "description": "Aquire Potential 3: Reduce No Healing duration" }, + ], + potential: [ + { + "Name": "Pinch Healing", + "description": [ + "Level 1: If HP is below 10% at the start of the turn, heals for 2x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 2: If HP is below 15% at the start of the turn, heals for 2x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 3: If HP is below 20% at the start of the turn, heals for 2x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 4: If HP is below 30% at the start of the turn, heals for 2x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 5: If HP is below 50% at the start of the turn, heals for 2x this character's RCV at the end of the turn each time you hit a Perfect" + ] + }, + { + "Name": "Barrier Penetration", + "description": [ + "Level 1: This character's attack will ignore barriers if HP is above 99%", + "Level 2: This character's attack will ignore barriers if HP is above 99%", + "Level 3: This character's attack will ignore barriers if HP is above 99%", + "Level 4: This character's attack will ignore barriers if HP is above 80%", + "Level 5: This character's attack will ignore barriers if HP is above 50%" + ] + }, + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: Reduces No Healing duration by 1 turn", + "Level 2: Reduces No Healing duration by 2 turns", + "Level 3: Reduces No Healing duration by 3 turns", + "Level 4: Reduces No Healing duration by 4 turns", + "Level 5: Reduces No Healing duration by 5 turns" + ] + }, + ] + }, + 1748: {//Bepo + captain: "Boosts ATK and HP of QCK characters by 1.5x", + special: "Cuts the current HP of one enemy by 15% and reduces enemy's Threshold Damage Reduction duration by 5 turns", + sailor: "If Bepo has a [QCK] orb and you hit a Perfect with him, keep his [QCK] orb for the next turn", + specialName: "Bear Rush Out", + }, + 1749: {//Bepo + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK and HP of QCK characters by 2x", + special: "Cuts the current HP of one enemy by 15% and reduces enemy's Threshold Damage Reduction duration by 5 turns", + sailor: "If Bepo has a [QCK] orb and you hit a Perfect with him, keep his [QCK] orb for the next turn", + specialName: "Bear Rush Out", + limit: [ + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base ATK by 10" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Aquire Sailor Ability #: Makes [DEX] orbs \"beneficial\" for this unit" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base HP by 90" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 10% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 15% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 20% chance to deal 10% of this character's attack in extra damage" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 1 turn on this character", + "Level 2: Reduces Slot Bind duration by 2 turns on this character", + "Level 3: Reduces Slot Bind duration by 3 turns on this character", + "Level 4: Reduces Slot Bind duration by 5 turns on this character", + "Level 5: Reduces Slot Bind duration by 10 turns on this character" + ] + }, + ] + }, + 1750: {//Korea Law + captain: "Boosts ATK of Striker characters by 3x and heals for .5x his RCV at the end of the turn each time you hit a Perfect", + special: [ + { + "description": "Deals 50,000 fixed damage to one enemy, and for Striker characters, amplifies the effect of orbs by 1.75x for 1 turn", + "cooldown": [ 15, 10 ] + }, + { + "description": "Deals 300,000 fixed damage to one enemy, and for Striker characters, amplifies the effect of orbs by 2.25x for 1 turn", + "cooldown": [ 20, 15 ] + } + ], + specialNotes:"#{stages}", + specialName: "Injection Shot", + }, + 1751: {//Korea Law + captain: "Boosts ATK of Striker characters by 3x and heals for .5x his RCV at the end of the turn each time you hit a Perfect", + special: [ + { + "description": "Deals 50,000 fixed damage to one enemy, and for Striker characters, amplifies the effect of orbs by 1.75x for 1 turn", + "cooldown": [ 15, 10 ] + }, + { + "description": "Deals 300,000 fixed damage to one enemy, and for Striker characters, amplifies the effect of orbs by 2.25x for 1 turn", + "cooldown": [ 20, 15 ] + } + ], + specialNotes:"#{stages}", + specialName: "Injection Shot", + limit: [ + { "description": "Boosts base ATK by 10" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Aquire Potential 1: Pinch Healing" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK of Striker characters by 50" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base HP by 40" }, + { "description": "Aquire Potential 2: Reduce No Healing Duration" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base HP by 50" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Boosts base HP by 70" }, + { "description": "Boosts base HP by 70" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Aquire Sailor Ability 2: Makes [RCV] and [TND] orbs \"beneficial\" for this unit" }, + { "description": "Boosts base HP by 90" }, + { "description": "Aquire Potential 3: Barrier Penetration" }, + ], + potential: [ + { + "Name": "Pinch Healing", + "description": [ + "Level 1: If HP is below 10% at the start of the turn, heals for 2x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 2: If HP is below 15% at the start of the turn, heals for 2x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 3: If HP is below 20% at the start of the turn, heals for 2x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 4: If HP is below 30% at the start of the turn, heals for 2x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 5: If HP is below 50% at the start of the turn, heals for 2x this character's RCV at the end of the turn each time you hit a Perfect" + ] + }, + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: Reduces No Healing duration by 1 turn", + "Level 2: Reduces No Healing duration by 1 turn", + "Level 3: Reduces No Healing duration by 2 turns", + "Level 4: Reduces No Healing duration by 2 turns", + "Level 5: Reduces No Healing duration by 3 turns" + ] + }, + { + "Name": "Barrier Penetration", + "description": [ + "Level 1: This character's attack will ignore barriers if HP is above 99%", + "Level 2: This character's attack will ignore barriers if HP is above 80%", + "Level 3: This character's attack will ignore barriers if HP is above 70%", + "Level 4: This character's attack will ignore barriers if HP is above 50%", + "Level 5: This character's attack will ignore barriers" + ] + }, + ] + }, + 1752: {//20th Anni Zoro + captain: "Boosts ATK of characters with cost 30 or less by 2.5x", + special: "Deals 60x character's ATK in [INT] damage to one enemy. Boosts ATK of characters with 30 cost or less by 1.75x for 1 turn. If Zoro is a Capain or Friend/Guest Captain, then if during that turn you score 4 Perfect hits, boosts ATK of characters with 30 cost or less by 2x in the following turn.", + sailor: "Boosts base ATK of Slasher characters by 50", + specialName: "Three Sword Style: Ultra Tiger Hunting", + }, + 1753: {//20th Anni Zoro + captain: "Boosts HP of characters with cost 30 or less by 1.3x and boosts ATK of characters with cost 30 or less by 2.5x at the start of the chain, 3.5x after the 3rd Perfect in a row", + special: "Deals 60x character's ATK in [INT] damage to one enemy. Boosts ATK of characters with 30 cost or less by 1.75x for 1 turn. If Zoro is a Capain or Friend/Guest Captain, then if during that turn you score 4 Perfect hits, boosts ATK of characters with 30 cost or less by 2x in the following turn.", + sailor: "Boosts base ATK of Slasher characters by 50", + specialName: "Three Sword Style: Ultra Tiger Hunting", + }, + 1754: {//20th Anni Sanji + captain: "Boosts ATK of Fighter and Powerhouse characters by 2x", + special: "Cuts the current HP of one enemy by 15%, removes Poison and amplifies the effects of orbs by 1.75x for 1 turn", + sailor: "Boosts base ATK, HP and RCV of all characters by 40", + specialName: "Diable Jambe: Collier Strike", + }, + 1755: {//20th Anni Sanji + captain: "Boosts ATK of Fighter and Powerhouse characters by 2.5x and their HP by 1.2x", + special: "Cuts the current HP of one enemy by 15%, removes Poison and amplifies the effects of orbs by 1.75x for 1 turn", + sailor: "Boosts base ATK, HP and RCV of all characters by 40", + specialName: "Diable Jambe: Collier Strike", + }, + 1756: {//20th Anni Nami + captain: "Recovers 2x character's RCV in HP at the end of each turn", + special: "Reduces damage received by 80% for 1 turn, reduces enemy's Threshold Damage Reduction and ATK UP duration by 3 turns", + sailor: "Makes [DEX] orbs \"beneficial\" for this unit", + specialName: "Gust Sword", + }, + 1757: {//20th Anni Nami + captain: "Recovers 5x character's RCV in HP at the end of each turn", + special: "Reduces damage received by 80% for 1 turn, reduces enemy's Threshold Damage Reduction and ATK UP duration by 3 turns", + sailor: "Makes [DEX] orbs \"beneficial\" for this unit", + specialName: "Gust Sword", + }, + 1758: {//20th Anni Brook + captain: "Boosts ATK of Free Spirit characters by 2x and their HP by 1.1x", + special: "Delays all enemies for 1 turn, reduces Paralysis, Bind and Despair duration by 1 turn.", + sailor: "Makes [RCV] orbs \"beneficial\" for this unit", + specialName: "Party Music: Quinte Tierce Fantasia", + }, + 1759: {//20th Anni Brook + captain: "Boosts ATK of Free Spirit characters by 2.5x and their HP by 1.2x", + special: "Delays all enemies for 1 turn, reduces Paralysis, Bind and Despair duration by 1 turn.", + sailor: "Makes [RCV] orbs \"beneficial\" for this unit", + specialName: "Party Music: Quinte Tierce Fantasia", + }, + 1760: {//20th Anni Chopper + captain: "Boosts ATK of [DEX] and [INT] characters by 2x", + special: "Changes the orbs in the left column into [INT], [RCV] and [DEX], the orbs in the right column into [INT], [PSY] and [DEX]", + sailor: "Restores his own special by 2 turns when it is rewinded and reduces Silence duration on this character by 2 turns", + sailorNotes: "#{silence}
    #{rewind : 2}", + specialName: "Intelligent Monster", + }, + 1761: {//20th Anni Chopper + captain: "Boosts ATK of [DEX] and [INT] characters by 2.5x", + special: "Changes the orbs in the left column into [INT], [RCV] and [DEX], the orbs in the right column into [INT], [PSY] and [DEX]", + sailor: "Restores his own special by 2 turns when it is rewinded and reduces Silence duration on this character by 2 turns", + sailorNotes: "#{silence}
    #{rewind : 2}", + specialName: "Intelligent Monster", + }, + 1762: {//Rob Lucci + captain: "Boosts ATK of Powerhouse characters by 2.5x and their HP by 1.2x at the start of the chain. Reduces RCV of all characters by 50%.
    Boosts ATK of Powerhouse characters by 2.75x after the 1st Perfect in a row, by 3.025x after the 2nd Perfect in a row, by 3.3275x after the 3rd Perfect in a row, by 3.66025x after the 4th Perfect in a row, and by 4.026275x after the 5th Perfect in a row.", + special: "Reduces the defense of all enemies by 80% for 2 turns, deals 50x character's ATK in typeless damage to all enemies and changes all orbs on Powerhouse characters into Matching orbs, recover 20% of crew's MAX HP.", + specialName: "Flying Finger Gun: Fire Sting", + }, + 1763: {//Rob Lucci + captain: "Boosts ATK of Powerhouse characters by 2.5x and their HP by 1.2x at the start of the chain. Reduces RCV of all characters by 50%.
    Boosts ATK of Powerhouse characters by 2.75x after the 1st Perfect in a row, by 3.025x after the 2nd Perfect in a row, by 3.3275x after the 3rd Perfect in a row, by 3.66025x after the 4th Perfect in a row, and by 4.026275x after the 5th Perfect in a row.", + special: "Reduces the defense of all enemies by 80% for 2 turns, deals 50x character's ATK in typeless damage to all enemies and changes all orbs on Powerhouse characters into Matching orbs, recover 20% of crew's MAX HP.", + specialName: "Flying Finger Gun: Fire Sting", + limit: [ + { "description": "Boosts base ATK by 10" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Aquire Potential 1: Pinch Healing" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK of Powerhouse characters by 50" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base HP by 40" }, + { "description": "Aquire Potential 2: Enrage" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base HP by 50" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Boosts base HP by 70" }, + { "description": "Boosts base HP by 70" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Aquire Sailor Ability 2: Makes [RCV] and [TND] orbs \"beneficial\" for this unit" }, + { "description": "Boosts base HP by 90" }, + { "description": "Aquire Potential 3: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "Pinch Healing", + "description": [ + "Level 1: If HP is below 10% at the start of the turn, heals for 2x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 2: If HP is below 15% at the start of the turn, heals for 2x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 3: If HP is below 20% at the start of the turn, heals for 2x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 4: If HP is below 30% at the start of the turn, heals for 2x this character's RCV at the end of the turn each time you hit a Perfect", + "Level 5: If HP is below 50% at the start of the turn, heals for 2x this character's RCV at the end of the turn each time you hit a Perfect" + ] + }, + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 30", + "Level 2: Boosts base ATK by 60", + "Level 3: Boosts base ATK by 90", + "Level 4: Boosts base ATK by 100", + "Level 5: Boosts base ATK by 150" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 3 turn on this character", + "Level 2: Reduces Slot Bind duration by 5 turns on this character", + "Level 3: Reduces Slot Bind duration by 7 turns on this character", + "Level 4: Reduces Slot Bind duration by 10 turns on this character", + "Level 5: Reduces Slot Bind completely on this character" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1764: {//6+ Aokiji + captain: "Boosts ATK of all characters by 2.25x and their HP by 1.25x. If you defeat an enemy, increases ATK boost slighty. Stacks up to 5 times to a maximum of 3.5x.", + captainNotes: "If a character dies and revives, it counts as killing a character. If you did not defeat an enemy, lose all ATK boost stacks.", + special: "Increases duration of any Class/Type boosting buffs and Orb Amplification buffs by 1 turn, locks the chain multiplier at 2.5x for 1 turn and deals 100000 fixed damage to all enemies that will ignore damage negating abilities and barriers.", + specialNotes: "#{ignoreBarrier}", + specialName: "Determined Man's Ice Attack", + }, + 1765: {//Blue Gilly + captain: "Boosts ATK of Fighter characters by 1.5x", + special: "Deals 10 hits of 5x character's ATK in typeless damage to random enemies, reduces the defense of all enemies by 50% for 1 turn, randomizes non-matching orbs, including [BLOCK] orbs", + specialName: "Jao Kun Do Consecutive Thrusting Kick", + }, + 1766: {//Blue Gilly + captain: "Boosts chain multiplier by 1.5x and boosts ATK of Fighter characters by 1.5x", + special: "Deals 10 hits of 5x character's ATK in typeless damage to random enemies, reduces the defense of all enemies by 50% for 1 turn, randomizes non-matching orbs, including [BLOCK] orbs", + specialName: "Jao Kun Do Consecutive Thrusting Kick", + }, + 1767: {//Funk Bros + captain: "Boosts ATK of Fighter characters by 1.75x", + special: "Delays all enemies for 1 turn, following the activation of the special, if every unit scores a Great hit, boosts ATK of Fighter characters by 1.5x in the following turn", + specialName: "Prideless Surprise Attack", + }, + 1768: {//Abdullah and Jeet + captain: "Boosts ATK of Striker and Slasher characters by 1.5x", + special: "At the end of the turn, cuts the current HP of each enemy by 10% for 2 turns", + specialName: "Nasty Final Blow", + }, + 1769: {//Ben Beckman + captain: "Boosts ATK of Cerebral characters by 2.5x", + special: "Delays all enemies for 1 turn. If your captain is a Cerebral Character, boosts ATK against delayed enemies by 1.5x for 1 turn and changes adjacent orbs into Matching Orbs", + specialName: "Restraining Gunpoint", + }, + 1770: {//Ben Beckman + captain: "Boosts ATK of Cerebral characters by 2.5x and their HP by 1.2x at the start of the chain, and boosts ATK of Cerebral characters by 3.25x following a chain of Good > Great > Perfect hits", + special: "Delays all enemies for 1 turn. If your captain is a Cerebral Character, boosts ATK against delayed enemies by 1.5x for 1 turn and changes adjacent orbs into Matching Orbs", + specialName: "Restraining Gunpoint", + limit: [ + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Aquire Sailor Ability 1: Reduces Blindness duration by 3 turns" }, + { "description": "Boosts base HP by 50" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Aquire Sailor Ability 2: Adds 2x character's ATK as Additional Typeless Damage" }, + { "description": "Aquire Potential 2: Enrage" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 10% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 15% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 20% chance to deal 10% of this character's attack in extra damage" + ] + }, + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 30", + "Level 2: Boosts base ATK by 50", + "Level 3: Boosts base ATK by 80", + "Level 4: Boosts base ATK by 100", + "Level 5: Boosts base ATK by 150" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1771: {//Kuma + captain: "Boosts ATK and HP of Cerebral characters by 2x", + specialName: "Thrust Pad Cannon [Neo]", + special: "Changes [RCV], [TND], [EMPTY], [BLOCK] and [BOMB] orbs into Matching orbs, amplifies the effect of orbs by 1.75x for 1 turn", + specialNotes: "#{orb : 1.75x}" + }, + 1772: {//Kuma + captain: "Boosts ATK and HP of Cerebral characters by 2x, deals 5 times the damage received in the previous turn in [INT] damage to all enemies at the end of each turn", + specialName: "Thrust Pad Cannon [Neo]", + special: "Changes [RCV], [TND], [EMPTY], [BLOCK] and [BOMB] orbs into Matching orbs, amplifies the effect of orbs by 1.75x for 1 turn", + specialNotes: "#{orb : 1.75x}" + }, + 1773: {//Kinemon + captain: "Boosts ATK of Free Spirit characters by 2x and their HP by 1.2x and reduces damage received by 10%", + special: "Deals 20x character's ATK in [INT] damage to one enemy, amplifies the effect of orbs for Free Spirit characters by 1.5x for 1 turn", + sailor: "Boosts base ATK of Free Spirit characters by 25" + }, + 1774: {//Kinemon + captain: "Boosts ATK of Free Spirit characters by 2.25x and their HP by 1.25x and reduces damage received by 15%", + special: "Deals 20x character's ATK in [INT] damage to one enemy, amplifies the effect of orbs for Free Spirit characters by 1.75x for 1 turn", + sailor: "Boosts base ATK of Free Spirit characters by 25" + }, + 1775: {//Momonosuke + captain: "Boosts ATK and RCV of QCK characters by 1.5x, and slightly boosts chances of getting [QCK] orbs", + special: "Reduces damage received by 50% for 1 turn and switches orbs between slots twice", + }, + 1776: {//Momonosuke + captain: "Boosts ATK and RCV of QCK characters by 1.75x, boosts chances of getting [QCK] orbs", + special: "Reduces damage received by 50% for 1 turn and switches orbs between slots twice", + }, + 1777:{//Kizaru + captain: "Not Translated", + special: "Deals 50x character's ATK in typeless damage to one enemy that will ignore damage negating abilities and barriers, changes [BLOCK], [STR], and [INT] orbs into Matching orbs for Free Spirit characters and adds .2x to Chain multiplier for 3 turns", + specialName: "Devil Destroyer's Light Arrow", + specialNotes: "#{ignoreBarrier}" + }, + 1778:{//Kizaru + captain: "Boosts ATK of Free Spirit characters by 2.5x, and their HP by 1.2x. Recovers 1.5x character's RCV in HP at the end of each turn", + special: "Deals 50x character's ATK in typeless damage to one enemy that will ignore damage negating abilities and barriers, changes [BLOCK], [STR], and [INT] orbs into Matching orbs for Free Spirit characters and adds .2x to Chain multiplier for 3 turns", + specialName: "Devil Destroyer's Light Arrow", + specialNotes: "#{ignoreBarrier}", + limit: [ + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Aquire Sailor Ability 1: Makes [DEX] orbs \"beneficial\" for this unit" }, + { "description": "Boosts base HP by 50" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Aquire Sailor Ability 2: Boosts base ATK, HP and RCV of Shooter and Free Spirit characters by 50" }, + { "description": "Aquire Potential 2: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 10% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 15% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 20% chance to deal 10% of this character's attack in extra damage" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 1 turn on this character", + "Level 2: Reduces Slot Bind duration by 2 turns on this character", + "Level 3: Reduces Slot Bind duration by 3 turns on this character", + "Level 4: Reduces Slot Bind duration by 4 turns on this character", + "Level 5: Reduces Slot Bind duration by 5 turns on this character" + ] + }, + ] + }, + 1779:{//Kizaru + captain: "Boosts ATK of Shooter characters by 2x", + specialName: "Yata no Kagami (Sacred Mirror) Neo", + special: [ + { + "description": "Changes own orb into [DEX]. Reduces Special Cooldown of Shooter and Fighter specials by 1 turn", + "cooldown": [ 14, 5 ] + }, + { + "description": "Changes own orb into [DEX]. Reduces Special Cooldown of Shooter and Fighter specials by 1 turn. Adds .5x to Chain multiplier for 2 turns", + "cooldown": [ 20, 11 ] + } + ], + specialNotes: "#{stages}" + }, + 1780:{//Kizaru + captain: "Reduces cooldown of Shooter specials by 2 turns at the start of the fight, boosts ATK of Shooter characters by 2.25x and boosts HP of Shooter characters by 1.5x", + specialName: "Yata no Kagami (Sacred Mirror) Neo", + special: [ + { + "description": "Changes own orb into [DEX]. Reduces Special Cooldown of Shooter and Fighter specials by 1 turn", + "cooldown": [ 14, 5 ] + }, + { + "description": "Changes own orb into [DEX]. Reduces Special Cooldown of Shooter and Fighter specials by 1 turn. Adds .5x to Chain multiplier for 2 turns", + "cooldown": [ 20, 11 ] + } + ], + specialNotes: "#{stages}", + }, + 1781: {//Fighting Fish + captain: "Boosts ATK of Powerhouse characters by 1.75x. Makes [TND] and [RCV] orbs \"beneficial\" to Powerhouse characters", + special: "Boosts ATK of ??? characters by 1.3x for 1 turn, changes own orb into STR and deals 5x character's ATK in [STR] damage to all enemies", + specialName: "Fish Special", + }, + 1782: {//Chinjao + captain: "Boosts ATK of [QCK] characters by 2.25x, boosts damage of QCK specials by 1.75x", + captainNotes: "#{noFixedPerc}", + special: "Delays all enemies for 2 turns, deals 25x character's ATK in [QCK] damage to all enemies", + specialName: "Chinjao Special", + }, + 1783: {//Hajrudin + captain: "Boosts ATK and HP of Powerhouse characters by 1.5x", + special: "Locks all orbs for 1 turn. If during that turn you score 4 Perfect hits, amplifies the effect of orbs by 1.5x for 1 turn.", + specialName: "Hajrudin Special", + }, + 1784: {//Fujitora + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of characters with fewer than 4 stars by 2.5x", + special: "Deals random [INT] damage to all enemies, reduces Special Cooldown of all characters by 1 turn and boosts ATK of all characters by 1.5x for 1 turn", + specialName: "Fujitora Special", + }, + 1785: {//Spartan + captain: "Recovers 3x character's RCV in HP at the end of each turn", + special: "Recovers 3000 HP and amplifies the effect of orbs by 1.25x for 1 turn", + specialName: "Spartan Special", + }, + 1786: {//Dressrosa Fodder + special: "Makes [QCK] orbs \"beneficial\" to Shooter characters for 1 turn", + specialName: "Shooter Beneficial Slot: [QCK]" + }, + 1787: {//Dressrosa Fodder + special: "Reduces crew's current HP by 50%, deals 5x the amount of HP subtracted in typeless damage to one enemy", + specialName: "Risky Attack" + }, + 1788: {//Dressrosa Fodder + special: "Boosts ATK of Shooter characters by 1.2x for 1 turn", + specialName: "Attack Boost: Shooter" + }, + 1789: {//Dressrosa Fodder + special: "Boosts chances of getting [RCV] orbs for 2 turns", + specialName: "Meat for Meat", + }, + 1790: {//Dressrosa Fodder + special: "Recovers 3x character's RCV in HP at the end of each turn for 3 turns", + specialName: "Auto Light Recovery" + }, + 1791:{//Lucy Luffy + captain: "Boosts ATK of [STR], [DEX] and [QCK] characters by 2.5x after scoring 3 Perfects in a row", + special: "Cuts the current HP of one enemy by 20% that will ignore damage negating abilities and barriers. Changes the orbs in the top row into [STR] orbs, changes the orbs in the middle row into [QCK] orbs, changes the orbs in the bottom row into [DEX] orbs and amplifies the effect of orbs by 1.75x for 1 turn", + specialNotes: "#{ignoreBarrier}", + sailor: "If you captain is a [STR] character, boosts this character's attack against [STR] characters by 1.5x", + specialName: "Gomu Gomu no Hawk Rifle", + }, + 1792:{//Lucy Luffy + captain: "Boosts RCV of [STR], [DEX] and [QCK] characters by 1.2x and boosts ATK of [STR], [DEX] and [QCK] characters by 3.25x after scoring 3 Perfects in a row", + special: "Cuts the current HP of one enemy by 20% that will ignore damage negating abilities and barriers. Changes the orbs in the top row into [STR] orbs, changes the orbs in the middle row into [QCK] orbs, changes the orbs in the bottom row into [DEX] orbs and amplifies the effect of orbs by 1.75x for 1 turn", + specialNotes: "#{ignoreBarrier}", + sailor: "If you captain is a [STR] character, boosts this character's attack against [STR] characters by 1.5x", + specialName: "Gomu Gomu no Hawk Rifle", + limit: [ + { "description": "Boosts base ATK by 10" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK and HP of STR, DEX, and QCK characters by 75 if your Captain is a [STR] character" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Aquire Potential 2: Enrage" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 20% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 30% chance to deal 3% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 30% chance to deal 3% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 50% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 50% chance to deal 7% of this character's attack in extra damage" + ] + }, + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 30", + "Level 2: Boosts base ATK by 60", + "Level 3: Boosts base ATK by 90", + "Level 4: Boosts base ATK by 120", + "Level 5: Boosts base ATK by 150" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1793:{//Lucy Sabo + captain: "If there is a [STR], [DEX] and [QCK] character in your crew, boosts ATK of [STR], [DEX] and [QCK] characters by 2.75x and their HP by 1.3x, lowers chances of getting [STR] orbs and makes [DEX] and [QCK] orbs \"beneficial\" to [STR], [DEX] and [QCK] characters. If there are not [PSY] or [INT] characters on your crew, boosts ATK by 3.7125x instead.", + captainNotes: "Sabo boosts ATK by 3.7125x if you have [STR], [DEX] and [QCK] type characters, and no [PSY] or [INT] characters at all.
    #{beneficial}", + special: "Boosts ATK of [STR], [DEX] and [QCK] characters by 1.75x for 1 turn. If during that turn you score 4 Perfect hits, boosts ATK of [STR], [DEX] and [QCK] characters by 2x in the following turn.", + specialName: "Dragon's Claw: Reverse Wave Motion", + }, + 1794:{//Lucy Sabo + captain: "If there is a [STR], [DEX] and [QCK] character in your crew, boosts ATK of [STR], [DEX] and [QCK] characters by 2.75x and their HP by 1.3x, lowers chances of getting [STR] orbs and makes [DEX] and [QCK] orbs \"beneficial\" to [STR], [DEX] and [QCK] characters. If there are not [PSY] or [INT] characters on your crew, boosts ATK by 3.7125x instead.", + captainNotes: "Sabo boosts ATK by 3.7125x if you have [STR], [DEX] and [QCK] type characters, and no [PSY] or [INT] characters at all.
    #{beneficial}", + special: "Boosts ATK of [STR], [DEX] and [QCK] characters by 1.75x for 1 turn. If during that turn you score 4 Perfect hits, boosts ATK of [STR], [DEX] and [QCK] characters by 2x in the following turn.", + specialName: "Dragon's Claw: Reverse Wave Motion", + limit: [ + { "description": "Boosts base ATK by 10" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base RCV by 5" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base RCV by 5" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base ATK by 10" }, + { "description": "Aquire Sailor Ability 1: Restores his own special by 2 turns when it is rewinded" }, + { "description": "Boosts base HP by 35" }, + { "description": "Boosts base HP by 45" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base ATK by 15" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Aquire Potential 2: Enrage" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base HP by 75" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base ATK by 35" }, + { "description": "Boosts base HP by 85" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base RCV by 25" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base ATK by 35" }, + { "description": "Aquire Sailor Ability 2: Boosts base ATK, HP and RCV of [STR], [DEX], and [QCK] characters by 50" }, + { "description": "Boosts base HP by 100" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Aquire Potential 3: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 20% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 30% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 30% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 50% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 50% chance to deal 10% of this character's attack in extra damage" + ] + }, + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 60", + "Level 2: Boosts base ATK by 90", + "Level 3: Boosts base ATK by 120", + "Level 4: Boosts base ATK by 150", + "Level 5: Boosts base ATK by 200" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 3 turn on this character", + "Level 2: Reduces Slot Bind duration by 5 turns on this character", + "Level 3: Reduces Slot Bind duration by 7 turns on this character", + "Level 4: Reduces Slot Bind duration by 10 turns on this character", + "Level 5: Reduces Slot Bind completely on this character" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1795:{//Diamante + captain: "Boosts ATK of Slasher and Driven characters by 2x", + special: "Delays all enemies for 2 turns, reduces enemies Percent Damage Reduction and Increased Defense duration by 3 turns and changes right column [STR], [DEX], [QCK], [PSY] and [INT] orbs into Matching orbs", + sailor: "Boosts this character's attack against [STR] characters by 1.1x", + specialName: "Snake Sword", + }, + 1796:{//Diamante + captain: "Boosts ATK of Slasher and Driven characters by 2.5x", + special: "Delays all enemies for 2 turns, reduces enemies Percent Damage Reduction and Increased Defense duration by 3 turns and changes right column [STR], [DEX], [QCK], [PSY] and [INT] orbs into Matching orbs", + sailor: "Boosts this character's attack against [STR] characters by 1.1x", + specialName: "Snake Sword", + limit: [ + { "description": "Boosts base ATK by 10" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Aquire Potential 1: Barrier Penetration" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base HP by 50" }, + { "description": "Aquire Sailor Ability 1: Reduces Silence duration on this character by 3 turns" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base HP by 90" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "Barrier Penetration", + "description": [ + "Level 1: This character's attack will ignore barriers if HP is above 99%", + "Level 2: This character's attack will ignore barriers if HP is above 99%", + "Level 3: This character's attack will ignore barriers if HP is above 99%", + "Level 4: This character's attack will ignore barriers if HP is above 80%", + "Level 5: This character's attack will ignore barriers if HP is above 50%" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 1 turn on this character", + "Level 2: Reduces Slot Bind duration by 2 turns on this character", + "Level 3: Reduces Slot Bind duration by 3 turns on this character", + "Level 4: Reduces Slot Bind duration by 5 turns on this character", + "Level 5: Reduces Slot Bind duration by 10 turns on this character" + ] + }, + ] + }, + 1797:{//Jesus Burgess + captain: "Boosts ATK of Fighter characters by 2.25x", + special: [ + { + "description": "Cuts the current HP of each enemy by 10%", + "cooldown": [ 15, 9 ] + }, + { + "description": "Cuts the current HP of each enemy by 20%", + "cooldown": [ 18, 12 ] + }, + { + "description": "Cuts the current HP of each enemy by 20% and boosts ATK against delayed enemies by 1.5x for 2 turns.", + "cooldown": [ 21, 15 ] + } + ], + specialNotes: "#{stages}", + sailor: "Boosts base ATK and HP of [STR], [DEX], and [QCK] characters by 75", + specialName: "Shockwave Elbow", + }, + 1798:{//Jesus Burgess + captain: "Boosts ATK of Fighter characters by 2.5x, boosts HP of Powerhouse and Driven characters by 1.25x", + special: [ + { + "description": "Cuts the current HP of each enemy by 10%", + "cooldown": [ 15, 9 ] + }, + { + "description": "Cuts the current HP of each enemy by 20%", + "cooldown": [ 18, 12 ] + }, + { + "description": "Cuts the current HP of each enemy by 20% and boosts ATK against delayed enemies by 1.5x for 2 turns.", + "cooldown": [ 21, 15 ] + } + ], + specialNotes: "#{stages}", + sailor: "Boosts base ATK and HP of [STR], [DEX], and [QCK] characters by 75", + specialName: "Shockwave Elbow", + limit: [ + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base HP by 10" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Aquire Sailor Ability 1: Reduces Silence duration on this character by 3 turns" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base HP by 90" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Enrage" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 10% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 15% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 40% chance to deal 7% of this character's attack in extra damage" + ] + }, + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 30", + "Level 2: Boosts base ATK by 50", + "Level 3: Boosts base ATK by 70", + "Level 4: Boosts base ATK by 100", + "Level 5: Boosts base ATK by 150" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1799:{//Cavendish + captain: "Boosts ATK of [STR], [DEX] and [QCK] characters by 2.25x", + special: "Changes [BLOCK] orbs into Matching orbs, locks all orbs for 1 turn, boosts ATK against enemies with reduced defense by 1.75x for 2 turns", + sailor: "Makes [INT] and [PSY] orbs \"beneficial\" for this unit", + specialName: "Beautiful Sword: Round Table", + }, + 1800:{//Cavendish + captain: "Boosts ATK of [STR], [DEX] and [QCK] characters by 2.5x and their RCV by 1.2x", + special: "Changes [BLOCK] orbs into Matching orbs, locks all orbs for 1 turn, boosts ATK against enemies with reduced defense by 1.75x for 2 turns", + sailor: "Makes [INT] and [PSY] orbs \"beneficial\" for this unit", + specialName: "Beautiful Sword: Round Table", + limit: [ + { "description": "Boosts base RCV by 10" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Aquire Potential 1: Reduce No Healing duration" }, + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK, HP and RCV of [STR], [DEX], and [QCK] characters by 50" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: Reduces No Healing duration by 1 turn", + "Level 2: Reduces No Healing duration by 1 turn", + "Level 3: Reduces No Healing duration by 1 turn", + "Level 4: Reduces No Healing duration by 2 turns", + "Level 5: Reduces No Healing duration by 3 turns" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 1 turn on this character", + "Level 2: Reduces Slot Bind duration by 2 turns on this character", + "Level 3: Reduces Slot Bind duration by 3 turns on this character", + "Level 4: Reduces Slot Bind duration by 5 turns on this character", + "Level 5: Reduces Slot Bind duration by 10 turns on this character" + ] + }, + ] + }, + 1801:{//Bartolomeo + captain: "Boosts ATK of [STR], [DEX] and [QCK] characters by 2x and if you don't attack with Bartolomeo, reduces damage received by 10% for that turn.", + special: "Deal 30x character's ATK in [QCK] damage to all enemies, reduces damage received by 90% for 1 turn and reduces the defense of all enemies by 80% for 2 turns", + sailor: "Reduces Paralysis for 3 turns for himself", + specialName: "Barrier Bulls", + }, + 1802:{//Bartolomeo + captain: "Boosts ATK of [STR], [DEX] and [QCK] characters by 2.5x and if you don't attack with Bartolomeo, reduces damage received by 15% for that turn.", + special: "Deal 30x character's ATK in [QCK] damage to all enemies, reduces damage received by 90% for 1 turn and reduces the defense of all enemies by 80% for 2 turns", + sailor: "Reduces Paralysis for 3 turns for himself", + specialName: "Barrier Bulls", + limit: [ + { "description": "Boosts base HP by 10" }, + { "description": "Boosts base HP by 15" }, + { "description": "Boosts base HP by 20" }, + { "description": "Aquire Potential 1: Reduce No Healing duration" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK, HP and RCV of [STR], [DEX], and [QCK] characters by 50" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base RCV by 60" }, + { "description": "Boosts base ATK by 50" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire Potential 2: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "Reduce No Healing duration", + "description": [ + "Level 1: Reduces No Healing duration by 1 turn", + "Level 2: Reduces No Healing duration by 1 turn", + "Level 3: Reduces No Healing duration by 1 turn", + "Level 4: Reduces No Healing duration by 2 turns", + "Level 5: Reduces No Healing duration by 3 turns" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 1 turn on this character", + "Level 2: Reduces Slot Bind duration by 2 turns on this character", + "Level 3: Reduces Slot Bind duration by 3 turns on this character", + "Level 4: Reduces Slot Bind duration by 5 turns on this character", + "Level 5: Reduces Slot Bind duration by 10 turns on this character" + ] + }, + ] + }, + 1803: {//Zoro + captain: "Boosts ATK of Slasher characters by 2x", + special: "Deals 13x character's ATK in [DEX] to one enemy, removes enemies' End of Turn Damage/Percent Cut, and randomizes all orbs, including [BLOCK] orbs", + specialName: "To Become Stronger. Santoryu Ogi: Sanzen Sekai", + }, + 1804: {//Zoro + captain: "Boosts ATK of Slasher characters by 2.25x and their HP by 1.3x", + special: "Deals 13x character's ATK in [DEX] to one enemy, removes enemies' End of Turn Damage/Percent Cut, and randomizes all orbs, including [BLOCK] orbs", + specialName: "To Become Stronger. Santoryu Ogi: Sanzen Sekai", + }, + 1805: {//Buggy + captain: "Boosts ATK of characters with cost 30 or less by 1.5x and their HP by 1.2x", + special: "Reduces the defense of all enemies by 100% for 1 turn, reduces damage received from STR enemies by 80% for 1 turn, Amplifies the effect of orbs by 1.5x for 1 turn", + specialName: "Deceiving the World with the Most Evil Show", + }, + 1806: {//Buggy + captain: "Boosts ATK of characters with cost 30 or less by 2.25x and their HP by 1.2x", + special: "Reduces the defense of all enemies by 100% for 1 turn, reduces damage received from STR enemies by 80% for 1 turn, Amplifies the effect of orbs by 1.5x for 1 turn", + specialName: "Deceiving the World with the Most Evil Show", + }, + 1807: {//Mihawk + captain: "Not Translated", + special: "Deals 100x character's ATK in typeless damage to all enemies, if your Captain is a Slasher character, locks the chain multiplier at 2.75x for 1 turn and amplifies the effects of orbs for Slasher characters by 2x for 1 turn", + specialName: "Black Blade • The Ultimate Sword", + }, + 1808: {//Mihawk + captain: { + "base": "Boosts ATK of Slasher characters by 1.2x and their HP by 1.1x. If you use \"Black Blade • The Ultimate Sword\" boosts ATK of Slasher characters by 1.62x instead for 1 turn.", + "level1": "Boosts ATK of Slasher characters by 1.35x and their HP by 1.1x. If you use \"Black Blade • The Ultimate Sword\" boosts ATK of Slasher characters by 1.8225x instead for 1 turn.", + "level2": "Boosts ATK of Slasher characters by 1.6x and their HP by 1.1x. If you use \"Black Blade • The Ultimate Sword\" boosts ATK of Slasher characters by 2.16x instead for 1 turn.", + "level3": "Boosts ATK of Slasher characters by 1.8x and their HP by 1.2x. If you use \"Black Blade • The Ultimate Sword\" boosts ATK of Slasher characters by 2.43x instead for 1 turn.", + "level4": "Boosts ATK of Slasher characters by 2x and their HP by 1.2x. If you use \"Black Blade • The Ultimate Sword\" boosts ATK of Slasher characters by 2.7x instead for 1 turn.", + "level5": "Boosts ATK of Slasher characters by 2x and their HP by 1.3x. If you use \"Black Blade • The Ultimate Sword\" boosts ATK of Slasher characters by 2.7x instead for 1 turn.", + "level6": "Boosts ATK of Slasher characters by 2.5x and their HP by 1.3x. If you use \"Black Blade • The Ultimate Sword\" boosts ATK of Slasher characters by 3.5x instead for 1 turn.", + }, + special: "Deals 100x character's ATK in typeless damage to all enemies, if your Captain is a Slasher character, locks the chain multiplier at 2.75x for 1 turn and amplifies the effects of orbs for Slasher characters by 2x for 1 turn", + specialName: "Black Blade • The Ultimate Sword", + limit: [ + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Boosts base ATK by 10" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base RCV by 5" }, + { "description": "Aquire Potential 1: Critical Hit" }, + { "description": "Aquire new Captain Ability: Boosts ATK of Slasher characters by 1.35x and their HP by 1.1x. If you use \"Black Blade • The Ultimate Sword\" boosts ATK of Slasher characters by 1.8225x instead for 1 turn." }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK of Slasher characters by 50" }, + { "description": "Boosts base ATK by 15" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Aquire new Captain Ability: Boosts ATK of Slasher characters by 1.6x and their HP by 1.1x. If you use \"Black Blade • The Ultimate Sword\" boosts ATK of Slasher characters by 2.16x instead for 1 turn." }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base RCV by 15" }, + { "description": "Aquire new Captain Ability: Boosts ATK of Slasher characters by 1.8x and their HP by 1.2x. If you use \"Black Blade • The Ultimate Sword\" boosts ATK of Slasher characters by 2.43x instead for 1 turn." }, + { "description": "Reduce base Special Cooldown by 2 turns" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Boosts base HP by 60" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Reduce base Special Cooldown by 3 turns" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base HP by 65" }, + { "description": "Reduce base Special Cooldown by 4 turns" }, + { "description": "Aquire new Captain Ability: Boosts ATK of Slasher characters by 2x and their HP by 1.2x. If you use \"Black Blade • The Ultimate Sword\" boosts ATK of Slasher characters by 2.7x instead for 1 turn." }, + { "description": "Boosts base ATK by 35" }, + { "description": "Boosts base HP by 70" }, + { "description": "Aquire Sailor Ability 2: Makes [QCK] orbs \"beneficial\" for this unit" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Boosts base HP by 75" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Reduce base Special Cooldown by 5 turns" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Aquire new Captain Ability: Boosts ATK of Slasher characters by 2x and their HP by 1.3x. If you use \"Black Blade • The Ultimate Sword\" boosts ATK of Slasher characters by 2.7x instead for 1 turn." }, + { "description": "Boosts base ATK by 50" }, + { "description": "Boosts base HP by 80" }, + { "description": "Aquire new Captain Ability: Boosts ATK of Slasher characters by 2.5x and their HP by 1.3x. If you use \"Black Blade • The Ultimate Sword\" boosts ATK of Slasher characters by 3.5x instead for 1 turn." }, + { "description": "Aquire Potential 2: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 15% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 25% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 50% chance to deal 7% of this character's attack in extra damage" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 1 turn on this character", + "Level 2: Reduces Slot Bind duration by 2 turns on this character", + "Level 3: Reduces Slot Bind duration by 3 turns on this character", + "Level 4: Reduces Slot Bind duration by 5 turns on this character", + "Level 5: Reduces Slot Bind duration by 10 turns on this character" + ] + }, + ], + }, + 1809: {//Wanda + captain: "Boosts ATK by 2.25x after scoring 2 Perfects in a row", + special: "Reduces Bind and Paralysis duration by 2 turns. If your Captain is a Slasher character, makes Perfects easier to hit for 1 turn", + sailor: "Reduces Paralysis for 1 turn for herself", + specialName: "Super Express Beast Path", + }, + 1810: {//Wanda + captain: "Boosts chances of getting Matching orbs, boosts ATK by 2.25x after scoring 2 Perfects in a row", + special: "Reduces Bind and Paralysis duration by 2 turns. If your Captain is a Slasher character, makes Perfects easier to hit for 1 turn", + sailor: "Reduces Paralysis for 1 turn for herself", + specialName: "Super Express Beast Path", + }, + 1811: {//Carrot + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of Fighter characters by 2x", + special: "Reduces Special Cooldown of your top row by 2 turns, boosts ATK of Fighter characters by 1.5x for 1 turn", + specialName: "Rabbit Mink's Air Step", + }, + 1812: {//Carrot + captain: "Reduces cooldown of all specials by 1 turn at the start of the fight, boosts ATK of Fighter characters by 2.25x", + special: "Reduces Special Cooldown of your top row by 2 turns, boosts ATK of Fighter characters by 1.5x for 1 turn", + specialName: "Rabbit Mink's Air Step", + }, + 1813: {//Koala + captain: "Boosts ATK of all characters by 2.25x and boosts EXP and amount of Beli recieved by 1.2x", + special: "Changes Captain's orb into Matching and boosts ATK of your Captain by 1.5x for 1 turn", + specialName: "Revolutionary Soldier's Anger", + }, + 1814: {//Raid Sanji + captain: "Boosts ATK of Powerhouse characters by 2.5x until the first hit other than Perfect and recovers 100 HP at end of each turn", + specialName: "Joue Shoot", + special: "Deal 150x character's ATK in typeless damage to one enemy, boosts ATK of Powerhouse characters by 2x for 1 turn", + }, + 1815: {//Raid Sanji + captain: "Boosts ATK of Powerhouse characters by 2.75x until the first hit other than Perfect and recovers 300 HP at end of each turn", + specialName: "Joue Shoot", + special: "Deal 150x character's ATK in typeless damage to one enemy, boosts ATK of Powerhouse characters by 2x for 1 turn", + limit: [ + { "description": "Boosts base HP by 20" }, + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Aquire Potential 1: Enrage" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base HP by 45" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base RCV by 50" }, + { "description": "Aquire 1 additional Socket slot" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base ATK by 40" }, + { "description": "Aquire Sailor Ability 1: Makes [RCV] orbs \"beneficial\" for all characters" }, + { "description": "Aquire Potential 2: Slot Bind Self-reduction" }, + ], + potential: [ + { + "Name": "Enrage", + "description": [ + "Level 1: Boosts base ATK by 20", + "Level 2: Boosts base ATK by 30", + "Level 3: Boosts base ATK by 40", + "Level 4: Boosts base ATK by 50", + "Level 5: Boosts base ATK by 100" + ] + }, + { + "Name": "Slot Bind Self-reduction", + "description": [ + "Level 1: Reduces Slot Bind duration by 1 turn on this character", + "Level 2: Reduces Slot Bind duration by 2 turns on this character", + "Level 3: Reduces Slot Bind duration by 3 turns on this character", + "Level 4: Reduces Slot Bind duration by 4 turns on this character", + "Level 5: Reduces Slot Bind duration by 5 turns on this character" + ] + }, + ], + potentialNotes: "Enrage is activated when your crew took damage from your enemies in the previous turn" + }, + 1816: {// Ace 6+ + special: "Reduces crew's current HP by 40%, deals 15x the amount of HP subtracted in typeless damage to all enemies, boosts ATK of Shooter characters by 2x for 1 turn", + specialName: "Great Flame Commandment: Flame Emperor • Flame Wheel", + captain: "Boosts HP of Shooter characters by 1.5x and boosts ATK by 3.25x if they have a matching orb, by 2.25x otherwise" + }, + 1817: {// Riku + captain: "Boosts ATK by 2x after scoring 3 Greats in a row", + special: "Cuts the current HP of one enemy by 7%, boosts ATK of the characters in the bottom and middle row by 1.2x for 1 turn and reduces special cooldown of all non-Captain specials by 1 turn", + specialName: "Divine Sword", + sailor: "Restores his own special by 1 turn when it is rewinded", + sailorNotes: "#{rewind : 1}", + }, + 1818: {// Riku + captain: "Boosts ATK of all characters by 1.5x and their HP by 1.2x, boosts ATK by 2.5x after scoring 3 Greats in a row", + special: "Cuts the current HP of one enemy by 7%, boosts ATK of the characters in the bottom and middle row by 1.2x for 1 turn and reduces special cooldown of all non-Captain specials by 1 turn", + specialName: "Divine Sword", + sailor: "Restores his own special by 1 turn when it is rewinded", + sailorNotes: "#{rewind : 1}", + }, + 1819: {//Tank + captain: "Boosts ATK of Powerhouse and Stiker characters by 1.75x", + special: "Boosts own ATK by 1.75x for 1 turn", + specialName: "Shameful Hidden Activity", + }, + 1820: {//Scarlet + captain: "Boosts HP and RCV of [PSY] characters by 1.5x", + special: "Locks all orbs for 1 turn and recovers 5x character's RCV in HP.", + specialName: "Frontier Love", + }, + 1821: {//Sanji + captain: "Boosts ATK of all characters by 1.5x. Recovers 1x character's RCV in HP at the end of each turn", + special: [ + { + "description": "Recovers 4x character's RCV in HP, reduces damage received by 50% for 1 turn. Randomly changes all orbs, including [BLOCK] orbs, into either [STR], [DEX], [QCK] or [RCV] orbs.", + "cooldown": [ 8, 8 ] + }, + { + "description": "Recovers 10x character's RCV in HP, reduces damage received by 50% for 1 turn. Randomly changes all orbs, including [BLOCK] orbs, into either [STR], [DEX], [QCK] or [RCV] orbs.", + "cooldown": [ 14, 14 ] + }, + ], + specialName: "Sanji Special", + sailor: "Makes [RCV] orbs \"beneficial\" for this unit", + }, + 1822: {//Sanji + captain: "Boosts ATK of all characters by 2x. Recovers 2x character's RCV in HP at the end of each turn", + special: [ + { + "description": "Recovers 4x character's RCV in HP, reduces damage received by 50% for 1 turn. Randomly changes all orbs, including [BLOCK] orbs, into either [STR], [DEX], [QCK] or [RCV] orbs.", + "cooldown": [ 8, 8 ] + }, + { + "description": "Recovers 10x character's RCV in HP, reduces damage received by 50% for 1 turn. Randomly changes all orbs, including [BLOCK] orbs, into either [STR], [DEX], [QCK] or [RCV] orbs.", + "cooldown": [ 14, 14 ] + }, + ], + specialName: "Sanji Special", + sailor: "Makes [RCV] orbs \"beneficial\" for this unit", + }, + 1823: {//World + captain: "Not Translated", + special: [ + { + "description": "Deals 100,000 fixed damage to one enemy and removes ATK down debuff from your team", + "cooldown": [ 14, 10 ] + }, + { + "description": "Deals 300,000 fixed damage to one enemy and removes ATK down debuff from your team", + "cooldown": [ 18, 14 ] + }, + { + "description": "Deals 500,000 fixed damage to one enemy, removes ATK down debuff from your team and reduces enemy Barrier duration by 1 turn", + "cooldown": [ 22, 18 ] + } + ], + specialNotes:"#{stages}", + specialName: "More More: Hundredfold Artillery Cannon", + }, + 1824: {//World + captain: "Boosts ATK of Shooter characters by 2.2x at the start of the chain.
    Boosts ATK of Shooter characters by 2.42x after the 1st Perfect in a row, by 2.662x after the 2nd Perfect in a row, by 2.9282x after the 3rd Perfect in a row, by 3.22102x after the 4th Perfect in a row, and by 3.543122x after the 5th Perfect in a row.", + special: [ + { + "description": "Deals 100,000 fixed damage to one enemy and removes ATK down debuff from your team", + "cooldown": [ 14, 10 ] + }, + { + "description": "Deals 300,000 fixed damage to one enemy and removes ATK down debuff from your team", + "cooldown": [ 18, 14 ] + }, + { + "description": "Deals 500,000 fixed damage to one enemy, removes ATK down debuff from your team and reduces enemy Barrier duration by 1 turn", + "cooldown": [ 22, 18 ] + } + ], + specialNotes:"#{stages}", + specialName: "More More: Hundredfold Artillery Cannon", + limit: "This character has a limit break path", + }, + 1825: {//Akainu + captain: "Boosts ATK by 2.5x following a chain of [INT] > [INT] > [INT] attacks no lower than Good", + special: "Deals 50x character's ATK in [INT] damage to all enemies. Changes orbs for [INT] characters into [INT] orbs. Boosts the Color Affinity of [INT] characters by 1.75x for 1 turn", + specialNotes: "#{colorAffinity : 1.75}", + specialName: "Great Eruption [Neo]", + }, + 1826: {//Akainu + captain: "Boosts ATK by 3x following a chain of [INT] > [INT] > [INT] attacks no lower than Good", + special: "Deals 50x character's ATK in [INT] damage to all enemies. Changes orbs for [INT] characters into [INT] orbs. Boosts the Color Affinity of [INT] characters by 1.75x for 1 turn", + specialNotes: "#{colorAffinity : 1.75}", + specialName: "Great Eruption [Neo]", + }, + 1827: {//Sicilian Colo + captain: "Boosts ATK of [INT] characters by 2x", + special: "Reduce crew's current HP by 50%, Boosts ATK of [INT] characters by 2x for 1 turn and randomize non-matching orbs, including [BLOCK] orbs", + specialName: "Explosive Spirit", + }, + 1828: {//Sicilian Colo + captain: "Boosts ATK of [INT] characters by 3x if HP is below 30% at the start of the turn, by 2.5x otherwise", + special: "Reduce crew's current HP by 50%, Boosts ATK of [INT] characters by 2x for 1 turn and randomize non-matching orbs, including [BLOCK] orbs", + specialName: "Explosive Spirit", + limit: [ + { "description": "Boosts base HP by 30" }, + { "description": "Boosts base RCV by 10" }, + { "description": "Aquire Sailor Ability 1: Boosts base ATK of Slasher characters by 40" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Boosts base HP by 40" }, + { "description": "Boosts base RCV by 20" }, + { "description": "Boosts base ATK by 20" }, + { "description": "Aquire Potential 1: [PSY] Damage Reduction" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base RCV by 30" }, + { "description": "Boosts base ATK by 25" }, + { "description": "Reduce base Special Cooldown by 1 turn" }, + { "description": "Boosts base HP by 50" }, + { "description": "Boosts base ATK by 30" }, + { "description": "Aquire Potential 2: Critical Hit" }, + ], + potential: [ + { + "Name": "[PSY] Damage Reduction", + "description": [ + "Level 1: Reduces Damage recieved from [PSY] enemies by 1%", + "Level 2: Reduces Damage recieved from [PSY] enemies by 2%", + "Level 3: Reduces Damage recieved from [PSY] enemies by 3%", + "Level 4: Reduces Damage recieved from [PSY] enemies by 4%", + "Level 5: Reduces Damage recieved from [PSY] enemies by 5%" + ] + }, + { + "Name": "Critical Hit", + "description": [ + "Level 1: If you hit a perfect with this character, there is a 10% chance to deal 3% of this character's attack in extra damage", + "Level 2: If you hit a perfect with this character, there is a 10% chance to deal 5% of this character's attack in extra damage", + "Level 3: If you hit a perfect with this character, there is a 15% chance to deal 5% of this character's attack in extra damage", + "Level 4: If you hit a perfect with this character, there is a 20% chance to deal 5% of this character's attack in extra damage", + "Level 5: If you hit a perfect with this character, there is a 20% chance to deal 10% of this character's attack in extra damage" + ] + }, + ] + }, + 1829: {//Raid Caesar + captain: "Boosts ATK of Cerebral and Driven characters by 2x", + special: "Deals 45x character's ATK in typeless damage to all enemies, amplifies the effect of orbs by 1.75x for Cerebral and Driven characters for 2 turns, and poisons all enemies", + spcialName: "Flammable Type: Miok GAS", + }, + 1830: {//Raid Caesar + captain: "Boosts ATK of Cerebral and Driven characters by 2.5x", + special: "Deals 45x character's ATK in typeless damage to all enemies, amplifies the effect of orbs by 1.75x for Cerebral and Driven characters for 2 turns, and poisons all enemies", + spcialName:"Flammable Type: Miok GAS", + limit: "This character has a limit break path", + }, + 1831: {//6* Judge + captain: "Increase the rate of PSY orbs, reduces damage recieved by 15%, boosts the HP of all characters by 1.25x and if there is a [STR], [DEX], [QCK], [PSY], and [INT] characters in your crew, boosts ATK of all characters by 3.9375x if they have a matching orb, by 2.25x otherwise", + special: "Reduces bind duration by 7 turns and amplifies the effect of orbs by 2x for 1 turn. If this character is the captain or the friend captain, slightly boosts the rate of [PSY] orbs and randomly shuffles all orbs including [BLOCK] orbs", + specialName: "Dengi Crack", + }, + 1832: {//6* Judge + captain: "Increase the rate of PSY orbs, reduces damage recieved by 15%, boosts the HP of all characters by 1.25x and if there is a [STR], [DEX], [QCK], [PSY], and [INT] characters in your crew, boosts ATK of all characters by 3.9375x if they have a matching orb, by 2.25x otherwise", + special: "Reduces bind duration by 7 turns and amplifies the effect of orbs by 2x for 1 turn. If this character is the captain or the friend captain, slightly boosts the rate of [PSY] orbs and randomly shuffles all orbs including [BLOCK] orbs", + specialName: "Dengi Crack", + limit: "This character has a limit break path", + }, + 1833: {//Reiju + captain: "Boosts ATK of [INT] characters by 1.75x and Powerhouse characters by 1.2x and the RCV of Powerhouse characters by 1.1x", + captainNotes: "Attack boost stacks, so an [INT] Powerhouse unit has 2.1x ATK", + special: "If your captain is [INT] or [PSY], recovers 7,000 HP, removes poison, and reduces the duration of paralysis, despair, and silence by 3 turns. If the captain is a Powerhouse character, reduces damage recieved by 70% for 2 turns ", + specialName: "Dangerous Healing", + sailor: "Makes [PSY] orbs \"beneficial\" for this unit", + sailorNotes: "#{beneficial}", + }, + 1834: {//Reiju + captain: "Boosts ATK of [INT] characters by 2.25x and Powerhouse characters by 1.3x and the RCV of Powerhouse characters by 1.2x", + captainNotes: "Attack boost stacks, so an [INT] Powerhouse unit has 2.925x ATK", + special: "If your captain is [INT] or [PSY], recovers 7,000 HP, removes poison, and reduces the duration of paralysis, despair, and silence by 3 turns. If the captain is a Powerhouse character, reduces damage recieved by 70% for 2 turns ", + specialName: "Dangerous Healing", + sailor: "Makes [PSY] orbs \"beneficial\" for this unit", + sailorNotes: "#{beneficial}", + limit: "This character has a limit break path", + }, + 1835: {//Ichiji + captain: "Boosts ATK of [STR] characters by 1.75x, boosts ATK of Powerhouse characters by 1.2x, and the HP of Powerhouse characters by 1.2x", + captainNotes: "Attack boost stacks, so an [STR] Powerhouse unit has 2.1x ATK", + special: "If your captain is [STR] or[PSY] character, locks chain multiplier at 2.5x for 2 turns. If your Captain is a Powerhouse character, delays all enemies for 2 turns", + specialName: "Majestic Impact", + sailor: "Makes [PSY] orbs \"beneficial\" for this unit", + sailorNotes: "#{beneficial}", + }, + 1836: {//Ichiji + captain: "Boosts ATK of [STR] characters by 2.25x, boosts ATK of Powerhouse characters by 1.3x, and the HP of Powerhouse characters by 1.2x", + captainNotes: "Attack boost stacks, so an [STR] Powerhouse unit has 2.925x ATK", + special: "If your captain is [STR] or[PSY] character, locks chain multiplier at 2.5x for 2 turns. If your Captain is a Powerhouse character, delays all enemies for 2 turns", + specialName: "Majestic Impact", + sailor: "Makes [PSY] orbs \"beneficial\" for this unit", + sailorNotes: "#{beneficial}", + limit: "This character has a limit break path", + }, + 1837: {//Niji + captain: "Boosts ATK of [QCK] characters by 1.75x, boosts ATK of Powerhouse characters by 1.2x, and the HP of Powerhouse characters by 1.2x", + captainNotes: "Attack boost stacks, so an [QCK] Powerhouse unit has 2.1x ATK", + special: "If your captain is a [QCK] or [PSY] character, boosts ATK of all characters by 1.75x for 2 turns. If your captain is a Powerhouse character, locks all orbs for 1 turn", + specialName: "Blitz Needle", + sailor: "Makes [PSY] orbs \"beneficial\" for this unit", + sailorNotes: "#{beneficial}", + }, + 1838: {//Niji + captain: "Boosts ATK of [QCK] characters by 2.25x, boosts ATK of Powerhouse characters by 1.3x, and the HP of Powerhouse characters by 1.2x", + captainNotes: "Attack boost stacks, so an [QCK] Powerhouse unit has 2.925x ATK", + special: "If your captain is a [QCK] or [PSY] character, boosts ATK of all characters by 1.75x for 2 turns. If your captain is a Powerhouse character, locks all orbs for 1 turn", + specialName: "Blitz Needle", + sailor: "Makes [PSY] orbs \"beneficial\" for this unit", + sailorNotes: "#{beneficial}", + limit: "This character has a limit break path", + }, + 1839: {//Yonji + captain: "Boosts ATK of [DEX] characters by 1.75x, boosts ATK of Powerhouse characters by 1.2x, and the HP of Powerhouse characters by 1.2x", + captainNotes: "Attack boost stacks, so an [DEX] Powerhouse unit has 2.1x ATK", + special: "If your captain is a [DEX] or [PSY] character, boosts ATK against delayed enemies by 1.75x for 1 turn. If your captain is a Powerhouse character, adds 40x characters ATK as additional typeless damage for 2 turns", + specialName: "Burst End Kick", + specialNotes: "Extra Damage can only be boosted by conditional Boosters.", + sailor: "Makes [PSY] orbs \"beneficial\" for this unit", + sailorNotes: "#{beneficial}", + }, + 1840: {//Yonji + captain: "Boosts ATK of [DEX] characters by 2.25x, boosts ATK of Powerhouse characters by 1.3x, and the HP of Powerhouse characters by 1.2x", + captainNotes: "Attack boost stacks, so an [DEX] Powerhouse unit has 2.925x ATK", + special: "If your captain is a [DEX] or [PSY] character, boosts ATK against delayed enemies by 1.75x for 1 turn. If your captain is a Powerhouse character, adds 40x characters ATK as additional typeless damage for 2 turns", + specialName: "Burst End Kick", + specialNotes: "Extra Damage can only be boosted by conditional Boosters.", + sailor: "Makes [PSY] orbs \"beneficial\" for this unit", + sailorNotes: "#{beneficial}", + limit: "This character has a limit break path", + }, + 1841: {//Caribou + captain: "Boosts ATK of Driven characters by 1.5x, deals 2x character's ATK in [DEX] damage to all enemies at the end of each turn", + special: "Boosts ATK of Driven characters by 1.5x for 1 turn, reduces enemy's Threshold Damage Reduction by 2 turns and ATK Up duration by 3 turns", + specialName: "Fathomless Infinite Hell", + sailor: "When any other character uses a special, reduces own cooldown by 5 turn", + }, + 1842: {//Caribou + captain: "Boosts ATK of Driven characters by 1.5x, deals 4x character's ATK in [DEX] damage to all enemies at the end of each turn", + special: "Boosts ATK of Driven characters by 1.5x for 1 turn, reduces enemy's Threshold Damage Reduction by 2 turns and ATK Up duration by 3 turns", + specialName: "Fathomless Infinite Hell", + sailor: "When any other character uses a special, reduces own cooldown by 5 turn", + }, + 1843: {//Coribou + captain: "Boosts ATK of Driven and Striker characters by 1.5x", + special: "Removes blindness and recovers 4x character's RCV in HP", + specialName: "Frantic Funeral", + }, + 1844: {//Coribou + captain: "Boosts ATK of Driven and Striker characters by 1.75x", + special: "Removes blindness and recovers 4x character's RCV in HP", + specialName: "Frantic Funeral", + }, + 1845: {//Garp + captain: "Boosts ATK of Fighter characters by 2.5x and reduce damage received by 5%", + special: "Reduces the defense of all enemies by 100% for 1 turn. If the targeted enemy has less than 25% HP, instantly defeats them, otherwise, cuts the current HP of one enemy by 30%", + specialName: "Garp Special", + }, + 1846: {//Garp + captain: "Boosts ATK of Fighter characters by 2.75x and reduce damage received by 15%", + special: "Reduces the defense of all enemies by 100% for 1 turn. If the targeted enemy has less than 25% HP, instantly defeats them, otherwise, cuts the current HP of one enemy by 30%", + specialName: "Garp Special", + }, + 1847: {//Sengoku+ + captain: "Reduce CD by 2 at the start of the adventure, boost ATK of characters that are 29 cost or lower by 3.25x, and their HP by 1.2x, boost ATK of characters with cost 54 by 3x", + captainNotes: "His captain ability also affects his evolved forms, his base form will NOT receive the boost. All evolved and plus evolved Sengoku characters in the team are included in the bonus.", + special: "Deals random large INT Damage to all enemies, boost ATK of all characters by 1.5x for 1 turn, changes orbs to matching orbs for chatacters that are 29 cost or lower", + specialName: "Requiem Shockwave", + }, + 1848: {//Treasure Map Akainu + captain: "Boosts ATK of Powerhouse characters by 2x", + special: "Deals 50x character's Atk in Str damage to one enemy, reduces enemy Barrier duration by 1 turn, and reduces any damage above 3000 by 80% for 1 turn", + specialName: "Hellhound Bite", + sailor: "Makes [PSY] and [INT] orbs \"beneficial\" for this unit", + sailorNotes: "#{beneficial}", + }, + 1849: {//Treasure Map Akainu + captain: "Boosts ATK of Powerhouse characters by 2.25x and their HP by 1.3x", + special: "Deals 50x character's Atk in Str damage to one enemy, reduces enemy Barrier duration by 1 turn, and reduces any damage above 3000 by 80% for 1 turn", + specialName: "Hellhound Bite", + sailor: "Makes [PSY] and [INT] orbs \"beneficial\" for this unit", + sailorNotes: "#{beneficial}", + }, + 1850: {//Treasure Map Squard + captain: "Boosts ATK of Driven characters by 2x", + special: "Deals 40x character's Atk in Dex damage to one enemy that will ignore damage negating abilities and barriers, makes Perfects easier to hit for 1 turn, and adds .5x to Chain multiplier for 1 turn", + specialName: "Piercing Hatred", + sailor: "Makes [PSY] and [INT] orbs \"beneficial\" for this unit", + sailorNotes: "#{beneficial}", + }, + 1851: {//Treasure Map Squard + captain: "Boosts ATK of Driven characters by 2.25x and their HP by 1.3x", + special: "Deals 40x character's Atk in Dex damage to one enemy that will ignore damage negating abilities and barriers, makes Perfects easier to hit for 1 turn, and adds .5x to Chain multiplier for 1 turn", + specialName: "Piercing Hatred", + sailor: "Makes [PSY] and [INT] orbs \"beneficial\" for this unit", + sailorNotes: "#{beneficial}", + }, + 1852: {//Whitebeard + captain: "Not Translated", + special: "Changes own orb into [INT], deals 100x character's ATK in typeless damage to all enemies that will ignore damage negating abilities and barriers. If enemies have All Debuff Protection or Delay Debuff Protection at the time the special was activated, amplifies the effect of orbs by 2x for 1 turn. If enemies have a barrier at the time the special was activated, boosts own ATK by 2.25x", + specialName: "Whitebeard Special", + }, + 1853: {//Whitebeard + captain: "Boosts ATK of all characters proportionally to the crew's current HP and their HP by 1.2x", + captainNotes: "#{captainProportional : lower : 1 + 1.25 * (1 - (remaining HP) / (total HP)) : 1 : 2.25}", + special: "Changes own orb into [INT], deals 100x character's ATK in typeless damage to all enemies that will ignore damage negating abilities and barriers. If enemies have All Debuff Protection or Delay Debuff Protection at the time the special was activated, amplifies the effect of orbs by 2x for 1 turn. If enemies have a barrier at the time the special was activated, boosts own ATK by 2.25x", + specialName: "Whitebeard Special", + }, + 1854: {//Apoo + captain: "Boosts ATK of Free Spirit characters by 2x", + special: "Amplifies the effect of orbs for Free Spirit characters by 1.5x and boosts ATK of Free Spirit characters by 1.5x for 1 turn", + specialName: "Fighting Musical Performance", + }, + 1855: {//Apoo + captain: "Boosts ATK of Free Spirit characters by 2x at the start of the chain, by 2.5x after the 3rd Perfect in a row and by 3x after the 5th Perfect in a row", + special: "Amplifies the effect of orbs for Free Spirit characters by 1.5x and boosts ATK of Free Spirit characters by 1.5x for 1 turn", + specialName: "Fighting Musical Performance", + }, + 1856: {//X Drake + captain: "Boosts ATK of Powerhouse characters by 2x", + special: "Cuts the current HP of each enemy by 7%. Boosts the Color Affinity of Powerhouse characters by 1.25x", + specialName: "Intervening A Fierce Battle", + }, + 1857: {//X Drake + captain: "Boosts ATK of Powerhouse characters by 2.5 and recovers 200 HP at end of each turnx", + special: "Cuts the current HP of each enemy by 7%. Boosts the Color Affinity of Powerhouse characters by 1.25x", + specialName: "Intervening A Fierce Battle", + }, + 1858: {//Leo + captain: "Boosts ATK of Striker characters by 2x at the start of the chain. Boosts ATK of Striker characters by 2.4x after scoring 3 Perfects in a row.", + special: "Reduce 3 turns of paralysis, randomize non-matching orbs, including [BLOCK] orbs, Adds 65x character's ATK as Additional Typeless Damage for 1 turn, when the captain is a Striker Character reduces enemies Percent Damage Reduction duration by 3 turns", + sailor: "If Leo has an [INT] orb and you hit a Perfect with him, keep his [INT] orb for the next turn", + }, + 1859: {//Leo + captain: "Boosts ATK of Striker characters by 2.5x and their HP by 1.2x at the start of the chain. Boosts ATK of Striker characters by 3.25x after scoring 3 Perfects in a row.", + special: "Reduce 3 turns of paralysis, randomize non-matching orbs, including [BLOCK] orbs, Adds 65x character's ATK as Additional Typeless Damage for 1 turn, when the captain is a Striker Character reduces enemies Percent Damage Reduction duration by 3 turns", + sailor: "If Leo has an [INT] orb and you hit a Perfect with him, keep his [INT] orb for the next turn", + }, + 1860: {//Coloseum Raizo + captain: "Not Translated", + special: [ + { + "description": "Deals 3x character's ATK in QCK damage to all enemies, changes [TND] and [RCV] orbs on Shooter characters into Matching Orbs,", + "cooldown": [ 19, 4 ] + }, + { + "description": "Deals 7x character's ATK in QCK damage to all enemies, changes [TND] and [RCV] orbs on Shooter characters into Matching Orbs. If your captain is a Shooter Character, boosts ATK against delayed enemies by 1.35x for 1 turn", + "cooldown": [ 24, 9 ] + }, + { + "description": "Deals 11x character's ATK in QCK damage to all enemies, changes [TND] and [RCV] orbs on Shooter characters into Matching Orbs. If your captain is a Shooter Character, boosts ATK against delayed enemies by 1.75x for 1 turn", + "cooldown": [ 30, 15 ] + } + ], + specialNotes: "#{stages}", + specialName: "Raizo Special", + }, + 1861: {//Coloseum Raizo + captain: "Reduces cooldown of all specials by 2 turns at the start of the fight, boosts ATK of Shooter characters by 2.5x", + special: [ + { + "description": "Deals 3x character's ATK in QCK damage to all enemies, changes [TND] and [RCV] orbs on Shooter characters into Matching Orbs,", + "cooldown": [ 19, 4 ] + }, + { + "description": "Deals 7x character's ATK in QCK damage to all enemies, changes [TND] and [RCV] orbs on Shooter characters into Matching Orbs. If your captain is a Shooter Character, boosts ATK against delayed enemies by 1.35x for 1 turn", + "cooldown": [ 24, 9 ] + }, + { + "description": "Deals 11x character's ATK in QCK damage to all enemies, changes [TND] and [RCV] orbs on Shooter characters into Matching Orbs. If your captain is a Shooter Character, boosts ATK against delayed enemies by 1.75x for 1 turn", + "cooldown": [ 30, 15 ] + } + ], + specialNotes: "#{stages}", + specialName: "Raizo Special", + }, + 1862: {//Neo Coliseum Kinemon + captain: "Boosts ATK of Free Spirit characters by 2x, recovers 1x character's RCV in HP at the end of each turn", + special: "Reduces Special Cooldown of Slasher and Free Spirit characters by 1 turn and changes adjacent orbs into Matching Orbs", + specialName: "Poof [Neo]", + }, + 1863: {//Neo Coliseum Kinemon + captain: "Boosts ATK of Free Spirit characters by 2.5x, recovers 2x character's RCV in HP at the end of each turn", + special: "Reduces Special Cooldown of Slasher and Free Spirit characters by 1 turn and changes adjacent orbs into Matching Orbs", + specialName: "Poof [Neo]", + }, + 1865: {//Urouge FN + captain: "Striker Characters ATK 1.75x, protects from defeat as long as HP is above a certain percent", + captainNotes: "PERFECT hits don't count, it has to GREAT hits", + special: "Recover 5000 HP, for 1 turn boost ATK by 1.5x for Striker Characters, if you hit 4 or more GREAT this turn boost ATK by 1.75x for Striker Characters the next turn", + specialName: "Culling the Criminals from this Earthly World" + }, + 1867: {//Hawkins FN + captain: "Cerebral Characters ATK 2x, boost chain multiplier by 1.5x", + special: "Cut HP of all enemies by 10%, for 3 turns cut HP of all enemies by 10%, reduce incoming damage by 40%", + specialName: "Fortune-Telling from the Shadow of Death" + }, + 2000: {//Rayleigh + captain: "Boosts ATK of Slasher and Cerebral characters by 2x", + special: "Randomizes all non-matching orbs, boosts ATK of all characters by 1.75x for 1 turn", + specialName: "Maelstrom at Sea", + }, + 2001: {//Rayleigh + captain: "Boosts ATK of Slasher and Cerebral characters by 2.5x, recovers 2x character's RCV in HP at the end of each turn", + special: "Randomizes all non-matching orbs, boosts ATK of all characters by 1.75x for 1 turn", + specialName: "Maelstrom at Sea", + }, +}; diff --git a/common/data/drops.js b/common/data/drops.js index 5b0987041..908ae8337 100644 --- a/common/data/drops.js +++ b/common/data/drops.js @@ -3,428 +3,753 @@ window.drops = { 'Story Island': [ { - name: "Fushia Village", + name: 'Fushia Village', thumb: 28, global: true, - "01": [ 119, 120 ], - "02": [ 27, 115, 119, 120 ], - "03": [ 28, 78, 79, 80, 119, 120 ] + completion: '5x Rainbow Gems', + gamewith: 3417, + '01': [ 119, 120 ], + '02': [ 27, 115, 119, 120 ], + '03': [ 28, 78, 79, 80, 119, 120 ] }, { - name: "Alvida's Hideout", + name: 'Alvida\'s Hideout', thumb: 29, global: true, - "01": [ 121, 123, 127, 131, 136 ], - "02": [ 78, 79, 80, 121, 122, 123, 126, 131, 132, 137, 138, 141 ], - "03": [ 29, 115, 121, 122, 123, 126, 127, 128, 131, 132, 133, 136, 137, 138, 141, 171 ] + gamewith: 3418, + completion: 'Unlocks Extra Islands', + 'Completion Units': [ 31, 105 ], + '01': [ 121, 123, 127, 131, 136 ], + '02': [ 78, 79, 80, 121, 122, 123, 126, 131, 132, 137, 138, 141 ], + '03': [ 29, 115, 121, 122, 123, 126, 127, 128, 131, 132, 133, 136, 137, 138, 141, 171 ] }, { - name: "Shells Town", + name: 'Shells Town', thumb: 35, global: true, - "01": [ 81, 82, 179, 180, 181, 182 ], - "02": [ 78, 79, 80, 179, 180, 181, 183 ], - "03": [ 33, 81, 82, 179, 180, 181, 182, 183 ], - "04": [ 115, 179, 180, 181, 182, 183 ], - "05": [ 105, 106, 107, 179, 180, 181, 182, 187 ], - "06": [ 116, 179, 180, 181, 188 ], - "07": [ 78, 79, 80, 184, 185, 186, 187 ], - "08": [ 33, 80, 105, 106, 107, 179, 180, 181, 184, 185, 186, 187, 188 ], - "09": [ 35, 89, 90, 91, 116, 184, 185, 186, 187, 188 ] - }, - - { - name: "Orange Town", + completion: 'Ship: Navy Ship', + gamewith: 3423, + 'Completion Units': [5, 80, 97, 116 ], + '01': [ 81, 82, 179, 180, 181, 182 ], + '02': [ 78, 79, 80, 179, 180, 181, 183 ], + '03': [ 33, 81, 82, 179, 180, 181, 182, 183 ], + '04': [ 115, 179, 180, 181, 182, 183 ], + '05': [ 105, 106, 107, 179, 180, 181, 182, 187 ], + '06': [ 116, 179, 180, 181, 188 ], + '07': [ 78, 79, 80, 184, 185, 186, 187 ], + '08': [ 33, 80, 105, 106, 107, 179, 180, 181, 184, 185, 186, 187, 188 ], + '09': [ 35, 89, 90, 91, 116, 184, 185, 186, 187, 188 ] + }, + + { + name: 'Orange Town', thumb: 38, global: true, - "01": [ 115, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 134, 135, 174 ], - "02": [ 78, 121, 126, 136, 142, 147, 170 ], - "03": [ 40, 80, 123, 124, 128, 129, 130, 133, 134, 135, 138, 139, 140, 144, 149, 154, 158, 159, 171 ], - "04": [ 40, 79, 122, 125, 127, 129, 132, 135, 137, 141, 143, 148, 153, 158, 172 ], - "05": [ 38, 40, 78, 79, 80, 81, 82, 124, 125, 129, 130, 134, 135, 136, 137, 138, 139, 140, 147, 148, 149, 157, 158, 159 ], - "06": [ 40, 89, 90, 91, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 162, 173 ], - "07": [ 40, 105, 115, 116, 117, 126, 136, 141, 142, 147, 152, 157, 170 ], - "08": [ 36, 40, 106, 115, 116, 117, 122, 127, 134, 135, 137, 141, 143, 148, 153, 158 ], - "09": [ 40, 107, 115, 116, 117, 124, 125, 139, 140, 141, 144, 149, 154, 159, 162, 174 ], - "10": [ 92, 93, 121, 125, 126, 129, 130, 134, 135, 136, 139, 142, 147, 152, 157, 158, 159, 172 ], - "11": [ 37, 92, 93, 116, 122, 129, 130, 132, 137, 139, 140, 143, 148, 153, 158 ], - "12": [ 81, 82, 123, 128, 133, 134, 135, 138, 139, 140, 144, 149, 154, 159, 171 ], - "13": [ 38, 89, 90, 91, 131, 132, 133, 139, 140, 141, 142, 152, 153, 154, 157, 158, 159, 162 ] - }, - - { - name: "Syrup Village", + completion: '5x Rainbow Gems', + gamewith: 3422, + '01': [ 115, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 134, 135, 174 ], + '02': [ 78, 121, 126, 136, 142, 147, 170 ], + '03': [ 40, 80, 123, 124, 128, 129, 130, 133, 134, 135, 138, 139, 140, 144, 149, 154, 158, 159, 171 ], + '04': [ 40, 79, 122, 125, 127, 129, 132, 135, 137, 141, 143, 148, 153, 158, 172 ], + '05': [ 38, 40, 78, 79, 80, 81, 82, 124, 125, 129, 130, 134, 135, 136, 137, 138, 139, 140, 147, 148, 149, 157, 158, 159 ], + '06': [ 40, 89, 90, 91, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 162, 173 ], + '07': [ 40, 105, 115, 116, 117, 126, 136, 141, 142, 147, 152, 157, 170 ], + '08': [ 36, 40, 106, 115, 116, 117, 122, 127, 134, 135, 137, 141, 143, 148, 153, 158 ], + '09': [ 40, 107, 115, 116, 117, 124, 125, 139, 140, 141, 144, 149, 154, 159, 162, 174 ], + '10': [ 92, 93, 121, 125, 126, 129, 130, 134, 135, 136, 139, 142, 147, 152, 157, 158, 159, 172 ], + '11': [ 37, 92, 93, 116, 122, 129, 130, 132, 137, 139, 140, 143, 148, 153, 158 ], + '12': [ 81, 82, 123, 128, 133, 134, 135, 138, 139, 140, 144, 149, 154, 159, 171 ], + '13': [ 38, 89, 90, 91, 131, 132, 133, 139, 140, 141, 142, 152, 153, 154, 157, 158, 159, 162 ] + }, + + { + name: 'Syrup Village', thumb: 45, global: true, - "01": [ 13, 78, 79, 80, 81, 82, 89, 90, 91, 95, 96, 97, 105, 106, 107, 115 ], - "02": [ 108, 109, 163, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188 ], - "03": [ 92, 93, 124, 125, 126, 127, 128, 147, 148, 149, 160, 161, 165, 166, 174 ], - "04": [ 43, 116, 131, 132, 133, 139, 140, 145, 146, 147, 148, 149, 152, 153, 154, 155, 156, 166, 167 ], - "05": [ 45, 92, 93, 131, 132, 133, 143, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 165, 167 ], - "06": [ 89, 90, 91, 164, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188 ], - "07": [ 116, 117, 165, 166, 167, 168 ], - "08": [ 105, 106, 107, 145, 146, 150, 151, 155, 156, 160, 161, 165, 166, 168, 173 ], - "09": [ 41, 116, 117, 141, 142, 145, 146, 147, 152, 157, 162, 165, 170 ], - "10": [ 42, 116, 117, 144, 149, 150, 151, 154, 159, 166, 169, 171 ], - "11": [ 41, 42, 108, 109, 141, 143, 148, 153, 162, 167, 172 ], - "12": [ 43, 95, 96, 97, 142, 143, 144, 145, 146, 150, 151, 155, 156, 162, 165, 166, 167, 168 ], - "13": [ 45, 105, 106, 107, 165, 166, 167, 168, 169, 170, 171, 172, 174 ] - }, - - { - name: "Baratie", + completion: 'Ship: Merry Go - 5x Rainbow Gems', + gamewith: 3424, + 'Completion Units': [13], + '01': [ 13, 78, 79, 80, 81, 82, 89, 90, 91, 95, 96, 97, 105, 106, 107, 115 ], + '02': [ 108, 109, 163, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188 ], + '03': [ 92, 93, 124, 125, 126, 127, 128, 147, 148, 149, 160, 161, 165, 166, 174 ], + '04': [ 43, 116, 131, 132, 133, 139, 140, 145, 146, 147, 148, 149, 152, 153, 154, 155, 156, 166, 167 ], + '05': [ 45, 92, 93, 131, 132, 133, 143, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 165, 167 ], + '06': [ 89, 90, 91, 164, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188 ], + '07': [ 116, 117, 165, 166, 167, 168 ], + '08': [ 105, 106, 107, 145, 146, 150, 151, 155, 156, 160, 161, 165, 166, 168, 173 ], + '09': [ 41, 116, 117, 141, 142, 145, 146, 147, 152, 157, 162, 165, 170 ], + '10': [ 42, 116, 117, 144, 149, 150, 151, 154, 159, 166, 169, 171 ], + '11': [ 41, 42, 108, 109, 141, 143, 148, 153, 162, 167, 172 ], + '12': [ 43, 95, 96, 97, 142, 143, 144, 145, 146, 150, 151, 155, 156, 162, 165, 166, 167, 168 ], + '13': [ 45, 105, 106, 107, 165, 166, 167, 168, 169, 170, 171, 172, 174 ] + }, + + { + name: 'Baratie', thumb: 57, global: true, - "01": [ 48, 131, 132, 133, 136, 137, 138, 140 ], - "02": [ 49, 116, 117, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188 ], - "03": [ 50, 51, 52, 184, 185, 186, 187, 188 ], - "04": [ 53, 110, 111, 112, 145, 146, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162 ], - "05": [ 57, 105, 106, 107, 122, 123, 132, 142, 147, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161 ], - "06": [ 92, 93, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 136, 137, 138, 142, 143, 144, 148, 149, 153, 154, 158, 159, 160, 161, 170, 171 ], - "07": [ 108, 109, 124, 125, 129, 130, 134, 135, 139, 140, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 172, 173 ], - "08": [ 55, 116, 136, 142, 143, 144, 145, 146, 147, 148, 149, 170 ], - "09": [ 55, 95, 110, 117, 142, 147, 149, 152, 153, 157, 162, 170, 171, 172 ], - "10": [ 105, 106, 107, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 173, 174 ], - "11": [ 55, 96, 111, 117, 143, 144, 148, 149, 152, 153, 154, 158, 159, 162 ], - "12": [ 53, 97, 112, 117, 144, 148, 149, 151, 154, 156, 159 ], - "13": [ 108, 109, 116, 124, 129, 134, 139, 145, 147, 148, 149, 150, 152, 153, 154, 155, 160, 170, 173 ], - "14": [ 92, 93, 116, 125, 130, 135, 140, 146, 151, 156, 157, 158, 159, 161, 171, 172, 174 ], - "15": [ 57, 89, 90, 91, 110, 111, 112, 117, 142, 143, 144, 145, 146, 149, 150, 151, 152, 153, 154, 160, 161, 162, 170, 171, 172 ] - }, - - { - name: "Arlong Park", + completion: 'Ship: Baratie - 5x Rainbow Gems', + gamewith: 3416, + 'Completion Units': [17], + '01': [ 48, 131, 132, 133, 136, 137, 138, 140 ], + '02': [ 49, 116, 117, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188 ], + '03': [ 50, 51, 52, 184, 185, 186, 187, 188 ], + '04': [ 53, 110, 111, 112, 145, 146, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162 ], + '05': [ 57, 105, 106, 107, 122, 123, 132, 142, 147, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161 ], + '06': [ 92, 93, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 136, 137, 138, 142, 143, 144, 148, 149, 153, 154, 158, 159, 160, 161, 170, 171 ], + '07': [ 108, 109, 124, 125, 129, 130, 134, 135, 139, 140, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 172, 173 ], + '08': [ 55, 116, 136, 142, 143, 144, 145, 146, 147, 148, 149, 170 ], + '09': [ 55, 95, 110, 117, 142, 147, 149, 152, 153, 157, 162, 170, 171, 172 ], + '10': [ 105, 106, 107, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 173, 174 ], + '11': [ 55, 96, 111, 117, 143, 144, 148, 149, 152, 153, 154, 158, 159, 162 ], + '12': [ 53, 97, 112, 117, 144, 148, 149, 151, 154, 156, 159 ], + '13': [ 108, 109, 116, 124, 129, 134, 139, 145, 147, 148, 149, 150, 152, 153, 154, 155, 160, 170, 173 ], + '14': [ 92, 93, 116, 125, 130, 135, 140, 146, 151, 156, 157, 158, 159, 161, 171, 172, 174 ], + '15': [ 57, 89, 90, 91, 110, 111, 112, 117, 142, 143, 144, 145, 146, 149, 150, 151, 152, 153, 154, 160, 161, 162, 170, 171, 172 ] + }, + + { + name: 'Arlong Park', thumb: 65, global: true, - "01": [ 89, 121, 126, 131, 136, 141, 142, 147, 152, 156, 157, 158, 159, 160, 162, 170, 173, 175, 178 ], - "02": [ 90, 122, 127, 132, 137, 141, 143, 148, 153, 155, 157, 158, 159, 161, 162, 172, 174, 177 ], - "03": [ 91, 123, 128, 133, 138, 141, 144, 149, 154, 157, 158, 159, 160, 161, 162, 171, 173, 175, 176, 177 ], - "04": [ 59, 92, 93, 179, 180, 181, 182, 184, 185, 186, 187, 188 ], - "05": [ 98, 99, 121, 122, 123, 126, 127, 142, 143, 144, 145, 146, 147, 148, 150, 151, 152, 153, 155, 156, 160, 161, 162, 172, 173, 174, 177 ], - "06": [ 78, 79, 80, 121, 122, 139, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 153, 154, 155, 156, 160, 161, 162, 170, 171, 172, 176 ], - "07": [ 60, 98, 99, 110, 111, 112, 122, 123, 139, 140, 141, 142, 145, 146, 147, 150, 151, 152, 155, 156, 160, 161, 170, 175, 178 ], - "08": [ 61, 110, 111, 112, 116, 117, 131, 133, 137, 143, 145, 146, 148, 153, 158, 172, 175, 176, 177, 178 ], - "09": [ 62, 110, 111, 112, 131, 132, 138, 142, 143, 144, 145, 146, 149, 150, 151, 154, 159, 162, 171, 176, 178 ], - "10": [ 81, 82, 124, 125, 129, 130, 134, 135, 139, 140, 146, 150, 151, 156, 157, 158, 159, 160, 161, 173, 174, 175, 176, 177, 178 ], - "11": [ 63, 117, 121, 123, 126, 127, 128, 131, 132, 133, 136, 138, 139, 140, 142, 143, 145, 146, 147, 149, 150, 151, 155, 156, 160, 161, 162, 170, 172, 175, 176, 177, 178 ], - "12": [ 63, 92, 93, 113, 114, 142, 147, 148, 149, 152, 157, 170, 175, 176, 177, 178 ], - "13": [ 116, 142, 143, 144, 148, 152, 153, 154, 158, 172, 175, 176, 177, 178 ], - "14": [ 65, 117, 123, 133, 136, 137, 138, 142, 143, 144, 149, 152, 153, 154, 159, 171, 175, 176, 177, 178 ], - "15": [ 62, 63, 65, 113, 114, 121, 122, 123, 126, 127, 128, 131, 132, 133, 136, 137, 138, 145, 146, 147, 148, 149, 150, 151, 155, 156, 173, 174, 175, 176, 177, 178 ], - }, - - { - name: "Logue Town", - thumb: 69, - global: true, - "01": [ 174, 170, 171, 172, 84 ], - "02": [ 29, 85 ], - "03": [ 174, 173, 86 ], - "04": [ 36, 87 ], - "05": [ 174, 162, 88 ], - "06": [ 36, 113, 29 ], - "07": [ 37, 114, 38 ], - "08": [ 184, 95 ], - "09": [ 185, 97 ], - "10": [ 67, 180, 181, 182, 183, 96 ], - "11": [ 188, 184, 185, 186, 98, 99 ], - "12": [ 69, 110, 111, 112 ] + completion: '5x Rainbow Gems', + gamewith: 3408, + 'Completion Units': [9], + '01': [ 89, 121, 126, 131, 136, 141, 142, 147, 152, 156, 157, 158, 159, 160, 162, 170, 173, 175, 178 ], + '02': [ 90, 122, 127, 132, 137, 141, 143, 148, 153, 155, 157, 158, 159, 161, 162, 172, 174, 177 ], + '03': [ 91, 123, 128, 133, 138, 141, 144, 149, 154, 157, 158, 159, 160, 161, 162, 171, 173, 175, 176, 177 ], + '04': [ 59, 92, 93, 179, 180, 181, 182, 184, 185, 186, 187, 188 ], + '05': [ 98, 99, 121, 122, 123, 126, 127, 142, 143, 144, 145, 146, 147, 148, 150, 151, 152, 153, 155, 156, 160, 161, 162, 172, 173, 174, 177 ], + '06': [ 78, 79, 80, 121, 122, 139, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 153, 154, 155, 156, 160, 161, 162, 170, 171, 172, 176 ], + '07': [ 60, 98, 99, 110, 111, 112, 122, 123, 139, 140, 141, 142, 145, 146, 147, 150, 151, 152, 155, 156, 160, 161, 170, 175, 178 ], + '08': [ 61, 110, 111, 112, 116, 117, 131, 133, 137, 143, 145, 146, 148, 153, 158, 172, 175, 176, 177, 178 ], + '09': [ 62, 110, 111, 112, 131, 132, 138, 142, 143, 144, 145, 146, 149, 150, 151, 154, 159, 162, 171, 176, 178 ], + '10': [ 81, 82, 124, 125, 129, 130, 134, 135, 139, 140, 146, 150, 151, 156, 157, 158, 159, 160, 161, 173, 174, 175, 176, 177, 178 ], + '11': [ 63, 117, 121, 123, 126, 127, 128, 131, 132, 133, 136, 138, 139, 140, 142, 143, 145, 146, 147, 149, 150, 151, 155, 156, 160, 161, 162, 170, 172, 175, 176, 177, 178 ], + '12': [ 63, 92, 93, 113, 114, 142, 147, 148, 149, 152, 157, 170, 175, 176, 177, 178 ], + '13': [ 116, 142, 143, 144, 148, 152, 153, 154, 158, 172, 175, 176, 177, 178 ], + '14': [ 65, 117, 123, 133, 136, 137, 138, 142, 143, 144, 149, 152, 153, 154, 159, 171, 175, 176, 177, 178 ], + '15': [ 62, 63, 65, 113, 114, 121, 122, 123, 126, 127, 128, 131, 132, 133, 136, 137, 138, 145, 146, 147, 148, 149, 150, 151, 155, 156, 173, 174, 175, 176, 177, 178 ], }, - + { - name: "Twin Cape", + name: 'Logue Town', + thumb: 69, + global: true, + completion: '5x Rainbow Gems', + gamewith: 2807, + '01': [ 174, 170, 171, 172, 84 ], + '02': [ 29, 85 ], + '03': [ 174, 173, 86 ], + '04': [ 36, 87 ], + '05': [ 174, 162, 88 ], + '06': [ 36, 113, 29 ], + '07': [ 37, 114, 38 ], + '08': [ 184, 95 ], + '09': [ 185, 97 ], + '10': [ 67, 180, 181, 182, 183, 96 ], + '11': [ 188, 184, 185, 186, 98, 99 ], + '12': [ 69, 110, 111, 112 ] + }, + + { + name: 'Twin Cape', thumb: 213, global: true, - "01": [ 215, 83, 95, 110 ], - "02": [ 174, 96, 111, 83 ], - "03": [ 173, 174, 97, 112, 83 ], - "04": [ 211, 99, 114, 83 ], - "05": [ 71, 173, 98, 113, 83 ], - "06": [ 71, 211, 84, 83 ], - "07": [ 215, 85, 83 ], - "08": [ 71, 86, 83, 211 ], - "09": [ 213, 87, 88, 83 ], - "10": [ 213, 117, 83, 84, 85, 86, 87, 88, 110, 111, 112, 113, 114 ] - }, - - { - name: "Whiskey Peak", + completion: '5x Rainbow Gems', + gamewith: 3753, + '01': [ 215, 83, 95, 110 ], + '02': [ 174, 96, 111, 83 ], + '03': [ 173, 174, 97, 112, 83 ], + '04': [ 211, 99, 114, 83 ], + '05': [ 71, 173, 98, 113, 83 ], + '06': [ 71, 211, 84, 83 ], + '07': [ 215, 85, 83 ], + '08': [ 71, 86, 83, 211 ], + '09': [ 213, 87, 88, 83 ], + '10': [ 213, 117, 83, 84, 85, 86, 87, 88, 110, 111, 112, 113, 114 ] + }, + + { + name: 'Whiskey Peak', thumb: 201, global: true, - "01": [ 237, 238, 239, 110, 118 ], - "02": [ 111, 118, 240 ], - "03": [ 84, 118, 235 ], - "04": [ 71, 85, 118, 211 ], - "05": [ 114, 118, 241 ], - "06": [ 233, 240, 241, 87, 118 ], - "07": [ 86, 99, 118, 233, 235 ], - "08": [ 113, 118, 240, 241 ], - "09": [ 88, 118, 199 ], - "10": [ 86, 118, 201 ], - "11": [ 98, 117, 118, 240, 241 ], - "12": [ 95, 96, 118, 201 ], - "13": [ 96, 97, 118, 199 ], - "14": [ 95, 97, 118, 199, 201 ], - "15": [ 2, 110, 111, 112, 118 ] - }, - - { - name: "Little Garden", + completion: '5x Rainbow Gems', + gamewith: 4911, + '01': [ 237, 238, 239, 110, 118 ], + '02': [ 111, 118, 240 ], + '03': [ 84, 118, 235 ], + '04': [ 71, 85, 118, 211 ], + '05': [ 114, 118, 241 ], + '06': [ 233, 240, 241, 87, 118 ], + '07': [ 86, 99, 118, 233, 235 ], + '08': [ 113, 118, 240, 241 ], + '09': [ 88, 118, 199 ], + '10': [ 86, 118, 201 ], + '11': [ 98, 117, 118, 240, 241 ], + '12': [ 95, 96, 118, 201 ], + '13': [ 96, 97, 118, 199 ], + '14': [ 95, 97, 118, 199, 201 ], + '15': [ 2, 110, 111, 112, 118, 199, 201 ] + }, + + { + name: 'Little Garden', thumb: 292, global: true, - "01": [ 289, 162, 141, 83, 116, 117 ], - "02": [ 83, 85, 90, 293 ], - "03": [ 83, 84, 89, 294 ], - "04": [ 83, 86, 91, 295 ], - "05": [ 83, 111, 112, 113, 293, 295 ], - "06": [ 83, 88, 93, 292 ], - "07": [ 83, 87, 92, 291 ], - "08": [ 83, 110, 111, 293, 294 ], - "09": [ 83, 110, 112, 293, 294, 295 ], - "10": [ 83, 240, 241, 303 ], - "11": [ 83, 203, 304 ], - "12": [ 83, 205, 302 ], - "13": [ 83, 290, 301 ], - "14": [ 83, 199, 201, 300 ], - "15": [ 113, 114, 83, 110, 111, 112, 203, 205, 300, 301, 302, 303, 304 ] - }, - - { - name: "Drum Island", + completion: '5x Rainbow Gems', + gamewith: 5419, + '01': [ 289, 162, 141, 83, 116, 117 ], + '02': [ 83, 85, 90, 293 ], + '03': [ 83, 84, 89, 294 ], + '04': [ 83, 86, 91, 295 ], + '05': [ 83, 111, 112, 113, 293, 295 ], + '06': [ 83, 88, 93, 292 ], + '07': [ 83, 87, 92, 291 ], + '08': [ 83, 110, 111, 293, 294 ], + '09': [ 83, 110, 112, 293, 294, 295 ], + '10': [ 83, 240, 241, 303 ], + '11': [ 83, 203, 304 ], + '12': [ 83, 205, 302 ], + '13': [ 83, 290, 301 ], + '14': [ 83, 199, 201, 300 ], + '15': [ 113, 114, 83, 110, 111, 112, 203, 205, 300, 301, 302, 303, 304 ] + }, + + { + name: 'Drum Island', thumb: 326, global: true, - "01": [ 328, 94, 117 ], - "02": [ 84, 94, 116, 334 ], - "03": [ 78, 79, 80, 81, 82, 94, 334 ], - "04": [ 85, 94, 110, 330 ], - "05": [ 86, 94, 111, 331 ], - "06": [ 94, 145, 150, 155, 160, 303 ], - "07": [ 24, 21, 87, 113, 333 ], - "08": [ 94, 146, 151, 156, 161, 304 ], - "09": [ 87, 94, 112, 330 ], - "10": [ 88, 94, 113, 331 ], - "11": [ 94, 143, 148, 153, 158, 301 ], - "12": [ 94, 302, 330, 331 ], - "13": [ 94, 300, 326 ], - "14": [ 94, 114, 117, 160, 162, 289 ], - "15": [ 94, 110, 111, 112, 113, 114, 300, 301, 302, 303, 304, 326 ] - }, - - { - name: "Nanohana - Rainbase", - shortName: "Nanohana", + completion: '5x Rainbow Gems', + gamewith: 6658, + 'Completion Units': [21], + '01': [ 328, 94, 117 ], + '02': [ 84, 94, 116, 334 ], + '03': [ 78, 79, 80, 81, 82, 94, 334 ], + '04': [ 85, 94, 110, 330 ], + '05': [ 86, 94, 111, 331 ], + '06': [ 94, 145, 150, 155, 160, 303 ], + '07': [ 24, 21, 87, 113, 333 ], + '08': [ 94, 146, 151, 156, 161, 304 ], + '09': [ 87, 94, 112, 330 ], + '10': [ 88, 94, 113, 331 ], + '11': [ 94, 143, 148, 153, 158, 301 ], + '12': [ 94, 302, 330, 331 ], + '13': [ 94, 300, 326 ], + '14': [ 94, 114, 117, 160, 162, 289 ], + '15': [ 94, 110, 111, 112, 113, 114, 300, 301, 302, 303, 304, 326 ] + }, + + { + name: 'Nanohana - Rainbase', + shortName: 'Alabasta 1', thumb: 383, global: true, - "01": [ 116, 300, 301, 302, 303, 304, 378 ], - "02": [ 69, 300, 301, 302, 303, 304 ], - "03": [ 113, 114, 184, 185, 186, 300, 301, 302, 303, 304 ], - "04": [ 300, 301, 302, 303, 304, 379 ], - "05": [ 84, 300, 301, 302, 303, 304, 368 ], - "06": [ 86, 300, 301, 302, 303, 304, 382 ], - "07": [ 85, 300, 301, 302, 303, 304, 369 ], - "08": [ 87, 88, 300, 301, 302, 303, 304, 372 ], - "09": [ 117, 300, 301, 302, 303, 304, 379, 382 ], - "10": [ 187, 188, 300, 301, 302, 303, 304 ], - "11": [ 300, 301, 302, 303, 304, 371 ], - "12": [ 300, 301, 302, 303, 304, 368 ], - "13": [ 95, 96, 97, 300, 301, 302, 303, 304, 381 ], - "14": [ 98, 99, 203, 300, 301, 302, 303, 304, 381 ], - "15": [ 110, 111, 112, 113, 114, 117, 300, 301, 302, 303, 304, 383 ] - }, - - { - name: "Alubarna", + completion: '5x Rainbow Gems', + gamewith: 7578, + '01': [ 116, 300, 301, 302, 303, 304, 378 ], + '02': [ 69, 300, 301, 302, 303, 304 ], + '03': [ 113, 114, 184, 185, 186, 300, 301, 302, 303, 304 ], + '04': [ 300, 301, 302, 303, 304, 379 ], + '05': [ 84, 300, 301, 302, 303, 304, 368 ], + '06': [ 86, 300, 301, 302, 303, 304, 382 ], + '07': [ 85, 300, 301, 302, 303, 304, 369 ], + '08': [ 87, 88, 300, 301, 302, 303, 304, 372 ], + '09': [ 117, 300, 301, 302, 303, 304, 379, 382 ], + '10': [ 187, 188, 300, 301, 302, 303, 304 ], + '11': [ 300, 301, 302, 303, 304, 371 ], + '12': [ 300, 301, 302, 303, 304, 368 ], + '13': [ 95, 96, 97, 300, 301, 302, 303, 304, 381 ], + '14': [ 98, 99, 203, 300, 301, 302, 303, 304, 381 ], + '15': [ 110, 111, 112, 113, 114, 117, 300, 301, 302, 303, 304, 383 ] + }, + + { + name: 'Alubarna', + shortName: 'Alabasta 2', thumb: 384, global: true, - "01": [ 368, 237, 78, 83, 89 ], - "02": [ 369, 239, 79, 90, 83 ], - "03": [ 207, 80, 91, 83 ], - "04": [ 81, 92, 83, 207 ], - "05": [ 395, 397, 82, 93, 83 ], - "06": [ 300, 301, 83, 395, 397 ], - "07": [ 238, 370, 171, 302, 83, 301 ], - "08": [ 83, 300, 302, 401 ], - "09": [ 116, 117, 83, 399 ], - "10": [ 383, 303, 304, 83 ], - "11": [ 372, 370, 83, 303, 304 ], - "12": [ 170, 171, 172, 371, 105, 106, 107, 108, 109, 83 ], - "13": [ 83, 115, 116, 117, 173, 174, 368, 370 ], - "14": [ 83, 117, 237, 238, 239, 240, 241 ], - "15": [ 110, 111, 112, 83, 383 ] - }, - - { - name: "Jaya", + completion: '10x Rainbow Gems', + gamewith: 8949, + '01': [ 368, 237, 78, 83, 89 ], + '02': [ 369, 239, 79, 90, 83 ], + '03': [ 207, 80, 91, 83 ], + '04': [ 81, 92, 83, 207 ], + '05': [ 395, 397, 82, 93, 83 ], + '06': [ 300, 301, 83, 395, 397 ], + '07': [ 238, 370, 171, 302, 83, 301 ], + '08': [ 83, 300, 302, 401 ], + '09': [ 116, 117, 83, 399 ], + '10': [ 383, 303, 304, 83 ], + '11': [ 372, 370, 83, 303, 304 ], + '12': [ 170, 171, 172, 371, 105, 106, 107, 108, 109, 83 ], + '13': [ 83, 115, 116, 117, 173, 174, 368, 370 ], + '14': [ 83, 117, 237, 238, 239, 240, 241 ], + '15': [ 110, 111, 112, 83, 383 ] + }, + + { + name: 'Jaya', + shortName: 'Jaya', thumb: 430, global: true, - "01": [ 215, 105, 106, 107, 108, 109, 115, 116, 381 ], - "02": [ 171, 91, 97, 96 ], - "03": [ 170, 426, 89, 95 ], - "04": [ 172, 90, 96 ], - "05": [ 174, 93, 99 ], - "06": [ 173, 92, 98 ], - "07": [ 430, 84, 85, 86, 432 ], - "08": [ 142, 147, 152, 284, 300 ], - "09": [ 159, 427, 302 ], - "10": [ 428, 303, 304 ], - "11": [ 143, 148, 153, 158, 301 ], - "12": [ 429, 87, 88, 293, 303, 304 ], - "13": [ 429, 78, 79, 80, 81, 82, 295 ], - "14": [ 142, 149, 153, 160, 289, 113, 114, 294 ], - "15": [ 110, 111, 112, 117, 116, 430 ] - }, - - { - name: "Sky Island: Angel Island - Upper Yard", - shortName: "Angel Island", + completion: 'Ship: Merry Go Flying - 5x Rainbow Gems', + gamewith: 9879, + '01': [ 215, 105, 106, 107, 108, 109, 115, 116, 381 ], + '02': [ 171, 91, 97, 96 ], + '03': [ 170, 426, 89, 95 ], + '04': [ 172, 90, 96 ], + '05': [ 174, 93, 99 ], + '06': [ 173, 92, 98 ], + '07': [ 430, 84, 85, 86, 432 ], + '08': [ 142, 147, 152, 284, 300 ], + '09': [ 159, 427, 302 ], + '10': [ 428, 303, 304 ], + '11': [ 143, 148, 153, 158, 301 ], + '12': [ 429, 87, 88, 293, 303, 304 ], + '13': [ 429, 78, 79, 80, 81, 82, 295 ], + '14': [ 142, 149, 153, 160, 289, 113, 114, 294 ], + '15': [ 110, 111, 112, 117, 116, 430 ] + }, + + { + name: 'Angel Island - Upper Yard', + shortName: 'Skypea 1', thumb: 467, global: true, - "01": [ 488, 487, 489, 493, 494, 116, 117 ], - "02": [ 468, 469, 92, 93, 98, 99 ], - "03": [ 468, 469, 303, 304 ], - "04": [ 469, 468, 113, 114 ], - "05": [ 472, 473, 474, 89, 90, 91, 95, 96, 97 ], - "06": [ 92, 93, 98, 99, 117, 463 ], - "07": [ 472, 473, 474, 170, 171, 172, 300, 301, 302, 303, 304 ], - "08": [ 464, 110, 111, 112 ], - "09": [ 477, 478, 479, 105, 106, 107 ], - "10": [ 480, 475, 481, 476, 108, 109 ], - "11": [ 105, 106, 107, 490, 491, 492, 493, 494 ], - "12": [ 472, 474, 89, 90, 91 ], - "13": [ 466, 108, 109 ], - "14": [ 95, 96, 97, 465, 472 ], - "15": [ 467, 110, 111, 112, 113, 114 ] - }, - - { - name: "Sky Island: Upper Yard - Ark Maxim", - shortName: "Ark Maxim", + completion: '5x Rainbow Gems', + gamewith: 11528, + '01': [ 488, 487, 489, 493, 494, 116, 117 ], + '02': [ 468, 469, 92, 93, 98, 99 ], + '03': [ 468, 469, 303, 304 ], + '04': [ 469, 468, 113, 114 ], + '05': [ 472, 473, 474, 89, 90, 91, 95, 96, 97 ], + '06': [ 92, 93, 98, 99, 117, 463 ], + '07': [ 472, 473, 474, 170, 171, 172, 300, 301, 302, 303, 304 ], + '08': [ 464, 110, 111, 112 ], + '09': [ 477, 478, 479, 105, 106, 107 ], + '10': [ 480, 475, 481, 476, 108, 109 ], + '11': [ 105, 106, 107, 490, 491, 492, 493, 494 ], + '12': [ 472, 474, 89, 90, 91 ], + '13': [ 466, 108, 109 ], + '14': [ 95, 96, 97, 465, 472 ], + '15': [ 467, 110, 111, 112, 113, 114 ] + }, + + { + name: 'Upper Yard - Ark Maxim', + shortName: 'Skypea 2', thumb: 545, global: true, - "01": [ 94, 300, 541 ], - "02": [ 94, 302, 464, 543 ], - "03": [ 94, 303, 542 ], - "04": [ 94, 301, 477, 478, 479 ], - "05": [ 94, 304, 476, 545 ], - "06": [ 464, 78, 79, 83, 88 ], - "07": [ 79, 80, 83, 86, 480, 481, 545 ], - "08": [ 80, 81, 83, 87, 463 ], - "09": [ 81, 82, 83, 85, 465, 473 ], - "10": [ 78, 82, 83, 84, 541 ], - "11": [ 83, 94, 116, 117, 477, 478, 479, 480, 481 ], - "12": [ 83, 98, 99, 113, 114, 117, 118, 545 ] - }, - - { - name: "Long Ring Long Land", + completion: '10x Rainbow Gems', + gamewith: 12130, + '01': [ 94, 300, 541 ], + '02': [ 94, 302, 464, 543 ], + '03': [ 94, 303, 542 ], + '04': [ 94, 301, 477, 478, 479 ], + '05': [ 94, 304, 476, 545 ], + '06': [ 464, 78, 79, 83, 88 ], + '07': [ 79, 80, 83, 86, 480, 481, 545 ], + '08': [ 80, 81, 83, 87, 463 ], + '09': [ 81, 82, 83, 85, 465, 473 ], + '10': [ 78, 82, 83, 84, 541 ], + '11': [ 83, 94, 116, 117, 477, 478, 479, 480, 481 ], + '12': [ 83, 98, 99, 113, 114, 117, 118, 545 ] + }, + + { + name: 'Long Ring Long Land', thumb: 568, global: true, - "01": [ 368, 147, 152, 300 ], - "02": [ 564, 158, 301 ], - "03": [ 171, 144, 149, 302 ], - "04": [ 371, 174, 372, 303, 304 ], - "05": [ 564, 563, 303, 304 ], - "06": [ 147, 148, 149, 368, 105, 106 ], - "07": [ 565, 566, 107, 106 ], - "08": [ 565, 566, 567, 105, 107 ], - "09": [ 142, 149, 153, 160, 289, 108, 109 ], - "10": [ 108, 109, 142, 143, 144, 145, 146, 568 ], - "11": [ 110, 111, 112, 568 ] - }, - - { - name: "Water Seven", + completion: '5x Rainbow Gems', + gamewith: 12773, + '01': [ 368, 147, 152, 300 ], + '02': [ 564, 158, 301 ], + '03': [ 171, 144, 149, 302 ], + '04': [ 371, 174, 372, 303, 304 ], + '05': [ 564, 563, 303, 304 ], + '06': [ 147, 148, 149, 368, 105, 106 ], + '07': [ 565, 566, 107, 106 ], + '08': [ 565, 566, 567, 105, 107 ], + '09': [ 142, 149, 153, 160, 289, 108, 109 ], + '10': [ 108, 109, 142, 143, 144, 145, 146, 568 ], + '11': [ 110, 111, 112, 568 ] + }, + + { + name: 'Water Seven', thumb: 632, global: true, - "01": [ 614, 87, 88, 266 ], - "02": [ 84, 85, 86, 173, 174, 237, 238, 239, 266 ], - "03": [ 110, 266, 615, 616, 617 ], - "04": [ 111, 266, 614, 615, 616 ], - "05": [ 112, 266, 614, 616, 617 ], - "06": [ 113, 114, 266, 614, 615, 616, 617 ], - "07": [ 98, 99, 222, 266 ], - "08": [ 117, 266, 629 ], - "09": [ 266, 302, 319, 620, 621, 625 ], - "10": [ 266, 300, 317, 321, 323, 325, 628 ], - "11": [ 266, 301, 618, 620, 622, 624, 626 ], - "12": [ 266, 303, 336 ], - "13": [ 266, 304, 622, 623, 626, 627 ], - "14": [ 117, 266, 618, 619 ], - "15": [ 117, 266, 300, 301, 302, 303, 304, 620, 621, 625, 630, 632 ] - }, - - { - name: "Enies Lobby: Entrance", - shortName: "Enies Lobby 1", + completion: '5x Rainbow Gems', + gamewith: 14293, + '01': [ 614, 87, 88, 266 ], + '02': [ 84, 85, 86, 173, 174, 237, 238, 239, 266 ], + '03': [ 110, 266, 615, 616, 617 ], + '04': [ 111, 266, 614, 615, 616 ], + '05': [ 112, 266, 614, 616, 617 ], + '06': [ 113, 114, 266, 614, 615, 616, 617 ], + '07': [ 98, 99, 222, 266 ], + '08': [ 117, 266, 629 ], + '09': [ 266, 302, 319, 620, 621, 625 ], + '10': [ 266, 300, 317, 321, 323, 325, 628 ], + '11': [ 266, 301, 618, 620, 622, 624, 626 ], + '12': [ 266, 303, 336 ], + '13': [ 266, 304, 622, 623, 626, 627 ], + '14': [ 117, 266, 618, 619 ], + '15': [ 117, 266, 300, 301, 302, 303, 304, 620, 621, 625, 630, 632 ] + }, + + { + name: 'Enies Lobby Front Gate', + shortName: 'Enies Lobby 1', thumb: 706, - "01": [ 78, 79, 80, 81, 82, 185, 186, 188, 694 ], - "02": [ 78, 79, 80, 81, 184, 185, 187, 692 ], - "03": [ 304, 695, 702 ], - "04": [ 303, 693, 701 ], - "05": [ 301, 692, 703 ], - "06": [ 300, 694, 706 ], - "07": [ 302, 691, 704 ], - "08": [ 110, 111, 112, 691, 692, 694 ], - "09": [ 113, 114, 695, 704, 705 ], - "10": [ 110, 111, 112, 691, 692, 693, 694, 695, 706 ] - }, - - { - name: "Enies Lobby: Tower of Justice - Gates of Justice", - shortName: "Enies Lobby 2", + global: true, + completion: '5x Rainbow Gems', + gamewith: 15599, + 'Completion Units': [708], + '01': [ 78, 79, 80, 81, 82, 185, 186, 188, 694 ], + '02': [ 78, 79, 80, 81, 184, 185, 187, 692 ], + '03': [ 304, 695, 702 ], + '04': [ 303, 693, 701 ], + '05': [ 301, 692, 703 ], + '06': [ 300, 694, 706 ], + '07': [ 302, 691, 704 ], + '08': [ 110, 111, 112, 691, 692, 694 ], + '09': [ 113, 114, 695, 704, 705 ], + '10': [ 110, 111, 112, 691, 692, 693, 694, 695, 706 ] + }, + + { + name: 'Tower of Law - Gates of Justice', + shortName: 'Enies Lobby 2', thumb: 737, - "01": [ 110 ], - "02": [ 111 ], - "03": [ 112 ], - "04": [ 98, 303, 734 ], - "05": [ 95, 300, 732 ], - "06": [ 113 ], - "07": [ 97, 302, 728 ], - "08": [ 99, 304, 730 ], - "09": [ 84, 300, 630 ], - "10": [ 114 ], - "11": [ 85, 86, 87, 738 ], - "12": [ 96, 301, 632 ], - "13": [ 105, 106, 107, 108, 109 ], - "14": [ 113, 114, 300, 301, 632 ] - }, - - { - name: "Thriller Bark: Mouth Gate - Hogback's Residence", - shortName: "Thriller Bark 1", + global: true, + completion: 'Ship: Thousand Sunny - 5x Rainbow Gems', + gamewith: 16618, + 'Completion Units': [739], + '01': [ 110 ], + '02': [ 111 ], + '03': [ 112 ], + '04': [ 98, 303, 734 ], + '05': [ 95, 300, 732 ], + '06': [ 113 ], + '07': [ 97, 302, 728 ], + '08': [ 99, 304, 730 ], + '09': [ 84, 300, 630 ], + '10': [ 114 ], + '11': [ 85, 86, 87, 738 ], + '12': [ 96, 301, 632 ], + '13': [ 105, 106, 107, 108, 109 ], + '14': [ 113, 114, 300, 301, 632 ] + }, + + { + name: 'Mouth Gate - Hogback\'s Mansion', + shortName: 'Thriller Bark 1', thumb: 816, - "01": [ 89, 90, 91, 387, 817, 818, 819, 820, 821 ], - "02": [ 89, 90, 91, 92, 93, 812, 817, 818, 819, 820, 821 ], - "03": [ 116, 817, 818, 819, 820, 821 ], - "04": [ 110, 111, 112, 814, 817, 818, 819 ], - "05": [ 113, 114, 425, 820, 821 ], - "06": [ 110, 111, 112, 814, 817, 818, 819 ], - "07": [ 80, 81, 82, 84, 85, 394, 822, 823, 824 ], - "08": [ 116, 117, 813, 817, 818, 819, 825, 826, 827 ], - "09": [ 116, 117, 820, 821, 825, 826, 827 ], - "10": [ 78, 79, 80, 81, 82, 393, 817, 818, 819, 820, 821, 822, 823, 824 ], - "11": [ 98, 99, 113, 114, 303, 304, 815, 817, 818, 819, 820, 821, 825, 826, 827 ] - }, - - { - name: "Thriller Bark: Moria's Mast Mansion", - shortName: "Thriller Bark 2", + global: true, + completion: '5x Rainbow Gems', + gamewith: 19269, + '01': [ 89, 90, 91, 387, 817, 818, 819, 820, 821 ], + '02': [ 89, 90, 91, 92, 93, 812, 817, 818, 819, 820, 821 ], + '03': [ 116, 817, 818, 819, 820, 821 ], + '04': [ 110, 111, 112, 814, 817, 818, 819 ], + '05': [ 113, 114, 425, 820, 821 ], + '06': [ 110, 111, 112, 814, 817, 818, 819 ], + '07': [ 80, 81, 82, 84, 85, 394, 822, 823, 824 ], + '08': [ 116, 117, 813, 817, 818, 819, 825, 826, 827 ], + '09': [ 116, 117, 820, 821, 825, 826, 827 ], + '10': [ 78, 79, 80, 81, 82, 393, 817, 818, 819, 820, 821, 822, 823, 824 ], + '11': [ 98, 99, 113, 114, 303, 304, 815, 817, 818, 819, 820, 821, 825, 826, 827 ] + }, + + { + name: 'Moria\'s Mast Mansion', + shortName: 'Thriller Bark 2', thumb: 894, - "01": [ 817, 818, 819, 888 ], - "02": [ 393, 888, 889 ], - "03": [ 425 ], - "04": [ 404, 406, 892 ], - "05": [ 818, 822, 823, 824, 827 ], - "06": [ 385, 387, 394, 407, 891 ], - "07": [ 825, 826, 827, 892 ], - "08": [ 825, 826, 827 ], - "09": [ 406, 820, 821, 825, 826, 827 ], - "10": [ 893 ], - "11": [ 893 ], - "12": [ 406, 815 ] - } + global: true, + completion: '5x Rainbow Gems', + gamewith: 22436, + 'Completion Units': [895], + '01': [ 817, 818, 819, 888 ], + '02': [ 393, 888, 889 ], + '03': [ 425 ], + '04': [ 404, 406, 892 ], + '05': [ 818, 822, 823, 824, 827 ], + '06': [ 385, 387, 394, 407, 891 ], + '07': [ 825, 826, 827, 892 ], + '08': [ 825, 826, 827 ], + '09': [ 406, 820, 821, 825, 826, 827 ], + '10': [ 893 ], + '11': [ 893 ], + '12': [ 406, 815 ] + }, + + { + name: 'Sabaody Archipelago', + shortName: 'Sabaody Archipelago', + thumb: 974, + global: true, + completion: '5x Rainbow Gems', + gamewith: 24829, + '01': [ 620, 111, 623, 113, 625, 114, 954, 955, 956 ], + '02': [ ], + '03': [ ], + '04': [ ], + '05': [ ], + '06': [ ], + '07': [ ], + '08': [ 114, 163, 164, 957, 958, 959, 960, 961, 962, 963 ], + '09': [ 112, 142, 144, 154, 157, 159, 170, 173, 174, 289, 618, 623, 624, 625, 626, 957, 958, 959, 961, 962, 964, 965, 967 ], + '10': [ 95, 97, 142, 150, 151, 154, 155, 162, 170, 172, 173, 174, 237, 241, 620, 622, 623, 626, 966 ], + '11': [ ], + '12': [ ], + '13': [ 111, 181, 184, 185, 186, 691, 692, 693, 694, 695, 971 ], + '14': [ 111, 112, 113, 114, 185, 186, 187, 691, 693, 695, 968, 969, 970, 972, 973 ] + }, + + { + name: 'Amazon Lily', + shortName: 'Amazon Lily', + thumb: 1056, + global: true, + completion: '5x Rainbow Gems', + gamewith: 30491, + '01': [ 919, 301, 300 ], + '02': [ 1059, 301, 303 ], + '03': [ 1068, 1067, 302 ], + '04': [ 1062, 1066, 1065, 88, 87 ], + '05': [ 1061, 1062, 86, 84 ], + '06': [ 1063, 1064, 1065, 1066, 1067, 1068, 110, 112 ], + '07': [ 1067, 1068, 88 ], + '08': [ 1055, 1057, 111, 113 ], + '09': [ 1055, 1057, 110, 112 ] + }, + + { + name: 'Impel Down', + shortName: 'Impel Down', + thumb: 1159, + global: true, + completion: '5x Rainbow Gems', + gamewith: 34745, + '01': [ 931 ], + '02': [ 540, 931 ], + '03': [ 1153, 931 ], + '04': [ 1154, 931 ], + '05': [ 1151, 931 ], + '06': [ 1158 ], + '07': [ 1155, 931 ], + '08': [ ], + '09': [ ], + '10': [ ], + '11': [ 551, 539, 1151, 1152, 931, 552 ], + '12': [ 1156, 549 ], + '13': [ ], + '14': [ 1152 ], + '15': [ ], + '16': [ 1158 ], + }, + + { + name: 'Marineford Bay', + shortName: 'Marineford 1', + thumb: 1228, + global: true, + completion: '5x Rainbow Gems', + gamewith: 37190, + '01': [ ], + '02': [ 1223 ], + '03': [ ], + '04': [ ], + '05': [ 1224 ], + '06': [ 1225 ], + '07': [ ], + '08': [ 815 ], + '09': [ 1226 ], + '10': [ 1227 ], + '11': [ ], + '12': [ 1228 ] + }, + + { + name: 'The Bay - Oris Plaza', + shortName: 'Marineford 2', + thumb: 1283, + global: true, + completion: '10x Rainbow Gems', + gamewith: 38886, + '01': [ 1279 ], + '02': [ ], + '03': [ 1280 ], + '04': [ 1228, 771, 770 ], + '05': [ ], + '06': [ 262 ], + '07': [ ], + '08': [ 1281, 1282 ], + '09': [ 1280 ], + '10': [ 1283 ], + '11': [ 1283 ], + '12': [ ], + '13': [ ], + '14': [ 1283 ], + '15': [ 1283 ], + }, + + { + name: '3D2Y', + shortName: '3D2Y', + thumb: 1353, + global: true, + completion: '5x Rainbow Gems', + gamewith: 45559, + '01': [ 1342 ], + '02': [ 1343 ], + '03': [ ], + '04': [ 1344 ], + '05': [ 1345 ], + '06': [ 1346, 'skullUsopp' ], + '07': [ 1347, 'skullChopper' ], + '08': [ 1348, 'skullZoro' ], + '09': [ 1349, 'skullNami' ], + '10': [ 'skullFranky' ], + '11': [ 1350, 'skullBrook' ], + '12': [ 1351, 'skullRobin' ], + '13': [ 1352, 'skullSanji' ], + '14': [ 1353, 'skullLuffy' ], + }, + + { + name: 'Sabaody Archipelago Redux', + shortName: 'Straw Hat Return', + global: true, + thumb: 1393, + completion: 'Ship: Coated Thousand Sunny - 5x Rainbow Gems', + gamewith: 46976, + '01': [ ], + '02': [ ], + '03': [ 1393 ], + '04': [ ], + '05': [ ], + '06': [ ], + '07': [ ], + '08': [ ], + '09': [ 1392 ], + }, + + { + name: 'Deep-Sea Aphotic Zone to Ryugu Palace', + shortName: 'Fishman Island 1', + thumb: 1506, + global: true, + completion: '5x Rainbow Gems', + gamewith: 52247, + '01': [ 1501, 1502 ], + '02': [ 1502, 340 ], + '03': [ ], + '04': [ ], + '05': [ 1503 ], + '06': [ ], + '07': [ ], + '08': [ ], + '09': [ ], + '10': [ ], + '11': [ ], + '12': [ ], + '13': [ 1504 ], + '14': [ 1505 ], + }, + + { + name: 'King Neptune\'s Execution Site - Noah\'s Ark', + shortName: 'Fishman Island 2', + thumb: 1562, + global: true, + completion: '5x Rainbow Gems', + gamewith: 54695, + '01': [ ], + '02': [ ], + '03': [ ], + '04': [ 1560 ], + '05': [ 1558, 1561 ], + '06': [ ], + '07': [ ], + '08': [ ], + '09': [ 1557 ], + '10': [ 1558, 1560 ], + '11': [ 1561 ], + '12': [ 1556 ], + '13': [ 1559 ], + '14': [ 1505 ], + }, + + { + name: 'Punk Hazard Burning Lands - Laboratory', + shortName: 'Punk Hazard 1', + thumb: 1637, + global: true, + completion: '5x Rainbow Gems', + gamewith: 60126, + '01': [ 1633 ], + '02': [ ], + '03': [ ], + '04': [ ], + '05': [ ], + '06': [ ], + '07': [ 1635 ], + '08': [ ], + '09': [ ], + '10': [ ], + '11': [ ], + '12': [ 1634 ], + '13': [ 1634 ], + '14': [ ], + '15': [ 1636 ], + }, + + { + name: 'Punk Hazard Ice Lands - First Floor Room R', + shortName: 'Punk Hazard 2', + thumb: 1716, + completion: '5x Rainbow Gems', + gamewith: 65822, + '01': [ 1636 ], + '02': [ ], + '03': [ ], + '04': [ ], + '05': [ ], + '06': [ 1717 ], + '07': [ 1636 ], + '08': [ ], + '09': [ 1714 ], + '10': [ 1714 ], + '11': [ ], + '12': [ 1718, 1719 ], + '13': [ 1715 ], + '14': [ 1636 ], + }, + + { + name: 'Dressrosa - Harbor Town Acacia Colosseum', + shortName: 'Dressrosa 1', + thumb: 1782, + completion: '5x Rainbow Gems', + gamewith: 70405, + '01': [ ], + '02': [ 1785 ], + '03': [ ], + '04': [ 1781 ], + '05': [ 1782 ], + '06': [ 1648 ], + '07': [ ], + '08': [ 1784 ], + '09': [ 1783 ], + '10': [ ], + '11': [ 1648 ], + '12': [ 1782 ], + }, ], @@ -440,6 +765,7 @@ window.drops = { { name: 'Princess Turtle\'s Dragon Palace', thumb: 595, + global: true, ' ': [ 110, 111, 112, 113, 114, 189, 190, 191, 192, 193, 591, 592, 593, 594, 595 ] }, @@ -485,11 +811,20 @@ window.drops = { }, { - name: 'Scissor Cavern, Intern', + name: 'Scissor Cavern, Inner Cave', day: 4, thumb: 304, + global: true, ' ': [ 89, 90, 91, 92, 93, 95, 96, 97, 98, 99, 300, 301, 302, 303, 304 ] }, + + { + name: 'Scissor Cavern, Deepest Parts', + day: 4, + thumb: 1180, + global: true, + ' ': [ 89, 90, 91, 92, 93, 95, 96, 97, 98, 99, 300, 301, 302, 303, 304, 1180 ] + }, { name: 'Jeweled Porc Sanctuary', @@ -505,7 +840,9 @@ window.drops = { name: 'Buggy\'s Counterattack!!', thumb: 39, global: true, - Expert: [ 36, 37, 38, 99, 109, 114, -4 ], + condition: 'None', + gamewith: 6600, + Expert: [ 36, 37, 38, 99, 109, 114, -4, -1387 ], Elite: [ 36, 37, 38, 99, 109, 114, -3 ] }, @@ -513,7 +850,9 @@ window.drops = { name: 'Alvida\'s Romance', thumb: 30, global: true, - Expert: [ 28, 29, 31, 40, 84, 95, 110, 117, -30, -21, -8 ], + condition: 'None', + gamewith: 7457, + Expert: [ 28, 29, 31, 40, 84, 95, 110, 117, -30, -21, -8, -1388 ], Elite: [ 28, 29, 31, 40, 95, 105, 110, -21, -7 ] }, @@ -521,7 +860,9 @@ window.drops = { name: 'Kuro\'s Master Plan', thumb: 46, global: true, - Expert: [ 41, 42, 43, 45, -16 ], + condition: 'None', + gamewith: 7784, + Expert: [ 41, 42, 43, 45, -16, -1446 ], Elite: [ 41, 42, 43, 45, 96, 106, 111, -15 ] }, @@ -529,7 +870,9 @@ window.drops = { name: 'Arlong: Empire Rising', thumb: 66, global: true, - Expert: [ 61, 62, 63, 65, 89, 95, 105, 110, -12, -66 ], + condition: 'None', + gamewith: 5852, + Expert: [ 61, 62, 63, 65, 89, 95, 105, 110, -12, -66, -1389 ], Elite: [ 61, 62, 63, 65, 95, 105, 110, -11 ] }, @@ -537,22 +880,29 @@ window.drops = { name: 'Krieg\'s Assault!', thumb: 58, global: true, + condition: 'None', + gamewith: 8111, Expert: [ 98, 99, 108, 109, 113, 114, 53, 55, 57, -58, -20 ], - Elite: [ 98, 99, 108, 109, 113, 114, 53, 55, 57, -58, -20, -19 ] + Elite: [ 98, 99, 108, 109, 113, 114, 53, 55, 57, -58, -20, -1447, -19 ] }, { name: 'Escaped! Morgan', thumb: 228, global: true, - Expert: [ 33, 35, 84, 95, 105, 107, 110, 112, -228, -34, -26, -25, -24, -23, -22 ], - Elite: [ 33, 35, 84, 95, 105, 107, 110, 112, -228, -34, -26, -25, -24, -23, -22 ] + condition: 'None', + gamewith: 22603, + 'All Difficulties': [ 33, 35, 84, 95, 105, 107, 110, 112, -228, -34, -26, -25, -24, -23, -22, -1448 ] }, { name: 'Hina\'s Resort Getaway', thumb: 232, global: true, + condition: 'None', + gamewith: 5853, + challenge: 'High Score calculated with Crew Cost, Turns Taken and Tap Accuracy', + challengeData: [['150,000','1x Blue Elder'],['450,000','1x ATK Cotton Candy'],['750,000','3x Rainbow Gems']], Expert: [ 43, 49, 79, 85, 96, 106, 231, -230, -229, -221, -208, -62, -54 ], Elite: [ 43, 49, 96, 111, 117, 231, -230, -229, -221, -208 ] }, @@ -561,22 +911,30 @@ window.drops = { name: 'Cobymeppo\'s Proving Ground!', thumb: 263, global: true, - Expert: [ 31, 33, 262, 264, 87, 88, 98, 99, 113, -265, -263, -225, -210, -64, -56, -32 ], - Elite: [ 31, 33, 262, 264, 87, 88, 98, 99, 113, -265, -263, -225, -210, -64, -56, -32 ] + condition: 'None', + gamewith: 5777, + challenge:'Total number of hits above 50,000', + challengeData: [['5 Times','1x Yellow Elder'],['15 Times','1x ATK Cotton Candy'],['25 Times','3x Rainbow Gems']], + 'All Difficulties': [ 31, 33, 262, 264, 87, 88, 98, 99, 113, -265, -263, -225, -210, -64, -56, -32 ] }, { name: 'Smoker\'s Great Pursuit', thumb: 268, global: true, - Expert: [ 67, 69, 86, 97, 112, -219, -212, -206, -204, -73, -52, -50 ], - Elite: [ 67, 69, 86, 97, 112, -219, -212, -206, -204, -73, -52, -50 ] + condition: 'None', + gamewith: 6725, + challenge: 'Cumulative Damage dealt to enemies in a single run', + challengeData: [['600,000 Damage','1x Green Elder'],['1,400,000 Damage','1y Rainbow Gem & 1x HP Cotton Candy'],['3,000,000 Damage','2x Rainbow Gems, 1x Forbidden Tome']], + 'All Difficulties': [ 67, 69, 86, 97, 112, -219, -212, -206, -204, -73, -52, -50 ] }, { name: 'Tsuru\'s Morning Stroll', thumb: 297, global: true, + condition: 'None', + gamewith: 9181, Expert: [ 99, 88, 114, 296, 298, 299, -236, -234, -223, -217, -202, -200, -199 ], Elite: [ 99, 88, 114, 296, 298, 299, -236, -234, -223, -202, -200 ] }, @@ -585,22 +943,28 @@ window.drops = { name: 'Kalifa\'s Secret Assignment', thumb: 318, global: true, - Expert: [ 86, 97, 110, 112, 317, 319, -259, -253, -216, -215, -62, -56 ], - Elite: [ 86, 97, 110, 112, 317, 319, -259, -253, -216, -215, -62, -56 ] + gamewith: 6204, + condition: 'You may only bring STR units into this island', + 'All Difficulties': [ 86, 97, 110, 112, 317, 319, -259, -253, -216, -215, -62, -56 ] }, { name: 'Lucci\'s Artisan Spirit', thumb: 322, global: true, - Expert: [ 85, 96, 111, 112, 321, 323, 325, -251, -218, -75, -74, -54, -21 ], - Elite: [ 85, 96, 111, 112, 321, 323, 325, -251, -218, -75, -74, -54, -21 ] + gamewith: 5776, + condition: 'You may only bring DEX units for 15 and 30 Stamina', + 'All Difficulties': [ 85, 96, 111, 112, 321, 323, 325, -251, -218, -75, -74, -54, -21 ] }, { name: 'Franky - Pervert\'s Aesthetic!', thumb: 337, global: true, + gamewith: 22596, + condition: 'You may only bring INT units for 15 and 30 Stamina', + challenge: 'Total Damage dealt to enemies in one turn', + challengeData: [['150,000 Damage','1x Yellow Elder'],['400,000 Damage','1x ATK Cotton Candy'],['800,000 Damage','3x Rainbow Gems']], Expert: [ 87, 98, 113, 114, 336, 338, 339, -339, -338, -255, -222, -77, -68 ], Elite: [ 87, 98, 113, 336, 338, 339, -339, -338, -255, -222, -77, -68 ] }, @@ -609,114 +973,157 @@ window.drops = { name: 'Deep Sea Kraken', thumb: 341, global: true, - Expert: [ 28, 40, 60, 213, 215, 340, -292, -291, -290, -261, -257, -214, -71, -44 ], - Elite: [ 28, 40, 60, 213, 215, 340, -292, -291, -290, -261, -257, -214, -71, -44 ] + gamewith: 26802, + condition: 'You may only bring QCK units for 15 and 30 Stamina', + challenge: 'High Score calculated with Crew Cost, Turns Taken and Tap Accuracy', + challengeData: [['200,000 Points','1x Red Elder'],['400,000 Points','1x HP Cotton Candy'],['700,000 Points','3x Rainbow Gems']], + 'All Difficulties': [ 28, 40, 60, 213, 215, 340, -292, -291, -290, -261, -257, -214, -71, -44, -1413 ] }, { name: 'Dr. Hogback\'s Lab of the Dead', thumb: 386, global: true, - Expert: [ 385, 387, -388, -335, -314, -36, -16, -11 ], - Elite: [ 385, 387, -388, -335, -314, -36, -16, -11 ] + gamewith: 25982, + condition: 'You may only bring PSY units for 15 and 30 Stamina', + challenge: 'High Score calculated with Crew Cost, Turns Taken and Tap Accuracy', + challengeData: [['10,000 Points','1x Black Elder'],['40,000 Points','1x Rainbow Gem, 1x ATK Cotton Candy'],['70,000 Points','2x Rainbow Gems, 1x Defence Boost Forbidden Tome']], + 'All Difficulties': [ 385, 387, -388, -335, -314, -36, -16, -1446, -11 ] }, { name: 'Perona\'s Worden Garden', thumb: 392, global: true, - Expert: [ 391, 393, 394, -394, -393, -329, -316, -47, -34, -4 ], - Elite: [ 391, 393, 394, -394, -393, -329, -316, -47, -34, -4 ] + gamewith: 7767, + condition: 'You can only get STR, QCK, INT and Food Orbs', + challenge: 'Total number of hits over 50,000', + challengeData: [['3 Times','1x Green Elder'],['12 Times','1x RCV Cotton Candy'],['25 Times','3x Rainbow Gems']], + 'All Difficulties': [ 391, 393, 394, -394, -393, -329, -316, -47, -34, -4, -1387 ] }, { - name: 'Perv-salom\'s Manly Adventure', + name: 'Perv-salom\'s Very Manly Adventure', thumb: 405, global: true, - Expert: [ 404, 406, 407, -407, -406, -333, -312, -208, -26, -20 ], - Elite: [ 404, 406, 407, -407, -406, -333, -312, -208, -26, -20 ] + gamewith: 6332, + condition: 'You can only get QCK, DEX, PSY and Food Orbs', + 'All Difficulties': [ 404, 406, 407, -407, -406, -333, -312, -208, -26, -20, -1447 ] }, { name: 'Rising Sun, Rising Fortunes', thumb: 420, global: true, - Expert: [ 36, 37, 47, 48, 49, 50, 51, 59, 63, 211, 233, 420, 421, 422, -422, -332, -308, -225, -206, -204, -8 ], - Elite: [ 36, 37, 47, 48, 49, 50, 51, 59, 63, 211, 233, 420, 421, 422, -422, -332, -308, -225, -206, -204, -8 ] + gamewith: 7161, + condition: 'None', + 'All Difficulties': [ 36, 37, 47, 48, 49, 50, 51, 59, 63, 211, 233, 420, 421, 422, -422, -332, -308, -225, -206, -204, -8, -1388 ] }, { name: 'Adrift!? Humming Brook', thumb: 424, global: true, - Expert: [ 423, 425, -425, -327, -310, -223, -219, -214, -202 ], - Elite: [ 423, 425, -425, -327, -310, -223, -219, -214, -202 ] + gamewith: 5383, + condition: 'You can only get STR, DEX, INT and PSY Orbs', + challenge: 'Cumulative Damage dealt to enemies in a single run', + challengeData: [['500,000 Damage','1x Black Elder'],['1,500,000 Damage','1x ATK Cotton Candy'],['3,000,000 Damage','3x Rainbow Gems']], + 'All Difficulties': [ 423, 425, -425, -327, -310, -223, -219, -214, -202 ] }, { - name: 'Little Ms. Candy the Maiden-Hearted!', + name: 'Candy the Maiden-Hearted', thumb: 436, global: true, - Expert: [ 433, 434, 435, -384, -372, -371, -359, -217, -210, -19 ], - Elite: [ 433, 434, 435, -384, -372, -371, -359, -217, -210, -19 ] + gamewith: 7785, + challenge: 'Damage dealt in a single Round', + challengeData: [['350,000','1x Black Elder'], ['900,000','1x HP Cotton Candy'], ['2,000,000','3x Rainbow Gems']], + condition: 'Each non-Okama in your Team will take 60 Damage each turn', + 'All Difficulties': [ 433, 434, 435, -384, -372, -371, -359, -217, -210, -19 ] }, { name: 'Supersonic Duck Squadron!', thumb: 445, global: true, - Expert: [ 290, 293, 294, 295, 334, 379, 381, 382, 441, 442, 443, 444, -378, -368, -363, -251, -73, -15 ], - Elite: [ 290, 293, 294, 295, 334, 379, 381, 382, 441, 442, 443, 444, -378, -368, -363, -251, -73, -15 ] + gamewith: 7566, + condition: 'Higher Chance of Food orbs', + challenge: 'Cumulative Damage dealt to enemies in a single run', + challengeData: [['450,000 Damage','1x Yellow Elder'],['1,250,000 Damage','1x RCV Cotton Candy'],['3,000,000 Damage','3x Rainbow Gems']], + 'All Difficulties': [ 290, 293, 294, 295, 334, 379, 381, 382, 429, 441, 442, 443, 444, -378, -368, -363, -251, -73, -15 ] }, { - name: 'Jailbreaking Baroque Works', + name: 'Prison Break! Baroque Works', thumb: 462, - Expert: [ 460, 461, -398, -396, -370, -361, -253, -236, -234 ], - Elite: [ 460, 461, -398, -396, -370, -361, -253, -236, -234 ] + global: true, + gamewith: 5924, + condition: '30: Non-Fighter, Evolver, or Booster class characters are weakend; 15: Striker and Slasher class characters are weakened (Note: Multi-class characters such as Fighter / Powerhouse are not affected)', + challenge: 'Damage dealt in a single Round', + challengeData: [['???','1x ??? Elder'], ['???','1x ?? Cotton Candy'], ['???','3x Rainbow Gems']], + 'All Difficulties': [ 460, 461, -398, -396, -370, -361, -253, -236, -234 ] }, { name: 'Crocodile: Life on the Inside', thumb: 510, global: true, - Expert: [ 509, 511, -402, -400, -374, -357, -259, -212, -209 ], - Elite: [ 509, 511, -402, -400, -374, -357, -259, -212, -209 ] + gamewith: 5784, + condition: '30: Non-Striker, Evolver, or Booster class characters are weakend; 15: Fighter and Shooter class characters are weakened (Note: Multi-class characters such as Striker / Slasher are not affected)', + challenge: 'Total Damage dealt to enemies in one turn', + challengeData: [['120,000 Damage','1x Blue Elder'],['600,000 Damage','1x HP Cotton Candy, 1x Rainbow Gem'],['2,500,000 Damage','1x Cooldown Reduction Forbidden Tome, 2x Rainbow Gems']], + 'All Difficulties': [ 509, 511, -402, -400, -374, -357, -259, -212, -209 ] }, { - name: 'Jailer Domino\' Special Guard', + name: 'Domino\'s Special Security', thumb: 538, - Expert: [ 537, 539, 540, -539, -428, -416, -365, -257, -59 ], - Elite: [ 537, 539, 540, -539, -428, -416, -365, -257, -59 ] + global: true, + gamewith: 7565, + condition: '30: Non-Shooter, Evolver, or Booster class characters are weakend; 15: Fighter and Slasher class characters are weakened', + challenge: 'Cumulative Damage dealt to enemies in a single run', + challengeData: [['600,000 Damage','1x Yellow Elder'],['2,000,000 Damage','1x HP Cotton Candy, 1x Rainbow Gem'],['5,000,000 Damage','1x Matching Orb Forbidden Tome, 2x Rainbow Gems']], + 'All Difficulties': [ 537, 539, 540, -539, -428, -416, -365, -257, -59, -1445 ] }, { - name: 'Chief Guard Sadi-chan\'s Pun♥ish♥ment', + name: 'Chief Jailer Sadie', thumb: 550, - Expert: [ 549, 551, 552, -552, -551, -432, -426, -408, -329, -308, -255 ], - Elite: [ 549, 551, 552, -552, -551, -432, -426, -408, -329, -308, -255 ] + global: true, + gamewith: 6225, + condition: '30: Non-Slasher, Evolver, or Booster class characters are weakend; 15: Striker and Shooter class characters are weakened', + challenge: 'Cumulative Damage dealt to enemies in a single run', + challengeData: [['600,000 Damage','1x Black Elder'],['2,000,000 Damage','1x ATK Cotton Candy, 1x Rainbow Gem'],['5,000,000 Damage','1x Defence Boost Forbidden Tome, 2x Rainbow Gems']], + 'All Difficulties': [ 549, 551, 552, -552, -551, -432, -426, -408, -329, -308, -255 ] }, { name: 'Brother Soul! Afro Luffy!', thumb: 571, global: true, - Expert: [ 570, 572, 573, -431, -429, -410, -333, -332, -327, -316, -75 ], - Elite: [ 570, 572, 573, -431, -429, -410, -333, -332, -327, -316, -75 ] + gamewith: 5857, + challenge: 'Total number of hits over 50,000', + challengeData: [['3 Times','1x Red Elder'],['12 Times','1x RCV Cotton Candy'],['34 Times','3x Rainbow Gems & 1x Forbidden Tome']], + 'All Difficulties': [ 570, 572, 573, -431, -429, -410, -333, -332, -327, -316, -75 ] }, { - name: 'Warriors of Shandia! Dreams of a Homeland!', + name: 'Shandia - Dreams of a Homeland!', thumb: 583, global: true, - Expert: [ 581, 582, 583, 584, -584, -544, -466, -412, -371, -335, -314, -291 ], - Elite: [ 581, 582, 583, 584, -584, -544, -466, -412, -371, -335, -314, -291 ] + gamewith: 25677, + condition: 'All Units considered from the “Sea” will lose 20% to all stats', + challenge: 'Total number of hits over 50,000', + challengeData: [['4 Times','1x Black Elder'],['16 Times','1x ATK Cotton Candy'],['38 Times','3x Rainbow Gems']], + 'All Difficulties': [ 581, 582, 583, 584, -584, -544, -466, -412, -371, -335, -314, -291 ] }, { - name: 'Pirate Apprentices! Shanks and Buggy', + name: 'Apprentices! Shanks and Buggy!', thumb: 599, + global: true, + gamewith: 6333, + condition: 'You cannot use any two units that are the same', Expert: [ 598, 600, -504, -467, -463, -414, -372, -332, -310, -77 ], Elite: [ 598, 600, -467, -463, -414, -372, -332, -310, -77 ] }, @@ -724,145 +1131,585 @@ window.drops = { { name: 'Raging Cook! Red Leg Zeff', thumb: 607, - Expert: [ 606, 608, 609, -502, -457, -449, -312, -52, -50 ], - Elite: [ 606, 608, 609, -502, -457, -449, -312, -52, -50 ] + global: true, + gamewith: 26093, + condition: 'You cannot use any two units that are the same', + 'All Difficulties': [ 606, 608, 609, -502, -457, -449, -312, -52, -50 ] }, { - name: 'Keimi and Hachi\'s Takoyaki Shop!', + name: 'Camie and Hachi\'s Takoyaki Stand!', thumb: 635, - Expert: [ 634, 636, 637, -636, -464, -451, -396, -370, -367, -359, -64 ], - Elite: [ 634, 636, 637, -636, -464, -451, -396, -370, -367, -359, -64 ] + global: true, + gamewith: 9782, + condition: 'No Units above the cost of 49 is allowed', + challenge: 'Total number of hits over 50,000', + challengeData: [['4 Times','1x Blue Elder'],['8 Times','1x Rainbow Gem, 1x HP Cotton Candy'],['22 Times','2x Rainbow Gems, 1x Orb Matching Forbidden Tome']], + 'All Difficulties': [ 634, 636, 637, -636, -464, -451, -396, -370, -367, -1619, -359, -64 ] }, { - name: 'Invasion! Pirate Arlong\'s Crew!!', + name: 'Shark Attack! Arlong Pirates', thumb: 656, - Expert: [ 655, 657, 658, -658, -500, -465, -455, -453, -398, -357, -60 ], - Elite: [ 655, 657, 658, -658, -500, -465, -455, -453, -398, -357, -60 ] + global: true, + gamewith: 8739, + condition: 'You can only get STR, QCK, DEX, PSY and INT orbs', + 'All Difficulties': [ 655, 657, 658, -658, -500, -465, -455, -453, -398, -357, -60 ] }, { - name: 'Fight! Suna Suna Clan!!', + name: 'Fight! Sand-Sand Band!!', thumb: 664, - Expert: [ 663, 665, 667, -667, -522, -508, -506, -459, -378, -221, -73 ], - Elite: [ 663, 665, 667, -667, -522, -508, -506, -459, -378, -221, -73 ] + global: true, + gamewith: 5504, + condition: 'Heatwave causes damage every 2 turns', + 'Japan': [ 663, 665, 667, -667, -522, -508, -506, -459, -378, -221, -73, -1117 ], + 'Global': [ 663, 665, 667, -667, -639, -508, -506, -459, -378, -221, -73 ] }, { - name: 'Guidance from the Sound of a Bell! Calgara and Noland!', + name: 'Calgara & Noland!', thumb: 688, - Expert: [ 687, 689, -542, -524, -528, -429, -428, -401, -365, -218 ], - Elite: [ 687, 689, -542, -524, -528, -429, -428, -401, -365, -218 ], + global: true, + gamewith: 5352, + condition: 'Bomb orbs appear', + 'Japan': [ 687, 689, -542, -524, -528, -429, -428, -402, -365, -218, -1119, -1177 ], + 'Global': [ 687, 689, -542, -645, -647, -429, -428, -402, -365, -218 ] }, { - name: "Knight of the Sky Gan Fall", + name: 'Sky Night Ganfor', thumb: 713, - Expert: [ 712, 714, 715, -716, -546, -541, -520 ], - Elite: [ 712, 714, 715, -716, -546, -541, -520 ] + global: true, + gamewith: 5882, + condition: '30: Non-Free Spirit, Evolver, or Booster class characters are weakend; 15: Striker and Shooter class characters are weakened', + challenge: 'Cumulative Damage dealt to enemies in a single run', + challengeData: [['600,000','1x Blue Elder'],['2,000,000','1x RCV Cotton Candy, 1x Rainbow Gem'],['5,000,000','1x Lock Resistance Forbidden Tome, 2x Rainbow Gems']], + 'Japan': [ 712, 714, 715, -716, -546, -541, -520, -1115, -400, -202, -363, -204 ], + 'Global': [ 712, 714, 715, -716, -643, -546, -541, -400, -202, -363, -204 ] }, { - name: "T-Bone's Absolute Justice", + name: 'T-Bone\'s Absolute Justice', thumb: 724, - Expert: [ 721, 723, -590, -564, -563, -529, -526, -384, -361, -219 ], - Elite: [ 721, 723, -590, -564, -563, -529, -526, -384, -361, -219 ] + global: true, + gamewith: 5451, + condition: 'You can only bring INT, PSY and QCK units', + 'Japan': [ 721, 723, -590, -564, -563, -530, -1707, -526, -384, -361, -219, -1173 ], + 'Global': [ 721, 723, -590, -564, -563, -530, -1707, -641, -384, -361, -219 ] }, { - name: "Explosive! Wanze's Ramen Kenpo!!", + name: 'Wanze\'s Ramen Kung Fu!!', thumb: 743, - Expert: [ 740, 742, -560, -558, -586, -567, -566, -412, -225, -18 ], - Elite: [ 740, 742, -560, -558, -586, -567, -566, -412, -225, -18 ] + global: true, + gamewith: 7031, + condition: 'You can only bring STR, QCK and DEX units', + 'Japan': [ 740, 742, -560, -558, -586, -567, -566, -412, -225, -18, -1208, -1212 ], + 'Global': [ 740, 742, -671, -673, -586, -567, -566, -412, -225, -18 ] }, { - name: "Twilight Party DEAD or TREAT!!", + name: 'Twilight Party! DEAD or TREAT!!', thumb: 761, - Expert: [ 761, 762, 763, 764, 765, -610, -588, -565, -556, -426, -408, -261, -217 ], - Elite: [ 761, 762, 763, 764, 765, -610, -588, -565, -556, -426, -408, -261, -217 ] - }, - - { - name: "Twilight Party DEAD or TREAT!! (Global)", - thumb: 763, global: true, - Expert: [ 761, 762, 763, 764, 765, -426, -408, -332, -308, -292, -261, -217, -8 ], - Elite: [ 761, 762, 763, 764, 765, -426, -408, -332, -308, -292, -261, -217, -8 ] + gamewith: 25120, + condition: 'None', + 'Japan': [ 761, 762, 763, 764, 765, -610, -588, -565, -556, -426, -408, -261, -217, -1210, -1413 ], + 'Global': [ 761, 762, 763, 764, 765, -426, -408, -332, -308, -292, -261, -217, -8, -1413, -1388 ] }, { - name: "Midnight Party DEAD or TREAT!!", + name: 'Midnight Party! DEAD or TREAT!!', thumb: 766, - Expert: [ 762, 766, 767, 768, 769, -629, -611, -569, -554, -431, -410, -367, -223 ], - Elite: [ 762, 766, 767, 768, 769, -629, -611, -569, -554, -431, -410, -367, -223 ] - }, - - { - name: "Midnight Party DEAD or TREAT!! (Global)", - thumb: 768, global: true, - Expert: [ 762, 766, 767, 768, 769, -431, -367, -291, -253, -251, -223, -212, -75 ], - Elite: [ 762, 766, 767, 768, 769, -431, -367, -291, -253, -251, -223, -212, -75 ] + gamewith: 25101, + condition: 'None', + 'Japan': [ 762, 766, 767, 768, 769, -629, -611, -569, -554, -431, -410, -367, -1619, -223, -1175 ], + 'Global': [ 762, 766, 767, 768, 769, -431, -367, -1619, -291, -253, -251, -223, -212, -75 ] }, { - name: "Evil Manager Breed's Marine Circus!", + name: 'Breed\'s Sea Animal Circus!', thumb: 797, - Expert: [ 796, 798, 799, 800, -800, -639, -628, -562, -414, -432, -380, -75 ], - Elite: [ 796, 798, 799, 800, -800, -639, -628, -562, -414, -432, -380, -75 ] + global: true, + gamewith: 2191, + condition: 'You can only bring Fighter and Powerhouse units', + challenge: 'High Score calculated with Crew Cost, Turns Taken and Tap Accuracy', + challengeData: [['100,000','1x Purple Elder'],['400,000','1x RCV Candy, 1x Rainbow Gem'],['750,000','1x Auto-Heal Skullbook, 2x Rainbow Gem']], + 'Japan': [ 796, 798, 799, 800, -800, -639, -628, -562, -414, -432, -380, -75 ], + 'Global': [ 796, 798, 799, 800, -800, -677, -628, -562, -414, -432, -380, -75 ] }, { - name: "Nami and Lola's Great Proposal Plan", + name: 'Operation: Proposal!', thumb: 808, - Expert: [ 807, 809, 811, -811, -645, -641, -631, -502, -11, -12, -9 ], - Elite: [ 807, 809, 811, -811, -645, -641, -631, -502, -11, -12, -9 ] + global: true, + gamewith: 19169, + condition: 'You can only bring Slasher and Cerebral units. (No Evolution/Booster)', + 'Japan': [ 807, 809, 811, 17, 404, -811, -645, -641, -631, -502, -11, -12, -9, -1389 ], + 'Global': [ 807, 809, 811, 17, 404, -811, -760, -675, -631, -502, -11, -12, -9, -1389 ], }, { - name: "Legendary Shipbuilding Company Tom's Workers", + name:'Tom\'s Workers', thumb: 848, - Expert: [ 847, 849, 850, -849, -647, -617, -616, -615, -578, -508, -455 ], - Elite: [ 847, 849, 850, -849, -647, -617, -616, -615, -578, -508, -455 ] + global: true, + gamewith: 19832, + condition: 'You can only bring Impact and Free Spirit units. (No Evo/Boosters)', + challenge: 'Total Damage dealt to enemies in one turn', + challengeData: [['100,000 Damage','1x DEX Elder Turtle'],['500,000 Damage','1x Rainbow Gem, 1x ATK Cotton Candy'],['2,000,000 Damage','2x Rainbow Gems, 1x Auto-Heal Forbidden Tome']], + 'Japan': [ 847, 849, 850, -849, -647, -617, -616, -615, -578, -508, -455, -1121 ], + 'Global': [ 847, 849, 850, -849, -750, -617, -616, -615, -578, -508, -455, -1121 ] }, { - name: "Wapol's Counterattack", + name: 'Wapol\'s Revenge', thumb: 852, - Expert: [ 328, 330, 331, 333, 851, 853, 854, -854, -649, -643, -614, -463, -457, -327, -22 ], - Elite: [ 328, 330, 331, 333, 851, 853, 854, -854, -649, -643, -614, -463, -457, -327, -22 ] + global: true, + gamewith: 20412, + condition: 'You can only bring Shooter and Driven units. (No Evo/Boosters)', + challenge: 'Cumulative Damage dealt to enemies in a single run', + challengeData: [['400,000 Damage','1x QCK Elder Turtle'],['1,400,000 Damage','1x ATK Cotton Candy, 1x Rainbow Gem'],['4,000,000 Damage','2x Rainbow Gems, 1x Despair Resistance Forbidden Tome']], + 'Japan': [ 328, 330, 331, 333, 851, 853, 854, -854, -649, -643, -614, -463, -457, -327, -22, -1448 ], + 'Global': [ 328, 330, 331, 333, 851, 853, 854, -854, -649, -754, -614, -463, -457, -327, -22, -1448 ] }, { - name: "Lightning Speed! Strawhat Crew's Surprise Visit", + name: 'Lightning Speed! Strawhat Crew\'s Surprise Visit', thumb: 866, - Expert: [ 41, 42, 53, 235, 395, 397, 419, 426, 427, 432, 563, 564, 866, 867, 868, -709, -673, -671, -633, -500, -467, -465, -451, -431 ], - Elite: [ 41, 42, 53, 235, 395, 397, 419, 426, 427, 432, 563, 564, 866, 867, 868, -709, -673, -671, -633, -500, -467, -465, -451, -431 ] + gamewith: 21530, + condition: 'None', + challenge:'Total number of hits above 50,000', + challengeData: [['4 Times','1x INT Elder'],['9 Times','1x ATK Cotton Candy, 1x Rainbow Gem'],['22 Times','1x Despair Resistance Forbidden Tome, 2x Rainbow Gems']], + 'Japan': [ 41, 42, 53, 235, 395, 397, 419, 426, 427, 432, 563, 564, 866, 867, 868, -709, -1549, -673, -671, -633, -500, -467, -465, -451, -431 ], + 'Global': [ 41, 42, 53, 235, 395, 397, 419, 426, 427, 432, 563, 564, 866, 867, 868, -451, -558, -1208, -560, -1212, -465, -500, -633, -709, -1549, -467 ] }, { - name: "Riverside Banquet! Enter the Crazy Ones!", + name: 'Riverside Banquet! Enter the Crazy Ones!', thumb: 885, - Expert: [ 885, 886, 887, -887, -704, -703, -677, -675, -504, -453, -416 ], - Elite: [ 885, 886, 887, -887, -704, -703, -677, -675, -504, -453, -416 ] + global: true, + gamewith: 22421, + condition: 'Highly increased chance of TND, Bomb, and G orbs', + 'All Difficulties': [ 885, 886, 887, -887, -704, -703, -677, -675, -504, -453, -416, -1445 ] }, { - name: "Mountaintop Banquet! Enter the Generals!", + name: 'Mountaintop Banquet! Enter the Generals!', thumb: 897, - Expert: [ 897, 898, 899, -899, -754, -702, -701, -669, -528, -466, -449, -464 ], - Elite: [ 897, 898, 899, -899, -754, -702, -701, -669, -528, -466, -449, -464 ] + gamewith: 23047, + condition: 'Only STR/DEX/QCK/PSY/INT orbs will appear', + 'All Difficulties': [ 897, 898, 899, -899, -754, -702, -701, -669, -1492, -528, -466, -449, -464, -1177 ] }, { - name: "Men are Forbidden!? The Secret Flower Garden", + name: 'The Secret Garden! Men are Forbidden!?', thumb: 918, - Expert: [ 917, 919, 920, -920, -791, -756, -720, -706, -705, -542, -541, -522 ], - Elite: [ 917, 919, 920, -920, -791, -756, -720, -706, -705, -542, -541, -522 ] - } - + global: true, + gamewith: 23687, + condition: 'You can only bring DEX units', + 'Japan': [ 917, 919, 920, -920, -791, -756, -720, -707, -705, -542, -541, -522, -1117 ], + 'Global': [ 917, 919, 920, -920, -506, -756, -720, -707, -705, -542, -541, -522, -1117 ] + }, + + { + name: 'Hannyabal\'s Great Ambition', + thumb: 929, + global: true, + gamewith: 24198, + condition: 'You can only bring STR units', + 'All Difficulties': [ 928, 930, 931, -752, -758, -520, -729, -733, -787, -930, -544, -506, -1115 ] + }, + + { + name: 'Encounter! Whitebeard Pirates', + thumb: 946, + global: true, + gamewith: 25000, + condition: 'You can only bring PSY units', + 'Japan': [ 946, 947, 948, 949, -718, -750, -760, -526, -793, -735, -546, -738, -1173 ], + 'Global': [ 946, 947, 948, 949, -718, -524, -1119, -528, -1177, -526, -793, -735, -546, -738, -1173 ] + }, + + { + name: 'Clash! Whitebeard Pirates', + thumb: 979, + global: true, + gamewith: 25750, + condition: 'You can only bring INT units', + challenge: 'High Score calculated with Crew Cost, Turns Taken and Tap Accuracy', + challengeData: [['150,000','1x Blue Elder'],['420,000','1x HP Cotton Candy, 1x Rainbow Gem'],['700,000','2x Rainbow Gems, 1x Orb Forbidden Tome']], + 'Japan': [ 979, 980, 981, 949, -459, -838, -842, -524, -789, -736, -731, -563, -1119 ], + 'Global': [ 979, 980, 981, 949, -459, -838, -842, -560, -789, -736, -731, -563, -1212 ] + }, + + { + name: 'Let\'s Find Our Captain! Heart Pirates!', + condition: 'You can only bring QCK units', + thumb: 1003, + global: true, + gamewith: 26908, + 'All Difficulties': [ 1002, 1004, 1005, -748, -1663, -844, -558, -846, -737, -1006, -785, -564, -1208 ] + }, + + { + name: 'Butler and Strange Animal Island', + thumb: 1011, + condition: 'None', + global: true, + gamewith: 27631, + 'Global': [ 1010, 1012, 1013, 1014, -1014, -530, -1707, -840, -671, -880, -739, -1550, -812, -565 ], + 'Japan': [ 1010, 1012, 1013, 1014, -1014, -530, -1707, -840, -560, -880, -739, -1550, -812, -565, -1212 ] + }, + + { + name: 'The Queen of Kamabakka Queendom!', + thumb: 1037, + global: true, + gamewith: 29442, + condition: 'Only DEX/RCV/TND orbs will appear', + 'All Dificulties': [ 1036, 1038, -874, -876, -878, -554, -813, -814, -566, -1175 ] + }, + + { + name: 'Archaeologist Nico Olvia', + thumb: 1049, + global: true, + gamewith: 29912, + condition: 'Only TND/RCV/INT orbs will appear', + 'All Difficulties': [ 1048, 1050, 1052, -556, -567, -586, -614, -816, -870, -872, -908, -1210 ] + }, + + { + name: 'Dead End Begins! Raging Blast!', + thumb: 1072, + global: true, + gamewith: 30767, + //OLD condition: 'STR/DEX/QCK units get their ATK boosted by 1.6x and their HP reduced by 90%. INT/PSY units get their ATK reduced by 80% and their HP boosted by 2.0x', + condition: 'STR/DEX/QCK units get their ATK boosted by 1.6x. INT/PSY units get their HP boosted by 2.0x', + 'All Difficulties': [ 1069, 1071, 1073, -562, -906, -914, -645, -890, -587, -629, -888, -1070] + }, + + { + name: 'Golden Lion Pirates\' Attack!', + thumb: 1095, + global: true, + gamewith: 33039, + //OLD condition: 'Boosts ATK of Driven and Powerhouse characters by 2x, other classes get .5x ATK. Boosts HP of Slasher and Fighter characters by 2x, other classes get .5x HP. (This STACKS for characters with multiple classes)', + condition: 'Boosts ATK of Driven characters by 2x and boosts HP for Powerhouse characters by 2x.', + 'All Difficulties': [ 1094, 1096, 1098, -649, -910, -647, -891, -590, -611, -893, -1098, -912] + }, + + { + name: 'Robin and Nami\'s Secret Undercover Investigation', + thumb: 1112, + global: true, + gamewith: 33849, + condition: 'Boosts ATK of Cerebral and Free Spirit characters by 2x, other classes get .5x ATK. Boosts HP of Striker and Shooter characters by 2x, other classes get .5x HP. (This STACKS for characters with multiple classes)', + 'All Difficulties': [ 1109, 1111, 1113, -23, -628, -639, -641, -892, -937, -939, -941 ] + }, + + { + name: 'Behind the Scenes Intelligency Agency: CP9', + thumb: 1137, + global: true, + gamewith: 34515, + condition: 'Only [STR], [QCK], [DEX], [INT], and [PSY] orbs appear', + 'All Difficulties': [ 1136, 1137, 1138, 1139, -935, -643, -673, -894, -943, -995, -615, -705, -704 ] + }, + + { + name: 'Welcome To The Gran Tesoro!', + thumb: 1167, + global: true, + gamewith: 35095, + condition: 'None', + 'All Difficulties': [ 1166, 1168, 1170, -578, -999, -991, -993, -675, -508, -616, -703, -1121 ] + }, + + { + name: 'Rumbar Pirates!', + thumb: 1203, + global: true, + gamewith: 35905, + condition: '\'Musical\' units get their stats boosted by 1.5x (Dancers, Singers, Playing an instrument, etc)', + 'All Difficulties': [ 1202, 1204, 1206, -1001, -997, -558, -1208, -677, -896, -1551, -631, -954, -1206, -617, -1027 ] + }, + + { + name: 'World Pirates!', + thumb: 1215, + global: true, + gamewith: 36738, + condition: 'Total Crew Cost must be lower than 180 (Including friend captain)', + 'All Difficulties': [ 1215, 1216, 1217, 1218, -1025, -1029, -1033, -671, -956, -964, -633, -504, -1218 ] + }, + + { + name: 'Revealing the Truth!', + thumb: 1242, + global: true, + gamewith: 37425, + condition: 'Free Spirit Characters have their cooldowns reduced by 10 turns at the start of the fight', + 'All Difficulties': [ 1241, 1243, -1035, -965, -1031, -1081, -754, -966, -502, -707, -955 ] + }, + + { + name: 'Gather! Whitebeard Alliance', + thumb: 1254, + global: true, + gamewith: 38336, + condition: 'Driven Characters have their cooldowns reduced by 10 turns at the start of the fight', + 'All Difficulties': [ 1254, 1255, 1256, -669, -1492, -1077, -1079, -967, -972, -974, -750, -701, -500 ] + }, + + { + name: 'Young Donquixote Pirates - Baby 5 And Buffalo', + thumb: 1287, + global: true, + gamewith: 39522, + condition: 'Child-like characters get their ATK and HP boosted by 3.5x, RCV by 1.5x, and cooldowns reduced by 7 turns at the start of the fight', + 'All Difficulties': [ 1286, 1288, 1290, -963, -1045, -251, -760, -1083, -1129, -506, -1062, -702 ] + }, + + { + name: 'Jailbreak Battle! Mr. 3 and Buggy', + thumb: 1304, + global: true, + gamewith: 41928, + condition: 'Shooter and Fighter characters are Silenced for 99 turns and have their ATK reduced by a variable amount. (75% on 30 stamina)', + 'All Difficulties': [ 1301, 1303, 1152, 1151, 551, 539, -718, -752, -1125, -1133, -15, -203, -733, -1056, -1060 ] + }, + + { + name: 'Tontatta Tribe: Catch the Big Person!', + thumb: 1328, + global: true, + gamewith: 44164, + condition: 'Slasher characters are Silenced for 99 turns and have their ATK reduced by a variable amount. (75% on 30 stamina)', + 'All Difficulties': [ 1327, 1329, 1330, -1085, -1127, -1131, -1058, -758, -760, -735, -4, -508, -1387 ] + }, + + { + name: 'Tontatta Tribe: Find the Beloved Prince?!', + thumb: 1332, + global: true, + gamewith: 44747, + condition: 'Striker characters are Silenced for 99 turns and have their ATK reduced by a variable amount. (70% on 30 stamina)', + 'All Difficulties': [ 1331, 1333, 1334, -720, -1186, -1190, -756, -1188, -1151, -1153, -738 ] + }, + + { + name: 'Gather the Candy!', + thumb: 1357, + global: true, + gamewith: 45801, + 'All Difficulties': [ 1356, 1358, -1123, -1184, -1182, -1152, -1157, -8, -840, -736, -610, -1388 ] + }, + + { + name: 'Fight for your Happiness!', + thumb: 1384, + global: true, + gamewith: 46658, + condition: 'Limited amount of turns to complete the mission.', + 'All Difficulties': [ 1383, 1385, -748, -1663, -1234, -1075, -1230, -1155, -1154, -846, -842, -739, -1550 ] + }, + + { + name: 'Shambles! Tashigi and Smoker?!?', + thumb: 1397, + global: true, + gamewith: 47247, + condition: 'Your captain will be switched with your middle right character when you encounter Law.', + 'All Difficulties': [ 1396, 1398, -1192, -1764, -1232, -1238, -844, -838, -1159, -1389, -12, -737, -257 ] + }, + + { + name: 'Marines! Sengoku the Fleet Admiral!', + thumb: 1416, + global: true, + gamewith: 48079, + condition: 'You can only bring INT units', + 'All Difficulties': [ 1415, 1417, 1418, -1418, -870, -1276, -1274, -1236, -874, -253, -1223, -813 ] + }, + + { + name: 'Chinjao Family!', + thumb: 1426, + global: true, + gamewith: 49862, + condition: 'You can only bring DEX units', + 'All Difficulties': [ 1425, 1427, 1428, -1240, -1272, -1270, -1227, -1224, -872, -878, -255, -812 ] + }, + + { + name: 'Fugitive of Love and Passion!!', + thumb: 1450, + global: true, + gamewith: 50895, + condition: 'You can only bring STR units', + 'All Difficulties': [ 1449, 1451, -935, -1278, -1318, -1324, -880, -876, -259, -1226, -814 ] + }, + + { + name: 'Gatekeeper of the New World!', + thumb: 1469, + global: true, + gamewith: 51926, + condition: 'You can only bring QCK units', + 'All Difficulties': [ 1468, 1470, 1471, -1268, -1322, -1228, -906, -914, -310, -1061, -1470, -1320 ] + }, + + { + name: 'Departure! Whitebeard Pirates', + thumb: 1509, + global: true, + gamewith: 52629, + condition: 'You can only bring PSY units', + 'All Difficulties': [ 1509, 1510, 1511, 1512, -1001, -1316, -1280, -314, -908, -16, -1446, -1370, -1368, -816 ], + }, + + { + name: 'Bandits! Dadan Family!', + thumb: 1520, + global: true, + gamewith: 53569, + 'All Difficulties': [ 1519, 1521, 1522, -1314, -1366, -1364, -912, -937, -316, -1281, -891, -22, -1448 ], + }, + + { + name: 'Encourage the Soul!', + thumb: 1547, + global: true, + gamewith: 54302, + condition: 'Strawhat Pirates get ATK, HP, and RCV boosted by 1.5x and reduces cooldown of specials by 9 turns at the start of the fight', + 'All Difficulties': [ 1546, 1548, -1035, -1410, -1406, -939, -943, -312, -1279, -1282, -1447, -20 ], + }, + + { + name: 'Fight for your Friends!', + thumb: 1564, + global: true, + gamewith: 55145, + condition: 'Elizabello will kill you with one punch', + 'All Difficulties': [ 1563, 1565, -1362, -1408, -1412, -941, -991, -308, -1283, -892, -1549, -709 ], + }, + + { + name: 'The Mysterious Warlord!', + thumb: 1581, + gamewith: 56038, + 'All Difficulties': [ 1580, 1582, -1391, -1444, -1436, -1551, -896, -910, -357, -995, -890, -1342 ], + }, + + { + name: 'Targeted Mermaid Princess!', + thumb: 1597, + gamewith: 57039, + 'All Difficulties': [ 1596, 1598, 1599, -1045, -359, -999, -1033, -1550, -739, -1438, -1440, -893, -1343 ], + }, + + { + name: 'The Dark Path of the Blackbeard Pirates!', + thumb: 1606, + gamewith: 57820, + 'All Difficulties': [ 1606, 1607, 1608, -1404, -1593, -1481, -1442, -1029, -361, -363, -997, -894, -1344 ], + }, + + { + name: 'The Time of Revenge has Come! New Fishman Pirates!', + thumb: 1624, + gamewith: 59321, + 'All Difficulties': [ 1624, 1625, 1626, -1434, -1477, -1475, -410, -365, -993, -1031, -954, -1347 ], + }, + + { + name: 'Seeking The Best Art! Giolla and Brook!', + thumb: 1649, + gamewith: 60685, + condition: 'You must have at least one character of each type on your team: STR, DEX, QCK, PSY, and INT.', + 'All Difficulties': [ 1648, 1650, -1473, -1483, -412, -414, -1075, -1027, -1479, -1348, -956 ], + }, + + { + name: 'Open the Cafe!', + thumb: 1670, + gamewith: 61622, + condition: 'Total Crew Cost must be lower than 180 (Including friend captain)', + 'All Difficulties': [ 1670, 1671, 1672, -1085, -451, -457, -1081, -1353, -1540, -1345, -955, -1350 ], + }, + + { + name: 'Kid Pirates!', + thumb: 1690, + gamewith: 62883, + condition: 'Only [INT] and [PSY] orbs appear', + 'All Difficulties': [ 1689, 1691, 1692, -1532, -1543, -449, -453, -1079, -1538, -967, -1346, -1349 ], + }, + + { + name: 'Royal Neptune Family!', + thumb: 1723, + gamewith: 64138, + condition: 'Strikers and Powerhouse characters get a boost (1.5x ATK boost on 30 stamina)', + 'All Difficulties': [ 1722, 1724, -1123, -455, -1077, -560, -1212, -1536, -1577, -1579, -966, -1352 ], + }, + + { + name: 'Underground Trade Port! Escape!', + thumb: 1735, + gamewith: 66021, + condition: 'Limited amount of turns to complete the mission.', + 'All Difficulties': [ 1734, 1736, -1571, -1573, -1654, -641, -1182, -1188, -1210, -556, -964, -1354 ] + }, + + { + name: 'Battle Royale!', + thumb: 1766, + gamewith: 67118, + 'All Difficulties': [ 1765, 1767, 1768, -1192, -1764, -520, -1115, -1184, -1190, -554, -1175, -1612, -1614, -1353, -1393 ] + }, + + { + name: 'Wano Samurai!', + thumb: 1774, + condition: 'Shooter and Free Spirit characters get a boost (1.2x ATK, HP and RCV boost on 30 stamina)', + gamewith: 68608, + 'All Difficulties': [ 1773, 1775, -963, -1588, -451, -1186, -528, -1177, -1208, -558, -1616, -1618, -1392 ] + }, + + { + name: 'Zou Royal Guard!', + thumb: 1812, + condition: 'Powerhouse Characters will be weakened', + gamewith: 71416, + 'All Difficulties': [ 1811, 1809, -1240, -1575, -1658, -1232, -1238, -1117, -522, -1119, -524, -1504, -1503 ] + }, + + { + name: 'Crisis of the 800 Year Old Kingdom!', + thumb: 1818, + gamewith: 72655, + 'All Difficulties': [ 1817, 1819, 1820, -1610, -1656, -1660, -1230, -1236, -1173, -526, -643, -1506, -964 ] + }, + + { + name: 'Caribou Pirates!', + thumb: 1842, + gamewith: 75879, + condition: '[STR] orbs will not appear naturally', + 'All Difficulties': [ 1841, 1843, -1268, -639, -645, -1234, -1270, -1700, -1704, -1501, -1502 ] + }, + + { + name: 'Supernova! Worst Generation!', + thumb: 1855, + gamewith: null, + 'All Difficulties': [ 1854, 1856, -1652, -1272, -1278, -1620, -1702, -1558 ] + }, + ], @@ -872,14 +1719,27 @@ window.drops = { name: 'Clash!! Mihawk', thumb: 227, global: true, + gamewith: 4142, + teamDatabase: 'raid_bosses/3', Master: [ 86, 112, 118, 226 ], Expert: [ 97, 112, 226 ] }, + + { + name: 'Clash Neo!! Mihawk', + thumb: 1680, + global: true, + gamewith: 62444, + Master: [ 85, 111, 118, 1679 ], + Expert: [ 96, 111, 1679 ] + }, { name: 'Clash!! Chopper\'s Rampage', thumb: 249, global: true, + gamewith: 5210, + teamDatabase: 'raid_bosses/4', Master: [ 84, 110, 118, 248 ], Expert: [ 84, 110, 248 ] }, @@ -888,12 +1748,17 @@ window.drops = { name: 'Clash!! Vice-Admiral Garp', thumb: 306, global: true, + gamewith: 5905, + teamDatabase: 'raid_bosses/5', Master: [ 113, 118, 262, 264, 305 ], }, { name: 'Clash!! Black Arm Zephyr', thumb: 353, + global: true, + gamewith: 7293, + teamDatabase: 'raid_bosses/27', Master: [ 88, 114, 118, 352, 354 ], Expert: [ 99, 114, 117, 352, 354 ] }, @@ -902,6 +1767,8 @@ window.drops = { name: 'Clash!! Ivankov', thumb: 390, global: true, + gamewith: 8285, + teamDatabase: 'raid_bosses/6', Master: [ 85, 111, 118, 389 ], Expert: [ 85, 96, 111, 389 ] }, @@ -910,14 +1777,27 @@ window.drops = { name: 'Clash!! Doflamingo', thumb: 418, global: true, + gamewith: 9037, + teamDatabase: 'raid_bosses/7', Ultimate: [ 86, 112, 118, 302, 417 ], Master: [ 86, 97, 112, 417 ] }, + { + name: 'Clash Neo!! Doflamingo', + thumb: 1623, + condition: '1 Master version and 3 different Ultimate versions with different conditions. Master: Striker/Cerebral/Fighter Only. Ultimate: Striker Only, Cerebral Only, and Fighter Only', + gamewith: 58437, + Ultimate: [ 1622 ], + Master: [ 1622 ] + }, + { name: 'Clash!! Blackbeard', thumb: 447, global: true, + gamewith: 11051, + teamDatabase: 'raid_bosses/8', Master: [ 84, 110, 118, 300, 446 ], Expert: [ 84, 110, 446 ] }, @@ -925,12 +1805,18 @@ window.drops = { { name: 'Clash!? Usopp\'n', thumb: 518, - 'Ultimate': [ 517 ] + showManual: true, + global: true, + gamewith: 12014, + 'Ultimate': [ 517, -15, -16, -1446, -223 ] }, { name: 'Clash!! Heracles\'n', thumb: 516, + global: true, + gamewith: 11958, + teamDatabase: 'raid_bosses/9', Master: [ 87, 97, 113, 117, 118, 294, 295, 303, 429, 515 ], Expert: [ 87, 98, 113, 117, 293, 295, 429, 379, 515 ] }, @@ -938,14 +1824,30 @@ window.drops = { { name: 'Clash!! Aokiji', thumb: 575, + global: true, + gamewith: 12792, + teamDatabase: 'raid_bosses/10', Ultimate: [ 88, 114, 118, 304, 574 ], Master: [ 114, 118, 574 ] }, + { + name: 'Clash Neo!! Aokiji', + thumb: 1669, + global: true, + condition: '1 Master version and 3 different Ultimate versions with different conditions. Master: Free Spirit/Shooter/Striker Only. Ultimate: Free Spirit Only, Shooter Only, and Striker Only', + gamewith: 61262, + Ultimate: [ 86, 112, 118, 302, 1668 ], + Master: [ 112, 118, 1668 ] + }, + { name: 'Clash!! Eneru', thumb: 603, global: true, + gamewith: 13682, + teamDatabase: 'raid_bosses/11', + condition: 'Take 300 damage per character in Environmental Lightning Damage every 3 turns', Ultimate: [ 85, 111, 118, 301, 602 ], Master: [ 85, 111, 118, 602 ] , Expert: [ 111, 118, 602 ] @@ -954,6 +1856,9 @@ window.drops = { { name: 'Clash!! Duval', thumb: 654, + global: true, + gamewith: 14747, + teamDatabase: 'raid_bosses/12', Master: [ 112, 118, 302, 652 ], Expert: [ 86, 97, 112, 652 ] }, @@ -961,6 +1866,9 @@ window.drops = { { name: 'Clash!! Buster Call', thumb: 771, + global: true, + gamewith: 17344, + teamDatabase: 'raid_bosses/13', Master: [ 110, 111, 112, 113, 114, 770, 771, 772, 773, 774, 775 ], Expert: [ 110, 111, 112, 113, 114, 770, 771, 772, 773, 774, 775 ] }, @@ -968,6 +1876,10 @@ window.drops = { { name: 'Clash!! Nightmare Luffy', thumb: 795, + global: true, + gamewith: 18565, + teamDatabase: 'raid_bosses/28', + condition: 'Take 10% current Health in Environmental Damage every 2 turns', Master: [ 794 ], Expert: [ 794 ] }, @@ -975,17 +1887,220 @@ window.drops = { { name: 'Clash!! Tyrant Kuma', thumb: 836, - Master: [ 835 ], - Expert: [ 835 ] + global: true, + gamewith: 19424, + teamDatabase: 'raid_bosses/14', + Ultimate: [ 835 ], + Master: [ 835 ] + }, + + { + name: 'Clash Neo!! Tyrant Kuma', + thumb: 1772, + gamewith: 67120, + condition: '1 Master version and 3 Ultimate versions with different conditions. Master: Shooter/Slasher/Cerebral Only. Can only complete 10 times each. Ultimate: Shooter Only, Slasher Only, and Cerebral Only', + Ultimate: [ 1771 ], + Master: [ 1771 ] }, { name: 'Clash!! Pirate Empress Hancock', thumb: 865, + global: true, + gamewith: 21345, + teamDatabase: 'raid_bosses/15', Ultimate: [ 864 ], Master: [ 864 ], Expert: [ 864 ] - } + }, + + { + name: 'Clash!! Pica', + thumb: 932, + global: true, + gamewith: 23507, + teamDatabase: 'raid_bosses/24', + Master: [ 932 ], + Expert: [ 932 ] + }, + + { + name: 'Clash Neo!! Pica', + thumb: 1647, + gamewith: 60095, + condition: '1 Expert version and 3 different Master versions with different conditions. Expert: Powerhouse/Driven/Slasher Only. Master: Powerhouse Only, Driven Only, and Slasher Only', + Master: [ 1646 ], + Expert: [ 1646 ] + }, + + { + name: 'Clash!! Kizaru', + thumb: 978, + global: true, + gamewith: 25109, + teamDatabase: 'raid_bosses/16', + Ultimate: [ 977 ], + Master: [ 977 ] + }, + + { + name: 'Clash Neo!! Kizaru', + thumb: 1780, + gamewith: 68681, + condition: '1 Master version and 3 Ultimate versions with different conditions. Master: Free Spirit/Striker/Powerhouse Only. Can only complete 10 times each. Ultimate: Free Spirit Only, Striker Only, and Powerhouse Only', + Ultimate: [ 1779 ], + Master: [ 1779 ] + }, + + { + name: 'Clash!? Impostor Straw Hat Pirates', + showManual: true, + global: true, + gamewith: 26803, + thumb: 989, + Ultimate: [ 985, 986, 987, 988, -989, -4, -8, -11, -12, -15, -16, -1446, -556, -528, -520, -554, -558, -20, -1447, -217, -709, -1549, -1115, -1177, -1175, -1210, -1208, -1387, -1388, -1389 ] + }, + + { + name: 'Clash!! Sabo', + global: true, + gamewith: 29788, + teamDatabase: 'raid_bosses/17', + thumb: 1047, + Ultimate: [ 1046 ], + Master: [ 1046 ], + Expert: [ 1046 ] + }, + + { + name: 'Clash Neo!! Sabo', + global: true, + gamewith: 64230, + thumb: 1727, + condition: '1 Expert version, 1 Master version, and 3 different Ultimate versions with different conditions. Expert/Master: Shooter/Fighter/Cerebral Only. Can only complete 10 times each. Ultimate: Shooter Only, Fighter Only, and Cerebral Only', + Ultimate: [ 1726 ], + Master: [ 1726 ], + Expert: [ 1726 ] + }, + + { + name: 'Clash!! Shiki', + thumb: 1108, + global: true, + gamewith: 33648, + teamDatabase: 'raid_bosses/25', + Ultimate: [ 1107 ], + Master: [ 1107 ], + Expert: [ 1107 ] + }, + + { + name: 'Clash!! Gild Tesoro', + thumb: 1163, + global: true, + gamewith: 35950, + teamDatabase: 'raid_bosses/26', + Master: [ 1162, 1164 ], + Ultimate: [ 1162, 1164, 1180 ] + }, + + { + name: 'Clash!! Akainu', + thumb: 1298, + global: true, + gamewith: 41277, + teamDatabase: 'raid_bosses/18', + Ultimate: [ 1297 ] + }, + + { + name: 'Clash Neo!! Akainu', + thumb: 1826, + gamewith: 73951, + condition: '1 Master version and 3 different Ultimate versions with different conditions. Master: Shooter/Striker/Slaher Only. Ultimate: Shooter Only, Striker Only, and Slasher Only', + Ultimate: [ 1825 ], + Master: [ 1825 ], + }, + + { + name: 'Clash!! Warden Magellan', + thumb: 1374, + global: true, + condition: 'Take 7% MAX Health in Environmental Damage', + gamewith: 45906, + Master: [ 1373 ], + Expert: [ 1373 ], + }, + + { + name: 'Clash!! Shogun Franky', + thumb: 1432, + gamewith: 50030, + Master: [ 1431, 215, 799 ], + Ultimate: [ 1431, 215, 799 ], + }, + + { + name: 'Clash!! Bellamy', + thumb: 1518, + global: true, + gamewith: '%20%2053151', + Master: [ 1517 ], + Expert: [ 1517 ], + }, + + { + name: 'Clash Neo!! Bellamy', + thumb: 1738, + gamewith: 66087, + condition: '1 Expert version and 3 Master versions with different conditions. Expert: Driven/Free Spirit/Striker Only. Can only complete 10 times each. Master: Driven Only, Free Spirit Only, and Striker Only', + Master: [ 1738 ], + Expert: [ 1738 ], + }, + + { + name: 'Clash!! Fujitora', + thumb: 1595, + gamewith: 56946, + Ultimate: [ 1594 ], + Master: [ 1594 ], + Expert: [ 1594 ] + }, + + { + name: 'Clash!! Vergo', + thumb: 1696, + gamewith: 63217, + Master: [ 1695 ], + Expert: [ 1695 ] + }, + + { + name: 'Clash!! Vinsmoke Sanji', + thumb: 1815, + gamewith: 70374, + Ultimate: [ 1814 ], + Master: [ 1814 ], + Expert: [ 1814 ] + }, + + { + name: 'Clash!! Caesar', + thumb: 1830, + gamewith: null, + condition: 'Take 10% MAX Health in Environmental Damage every 2 turns', + Master: [ 1829 ], + Expert: [ 1829 ] + }, + + { + name: 'Clash!! Rayleigh', + global: true, + thumb: 2001, + gamewith: null, + Ultimate: [ 2000 ], + Master: [ 2000 ] + }, ], @@ -994,28 +2109,369 @@ window.drops = { { name: 'Chopper\'s Sweet Special Adventure', thumb: 247, + global: true, '': [ 247 ] }, { - name: 'Battle Royal! Oars', - thumb: 414, - 'Master': [ -367, -316, -314, -312, -308, -259, -257, -255, -253, -251, -221, -218, -217, -210, -75, -30, -16, -15, -8 ] + name: 'Ace Training Ground', + thumb: 1605, + global: true, + 'All Difficulties': [ 1604 ], + }, + + { + name: 'Battle Royale! Oars', + thumb: 893, + global: true, + challenge:'Total number of hits above 50,000', + challengeData: [['6 Times','1x Forbidden Tome + 1x Red Elder'],['14 Times','1x Forbidden Tome, 1x RCV Cotton Candy, 1x Rainbow Gem'],['32 Times','1x Bind Resistance Forbidden Tome, 2x Rainbow Gems']], + 'All Difficulties': [ -367, -1619, -316, -314, -312, -308, -259, -257, -255, -253, -251, -221, -218, -217, -210, -75, -30, -16, -1446, -15, -8, -1388 ] }, { name: 'Girls of Summer Paradise', thumb: 683, - Expert: [ 659, 680, 682, 684, 686 ] + global: true, + gamewith: 15440, + challenge: 'Total number of hits over 30,000', + challengeData: [['Japan Rewards', ''],['10 Times','#686 Vivi\'s Breather Unit'],['35 Times','1x HP Cotton Candy'],['72 Times','3x Rainbow Gems'], ['Global Rewards', ''],['10 Times','1x Bind Resistance Forbidden Tome, 1x Despair Resistance Forbidden Tome, 1x Auto-Heal Forbidden Tome, 1x Rainbow Gem'],['35 Times','1x Red Elder Turtle, 1x Blue Elder Turtle, 1x Green Elder Turtle, 1x Yellow Elder Turtle, 1x Black Elder Turtle, 2x Rainbow Gems'],['72 Times','5x Rainbow Gems']], + 'All Difficulties': [ 659, 680, 682, 684, 1200, 1198, 1708, 1710 ], + 'Challenge Unit': [ 686 ], + }, + + { + name: 'Halloween Event Characters', + global: true, + thumb: 1300, + 'All Difficulties': [ 1299, 1305, 1325 ], + }, + + { + name: 'Valentines Day and White Day Characters', + thumb: 1463, + gamewith: 51651, + 'Luffy': [ 1462, 29, 563, 1059, 345, 192, 113, 108, 115, 116, 117, 1180, 266, 94, 83 ], + 'Chopper': [ 1464, 1155, 333, 728, 334, 1061, 346, 193, 109, 114, 115, 116, 117, 1180, 266, 94, 83 ], + 'Sanji': [ 1507, 52, 207, 892, 343, 190, 111, 106, 115, 116, 117, 1180, 266, 94, 83 ], + 'Brook': [ 1515, 954, 614, 379, 730, 342, 189, 110, 105, 115, 116, 117, 1180, 266, 94, 83 ], + }, + + { + name: 'Straw Hat Pirates!', + thumb: 1387, + global: true, + 'All Difficulties': [ 2, 5, 9, 13, 17, 21, 708, 629, 895 ], + }, + + { + name: '2nd Anniversary Celebration! Duel! Ace', + thumb: 1023, + global: true, + 'All Difficulties': [ 1023 ] + }, + + { + name: '3rd Anniversary Celebration! Duel! Luffy', + thumb: 1600, + '30 Stamina': [ 1600 ] }, { - name: 'Colosseum', + name: 'Coliseum', thumb: 779, - Exhibition: [ 776, 778, 803, 832, 834, 859, 861, 883, 902, 904 ], - Underground: [ 776, 778, 803, 832, 834, 859, 861, 883, 902, 904 ], - Chaos: [ 776, 778, 780, 803, 805, 830, 832, 834, 859, 861, 881, 883, 900, 902 ] - } + global: true, + gamewith: 17473, + teamDatabase: 'coliseums', + Exhibition: [ 776, 778, 803, 832, 834, 859, 861, 883, 902, 904, 925, 927, 952, 984, 1017, 1019, 1103, 1105, 1195, 1197, 1221, 1252, 1253, 1293, 1311, 1339, 1340, 1377, 1402, 1423, 1424, 1457, 1459, 1488, 1490, 1526, 1528, 1552, 1585, 1603, 1629 ], + Underground: [ 776, 778, 803, 832, 834, 859, 861, 883, 902, 904, 925, 927, 952, 984, 1017, 1019, 1103, 1105, 1195, 1197, 1221, 1252, 1253, 1293, 1311, 1339, 1340, 1377, 1402, 1423, 1424, 1457, 1459, 1488, 1490, 1526, 1528, 1552, 1585, 1603, 1629 ], + Chaos: [ 776, 778, 780, 803, 805, 830, 832, 834, 859, 861, 881, 883, 900, 902, 923, 925, 950, 982, 984, 1017, 1015, 1040, 1042, 1086, 1088, 1090, 1101, 1103, 1105, 1140, 1142, 1144, 1195, 1219, 1221, 1250, 1252, 1291, 1293, 1309, 1311, 1337, 1339, 1340, 1375, 1377, 1400, 1421, 1423, 1455, 1457, 1486, 1488, 1525, 1526, 1528, 1552, 1554, 1583, 1585, 1601, 1603, 1627, 1629, 1666, 1693, 1732, 1791, 1827, 1860 ], + Neo: [ 1862 ] + }, + + { + name: 'Adventure Mode', + thumb: 1808, + Adventure: [ 1807, 1852 ] + }, + + { + name: 'Invasion! Young Whitebeard', + thumb: 1258, + global: true, + gamewith: 38237, + condition: 'Has a chance of appearing at the end of ANY Raid boss when available. You MUST use the same team that you just used to complete the raid boss to fight Young Whitebeard.', + 'All Difficulties': [ 1257, 'skullSTR', 'skullDEX', 'skullQCK', 'skullPSY', 'skullINT' ] + }, + + { + name: 'Invasion! Red Hair Shanks', + thumb: 1380, + global: true, + gamewith: 46369, + condition: 'Has a chance of appearing at the end of ANY Raid boss when available. You MUST use the same team that you just used to complete the raid boss to fight Shanks.', + 'All Difficulties': [ 1379, 952, 776, 'skullSTR', 'skullDEX', 'skullQCK', 'skullPSY', 'skullINT' ] + }, + + { + name: 'Invasion! Cavendish', + thumb: 1530, + global: true, + gamewith: 53621, + condition: 'Has a chance of appearing at the end of ANY Chaos Coliseum boss. You MUST use the same team that you just used to complete the Coliseum boss to fight Cavendish.', + 'All Difficulties': [ 1529, 'skullSTR', 'skullDEX', 'skullQCK', 'skullPSY', 'skullINT' ] + }, + + { + name: 'Invasion! Garp', + thumb: 1846, + gamewith: 75260, + condition: 'Has a chance of appearing at the end of ANY Chaos Coliseum boss. You MUST use the same team that you just used to complete the Coliseum boss to fight Garp.', + 'All Difficulties': [ 1845, 'skullSTR', 'skullDEX', 'skullQCK', 'skullPSY', 'skullINT' ] + }, + + { + name: 'Rescue Ace Event - Akainu', + thumb: 1283, + global: true, + condition: '10, 20, 30, 35 stamina difficulty. 30 and 35 Stamina has a chance of dropping the Almighty Book.', + 'Characters': [ 927, 296, 299, 773, 774, 1224 ], + 'Boosters and Evolvers': [ 351, 193, 114, 266, 83, 118 ], + 'Global': [ -261, -1413, -562, -720, -8, -1388, -219, -75, -255, -314, -316, -357, -410, -408, -449, -451, -455, -641, -643, -754, -760, -840, -880, -906, -910, -999, -554, -1175, -528, -1177, -560, -1212, -1245, -218, -22, -1448, -24, -204, -384, -504, -508, -785, -789 ], + 'Japan': [ -261, -562, -720, -748, -1663, -935, -1413 ] + }, + + { + name: 'Rescue Ace Event - Aokiji', + thumb: 1280, + global: true, + condition: '10, 20, 30, 35 stamina difficulty. 30 and 35 Stamina has a chance of dropping the Almighty Book.', + 'Characters': [ 67, 69, 262, 264, 298 ], + 'Boosters and Evolvers': [ 113, 192, 350, 266, 83, 118 ], + 'Global': [ -416, -459, -530, -1707, -217, -004, -1387, -12, -221, -1389, -77, -210, -253, -259, -310, -312, -361, -363, -414, -453, -645, -647, -752, -756, -937, -939, -991, -520, -1115, -524, -1119, -558, -1208, -1245, -25, -202, -208, -206, -502, -787, -789, -739, -1550, -1445 ], + 'Japan': [ -416, -459, -530, -1707, -669, -1492, -578, -1121, -1445 ] + }, + + { + name: 'Rescue Ace Event - Kizaru', + thumb: 1228, + global: true, + condition: '10, 20, 30, 35 stamina difficulty. 30 and 35 Stamina has a chance of dropping the Silver Almighty Book.', + 'Characters': [ 968, 969, 970, 971, 972, 231, 775, 1223, 49, 43 ], + 'Boosters and Evolvers': [ 112, 191, 349, 266, 83, 118 ], + 'Global': [ -367, -1619, -649, -718, -16, -1446, -20, -1447, -73, -251, -257, -308, -359, -365, -412, -457, -639, -750, -758, -912, -914, -941, -993, -522, -1117, -526, -1173, -556, -1210, -1245, -223, -15, -23, -25, -200, -225, -546, -500, -506, -569, -791, -793 ], + 'Japan': [ -367, -1619, -649, -718, -870, -1001 ] + }, + + { + name: 'Battle Blitz! The Three Admirals', + thumb: 1314, + global: true, + gamewith: 61665, + condition: 'Chance of dropping the Silver Almighty Book.', + 'All Bosses': [ -1621, -1632, -1665 ], + 'Chopperman Mission': [ 1675 ], + }, + + { + name: 'Battle Blitz! Straw Hat Pirates', + thumb: 1404, + gamewith: 65078, + condition: 'Chance of dropping the Silver Almighty Book.', + 'All Bosses': [ -1621, -1632, -1665, -1678, -1721 ], + 'Chopperman Missions': [ 1728 ], + }, + + { + name: 'Battle Blitz! Doflamingo Family', + thumb: 870, + gamewith: 68282, + condition: 'Chance of dropping the Silver Almighty Book, Guidence Fragments and Guidence Crystals.', + 'All Bosses': [ -1621, -1632, -1665, -1678, -1713, -1721, -1770 ], + }, + + { + name: 'The Flashback Before the Reunion! Fight all your Enemies!', + thumb: 1353, + global: true, + condition: 'The fight gets more difficult every time you complete it until it gets to 40 stamina. You an only beat the first 7 stages once, but you can challenge the 8th stage multiple times and it has randomly selected stages.', + '1st Stage': [ 27, 29, 35, 36, 37, 38, 43, 35, 53, 55, 57, 61, 62, 63, 65 ], + '2nd Stage': [ 71, 211, 233, 235, 199, 201, 203, 205, 395, 397, 207, 399, 401, 383 ], + '3rd Stage': [ 430, 432, 463, 467, 542, 464, 465, 541, 545 ], + '4th Stage': [ 630, 632, 706, 728, 730, 732, 734, 738 ], + '5th Stage': [ 813, 891, 892, 889, 893, 815, 425, 387 ], + '6th Stage': [ 963, 966, 967, 973, 1059, 1055, 1057, 1156, 1158 ], + '7th Stage': [ 1224, 1223, 1225, 1226, 1227, 1282, 1281, 1280, 1228, 1283 ], + '8th Stage': [ 37, 38, 53, 55, 43, 36, 45, 57, 65, 203, 205, 383, 395, 397, 399, 401, 464, 465, 541, 545, 630, 632, 728, 730, 815, 889, 893, 973, 1055, 1057, 1158, 1156, 1227, 1228, 1280, 1283, 1353 ], + 'Evolvers and Boosters': [ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 115, 116, 117, 118, 266, 300, 301, 302, 303, 304, 1180, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 189, 190, 191, 192, 193, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351 ] + }, + + { + name: 'Challenge the Enemy! Sugofest Exclusive Character Skillbooks!', + thumb: 1588, + gamewith: 56742, + showManual: true, + condition: 'High chance of dropping 6* skillbooks. Only Evolvers and Booster characters will drop posters.', + 'Black Clad Shanks': [ 301, 101, 96, 79, 90, 348, -530, -1707, -316, -910, -995, -1236, -1364, -465, -590, -967, -813, -888 ], + 'Donquixote Doflamingo': [ 304, 104, 88, 99, 82, 93, 351, -870, -312, -645, -838, -876, -880, -1190, -396, -586, -631, -567 ], + 'Trafalgar Law': [ 300, 100, 84, 95, 78, 89, 347, -964, -1045, -219, -308, -675, -991, -1077, -504, -1159, -212, -892 ], + 'Black Clad Ace': [ 302, 102, 86, 97, 80, 91, 349, -562, -310, -359, -941, -560, -1212, -1406, -789, -966, -432, -565, -566 ], + 'Cavendish': [ 303, 103, 87, 98, 81, 92, 350, -963, -1123, -217, -914, -1029, -1127, -1408, -202, -464, -1227, -705 ], + 'Blackbeard': [ 304, 104, 88, 99, 82, 93, 351, -1268, -75, -733, -1033, -1082, -1230, -1278, -569, -1061, -52, -335 ], + 'Crocodile': [ 302, 102, 86, 97, 80, 91, 349, -720, -410, -908, -1208, -558, -1234, -1366, -544, -731, -236, -814, -1224 ], + 'Log Luffy': [ 300, 100, 84, 95, 78, 89, 347, -1121, -578, -1075, -1131, -1133, -1115, -520, -1177, -528, -1387, -4, -816, -426, -542, -563 ], + 'Corazon': [ 303, 103, 87, 98, 81, 92, 350, -1001, -451, -878, -1079, -1183, -1316, -1446, -16, -223, -327, -628, -614 ], + 'Kuzan': [ 301, 101, 96, 79, 90, 348, -1192, -1764, -255, -365, -449, -1210, -556, -1370, -200, -384, -1060, -428, -703 ], + 'Issho': [ 301, 101, 96, 79, 90, 348, -1085, -965, -414, -457, -999, -1270, -218, -15, -785, -1228, -467 ], + 'Dracule Mihawk': [ 303, 103, 87, 98, 81, 92, 350, -718, -639, -846, -906, -1129, -1238, -1322, -463, -729, -791, -215 ], + 'Sabo': [ 304, 104, 88, 99, 82, 93, 351, -669, -874, -937, -1027, -1119, -524, -1318, -216, -332, -502, -737, -1062 ], + 'Rayleigh': [ 300, 100, 84, 95, 78, 89, 347, -367, -1619, -210, -894, -997, -1389, -12, -1412, -208, -431, -544, -954, -1151 ], + 'Jinbei': [ 302, 102, 86, 97, 80, 91, 349, -935, -408, -641, -671, -673, -1187, -1274, -1368, -333, -704, -956 ], + 'Sakazuki': [ 303, 103, 87, 98, 81, 92, 350, -1314, -73, -259, -412, -455, -647, -1324, -292, -329, -1283, -955 ], + 'Rob Lucci': [ 300, 100, 84, 95, 78, 89, 347, -748, -1663, -314, -756, -912, -1238, -1447, -20, -633, -787, -731, -427, -1279 ], + 'Sengoku': [ 304, 104, 88, 99, 82, 93, 351, -459, -453, -1117, -522, -1186, -1175, -554, -1549, -709, -400, -500, -974, -1152, -1153 ], + 'Whitebeard': [ 302, 102, 86, 97, 80, 91, 349, -261, -1413, -361, -363, -752, -872, -939, -204, -1280, -564, -701, -1154 ], + 'Marco': [ 301, 101, 96, 79, 90, 348, -649, -251, -750, -842, -993, -1173, -508, -631, -378, -891, -1226 ], + 'Zoro': [ 301, 101, 96, 79, 90, 348, -1362, -844, -1081, -1125, -1410, -546, -1282, -234, -812, -47 ], + 'Boa Hancock': [ 303, 103, 87, 98, 81, 92, 350, -416, -1445, -253, -677, -1320, -1448, -22, -402, -506, -588, -893, -1157, -702 ], + 'Bartolomeo': [ 304, 104, 88, 99, 82, 93, 351, -1035, -221, -357, -643, -840, -1025, -1029, -225, -541, -733, -1056 ], + 'Borsalino': [ 302, 102, 86, 97, 80, 91, 349, -1240, -77, -257, -760, -943, -1272, -1551, -896, -398, -793, -1058, -59 ], + 'Captain Buggy': [ 300, 100, 84, 95, 78, 89, 347, -1391, -1031, -1232, -1276, -1550, -739, -214, -707, -735, -890, -1318, -290 ], + }, + + { + name: '20th Anniversary! Nico Robin!', + thumb: 1684, + global: true, + gamewith: 62383, + showManual: true, + condition: 'No characters will drop posters.', + 'All Difficulties': [ -1121, -578, -1404, -1593, -217, -210, -908, -937, -941, -943, -1115, -520, -1208, -558, -1210, -556, -1212, -560, -1364, -1408, -1387, -4, -1446, -16, -1549, -709, -1550, -739, -223, -15, -629, -209 ], + }, + + { + name: '20th Anniversary! Sanji!', + thumb: 1755, + gamewith: 66019, + showManual: true, + condition: 'No characters will drop posters.', + 'All Difficulties': [ -1388, -1362, -1175, -906, -554, -219, -218, -8, -1447, -1368, -1117, -912, -522, -20, -19, -1389, -1366, -1119, -221, -12, -11, -1410, -1551, -1173, -914, -896, -526, -1412, -1370, -1448, -1177, -910, -528, -23, -22 ], + }, + + { + name: '20th Anniversary! Straw Hats!', + thumb: 1686, + global: true, + gamewith: 62386, + condition: 'Gain gems by completeing the missions. Once you complete a mission, it will no longer be available and the next difficulty will be available. Total of 46 gems possible. Only Booster characters will drop posters.', + 'All Difficulties': [ 591, 592, 593, 594, 595, 189, 190, 191, 192, 193 ], + }, + + ], + + 'Training Forest': [ + + { + name: 'Forest of Training: Hawk', + thumb: 227, + gamewith: 2949, + teamDatabase: 'forests/1', + global: true, + completion: 'Ship: Coffin Boat', + }, + + { + name: 'Forest of Training: Flame Fist', + thumb: 562, + gamewith: 15896, + teamDatabase: 'forests/2', + global: true, + completion: 'Ship: Striker', + }, + + { + name: 'Forest of Training: Kami', + thumb: 603, + gamewith: 25369, + teamDatabase: 'forests/7', + global: true, + completion: 'Ship: Ark Maxim', + }, + + { + name: 'Forest of Training: Sun', + thumb: 935, + gamewith: 32540, + teamDatabase: 'forests/9', + global: true, + completion: 'Ship: Sun Pirates Ship', + }, + + { + name: 'Forest of Training: Beard', + thumb: 261, + gamewith: 11685, + teamDatabase: 'forests/6', + global: true, + completion: 'Ship: Moby Dick', + }, + + { + name: 'Forest of Training: Pheasant', + thumb: 575, + gamewith: 15617, + teamDatabase: 'forests/11', + global: true, + completion: 'Ship: Aokiji\'s Bicycle', + }, + + { + name: 'Forest of Training: Snake', + thumb: 416, + gamewith: 24312, + teamDatabase: 'forests/8', + global: true, + completion: 'Ship: Kuja Pirates Ship', + }, + + { + name: 'Forest of Training: Red Hair', + thumb: 530, + gamewith: 27893, + teamDatabase: 'forests/10', + global: true, + completion: 'Ship: Red Force', + }, + + { + name: 'Forest of Training: Heavenly Demon', + thumb: 870, + gamewith: 34319, + global: true, + completion: 'Ship: Doflamingo Pirates Ship', + }, + + { + name: 'Forest of Training: ROOM', + thumb: 1045, + gamewith: 44527, + global: true, + completion: 'Ship: Polar Tang', + }, + + { + name: 'Forest of Training: Monkey', + thumb: 1240, + gamewith: 48115, + completion: 'Ship: Kizaru\'s Cannonball', + }, + + { + name: 'Forest of Training: Darkness', + thumb: 1268, + gamewith: 59779, + completion: 'Ship: Blackbeard Pirates Ship', + }, ] @@ -1025,20 +2481,25 @@ var bonuses = [ { type: 'stamina' , x: 3 , y: 0 }, { type: 'stamina' , x: 6 , y: 5 }, { type: 'stamina' , x: 6 , y: 12 }, - { type: 'stamina' , x: 6 , y: 19, stop: 4 }, + { type: 'stamina' , x: 6 , y: 19 }, + { type: 'stamina' , x: 6 , y: 26 }, { type: 'drop' , x: 6 , y: 1 }, { type: 'drop' , x: 6 , y: 8 }, { type: 'drop' , x: 6 , y: 15 }, { type: 'drop' , x: 6 , y: 22 }, + { type: 'drop' , x: 6 , y: 29 }, { type: 'beli' , x: 6 , y: 3 }, { type: 'beli' , x: 1 , y: 4 }, { type: 'beli' , x: 6 , y: 10 }, { type: 'beli' , x: 6 , y: 17 }, + { type: 'beli' , x: 6 , y: 24 }, + { type: 'beli' , x: 6 , y: 31 }, { type: 'exp' , x: 2 , y: 2 }, { type: 'exp' , x: 6 , y: 2 }, { type: 'exp' , x: 5 , y: 5, stop: 5 }, { type: 'exp' , x: 6 , y: 6 }, { type: 'exp' , x: 6 , y: 9, stop: 2 }, { type: 'exp' , x: 6 , y: 13 }, - { type: 'exp' , x: 6 , y: 20 } + { type: 'exp' , x: 6 , y: 20 }, + { type: 'exp' , x: 6 , y: 27 } ]; diff --git a/common/data/effects.js b/common/data/effects.js index d5c82c5b9..53213a06e 100644 --- a/common/data/effects.js +++ b/common/data/effects.js @@ -2,7 +2,8 @@ window.effects = { // always use unique IDs, and don't ever change an ID once you've set it // IDs must always be greater than 0 - // last ID used: 25 + // last ID used: 46 + // Use p.type instead of p.unit.type here 'Baroque Works (pre-v4.0)': { description: 'Stats of non-Fighter units reduced by 90%', @@ -116,12 +117,12 @@ window.effects = { }, 'Gan Fall': { - description: 'Stats of non-Freedom, non-Booster, non-Evolver units reduced by 90%', + description: 'Stats of non-Free Spirit, non-Booster, non-Evolver units reduced by 90%', thumb: 713, id: 11, // don't change this - atk: function(p) { return p.class.has('Freedom') || p.class.has('Booster') || p.class.has('Evolver') ? 1 : 0.1; }, - hp: function(p) { return p.class.has('Freedom') || p.class.has('Booster') || p.class.has('Evolver') ? 1 : 0.1; }, - rcv: function(p) { return p.class.has('Freedom') || p.class.has('Booster') || p.class.has('Evolver') ? 1 : 0.1; } + atk: function(p) { return p.class.has('Free Spirit') || p.class.has('Booster') || p.class.has('Evolver') ? 1 : 0.1; }, + hp: function(p) { return p.class.has('Free Spirit') || p.class.has('Booster') || p.class.has('Evolver') ? 1 : 0.1; }, + rcv: function(p) { return p.class.has('Free Spirit') || p.class.has('Booster') || p.class.has('Evolver') ? 1 : 0.1; } }, 'Orb amplification (1.05x)': { @@ -145,17 +146,10 @@ window.effects = { chainLimiter: function() { return 2.0; } }, - 'Hit barrier (11 hits)': { - description: 'Nullifies the first 11 hits in the chain', - thumb: 794, - id: 15, // don't change this - comboShield: 11 - }, - 'Nightmare Luffy, 2nd stage': { description: 'Limits chain multiplier to 2.0x, nullifies the first 11 hits in the chain', thumb: 795, - id: 16, // don't change this + id: 15, // don't change this comboShield: 11, chainLimiter: function() { return 2.0; } }, @@ -163,64 +157,435 @@ window.effects = { 'Attack reduction (50%)': { description: 'ATK of all units reduced by 50%', thumb: 546, - id: 17, // don't change this + id: 16, // don't change this atk: function(p) { return 0.5; } }, 'Attack reduction (70%)': { description: 'ATK of all units reduced by 70%', thumb: 765, - id: 18, // don't change this + id: 17, // don't change this atk: function(p) { return 0.3; } }, 'Kuma': { description: 'Damage of STR and DEX characters nullified', thumb: 836, - id: 19, // don't change this - damage: function(p) { return p.type == 'STR' || p.type == 'DEX' ? 0 : 1; } + id: 18, // don't change this + atk: function(p) { return p.type == 'STR' || p.type == 'DEX' ? 0 : 1; } }, 'Shu (Expert)': { description: 'Attack of Slasher units reduced by 50%', thumb: 773, - id: 20, // don't change this + id: 19, // don't change this atk: function(p) { return p.class.has("Slasher") ? 0.5 : 1; } }, 'Shu (Master)': { description: 'Attack of Slasher units reduced by 70%', thumb: 773, - id: 21, // don't change this + id: 20, // don't change this atk: function(p) { return p.class.has("Slasher") ? 0.3 : 1; } }, 'Attack reduction (20%)': { description: 'ATK of all units reduced by 20%', thumb: 567, - id: 22, // don't change this + id: 21, // don't change this atk: function(p) { return 0.8; } }, 'Hit barrier (26 hits)': { description: 'Nullifies the first 26 hits in the chain', thumb: 375, - id: 23, // don't change this + id: 22, // don't change this comboShield: 26 }, - 'Hancock chain bug': { - description: 'Allows higher than usual chain multipliers', - thumb: 865, - id: 24, // don't change this - chainLimiter: function(p) { return Infinity; } - }, - 'There\'s the G!': { description: 'Activates [G] orb support even when Lao-G is not in the team', thumb: 880, - id: 25, // don't change this + id: 23, // don't change this + gOrbsEnabled: true + }, + + 'Coliseum Franky': { + description: 'Activates [G] orb Support, boosts Orbs by 1.5x', + thumb: 560, + id: 24, // don't change this + orb: function(p) { return p.orb == 2.0 ? 1.5 : (p.orb == 0.5 ? 10/15 : 1); }, gOrbsEnabled: true }, + 'Coliseum Killer': { + description: 'ATK of all units reduced by 95%', + thumb: 1043, + id: 25, // don't change this + atk: function(p) { return 0.05; } + }, + + 'Coliseum Cricket': { + description: 'Fixed threshold barrier (200,000)', + thumb: 428, + id: 26, + barrierThreshold: 200000, + barrierReduction: 0.99 + }, + + 'Sabo Raid Boss': { + description: 'Reduces Chain By Half', + thumb: 1047, + id: 27, + chainModifier: function(p) { return 0.5 ; } + }, + + 'Pirate Ship Competition! \"Dead End\" Opens!': { + description: 'STR/DEX/QCK ATK 1.6x. INT/PSY HP 2x', + thumb: 1072, + id: 28, + atk: function(p) { return (p.type == "STR" || p.type == "DEX" || p.type == "QCK") ? 1.6 : 1; }, + hp: function(p) { return (p.type == "STR" || p.type == "DEX" || p.type == "QCK") ? 1 : 2.0; } + + }, + + '1.25x Orb Boost': { + description: 'Used by Christmas Law in Saga Coliseum', + thumb: 856, + id: 29, + orb: function(p) { return p.orb == 2.0 ? 1.25 : (p.orb == 0.5 ? 20/25 : 1); } + }, + + '700k Damage Treshold Barrier': { + description: 'Used by Saga. You cannot do more that 700k damage in one hit', + thumb: 1089, + id: 30, + barrierThreshold: 700000, + barrierReduction: 0.99 + }, + + 'Dr. Indigo & Scarlet! Fortnight': { + //OLD description: 'Boosts ATK of Driven and Powerhouse characters by 2x, other classes get .5x ATK. Boosts HP of Slasher and Fighter characters by 2x, other classes get .5x HP.', + description: 'Boosts ATK of Driven characters by 2x and boosts HP for Powerhouse characters by 2x.', + thumb: 1095, + id: 31, + atk: function(p) { +/* var boost1 = 1.0, boost2 = 1.0, boost3 = 1.0, boost4 = 1.0, boost5 = 1.0; + if(p.class.has('Driven')) { boost1 = 2.0} + if(p.class.has('Powerhouse')) { boost2 = 2.0} + if(!(p.class.has('Driven')&&p.class.has('Powerhouse')) && p.class.constructor === Array){ + if(!p.class.has('Driven')){ boost3 = 0.5} + if(!p.class.has('Powerhouse')){ boost4 = 0.5}} + if(p.class.constructor === String){ + if(!(p.class.has('Driven') || p.class.has('Powerhouse'))){ boost5 = 0.5} + } + return 1*boost1*boost2*boost3*boost4*boost5;*/ + return p.class.has('Driven') ? 2 : 1; + }, + hp: function(p) { +/* var boost1 = 1.0, boost2 = 1.0, boost3 = 1.0, boost4 = 1.0, boost5 = 1.0; + if(p.class.has('Fighter')) { boost1 = 2.0} + if(p.class.has('Slasher')) { boost2 = 2.0} + if(!(p.class.has('Fighter')&&p.class.has('Slasher')) && p.class.constructor === Array){ + if(!p.class.has('Fighter')){ boost3 = 0.5} + if(!p.class.has('Slasher')){ boost4 = 0.5}} + if(p.class.constructor === String){ + if(!(p.class.has('Fighter') || p.class.has('Slasher'))){ boost5 = 0.5} + } + return 1*boost1*boost2*boost3*boost4*boost5;*/ + return p.class.has('Powerhouse') ? 2 : 1; + } + }, + + 'Coliseum Tashigi': { + description: '25 hit barrier and 2x chain limit', + thumb: 783, + id: 32, + comboShield: 25, + chainLimiter: function() { return 2.0; } + }, + + 'Robin and Nami\'s Secret Undercover Investigation': { + description: 'Boosts ATK of Cerebral and Free Spirit characters by 2x, other classes get .5x ATK. Boosts HP of Striker and Shooter characters by 2x, other classes get .5x HP.', + thumb: 1112, + id: 33, + atk: function(p) { + var boost1 = 1.0, boost2 = 1.0, boost3 = 1.0, boost4 = 1.0, boost5 = 1.0; + if(p.class.has('Cerebral')) { boost1 = 2.0} + if(p.class.has('Free Spirit')) { boost2 = 2.0} + if(!(p.class.has('Cerebral')&&p.class.has('Free Spirit')) && p.class.constructor === Array){ + if(!p.class.has('Cerebral')){ boost3 = 0.5} + if(!p.class.has('Free Spirit')){ boost4 = 0.5}} + if(p.class.constructor === String){ + if(!(p.class.has('Cerebral') || p.class.has('Free Spirit'))){ boost5 = 0.5} + } + //console.log(boost1+" "+boost2+" "+boost3+" "+boost4+" "+boost5) + return 1*boost1*boost2*boost3*boost4*boost5; + }, + hp: function(p) { + var boost1 = 1.0, boost2 = 1.0, boost3 = 1.0, boost4 = 1.0, boost5 = 1.0; + if(p.class.has('Striker')) { boost1 = 2.0} + if(p.class.has('Shooter')) { boost2 = 2.0} + if(!(p.class.has('Striker')&&p.class.has('Shooter')) && p.class.constructor === Array){ + if(!p.class.has('Striker')){ boost3 = 0.5} + if(!p.class.has('Shooter')){ boost4 = 0.5}} + if(p.class.constructor === String){ + if(!(p.class.has('Striker') || p.class.has('Shooter'))){ boost5 = 0.5} + } + return 1*boost1*boost2*boost3*boost4*boost5; + } + }, + + 'Gild Tesoro - 40 Stamina': { + description: 'Boosts the Orbs and ATK of all characters by 1.1x', + thumb: 1162, + id: 34, + orb: function(p) { return p.orb == 2.0 ? 1.1 : (p.orb == 0.5 ? 10/11 : 1); }, + atk: function(p) { return 1.1; } + }, + + 'Gild Tesoro - 60 Stamina': { + description: 'Boosts the Orbs and ATK of all characters by 1.2x', + thumb: 1163, + id: 35, + orb: function(p) { return p.orb == 2.0 ? 1.2 : (p.orb == 0.5 ? 5/6 : 1); }, + atk: function(p) { return 1.2; } + }, + + 'World Pirates - Boa Stage 1': { + description: 'Boosts the ATK of characters with 30 cost or less by 1.5x', + thumb: 865, + id: 36, + atk: function(p) { return p.cost <= 30 ? 1.5 : 1; } + }, + + 'Aokiji Neo - Striker Raid Boss': { + description: 'Reduces Chain By 90%', + thumb: 1668, + id: 37, + chainModifier: function(p) { return 0.1 ; } + }, + + 'Doflamingo Neo - Fighter Raid Boss': { + description: 'Reduces Damage taken by 30%', + thumb: 1623, + id: 38, // don't change this + atk: function(p) { return .7 ; }, + }, + + 'Doflamingo Neo [GLOBAL] - Fighter Raid Boss': { + description: 'Reduces Damage taken by 50%', + thumb: 1623, + id: 39, // don't change this + atk: function(p) { return .5 ; }, + }, + + 'Doflamingo Neo [GLOBAL] - Striker Raid Boss': { + description: 'Halves Chain Multiplier.', + thumb: 1623, + id: 40, // don't change this + chainModifier: function(p) { return 0.5 ; } + }, + + 'Sabo Neo - Fighter Raid Boss': { + description: 'Boosts the Orbs all characters by 1.2x, ATK by 1.3x and Reduces Chain by Half.', + thumb: 1727, + id: 41, + orb: function(p) { return p.orb == 2.0 ? 1.2 : (p.orb == 0.5 ? 5/6 : 1); }, + atk: function(p) { return 1.3; }, + chainModifier: function(p) { return 0.5 ; } + }, + + 'Kyros Colisuem - Chain multiplier limiter (1.5x)': { + description: 'Limits chain multiplier to 1.5x', + thumb: 1667, + id: 42, // don't change this + chainLimiter: function() { return 1.5; } + }, + + 'Treasure Map [Mihawk Season]': { + description: 'Boost stats of Buggy & Zoro 2.5x', + thumb: 1808, + id: 43, // don't change this + atk: function(p) { + var id = p.number + 1, + matching = ((id > 1803 && id < 1806) || + [ 1804, 1806 ].indexOf(id) != -1); + return !matching ? 1 : 2.5; + }, + hp: function(p) { + var id = p.number + 1, + matching = ((id > 1803 && id < 1806) || + [ 1804, 1806 ].indexOf(id) != -1); + return !matching ? 1 : 2.5; + }, + rcv: function(p) { + var id = p.number + 1, + matching = ((id > 1803 && id < 1806) || + [ 1804, 1806 ].indexOf(id) != -1); + return !matching ? 1 : 2.5; + }, + }, + + 'Akainu Neo': { + description: 'Certain units boosted', + thumb: 1826, + id: 44, // don't change this + atk: function(p) { + var id = p.number + 1, + matching = ((id > 1740 && id < 1745) || + [ 1795, 1796, 1539, 1540, 1823, 1844, 1277, 1278 ].indexOf(id) != -1); + return !matching ? 1 : 1.75; + }, + hp: function(p) { + var id = p.number + 1, + matching = ((id > 1740 && id < 1745) || + [ 1795, 1796, 1539, 1540, 1823, 1844, 1277, 1278 ].indexOf(id) != -1); + return !matching ? 1 : 1.75; + }, + rcv: function(p) { + var id = p.number + 1, + matching = ((id > 1740 && id < 1745) || + [ 1795, 1796, 1539, 1540, 1823, 1844, 1277, 1278 ].indexOf(id) != -1); + return !matching ? 1 : 1.75; + }, + }, + + 'Blitz Battle! The Three Admirals': { + description: 'Lot of units boosted', + thumb: 1314, + id: 45, // don't change this + atk: function(p) { + var id = p.number + 1, + matching = ((id > 446 && id < 457) || (id > 638 && id < 659) || + [ 1, 2, 3, 4, 216, 1245, 217, 250, 251, 252, 1248, 1249, 253, 254, 255, 420, 547, 548, 570, 571, 577, 578, 727, 761, 794, 946, 947, 948, 936, 937, 1022, 1114, 1115, 1120, 1121, 1285, 1387, 1403, 1404, 38, 39, 598, 599, 887, 1301, 1302, 1390, 1391, 74, 75, 497, 498, 561, 562, 950, 951, 1023, 1246, 1247, 1265, 1266, 1604, 1605, 1040, 1041, 982, 983, 260, 261, 1257, 1258, 1413, 383, 384, 408, 509, 510, 719, 720, 897, 389, 390, 674, 675, 1036, 1037, 1352, 409, 410, 885, 934, 935, 1345, 415, 416, 864, 865, 921, 922, 1193, 1194, 1218, 1445, 981, 1255, 1254, 1256, 676, 677, 1038, 1039, 1181, 1182, 1183, 1184, 1512, 1187, 1188, 1511, 1189, 1190, 1510, 1267, 1268, 321, 322, 632, 633, 737, 747, 748, 1762, 1763, 949, 366, 367, 1353, 1354, 1355, 1533, 1534, 1619, 2000, 2001, 545, 546, 602, 603, 226, 227, 717, 718, 1227, 1679, 1680, 391, 392, 437, 438, 684, 685, 889, 890, 944, 945, 1539, 1540, 1309, 1310, 1576, 1577, 1337, 1338, 1657, 1658, 1570, 1571, 1572, 1573, 1574, 1575, 1578, 1579, 1651, 1652, 1653, 1654, 1655, 1656, 1659, 1660, 1158, 1159, 1373, 1374, 1697, 1698, 928, 929, 1156, 1157, 207, 208, 461, 462, 899 ].indexOf(id) != -1); + return !matching ? 1 : 1.5; + }, + hp: function(p) { + var id = p.number + 1, + matching = ((id > 446 && id < 457) || (id > 638 && id < 659) || + [ 1, 2, 3, 4, 216, 1245, 217, 250, 251, 252, 1248, 1249, 253, 254, 255, 420, 547, 548, 570, 571, 577, 578, 727, 761, 794, 946, 947, 948, 936, 937, 1022, 1114, 1115, 1120, 1121, 1285, 1387, 1403, 1404, 38, 39, 598, 599, 887, 1301, 1302, 1390, 1391, 74, 75, 497, 498, 561, 562, 950, 951, 1023, 1246, 1247, 1265, 1266, 1604, 1605, 1040, 1041, 982, 983, 260, 261, 1257, 1258, 1413, 383, 384, 408, 509, 510, 719, 720, 897, 389, 390, 674, 675, 1036, 1037, 1352, 409, 410, 885, 934, 935, 1345, 415, 416, 864, 865, 921, 922, 1193, 1194, 1218, 1445, 981, 1255, 1254, 1256, 676, 677, 1038, 1039, 1181, 1182, 1183, 1184, 1512, 1187, 1188, 1511, 1189, 1190, 1510, 1267, 1268, 321, 322, 632, 633, 737, 747, 748, 1762, 1763, 949, 366, 367, 1353, 1354, 1355, 1533, 1534, 1619, 2000, 2001, 545, 546, 602, 603, 226, 227, 717, 718, 1227, 1679, 1680, 391, 392, 437, 438, 684, 685, 889, 890, 944, 945, 1539, 1540, 1309, 1310, 1576, 1577, 1337, 1338, 1657, 1658, 1570, 1571, 1572, 1573, 1574, 1575, 1578, 1579, 1651, 1652, 1653, 1654, 1655, 1656, 1659, 1660, 1158, 1159, 1373, 1374, 1697, 1698, 928, 929, 1156, 1157, 207, 208, 461, 462, 899 ].indexOf(id) != -1); + return !matching ? 1 : 1.5; + }, + rcv: function(p) { + var id = p.number + 1, + matching = ((id > 446 && id < 457) || (id > 638 && id < 659) || + [ 1, 2, 3, 4, 216, 1245, 217, 250, 251, 252, 1248, 1249, 253, 254, 255, 420, 547, 548, 570, 571, 577, 578, 727, 761, 794, 946, 947, 948, 936, 937, 1022, 1114, 1115, 1120, 1121, 1285, 1387, 1403, 1404, 38, 39, 598, 599, 887, 1301, 1302, 1390, 1391, 74, 75, 497, 498, 561, 562, 950, 951, 1023, 1246, 1247, 1265, 1266, 1604, 1605, 1040, 1041, 982, 983, 260, 261, 1257, 1258, 1413, 383, 384, 408, 509, 510, 719, 720, 897, 389, 390, 674, 675, 1036, 1037, 1352, 409, 410, 885, 934, 935, 1345, 415, 416, 864, 865, 921, 922, 1193, 1194, 1218, 1445, 981, 1255, 1254, 1256, 676, 677, 1038, 1039, 1181, 1182, 1183, 1184, 1512, 1187, 1188, 1511, 1189, 1190, 1510, 1267, 1268, 321, 322, 632, 633, 737, 747, 748, 1762, 1763, 949, 366, 367, 1353, 1354, 1355, 1533, 1534, 1619, 2000, 2001, 545, 546, 602, 603, 226, 227, 717, 718, 1227, 1679, 1680, 391, 392, 437, 438, 684, 685, 889, 890, 944, 945, 1539, 1540, 1309, 1310, 1576, 1577, 1337, 1338, 1657, 1658, 1570, 1571, 1572, 1573, 1574, 1575, 1578, 1579, 1651, 1652, 1653, 1654, 1655, 1656, 1659, 1660, 1158, 1159, 1373, 1374, 1697, 1698, 928, 929, 1156, 1157, 207, 208, 461, 462, 899 ].indexOf(id) != -1); + return !matching ? 1 : 1.5; + }, + }, + + 'Sicilian Coloseum': { + description: 'Certain units boosted', + thumb: 1828, + id: 46, // don't change this + atk: function(p) { + var id = p.number + 1, + matching = ((id > 1831 && id < 1840) || + [ ].indexOf(id) != -1); + return !matching ? 1 : 1.25; + }, + hp: function(p) { + var id = p.number + 1, + matching = ((id > 1831 && id < 1840) || + [ ].indexOf(id) != -1); + return !matching ? 1 : 1.25; + }, + rcv: function(p) { + var id = p.number + 1, + matching = ((id > 1831 && id < 1840) || + [ ].indexOf(id) != -1); + return !matching ? 1 : 1.25; + }, + }, + + 'Treasure Map [Whitebeard Season]': { + description: 'Boost stats of Akainu & Squard 2.5x', + thumb: 1853, + id: 47, // don't change this + atk: function(p) { + var id = p.number + 1, + matching = ((id > 1848 && id < 1851) || + [ 1851 ].indexOf(id) != -1); + return !matching ? 1 : 2.5; + }, + hp: function(p) { + var id = p.number + 1, + matching = ((id > 1848 && id < 1851) || + [ 1851 ].indexOf(id) != -1); + return !matching ? 1 : 2.5; + }, + rcv: function(p) { + var id = p.number + 1, + matching = ((id > 1848 && id < 1851) || + [ 1851 ].indexOf(id) != -1); + return !matching ? 1 : 2.5; + }, + }, + + 'Coloseum Kinemon Neo': { + description: 'Certain units boosted', + thumb: 1863, + id: 48, // don't change this + atk: function(p) { + var id = p.number + 1, + matching = ((id > 1858 && id < 1859) || + [ 1720, 1621, 1631, 1632, 1777, 1778, 1833, 1834, 871, 872, 1695, 1696, 1791, 1792, 1431, 1432 ].indexOf(id) !== -1); + return !matching ? 1 : 1.75; + }, + hp: function(p) { + var id = p.number + 1, + matching = ((id > 1858 && id < 1859) || + [ 1720, 1621, 1631, 1632, 1777, 1778, 1833, 1834, 871, 872, 1695, 1696, 1791, 1792, 1431, 1432 ].indexOf(id) !== -1); + return !matching ? 1 : 1.75; + }, + rcv: function(p) { + var id = p.number + 1, + matching = ((id > 1858 && id < 1859) || + [ 1720, 1621, 1631, 1632, 1777, 1778, 1833, 1834, 871, 872, 1695, 1696, 1791, 1792, 1431, 1432 ].indexOf(id) !== -1); + return !matching ? 1 : 1.75; + } + }, + + 'Kizaru Neo [GLOBAL] - Free Spirit': { + description: 'Chain multiplier reduced.', + thumb: 1780, + id: 49, + //orb: function(p) { return p.orb === 2.0 ? 1.2 : (p.orb === 0.5 ? 5/6 : 1); }, + atk: function(p) { + var id = p.number + 1, + matching = ((id > 1777 && id < 1778) || + [ 1441, 1442, 1701, 1702, 1659, 1660, 1631, 1632, 1699, 1700, 1748, 1749, 1615, 1616 ].indexOf(id) !== -1); + return !matching ? 1 : 1.75; + }, + chainModifier: function(p) { return 0.5 ; }//Chain by half + }, + + 'Kizaru Neo [GLOBAL] - Striker': { + description: 'Chain multiplier halved.', + thumb: 1780, + id: 50, + //orb: function(p) { return p.orb === 2.0 ? 1.2 : (p.orb === 0.5 ? 5/6 : 1); }, + atk: function(p) { + var id = p.number + 1, + matching = ((id > 1777 && id < 1778) || + [ 1441, 1442, 1701, 1702, 1659, 1660, 1631, 1632, 1699, 1700, 1748, 1749, 1615, 1616 ].indexOf(id) !== -1); + return !matching ? 1 : 1.75; + }, + chainModifier: function(p) { return 0.5 ; }//Chain by half + }, + + 'Kizaru Neo [GLOBAL] - Powerhouse': { + description: 'Chain multiplier locked at 1.1x after revive.', + thumb: 1780, + id: 51, + //orb: function(p) { return p.orb === 2.0 ? 1.2 : (p.orb === 0.5 ? 5/6 : 1); }, + atk: function(p) { + var id = p.number + 1, + matching = ((id > 1777 && id < 1778) || + [ 1441, 1442, 1701, 1702, 1659, 1660, 1631, 1632, 1699, 1700, 1748, 1749, 1615, 1616 ].indexOf(id) !== -1); + return !matching ? 1 : 1.75; + }, + chainLimiter: function() { return 1.1; } //Chain locked at 1.1x + } }; diff --git a/common/data/events.js b/common/data/events.js index 385c048ce..af28e3b6d 100644 --- a/common/data/events.js +++ b/common/data/events.js @@ -18,5 +18,235 @@ window.events = { if (--$scope.options.gOrbsEnabled === 0) $scope.notify({ text: 'Disabling [G] orbs support.' }); } - } + }, + 900: { + onInsertion: function($scope) { + if (++$scope.options.gOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [G] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.gOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [G] orbs support.' }); + } + }, + 901: { + onInsertion: function($scope) { + if (++$scope.options.gOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [G] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.gOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [G] orbs support.' }); + } + }, + 989: { + onInsertion: function($scope) { + if (++$scope.options.gOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [G] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.gOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [G] orbs support.' }); + } + }, + 1036: { + onInsertion: function($scope) { + if (++$scope.options.gOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [G] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.gOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [G] orbs support.' }); + } + }, + 1037: { + onInsertion: function($scope) { + if (++$scope.options.gOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [G] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.gOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [G] orbs support.' }); + } + }, + 1243: { + onInsertion: function($scope) { + if (++$scope.options.gOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [G] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.gOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [G] orbs support.' }); + } + }, + 1244: { + onInsertion: function($scope) { + if (++$scope.options.gOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [G] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.gOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [G] orbs support.' }); + } + }, + 1291: { + onInsertion: function($scope) { + if (++$scope.options.gOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [G] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.gOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [G] orbs support.' }); + } + }, + 1292: { + onInsertion: function($scope) { + if (++$scope.options.gOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [G] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.gOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [G] orbs support.' }); + } + }, + 1305: { + onInsertion: function($scope) { + if (++$scope.options.gOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [G] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.gOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [G] orbs support.' }); + } + }, + 1306: { + onInsertion: function($scope) { + if (++$scope.options.gOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [G] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.gOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [G] orbs support.' }); + } + }, + 1313: { + onInsertion: function($scope) { + if (++$scope.options.strOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [STR] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.strOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [STR] orbs support.' }); + } + }, + 1314: { + onInsertion: function($scope) { + if (++$scope.options.strOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [STR] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.strOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [STR] orbs support.' }); + } + }, + 1472: { + onInsertion: function($scope) { + if (++$scope.options.rainbowOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [RAINBOW] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.rainbowOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [RAINBOW] orbs support.' }); + } + }, + 1473: { + onInsertion: function($scope) { + if (++$scope.options.rainbowOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [RAINBOW] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.rainbowOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [RAINBOW] orbs support.' }); + } + }, + 1523: { + onInsertion: function($scope) { + if (++$scope.options.gOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [G] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.gOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [G] orbs support.' }); + } + }, + 1524: { + onInsertion: function($scope) { + if (++$scope.options.gOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [G] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.gOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [G] orbs support.' }); + } + }, + 1531: { + onInsertion: function($scope) { + if (++$scope.options.meatOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [MEAT] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.meatOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [MEAT] orbs support.' }); + } + }, + 1532: { + onInsertion: function($scope) { + if (++$scope.options.meatOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [MEAT] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.meatOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [MEAT] orbs support.' }); + } + }, + 1609: { + onInsertion: function($scope) { + if (++$scope.options.meatOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [MEAT] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.meatOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [MEAT] orbs support.' }); + } + }, + 1610: { + onInsertion: function($scope) { + if (++$scope.options.meatOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [MEAT] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.meatOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [MEAT] orbs support.' }); + } + }, + 1651: { + onInsertion: function($scope) { + if (++$scope.options.meatOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [MEAT] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.meatOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [MEAT] orbs support.' }); + } + }, + 1652: { + onInsertion: function($scope) { + if (++$scope.options.meatOrbsEnabled == 1) + $scope.notify({ text: 'Enabling [MEAT] orbs support.' }); + }, + onRemoval: function($scope) { + if (--$scope.options.meatOrbsEnabled === 0) + $scope.notify({ text: 'Disabling [MEAT] orbs support.' }); + } + }, }; diff --git a/common/data/evolutions.js b/common/data/evolutions.js index 207d06a55..0853df100 100644 --- a/common/data/evolutions.js +++ b/common/data/evolutions.js @@ -1,1398 +1,2930 @@ window.evolutions = { - 1: { - evolution: 2, - evolvers: [ 78 ] - }, - 2: { - evolution: 3, - evolvers: [ 115, 78 ] - }, - 3: { - evolution: 4, - evolvers: [ 117, 84, 95, 100 ] - }, - 5: { - evolution: [ 6, 7 ], - evolvers: [ [ 115, 80 ], [ 116, 80, 97 ] ] - }, - 6: { - evolution: 8, - evolvers: [ 117, 86, 97, 102 ] - }, - 7: { - evolution: 8, - evolvers: [ 117, 80, 102 ] - }, - 9: { - evolution: [ 10, 11 ], - evolvers: [ [ 115, 82 ], [ 116, 82, 99 ] ] - }, - 10: { - evolution: 12, - evolvers: [ 117, 88, 99, 104 ] - }, - 11: { - evolution: 12, - evolvers: [ 117, 82, 104 ] - }, - 13: { - evolution: [ 14, 15 ], - evolvers: [ [ 115, 81 ], [ 115, 81, 98 ] ] - }, - 14: { - evolution: [ 15, 16 ], - evolvers: [ [ 117 ], [ 117, 87, 98, 103 ] ] - }, - 15: { - evolution: 16, - evolvers: [ 117, 81, 103 ] - }, - 17: { - evolution: [ 18, 19 ], - evolvers: [ [ 115, 79 ], [ 116, 79, 96 ] ] - }, - 18: { - evolution: 20, - evolvers: [ 117, 85, 96, 101 ] - }, - 19: { - evolution: 20, - evolvers: [ 117, 79, 101 ] - }, - 21: { - evolution: [ 22, 23, 24, 25, 26 ], - evolvers: [ [ 116, 81, 98 ], [ 116, 82, 99 ], [ 116, 78, 95 ], [ 116, 79, 96 ], [ 116, 80, 97 ] ] - }, - 29: { - evolution: 30, - evolvers: [ 117, 78, 89, 100 ] - }, - 31: { - evolution: 32, - evolvers: [ 115, 81 ] - }, - 33: { - evolution: 34, - evolvers: [ 115, 82 ] - }, - 35: { - evolution: 228, - evolvers: [ 116, 78, 89 ] - }, - 38: { - evolution: 39, - evolvers: [ 116, 82, 93 ] - }, - 43: { - evolution: [ 44, 229 ], - evolvers: [ [ 116, 80, 91 ], [ 116, 81, 92 ] ] - }, - 45: { - evolution: 46, - evolvers: [ 117, 79, 90, 101 ] - }, - 49: { - evolution: 230, - evolvers: [ 116, 78, 89 ] - }, - 53: { - evolution: 54, - evolvers: [ 116, 79, 90 ] - }, - 55: { - evolution: 56, - evolvers: [ 116, 78, 89 ] - }, - 57: { - evolution: 58, - evolvers: [ 117, 82, 93, 104 ] - }, - 63: { - evolution: 64, - evolvers: [ 116, 80, 91 ] - }, - 65: { - evolution: 66, - evolvers: [ 117, 78, 89, 100 ] - }, - 67: { - evolution: 68, - evolvers: [ 117, 83, 79, 85, 96 ] - }, - 69: { - evolution: 70, - evolvers: [ 117, 83, 80, 86, 97 ] - }, - 70: { - evolution: 268, - evolvers: [ 117, 80, 86, 91, 102 ] - }, - 71: { - evolution: [ 72, 72 ], - evolvers: [ [ 117, 81, 98 ], [ 444 ] ] - }, - 72: { - evolution: 73, - evolvers: [ 118, 83, 87, 98, 103 ] - }, - 74: { - evolution: 75, - evolvers: [ 118, 83, 85, 85, 101 ] - }, - 76: { - evolution: 77, - evolvers: [ 118, 83, 87, 98, 103 ] - }, - 121: { - evolution: 142, - evolvers: [ 89 ] - }, - 122: { - evolution: 143, - evolvers: [ 90 ] - }, - 123: { - evolution: 144, - evolvers: [ 91 ] - }, - 124: { - evolution: 145, - evolvers: [ 92 ] - }, - 125: { - evolution: 146, - evolvers: [ 93 ] - }, - 126: { - evolution: 147, - evolvers: [ 89 ] - }, - 127: { - evolution: 148, - evolvers: [ 90 ] - }, - 128: { - evolution: 149, - evolvers: [ 91 ] - }, - 129: { - evolution: 150, - evolvers: [ 92 ] - }, - 130: { - evolution: 151, - evolvers: [ 93 ] - }, - 131: { - evolution: 152, - evolvers: [ 89 ] - }, - 132: { - evolution: 153, - evolvers: [ 90 ] - }, - 133: { - evolution: 154, - evolvers: [ 91 ] - }, - 134: { - evolution: 155, - evolvers: [ 92 ] - }, - 135: { - evolution: 156, - evolvers: [ 93 ] - }, - 136: { - evolution: 157, - evolvers: [ 89 ] - }, - 137: { - evolution: 158, - evolvers: [ 90 ] - }, - 138: { - evolution: 159, - evolvers: [ 91 ] - }, - 139: { - evolution: 160, - evolvers: [ 92 ] - }, - 140: { - evolution: 161, - evolvers: [ 93 ] - }, - 141: { - evolution: 162, - evolvers: [ 115, 93 ] - }, - 142: { - evolution: 269, - evolvers: [ 115, 116, 89 ] - }, - 143: { - evolution: 270, - evolvers: [ 115, 116, 90 ] - }, - 144: { - evolution: 271, - evolvers: [ 115, 116, 91 ] - }, - 145: { - evolution: 272, - evolvers: [ 115, 116, 92 ] - }, - 146: { - evolution: 273, - evolvers: [ 115, 116, 93 ] - }, - 147: { - evolution: 274, - evolvers: [ 116, 95 ] - }, - 148: { - evolution: 275, - evolvers: [ 116, 96 ] - }, - 149: { - evolution: 276, - evolvers: [ 116, 97 ] - }, - 150: { - evolution: 277, - evolvers: [ 116, 98 ] - }, - 151: { - evolution: 278, - evolvers: [ 116, 99 ] - }, - 152: { - evolution: 279, - evolvers: [ 78, 84 ] - }, - 153: { - evolution: 280, - evolvers: [ 79, 85 ] - }, - 154: { - evolution: 281, - evolvers: [ 80, 86 ] - }, - 155: { - evolution: 282, - evolvers: [ 81, 87 ] - }, - 156: { - evolution: 283, - evolvers: [ 82, 88 ] - }, - 157: { - evolution: 284, - evolvers: [ 115, 116, 89 ] - }, - 158: { - evolution: 285, - evolvers: [ 115, 116, 90 ] - }, - 159: { - evolution: 286, - evolvers: [ 115, 116, 91 ] - }, - 160: { - evolution: 287, - evolvers: [ 115, 116, 92 ] - }, - 161: { - evolution: 288, - evolvers: [ 115, 116, 93 ] - }, - 162: { - evolution: 289, - evolvers: [ 104 ] - }, - 179: { - evolution: 184, - evolvers: [ 78 ] - }, - 180: { - evolution: 185, - evolvers: [ 80 ] - }, - 181: { - evolution: 186, - evolvers: [ 79 ] - }, - 182: { - evolution: 187, - evolvers: [ 81 ] - }, - 183: { - evolution: 188, - evolvers: [ 115, 82 ] - }, - 184: { - evolution: 194, - evolvers: [ 116, 78, 84 ] - }, - 185: { - evolution: 195, - evolvers: [ 116, 80, 86 ] - }, - 186: { - evolution: 196, - evolvers: [ 116, 79, 85 ] - }, - 187: { - evolution: 197, - evolvers: [ 116, 81, 87 ] - }, - 188: { - evolution: 198, - evolvers: [ 116, 117, 82, 88 ] - }, - 199: { - evolution: 200, - evolvers: [ 94, 78 ] - }, - 201: { - evolution: 202, - evolvers: [ 94, 79 ] - }, - 203: { - evolution: 204, - evolvers: [ 94, 82 ] - }, - 205: { - evolution: 206, - evolvers: [ 94, 80 ] - }, - 207: { - evolution: [ 208, 462 ], - evolvers: [ [ 94, 81 ], [ 117, 231 ] ] - }, - 209: { - evolution: 210, - evolvers: [ 118, 82, 83, 88, 104 ] - }, - 211: { - evolution: 212, - evolvers: [ 116, 79, 90 ] - }, - 213: { - evolution: 214, - evolvers: [ 117, 78, 95, 100 ] - }, - 216: { - evolution: 217, - evolvers: [ 118, 84, 100, 94, 89 ] - }, - 218: { - evolution: 219, - evolvers: [ 118, 86, 102, 94, 91 ] - }, - 220: { - evolution: 221, - evolvers: [ 118, 88, 104, 94, 93 ] - }, - 222: { - evolution: 223, - evolvers: [ 117, 81, 98, 83 ] - }, - 224: { - evolution: 225, - evolvers: [ 117, 79, 90, 83 ] - }, - 226: { - evolution: 227, - evolvers: [ 118, 83, 86, 86, 102 ] - }, - 231: { - evolution: 232, - evolvers: [ 117, 79, 85, 90, 101 ] - }, - 233: { - evolution: 234, - evolvers: [ 116, 81, 92 ] - }, - 235: { - evolution: 236, - evolvers: [ 116, 78, 89 ] - }, - 237: { - evolution: 242, - evolvers: [ 115, 89, 95 ] - }, - 238: { - evolution: 243, - evolvers: [ 115, 91, 97 ] - }, - 239: { - evolution: 244, - evolvers: [ 115, 90, 96 ] - }, - 240: { - evolution: 245, - evolvers: [ 115, 92, 98 ] - }, - 241: { - evolution: 246, - evolvers: [ 115, 93, 99 ] - }, - 248: { - evolution: 249, - evolvers: [ 118, 84, 84, 95, 100 ] - }, - 250: { - evolution: 251, - evolvers: [ 118, 87, 94, 98, 103 ] - }, - 252: { - evolution: 253, - evolvers: [ 118, 85, 94, 96, 101 ] - }, - 254: { - evolution: 255, - evolvers: [ 118, 88, 94, 99, 104 ] - }, - 256: { - evolution: 257, - evolvers: [ 118, 86, 94, 97, 102 ] - }, - 258: { - evolution: 259, - evolvers: [ 118, 84, 94, 95, 100 ] - }, - 260: { - evolution: 261, - evolvers: [ 118, 84, 266, 95, 267 ] - }, - 262: { - evolution: 263, - evolvers: [ 117, 81, 87, 92, 103 ] - }, - 264: { - evolution: 265, - evolvers: [ 117, 82, 88, 93, 104 ] - }, - 296: { - evolution: 297, - evolvers: [ 117, 82, 88, 93, 104 ] - }, - 305: { - evolution: 306, - evolvers: [ 118, 87, 87, 303, 103 ] - }, - 307: { - evolution: 308, - evolvers: [ 118, 80, 83, 302, 102 ] - }, - 309: { - evolution: 310, - evolvers: [ 118, 82, 83, 304, 104 ] - }, - 311: { - evolution: 312, - evolvers: [ 118, 79, 83, 301, 101 ] - }, - 313: { - evolution: 314, - evolvers: [ 118, 81, 83, 303, 103 ] - }, - 315: { - evolution: 316, - evolvers: [ 118, 78, 83, 300, 100 ] - }, - 317: { - evolution: 318, - evolvers: [ 117, 80, 86, 97, 102 ] - }, - 319: { - evolution: 320, - evolvers: [ 117, 80, 86, 97, 102 ] - }, - 321: { - evolution: 322, - evolvers: [ 117, 79, 85, 96, 101 ] - }, - 323: { - evolution: 324, - evolvers: [ 117, 90, 85, 96, 101 ] - }, - 326: { - evolution: 327, - evolvers: [ 117, 84, 89, 95, 300 ] - }, - 328: { - evolution: 329, - evolvers: [ 117, 79, 85, 96 ] - }, - 330: { - evolution: 332, - evolvers: [ 116, 331, 302 ] - }, - 331: { - evolution: 332, - evolvers: [ 116, 330, 302 ] - }, - 334: { - evolution: 335, - evolvers: [ 116, 82, 304 ] - }, - 336: { - evolution: 337, - evolvers: [ 117, 81, 87, 98, 103 ] - }, - 340: { - evolution: 341, - evolvers: [ 117, 78, 84, 95, 100 ] - }, - 342: { - evolution: [ 347, 347, 347 ], - evolvers: [ [ 115, 105, 105 ], [ 78, 105, 105 ], [ 89, 105, 105 ] ] - }, - 343: { - evolution: [ 348, 348, 348 ], - evolvers: [ [ 115, 106, 106 ], [ 79, 106, 106 ], [ 90, 106, 106 ] ] - }, - 344: { - evolution: [ 349, 349, 349 ], - evolvers: [ [ 115, 107, 107 ], [ 80, 107, 107 ], [ 91, 107, 107 ] ] - }, - 345: { - evolution: [ 350, 350, 350 ], - evolvers: [ [ 115, 108, 108 ], [ 81, 108, 108 ], [ 92, 108, 108 ] ] - }, - 346: { - evolution: [ 351, 351, 351 ], - evolvers: [ [ 115, 109, 109 ], [ 82, 109, 109 ], [ 93, 109, 109 ] ] - }, - 352: { - evolution: 353, - evolvers: [ 118, 83, 88, 304, 104 ] - }, - 354: { - evolution: 355, - evolvers: [ 116, 85, 90, 96 ] - }, - 356: { - evolution: 357, - evolvers: [ 118, 78, 83, 300, 100 ] - }, - 358: { - evolution: 359, - evolvers: [ 118, 80, 83, 302, 102 ] - }, - 360: { - evolution: 361, - evolvers: [ 118, 82, 83, 304, 104 ] - }, - 362: { - evolution: 363, - evolvers: [ 118, 81, 83, 303, 103 ] - }, - 364: { - evolution: 365, - evolvers: [ 118, 79, 83, 301, 101 ] - }, - 366: { - evolution: 367, - evolvers: [ 118, 88, 266, 99, 267 ] - }, - 368: { - evolution: 373, - evolvers: [ 116, 89, 95 ] - }, - 369: { - evolution: 374, - evolvers: [ 116, 90, 96 ] - }, - 370: { - evolution: 375, - evolvers: [ 116, 91, 97 ] - }, - 371: { - evolution: 376, - evolvers: [ 116, 92, 98 ] - }, - 372: { - evolution: 377, - evolvers: [ 116, 93, 99 ] - }, - 379: { - evolution: 380, - evolvers: [ 115, 78, 300 ] - }, - 383: { - evolution: [ 384, 408 ], - evolvers: [ [ 117, 88, 93, 94, 104 ], [ 118, 88, 266, 304, 267 ] ] - }, - 385: { - evolution: 386, - evolvers: [ 117, 82, 88, 93, 99 ] - }, - 387: { - evolution: 388, - evolvers: [ 117, 81, 87, 385 ] - }, - 389: { - evolution: 390, - evolvers: [ 118, 85, 94, 301, 101 ] - }, - 391: { - evolution: 392, - evolvers: [ 117, 86, 91, 97, 102 ] - }, - 395: { - evolution: 396, - evolvers: [ 79, 85, 90, 301 ] - }, - 397: { - evolution: 398, - evolvers: [ 78, 84, 89, 300 ] - }, - 399: { - evolution: 400, - evolvers: [ 80, 86, 91, 302 ] - }, - 401: { - evolution: 402, - evolvers: [ 78, 84, 89, 300 ] - }, - 404: { - evolution: 405, - evolvers: [ 117, 84, 89, 95, 100 ] - }, - 409: { - evolution: 410, - evolvers: [ 118, 85, 94, 301, 101 ] - }, - 411: { - evolution: 412, - evolvers: [ 118, 84, 94, 300, 100 ] - }, - 413: { - evolution: 414, - evolvers: [ 118, 88, 94, 304, 104 ] - }, - 415: { - evolution: 416, - evolvers: [ 118, 266, 94, 96, 267 ] - }, - 417: { - evolution: 418, - evolvers: [ 118, 83, 86, 302, 102 ] - }, - 423: { - evolution: 424, - evolvers: [ 117, 79, 85, 96, 101 ] - }, - 430: { - evolution: 431, - evolvers: [ 116, 86, 91, 97 ] - }, - 435: { - evolution: 436, - evolvers: [ 117, 85, 433, 434, 96 ] - }, - 437: { - evolution: 438, - evolvers: [ 118, 80, 86, 94, 97 ] - }, - 439: { - evolution: 440, - evolvers: [ 118, 81, 87, 94, 98 ] - }, - 444: { - evolution: 445, - evolvers: [ 441, 442, 443 ] - }, - 446: { - evolution: 447, - evolvers: [ 118, 266, 89, 300, 100 ] - }, - 448: { - evolution: 449, - evolvers: [ 118, 83, 85, 301, 101 ] - }, - 450: { - evolution: 451, - evolvers: [ 118, 83, 86, 302, 102 ] - }, - 452: { - evolution: 453, - evolvers: [ 118, 83, 87, 303, 103 ] - }, - 454: { - evolution: 455, - evolvers: [ 118, 83, 84, 300, 100 ] - }, - 456: { - evolution: 457, - evolvers: [ 118, 83, 88, 304, 104 ] - }, - 458: { - evolution: 459, - evolvers: [ 118, 266, 94, 98, 267 ] - }, - 461: { - evolution: 462, - evolvers: [ 117, 80, 86, 97, 102 ] - }, - 468: { - evolution: 470, - evolvers: [ 116, 81, 98 ] - }, - 469: { - evolution: 471, - evolvers: [ 116, 82, 99 ] - }, - 477: { - evolution: 482, - evolvers: [ 116, 84, 89, 95 ] - }, - 478: { - evolution: 483, - evolvers: [ 116, 85, 90, 96 ] - }, - 479: { - evolution: 484, - evolvers: [ 116, 86, 91, 97 ] - }, - 480: { - evolution: 485, - evolvers: [ 116, 87, 92, 98 ] - }, - 481: { - evolution: 486, - evolvers: [ 116, 88, 93, 99 ] - }, - 487: { - evolution: 490, - evolvers: [ 115, 300 ] - }, - 488: { - evolution: 491, - evolvers: [ 116, 301 ] - }, - 489: { - evolution: 492, - evolvers: [ 117, 302 ] - }, - 493: { - evolution: 495, - evolvers: [ 117, 81, 87 ] - }, - 494: { - evolution: 496, - evolvers: [ 117, 82, 88 ] - }, - 497: { - evolution: 498, - evolvers: [ 90, 94, 96, 301, 101 ] - }, - 499: { - evolution: 500, - evolvers: [ 117, 80, 97, 94 ] - }, - 501: { - evolution: 502, - evolvers: [ 117, 87, 92, 94 ] - }, - 503: { - evolution: 504, - evolvers: [ 117, 82, 88, 104 ] - }, - 505: { - evolution: 506, - evolvers: [ 116, 79, 85, 266 ] - }, - 507: { - evolution: 508, - evolvers: [ 116, 89, 95, 300 ] - }, - 509: { - evolution: 510, - evolvers: [ 117, 85, 96, 96, 301 ] - }, - 512: { - evolution: 513, - evolvers: [ 115, 116, 117, 118, 81 ] - }, - 515: { - evolution: 516, - evolvers: [ 118, 87, 266, 303, 103 ] - }, - 517: { - evolution: 518, - evolvers: [ 116, 81, 98 ] - }, - 519: { - evolution: 520, - evolvers: [ 118, 84, 95, 94, 100 ] - }, - 521: { - evolution: 522, - evolvers: [ 118, 83, 88, 94, 104 ] - }, - 523: { - evolution: 524, - evolvers: [ 118, 85, 96, 301, 101 ] - }, - 525: { - evolution: 526, - evolvers: [ 118, 92, 94, 98, 303 ] - }, - 527: { - evolution: 528, - evolvers: [ 118, 86, 266, 97, 302 ] - }, - 529: { - evolution: 530, - evolvers: [ 118, 87, 266, 98, 267 ] - }, - 531: { - evolution: 532, - evolvers: [ 117, 80, 86, 91, 97 ] - }, - 533: { - evolution: 534, - evolvers: [ 118, 79, 85, 96, 101 ] - }, - 535: { - evolution: 536, - evolvers: [ 118, 80, 86, 91, 97 ] - }, - 537: { - evolution: 538, - evolvers: [ 117, 81, 92, 98, 103 ] - }, - 543: { - evolution: 544, - evolvers: [ 117, 86, 97, 102 ] - }, - 545: { - evolution: 546, - evolvers: [ 118, 266, 92, 303, 103 ] - }, - 547: { - evolution: 548, - evolvers: [ 118, 78, 78, 84, 84 ] - }, - 549: { - evolution: 550, - evolvers: [ 117, 82, 88, 99, 104 ] - }, - 553: { - evolution: 554, - evolvers: [ 118, 83, 97, 302, 102 ] - }, - 555: { - evolution: 556, - evolvers: [ 118, 83, 96, 301, 101 ] - }, - 557: { - evolution: 558, - evolvers: [ 118, 88, 94, 304, 104 ] - }, - 559: { - evolution: 560, - evolvers: [ 118, 83, 84, 300, 100 ] - }, - 561: { - evolution: 562, - evolvers: [ 118, 86, 266, 302, 267 ] - }, - 568: { - evolution: 569, - evolvers: [ 117, 83, 88, 93, 99 ] - }, - 570: { - evolution: 571, - evolvers: [ 170, 142, 184, 237, 572 ] - }, - 574: { - evolution: 575, - evolvers: [ 118, 88, 266, 304, 104 ] - }, - 577: { - evolution: 578, - evolvers: [ 118, 266, 95, 300, 267 ] - }, - 579: { - evolution: 580, - evolvers: [ 117, 85, 86, 96, 97 ] - }, - 585: { - evolution: 586, - evolvers: [ 116, 87, 92, 98 ] - }, - 587: { - evolution: 588, - evolvers: [ 117, 304 ] - }, - 589: { - evolution: 590, - evolvers: [ 116, 117, 79, 85 ] - }, - 596: { - evolution: 597, - evolvers: [ 117, 78, 84, 89, 95 ] - }, - 598: { - evolution: 599, - evolvers: [ 117, 82, 82, 88, 88 ] - }, - 600: { - evolution: 601, - evolvers: [ 117, 81, 87, 98, 103 ] - }, - 602: { - evolution: 603, - evolvers: [ 118, 266, 96, 301, 101 ] - }, - 604: { - evolution: 605, - evolvers: [ 117, 86, 97, 97, 302 ] - }, - 606: { - evolution: 607, - evolvers: [ 117, 80, 86, 97, 102 ] - }, - 612: { - evolution: 613, - evolvers: [ 91, 94, 97, 97, 302 ] - }, - 629: { - evolution: 739, - evolvers: [ 117, 82, 83, 99, 104 ] - }, - 630: { - evolution: [ 631, 736 ], - evolvers: [ [ 117, 90, 96, 301, 101 ], [ 118, 78, 94, 95, 100 ] ] - }, - 632: { - evolution: [ 633, 737 ], - evolvers: [ [ 117, 89, 95, 300, 100 ], [ 118, 79, 94, 96, 101 ] ] - }, - 634: { - evolution: 635, - evolvers: [ 117, 79, 85, 96, 101 ] - }, - 638: { - evolution: 639, - evolvers: [ 118, 83, 96, 301, 101 ] - }, - 640: { - evolution: 641, - evolvers: [ 118, 83, 86, 302, 102 ] - }, - 642: { - evolution: 643, - evolvers: [ 118, 92, 94, 303, 103 ] - }, - 644: { - evolution: 645, - evolvers: [ 118, 94, 99, 304, 104 ] - }, - 646: { - evolution: 647, - evolvers: [ 118, 84, 266, 95, 100 ] - }, - 648: { - evolution: 649, - evolvers: [ 118, 85, 266, 301, 267 ] - }, - 650: { - evolution: 651, - evolvers: [ 117, 83, 88, 93, 104 ] - }, - 652: { - evolution: 653, - evolvers: [ 116, 117, 80, 91, 97 ] - }, - 653: { - evolution: [ 654, 654 ], - evolvers: [ [ 118, 86, 266, 97, 102 ], [ 18 ] ] - }, - 655: { - evolution: 656, - evolvers: [ 117, 78, 84, 95, 100 ] - }, - 660: { - evolution: 661, - evolvers: [ 117, 85, 94, 96, 101 ] - }, - 663: { - evolution: 664, - evolvers: [ 117, 81, 87, 98, 103 ] - }, - 665: { - evolution: 666, - evolvers: [ 117, 79, 85, 96, 101 ] - }, - 668: { - evolution: 669, - evolvers: [ 118, 87, 266, 303, 267 ] - }, - 670: { - evolution: 671, - evolvers: [ 118, 83, 86, 302, 102 ] - }, - 672: { - evolution: 673, - evolvers: [ 118, 84, 94, 300, 100 ] - }, - 674: { - evolution: 675, - evolvers: [ 118, 83, 88, 304, 104 ] - }, - 676: { - evolution: 677, - evolvers: [ 94, 96, 96, 301, 301 ] - }, - 678: { - evolution: 679, - evolvers: [ 117, 87, 94, 303, 103 ] - }, - 680: { - evolution: 681, - evolvers: [ 117, 80, 86, 97, 302 ] - }, - 682: { - evolution: 683, - evolvers: [ 117, 81, 87, 98, 303 ] - }, - 684: { - evolution: 685, - evolvers: [ 117, 88, 93, 99, 304 ] - }, - 687: { - evolution: 688, - evolvers: [ 117, 78, 84, 95, 100 ] - }, - 689: { - evolution: 690, - evolvers: [ 117, 82, 88, 99, 104 ] - }, - 691: { - evolution: 696, - evolvers: [ 116, 97, 302 ] - }, - 692: { - evolution: 697, - evolvers: [ 116, 96, 301 ] - }, - 693: { - evolution: 698, - evolvers: [ 116, 98, 303 ] - }, - 694: { - evolution: 699, - evolvers: [ 116, 95, 300 ] - }, - 695: { - evolution: 700, - evolvers: [ 116, 99, 304 ] - }, - 706: { - evolution: 707, - evolvers: [ 117, 84, 89, 95, 100 ] - }, - 708: { - evolution: 709, - evolvers: [ 117, 81, 87, 303, 103 ] - }, - 710: { - evolution: 711, - evolvers: [ 117, 87, 94, 303, 103 ] - }, - 712: { - evolution: 713, - evolvers: [ 117, 90, 96, 301, 101 ] - }, - 715: { - evolution: 716, - evolvers: [ 116, 117, 81, 87 ] - }, - 717: { - evolution: 718, - evolvers: [ 118, 266, 99, 304, 267 ] - }, - 719: { - evolution: 720, - evolvers: [ 118, 86, 266, 102, 267 ] - }, - 721: { - evolution: 722, - evolvers: [ 117, 78, 89, 95 ] - }, - 723: { - evolution: 724, - evolvers: [ 117, 92, 98, 98, 103 ] - }, - 725: { - evolution: 726, - evolvers: [ 117, 79, 85, 96, 101 ] - }, - 728: { - evolution: 729, - evolvers: [ 117, 86, 91, 97, 302 ] - }, - 730: { - evolution: 731, - evolvers: [ 117, 88, 93, 99, 304 ] - }, - 732: { - evolution: 733, - evolvers: [ 116, 84, 95, 300 ] - }, - 734: { - evolution: 735, - evolvers: [ 116, 87, 98, 303 ] - }, - 740: { - evolution: 741, - evolvers: [ 117, 79, 90, 96 ] - }, - 742: { - evolution: 743, - evolvers: [ 117, 80, 86, 91, 97 ] - }, - 744: { - evolution: 745, - evolvers: [ 118, 85, 94, 301, 101 ] - }, - 747: { - evolution: 748, - evolvers: [ 118, 84, 266, 300, 267 ] - }, - 749: { - evolution: 750, - evolvers: [ 118, 83, 86, 302, 102 ] - }, - 751: { - evolution: 752, - evolvers: [ 118, 83, 85, 301, 101 ] - }, - 753: { - evolution: 754, - evolvers: [ 118, 94, 96, 301, 101 ] - }, - 755: { - evolution: 756, - evolvers: [ 118, 83, 88, 304, 104 ] - }, - 757: { - evolution: 758, - evolvers: [ 118, 87, 87, 303, 103 ] - }, - 759: { - evolution: 760, - evolvers: [ 118, 84, 84, 300, 100 ] - }, - 776: { - evolution: 777, - evolvers: [ 116, 117, 81, 87, 103 ] - }, - 778: { - evolution: 779, - evolvers: [ 117, 85, 94, 96, 301 ] - }, - 780: { - evolution: 781, - evolvers: [ 118, 84, 94, 300, 100 ] - }, - 782: { - evolution: 783, - evolvers: [ 117, 93, 94, 304, 104 ] - }, - 784: { - evolution: 785, - evolvers: [ 116, 89, 95 ] - }, - 786: { - evolution: 787, - evolvers: [ 116, 81, 87 ] - }, - 788: { - evolution: 789, - evolvers: [ 116, 80, 86 ] - }, - 790: { - evolution: 791, - evolvers: [ 89, 90, 91 ] - }, - 792: { - evolution: 793, - evolvers: [ 116, 117, 99 ] - }, - 794: { - evolution: 795, - evolvers: [ 118, 88, 266, 304, 104 ] - }, - 796: { - evolution: 797, - evolvers: [ 117, 82, 88, 99, 104 ] - }, - 801: { - evolution: 802, - evolvers: [ 87, 94, 98, 303, 103 ] - }, - 803: { - evolution: 804, - evolvers: [ 117, 80, 86, 302, 102 ] - }, - 805: { - evolution: 806, - evolvers: [ 118, 83, 88, 99, 304 ] - }, - 807: { - evolution: 808, - evolvers: [ 117, 87, 92, 98, 103 ] - }, - 809: { - evolution: [ 810, 810 ], - evolvers: [ [ 116, 78, 84, 89, 95 ], [ 404 ] ] - }, - 815: { - evolution: [ 816, 894 ], - evolvers: [ [ 117, 88, 94, 304, 104 ], [ 117, 88, 94, 99, 104 ] ] - }, - 830: { - evolution: 831, - evolvers: [ 118, 86, 94, 302, 102 ] - }, - 832: { - evolution: 833, - evolvers: [ 117, 89, 95, 300, 100 ] - }, - 835: { - evolution: 836, - evolvers: [ 118, 84, 266, 300, 100 ] - }, - 837: { - evolution: 838, - evolvers: [ 83, 86, 97, 302, 102 ] - }, - 839: { - evolution: 840, - evolvers: [ 118, 88, 266, 304, 104 ] - }, - 841: { - evolution: 842, - evolvers: [ 118, 83, 87, 303, 103 ] - }, - 843: { - evolution: 844, - evolvers: [ 118, 84, 95, 300, 100 ] - }, - 845: { - evolution: 846, - evolvers: [ 118, 85, 94, 301, 101 ] - }, - 847: { - evolution: 848, - evolvers: [ 117, 80, 86, 97, 102 ] - }, - 851: { - evolution: 852, - evolvers: [ 117, 78, 85, 95, 101 ] - }, - 855: { - evolution: 856, - evolvers: [ 117, 86, 94, 97, 102 ] - }, - 857: { - evolution: 858, - evolvers: [ 117, 98, 98, 303, 303 ] - }, - 859: { - evolution: 860, - evolvers: [ 117, 87, 98, 98, 303 ] - }, - 861: { - evolution: 862, - evolvers: [ 117, 79, 85, 301, 101 ] - }, - 864: { - evolution: 865, - evolvers: [ 118, 87, 266, 303, 103 ] - }, - 869: { - evolution: 870, - evolvers: [ 118, 85, 266, 301, 267 ] - }, - 871: { - evolution: 872, - evolvers: [ 83, 85, 96, 301, 101 ] - }, - 873: { - evolution: 874, - evolvers: [ 118, 87, 94, 303, 103 ] - }, - 875: { - evolution: 876, - evolvers: [ 118, 88, 99, 304, 104 ] - }, - 877: { - evolution: 878, - evolvers: [ 86, 266, 91, 97, 102 ] - }, - 879: { - evolution: 880, - evolvers: [ 118, 83, 84, 300, 100 ] - }, - 881: { - evolution: 882, - evolvers: [ 118, 85, 94, 301, 101 ] - }, - 883: { - evolution: 884, - evolvers: [ 117, 88, 93, 99, 104 ] - }, - 889: { - evolution: 890, - evolvers: [ 117, 80, 86, 97, 302 ] - }, - 895: { - evolution: 896, - evolvers: [ 117, 86, 91, 97, 102 ] - }, - 900: { - evolution: 901, - evolvers: [ 118, 86, 94, 302, 102 ] - }, - 902: { - evolution: 903, - evolvers: [ 117, 87, 92, 98, 103 ] - }, - 905: { - evolution: 906, - evolvers: [ 118, 83, 84, 300, 100 ] - }, - 907: { - evolution: 908, - evolvers: [ 88, 266, 94, 304, 104 ] - }, - 909: { - evolution: 910, - evolvers: [ 118, 83, 87, 98, 103 ] - }, - 911: { - evolution: 912, - evolvers: [ 118, 86, 266, 97, 102 ] - }, - 913: { - evolution: 914, - evolvers: [ 85, 94, 94, 301, 101 ] - }, - 915: { - evolution: 916, - evolvers: [ 84, 85, 86, 87, 88 ] - }, - 917: { - evolution: 918, - evolvers: [ 117, 79, 85, 96, 101 ] - } -}; \ No newline at end of file + 1: { + evolution: 2, + evolvers: [ 78 ] + }, + 2: { + evolution: 3, + evolvers: [ 115, 78 ] + }, + 3: { + evolution: 4, + evolvers: [ 117, 84, 95, 100 ] + }, + 5: { + evolution: [ 6, 7 ], + evolvers: [ [ 115, 80 ], [ 116, 80, 97 ] ] + }, + 6: { + evolution: 8, + evolvers: [ 117, 86, 97, 102 ] + }, + 7: { + evolution: 8, + evolvers: [ 117, 80, 102 ] + }, + 9: { + evolution: [ 10, 11 ], + evolvers: [ [ 115, 82 ], [ 116, 82, 99 ] ] + }, + 10: { + evolution: 12, + evolvers: [ 117, 88, 99, 104 ] + }, + 11: { + evolution: 12, + evolvers: [ 117, 82, 104 ] + }, + 13: { + evolution: [ 14, 15 ], + evolvers: [ [ 115, 81 ], [ 115, 81, 98 ] ] + }, + 14: { + evolution: [ 15, 16 ], + evolvers: [ [ 117 ], [ 117, 87, 98, 103 ] ] + }, + 15: { + evolution: 16, + evolvers: [ 117, 81, 103 ] + }, + 17: { + evolution: [ 18, 19 ], + evolvers: [ [ 115, 79 ], [ 116, 79, 96 ] ] + }, + 18: { + evolution: 20, + evolvers: [ 117, 85, 96, 101 ] + }, + 19: { + evolution: 20, + evolvers: [ 117, 79, 101 ] + }, + 21: { + evolution: [ 22, 23, 24, 25, 26 ], + evolvers: [ [ 116, 81, 98 ], [ 116, 82, 99 ], [ 116, 78, 95 ], [ 116, 79, 96 ], [ 116, 80, 97 ] ] + }, + 29: { + evolution: 30, + evolvers: [ 117, 78, 89, 100 ] + }, + 31: { + evolution: 32, + evolvers: [ 115, 81 ] + }, + 33: { + evolution: 34, + evolvers: [ 115, 82 ] + }, + 35: { + evolution: 228, + evolvers: [ 116, 78, 89 ] + }, + 38: { + evolution: 39, + evolvers: [ 116, 82, 93 ] + }, + 43: { + evolution: [ 44, 229 ], + evolvers: [ [ 116, 80, 91 ], [ 116, 81, 92 ] ] + }, + 45: { + evolution: 46, + evolvers: [ 117, 79, 90, 101 ] + }, + 49: { + evolution: 230, + evolvers: [ 116, 78, 89 ] + }, + 53: { + evolution: 54, + evolvers: [ 116, 79, 90 ] + }, + 55: { + evolution: 56, + evolvers: [ 116, 78, 89 ] + }, + 57: { + evolution: 58, + evolvers: [ 117, 82, 93, 104 ] + }, + 63: { + evolution: 64, + evolvers: [ 116, 80, 91 ] + }, + 65: { + evolution: 66, + evolvers: [ 117, 78, 89, 100 ] + }, + 67: { + evolution: 68, + evolvers: [ 117, 83, 79, 85, 96 ] + }, + 69: { + evolution: 70, + evolvers: [ 117, 83, 80, 86, 97 ] + }, + 70: { + evolution: 268, + evolvers: [ 117, 80, 86, 91, 102 ] + }, + 71: { + evolution: [ 72, 72 ], + evolvers: [ [ 117, 81, 98 ], [ 444 ] ] + }, + 72: { + evolution: 73, + evolvers: [ 118, 83, 87, 98, 103 ] + }, + 74: { + evolution: 75, + evolvers: [ 118, 83, 85, 85, 101 ] + }, + 76: { + evolution: 77, + evolvers: [ 118, 83, 87, 98, 103 ] + }, + 121: { + evolution: 142, + evolvers: [ 89 ] + }, + 122: { + evolution: 143, + evolvers: [ 90 ] + }, + 123: { + evolution: 144, + evolvers: [ 91 ] + }, + 124: { + evolution: 145, + evolvers: [ 92 ] + }, + 125: { + evolution: 146, + evolvers: [ 93 ] + }, + 126: { + evolution: 147, + evolvers: [ 89 ] + }, + 127: { + evolution: 148, + evolvers: [ 90 ] + }, + 128: { + evolution: 149, + evolvers: [ 91 ] + }, + 129: { + evolution: 150, + evolvers: [ 92 ] + }, + 130: { + evolution: 151, + evolvers: [ 93 ] + }, + 131: { + evolution: 152, + evolvers: [ 89 ] + }, + 132: { + evolution: 153, + evolvers: [ 90 ] + }, + 133: { + evolution: 154, + evolvers: [ 91 ] + }, + 134: { + evolution: 155, + evolvers: [ 92 ] + }, + 135: { + evolution: 156, + evolvers: [ 93 ] + }, + 136: { + evolution: 157, + evolvers: [ 89 ] + }, + 137: { + evolution: 158, + evolvers: [ 90 ] + }, + 138: { + evolution: 159, + evolvers: [ 91 ] + }, + 139: { + evolution: 160, + evolvers: [ 92 ] + }, + 140: { + evolution: 161, + evolvers: [ 93 ] + }, + 141: { + evolution: 162, + evolvers: [ 115, 93 ] + }, + 142: { + evolution: 269, + evolvers: [ 115, 116, 89 ] + }, + 143: { + evolution: 270, + evolvers: [ 115, 116, 90 ] + }, + 144: { + evolution: 271, + evolvers: [ 115, 116, 91 ] + }, + 145: { + evolution: 272, + evolvers: [ 115, 116, 92 ] + }, + 146: { + evolution: 273, + evolvers: [ 115, 116, 93 ] + }, + 147: { + evolution: 274, + evolvers: [ 116, 95 ] + }, + 148: { + evolution: 275, + evolvers: [ 116, 96 ] + }, + 149: { + evolution: 276, + evolvers: [ 116, 97 ] + }, + 150: { + evolution: 277, + evolvers: [ 116, 98 ] + }, + 151: { + evolution: 278, + evolvers: [ 116, 99 ] + }, + 152: { + evolution: 279, + evolvers: [ 78, 84 ] + }, + 153: { + evolution: 280, + evolvers: [ 79, 85 ] + }, + 154: { + evolution: 281, + evolvers: [ 80, 86 ] + }, + 155: { + evolution: 282, + evolvers: [ 81, 87 ] + }, + 156: { + evolution: 283, + evolvers: [ 82, 88 ] + }, + 157: { + evolution: 284, + evolvers: [ 115, 116, 89 ] + }, + 158: { + evolution: 285, + evolvers: [ 115, 116, 90 ] + }, + 159: { + evolution: 286, + evolvers: [ 115, 116, 91 ] + }, + 160: { + evolution: 287, + evolvers: [ 115, 116, 92 ] + }, + 161: { + evolution: 288, + evolvers: [ 115, 116, 93 ] + }, + 162: { + evolution: 289, + evolvers: [ 104 ] + }, + 179: { + evolution: 184, + evolvers: [ 78 ] + }, + 180: { + evolution: 185, + evolvers: [ 80 ] + }, + 181: { + evolution: 186, + evolvers: [ 79 ] + }, + 182: { + evolution: 187, + evolvers: [ 81 ] + }, + 183: { + evolution: 188, + evolvers: [ 115, 82 ] + }, + 184: { + evolution: 194, + evolvers: [ 116, 78, 84 ] + }, + 185: { + evolution: 195, + evolvers: [ 116, 80, 86 ] + }, + 186: { + evolution: 196, + evolvers: [ 116, 79, 85 ] + }, + 187: { + evolution: 197, + evolvers: [ 116, 81, 87 ] + }, + 188: { + evolution: 198, + evolvers: [ 116, 117, 82, 88 ] + }, + 199: { + evolution: 200, + evolvers: [ 94, 78 ] + }, + 201: { + evolution: 202, + evolvers: [ 94, 79 ] + }, + 203: { + evolution: 204, + evolvers: [ 94, 82 ] + }, + 205: { + evolution: 206, + evolvers: [ 94, 80 ] + }, + 207: { + evolution: [ 208, 462 ], + evolvers: [ [ 94, 81 ], [ 117, 231 ] ] + }, + 209: { + evolution: 210, + evolvers: [ 118, 82, 83, 88, 104 ] + }, + 211: { + evolution: 212, + evolvers: [ 116, 79, 90 ] + }, + 213: { + evolution: 214, + evolvers: [ 117, 78, 95, 100 ] + }, + 216: { + evolution: 217, + evolvers: [ 118, 84, 100, 94, 89 ] + }, + 218: { + evolution: 219, + evolvers: [ 118, 86, 102, 94, 91 ] + }, + 220: { + evolution: 221, + evolvers: [ 118, 88, 104, 94, 93 ] + }, + 222: { + evolution: 223, + evolvers: [ 117, 81, 98, 83 ] + }, + 224: { + evolution: 225, + evolvers: [ 117, 79, 90, 83 ] + }, + 226: { + evolution: 227, + evolvers: [ 118, 83, 86, 86, 102 ] + }, + 231: { + evolution: 232, + evolvers: [ 117, 79, 85, 90, 101 ] + }, + 233: { + evolution: 234, + evolvers: [ 116, 81, 92 ] + }, + 235: { + evolution: 236, + evolvers: [ 116, 78, 89 ] + }, + 237: { + evolution: 242, + evolvers: [ 115, 89, 95 ] + }, + 238: { + evolution: 243, + evolvers: [ 115, 91, 97 ] + }, + 239: { + evolution: 244, + evolvers: [ 115, 90, 96 ] + }, + 240: { + evolution: 245, + evolvers: [ 115, 92, 98 ] + }, + 241: { + evolution: 246, + evolvers: [ 115, 93, 99 ] + }, + 248: { + evolution: 249, + evolvers: [ 118, 84, 84, 95, 100 ] + }, + 250: { + evolution: 251, + evolvers: [ 118, 87, 94, 98, 103 ] + }, + 252: { + evolution: 253, + evolvers: [ 118, 85, 94, 96, 101 ] + }, + 254: { + evolution: 255, + evolvers: [ 118, 88, 94, 99, 104 ] + }, + 256: { + evolution: 257, + evolvers: [ 118, 86, 94, 97, 102 ] + }, + 258: { + evolution: 259, + evolvers: [ 118, 84, 94, 95, 100 ] + }, + 260: { + evolution: 261, + evolvers: [ 118, 84, 266, 95, 267 ] + }, + 262: { + evolution: 263, + evolvers: [ 117, 81, 87, 92, 103 ] + }, + 264: { + evolution: 265, + evolvers: [ 117, 82, 88, 93, 104 ] + }, + 296: { + evolution: 297, + evolvers: [ 117, 82, 88, 93, 104 ] + }, + 305: { + evolution: 306, + evolvers: [ 118, 87, 87, 303, 103 ] + }, + 307: { + evolution: 308, + evolvers: [ 118, 80, 83, 302, 102 ] + }, + 309: { + evolution: 310, + evolvers: [ 118, 82, 83, 304, 104 ] + }, + 311: { + evolution: 312, + evolvers: [ 118, 79, 83, 301, 101 ] + }, + 313: { + evolution: 314, + evolvers: [ 118, 81, 83, 303, 103 ] + }, + 315: { + evolution: 316, + evolvers: [ 118, 78, 83, 300, 100 ] + }, + 317: { + evolution: 318, + evolvers: [ 117, 80, 86, 97, 102 ] + }, + 319: { + evolution: 320, + evolvers: [ 117, 80, 86, 97, 102 ] + }, + 321: { + evolution: 322, + evolvers: [ 117, 79, 85, 96, 101 ] + }, + 323: { + evolution: 324, + evolvers: [ 117, 90, 85, 96, 101 ] + }, + 326: { + evolution: 327, + evolvers: [ 117, 84, 89, 95, 300 ] + }, + 328: { + evolution: 329, + evolvers: [ 117, 79, 85, 96 ] + }, + 330: { + evolution: 332, + evolvers: [ 116, 331, 302 ] + }, + 331: { + evolution: 332, + evolvers: [ 116, 330, 302 ] + }, + 334: { + evolution: 335, + evolvers: [ 116, 82, 304 ] + }, + 336: { + evolution: 337, + evolvers: [ 117, 81, 87, 98, 103 ] + }, + 340: { + evolution: 341, + evolvers: [ 117, 78, 84, 95, 100 ] + }, + 342: { + evolution: [ 347, 347, 347 ], + evolvers: [ [ 115, 105, 105 ], [ 78, 105, 105 ], [ 89, 105, 105 ] ] + }, + 343: { + evolution: [ 348, 348, 348 ], + evolvers: [ [ 115, 106, 106 ], [ 79, 106, 106 ], [ 90, 106, 106 ] ] + }, + 344: { + evolution: [ 349, 349, 349 ], + evolvers: [ [ 115, 107, 107 ], [ 80, 107, 107 ], [ 91, 107, 107 ] ] + }, + 345: { + evolution: [ 350, 350, 350 ], + evolvers: [ [ 115, 108, 108 ], [ 81, 108, 108 ], [ 92, 108, 108 ] ] + }, + 346: { + evolution: [ 351, 351, 351 ], + evolvers: [ [ 115, 109, 109 ], [ 82, 109, 109 ], [ 93, 109, 109 ] ] + }, + 352: { + evolution: 353, + evolvers: [ 118, 83, 88, 304, 104 ] + }, + 354: { + evolution: 355, + evolvers: [ 116, 85, 90, 96 ] + }, + 356: { + evolution: 357, + evolvers: [ 118, 78, 83, 300, 100 ] + }, + 358: { + evolution: 359, + evolvers: [ 118, 80, 83, 302, 102 ] + }, + 360: { + evolution: 361, + evolvers: [ 118, 82, 83, 304, 104 ] + }, + 362: { + evolution: 363, + evolvers: [ 118, 81, 83, 303, 103 ] + }, + 364: { + evolution: 365, + evolvers: [ 118, 79, 83, 301, 101 ] + }, + 366: { + evolution: 367, + evolvers: [ 118, 88, 266, 99, 267 ] + }, + 368: { + evolution: 373, + evolvers: [ 116, 89, 95 ] + }, + 369: { + evolution: 374, + evolvers: [ 116, 90, 96 ] + }, + 370: { + evolution: 375, + evolvers: [ 116, 91, 97 ] + }, + 371: { + evolution: 376, + evolvers: [ 116, 92, 98 ] + }, + 372: { + evolution: 377, + evolvers: [ 116, 93, 99 ] + }, + 379: { + evolution: 380, + evolvers: [ 115, 78, 300 ] + }, + 383: { + evolution: [ 384, 408 ], + evolvers: [ [ 117, 88, 93, 94, 104 ], [ 118, 88, 266, 304, 267 ] ] + }, + 385: { + evolution: 386, + evolvers: [ 117, 82, 88, 93, 99 ] + }, + 387: { + evolution: 388, + evolvers: [ 117, 81, 87, 385 ] + }, + 389: { + evolution: 390, + evolvers: [ 118, 85, 94, 301, 101 ] + }, + 391: { + evolution: 392, + evolvers: [ 117, 86, 91, 97, 102 ] + }, + 395: { + evolution: 396, + evolvers: [ 79, 85, 90, 301 ] + }, + 397: { + evolution: 398, + evolvers: [ 78, 84, 89, 300 ] + }, + 399: { + evolution: 400, + evolvers: [ 80, 86, 91, 302 ] + }, + 401: { + evolution: 402, + evolvers: [ 78, 84, 89, 300 ] + }, + 404: { + evolution: 405, + evolvers: [ 117, 84, 89, 95, 100 ] + }, + 409: { + evolution: 410, + evolvers: [ 118, 85, 94, 301, 101 ] + }, + 411: { + evolution: 412, + evolvers: [ 118, 84, 94, 300, 100 ] + }, + 413: { + evolution: 414, + evolvers: [ 118, 88, 94, 304, 104 ] + }, + 415: { + evolution: 416, + evolvers: [ 118, 266, 94, 96, 267 ] + }, + 417: { + evolution: 418, + evolvers: [ 118, 83, 86, 302, 102 ] + }, + 423: { + evolution: 424, + evolvers: [ 117, 79, 85, 96, 101 ] + }, + 430: { + evolution: 431, + evolvers: [ 116, 86, 91, 97 ] + }, + 435: { + evolution: 436, + evolvers: [ 117, 85, 433, 434, 96 ] + }, + 437: { + evolution: 438, + evolvers: [ 118, 80, 86, 94, 97 ] + }, + 439: { + evolution: 440, + evolvers: [ 118, 81, 87, 94, 98 ] + }, + 444: { + evolution: 445, + evolvers: [ 441, 442, 443 ] + }, + 446: { + evolution: 447, + evolvers: [ 118, 266, 89, 300, 100 ] + }, + 448: { + evolution: 449, + evolvers: [ 118, 83, 85, 301, 101 ] + }, + 450: { + evolution: 451, + evolvers: [ 118, 83, 86, 302, 102 ] + }, + 452: { + evolution: 453, + evolvers: [ 118, 83, 87, 303, 103 ] + }, + 454: { + evolution: 455, + evolvers: [ 118, 83, 84, 300, 100 ] + }, + 456: { + evolution: 457, + evolvers: [ 118, 83, 88, 304, 104 ] + }, + 458: { + evolution: 459, + evolvers: [ 118, 266, 94, 98, 267 ] + }, + 461: { + evolution: 462, + evolvers: [ 117, 80, 86, 97, 102 ] + }, + 468: { + evolution: 470, + evolvers: [ 116, 81, 98 ] + }, + 469: { + evolution: 471, + evolvers: [ 116, 82, 99 ] + }, + 477: { + evolution: 482, + evolvers: [ 116, 84, 89, 95 ] + }, + 478: { + evolution: 483, + evolvers: [ 116, 85, 90, 96 ] + }, + 479: { + evolution: 484, + evolvers: [ 116, 86, 91, 97 ] + }, + 480: { + evolution: 485, + evolvers: [ 116, 87, 92, 98 ] + }, + 481: { + evolution: 486, + evolvers: [ 116, 88, 93, 99 ] + }, + 487: { + evolution: 490, + evolvers: [ 115, 300 ] + }, + 488: { + evolution: 491, + evolvers: [ 116, 301 ] + }, + 489: { + evolution: 492, + evolvers: [ 117, 302 ] + }, + 493: { + evolution: 495, + evolvers: [ 117, 81, 87 ] + }, + 494: { + evolution: 496, + evolvers: [ 117, 82, 88 ] + }, + 497: { + evolution: 498, + evolvers: [ 90, 94, 96, 301, 101 ] + }, + 499: { + evolution: 500, + evolvers: [ 117, 80, 97, 94 ] + }, + 501: { + evolution: 502, + evolvers: [ 117, 87, 92, 94 ] + }, + 503: { + evolution: 504, + evolvers: [ 117, 82, 88, 104 ] + }, + 505: { + evolution: 506, + evolvers: [ 116, 79, 85, 266 ] + }, + 507: { + evolution: 508, + evolvers: [ 116, 89, 95, 300 ] + }, + 509: { + evolution: 510, + evolvers: [ 117, 85, 96, 96, 301 ] + }, + 512: { + evolution: 513, + evolvers: [ 115, 116, 117, 118, 81 ] + }, + 515: { + evolution: 516, + evolvers: [ 118, 87, 266, 303, 103 ] + }, + 517: { + evolution: 518, + evolvers: [ 116, 81, 98 ] + }, + 519: { + evolution: 520, + evolvers: [ 118, 84, 95, 94, 100 ] + }, + 521: { + evolution: 522, + evolvers: [ 118, 83, 88, 94, 104 ] + }, + 523: { + evolution: 524, + evolvers: [ 118, 85, 96, 301, 101 ] + }, + 525: { + evolution: 526, + evolvers: [ 118, 92, 94, 98, 303 ] + }, + 527: { + evolution: 528, + evolvers: [ 118, 86, 266, 97, 302 ] + }, + 529: { + evolution: 530, + evolvers: [ 118, 87, 266, 98, 267 ] + }, + 531: { + evolution: 532, + evolvers: [ 117, 80, 86, 91, 97 ] + }, + 533: { + evolution: 534, + evolvers: [ 118, 79, 85, 96, 101 ] + }, + 535: { + evolution: 536, + evolvers: [ 118, 80, 86, 91, 97 ] + }, + 537: { + evolution: 538, + evolvers: [ 117, 81, 92, 98, 103 ] + }, + 543: { + evolution: 544, + evolvers: [ 117, 86, 97, 102 ] + }, + 545: { + evolution: 546, + evolvers: [ 118, 266, 92, 303, 103 ] + }, + 547: { + evolution: 548, + evolvers: [ 118, 78, 78, 84, 84 ] + }, + 549: { + evolution: 550, + evolvers: [ 117, 82, 88, 99, 104 ] + }, + 553: { + evolution: 554, + evolvers: [ 118, 83, 97, 302, 102 ] + }, + 555: { + evolution: 556, + evolvers: [ 118, 83, 96, 301, 101 ] + }, + 557: { + evolution: 558, + evolvers: [ 118, 88, 94, 304, 104 ] + }, + 559: { + evolution: 560, + evolvers: [ 118, 83, 84, 300, 100 ] + }, + 561: { + evolution: 562, + evolvers: [ 118, 86, 266, 302, 267 ] + }, + 568: { + evolution: 569, + evolvers: [ 117, 83, 88, 93, 99 ] + }, + 570: { + evolution: 571, + evolvers: [ 170, 142, 184, 237, 572 ] + }, + 574: { + evolution: 575, + evolvers: [ 118, 88, 266, 304, 104 ] + }, + 577: { + evolution: 578, + evolvers: [ 118, 266, 95, 300, 267 ] + }, + 579: { + evolution: 580, + evolvers: [ 117, 85, 86, 96, 97 ] + }, + 585: { + evolution: 586, + evolvers: [ 116, 87, 92, 98 ] + }, + 587: { + evolution: 588, + evolvers: [ 117, 304 ] + }, + 589: { + evolution: 590, + evolvers: [ 116, 117, 79, 85 ] + }, + 596: { + evolution: 597, + evolvers: [ 117, 78, 84, 89, 95 ] + }, + 598: { + evolution: 599, + evolvers: [ 117, 82, 82, 88, 88 ] + }, + 600: { + evolution: 601, + evolvers: [ 117, 81, 87, 98, 103 ] + }, + 602: { + evolution: 603, + evolvers: [ 118, 266, 96, 301, 101 ] + }, + 604: { + evolution: 605, + evolvers: [ 117, 86, 97, 97, 302 ] + }, + 606: { + evolution: 607, + evolvers: [ 117, 80, 86, 97, 102 ] + }, + 612: { + evolution: 613, + evolvers: [ 91, 94, 97, 97, 302 ] + }, + 629: { + evolution: 739, + evolvers: [ 117, 82, 83, 99, 304 ] + }, + 630: { + evolution: [ 631, 736 ], + evolvers: [ [ 117, 90, 96, 301, 101 ], [ 118, 78, 94, 95, 100 ] ] + }, + 632: { + evolution: [ 633, 737 ], + evolvers: [ [ 117, 89, 95, 300, 100 ], [ 118, 79, 94, 96, 101 ] ] + }, + 634: { + evolution: 635, + evolvers: [ 117, 79, 85, 96, 101 ] + }, + 638: { + evolution: 639, + evolvers: [ 118, 83, 96, 301, 101 ] + }, + 640: { + evolution: 641, + evolvers: [ 118, 83, 86, 302, 102 ] + }, + 642: { + evolution: 643, + evolvers: [ 118, 92, 94, 303, 103 ] + }, + 644: { + evolution: 645, + evolvers: [ 118, 94, 99, 304, 104 ] + }, + 646: { + evolution: 647, + evolvers: [ 118, 84, 266, 95, 100 ] + }, + 648: { + evolution: 649, + evolvers: [ 118, 85, 266, 301, 267 ] + }, + 650: { + evolution: 651, + evolvers: [ 117, 83, 88, 93, 104 ] + }, + 652: { + evolution: 653, + evolvers: [ 116, 117, 80, 91, 97 ] + }, + 653: { + evolution: [ 654, 654 ], + evolvers: [ [ 118, 86, 266, 97, 102 ], [ 18 ] ] + }, + 655: { + evolution: 656, + evolvers: [ 117, 78, 84, 95, 100 ] + }, + 660: { + evolution: 661, + evolvers: [ 117, 85, 94, 96, 101 ] + }, + 663: { + evolution: 664, + evolvers: [ 117, 81, 87, 98, 103 ] + }, + 665: { + evolution: 666, + evolvers: [ 117, 79, 85, 96, 101 ] + }, + 668: { + evolution: 669, + evolvers: [ 118, 87, 266, 303, 267 ] + }, + 670: { + evolution: 671, + evolvers: [ 118, 83, 86, 302, 102 ] + }, + 672: { + evolution: 673, + evolvers: [ 118, 84, 94, 300, 100 ] + }, + 674: { + evolution: 675, + evolvers: [ 118, 83, 88, 304, 104 ] + }, + 676: { + evolution: 677, + evolvers: [ 94, 96, 96, 301, 301 ] + }, + 678: { + evolution: 679, + evolvers: [ 117, 87, 94, 303, 103 ] + }, + 680: { + evolution: 681, + evolvers: [ 117, 80, 86, 97, 302 ] + }, + 682: { + evolution: 683, + evolvers: [ 117, 81, 87, 98, 303 ] + }, + 684: { + evolution: 685, + evolvers: [ 117, 88, 93, 99, 304 ] + }, + 687: { + evolution: 688, + evolvers: [ 117, 78, 84, 95, 100 ] + }, + 689: { + evolution: 690, + evolvers: [ 117, 82, 88, 99, 104 ] + }, + 691: { + evolution: 696, + evolvers: [ 116, 97, 302 ] + }, + 692: { + evolution: 697, + evolvers: [ 116, 96, 301 ] + }, + 693: { + evolution: 698, + evolvers: [ 116, 98, 303 ] + }, + 694: { + evolution: 699, + evolvers: [ 116, 95, 300 ] + }, + 695: { + evolution: 700, + evolvers: [ 116, 99, 304 ] + }, + 706: { + evolution: 707, + evolvers: [ 117, 84, 89, 95, 100 ] + }, + 708: { + evolution: 709, + evolvers: [ 117, 81, 87, 303, 103 ] + }, + 710: { + evolution: 711, + evolvers: [ 117, 87, 94, 303, 103 ] + }, + 712: { + evolution: 713, + evolvers: [ 117, 90, 96, 301, 101 ] + }, + 715: { + evolution: 716, + evolvers: [ 116, 117, 81, 87 ] + }, + 717: { + evolution: 718, + evolvers: [ 118, 266, 99, 304, 267 ] + }, + 719: { + evolution: 720, + evolvers: [ 118, 86, 266, 102, 267 ] + }, + 721: { + evolution: 722, + evolvers: [ 117, 78, 89, 95 ] + }, + 723: { + evolution: 724, + evolvers: [ 117, 92, 98, 98, 103 ] + }, + 725: { + evolution: 726, + evolvers: [ 117, 79, 85, 96, 101 ] + }, + 728: { + evolution: 729, + evolvers: [ 117, 86, 91, 97, 302 ] + }, + 730: { + evolution: 731, + evolvers: [ 117, 88, 93, 99, 304 ] + }, + 732: { + evolution: 733, + evolvers: [ 116, 84, 95, 300 ] + }, + 734: { + evolution: 735, + evolvers: [ 116, 87, 98, 303 ] + }, + 740: { + evolution: 741, + evolvers: [ 117, 79, 90, 96 ] + }, + 742: { + evolution: 743, + evolvers: [ 117, 80, 86, 91, 97 ] + }, + 744: { + evolution: 745, + evolvers: [ 118, 85, 94, 301, 101 ] + }, + 747: { + evolution: 748, + evolvers: [ 118, 84, 266, 300, 267 ] + }, + 749: { + evolution: 750, + evolvers: [ 118, 83, 86, 302, 102 ] + }, + 751: { + evolution: 752, + evolvers: [ 118, 83, 85, 301, 101 ] + }, + 753: { + evolution: 754, + evolvers: [ 118, 94, 96, 301, 101 ] + }, + 755: { + evolution: 756, + evolvers: [ 118, 83, 88, 304, 104 ] + }, + 757: { + evolution: 758, + evolvers: [ 118, 87, 87, 303, 103 ] + }, + 759: { + evolution: 760, + evolvers: [ 118, 84, 84, 300, 100 ] + }, + 776: { + evolution: 777, + evolvers: [ 116, 117, 81, 87, 103 ] + }, + 778: { + evolution: 779, + evolvers: [ 117, 85, 94, 96, 301 ] + }, + 780: { + evolution: 781, + evolvers: [ 118, 84, 94, 300, 100 ] + }, + 782: { + evolution: 783, + evolvers: [ 117, 93, 94, 304, 104 ] + }, + 784: { + evolution: 785, + evolvers: [ 116, 89, 95 ] + }, + 786: { + evolution: 787, + evolvers: [ 116, 81, 87 ] + }, + 788: { + evolution: 789, + evolvers: [ 116, 80, 86 ] + }, + 790: { + evolution: 791, + evolvers: [ 89, 90, 91 ] + }, + 792: { + evolution: 793, + evolvers: [ 116, 117, 99 ] + }, + 794: { + evolution: 795, + evolvers: [ 118, 88, 266, 304, 104 ] + }, + 796: { + evolution: 797, + evolvers: [ 117, 82, 88, 99, 104 ] + }, + 801: { + evolution: 802, + evolvers: [ 87, 94, 98, 303, 103 ] + }, + 803: { + evolution: 804, + evolvers: [ 117, 80, 86, 302, 102 ] + }, + 805: { + evolution: 806, + evolvers: [ 118, 83, 88, 99, 304 ] + }, + 807: { + evolution: 808, + evolvers: [ 117, 87, 92, 98, 103 ] + }, + 809: { + evolution: [ 810, 810 ], + evolvers: [ [ 116, 78, 84, 89, 95 ], [ 404 ] ] + }, + 815: { + evolution: [ 816, 894 ], + evolvers: [ [ 117, 88, 94, 304, 104 ], [ 118, 88, 94, 99, 104 ] ] + }, + 828: { + evolution: 829, + evolvers: [ 115, 116, 117, 118 ] + }, + 830: { + evolution: 831, + evolvers: [ 118, 86, 94, 302, 102 ] + }, + 832: { + evolution: 833, + evolvers: [ 117, 89, 95, 300, 100 ] + }, + 835: { + evolution: 836, + evolvers: [ 118, 84, 266, 300, 100 ] + }, + 837: { + evolution: 838, + evolvers: [ 83, 86, 97, 302, 102 ] + }, + 839: { + evolution: 840, + evolvers: [ 118, 88, 266, 304, 104 ] + }, + 841: { + evolution: 842, + evolvers: [ 118, 83, 87, 303, 103 ] + }, + 843: { + evolution: 844, + evolvers: [ 118, 84, 95, 300, 100 ] + }, + 845: { + evolution: 846, + evolvers: [ 118, 85, 94, 301, 101 ] + }, + 847: { + evolution: 848, + evolvers: [ 117, 80, 86, 97, 102 ] + }, + 851: { + evolution: 852, + evolvers: [ 117, 78, 85, 95, 101 ] + }, + 855: { + evolution: 856, + evolvers: [ 117, 86, 94, 97, 102 ] + }, + 857: { + evolution: 858, + evolvers: [ 117, 98, 98, 303, 303 ] + }, + 859: { + evolution: 860, + evolvers: [ 117, 87, 98, 98, 303 ] + }, + 861: { + evolution: 862, + evolvers: [ 117, 79, 85, 301, 101 ] + }, + 864: { + evolution: 865, + evolvers: [ 118, 87, 266, 303, 103 ] + }, + 869: { + evolution: 870, + evolvers: [ 118, 85, 266, 301, 267 ] + }, + 871: { + evolution: 872, + evolvers: [ 83, 85, 96, 301, 101 ] + }, + 873: { + evolution: 874, + evolvers: [ 118, 87, 94, 303, 103 ] + }, + 875: { + evolution: 876, + evolvers: [ 118, 88, 99, 304, 104 ] + }, + 877: { + evolution: 878, + evolvers: [ 86, 266, 91, 97, 102 ] + }, + 879: { + evolution: 880, + evolvers: [ 118, 83, 84, 300, 100 ] + }, + 881: { + evolution: 882, + evolvers: [ 118, 85, 94, 301, 101 ] + }, + 883: { + evolution: 884, + evolvers: [ 117, 88, 93, 99, 104 ] + }, + 889: { + evolution: 890, + evolvers: [ 117, 80, 86, 97, 302 ] + }, + 895: { + evolution: 896, + evolvers: [ 117, 86, 91, 97, 102 ] + }, + 900: { + evolution: 901, + evolvers: [ 118, 86, 94, 302, 102 ] + }, + 902: { + evolution: 903, + evolvers: [ 117, 87, 92, 98, 103 ] + }, + 905: { + evolution: 906, + evolvers: [ 118, 83, 84, 300, 100 ] + }, + 907: { + evolution: 908, + evolvers: [ 88, 266, 94, 304, 104 ] + }, + 909: { + evolution: 910, + evolvers: [ 118, 83, 87, 98, 103 ] + }, + 911: { + evolution: 912, + evolvers: [ 118, 86, 266, 97, 102 ] + }, + 913: { + evolution: 914, + evolvers: [ 85, 94, 94, 301, 101 ] + }, + 915: { + evolution: 916, + evolvers: [ 84, 85, 86, 87, 88 ] + }, + 917: { + evolution: 918, + evolvers: [ 117, 79, 85, 96, 101 ] + }, + 921: { + evolution: 922, + evolvers: [ 84 , 85, 86 , 87 , 88] + }, + 923: { + evolution: 924, + evolvers: [ 118 , 83, 84 , 95 , 300] + }, + 925: { + evolution: 926, + evolvers: [ 117 , 85, 90 , 96 , 101] + }, + 928: { + evolution: 929, + evolvers: [ 117, 80, 86, 97, 102 ] + }, + 932: { + evolution: 933, + evolvers: [ 118, 87, 266, 303, 103 ] + }, + 934: { + evolution: 935, + evolvers: [ 118, 88, 266, 304, 267 ] + }, + 936: { + evolution: 937, + evolvers: [ 118, 94, 96, 301, 101 ] + }, + 938: { + evolution: 939, + evolvers: [ 117, 118, 83, 87, 103 ] + }, + 940: { + evolution: 941, + evolvers: [ 94, 97, 97, 302, 102 ] + }, + 942: { + evolution: 943, + evolvers: [ 118, 83, 84, 95, 100 ] + }, + 944: { + evolution: 945, + evolvers: [ 84, 85, 86, 87, 88 ] + }, + 950: { + evolution: 951, + evolvers: [ 118, 83, 87, 98, 303 ] + }, + 952: { + evolution: 953, + evolvers: [ 116, 117, 80, 86, 97 ] + }, + 973: { + evolution: [ 974, 974, 974, 974, 974 ], + evolvers: [ [ 117, 971 ], [ 87, 968], [ 98, 970], [ 87, 969], [ 117, 972] ] + }, + 975: { + evolution: 976, + evolvers: [ 117, 80, 91, 97 ] + }, + 977: { + evolution: 978, + evolvers: [ 118, 85, 266, 301, 101 ] + }, + 982: { + evolution: 983, + evolvers: [ 118, 85, 94, 301, 101 ] + }, + 985: { + evolution: 989, + evolvers: [ 986, 987, 988 ] + }, + 990: { + evolution: 991, + evolvers: [ 99, 304, 304, 104, 104 ] + }, + 992: { + evolution: 993, + evolvers: [ 118, 83, 85, 96, 101 ] + }, + 994: { + evolution: 995, + evolvers: [ 118, 87, 94, 303, 103 ] + }, + 996: { + evolution: 997, + evolvers: [ 80, 86, 266, 302, 102 ] + }, + 998: { + evolution: 999, + evolvers: [ 118, 83, 84, 95, 100 ] + }, + 1000: { + evolution: 1001, + evolvers: [ 118, 86, 266, 302, 267 ] + }, + 1002: { + evolution: 1003, + evolvers: [ 117, 78, 84, 95, 100 ] + }, + 1005: { + evolution: 1006, + evolvers: [ 116, 84, 89, 95, 100 ] + }, + 1007: { + evolution: 1008, + evolvers: [ 117, 85, 87, 96, 98 ] + }, + 1010: { + evolution: 1011, + evolvers: [ 116, 82, 88, 93, 104 ] + }, + 1015: { + evolution: 1016, + evolvers: [ 82, 83, 88, 304, 104 ] + }, + 1017: { + evolution: 1018, + evolvers: [ 117, 81, 87, 98, 103 ] + }, + 1020: { + evolution: 1021, + evolvers: [ 117, 85, 88, 96, 99 ] + }, + 1024: { + evolution: 1025, + evolvers: [ 88, 266, 94, 100, 104 ] + }, + 1026: { + evolution: 1027, + evolvers: [ 85, 96, 301, 301, 101 ] + }, + 1028: { + evolution: 1029, + evolvers: [ 118, 84, 86, 100, 102 ] + }, + 1030: { + evolution: 1031, + evolvers: [ 83, 87, 98, 303, 103 ] + }, + 1032: { + evolution: 1033, + evolvers: [ 118, 84, 87, 300, 303 ] + }, + 1034: { + evolution: 1035, + evolvers: [ 118, 84, 266, 300, 267] + }, + 1036: { + evolution: 1037, + evolvers: [ 117, 79, 85, 96, 101] + }, + 1038: { + evolution: 1039, + evolvers: [ 90, 91, 96, 97 ] + }, + 1040: { + evolution: 1041, + evolvers: [ 118, 83, 84, 95, 300 ] + }, + 1042: { + evolution: 1043, + evolvers: [ 118, 86, 97, 302, 102 ] + }, + 1044: { + evolution: 1045, + evolvers: [ 118, 87, 266, 303, 267 ] + }, + 1046: { + evolution: 1047, + evolvers: [ 118, 86, 266, 302, 102 ] + }, + 1048: { + evolution: 1049, + evolvers: [ 117, 81, 81, 87, 103 ] + }, + 1050: { + evolution: 1051, + evolvers: [ 117, 92, 92, 98, 103 ] + }, + 1053: { + evolution: 1054, + evolvers: [ 117, 79, 90, 96 ] + }, + 1055: { + evolution: 1056, + evolvers: [ 117, 80, 86, 97, 102 ] + }, + 1057: { + evolution: 1058, + evolvers: [ 117, 78, 84, 95, 100 ] + }, + 1059: { + evolution: 1060, + evolvers: [ 116, 92, 98, 303 ] + }, + 1069: { + evolution: 1070, + evolvers: [ 116, 80, 86, 91 ] + }, + 1071: { + evolution: 1072, + evolvers: [ 117, 78, 84, 95, 100 ] + }, + 1074: { + evolution: 1075, + evolvers: [ 118, 94, 99, 304, 104 ] + }, + 1076: { + evolution: 1077, + evolvers: [ 118, 83, 85, 96, 101 ] + }, + 1078: { + evolution: 1079, + evolvers: [ 83, 87, 87, 303, 103 ] + }, + 1080: { + evolution: 1081, + evolvers: [ 86, 266, 97, 302, 102 ] + }, + 1082: { + evolution: 1083, + evolvers: [ 118, 83, 84, 300, 100 ] + }, + 1084: { + evolution: 1085, + evolvers: [ 118, 88, 266, 304, 267 ] + }, + 1086: { + evolution: 1087, + evolvers: [ 117, 88, 99, 304, 104 ] + }, + 1088: { + evolution: 1089, + evolvers: [ 117, 85, 96, 301, 101 ] + }, + 1090: { + evolution: 1091, + evolvers: [ 118, 83, 87, 303, 103 ] + }, + 1092: { + evolution: 1093, + evolvers: [ 115, 116, 117, 81 ] + }, + 1094: { + evolution: 1095, + evolvers: [ 117, 80, 86, 97, 102 ] + }, + 1096: { + evolution: 1097, + evolvers: [ 117, 82, 82, 99, 104] + }, + 1099: { + evolution: 1100, + evolvers: [ 117, 91, 92, 97, 98 ] + }, + 1101: { + evolution: [1102, 1102], + evolvers: [ [118, 266, 300, 100, 104 ], [ 1103, 1105 ]] + }, + 1103: { + evolution: 1104, + evolvers: [ 117, 82, 88, 304, 104 ] + }, + 1105: { + evolution: 1106, + evolvers: [ 117, 80, 86, 97, 302 ] + }, + 1107: { + evolution: 1108, + evolvers: [ 118, 84, 266, 300, 100 ] + }, + 1109: { + evolution: 1110, + evolvers: [ 116, 117, 81, 87, 98 ] + }, + 1111: { + evolution: 1112, + evolvers: [ 117, 79, 85, 96, 101 ] + }, + 1114: { + evolution: 1115, + evolvers: [ 118, 84, 95, 94, 100 ] + }, + 1116: { + evolution: 1117, + evolvers: [ 118, 83, 88, 94, 104 ] + }, + 1118: { + evolution: 1119, + evolvers: [ 118, 85, 96, 301, 101 ] + }, + 1120: { + evolution: 1121, + evolvers: [ 118, 266, 95, 300, 267 ] + }, + 1122: { + evolution: 1123, + evolvers: [ 118, 85, 266, 301, 267 ] + }, + 1124: { + evolution: 1125, + evolvers: [ 118, 83, 87, 98, 303 ] + }, + 1126: { + evolution: 1127, + evolvers: [ 83, 86, 97, 302, 102 ] + }, + 1128: { + evolution: 1129, + evolvers: [ 118, 94, 99, 304, 104 ] + }, + 1130: { + evolution: 1131, + evolvers: [ 84, 94, 95, 300, 100 ] + }, + 1132: { + evolution: 1133, + evolvers: [ 118, 83, 88, 304, 104 ] + }, + 1134: { + evolution: 1135, + evolvers: [ 117, 82, 93, 99 ] + }, + 1140: { + evolution: 1141, + evolvers: [ 118, 83, 86, 88, 102 ] + }, + 1142: { + evolution: 1143, + evolvers: [ 117, 95, 99, 300, 304 ] + }, + 1144: { + evolution: 1145, + evolvers: [ 116, 117, 87, 98 ] + }, + 1156: { + evolution: 1157, + evolvers: [ 117, 81, 87, 92, 98 ] + }, + 1158: { + evolution: 1159, + evolvers: [ 118, 78, 82, 95, 304 ] + }, + 1160: { + evolution: 1161, + evolvers: [ 117, 79, 85, 96, 101 ] + }, + 1162: { + evolution: 1163, + evolvers: [ 118, 1180 ] + }, + 1164: { + evolution: 1165, + evolvers: [ 116, 117, 80, 86 ] + }, + 1166: { + evolution: 1167, + evolvers: [ 117, 88, 99 ] + }, + 1168: { + evolution: 1169, + evolvers: [ 117, 84, 95 ] + }, + 1170: { + evolution: 1171, + evolvers: [ 116, 117, 85 ] + }, + 1172: { + evolution: 1173, + evolvers: [ 118, 92, 94, 98, 303 ] + }, + 1174: { + evolution: 1175, + evolvers: [ 118, 83, 97, 302, 102 ] + }, + 1176: { + evolution: 1177, + evolvers: [ 118, 86, 266, 97, 302 ] + }, + 1178: { + evolution: 1179, + evolvers: [ 118, 84, 95, 300, 100 ] + }, + 1181: { + evolution: 1182, + evolvers: [ 118, 83, 86, 97, 102 ] + }, + 1183: { + evolution: 1184, + evolvers: [ 87, 94, 98, 303, 103 ] + }, + 1185: { + evolution: 1186, + evolvers: [ 118, 88, 99, 99, 104 ] + }, + 1187: { + evolution: 1188, + evolvers: [ 83, 84, 95, 300, 300 ] + }, + 1189: { + evolution: 1190, + evolvers: [ 118, 85, 94, 96, 96 ] + }, + 1191: { + evolution: 1192, + evolvers: [ 118, 266, 301, 101, 267 ] + }, + 1193: { + evolution: 1194, + evolvers: [ 117, 80, 86, 97, 102 ] + }, + 1195: { + evolution: 1196, + evolvers: [ 117, 81, 87, 303, 103 ] + }, + 1198: { + evolution: 1199, + evolvers: [ 117, 78, 84, 95, 300 ] + }, + 1200: { + evolution: 1201, + evolvers: [ 117, 79, 85, 96, 301 ] + }, + 1202: { + evolution: 1203, + evolvers: [ 117, 81, 87, 98, 103 ] + }, + 1204: { + evolution: 1205, + evolvers: [ 116, 117, 90, 96, 101 ] + }, + 1207: { + evolution: 1208, + evolvers: [ 118, 88, 94, 304, 104 ] + }, + 1209: { + evolution: 1210, + evolvers: [ 118, 83, 96, 301, 101 ] + }, + 1211: { + evolution: 1212, + evolvers: [ 118, 83, 84, 300, 100 ] + }, + 1213: { + evolution: 1214, + evolvers: [ 117, 78, 98, 95, 100 ] + }, + 1219: { + evolution: 1220, + evolvers: [ 118, 88, 84, 304, 104 ] + }, + 1221: { + evolution: 1222, + evolvers: [ 83, 84, 89, 95, 300 ] + }, + 1229: { + evolution: 1230, + evolvers: [ 98, 99, 300, 303, 304 ] + }, + 1231: { + evolution: 1232, + evolvers: [ 118, 83, 86, 302, 102 ] + }, + 1233: { + evolution: 1234, + evolvers: [ 118, 83, 85, 301, 101 ] + }, + 1235: { + evolution: 1236, + evolvers: [ 266, 94, 98, 303, 103 ] + }, + 1237: { + evolution: 1238, + evolvers: [ 84, 89, 94, 95, 100 ] + }, + 1239: { + evolution: 1240, + evolvers: [ 118, 266, 98, 303, 267 ] + }, + 1241: { + evolution: 1242, + evolvers: [ 116, 117, 78, 84, 100 ] + }, + 1243: { + evolution: 1244, + evolvers: [ 116, 117, 93, 99, 104 ] + }, + 1246: { + evolution: 1247, + evolvers: [ 118, 84, 94, 95, 100 ] + }, + 1248: { + evolution: 1249, + evolvers: [ 117, 80, 86, 97, 102 ] + }, + 1250: { + evolution: 1251, + evolvers: [ 118, 85, 87, 301, 101 ] + }, + 1257: { + evolution: 1258, + evolvers: [ 118, 87, 266, 98, 267 ] + }, + 1259: { + evolution: 1260, + evolvers: [ 300, 301, 302, 303, 304 ] + }, + 1261: { + evolution: 1262, + evolvers: [ 266, 88, 88, 88, 88 ] + }, + 1263: { + evolution: 1264, + evolvers: [ 96, 99, 101, 104 ] + }, + 1265: { + evolution: 1266, + evolvers: [ 117, 78, 84, 95, 100 ] + }, + 1267: { + evolution: 1268, + evolvers: [ 266, 302, 304, 102, 267 ] + }, + 1269: { + evolution: 1270, + evolvers: [ 83, 86, 94, 97, 302 ] + }, + 1271: { + evolution: 1272, + evolvers: [ 85, 94, 96, 301, 101 ] + }, + 1273: { + evolution: 1274, + evolvers: [ 118, 118, 78, 78, 100 ] + }, + 1275: { + evolution: 1276, + evolvers: [ 118, 88, 99, 304, 104 ] + }, + 1277: { + evolution: 1278, + evolvers: [ 118, 87, 98, 303, 103 ] + }, + 1284: { + evolution: 1285, + evolvers: [ 95, 96, 97, 303, 304 ] + }, + 1286: { + evolution: 1287, + evolvers: [ 116, 117, 81, 98 ] + }, + 1288: { + evolution: 1289, + evolvers: [ 116, 117, 80, 97 ] + }, + 1291: { + evolution: 1292, + evolvers: [ 118, 94, 97, 302, 102 ] + }, + 1293: { + evolution: 1294, + evolvers: [ 117, 80, 81, 86, 87 ] + }, + 1295: { + evolution: 1296, + evolvers: [ 117, 78, 84, 300, 100 ] + }, + 1297: { + evolution: 1298, + evolvers: [ 118, 94, 300, 300, 100 ] + }, + 1299: { + evolution: 1300, + evolvers: [ 116, 117, 82, 88, 104 ] + }, + 1301: { + evolution: 1302, + evolvers: [ 116, 117, 79, 85, 101 ] + }, + 1303: { + evolution: 1304, + evolvers: [ 116, 117, 82, 88, 104 ] + }, + 1305: { + evolution: 1306, + evolvers: [ 116, 117, 80, 86, 102 ] + }, + 1307: { + evolution: 1308, + evolvers: [ 117, 79, 85, 301, 101 ] + }, + 1309: { + evolution: 1310, + evolvers: [ 118, 95, 95, 300, 267 ] + }, + 1311: { + evolution: 1312, + evolvers: [ 117, 78, 82, 84, 88 ] + }, + 1313: { + evolution: 1314, + evolvers: [ 118, 266, 95, 300, 267 ] + }, + 1315: { + evolution: 1316, + evolvers: [ 87, 94, 98, 303, 103 ] + }, + 1317: { + evolution: 1318, + evolvers: [ 118, 84, 94, 300, 100 ] + }, + 1319: { + evolution: 1320, + evolvers: [ 83, 85, 96, 301, 101 ] + }, + 1321: { + evolution: 1322, + evolvers: [ 118, 80, 83, 97, 102 ] + }, + 1323: { + evolution: 1324, + evolvers: [ 88, 266, 99, 304, 104 ] + }, + 1325: { + evolution: 1326, + evolvers: [ 116, 117, 81, 87, 103 ] + }, + 1327: { + evolution: 1328, + evolvers: [ 116, 117, 80, 91, 102 ] + }, + 1331: { + evolution: 1332, + evolvers: [ 116, 117, 81, 92, 103 ] + }, + 1335: { + evolution: 1336, + evolvers: [ 117, 88, 94, 99, 104 ] + }, + 1337: { + evolution: 1338, + evolvers: [ 118, 98, 98, 303, 267 ] + }, + 1340: { + evolution: 1341, + evolvers: [ 79, 85, 90, 94, 301 ] + }, + 1354: { + evolution: 1355, + evolvers: [ 117, 80, 83, 97, 302 ] + }, + 1356: { + evolution: 1357, + evolvers: [ 78, 78, 78, 84, 84 ] + }, + 1358: { + evolution: 1359, + evolvers: [ 82, 82, 82, 88, 88 ] + }, + 1361: { + evolution: 1362, + evolvers: [ 118, 86, 266, 302, 267 ] + }, + 1363: { + evolution: 1364, + evolvers: [ 1180, 87, 266, 98, 103 ] + }, + 1365: { + evolution: 1366, + evolvers: [ 1180, 82, 83, 88, 304 ] + }, + 1367: { + evolution: 1368, + evolvers: [ 1180, 117, 84, 300, 100 ] + }, + 1369: { + evolution: 1370, + evolvers: [ 1180, 85, 94, 301, 101 ] + }, + 1371: { + evolution: 1372, + evolvers: [ 95, 302, 301, 98, 99 ] + }, + 1373: { + evolution: 1374, + evolvers: [ 118, 88, 94, 304, 104 ] + }, + 1375: { + evolution: 1376, + evolvers: [ 118, 79, 83, 96, 301 ] + }, + 1377: { + evolution: 1378, + evolvers: [ 117, 118, 86, 91, 97 ] + }, + 1379: { + evolution: 1380, + evolvers: [ 118, 88, 266, 99, 267 ] + }, + 1381: { + evolution: 1382, + evolvers: [ 95, 96, 97, 303, 304 ] + }, + 1383: { + evolution: 1384, + evolvers: [ 117, 79, 85, 96, 101 ] + }, + 1385: { + evolution: 1386, + evolvers: [ 116, 117, 81, 98 ] + }, + 4: { + evolution: 1387, + evolvers: [ 'skullLuffy', 267 ] + }, + 8: { + evolution: 1388, + evolvers: [ 'skullZoro', 267 ] + }, + 12: { + evolution: 1389, + evolvers: [ 'skullNami', 267 ] + }, + 1390: { + evolution: 1391, + evolvers: [ 118, 88, 99, 304, 267 ] + }, + 1394: { + evolution: 1395, + evolvers: [ 117, 118, 84, 85 ] + }, + 1396: { + evolution: 1397, + evolvers: [ 117, 80, 91, 97, 102 ] + }, + 1398: { + evolution: 1399, + evolvers: [ 117, 79, 90, 96, 101 ] + }, + 1400: { + evolution: 1401, + evolvers: [ 118, 78, 83, 95, 300 ] + }, + 1403: { + evolution: 1404, + evolvers: [ 118, 85, 266, 301, 267 ] + }, + 1405: { + evolution: 1406, + evolvers: [ 1180, 87, 98, 303, 103 ] + }, + 1407: { + evolution: 1408, + evolvers: [ 1180, 117, 94, 302, 303 ] + }, + 1409: { + evolution: 1410, + evolvers: [ 1180, 83, 88, 304, 104 ] + }, + 1411: { + evolution: 1412, + evolvers: [ 1180, 118, 89, 95, 100 ] + }, + 261: { + evolution: 1413, + evolvers: [ 'skullSTR', 118, 84, 300, 267 ] + }, + 1415: { + evolution: 1416, + evolvers: [ 116, 117, 92, 98, 103 ] + }, + 1419: { + evolution: 1420, + evolvers: [ 84, 88, 300, 304, 104 ] + }, + 1421: { + evolution: 1422, + evolvers: [ 118, 94, 99, 304, 267 ] + }, + 1425: { + evolution: 1426, + evolvers: [ 117, 79, 85, 96, 101 ] + }, + 1429: { + evolution: 1430, + evolvers: [ 117, 83, 86, 91, 97 ] + }, + 1431: { + evolution: 1432, + evolvers: [ 118, 266, 300, 301, 302 ] + }, + 1433: { + evolution: 1434, + evolvers: [ 118, 266, 267, 99, 304 ] + }, + 1435: { + evolution: 1436, + evolvers: [ 118, 96, 1180, 101, 301 ] + }, + 1437: { + evolution: 1438, + evolvers: [ 87, 1180, 94, 103, 303 ] + }, + 1439: { + evolution: 1440, + evolvers: [ 118, 83, 86, 102, 302 ] + }, + 1441: { + evolution: 1442, + evolvers: [ 266, 93, 104, 104, 304 ] + }, + 1443: { + evolution: 1444, + evolvers: [ 95, 95, 1180, 300, 300 ] + }, + 416: { + evolution: 1445, + evolvers: [ 'skullQCK', 118, 85, 301, 267 ] + }, + 16: { + evolution: 1446, + evolvers: [ 'skullUsopp', 267 ] + }, + 20: { + evolution: 1447, + evolvers: [ 'skullSanji', 267 ] + }, + 22: { + evolution: 1448, + evolvers: [ 'skullChopper', 267 ] + }, + 1449: { + evolution: 1450, + evolvers: [ 116, 80, 86, 91, 102 ] + }, + 1451: { + evolution: 1452, + evolvers: [ 117, 80, 91, 97, 102 ] + }, + 1453: { + evolution: 1454, + evolvers: [ 117, 83, 84, 89, 95 ] + }, + 1455: { + evolution: 1456, + evolvers: [ 118, 266, 98, 303, 103 ] + }, + 1457: { + evolution: 1458, + evolvers: [ 83, 85, 88, 96, 99 ] + }, + 1459: { + evolution: 1460, + evolvers: [ 117, 78, 89, 95 ] + }, + 1462: { + evolution: 1463, + evolvers: [ 116, 117, 81, 87, 98 ] + }, + 1464: { + evolution: 1465, + evolvers: [ 116, 117, 82, 88, 99 ] + }, + 1466: { + evolution: 1467, + evolvers: [ 117, 85, 87, 96, 98 ] + }, + 1468: { + evolution: 1469, + evolvers: [ 117, 78, 84, 89, 100 ] + }, + 1472: { + evolution: 1473, + evolvers: [ 118, 266, 98, 267, 303 ] + }, + 1474: { + evolution: 1475, + evolvers: [ 118, 84, 95, 1180, 100 ] + }, + 1476: { + evolution: 1477, + evolvers: [ 116, 87, 266, 1180, 303 ] + }, + 1478: { + evolution: 1479, + evolvers: [ 83, 85, 94, 101, 301 ] + }, + 1480: { + evolution: 1481, + evolvers: [ 118, 86, 94, 102, 302 ] + }, + 1482: { + evolution: 1483, + evolvers: [ 88, 99, 1180, 104, 304 ] + }, + 1484: { + evolution: 1485, + evolvers: [ 95, 96, 97, 300, 100 ] + }, + 1486: { + evolution: 1487, + evolvers: [ 118, 266, 97, 302, 102 ] + }, + 1488: { + evolution: 1489, + evolvers: [ 84, 89, 94, 95, 300 ] + }, + 1490: { + evolution: 1491, + evolvers: [ 117, 79, 90, 96 ] + }, + 669: { + evolution: 1492, + evolvers: [ 'skullPSY', 118, 87, 303, 267 ] + }, + 1505: { + evolution: [ 1506, 1562 ], + evolvers: [[ 118, 95, 99, 300, 304 ], [ 118, 83, 85, 96, 101 ] ] + }, + 1507: { + evolution: 1508, + evolvers: [ 116, 117, 79, 85, 96 ] + }, + 1513: { + evolution: 1514, + evolvers: [ 116, 117, 84, 85, 86 ] + }, + 1515: { + evolution: 1516, + evolvers: [ 116, 117, 78, 84, 95 ] + }, + 1517: { + evolution: 1518, + evolvers: [ 118, 79, 85, 94, 96 ] + }, + 1519: { + evolution: 1520, + evolvers: [ 117, 81, 81, 98, 103 ] + }, + 1523: { + evolution: 1524, + evolvers: [ 115, 115, 116, 117, 118 ] + }, + 1526: { + evolution: 1527, + evolvers: [ 88, 89, 94, 95, 304 ] + }, + 1529: { + evolution: 1530, + evolvers: [ 118, 85, 266, 96, 267 ] + }, + 1531: { + evolution: 1532, + evolvers: [ 118, 86, 266, 302, 267 ] + }, + 1533: { + evolution: 1534, + evolvers: [ 118, 85, 266, 301, 101 ] + }, + 1535: { + evolution: 1536, + evolvers: [ 94, 98, 1180, 303, 103 ] + }, + 1537: { + evolution: 1538, + evolvers: [ 95, 96, 97, 300, 100 ] + }, + 1539: { + evolution: 1540, + evolvers: [ 83, 88, 99, 304, 104 ] + }, + 1541: { + evolution: 1542, + evolvers: [ 115, 116, 117, 118, 94 ] + }, + 1532: { + evolution: 1543, + evolvers: [ 'skullDEX', 118, 86, 302, 267 ] + }, + 1544: { + evolution: 1545, + evolvers: [ 116, 117, 82, 88, 104 ] + }, + 1546: { + evolution: 1547, + evolvers: [ 117, 79, 85, 96, 101 ] + }, + 709: { + evolution: 1549, + evolvers: [ 'skullRobin', 267 ] + }, + 739: { + evolution: 1550, + evolvers: [ 'skullFranky', 267 ] + }, + 896: { + evolution: 1551, + evolvers: [ 'skullBrook', 267 ] + }, + 1552: { + evolution: 1553, + evolvers: [ 118, 94, 95, 300, 100 ] + }, + 1554: { + evolution: 1555, + evolvers: [ 117, 80, 86, 97, 302 ] + }, + 1563: { + evolution: 1564, + evolvers: [ 117, 78, 84, 95, 100 ] + }, + 1565: { + evolution: 1566, + evolvers: [ 117, 80, 86, 97, 102 ] + }, + 1567: { + evolution: 1568, + evolvers: [ 117, 118, 79, 101 ] + }, + 1570: { + evolution: 1571, + evolvers: [ 118, 84, 266, 100, 267 ] + }, + 1572: { + evolution: 1573, + evolvers: [ 85, 96, 1180, 301, 101 ] + }, + 1574: { + evolution: 1575, + evolvers: [ 83, 88, 94, 99, 304 ] + }, + 1576: { + evolution: 1577, + evolvers: [ 118, 86, 97, 1180, 102 ] + }, + 1578: { + evolution: 1579, + evolvers: [ 115, 116, 117, 118, 103 ] + }, + 1580: { + evolution: 1581, + evolvers: [ 117, 80, 86, 97, 102 ] + }, + 1583: { + evolution: 1584, + evolvers: [ 118, 98, 98, 303, 103 ] + }, + 1585: { + evolution: 1586, + evolvers: [ 117, 79, 85, 96, 301 ] + }, + 1404: { + evolution: 1593, + evolvers: [ 'skullQCK', 'skullPSY', 98, 303, 267 ] + }, + 1587: { + evolution: 1588, + evolvers: [ 118, 88, 266, 304, 267 ] + }, + 1589: { + evolution: 1590, + evolvers: [ 83, 85, 1180, 101, 301 ] + }, + 1591: { + evolution: 1592, + evolvers: [ 118, 88, 94, 104, 304 ] + }, + 1594: { + evolution: 1595, + evolvers: [ 118, 83, 87, 303, 103 ] + }, + 1596: { + evolution: 1597, + evolvers: [ 117, 82, 88, 99, 104 ] + }, + 1601: { + evolution: 1602, + evolvers: [ 118, 99, 99, 304, 104 ] + }, + 1604: { + evolution: 1605, + evolvers: [ 117, 78, 89, 95 ] + }, + 1609: { + evolution: 1610, + evolvers: [ 118, 266, 96, 301, 267 ] + }, + 1611: { + evolution: 1612, + evolvers: [ 87, 98, 1180, 303, 103 ] + }, + 1613: { + evolution: 1614, + evolvers: [ 83, 86, 94, 102, 302 ] + }, + 1615: { + evolution: 1616, + evolvers: [ 118, 82, 88, 266, 304 ] + }, + 1617: { + evolution: 1618, + evolvers: [ 83, 84, 95, 1180, 100 ] + }, + 367: { + evolution: 1619, + evolvers: [ 'skullINT', 118, 304, 99, 267 ] + }, + 1620: { + evolution: 1621, + evolvers: [ 118, 84, 266, 95, 300 ] + }, + 1622: { + evolution: 1623, + evolvers: [ 118, 83, 88, 304, 104 ] + }, + 1627: { + evolution: 1628, + evolvers: [ 118, 97, 97, 302, 102 ] + }, + 1629: { + evolution: 1630, + evolvers: [ 117, 82, 88, 99, 304 ] + }, + 1631: { + evolution: 1632, + evolvers: [ 118, 87, 266, 98, 303 ] + }, + 1636: { + evolution: [ 1637, 1716 ], + evolvers: [ [ 118, 96, 97, 301, 302 ], [ 118, 83, 84, 95, 100 ] ] + }, + 1646: { + evolution: 1647, + evolvers: [ 118, 84, 266, 300, 100 ] + }, + 1648: { + evolution: 1649, + evolvers: [ 117, 78, 84, 95, 100 ] + }, + 1651: { + evolution: 1652, + evolvers: [ 118, 266, 98, 303, 267 ] + }, + 1653: { + evolution: 1654, + evolvers: [ 88, 99, 1180, 304, 104 ] + }, + 1655: { + evolution: 1656, + evolvers: [ 83, 85, 94, 301, 101 ] + }, + 1657: { + evolution: 1658, + evolvers: [ 118, 80, 86, 266, 102 ] + }, + 1659: { + evolution: 1660, + evolvers: [ 83, 84, 95, 1180, 100 ] + }, + 1661: { + evolution: 1662, + evolvers: [ 118, 85, 1180, 301, 101 ] + }, + 748: { + evolution: 1663, + evolvers: [ 'skullSTR', 118, 95, 300, 267 ] + }, + 1664: { + evolution: 1665, + evolvers: [ 118, 84, 94, 300, 100 ] + }, + 1666: { + evolution: 1667, + evolvers: [ 118, 96, 96, 301, 101 ] + }, + 1668: { + evolution: 1669, + evolvers: [ 118, 86, 266, 302, 102 ] + }, + 1673: { + evolution: 1674, + evolvers: [ 115, 115, 90, 96, 301 ] + }, + 1675: { + evolution: 1676, + evolvers: [ 81, 81, 87, 92, 98 ] + }, + 1677: { + evolution: 1678, + evolvers: [ 118, 88, 99, 304, 104 ] + }, + 1679: { + evolution: 1680, + evolvers: [ 118, 83, 85, 85, 101 ] + }, + 1681: { + evolution: 1682, + evolvers: [ 78, 84, 89, 95, 100 ] + }, + 1683: { + evolution: 1684, + evolvers: [ 79, 85, 90, 96, 101 ] + }, + 1685: { + evolution: 1686, + evolvers: [ 82, 88, 93, 99, 104 ] + }, + 1687: { + evolution: 1688, + evolvers: [ 80, 86, 91, 97, 102 ] + }, + 1689: { + evolution: 1690, + evolvers: [ 117, 82, 88, 99, 304 ] + }, + 1693: { + evolution: 1694, + evolvers: [ 118, 98, 1180, 303, 103 ] + }, + 1695: { + evolution: 1696, + evolvers: [ 118, 86, 266, 302, 102 ] + }, + 1697: { + evolution: 1698, + evolvers: [ 118, 86, 1180, 302, 267 ] + }, + 1699: { + evolution: 1700, + evolvers: [ 87, 94, 98, 303, 103 ] + }, + 1701: { + evolution: 1702, + evolvers: [ 118, 83, 85, 96, 101 ] + }, + 1703: { + evolution: 1704, + evolvers: [ 266, 93, 1180, 304, 104 ] + }, + 1705: { + evolution: 1706, + evolvers: [ 83, 84, 95, 1180, 100 ] + }, + 530: { + evolution: 1707, + evolvers: [ 'skullPSY', 118, 98, 303, 267 ] + }, + 1708: { + evolution: 1709, + evolvers: [ 116, 117, 79, 85, 96 ] + }, + 1710: { + evolution: 1711, + evolvers: [ 116, 117, 81, 87, 98 ] + }, + 1712: { + evolution: 1713, + evolvers: [ 118, 86, 97, 302, 102 ] + }, + 1720: { + evolution: 1721, + evolvers: [ 118, 85, 96, 301, 101 ] + }, + 1722: { + evolution: 1723, + evolvers: [ 117, 81, 87, 98, 103 ] + }, + 1724: { + evolution: 1725, + evolvers: [ 117, 79, 85, 96, 101 ] + }, + 1726: { + evolution: 1727, + evolvers: [ 118, 87, 266, 303, 103 ] + }, + 1728: { + evolution: 1729, + evolvers: [ 116, 117, 78, 84, 95 ] + }, + 1730: { + evolution: 1731, + evolvers: [ 115, 115, 93, 99, 304 ] + }, + 1732: { + evolution: 1733, + evolvers: [ 118, 95, 1180, 300, 100 ] + }, + 1734: { + evolution: 1735, + evolvers: [ 117, 78, 84, 95, 100 ] + }, + 1736: { + evolution: 1737, + evolvers: [ 117, 82, 88, 99, 104 ] + }, + 1738: { + evolution: 1739, + evolvers: [ 118, 78, 84, 94, 95 ] + }, + 1740: { + evolution: 1741, + evolvers: [ 117, 86, 1180, 302, 102 ] + }, + 1742: { + evolution: 1743, + evolvers: [ 117, 84, 1180, 300, 100 ] + }, + 1744: { + evolution: 1745, + evolvers: [ 83, 88, 94, 99, 104 ] + }, + 1746: { + evolution: 1747, + evolvers: [ 118, 266, 94, 98, 267 ] + }, + 1748: { + evolution: 1749, + evolvers: [ 83, 85, 94, 96, 101 ] + }, + 1750: { + evolution: 1751, + evolvers: [ 118, 85, 266, 301, 267 ] + }, + 1752: { + evolution: 1753, + evolvers: [ 82, 88, 93, 99, 104 ] + }, + 1754: { + evolution: 1755, + evolvers: [ 81, 87, 92, 98, 103 ] + }, + 1756: { + evolution: 1757, + evolvers: [ 78, 84, 89, 95, 100 ] + }, + 1758: { + evolution: 1759, + evolvers: [ 79, 85, 90, 96, 101 ] + }, + 1760: { + evolution: 1761, + evolvers: [ 80, 86, 91, 97, 102 ] + }, + 1762: { + evolution: 1763, + evolvers: [ 118, 79, 1180, 301, 267 ] + }, + 1192: { + evolution: 1764, + evolvers: [ 'skullQCK', 118, 85, 301, 267 ] + }, + 1765: { + evolution: 1766, + evolvers: [ 117, 80, 86, 97, 102 ] + }, + 1769: { + evolution: 1770, + evolvers: [ 118, 88, 99, 304, 104 ] + }, + 1771: { + evolution: 1772, + evolvers: [ 118, 88, 266, 304, 104 ] + }, + 1773: { + evolution: 1774, + evolvers: [ 117, 82, 88, 99, 104 ] + }, + 1775: { + evolution: 1776, + evolvers: [ 117, 79, 85, 96, 101 ] + }, + 1777: { + evolution: 1778, + evolvers: [ 118, 85, 96, 301, 101 ] + }, + 1779: { + evolution: 1780, + evolvers: [ 118, 86, 266, 302, 102 ] + }, + 1791: { + evolution: 1792, + evolvers: [ 118, 86, 1180, 302, 102 ] + }, + 1793: { + evolution: 1794, + evolvers: [ 118, 100, 101, 102, 267 ] + }, + 1795: { + evolution: 1796, + evolvers: [ 85, 96, 1180, 301, 101 ] + }, + 1797: { + evolution: 1798, + evolvers: [ 83, 94, 97, 302, 102 ] + }, + 1799: { + evolution: 1800, + evolvers: [ 118, 86, 97, 302, 102 ] + }, + 1801: { + evolution: 1802, + evolvers: [ 85, 266, 96, 301, 101 ] + }, + 1803: { + evolution: 1804, + evolvers: [ 117, 80, 91, 97, 102 ] + }, + 1805: { + evolution: 1806, + evolvers: [ 117, 79, 90, 96, 101 ] + }, + 1807: { + evolution: 1808, + evolvers: [ 115, 116, 117, 118, 100 ] + }, + 1809: { + evolution: 1810, + evolvers: [ 117, 81, 87, 98, 103 ] + }, + 1811: { + evolution: 1812, + evolvers: [ 117, 80, 86, 97, 102 ] + }, + 1814: { + evolution: 1815, + evolvers: [ 118, 95, 1180, 300, 100 ] + }, + 562: { + evolution: 1816, + evolvers: [ 'skullDEX', 118, 86, 302, 267 ] + }, + 1817: { + evolution: 1818, + evolvers: [ 117, 82, 88, 99, 104 ] + }, + 1821: { + evolution: 1822, + evolvers: [ 78, 84, 89, 95, 100 ] + }, + 1823: { + evolution: 1824, + evolvers: [ 118, 84, 95, 300, 100 ] + }, + 1825: { + evolution: 1826, + evolvers: [ 118, 94, 304, 304, 104 ] + }, + 1827: { + evolution: 1828, + evolvers: [ 118, 99, 1180, 304, 104 ] + }, + 1829: { + evolution: 1830, + evolvers: [ 118, 88, 266, 304, 104 ], + }, + 1831: { + evolution: 1832, + evolvers: [ ], + }, + 1833: { + evolution: 1834, + evolvers: [ ], + }, + 1835: { + evolution: 1836, + evolvers: [ 83, 94, 95, 300, 100 ], + }, + 1837: { + evolution: 1838, + evolvers: [ 118, 85, 96, 301, 101 ], + }, + 1839: { + evolution: 1840, + evolvers: [ 86, 266, 97, 302, 102 ], + }, + 1841: { + evolution: 1842, + evolvers: [ 117, 80, 86, 97, 102 ], + }, + 1843: { + evolution: 1844, + evolvers: [ 117, 78, 84, 95, 100 ], + }, + 1845: { + evolution: 1846, + evolvers: [ 118, 84, 266, 95, 267 ], + }, + 459: { + evolution: 1847, + evolvers: [ 'skullINT', 118, 88, 304, 267 ], + }, + 1848: { + evolution: 1849, + evolvers: [ 117, 78, 89, 95, 100 ], + }, + 1850: { + evolution: 1851, + evolvers: [ 117, 80, 91, 97, 102 ], + }, + 1852: { + evolution: 1853, + evolvers: [ 115, 116, 117, 118, 104 ], + }, + 1854: { + evolution: 1855, + evolvers: [ 78, 84, 89, 95, 100 ], + }, + 1856: { + evolution: 1857, + evolvers: [ 81, 87, 92, 98, 103 ], + }, + 1858: { + evolution: 1859, + evolvers: [ ], + }, + 1860: { + evolution: 1861, + evolvers: [ ], + }, + 1862: { + evolution: 1863, + evolvers: [ ], + }, + 2000: { + evolution: 2001, + evolvers: [ 118, 84, 266, 300, 100 ] + }, +}; diff --git a/common/data/families.js b/common/data/families.js index 05a1e1930..325f46535 100644 --- a/common/data/families.js +++ b/common/data/families.js @@ -1,922 +1,2003 @@ window.families = [ - "Monkey D. Luffy", - "Monkey D. Luffy", - "Monkey D. Luffy", - "Monkey D. Luffy", - "Roronoa Zoro", - "Roronoa Zoro", - "Roronoa Zoro", - "Roronoa Zoro", - "Nami", - "Nami", - "Nami", - "Nami", - "Usopp", - "Usopp", - "Usopp", - "Usopp", - "Sanji", - "Sanji", - "Sanji", - "Sanji", - "Tony Tony Chopper", - "Tony Tony Chopper", - "Tony Tony Chopper", - "Tony Tony Chopper", - "Tony Tony Chopper", - "Tony Tony Chopper", - "Higuma", - "Master of the Near Sea", - "Alvida", - "Alvida", - "Coby", - "Coby", - "Helmeppo", - "Helmeppo", - "Morgan", - "Mohji & Richie", - "Cabaji", - "Buggy", - "Buggy", - "Gaimon", - "Siam", - "Butchie", - "Django", - "Django", - "Kuro", - "Kuro", - "Yosaku", - "Johnny", - "Fullbody", - "Patty", - "Carne", - "Zeff", - "Gin", - "Gin", - "Pearl", - "Pearl", - "Don Krieg", - "Don Krieg", - "Nezumi", - "Momoo", - "Choo", - "Kuroobi", - "Hachi", - "Hachi", - "Arlong", - "Arlong", - "Tashigi", - "Tashigi", - "Smoker", - "Smoker", - "Nefertari Vivi", - "Nefertari Vivi", - "Nefertari Vivi", - "Portgas D. Ace", - "Portgas D. Ace", - "Shanks", - "Shanks", - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - "Sword Bandit", - "Pistol Bandit", - "Fighter Group Crew Pirates", - "Fighter Group Crew Pirates", - "Fighter Group Crew Pirates", - "Fighter Group Crew Pirates", - "Fighter Group Crew Pirates", - "Slasher Group Crew Pirates", - "Slasher Group Crew Pirates", - "Slasher Group Crew Pirates", - "Slasher Group Crew Pirates", - "Slasher Group Crew Pirates", - "Striker Group Crew Pirates", - "Striker Group Crew Pirates", - "Striker Group Crew Pirates", - "Striker Group Crew Pirates", - "Striker Group Crew Pirates", - "Shooter Group Crew Pirates", - "Shooter Group Crew Pirates", - "Shooter Group Crew Pirates", - "Shooter Group Crew Pirates", - "Shooter Group Crew Pirates", - "Cannoneer", - "Fighter Group Crew Pirates", - "Fighter Group Crew Pirates", - "Fighter Group Crew Pirates", - "Fighter Group Crew Pirates", - "Fighter Group Crew Pirates", - "Slasher Group Crew Pirates", - "Slasher Group Crew Pirates", - "Slasher Group Crew Pirates", - "Slasher Group Crew Pirates", - "Slasher Group Crew Pirates", - "Striker Group Crew Pirates", - "Striker Group Crew Pirates", - "Striker Group Crew Pirates", - "Striker Group Crew Pirates", - "Striker Group Crew Pirates", - "Shooter Group Crew Pirates", - "Shooter Group Crew Pirates", - "Shooter Group Crew Pirates", - "Shooter Group Crew Pirates", - "Shooter Group Crew Pirates", - "Cannoneer", - "Bodyguard", - "Bodyguard", - "Black Cat Pirates", - "Black Cat Pirates", - "Black Cat Pirates", - "Black Cat Pirates", - "Black Cat Pirates", - "Fighter Group Leader", - "Slasher Group Leader", - "Striker Group Leader", - "Shooter Group Leader", - "Assassin Master", - "Arlong Crewmember", - "Arlong Crewmember", - "Arlong Crewmember", - "Arlong Crewmember", - "Knuckle Navy", - "Saber Navy", - "Halberd Navy", - "Pistol Navy", - "Cannoneer Navy", - "Knuckle Navy", - "Saber Navy", - "Halberd Navy", - "Pistol Navy", - "Cannoneer Navy", - null, - null, - null, - null, - null, - "Knuckle Navy", - "Saber Navy", - "Halberd Navy", - "Pistol Navy", - "Cannoneer Navy", - "Mr. 5", - "Mr. 5", - "Miss Valentine", - "Miss Valentine", - "Galdino", - "Galdino", - "Miss Goldenweek", - "Miss Goldenweek", - "Bentham", - "Bentham", - "Nico Robin", - "Nico Robin", - "Mr. 9", - "Mr. 9", - "Laboon", - "Laboon", - "Neptunian Squid", - "Monkey D. Luffy", - "Monkey D. Luffy", - "Roronoa Zoro", - "Roronoa Zoro", - "Nami", - "Nami", - "Usopp", - "Usopp", - "Sanji", - "Sanji", - "Dracule Mihawk", - "Dracule Mihawk", - "Morgan", - "Django", - "Fullbody", - "Hina", - "Hina", - "Mr. 8", - "Mr. 8", - "Misss Monday", - "Misss Monday", - "Knuckle Baroque Works", - "Saber Baroque Works", - "Halberd Baroque Works", - "Pistol Baroque Works", - "Bazooka Baroque Works", - "Knuckle Baroque Works", - "Saber Baroque Works", - "Halberd Baroque Works", - "Pistol Baroque Works", - "Bazooka Baroque Works", - "Tony Tony Chopper", - "Tony Tony Chopper", - "Tony Tony Chopper", - "Marco", - "Marco", - "Jozu", - "Jozu", - "Vista", - "Vista", - "Izo", - "Izo", - "Blamenco", - "Blamenco", - "Whitebeard", - "Whitebeard", - "Coby", - "Coby", - "Helmeppo", - "Helmeppo", - null, - null, - "Smoker", - "Fighter Group Crew Pirates", - "Fighter Group Crew Pirates", - "Fighter Group Crew Pirates", - "Fighter Group Crew Pirates", - "Fighter Group Crew Pirates", - "Slasher Group Crew Pirates", - "Slasher Group Crew Pirates", - "Slasher Group Crew Pirates", - "Slasher Group Crew Pirates", - "Slasher Group Crew Pirates", - "Striker Group Crew Pirates", - "Striker Group Crew Pirates", - "Striker Group Crew Pirates", - "Striker Group Crew Pirates", - "Striker Group Crew Pirates", - "Shooter Group Crew Pirates", - "Shooter Group Crew Pirates", - "Shooter Group Crew Pirates", - "Shooter Group Crew Pirates", - "Shooter Group Crew Pirates", - "Cannoneer", - "Mr. 13", - "Dorry", - "Broggy", - "Triceratops", - "Rex", - "Brontosaurus", - "Tsuru", - "Tsuru", - "Momonga", - "Onigumo", - null, - null, - null, - null, - null, - "Monkey D. Garp", - "Monkey D. Garp", - "Trafalgar Law", - "Trafalgar Law", - "Basil Hawkins", - "Basil Hawkins", - "Killer", - "Killer", - "Urouge", - "Urouge", - "Bepo", - "Bepo", - "Kalifa", - "Kalifa", - "Paulie", - "Paulie", - "Rob Lucci", - "Rob Lucci", - "Kaku", - "Kaku", - "Lulu", - "Wapol", - "Wapol", - "Dalton", - "Dalton", - "Chessmarimo", - "Chessmarimo", - "Chessmarimo", - "Dr. Kureha", - "Lapin", - "Lapin", - "Franky", - "Franky", - "Kiwi & Mozu", - "Kiwi & Mozu", - "Surume", - "Surume", - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - "Zephyr", - "Zephyr", - "Ain", - "Ain", - "Eustass Kid", - "Eustass Kid", - "Scratchmen Apoo", - "Scratchmen Apoo", - "X Drake", - "X Drake", - "Jewelry Bonney", - "Jewelry Bonney", - "Capone Bege", - "Capone Bege", - "Silvers Rayleigh", - "Silvers Rayleigh", - "Giant Red Pirates", - "Giant Blue Pirates", - "Giant Green Pirates", - "Giant Yellow Pirates", - "Giant Black Pirates", - "Giant Red Pirates", - "Giant Blue Pirates", - "Giant Green Pirates", - "Giant Yellow Pirates", - "Giant Black Pirates", - "Sea Cat", - "Dugong", - "Dugong", - "Banana Gator", - "Sandora Dragon", - "Crocodile", - "Crocodile", - "Hogback", - "Hogback", - "Cindry", - "Cindry", - "Emporio Ivankov", - "Emporio Ivankov", - "Perona", - "Perona", - "Kumacy", - "Dog Penguin", - "Miss Merry Christmas", - "Miss Merry Christmas", - "Mr. 4", - "Mr. 4", - "Miss Doublefinger", - "Miss Doublefinger", - "Daz Bones", - "Daz Bones", - "Rebecca", - "Absalom", - "Absalom", - "General Zombie", - "Jigoro of the Wind", - "Crocodile", - "Jimbe", - "Jimbe", - "Bartholomew Kuma", - "Bartholomew Kuma", - "Gecko Moria", - "Gecko Moria", - "Boa Hancock", - "Boa Hancock", - "Donquixote Doflamingo", - "Donquixote Doflamingo", - "Sanji", - "Monkey D. Luffy", - "Roronoa Zoro", - "Nami", - "Brook", - "Brook", - "Ryuuma", - "Masira", - "Shoujou", - "Montblanc Cricket", - "South Bird and Forest Residents", - "Bellamy", - "Bellamy", - "Sarquiss", - "Elizabeth", - "Caroline", - "Sanji", - "Sanji", - "Perona", - "Perona", - "Nefertari Vivi", - "Nefertari Vivi", - "Duck Squadron", - "Duck Squadron", - "Duck Squadron", - "Duck Squadron", - "Duck Squadron", - "Blackbeard", - "Blackbeard", - "Thatch", - "Thatch", - "Namule", - "Namule", - "Rakuyo", - "Rakuyo", - "Fossa", - "Fossa", - "Curiel", - "Curiel", - "Sengoku", - "Sengoku", - "Galdino", - "Bentham", - "Bentham", - "Satori", - "Shura", - "Gedatsu", - "Braham", - "Yama", - "Yellow Skypiea Guard", - "Black Skypiea Guard", - "Yellow Skypiea Guard", - "Black Skypiea Guard", - "Red Skypiea Guard Enforcer", - "Blue Skypiea Guard Enforcer", - "Green Skypiea Guard Enforcer", - "Yellow Skypiea Guard Enforcer", - "Black Skypiea Guard Enforcer", - "Red Skypiea Enforcer", - "Blue Skypiea Enforcer", - "Green Skypiea Enforcer", - "Yellow Skypiea Enforcer", - "Black Skypiea Enforcer", - "Red Skypiea Enforcer", - "Blue Skypiea Enforcer", - "Green Skypiea Enforcer", - "Yellow Skypiea Enforcer", - "Black Skypiea Enforcer", - "Red Shandian Warrior", - "Blue Shandian Warrior", - "Green Shandian Warrior", - "Red Shandian Warrior", - "Blue Shandian Warrior", - "Green Shandian Warrior", - "Yellow Shandian Warrior", - "Black Shandian Warrior", - "Yellow Shandian Warrior", - "Black Shandian Warrior", - "Portgas D. Ace", - "Portgas D. Ace", - "Bellmere", - "Bellmere", - "Kaya", - "Kaya", - "Hotori and Kotori", - "Hotori and Kotori", - "Pell", - "Pell", - "Chaka", - "Chaka", - "Crocodile", - "Crocodile", - "Daz Bones", - "Sabo", - "Sabo", - "Nico Robin", - "Heracles'n", - "Heracles'n", - "Usopp", - "Usopp", - "Monkey D. Luffy", - "Monkey D. Luffy", - "Sanji", - "Sanji", - "Nami", - "Nami", - "Brook", - "Brook", - "Tony Tony Chopper", - "Tony Tony Chopper", - "Shanks", - "Shanks", - "Nico Robin", - "Nico Robin", - "Brook", - "Brook", - "Nami", - "Nami", - "Domino", - "Domino", - "Minorhinoceros", - "Basilisk", - "Ohm", - "Nola Giant Snake", - "Wyper", - "Wyper", - "Eneru", - "Eneru", - "Monkey D. Luffy", - "Monkey D. Luffy", - "Sadi-chan", - "Sadi-chan", - "Minokoala", - "Manticore", - "Roronoa Zoro", - "Roronoa Zoro", - "Usopp", - "Usopp", - "Nico Robin", - "Nico Robin", - "Franky", - "Franky", - "Portgas D. Ace", - "Portgas D. Ace", - "Porche", - "Capote", - "Hamburg", - "Pickles", - "Big Bun", - "Foxy", - "Foxy", - "Monkey D. Luffy", - "Monkey D. Luffy", - "Usopp", - "Tony Tony Chopper", - "Aokiji", - "Aokiji", - "Nami", - "Monkey D. Luffy", - "Monkey D. Luffy", - "Roronoa Zoro", - "Roronoa Zoro", - "Genbou", - "Kamakiri", - "Raki", - "Aisa", - "Nojiko", - "Nojiko", - "Crocus", - "Crocus", - "Koza", - "Koza", - null, - null, - null, - null, - null, - "Tony Tony Chopper", - "Tony Tony Chopper", - "Buggy", - "Buggy", - "Shanks", - "Shanks", - "Eneru", - "Eneru", - "Sanji", - "Sanji", - "Zeff", - "Zeff", - "Patty", - "Carne", - "Hiking Bear", - "Purinpurin", - "Brook", - "Brook", - "Zanbai", - "Superhuman Destroyers", - "Superhuman Destroyers", - "Superhuman Destroyers", - "Street Punk Brawler", - "Street Punk Brawler", - "Street Punk Blade", - "Street Punk Blade", - "Street Punk Bullet", - "Street Punk Bullet", - "Street Punk Nails", - "Street Punk Nails", - "Street Punk Gatling", - "Street Punk Gatling", - "Tilestone", - "Franky", - "Kaku", - "Kaku", - "Rob Lucci", - "Rob Lucci", - "Keimi", - "Keimi", - "Pappug", - "Hachi", - "Doma", - "Doma", - "Decalvan Brothers", - "Decalvan Brothers", - "Squard", - "Squard", - "Whitey Bay", - "Whitey Bay", - "Little Oars Jr.", - "Little Oars Jr.", - "Marco", - "Marco", - "Nami", - "Nami", - "Duval", - "Duval", - "Duval", - "Arlong", - "Arlong", - "Kuroobi", - "Choo", - "Monkey D. Luffy", - "Usopp", - "Usopp", - "Nami", - "Nefertari Vivi", - "Nefertari Vivi", - "Koza", - "Koza", - "Nefertari Cobra", - "Sabo", - "Sabo", - "Koala", - "Koala", - "Hack", - "Hack", - "Emporio Ivankov", - "Emporio Ivankov", - "Inazuma", - "Inazuma", - "Nico Robin", - "Nico Robin", - "Nami", - "Nami", - "Nico Robin", - "Nico Robin", - "Perona", - "Perona", - "Nefertari Vivi", - "Calgara", - "Calgara", - "Montblanc Noland", - "Montblanc Noland", - "Halberd Coporal Navy", - "Pistol Coporal Navy", - "Saber Coporal Navy", - "Bazooka Coporal Navy", - "Knuckle Coporal Navy", - "Halberd Coporal Navy", - "Pistol Coporal Navy", - "Saber Coporal Navy", - "Bazooka Coporal Navy", - "Knuckle Coporal Navy", - "Oimo", - "Kashi", - "Watchdog Unit of the Law", - "Just Juryman", - "Three-Headed Baskerville", - "Blueno", - "Blueno", - "Nico Robin", - "Nico Robin", - "Franky", - "Franky", - "Gan Fall", - "Gan Fall", - "Pierre", - "Konis", - "Konis", - "Dracule Mihawk", - "Dracule Mihawk", - "Crocodile", - "Crocodile", - "Jerry", - "Jerry", - "T-Bone", - "T-Bone", - "Nefertari Vivi", - "Nefertari Vivi", - "Monkey D. Luffy", - "Kalifa", - "Kalifa", - "Jabra", - "Jabra", - "Fukuro", - "Fukuro", - "Kumadori", - "Kumadori", - "Kaku", - "Rob Lucci", - "Spandam", - "Franky", - "Nero", - "Nero", - "Wanze", - "Wanze", - "Portgas D. Ace", - "Portgas D. Ace", - "Princess Shirahoshi", - "Rob Lucci", - "Rob Lucci", - "Kaku", - "Kaku", - "Kalifa", - "Kalifa", - "Jabra", - "Jabra", - "Blueno", - "Blueno", - "Fukuro", - "Fukuro", - "Kumadori", - "Kumadori", - "Monkey D. Luffy", - "Usopp", - "Franky", - "Nami", - "Tony Tony Chopper", - "Roronoa Zoro", - "Nico Robin", - "Sanji", - "Brook", - "Dalmatian", - "Momonga", - "Onigumo", - "Shu", - "Very Good", - "Strawberry", - "Lucky Roo", - "Lucky Roo", - "Rebecca", - "Rebecca", - "Urouge", - "Urouge", - "Tashigi", - "Tashigi", - "Genzo", - "Genzo", - "Dr. Hiluluk", - "Dr. Hiluluk", - "Kuina", - "Kuina", - "Usopp Pirates", - "Usopp Pirates", - "Iceburg", - "Iceburg", - "Monkey D. Luffy", - "Monkey D. Luffy", - "Breed", - "Breed", - "Dugong", - "Lapin", - "Octopus Boxer", - "Bentham", - "Bentham", - "Hina", - "Hina", - "Smoker", - "Smoker", - "Nami", - "Nami", - "Lola", - "Lola", - "Risky Brothers", - "Cerberus", - "Tararan", - "Bear-Skin Rug", - "Gecko Moria", - "Gecko Moria", - "Soldier Zombie", - "Soldier Zombie", - "Soldier Zombie", - "Soldier Zombie", - "Soldier Zombie", - "Wild Zombie", - "Wild Zombie", - "Wild Zombie", - "General Zombie", - "General Zombie", - "General Zombie", - null, - null, - "Basil Hawkins", - "Basil Hawkins", - "Wyper", - "Wyper", - "Mr. 7 & Miss Father's Day", - "Bartholomew Kuma", - "Bartholomew Kuma", - "Caesar Clown", - "Caesar Clown", - "Vergo", - "Vergo", - "Monet", - "Monet", - "Baby 5", - "Baby 5", - "Buffalo", - "Buffalo", - "Tom", - "Tom", - "Franky", - "Iceburg", - "Wapol", - "Wapol", - "Robson", - "Tony Tony Chopper", - "Trafalgar Law", - "Trafalgar Law", - "Jewelry Bonney", - "Jewelry Bonney", - "Coby", - "Coby", - "Alvida", - "Alvida", - "Nami", - "Boa Hancock", - "Boa Hancock", - "Nico Robin", - "Usopp", - "Tony Tony Chopper", - "Donquixote Doflamingo", - "Donquixote Doflamingo", - "Sugar", - "Sugar", - "Señor Pink", - "Señor Pink", - "Trebol", - "Trebol", - "Jora", - "Jora", - "Lao-G", - "Lao-G", - "Scratchmen Apoo", - "Scratchmen Apoo", - "Dorry", - "Dorry", - "Jimbe", - "Daz Bones", - "Buggy", - null, - "Perona", - "Perona", - "Hogback", - "Absalom", - "Oars", - "Gecko Moria", - "Brook", - "Brook", - "Crocodile", - "Galdino", - "Bentham", - "Franky", - "Franky", - "Broggy", - "Broggy", - "Yokozuna", - "Roronoa Zoro", - "Roronoa Zoro", - "Nico Robin", - "Nico Robin", - "Tony Tony Chopper", - "Tony Tony Chopper", - "Sanji", - "Sanji", - "Brook", - "Brook", - "Nico Nico Robin", - "Nico Nico Robin", - "Marguerite", - "Marguerite", - "Aphelandra", - "Sweet Pea" + "Monkey D. Luffy", + "Monkey D. Luffy", + "Monkey D. Luffy", + "Monkey D. Luffy", + "Roronoa Zoro", + "Roronoa Zoro", + "Roronoa Zoro", + "Roronoa Zoro", + "Nami", + "Nami", + "Nami", + "Nami", + "Usopp", + "Usopp", + "Usopp", + "Usopp", + "Sanji", + "Sanji", + "Sanji", + "Sanji", + "Tony Tony Chopper", + "Tony Tony Chopper", + "Tony Tony Chopper", + "Tony Tony Chopper", + "Tony Tony Chopper", + "Tony Tony Chopper", + "Higuma", + "Master of the Near Sea", + "Alvida", + "Alvida", + "Coby", + "Coby", + "Helmeppo", + "Helmeppo", + "Morgan", + "Mohji & Richie", + "Cabaji", + "Buggy", + "Buggy", + "Gaimon", + "Siam", + "Butchie", + "Django", + "Django", + "Kuro", + "Kuro", + "Yosaku", + "Johnny", + "Fullbody", + "Patty", + "Carne", + "Zeff", + "Gin", + "Gin", + "Pearl", + "Pearl", + "Don Krieg", + "Don Krieg", + "Nezumi", + "Momoo", + "Choo", + "Kuroobi", + "Hachi", + "Hachi", + "Arlong", + "Arlong", + "Tashigi", + "Tashigi", + "Smoker", + "Smoker", + "Nefertari Vivi", + "Nefertari Vivi", + "Nefertari Vivi", + "Portgas D. Ace", + "Portgas D. Ace", + "Shanks", + "Shanks", + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + "Sword Bandit", + "Pistol Bandit", + "Fighter Group Crew Pirates", + "Fighter Group Crew Pirates", + "Fighter Group Crew Pirates", + "Fighter Group Crew Pirates", + "Fighter Group Crew Pirates", + "Slasher Group Crew Pirates", + "Slasher Group Crew Pirates", + "Slasher Group Crew Pirates", + "Slasher Group Crew Pirates", + "Slasher Group Crew Pirates", + "Striker Group Crew Pirates", + "Striker Group Crew Pirates", + "Striker Group Crew Pirates", + "Striker Group Crew Pirates", + "Striker Group Crew Pirates", + "Shooter Group Crew Pirates", + "Shooter Group Crew Pirates", + "Shooter Group Crew Pirates", + "Shooter Group Crew Pirates", + "Shooter Group Crew Pirates", + "Cannoneer", + "Fighter Group Crew Pirates", + "Fighter Group Crew Pirates", + "Fighter Group Crew Pirates", + "Fighter Group Crew Pirates", + "Fighter Group Crew Pirates", + "Slasher Group Crew Pirates", + "Slasher Group Crew Pirates", + "Slasher Group Crew Pirates", + "Slasher Group Crew Pirates", + "Slasher Group Crew Pirates", + "Striker Group Crew Pirates", + "Striker Group Crew Pirates", + "Striker Group Crew Pirates", + "Striker Group Crew Pirates", + "Striker Group Crew Pirates", + "Shooter Group Crew Pirates", + "Shooter Group Crew Pirates", + "Shooter Group Crew Pirates", + "Shooter Group Crew Pirates", + "Shooter Group Crew Pirates", + "Cannoneer", + "Bodyguard", + "Bodyguard", + "Black Cat Pirates", + "Black Cat Pirates", + "Black Cat Pirates", + "Black Cat Pirates", + "Black Cat Pirates", + "Fighter Group Leader", + "Slasher Group Leader", + "Striker Group Leader", + "Shooter Group Leader", + "Assassin Master", + "Arlong Crewmember", + "Arlong Crewmember", + "Arlong Crewmember", + "Arlong Crewmember", + "Knuckle Navy", + "Saber Navy", + "Halberd Navy", + "Pistol Navy", + "Cannoneer Navy", + "Knuckle Navy", + "Saber Navy", + "Halberd Navy", + "Pistol Navy", + "Cannoneer Navy", + null, + null, + null, + null, + null, + "Knuckle Navy", + "Saber Navy", + "Halberd Navy", + "Pistol Navy", + "Cannoneer Navy", + "Mr. 5", + "Mr. 5", + "Miss Valentine", + "Miss Valentine", + "Galdino", + "Galdino", + "Miss Goldenweek", + "Miss Goldenweek", + "Bentham", + "Bentham", + "Nico Robin", + "Nico Robin", + "Mr. 9", + "Mr. 9", + "Laboon", + "Laboon", + "Neptunian Squid", + "Monkey D. Luffy", + "Monkey D. Luffy", + "Roronoa Zoro", + "Roronoa Zoro", + "Nami", + "Nami", + "Usopp", + "Usopp", + "Sanji", + "Sanji", + "Dracule Mihawk", + "Dracule Mihawk", + "Morgan", + "Django", + "Fullbody", + "Hina", + "Hina", + "Mr. 8", + "Mr. 8", + "Misss Monday", + "Misss Monday", + "Knuckle Baroque Works", + "Saber Baroque Works", + "Halberd Baroque Works", + "Pistol Baroque Works", + "Bazooka Baroque Works", + "Knuckle Baroque Works", + "Saber Baroque Works", + "Halberd Baroque Works", + "Pistol Baroque Works", + "Bazooka Baroque Works", + "Tony Tony Chopper", + "Tony Tony Chopper", + "Tony Tony Chopper", + "Marco", + "Marco", + "Jozu", + "Jozu", + "Vista", + "Vista", + "Izo", + "Izo", + "Blamenco", + "Blamenco", + "Whitebeard", + "Whitebeard", + "Coby", + "Coby", + "Helmeppo", + "Helmeppo", + null, + null, + "Smoker", + "Fighter Group Crew Pirates", + "Fighter Group Crew Pirates", + "Fighter Group Crew Pirates", + "Fighter Group Crew Pirates", + "Fighter Group Crew Pirates", + "Slasher Group Crew Pirates", + "Slasher Group Crew Pirates", + "Slasher Group Crew Pirates", + "Slasher Group Crew Pirates", + "Slasher Group Crew Pirates", + "Striker Group Crew Pirates", + "Striker Group Crew Pirates", + "Striker Group Crew Pirates", + "Striker Group Crew Pirates", + "Striker Group Crew Pirates", + "Shooter Group Crew Pirates", + "Shooter Group Crew Pirates", + "Shooter Group Crew Pirates", + "Shooter Group Crew Pirates", + "Shooter Group Crew Pirates", + "Cannoneer", + "Mr. 13", + "Dorry", + "Broggy", + "Triceratops", + "Rex", + "Brontosaurus", + "Tsuru", + "Tsuru", + "Momonga", + "Onigumo", + null, + null, + null, + null, + null, + "Monkey D. Garp", + "Monkey D. Garp", + "Trafalgar Law", + "Trafalgar Law", + "Basil Hawkins", + "Basil Hawkins", + "Killer", + "Killer", + "Urouge", + "Urouge", + "Bepo", + "Bepo", + "Kalifa", + "Kalifa", + "Paulie", + "Paulie", + "Rob Lucci", + "Rob Lucci", + "Kaku", + "Kaku", + "Lulu", + "Wapol", + "Wapol", + "Dalton", + "Dalton", + "Chessmarimo", + "Chessmarimo", + "Chessmarimo", + "Dr. Kureha", + "Lapin", + "Lapin", + "Franky", + "Franky", + "Kiwi & Mozu", + "Kiwi & Mozu", + "Surume", + "Surume", + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + "Zephyr", + "Zephyr", + "Ain", + "Ain", + "Eustass Kid", + "Eustass Kid", + "Scratchmen Apoo", + "Scratchmen Apoo", + "X Drake", + "X Drake", + "Jewelry Bonney", + "Jewelry Bonney", + "Capone Bege", + "Capone Bege", + "Silvers Rayleigh", + "Silvers Rayleigh", + "Giant Red Pirates", + "Giant Blue Pirates", + "Giant Green Pirates", + "Giant Yellow Pirates", + "Giant Black Pirates", + "Giant Red Pirates", + "Giant Blue Pirates", + "Giant Green Pirates", + "Giant Yellow Pirates", + "Giant Black Pirates", + "Sea Cat", + "Dugong", + "Dugong", + "Banana Gator", + "Sandora Dragon", + "Crocodile", + "Crocodile", + "Hogback", + "Hogback", + "Cindry", + "Cindry", + "Emporio Ivankov", + "Emporio Ivankov", + "Perona", + "Perona", + "Kumacy", + "Dog Penguin", + "Miss Merry Christmas", + "Miss Merry Christmas", + "Mr. 4", + "Mr. 4", + "Miss Doublefinger", + "Miss Doublefinger", + "Daz Bones", + "Daz Bones", + "Rebecca", + "Absalom", + "Absalom", + "General Zombie", + "Jigoro of the Wind", + "Crocodile", + "Jimbe", + "Jimbe", + "Bartholomew Kuma", + "Bartholomew Kuma", + "Gecko Moria", + "Gecko Moria", + "Boa Hancock", + "Boa Hancock", + "Donquixote Doflamingo", + "Donquixote Doflamingo", + "Sanji", + "Monkey D. Luffy", + "Roronoa Zoro", + "Nami", + "Brook", + "Brook", + "Ryuuma", + "Masira", + "Shoujou", + "Montblanc Cricket", + "South Bird and Forest Residents", + "Bellamy", + "Bellamy", + "Sarquiss", + "Elizabeth", + "Caroline", + "Sanji", + "Sanji", + "Perona", + "Perona", + "Nefertari Vivi", + "Nefertari Vivi", + "Duck Squadron", + "Duck Squadron", + "Duck Squadron", + "Duck Squadron", + "Duck Squadron", + "Blackbeard", + "Blackbeard", + "Thatch", + "Thatch", + "Namule", + "Namule", + "Rakuyo", + "Rakuyo", + "Fossa", + "Fossa", + "Curiel", + "Curiel", + "Sengoku", + "Sengoku", + "Galdino", + "Bentham", + "Bentham", + "Satori", + "Shura", + "Gedatsu", + "Braham", + "Yama", + "Yellow Skypiea Guard", + "Black Skypiea Guard", + "Yellow Skypiea Guard", + "Black Skypiea Guard", + "Red Skypiea Guard Enforcer", + "Blue Skypiea Guard Enforcer", + "Green Skypiea Guard Enforcer", + "Yellow Skypiea Guard Enforcer", + "Black Skypiea Guard Enforcer", + "Red Skypiea Enforcer", + "Blue Skypiea Enforcer", + "Green Skypiea Enforcer", + "Yellow Skypiea Enforcer", + "Black Skypiea Enforcer", + "Red Skypiea Enforcer", + "Blue Skypiea Enforcer", + "Green Skypiea Enforcer", + "Yellow Skypiea Enforcer", + "Black Skypiea Enforcer", + "Red Shandian Warrior", + "Blue Shandian Warrior", + "Green Shandian Warrior", + "Red Shandian Warrior", + "Blue Shandian Warrior", + "Green Shandian Warrior", + "Yellow Shandian Warrior", + "Black Shandian Warrior", + "Yellow Shandian Warrior", + "Black Shandian Warrior", + "Portgas D. Ace", + "Portgas D. Ace", + "Bellmere", + "Bellmere", + "Kaya", + "Kaya", + "Hotori and Kotori", + "Hotori and Kotori", + "Pell", + "Pell", + "Chaka", + "Chaka", + "Crocodile", + "Crocodile", + "Daz Bones", + "Sabo", + "Sabo", + "Nico Robin", + "Heracles'n", + "Heracles'n", + "Usopp", + "Usopp", + "Monkey D. Luffy", + "Monkey D. Luffy", + "Sanji", + "Sanji", + "Nami", + "Nami", + "Brook", + "Brook", + "Tony Tony Chopper", + "Tony Tony Chopper", + "Shanks", + "Shanks", + "Nico Robin", + "Nico Robin", + "Brook", + "Brook", + "Nami", + "Nami", + "Domino", + "Domino", + "Minorhinoceros", + "Basilisk", + "Ohm", + "Nola Giant Snake", + "Wyper", + "Wyper", + "Eneru", + "Eneru", + "Monkey D. Luffy", + "Monkey D. Luffy", + "Sadi-chan", + "Sadi-chan", + "Minokoala", + "Manticore", + "Roronoa Zoro", + "Roronoa Zoro", + "Usopp", + "Usopp", + "Nico Robin", + "Nico Robin", + "Franky", + "Franky", + "Portgas D. Ace", + "Portgas D. Ace", + "Porche", + "Capote", + "Hamburg", + "Pickles", + "Big Bun", + "Foxy", + "Foxy", + "Monkey D. Luffy", + "Monkey D. Luffy", + "Usopp", + "Tony Tony Chopper", + "Aokiji", + "Aokiji", + "Nami", + "Monkey D. Luffy", + "Monkey D. Luffy", + "Roronoa Zoro", + "Roronoa Zoro", + "Genbou", + "Kamakiri", + "Raki", + "Aisa", + "Nojiko", + "Nojiko", + "Crocus", + "Crocus", + "Koza", + "Koza", + null, + null, + null, + null, + null, + "Tony Tony Chopper", + "Tony Tony Chopper", + "Buggy", + "Buggy", + "Shanks", + "Shanks", + "Eneru", + "Eneru", + "Sanji", + "Sanji", + "Zeff", + "Zeff", + "Patty", + "Carne", + "Hiking Bear", + "Purinpurin", + "Brook", + "Brook", + "Zanbai", + "Superhuman Destroyers", + "Superhuman Destroyers", + "Superhuman Destroyers", + "Street Punk Brawler", + "Street Punk Brawler", + "Street Punk Blade", + "Street Punk Blade", + "Street Punk Bullet", + "Street Punk Bullet", + "Street Punk Nails", + "Street Punk Nails", + "Street Punk Gatling", + "Street Punk Gatling", + "Tilestone", + "Franky", + "Kaku", + "Kaku", + "Rob Lucci", + "Rob Lucci", + "Camie", + "Camie", + "Pappagu", + "Hachi", + "Doma", + "Doma", + "Decalvan Brothers", + "Decalvan Brothers", + "Squard", + "Squard", + "Whitey Bay", + "Whitey Bay", + "Little Oars Jr.", + "Little Oars Jr.", + "Marco", + "Marco", + "Nami", + "Nami", + "Duval", + "Duval", + "Duval", + "Arlong", + "Arlong", + "Kuroobi", + "Choo", + "Monkey D. Luffy", + "Usopp", + "Usopp", + "Nami", + "Nefertari Vivi", + "Nefertari Vivi", + "Koza", + "Koza", + "Nefertari Cobra", + "Sabo", + "Sabo", + "Koala", + "Koala", + "Hack", + "Hack", + "Emporio Ivankov", + "Emporio Ivankov", + "Inazuma", + "Inazuma", + "Nico Robin", + "Nico Robin", + "Nami", + "Nami", + "Nico Robin", + "Nico Robin", + "Perona", + "Perona", + "Nefertari Vivi", + "Calgara", + "Calgara", + "Montblanc Noland", + "Montblanc Noland", + "Halberd Coporal Navy", + "Pistol Coporal Navy", + "Saber Coporal Navy", + "Bazooka Coporal Navy", + "Knuckle Coporal Navy", + "Halberd Coporal Navy", + "Pistol Coporal Navy", + "Saber Coporal Navy", + "Bazooka Coporal Navy", + "Knuckle Coporal Navy", + "Oimo", + "Kashi", + "Watchdog Unit of the Law", + "Just Juryman", + "Three-Headed Baskerville", + "Blueno", + "Blueno", + "Nico Robin", + "Nico Robin", + "Franky", + "Franky", + "Gan Fall", + "Gan Fall", + "Pierre", + "Konis", + "Konis", + "Dracule Mihawk", + "Dracule Mihawk", + "Crocodile", + "Crocodile", + "Jerry", + "Jerry", + "T-Bone", + "T-Bone", + "Nefertari Vivi", + "Nefertari Vivi", + "Monkey D. Luffy", + "Kalifa", + "Kalifa", + "Jabra", + "Jabra", + "Fukuro", + "Fukuro", + "Kumadori", + "Kumadori", + "Kaku", + "Rob Lucci", + "Spandam", + "Franky", + "Nero", + "Nero", + "Wanze", + "Wanze", + "Portgas D. Ace", + "Portgas D. Ace", + "Princess Shirahoshi", + "Rob Lucci", + "Rob Lucci", + "Kaku", + "Kaku", + "Kalifa", + "Kalifa", + "Jabra", + "Jabra", + "Blueno", + "Blueno", + "Fukuro", + "Fukuro", + "Kumadori", + "Kumadori", + "Monkey D. Luffy", + "Usopp", + "Franky", + "Nami", + "Tony Tony Chopper", + "Roronoa Zoro", + "Nico Robin", + "Sanji", + "Brook", + "Dalmatian", + "Momonga", + "Onigumo", + "Shu", + "Very Good", + "Strawberry", + "Lucky Roo", + "Lucky Roo", + "Rebecca", + "Rebecca", + "Urouge", + "Urouge", + "Tashigi", + "Tashigi", + "Genzo", + "Genzo", + "Dr. Hiluluk", + "Dr. Hiluluk", + "Kuina", + "Kuina", + "Usopp Pirates", + "Usopp Pirates", + "Iceburg", + "Iceburg", + "Monkey D. Luffy", + "Monkey D. Luffy", + "Breed", + "Breed", + "Dugong", + "Lapin", + "Octopus Boxer", + "Bentham", + "Bentham", + "Hina", + "Hina", + "Smoker", + "Smoker", + "Nami", + "Nami", + "Lola", + "Lola", + "Risky Brothers", + "Cerberus", + "Tararan", + "Bear-Skin Rug", + "Gecko Moria", + "Gecko Moria", + "Soldier Zombie", + "Soldier Zombie", + "Soldier Zombie", + "Soldier Zombie", + "Soldier Zombie", + "Wild Zombie", + "Wild Zombie", + "Wild Zombie", + "General Zombie", + "General Zombie", + "General Zombie", + "Trafalgar Law", + "Trafalgar Law", + "Basil Hawkins", + "Basil Hawkins", + "Wyper", + "Wyper", + "Mr. 7 & Miss Father's Day", + "Bartholomew Kuma", + "Bartholomew Kuma", + "Caesar Clown", + "Caesar Clown", + "Vergo", + "Vergo", + "Monet", + "Monet", + "Baby 5", + "Baby 5", + "Buffalo", + "Buffalo", + "Tom", + "Tom", + "Franky", + "Iceburg", + "Wapol", + "Wapol", + "Robson", + "Tony Tony Chopper", + "Trafalgar Law", + "Trafalgar Law", + "Jewelry Bonney", + "Jewelry Bonney", + "Coby", + "Coby", + "Alvida", + "Alvida", + "Nami", + "Boa Hancock", + "Boa Hancock", + "Nico Robin", + "Usopp", + "Tony Tony Chopper", + "Donquixote Doflamingo", + "Donquixote Doflamingo", + "Sugar", + "Sugar", + "Señor Pink", + "Señor Pink", + "Trebol", + "Trebol", + "Jora", + "Jora", + "Lao-G", + "Lao-G", + "Scratchmen Apoo", + "Scratchmen Apoo", + "Dorry", + "Dorry", + "Jimbe", + "Daz Bones", + "Buggy", + "Horo Horo Ghost", + "Perona", + "Perona", + "Hogback", + "Absalom", + "Oars", + "Gecko Moria", + "Brook", + "Brook", + "Crocodile", + "Galdino", + "Bentham", + "Franky", + "Franky", + "Broggy", + "Broggy", + "Yokozuna", + "Roronoa Zoro", + "Roronoa Zoro", + "Nico Robin", + "Nico Robin", + "Tony Tony Chopper", + "Tony Tony Chopper", + "Sanji", + "Sanji", + "Brook", + "Brook", + "Nico Robin", + "Nico Robin", + "Marguerite", + "Marguerite", + "Aphelandra", + "Sweet Pea", + "Boa Hancock", + "Boa Hancock", + "Eustass Kid", + "Eustass Kid", + "Sadi-chan", + "Sadi-chan", + "Doberman", + "Hannyabal", + "Hannyabal", + "Saldeath", + "Blugori", + "Pica", + "Pica", + "Jimbe", + "Jimbe", + "Monkey D. Luffy", + "Monkey D. Luffy", + "Nami", + "Nami", + "Usopp", + "Usopp", + "Franky", + "Franky", + "Perona", + "Perona", + "Rakuyo", + "Fossa", + "Curiel", + "Thatch", + "Portgas D. Ace", + "Portgas D. Ace", + "Ben Beckman", + "Ben Beckman", + "Gyaro", + "Makuro", + "Tansui", + "Gunman QCK 2", + "Gunman INT", + "Gunman DEX", + "Gunman QCK", + "Gunman STR", + "Gunman PSY", + "Charloss", + "Roswald", + "Shalulia", + "Eustass Kid", + "Trafalgar Law", + "Pacifista", + "Pacifista", + "Pacifista", + "Pacifista", + "Pacifista", + "Sentomaru", + "Sentomaru", + "Smoker", + "Smoker", + "Kizaru", + "Kizaru", + "Izo", + "Blamenco", + "Namule", + "Vista", + "Vista", + "Paulie", + "Impostor Straw Hats", + "Impostor Straw Hats", + "Impostor Straw Hats", + "Impostor Straw Hats", + "Impostor Straw Hats", + "Machvise", + "Machvise", + "Gladius", + "Gladius", + "Violet", + "Violet", + "Dellinger", + "Dellinger", + "Diamante", + "Diamante", + "Corazon", + "Corazon", + "Bepo", + "Bepo", + "Sachi and Penguin", + "Jean Bart", + "Jean Bart", + "Monet", + "Monet", + "Monkey D. Luffy", + "Count Butler", + "Count Butler", + "President Heaby", + "General Hotdog", + "Tony Tony Chopper", + "Capone Bege", + "Capone Bege", + "Brownbeard", + "Brownbeard", + "Lulu", + "Sugar", + "Sugar", + "Monkey D. Luffy", + "Portgas D. Ace", + "Don Chinjao", + "Don Chinjao", + "Blue Gilly", + "Blue Gilly", + "Funk Brothers", + "Funk Brothers", + "Hajrudin", + "Hajrudin", + "Abdullah and Jeet", + "Abdullah and Jeet", + "Bartolomeo", + "Bartolomeo", + "Emporio Ivankov", + "Emporio Ivankov", + "Inazuma", + "Inazuma", + "Jozu", + "Jozu", + "Killer", + "Killer", + "Trafalgar Law", + "Trafalgar Law", + "Sabo", + "Sabo", + "Nico Olvia", + "Nico Olvia", + "Saul", + "Saul", + "Nico Robin", + "Hina", + "Hina", + "Boa Sandersonia", + "Boa Sandersonia", + "Boa Marigold", + "Boa Marigold", + "Marguerite", + "Marguerite", + "Kikyo", + "Gloriosa", + "Female Archer STR", + "Female Archer INT", + "Swordswoman INT", + "Swordswoman PSY", + "Female Fighter DEX", + "Female Fighter QCK", + "Shuraiya", + "Shuraiya", + "Gasparde", + "Gasparde", + "Needless", + "Ricky", + "Ricky", + "Leo", + "Leo", + "Mansherry", + "Mansherry", + "Kyros", + "Kyros", + "Don Sai", + "Don Sai", + "Fujitora", + "Fujitora", + "Musshuru", + "Musshuru", + "Saga", + "Saga", + "X Drake", + "X Drake", + "Rebecca", + "Rebecca", + "Dr. Indigo", + "Dr. Indigo", + "Scarlet", + "Scarlet", + "Billy", + "Coby", + "Coby", + "Zephyr", + "Zephyr", + "Ain", + "Ain", + "Binz", + "Binz", + "Shiki", + "Shiki", + "Nami", + "Nami", + "Nico Robin", + "Nico Robin", + "Tony Tony Chopper", + "Monkey D. Luffy", + "Monkey D. Luffy", + "Sanji", + "Sanji", + "Nami", + "Nami", + "Monkey D. Luffy", + "Monkey D. Luffy", + "Cavendish", + "Cavendish", + "Suleiman", + "Suleiman", + "Orlumbus", + "Orlumbus", + "Dagama", + "Dagama", + "Elizabello", + "Elizabello", + "Ideo", + "Ideo", + "Tashigi", + "Tashigi", + "Fukuro", + "Jabra", + "Blueno", + "Kumadori", + "Gecko Moria", + "Gecko Moria", + "Foxy", + "Foxy", + "Porche", + "Porche", + "Uniformed Guard STR", + "Uniformed Guard QCK", + "Uniformed Guard DEX", + "Jailer INT", + "Jailer PSY", + "Minotaur", + "Minozebra", + "Sphinx", + "Saldeath", + "Army Wolf", + "Hannyabal", + "Hannyabal", + "Magellan", + "Magellan", + "Koala", + "Koala", + "Tesoro", + "Tesoro", + "Carina", + "Carina", + "Baccarat", + "Baccarat", + "Dice", + "Dice", + "Tanaka", + "Tanaka", + "Brook", + "Brook", + "Roronoa Zoro", + "Roronoa Zoro", + "Tony Tony Chopper", + "Tony Tony Chopper", + "Oars", + "Oars", + null, + "Blenheim", + "Blenheim", + "Kingdew", + "Kingdew", + "Haruta", + "Haruta", + "Atmos", + "Atmos", + "Speed Jiru", + "Speed Jiru", + "Aokiji", + "Aokiji", + "Boa Hancock", + "Boa Hancock", + "Gan Fall", + "Gan Fall", + "Ohm", + "Jewelry Bonney", + "Jewelry Bonney", + "Violet", + "Violet", + "Yoki", + "Yoki", + "Brook", + "Brook", + "Laboon", + "Nico Robin", + "Nico Robin", + "Usopp", + "Usopp", + "Franky", + "Franky", + "Baby 5", + "Baby 5", + "Gairam", + "Sebastian", + "Nightin", + "Boa Hancock", + "Byrnndi World", + "Byrnndi World", + "Little Oars Jr.", + "Little Oars Jr.", + "Bastille", + "Yamakaji", + "Hina", + "Smoker", + "Dracule Mihawk", + "Kizaru", + "Sentomaru", + "Sentomaru", + "Smoker", + "Smoker", + "Tashigi", + "Tashigi", + "Maynard", + "Maynard", + "Bastille", + "Bastille", + "Kizaru", + "Kizaru", + "Koala", + "Koala", + "Hack", + "Hack", + "Monkey D. Luffy", + "Portgas D. Ace", + "Portgas D. Ace", + "Marco", + "Marco", + "Marco", + "Marco", + "Doma", + "Shura", + "Squard", + "Decalvan Brothers", + "Whitey Bay", + "Whitebeard", + "Whitebeard", + "Donquixote Doflamingo", + "Donquixote Doflamingo", + "Señor Pink", + "Señor Pink", + "Vergo", + "Vergo", + "Portgas D. Ace", + "Portgas D. Ace", + "Blackbeard", + "Blackbeard", + "Laffitte", + "Laffitte", + "Van Augur", + "Van Augur", + "Jesus Burgess", + "Jesus Burgess", + "Shiliew", + "Shiliew", + "Doc Q", + "Doc Q", + "John Giant", + "Aokiji", + "Monkey D. Garp", + "Sengoku", + "Akainu", + "Monkey D. Luffy", + "Monkey D. Luffy", + "Baby 5", + "Baby 5", + "Trafalgar Law", + "Trafalgar Law", + "Buffalo", + "Lao-G", + "Lao-G", + "Boa Sandersonia", + "Boa Sandersonia", + "Kalifa", + "Kalifa", + "Akainu", + "Akainu", + "Rebecca", + "Rebecca", + "Buggy", + "Buggy", + "Galdino", + "Galdino", + "Sugar", + "Sugar", + "Bartolomeo", + "Bartolomeo", + "Kinemon", + "Kinemon", + "Boa Marigold", + "Boa Marigold", + "Akainu", + "Akainu", + "Coby", + "Coby", + "Monkey D. Garp", + "Monkey D. Garp", + "Tsuru", + "Tsuru", + "Momonga", + "Momonga", + "Onigumo", + "Onigumo", + "Corazon", + "Corazon", + "Leo", + "Leo", + "Wicca", + "Gancho", + "Mansherry", + "Mansherry", + "Kabu", + "Bian", + "Sabo", + "Sabo", + "Kanjuro", + "Kanjuro", + "Tony Tony Chopper", + "Gedatsu", + "Gedatsu", + "Dadan", + "Porchemy", + "Bluejam", + "Jimbe", + "Heracles'n", + "Torino Kingdom Monsters", + "Humandrills", + "Haredas", + "Thieves of Tehna Gehna Kingdom", + "Tequila Wolf Guard", + "Emporio Ivankov", + "Silvers Rayleigh", + "Silvers Rayleigh", + "Silvers Rayleigh", + "Pekoms", + "Pekoms", + "Tamago", + "Tamago", + "Monkey D. Luffy", + "Roronoa Zoro", + "Roronoa Zoro", + "Franky", + "Franky", + "Nami", + "Nami", + "Sanji", + "Sanji", + "Tony Tony Chopper", + "Tony Tony Chopper", + "Roronoa Zoro", + "Roronoa Zoro", + "Magellan", + "Magellan", + "Dellinger", + "Dellinger", + "Marguerite", + "Marguerite", + "Shanks", + "Shanks", + "Tashigi", + "Tashigi", + "Kyros", + "Kyros", + "Rebecca", + "Rebecca", + "Monkey D. Luffy", + "Roronoa Zoro", + "Nami", + "Buggy", + "Buggy", + "Sentomaru", + "Demalo Black", + "Baby 5", + "Baby 5", + "Tashigi", + "Tashigi", + "Smoker", + "Smoker", + "Gladius", + "Gladius", + "Dalton", + "Monkey D. Luffy", + "Monkey D. Luffy", + "Usopp", + "Usopp", + "Nico Robin", + "Nico Robin", + "Brook", + "Brook", + "Tony Tony Chopper", + "Tony Tony Chopper", + "Whitebeard", + "Sanji", + "Sengoku", + "Sengoku", + "Ronse", + "Stainless", + "Rob Lucci", + "Rob Lucci", + "Diamante", + "Diamante", + "T-Bone", + "Gin", + "Don Sai", + "Don Sai", + "Boo", + "Jean Ango", + "Mansherry", + "Mansherry", + "Franky", + "Franky", + "Hody Jones", + "Hody Jones", + "Hyouzou", + "Hyouzou", + "Ikaros Much", + "Ikaros Much", + "Daruma", + "Daruma", + "Zeo", + "Zeo", + "Dosun", + "Dosun", + "Boa Hancock", + "Usopp", + "Sanji", + "Tony Tony Chopper", + "Violet", + "Violet", + "Sanji", + "Sanji", + "Marguerite", + "Marguerite", + "Don Chinjao", + "Don Chinjao", + "Kuro", + "Kuro", + "Miss Valentine", + "Miss Valentine", + "Roronoa Zoro", + "Monkey D. Luffy", + "Monkey D. Luffy", + "Tony Tony Chopper", + "Tony Tony Chopper", + "Cavendish", + "Cavendish", + "Sentomaru", + "Sentomaru", + "Lip Service", + "Albion", + "Princess Shirahoshi", + "Princess Shirahoshi", + "King Neptune", + "King Neptune", + "Fukaboshi", + "Fukaboshi", + "Caribou", + "Caribou", + "Vander Decken IX", + "Vander Decken IX", + "Madame Shyarly", + "Madame Shyarly", + "Sanji", + "Sanji", + "Ideo", + "Ideo", + "Don Krieg", + "Don Krieg", + "Mr. 5", + "Mr. 5", + "Sabo", + "Fishman Outlaw STR", + "Fishman Outlaw QCK", + "Fishman Outlaw DEX", + "Bombardment Fishman Outlaw INT", + "Bombardment Fishman Outlaw PSY", + "Fishman Guard STR", + "Fishman Guard QCK", + "Fishman Guard DEX", + "Caribou", + "Coribou", + "Hammond", + "Vander Decken IX", + "Hody Jones", + "Hody Jones", + "Sanji", + "Sanji", + "Haruta", + "Speed Jiru", + "Atmos", + "Kingdew", + "Sanji", + "Sanji", + "Brook", + "Brook", + "Bellamy", + "Bellamy", + "Dadan", + "Dadan", + "Dogra", + "Portgas D. Ace", + "Tony Tony Chopper", + "Tony Tony Chopper", + "Suleiman", + "Arlong", + "Arlong", + "Blenheim", + "Cavendish", + "Cavendish", + "Usopp", + "Usopp", + "Rayleigh", + "Rayleigh", + "Duval", + "Duval", + "Heracles'n", + "Heracles'n", + "Perona", + "Perona", + "Elizabeth", + "Elizabeth", + "Usopp", + "Koala", + "Koala", + "Brook", + "Brook", + "Thieves of Tehna Gehna Kingdom", + "Nico Robin", + "Franky", + "Brook", + "Hajrudin", + "Hajrudin", + "Ryuuma", + "Ryuuma", + "Wadatsumi", + "Zeo", + "Ikaros Much", + "Hyouzou", + "Daruma", + "Dosun", + "Hody Jones", + "Elizabello", + "Elizabello", + "Dagama", + "Dagama", + "Boa Hancock", + "Boa Hancock", + "Trafalgar Law", + "Inuarashi", + "Inuarashi", + "Wanda", + "Wanda", + "Sicilian", + "Sicilian", + "Kinemon", + "Kinemon", + "Momonosuke", + "Momonosuke", + "Trafalgar Law", + "Trafalgar Law", + "Monet", + "Orlumbus", + "Orlumbus", + "Helmeppo", + "Helmeppo", + "Sanji", + "Sanji", + "Shanks", + "Shanks", + "Boa Hancock", + "Boa Hancock", + "Monkey D. Luffy", + "Fujitora", + "Fujitora", + "Princess Shirahoshi", + "Princess Shirahoshi", + "Ryuboshi", + "Manboshi", + "Monkey D. Luffy", + "Shiliew", + "Shiliew", + "McGuy", + "Portgas D. Ace", + "Portgas D. Ace", + "Laffitte", + "Van Augur", + "Doc Q", + "Eneru", + "Eneru", + "Bartholomew Kuma", + "Bartholomew Kuma", + "Rob Lucci", + "Rob Lucci", + "Crocodile", + "Crocodile", + "Gecko Moria", + "Gecko Moria", + "Silvers Rayleigh", + "Eustass Kid", + "Eustass Kid", + "Donquixote Doflamingo", + "Donquixote Doflamingo", + "Hyouzou", + "Daruma", + "Dosun", + "Machvise", + "Machvise", + "Ikaros Much", + "Ikaros Much", + "Fisher Tiger", + "Fisher Tiger", + "Punk Hazard Dragon", + "Rock and Scotch", + "Brownbeard", + "Caesar Clown", + "Caesar Clown", + "Gas Mask Patrol STR", + "Gas Mask Patrol QCK", + "Gas Mask Patrol DEX", + "Gas Mask Patrol INT", + "Gas Mask Patrol PSY", + "Patrol Troop Corps STR", + "Patrol Troop Corps QCK", + "Patrol Troop Corps DEX", + "Pica", + "Pica", + "Jora", + "Jora", + "Brook", + "Nekomamushi", + "Nekomamushi", + "Pedro", + "Pedro", + "Carrot", + "Carrot", + "Kanjuro", + "Kanjuro", + "Raizo", + "Raizo", + "Corazon", + "Corazon", + "Rob Lucci", + "Aokiji", + "Aokiji", + "Kyros", + "Kyros", + "Aokiji", + "Aokiji", + "Madame Shyarly", + "Camie", + "Pappagu", + "Perona", + "Perona", + "Roronoa Zoro", + "Roronoa Zoro", + "Trafalgar Law", + "Trafalgar Law", + "Dracule Mihawk", + "Dracule Mihawk", + "Monkey D. Luffy", + "Monkey D. Luffy", + "Nico Robin", + "Nico Robin", + "Usopp", + "Usopp", + "Franky", + "Franky", + "Eustass Kid", + "Eustass Kid", + "Heat", + "Wire", + "Inuarashi", + "Inuarashi", + "Vergo", + "Vergo", + "Magellan", + "Magellan", + "Jimbe", + "Jimbe", + "Emporio Ivankov", + "Emporio Ivankov", + "Hannyabal", + "Hannyabal", + "Bentham", + "Bentham", + "Shanks", + "Nami", + "Nami", + "Nico Robin", + "Nico Robin", + "Akainu", + "Akainu", + "Monet", + "Vergo", + "Caesar Clown", + "Vegapunk's Dragon", + "Buffalo", + "Baby 5", + "Jimbe", + "Jimbe", + "King Neptune", + "King Neptune", + "Fukaboshi", + "Fukaboshi", + "Sabo", + "Sabo", + "Tashigi", + "Tashigi", + "Nefertari Vivi", + "Nefertari Vivi", + "Nekomamushi", + "Nekomamushi", + "Sugar", + "Sugar", + "Trebol", + "Trebol", + "Bellamy", + "Bellamy", + "Boa Sandersonia", + "Boa Sandersonia", + "Boa Marigold", + "Boa Marigold", + "Marguerite", + "Marguerite", + "Boa Hancock", + "Boa Hancock", + "Bepo", + "Bepo", + "Trafalgar Law", + "Trafalgar Law", + "Roronoa Zoro", + "Roronoa Zoro", + "Sanji", + "Sanji", + "Nami", + "Nami", + "Brook", + "Brook", + "Tony Tony Chopper", + "Tony Tony Chopper", + "Rob Lucci", + "Rob Lucci", + "Aokiji", + "Blue Gilly", + "Blue Gilly", + "Funk Brothers", + "Abdullah and Jeet", + "Ben Beckman", + "Ben Beckman", + "Bartholomew Kuma", + "Bartholomew Kuma", + "Kinemon", + "Kinemon", + "Momonosuke", + "Momonosuke", + "Kizaru", + "Kizaru", + "Kizaru", + "Kizaru", + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + "Monkey D. Luffy", + "Monkey D. Luffy", + "Sabo", + "Sabo", + "Diamante", + "Diamante", + "Jesus Burgess", + "Jesus Burgess", + "Cavendish", + "Cavendish", + "Bartolomeo", + "Bartolomeo", + "Roronoa Zoro", + "Roronoa Zoro", + "Buggy", + "Buggy", + "Dracule Mihawk", + "Dracule Mihawk", + "Wanda", + "Wanda", + "Carrot", + "Carrot", + "Koala", + "Sanji", + "Sanji", + "Portgas D. Ace", + "Ricky", + "Ricky", + "Princess Scarlet", + "Tank", + "Sanji", + "Sanji", + "Byrnndi World", + "Byrnndi World", + "Akainu", + "Akainu", + "Sicilian", + "Sicilian", + "Caesar Clown", + "Caesar Clown", + "Vinsmoke Judge", + "Vinsmoke Judge", + "Vinsmoke Reiju", + "Vinsmoke Reiju", + "Vinsmoke Ichiji", + "Vinsmoke Ichiji", + "Vinsmoke Niji", + "Vinsmoke Niji", + "Vinsmoke Yonji", + "Vinsmoke Yonji", + "Caribou", + "Caribou", + "Coribou", + "Coribou", + "Monkey D. Garp", + "Monkey D. Garp", + "Sengoku", + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + "Silvers Rayleigh", + "Silvers Rayleigh", ]; \ No newline at end of file diff --git a/common/data/flags.js b/common/data/flags.js index 7c20427e2..8c4d6ee60 100644 --- a/common/data/flags.js +++ b/common/data/flags.js @@ -1,726 +1,1689 @@ window.flags = { - 1: { global: 1 }, - 2: { global: 1, rr: 1 }, - 3: { global: 1, rr: 1 }, - 4: { global: 1, rr: 1 }, - 5: { global: 1, rr: 1 }, - 6: { global: 1, rr: 1 }, - 7: { global: 1, rr: 1 }, - 8: { global: 1, rr: 1 }, - 9: { global: 1, rr: 1 }, - 10: { global: 1, rr: 1 }, - 11: { global: 1, rr: 1 }, - 12: { global: 1, rr: 1 }, - 13: { global: 1, rr: 1 }, - 14: { global: 1, rr: 1 }, - 15: { global: 1, rr: 1 }, - 16: { global: 1, rr: 1 }, - 17: { global: 1, rr: 1 }, - 18: { global: 1, rr: 1 }, - 19: { global: 1, rr: 1 }, - 20: { global: 1, rr: 1 }, - 21: { global: 1, rr: 1 }, - 22: { global: 1, rr: 1 }, - 23: { global: 1, rr: 1 }, - 24: { global: 1, rr: 1 }, - 25: { global: 1, rr: 1 }, - 26: { global: 1, rr: 1 }, - 27: { global: 1 }, - 28: { global: 1 }, - 29: { global: 1, rr: 1 }, - 30: { global: 1, rr: 1 }, - 31: { global: 1 }, - 32: { global: 1, rr: 1 }, - 33: { global: 1 }, - 34: { global: 1, rr: 1 }, - 35: { global: 1 }, - 36: { global: 1 }, - 37: { global: 1 }, - 38: { global: 1, rr: 1 }, - 39: { global: 1, rr: 1 }, - 40: { global: 1 }, - 41: { global: 1 }, - 42: { global: 1 }, - 43: { global: 1 }, - 44: { global: 1, rr: 1 }, - 45: { global: 1, rr: 1 }, - 46: { global: 1, rr: 1 }, - 47: { global: 1 }, - 48: { global: 1 }, - 49: { global: 1 }, - 50: { global: 1 }, - 51: { global: 1 }, - 52: { global: 1 }, - 53: { global: 1 }, - 54: { global: 1, rr: 1 }, - 55: { global: 1 }, - 56: { global: 1, rr: 1 }, - 57: { global: 1, rr: 1 }, - 58: { global: 1, rr: 1 }, - 59: { global: 1 }, - 60: { global: 1 }, - 61: { global: 1, rr: 1 }, - 62: { global: 1, rr: 1 }, - 63: { global: 1, rr: 1 }, - 64: { global: 1, rr: 1 }, - 65: { global: 1, rr: 1 }, - 66: { global: 1, rr: 1 }, - 67: { global: 1, rr: 1 }, - 68: { global: 1, rr: 1 }, - 69: { global: 1, rr: 1 }, - 70: { global: 1, rr: 1 }, - 71: { global: 1, rr: 1 }, - 72: { global: 1, rr: 1 }, - 73: { global: 1, rr: 1 }, - 74: { global: 1, rr: 1, rro: 1 }, - 75: { global: 1, rr: 1, rro: 1 }, - 76: { global: 1, rr: 1, rro: 1 }, - 77: { global: 1, rr: 1, rro: 1 }, - 78: { global: 1 }, - 79: { global: 1 }, - 80: { global: 1 }, - 81: { global: 1 }, - 82: { global: 1 }, - 83: { global: 1 }, - 84: { global: 1 }, - 85: { global: 1 }, - 86: { global: 1 }, - 87: { global: 1 }, - 88: { global: 1 }, - 89: { global: 1 }, - 90: { global: 1 }, - 91: { global: 1 }, - 92: { global: 1 }, - 93: { global: 1 }, - 94: { global: 1 }, - 95: { global: 1 }, - 96: { global: 1 }, - 97: { global: 1 }, - 98: { global: 1 }, - 99: { global: 1 }, - 100: { global: 1 }, - 101: { global: 1 }, - 102: { global: 1 }, - 103: { global: 1 }, - 104: { global: 1 }, - 105: { global: 1 }, - 106: { global: 1 }, - 107: { global: 1 }, - 108: { global: 1 }, - 109: { global: 1 }, - 110: { global: 1 }, - 111: { global: 1 }, - 112: { global: 1 }, - 113: { global: 1 }, - 114: { global: 1 }, - 115: { global: 1 }, - 116: { global: 1 }, - 117: { global: 1 }, - 118: { global: 1 }, - 119: { global: 1 }, - 120: { global: 1 }, - 121: { global: 1 }, - 122: { global: 1 }, - 123: { global: 1 }, - 124: { global: 1 }, - 125: { global: 1 }, - 126: { global: 1 }, - 127: { global: 1 }, - 128: { global: 1 }, - 129: { global: 1 }, - 130: { global: 1 }, - 131: { global: 1 }, - 132: { global: 1 }, - 133: { global: 1 }, - 134: { global: 1 }, - 135: { global: 1 }, - 136: { global: 1 }, - 137: { global: 1 }, - 138: { global: 1 }, - 139: { global: 1 }, - 140: { global: 1 }, - 141: { global: 1 }, - 142: { global: 1 }, - 143: { global: 1 }, - 144: { global: 1 }, - 145: { global: 1 }, - 146: { global: 1 }, - 147: { global: 1 }, - 148: { global: 1 }, - 149: { global: 1 }, - 150: { global: 1 }, - 151: { global: 1 }, - 152: { global: 1 }, - 153: { global: 1 }, - 154: { global: 1 }, - 155: { global: 1 }, - 156: { global: 1 }, - 157: { global: 1 }, - 158: { global: 1 }, - 159: { global: 1 }, - 160: { global: 1 }, - 161: { global: 1 }, - 162: { global: 1 }, - 163: { global: 1 }, - 164: { global: 1 }, - 165: { global: 1 }, - 166: { global: 1 }, - 167: { global: 1 }, - 168: { global: 1 }, - 169: { global: 1 }, - 170: { global: 1 }, - 171: { global: 1 }, - 172: { global: 1 }, - 173: { global: 1 }, - 174: { global: 1 }, - 175: { global: 1 }, - 176: { global: 1 }, - 177: { global: 1 }, - 178: { global: 1 }, - 179: { global: 1 }, - 180: { global: 1 }, - 181: { global: 1 }, - 182: { global: 1 }, - 183: { global: 1 }, - 184: { global: 1 }, - 185: { global: 1 }, - 186: { global: 1 }, - 187: { global: 1 }, - 188: { global: 1 }, - 189: { global: 1 }, - 190: { global: 1 }, - 191: { global: 1 }, - 192: { global: 1 }, - 193: { global: 1 }, - 194: { global: 1 }, - 195: { global: 1 }, - 196: { global: 1 }, - 197: { global: 1 }, - 198: { global: 1 }, - 199: { global: 1, rr: 1 }, - 200: { global: 1, rr: 1 }, - 201: { global: 1, rr: 1 }, - 202: { global: 1, rr: 1 }, - 203: { global: 1, rr: 1 }, - 204: { global: 1, rr: 1 }, - 205: { global: 1, rr: 1 }, - 206: { global: 1, rr: 1 }, - 207: { global: 1, rr: 1 }, - 208: { global: 1, rr: 1 }, - 209: { global: 1, rr: 1, rro: 1 }, - 210: { global: 1, rr: 1, rro: 1 }, - 211: { global: 1 }, - 212: { global: 1 }, - 213: { global: 1 }, - 214: { global: 1 }, - 215: { global: 1 }, - 216: { global: 1, rr: 1, rro: 1 }, - 217: { global: 1, rr: 1, rro: 1 }, - 218: { global: 1, rr: 1, rro: 1 }, - 219: { global: 1, rr: 1, rro: 1 }, - 220: { global: 1, rr: 1, rro: 1 }, - 221: { global: 1, rr: 1, rro: 1 }, - 222: { global: 1, rr: 1 }, - 223: { global: 1, rr: 1 }, - 224: { global: 1, rr: 1, rro: 1 }, - 225: { global: 1, rr: 1, rro: 1 }, - 226: { global: 1 }, - 227: { global: 1 }, - 228: { global: 1 }, - 229: { global: 1 }, - 230: { global: 1 }, - 231: { global: 1 }, - 232: { global: 1 }, - 233: { global: 1 }, - 234: { global: 1 }, - 235: { global: 1 }, - 236: { global: 1 }, - 237: { global: 1 }, - 238: { global: 1 }, - 239: { global: 1 }, - 240: { global: 1 }, - 241: { global: 1 }, - 242: { global: 1 }, - 243: { global: 1 }, - 244: { global: 1 }, - 245: { global: 1 }, - 246: { global: 1 }, - 247: { global: 1, special: 1 }, - 248: { global: 1 }, - 249: { global: 1 }, - 250: { global: 1, rr: 1, rro: 1 }, - 251: { global: 1, rr: 1, rro: 1 }, - 252: { global: 1, rr: 1, rro: 1 }, - 253: { global: 1, rr: 1, rro: 1 }, - 254: { global: 1, rr: 1, rro: 1 }, - 255: { global: 1, rr: 1, rro: 1 }, - 256: { global: 1, rr: 1, rro: 1 }, - 257: { global: 1, rr: 1, rro: 1 }, - 258: { global: 1, rr: 1, rro: 1 }, - 259: { global: 1, rr: 1, rro: 1 }, - 260: { global: 1, rr: 1, rro: 1 }, - 261: { global: 1, rr: 1, rro: 1 }, - 262: { global: 1 }, - 263: { global: 1 }, - 264: { global: 1 }, - 265: { global: 1 }, - 266: { global: 1 }, - 267: { global: 1 }, - 268: { global: 1 }, - 269: { global: 1 }, - 270: { global: 1 }, - 271: { global: 1 }, - 272: { global: 1 }, - 273: { global: 1 }, - 274: { global: 1 }, - 275: { global: 1 }, - 276: { global: 1 }, - 277: { global: 1 }, - 278: { global: 1 }, - 279: { global: 1 }, - 280: { global: 1 }, - 281: { global: 1 }, - 282: { global: 1 }, - 283: { global: 1 }, - 284: { global: 1 }, - 285: { global: 1 }, - 286: { global: 1 }, - 287: { global: 1 }, - 288: { global: 1 }, - 289: { global: 1 }, - 290: { global: 1 }, - 291: { global: 1 }, - 292: { global: 1 }, - 293: { global: 1 }, - 294: { global: 1 }, - 295: { global: 1 }, - 296: { global: 1 }, - 297: { global: 1 }, - 298: { global: 1 }, - 299: { global: 1 }, - 300: { global: 1 }, - 301: { global: 1 }, - 302: { global: 1 }, - 303: { global: 1 }, - 304: { global: 1 }, - 305: { global: 1 }, - 306: { global: 1 }, - 307: { global: 1, rr: 1, rro: 1 }, - 308: { global: 1, rr: 1, rro: 1 }, - 309: { global: 1, rr: 1, rro: 1 }, - 310: { global: 1, rr: 1, rro: 1 }, - 311: { global: 1, rr: 1, rro: 1 }, - 312: { global: 1, rr: 1, rro: 1 }, - 313: { global: 1, rr: 1, rro: 1 }, - 314: { global: 1, rr: 1, rro: 1 }, - 315: { global: 1, rr: 1, rro: 1 }, - 316: { global: 1, rr: 1, rro: 1 }, - 317: { global: 1 }, - 318: { global: 1 }, - 319: { global: 1 }, - 320: { global: 1 }, - 321: { global: 1 }, - 322: { global: 1 }, - 323: { global: 1 }, - 324: { global: 1 }, - 325: { global: 1 }, - 326: { global: 1 }, - 327: { global: 1 }, - 328: { global: 1 }, - 329: { global: 1 }, - 330: { global: 1 }, - 331: { global: 1 }, - 332: { global: 1 }, - 333: { global: 1 }, - 334: { global: 1 }, - 335: { global: 1 }, - 336: { global: 1 }, - 337: { global: 1 }, - 338: { global: 1 }, - 339: { global: 1 }, - 340: { global: 1 }, - 341: { global: 1 }, - 342: { global: 1 }, - 343: { global: 1 }, - 344: { global: 1 }, - 345: { global: 1 }, - 346: { global: 1 }, - 347: { global: 1 }, - 348: { global: 1 }, - 349: { global: 1 }, - 350: { global: 1 }, - 351: { global: 1 }, - 356: { global: 1, rr: 1, rro: 1 }, - 357: { global: 1, rr: 1, rro: 1 }, - 358: { global: 1, rr: 1, rro: 1 }, - 359: { global: 1, rr: 1, rro: 1 }, - 360: { global: 1, rr: 1, rro: 1 }, - 361: { global: 1, rr: 1, rro: 1 }, - 362: { global: 1, rr: 1, rro: 1 }, - 363: { global: 1, rr: 1, rro: 1 }, - 364: { global: 1, rr: 1, rro: 1 }, - 365: { global: 1, rr: 1, rro: 1 }, - 366: { global: 1, rr: 1, rro: 1 }, - 367: { global: 1, rr: 1, rro: 1 }, - 368: { global: 1 }, - 369: { global: 1 }, - 370: { global: 1 }, - 371: { global: 1 }, - 372: { global: 1 }, - 373: { global: 1 }, - 374: { global: 1 }, - 375: { global: 1 }, - 376: { global: 1 }, - 377: { global: 1 }, - 378: { global: 1 }, - 379: { global: 1 }, - 380: { global: 1 }, - 381: { global: 1 }, - 382: { global: 1 }, - 383: { global: 1 }, - 384: { global: 1 }, - 385: { global: 1 }, - 386: { global: 1 }, - 387: { global: 1 }, - 388: { global: 1 }, - 389: { global: 1 }, - 390: { global: 1 }, - 391: { global: 1 }, - 392: { global: 1 }, - 393: { global: 1 }, - 394: { global: 1 }, - 395: { global: 1 }, - 396: { global: 1 }, - 397: { global: 1 }, - 398: { global: 1 }, - 399: { global: 1 }, - 400: { global: 1 }, - 401: { global: 1 }, - 402: { global: 1 }, - 403: { promo: 1 }, - 404: { global: 1 }, - 405: { global: 1 }, - 406: { global: 1 }, - 407: { global: 1 }, - 408: { global: 1 }, - 409: { global: 1, rr: 1, rro: 1 }, - 410: { global: 1, rr: 1, rro: 1 }, - 411: { global: 1, rr: 1, rro: 1 }, - 412: { global: 1, rr: 1, rro: 1 }, - 413: { global: 1, rr: 1, rro: 1 }, - 414: { global: 1, rr: 1, rro: 1 }, - 415: { global: 1, rr: 1, rro: 1 }, - 416: { global: 1, rr: 1, rro: 1 }, - 417: { global: 1 }, - 418: { global: 1 }, - 419: { global: 1, promo: 1, special: 1 }, - 420: { global: 1 }, - 421: { global: 1 }, - 422: { global: 1 }, - 423: { global: 1 }, - 424: { global: 1 }, - 425: { global: 1 }, - 426: { global: 1 }, - 427: { global: 1 }, - 428: { global: 1 }, - 429: { global: 1 }, - 430: { global: 1 }, - 431: { global: 1 }, - 432: { global: 1 }, - 433: { global: 1 }, - 434: { global: 1 }, - 435: { global: 1 }, - 436: { global: 1 }, - 437: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 438: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 439: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 440: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 441: { global: 1 }, - 442: { global: 1 }, - 443: { global: 1 }, - 444: { global: 1 }, - 445: { global: 1 }, - 446: { global: 1 }, - 447: { global: 1 }, - 448: { global: 1, rr: 1, rro: 1 }, - 449: { global: 1, rr: 1, rro: 1 }, - 450: { global: 1, rr: 1, rro: 1 }, - 451: { global: 1, rr: 1, rro: 1 }, - 452: { global: 1, rr: 1, rro: 1 }, - 453: { global: 1, rr: 1, rro: 1 }, - 454: { global: 1, rr: 1, rro: 1 }, - 455: { global: 1, rr: 1, rro: 1 }, - 456: { global: 1, rr: 1, rro: 1 }, - 457: { global: 1, rr: 1, rro: 1 }, - 458: { global: 1, rr: 1, rro: 1 }, - 459: { global: 1, rr: 1, rro: 1 }, - 463: { global: 1 }, - 464: { global: 1 }, - 465: { global: 1 }, - 466: { global: 1 }, - 467: { global: 1 }, - 468: { global: 1 }, - 469: { global: 1 }, - 470: { global: 1 }, - 471: { global: 1 }, - 472: { global: 1 }, - 473: { global: 1 }, - 474: { global: 1 }, - 475: { global: 1 }, - 476: { global: 1 }, - 477: { global: 1 }, - 478: { global: 1 }, - 479: { global: 1 }, - 480: { global: 1 }, - 481: { global: 1 }, - 482: { global: 1 }, - 483: { global: 1 }, - 484: { global: 1 }, - 485: { global: 1 }, - 486: { global: 1 }, - 487: { global: 1 }, - 488: { global: 1 }, - 489: { global: 1 }, - 490: { global: 1 }, - 491: { global: 1 }, - 492: { global: 1 }, - 493: { global: 1 }, - 494: { global: 1 }, - 495: { global: 1 }, - 496: { global: 1 }, - 497: { global: 1, rr: 1, rro: 1 }, - 498: { global: 1, rr: 1, rro: 1 }, - 499: { global: 1, rr: 1, rro: 1 }, - 500: { global: 1, rr: 1, rro: 1 }, - 501: { global: 1, rr: 1, rro: 1 }, - 502: { global: 1, rr: 1, rro: 1 }, - 503: { global: 1, rr: 1, rro: 1 }, - 504: { global: 1, rr: 1, rro: 1 }, - 505: { global: 1, rr: 1, rro: 1 }, - 506: { global: 1, rr: 1, rro: 1 }, - 507: { global: 1, rr: 1, rro: 1 }, - 508: { global: 1, rr: 1, rro: 1 }, - 509: { global: 1 }, - 510: { global: 1 }, - 511: { global: 1 }, - 512: { global: 1, rr: 1, rro: 1, lrr: 1, promo: 1 }, - 513: { global: 1, rr: 1, rro: 1, lrr: 1, promo: 1 }, - 514: { rr: 1, rro: 1, lrr: 1 }, - 519: { rr: 1, rro: 1 }, - 520: { rr: 1, rro: 1 }, - 521: { rr: 1, rro: 1 }, - 522: { rr: 1, rro: 1 }, - 523: { rr: 1, rro: 1 }, - 524: { rr: 1, rro: 1 }, - 525: { rr: 1, rro: 1 }, - 526: { rr: 1, rro: 1 }, - 527: { rr: 1, rro: 1 }, - 528: { rr: 1, rro: 1 }, - 529: { global: 1, rr: 1, rro: 1 }, - 530: { global: 1, rr: 1, rro: 1 }, - 531: { promo: 1, global: 1 }, - 532: { promo: 1, global: 1 }, - 533: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 534: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 535: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 536: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 541: { global: 1 }, - 542: { global: 1 }, - 543: { global: 1 }, - 544: { global: 1 }, - 545: { global: 1 }, - 546: { global: 1 }, - 547: { global: 1, rr: 1, rro: 1, lrr: 1 }, - 548: { global: 1, rr: 1, rro: 1, lrr: 1 }, - 553: { rr: 1, rro: 1 }, - 554: { rr: 1, rro: 1 }, - 555: { rr: 1, rro: 1 }, - 556: { rr: 1, rro: 1 }, - 557: { rr: 1, rro: 1 }, - 558: { rr: 1, rro: 1 }, - 559: { rr: 1, rro: 1 }, - 560: { rr: 1, rro: 1 }, - 561: { rr: 1, rro: 1, global: 1 }, - 562: { rr: 1, rro: 1, global: 1 }, - 563: { global: 1 }, - 564: { global: 1 }, - 565: { global: 1 }, - 566: { global: 1 }, - 567: { global: 1 }, - 568: { global: 1 }, - 569: { global: 1 }, - 570: { global: 1 }, - 571: { global: 1 }, - 572: { global: 1 }, - 573: { global: 1 }, - 576: { special: 1 }, - 577: { rr: 1, rro: 1, global: 1 }, - 578: { rr: 1, rro: 1, global: 1 }, - 579: { global: 1, rr: 1, rro: 1, lrr: 1 }, - 580: { global: 1, rr: 1, rro: 1, lrr: 1 }, - 581: { global: 1 }, - 582: { global: 1 }, - 583: { global: 1 }, - 584: { global: 1 }, - 585: { global: 1, rr: 1, rro: 1 }, - 586: { global: 1, rr: 1, rro: 1 }, - 587: { global: 1, rr: 1, rro: 1 }, - 588: { global: 1, rr: 1, rro: 1 }, - 589: { global: 1, rr: 1, rro: 1 }, - 590: { global: 1, rr: 1, rro: 1 }, - 591: { global: 1 }, - 592: { global: 1 }, - 593: { global: 1 }, - 594: { global: 1 }, - 595: { global: 1 }, - 596: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 597: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 602: { global: 1 }, - 603: { global: 1 }, - 604: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 605: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 610: { global: 1 }, - 611: { global: 1 }, - 612: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 613: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 614: { global: 1 }, - 615: { global: 1 }, - 616: { global: 1 }, - 617: { global: 1 }, - 618: { global: 1 }, - 619: { global: 1 }, - 620: { global: 1 }, - 621: { global: 1 }, - 622: { global: 1 }, - 623: { global: 1 }, - 624: { global: 1 }, - 625: { global: 1 }, - 626: { global: 1 }, - 627: { global: 1 }, - 628: { global: 1 }, - 629: { global: 1 }, - 630: { global: 1 }, - 631: { global: 1 }, - 632: { global: 1 }, - 633: { global: 1 }, - 638: { rr: 1, rro: 1, global: 1 }, - 639: { rr: 1, rro: 1, global: 1 }, - 640: { rr: 1, rro: 1, global: 1 }, - 641: { rr: 1, rro: 1, global: 1 }, - 642: { rr: 1, rro: 1, global: 1 }, - 643: { rr: 1, rro: 1, global: 1 }, - 644: { rr: 1, rro: 1, global: 1 }, - 645: { rr: 1, rro: 1, global: 1 }, - 646: { rr: 1, rro: 1, global: 1 }, - 647: { rr: 1, rro: 1, global: 1 }, - 648: { rr: 1, rro: 1, global: 1 }, - 649: { rr: 1, rro: 1, global: 1 }, - 650: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 651: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 660: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 661: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 668: { rr: 1, rro: 1 }, - 669: { rr: 1, rro: 1 }, - 670: { rr: 1, rro: 1 }, - 671: { rr: 1, rro: 1 }, - 672: { rr: 1, rro: 1 }, - 673: { rr: 1, rro: 1 }, - 674: { rr: 1, rro: 1 }, - 675: { rr: 1, rro: 1 }, - 676: { rr: 1, rro: 1 }, - 677: { rr: 1, rro: 1 }, - 678: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 679: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 708: { special: 1 }, - 709: { special: 1 }, - 710: { global: 1, rr: 1, rro: 1, lrr: 1 }, - 711: { global: 1, rr: 1, rro: 1, lrr: 1 }, - 717: { rr: 1, rro: 1, global: 1 }, - 718: { rr: 1, rro: 1, global: 1 }, - 719: { rr: 1, rro: 1 }, - 720: { rr: 1, rro: 1 }, - 725: { global: 1, rr: 1, rro: 1, lrr: 1 }, - 726: { global: 1, rr: 1, rro: 1, lrr: 1 }, - 727: { special: 1 }, - 744: { rr: 1, rro: 1, lrr: 1 }, - 745: { rr: 1, rro: 1, lrr: 1 }, - 746: { promo: 1 }, - 747: { rr: 1, rro: 1 }, - 748: { rr: 1, rro: 1 }, - 749: { rr: 1, rro: 1 }, - 750: { rr: 1, rro: 1 }, - 751: { rr: 1, rro: 1 }, - 752: { rr: 1, rro: 1 }, - 753: { rr: 1, rro: 1 }, - 754: { rr: 1, rro: 1 }, - 755: { rr: 1, rro: 1 }, - 756: { rr: 1, rro: 1 }, - 757: { rr: 1, rro: 1 }, - 758: { rr: 1, rro: 1 }, - 759: { rr: 1, rro: 1 }, - 760: { rr: 1, rro: 1 }, - 761: { global: 1 }, - 762: { global: 1 }, - 763: { global: 1 }, - 764: { global: 1 }, - 765: { global: 1 }, - 766: { global: 1 }, - 767: { global: 1 }, - 768: { global: 1 }, - 769: { global: 1 }, - 782: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 783: { rr: 1, rro: 1, lrr: 1, global: 1 }, - 784: { rr: 1, rro: 1 }, - 785: { rr: 1, rro: 1 }, - 786: { rr: 1, rro: 1 }, - 787: { rr: 1, rro: 1 }, - 788: { rr: 1, rro: 1 }, - 789: { rr: 1, rro: 1 }, - 790: { rr: 1, rro: 1 }, - 791: { rr: 1, rro: 1 }, - 792: { rr: 1, rro: 1 }, - 793: { rr: 1, rro: 1 }, - 801: { rr: 1, rro: 1, lrr: 1 }, - 802: { rr: 1, rro: 1, lrr: 1 }, - 837: { rr: 1, rro: 1 }, - 838: { rr: 1, rro: 1 }, - 839: { rr: 1, rro: 1 }, - 840: { rr: 1, rro: 1 }, - 841: { rr: 1, rro: 1 }, - 842: { rr: 1, rro: 1 }, - 843: { rr: 1, rro: 1 }, - 844: { rr: 1, rro: 1 }, - 845: { rr: 1, rro: 1 }, - 846: { rr: 1, rro: 1 }, - 855: { rr: 1, rro: 1, global: 1 }, - 856: { rr: 1, rro: 1, global: 1 }, - 857: { rr: 1, rro: 1, global: 1 }, - 858: { rr: 1, rro: 1, global: 1 }, - 863: { special: 1 }, - 869: { rr: 1, rro: 1 }, - 870: { rr: 1, rro: 1 }, - 871: { rr: 1, rro: 1 }, - 872: { rr: 1, rro: 1 }, - 873: { rr: 1, rro: 1 }, - 874: { rr: 1, rro: 1 }, - 875: { rr: 1, rro: 1 }, - 876: { rr: 1, rro: 1 }, - 877: { rr: 1, rro: 1 }, - 878: { rr: 1, rro: 1 }, - 879: { rr: 1, rro: 1 }, - 880: { rr: 1, rro: 1 }, - 895: { special: 1 }, - 896: { special: 1 }, - 905: { rr: 1, rro: 1 }, - 906: { rr: 1, rro: 1 }, - 907: { rr: 1, rro: 1 }, - 908: { rr: 1, rro: 1 }, - 909: { rr: 1, rro: 1 }, - 910: { rr: 1, rro: 1 }, - 911: { rr: 1, rro: 1 }, - 912: { rr: 1, rro: 1 }, - 913: { rr: 1, rro: 1 }, - 914: { rr: 1, rro: 1 }, - 915: { rr: 1, rro: 1, lrr: 1 }, - 916: { rr: 1, rro: 1, lrr: 1 } + 1: { global: 1 }, + 2: { global: 1, rr: 1 }, + 3: { global: 1, rr: 1 }, + 4: { global: 1, rr: 1 }, + 5: { global: 1, rr: 1 }, + 6: { global: 1, rr: 1 }, + 7: { global: 1, rr: 1 }, + 8: { global: 1, rr: 1 }, + 9: { global: 1, rr: 1 }, + 10: { global: 1, rr: 1 }, + 11: { global: 1, rr: 1 }, + 12: { global: 1, rr: 1 }, + 13: { global: 1, rr: 1 }, + 14: { global: 1, rr: 1 }, + 15: { global: 1, rr: 1 }, + 16: { global: 1, rr: 1 }, + 17: { global: 1, rr: 1 }, + 18: { global: 1, rr: 1 }, + 19: { global: 1, rr: 1 }, + 20: { global: 1, rr: 1 }, + 21: { global: 1, rr: 1 }, + 22: { global: 1, rr: 1 }, + 23: { global: 1, rr: 1 }, + 24: { global: 1, rr: 1 }, + 25: { global: 1, rr: 1 }, + 26: { global: 1, rr: 1 }, + 27: { global: 1 }, + 28: { global: 1 }, + 29: { global: 1, rr: 1 }, + 30: { global: 1, rr: 1 }, + 31: { global: 1 }, + 32: { global: 1, rr: 1 }, + 33: { global: 1 }, + 34: { global: 1, rr: 1 }, + 35: { global: 1 }, + 36: { global: 1 }, + 37: { global: 1 }, + 38: { global: 1 }, + 39: { global: 1 }, + 40: { global: 1 }, + 41: { global: 1 }, + 42: { global: 1 }, + 43: { global: 1 }, + 44: { global: 1 }, + 45: { global: 1 }, + 46: { global: 1 }, + 47: { global: 1 }, + 48: { global: 1 }, + 49: { global: 1 }, + 50: { global: 1 }, + 51: { global: 1 }, + 52: { global: 1 }, + 53: { global: 1 }, + 54: { global: 1 }, + 55: { global: 1 }, + 56: { global: 1 }, + 57: { global: 1 }, + 58: { global: 1 }, + 59: { global: 1 }, + 60: { global: 1 }, + 61: { global: 1 }, + 62: { global: 1 }, + 63: { global: 1 }, + 64: { global: 1 }, + 65: { global: 1 }, + 66: { global: 1 }, + 67: { global: 1 }, + 68: { global: 1 }, + 69: { global: 1 }, + 70: { global: 1 }, + 71: { global: 1, rr: 1 }, + 72: { global: 1, rr: 1 }, + 73: { global: 1, rr: 1 }, + 74: { global: 1, rr: 1, rro: 1 }, + 75: { global: 1, rr: 1, rro: 1 }, + 76: { global: 1, rr: 1, rro: 1 }, + 77: { global: 1, rr: 1, rro: 1 }, + 78: { global: 1 }, + 79: { global: 1 }, + 80: { global: 1 }, + 81: { global: 1 }, + 82: { global: 1 }, + 83: { global: 1 }, + 84: { global: 1 }, + 85: { global: 1 }, + 86: { global: 1 }, + 87: { global: 1 }, + 88: { global: 1 }, + 89: { global: 1 }, + 90: { global: 1 }, + 91: { global: 1 }, + 92: { global: 1 }, + 93: { global: 1 }, + 94: { global: 1 }, + 95: { global: 1 }, + 96: { global: 1 }, + 97: { global: 1 }, + 98: { global: 1 }, + 99: { global: 1 }, + 100: { global: 1 }, + 101: { global: 1 }, + 102: { global: 1 }, + 103: { global: 1 }, + 104: { global: 1 }, + 105: { global: 1 }, + 106: { global: 1 }, + 107: { global: 1 }, + 108: { global: 1 }, + 109: { global: 1 }, + 110: { global: 1 }, + 111: { global: 1 }, + 112: { global: 1 }, + 113: { global: 1 }, + 114: { global: 1 }, + 115: { global: 1 }, + 116: { global: 1 }, + 117: { global: 1 }, + 118: { global: 1 }, + 119: { global: 1 }, + 120: { global: 1 }, + 121: { global: 1 }, + 122: { global: 1 }, + 123: { global: 1 }, + 124: { global: 1 }, + 125: { global: 1 }, + 126: { global: 1 }, + 127: { global: 1 }, + 128: { global: 1 }, + 129: { global: 1 }, + 130: { global: 1 }, + 131: { global: 1 }, + 132: { global: 1 }, + 133: { global: 1 }, + 134: { global: 1 }, + 135: { global: 1 }, + 136: { global: 1 }, + 137: { global: 1 }, + 138: { global: 1 }, + 139: { global: 1 }, + 140: { global: 1 }, + 141: { global: 1 }, + 142: { global: 1 }, + 143: { global: 1 }, + 144: { global: 1 }, + 145: { global: 1 }, + 146: { global: 1 }, + 147: { global: 1 }, + 148: { global: 1 }, + 149: { global: 1 }, + 150: { global: 1 }, + 151: { global: 1 }, + 152: { global: 1 }, + 153: { global: 1 }, + 154: { global: 1 }, + 155: { global: 1 }, + 156: { global: 1 }, + 157: { global: 1 }, + 158: { global: 1 }, + 159: { global: 1 }, + 160: { global: 1 }, + 161: { global: 1 }, + 162: { global: 1 }, + 163: { global: 1 }, + 164: { global: 1 }, + 165: { global: 1 }, + 166: { global: 1 }, + 167: { global: 1 }, + 168: { global: 1 }, + 169: { global: 1 }, + 170: { global: 1 }, + 171: { global: 1 }, + 172: { global: 1 }, + 173: { global: 1 }, + 174: { global: 1 }, + 175: { global: 1 }, + 176: { global: 1 }, + 177: { global: 1 }, + 178: { global: 1 }, + 179: { global: 1 }, + 180: { global: 1 }, + 181: { global: 1 }, + 182: { global: 1 }, + 183: { global: 1 }, + 184: { global: 1 }, + 185: { global: 1 }, + 186: { global: 1 }, + 187: { global: 1 }, + 188: { global: 1 }, + 189: { global: 1 }, + 190: { global: 1 }, + 191: { global: 1 }, + 192: { global: 1 }, + 193: { global: 1 }, + 194: { global: 1 }, + 195: { global: 1 }, + 196: { global: 1 }, + 197: { global: 1 }, + 198: { global: 1 }, + 199: { global: 1 }, + 200: { global: 1 }, + 201: { global: 1 }, + 202: { global: 1 }, + 203: { global: 1 }, + 204: { global: 1 }, + 205: { global: 1 }, + 206: { global: 1 }, + 207: { global: 1 }, + 208: { global: 1 }, + 209: { global: 1, rr: 1, rro: 1 }, + 210: { global: 1, rr: 1, rro: 1 }, + 211: { global: 1 }, + 212: { global: 1 }, + 213: { global: 1 }, + 214: { global: 1 }, + 215: { global: 1 }, + 216: { global: 1, rr: 1, rro: 1 }, + 217: { global: 1, rr: 1, rro: 1 }, + 218: { global: 1, rr: 1, rro: 1 }, + 219: { global: 1, rr: 1, rro: 1 }, + 220: { global: 1, rr: 1, rro: 1 }, + 221: { global: 1, rr: 1, rro: 1 }, + 222: { global: 1, rr: 1 }, + 223: { global: 1, rr: 1 }, + 224: { global: 1, rr: 1, rro: 1 }, + 225: { global: 1, rr: 1, rro: 1 }, + 226: { global: 1 }, + 227: { global: 1 }, + 228: { global: 1 }, + 229: { global: 1 }, + 230: { global: 1 }, + 231: { global: 1 }, + 232: { global: 1 }, + 233: { global: 1 }, + 234: { global: 1 }, + 235: { global: 1 }, + 236: { global: 1 }, + 237: { global: 1 }, + 238: { global: 1 }, + 239: { global: 1 }, + 240: { global: 1 }, + 241: { global: 1 }, + 242: { global: 1 }, + 243: { global: 1 }, + 244: { global: 1 }, + 245: { global: 1 }, + 246: { global: 1 }, + 247: { global: 1, special: 1, shop: 1 }, + 248: { global: 1 }, + 249: { global: 1 }, + 250: { global: 1, rr: 1, rro: 1 }, + 251: { global: 1, rr: 1, rro: 1 }, + 252: { global: 1, rr: 1, rro: 1 }, + 253: { global: 1, rr: 1, rro: 1 }, + 254: { global: 1, rr: 1, rro: 1 }, + 255: { global: 1, rr: 1, rro: 1 }, + 256: { global: 1, rr: 1, rro: 1 }, + 257: { global: 1, rr: 1, rro: 1 }, + 258: { global: 1, rr: 1, rro: 1 }, + 259: { global: 1, rr: 1, rro: 1 }, + 260: { global: 1, rr: 1, rro: 1 }, + 261: { global: 1, rr: 1, rro: 1 }, + 262: { global: 1 }, + 263: { global: 1 }, + 264: { global: 1 }, + 265: { global: 1 }, + 266: { global: 1 }, + 267: { global: 1 }, + 268: { global: 1 }, + 269: { global: 1 }, + 270: { global: 1 }, + 271: { global: 1 }, + 272: { global: 1 }, + 273: { global: 1 }, + 274: { global: 1 }, + 275: { global: 1 }, + 276: { global: 1 }, + 277: { global: 1 }, + 278: { global: 1 }, + 279: { global: 1 }, + 280: { global: 1 }, + 281: { global: 1 }, + 282: { global: 1 }, + 283: { global: 1 }, + 284: { global: 1 }, + 285: { global: 1 }, + 286: { global: 1 }, + 287: { global: 1 }, + 288: { global: 1 }, + 289: { global: 1 }, + 290: { global: 1 }, + 291: { global: 1 }, + 292: { global: 1 }, + 293: { global: 1 }, + 294: { global: 1 }, + 295: { global: 1 }, + 296: { global: 1 }, + 297: { global: 1 }, + 298: { global: 1 }, + 299: { global: 1 }, + 300: { global: 1 }, + 301: { global: 1 }, + 302: { global: 1 }, + 303: { global: 1 }, + 304: { global: 1 }, + 305: { global: 1 }, + 306: { global: 1 }, + 307: { global: 1, rr: 1, rro: 1 }, + 308: { global: 1, rr: 1, rro: 1 }, + 309: { global: 1, rr: 1, rro: 1 }, + 310: { global: 1, rr: 1, rro: 1 }, + 311: { global: 1, rr: 1, rro: 1 }, + 312: { global: 1, rr: 1, rro: 1 }, + 313: { global: 1, rr: 1, rro: 1 }, + 314: { global: 1, rr: 1, rro: 1 }, + 315: { global: 1, rr: 1, rro: 1 }, + 316: { global: 1, rr: 1, rro: 1 }, + 317: { global: 1 }, + 318: { global: 1 }, + 319: { global: 1 }, + 320: { global: 1 }, + 321: { global: 1 }, + 322: { global: 1 }, + 323: { global: 1 }, + 324: { global: 1 }, + 325: { global: 1 }, + 326: { global: 1 }, + 327: { global: 1 }, + 328: { global: 1 }, + 329: { global: 1 }, + 330: { global: 1 }, + 331: { global: 1 }, + 332: { global: 1 }, + 333: { global: 1 }, + 334: { global: 1 }, + 335: { global: 1 }, + 336: { global: 1 }, + 337: { global: 1 }, + 338: { global: 1 }, + 339: { global: 1 }, + 340: { global: 1 }, + 341: { global: 1 }, + 342: { global: 1 }, + 343: { global: 1 }, + 344: { global: 1 }, + 345: { global: 1 }, + 346: { global: 1 }, + 347: { global: 1 }, + 348: { global: 1 }, + 349: { global: 1 }, + 350: { global: 1 }, + 351: { global: 1 }, + 352: { global: 1 }, + 353: { global: 1 }, + 354: { global: 1 }, + 355: { global: 1 }, + 356: { global: 1, rr: 1, rro: 1 }, + 357: { global: 1, rr: 1, rro: 1 }, + 358: { global: 1, rr: 1, rro: 1 }, + 359: { global: 1, rr: 1, rro: 1 }, + 360: { global: 1, rr: 1, rro: 1 }, + 361: { global: 1, rr: 1, rro: 1 }, + 362: { global: 1, rr: 1, rro: 1 }, + 363: { global: 1, rr: 1, rro: 1 }, + 364: { global: 1, rr: 1, rro: 1 }, + 365: { global: 1, rr: 1, rro: 1 }, + 366: { global: 1, rr: 1, rro: 1 }, + 367: { global: 1, rr: 1, rro: 1 }, + 368: { global: 1 }, + 369: { global: 1 }, + 370: { global: 1 }, + 371: { global: 1 }, + 372: { global: 1 }, + 373: { global: 1 }, + 374: { global: 1 }, + 375: { global: 1 }, + 376: { global: 1 }, + 377: { global: 1 }, + 378: { global: 1 }, + 379: { global: 1 }, + 380: { global: 1 }, + 381: { global: 1 }, + 382: { global: 1 }, + 383: { global: 1 }, + 384: { global: 1 }, + 385: { global: 1 }, + 386: { global: 1 }, + 387: { global: 1 }, + 388: { global: 1 }, + 389: { global: 1 }, + 390: { global: 1 }, + 391: { global: 1 }, + 392: { global: 1 }, + 393: { global: 1 }, + 394: { global: 1 }, + 395: { global: 1 }, + 396: { global: 1 }, + 397: { global: 1 }, + 398: { global: 1 }, + 399: { global: 1 }, + 400: { global: 1 }, + 401: { global: 1 }, + 402: { global: 1 }, + 403: { promo: 1, shop: 1 }, + 404: { global: 1 }, + 405: { global: 1 }, + 406: { global: 1 }, + 407: { global: 1 }, + 408: { global: 1 }, + 409: { global: 1, rr: 1, rro: 1 }, + 410: { global: 1, rr: 1, rro: 1 }, + 411: { global: 1, rr: 1, rro: 1 }, + 412: { global: 1, rr: 1, rro: 1 }, + 413: { global: 1, rr: 1, rro: 1 }, + 414: { global: 1, rr: 1, rro: 1 }, + 415: { global: 1, rr: 1, rro: 1 }, + 416: { global: 1, rr: 1, rro: 1 }, + 417: { global: 1 }, + 418: { global: 1 }, + 419: { global: 1, promo: 1, special: 1 }, + 420: { global: 1 }, + 421: { global: 1 }, + 422: { global: 1 }, + 423: { global: 1 }, + 424: { global: 1 }, + 425: { global: 1 }, + 426: { global: 1 }, + 427: { global: 1 }, + 428: { global: 1 }, + 429: { global: 1 }, + 430: { global: 1 }, + 431: { global: 1 }, + 432: { global: 1 }, + 433: { global: 1 }, + 434: { global: 1 }, + 435: { global: 1 }, + 436: { global: 1 }, + 437: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 438: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 439: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 440: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 441: { global: 1 }, + 442: { global: 1 }, + 443: { global: 1 }, + 444: { global: 1 }, + 445: { global: 1 }, + 446: { global: 1 }, + 447: { global: 1 }, + 448: { global: 1, rr: 1, rro: 1 }, + 449: { global: 1, rr: 1, rro: 1 }, + 450: { global: 1, rr: 1, rro: 1 }, + 451: { global: 1, rr: 1, rro: 1 }, + 452: { global: 1, rr: 1, rro: 1 }, + 453: { global: 1, rr: 1, rro: 1 }, + 454: { global: 1, rr: 1, rro: 1 }, + 455: { global: 1, rr: 1, rro: 1 }, + 456: { global: 1, rr: 1, rro: 1 }, + 457: { global: 1, rr: 1, rro: 1 }, + 458: { global: 1, rr: 1, rro: 1 }, + 459: { global: 1, rr: 1, rro: 1 }, + 460: { global: 1 }, + 461: { global: 1 }, + 462: { global: 1 }, + 463: { global: 1 }, + 464: { global: 1 }, + 465: { global: 1 }, + 466: { global: 1 }, + 467: { global: 1 }, + 468: { global: 1 }, + 469: { global: 1 }, + 470: { global: 1 }, + 471: { global: 1 }, + 472: { global: 1 }, + 473: { global: 1 }, + 474: { global: 1 }, + 475: { global: 1 }, + 476: { global: 1 }, + 477: { global: 1 }, + 478: { global: 1 }, + 479: { global: 1 }, + 480: { global: 1 }, + 481: { global: 1 }, + 482: { global: 1 }, + 483: { global: 1 }, + 484: { global: 1 }, + 485: { global: 1 }, + 486: { global: 1 }, + 487: { global: 1 }, + 488: { global: 1 }, + 489: { global: 1 }, + 490: { global: 1 }, + 491: { global: 1 }, + 492: { global: 1 }, + 493: { global: 1 }, + 494: { global: 1 }, + 495: { global: 1 }, + 496: { global: 1 }, + 497: { global: 1, rr: 1, rro: 1, lrr: 1 }, + 498: { global: 1, rr: 1, rro: 1, lrr: 1 }, + 499: { global: 1, rr: 1, rro: 1 }, + 500: { global: 1, rr: 1, rro: 1 }, + 501: { global: 1, rr: 1, rro: 1 }, + 502: { global: 1, rr: 1, rro: 1 }, + 503: { global: 1, rr: 1, rro: 1 }, + 504: { global: 1, rr: 1, rro: 1 }, + 505: { global: 1, rr: 1, rro: 1 }, + 506: { global: 1, rr: 1, rro: 1 }, + 507: { global: 1, rr: 1, rro: 1 }, + 508: { global: 1, rr: 1, rro: 1 }, + 509: { global: 1 }, + 510: { global: 1 }, + 511: { global: 1 }, + 512: { global: 1, rr: 1, rro: 1, lrr: 1, promo: 1 }, + 513: { global: 1, rr: 1, rro: 1, lrr: 1, promo: 1 }, + 514: { special: 1, shop: 1, global: 1 }, + 515: { global: 1 }, + 516: { global: 1 }, + 517: { global: 1 }, + 518: { global: 1 }, +// 519: { rr: 1, rro: 1 }, +// 520: { rr: 1, rro: 1 }, +// 521: { rr: 1, rro: 1 }, +// 522: { rr: 1, rro: 1 }, +// 523: { rr: 1, rro: 1 }, +// 524: { rr: 1, rro: 1 }, +// 525: { rr: 1, rro: 1 }, +// 526: { rr: 1, rro: 1 }, +// 527: { rr: 1, rro: 1 }, +// 528: { rr: 1, rro: 1 }, + 529: { global: 1, rr: 1, rro: 1 }, + 530: { global: 1, rr: 1, rro: 1 }, + 531: { promo: 1, global: 1, shop: 1 }, + 532: { promo: 1, global: 1, shop: 1 }, + 533: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 534: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 535: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 536: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 537: { global: 1 }, + 538: { global: 1 }, + 539: { global: 1 }, + 540: { global: 1 }, + 541: { global: 1 }, + 542: { global: 1 }, + 543: { global: 1 }, + 544: { global: 1 }, + 545: { global: 1 }, + 546: { global: 1 }, + 547: { global: 1, rr: 1, rro: 1, lrr: 1 }, + 548: { global: 1, rr: 1, rro: 1, lrr: 1 }, + 549: { global: 1 }, + 550: { global: 1 }, + 551: { global: 1 }, + 552: { global: 1 }, +// 553: { rr: 1, rro: 1 }, +// 554: { rr: 1, rro: 1 }, +// 555: { rr: 1, rro: 1 }, +// 556: { rr: 1, rro: 1 }, +// 557: { rr: 1, rro: 1 }, +// 558: { rr: 1, rro: 1 }, +// 559: { rr: 1, rro: 1 }, +// 560: { rr: 1, rro: 1 }, + 561: { rr: 1, rro: 1, global: 1 }, + 562: { rr: 1, rro: 1, global: 1 }, + 563: { global: 1 }, + 564: { global: 1 }, + 565: { global: 1 }, + 566: { global: 1 }, + 567: { global: 1 }, + 568: { global: 1 }, + 569: { global: 1 }, + 570: { global: 1 }, + 571: { global: 1 }, + 572: { global: 1 }, + 573: { global: 1 }, + 574: { global: 1 }, + 575: { global: 1 }, + 576: { special: 1, shop: 1, global: 1 }, +// 577: { rr: 1, rro: 1, global: 1 }, + 577: { global: 1 }, +// 578: { rr: 1, rro: 1, global: 1 }, + 578: { global: 1 }, + 579: { global: 1, rr: 1, rro: 1, lrr: 1 }, + 580: { global: 1, rr: 1, rro: 1, lrr: 1 }, + 581: { global: 1 }, + 582: { global: 1 }, + 583: { global: 1 }, + 584: { global: 1 }, + 585: { global: 1, rr: 1, rro: 1 }, + 586: { global: 1, rr: 1, rro: 1 }, + 587: { global: 1, rr: 1, rro: 1 }, + 588: { global: 1, rr: 1, rro: 1 }, + 589: { global: 1, rr: 1, rro: 1 }, + 590: { global: 1, rr: 1, rro: 1 }, + 591: { global: 1 }, + 592: { global: 1 }, + 593: { global: 1 }, + 594: { global: 1 }, + 595: { global: 1 }, + 596: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 597: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 598: { global: 1 }, + 599: { global: 1 }, + 600: { global: 1 }, + 601: { global: 1 }, + 602: { global: 1 }, + 603: { global: 1 }, + 604: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 605: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 606: { global: 1 }, + 607: { global: 1 }, + 608: { global: 1 }, + 609: { global: 1 }, + 610: { global: 1 }, + 611: { global: 1 }, + 612: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 613: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 614: { global: 1 }, + 615: { global: 1 }, + 616: { global: 1 }, + 617: { global: 1 }, + 618: { global: 1 }, + 619: { global: 1 }, + 620: { global: 1 }, + 621: { global: 1 }, + 622: { global: 1 }, + 623: { global: 1 }, + 624: { global: 1 }, + 625: { global: 1 }, + 626: { global: 1 }, + 627: { global: 1 }, + 628: { global: 1 }, + 629: { global: 1 }, + 630: { global: 1 }, + 631: { global: 1 }, + 632: { global: 1 }, + 633: { global: 1 }, + 634: { global: 1 }, + 635: { global: 1 }, + 636: { global: 1 }, + 637: { global: 1 }, + 638: { rr: 1, rro: 1, global: 1 }, + 639: { rr: 1, rro: 1, global: 1 }, + 640: { rr: 1, rro: 1, global: 1 }, + 641: { rr: 1, rro: 1, global: 1 }, + 642: { rr: 1, rro: 1, global: 1 }, + 643: { rr: 1, rro: 1, global: 1 }, + 644: { rr: 1, rro: 1, global: 1 }, + 645: { rr: 1, rro: 1, global: 1 }, + 646: { rr: 1, rro: 1, global: 1 }, + 647: { rr: 1, rro: 1, global: 1 }, + 648: { rr: 1, rro: 1, global: 1 }, + 649: { rr: 1, rro: 1, global: 1 }, + 650: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 651: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 652: { global: 1 }, + 653: { global: 1 }, + 654: { global: 1 }, + 655: { global: 1 }, + 656: { global: 1 }, + 657: { global: 1 }, + 658: { global: 1 }, + 659: { global: 1 }, + 660: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 661: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 662: { shop: 1, global: 1 }, + 663: { global: 1 }, + 664: { global: 1 }, + 665: { global: 1 }, + 666: { global: 1 }, + 667: { global: 1 }, + 668: { rr: 1, rro: 1, global: 1 }, + 669: { rr: 1, rro: 1, global: 1 }, + 670: { rr: 1, rro: 1, global: 1 }, + 671: { rr: 1, rro: 1, global: 1 }, + 672: { rr: 1, rro: 1, global: 1 }, + 673: { rr: 1, rro: 1, global: 1 }, + 674: { rr: 1, rro: 1, global: 1 }, + 675: { rr: 1, rro: 1, global: 1 }, + 676: { rr: 1, rro: 1, global: 1 }, + 677: { rr: 1, rro: 1, global: 1 }, + 678: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 679: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 680: { global: 1 }, + 681: { global: 1 }, + 682: { global: 1 }, + 683: { global: 1 }, + 684: { global: 1 }, + 685: { global: 1 }, + 686: { shop: 1 }, + 687: { global: 1 }, + 688: { global: 1 }, + 689: { global: 1 }, + 690: { global: 1 }, + 691: { global: 1 }, + 692: { global: 1 }, + 693: { global: 1 }, + 694: { global: 1 }, + 695: { global: 1 }, + 696: { global: 1 }, + 697: { global: 1 }, + 698: { global: 1 }, + 699: { global: 1 }, + 700: { global: 1 }, + 701: { global: 1 }, + 702: { global: 1 }, + 703: { global: 1 }, + 704: { global: 1 }, + 705: { global: 1 }, + 706: { global: 1 }, + 707: { global: 1 }, + 708: { global: 1 }, + 709: { global: 1 }, + 710: { global: 1, rr: 1, rro: 1, lrr: 1 }, + 711: { global: 1, rr: 1, rro: 1, lrr: 1 }, + 712: { global: 1 }, + 713: { global: 1 }, + 714: { global: 1 }, + 715: { global: 1 }, + 716: { global: 1 }, + 717: { rr: 1, rro: 1, global: 1 }, + 718: { rr: 1, rro: 1, global: 1 }, + 719: { rr: 1, rro: 1, global: 1 }, + 720: { rr: 1, rro: 1, global: 1 }, + 721: { global: 1 }, + 722: { global: 1 }, + 723: { global: 1 }, + 724: { global: 1 }, + 725: { global: 1, rr: 1, rro: 1, lrr: 1 }, + 726: { global: 1, rr: 1, rro: 1, lrr: 1 }, + 727: { special: 1, shop: 1, global: 1 }, + 728: { global: 1 }, + 729: { global: 1 }, + 730: { global: 1 }, + 731: { global: 1 }, + 732: { global: 1 }, + 733: { global: 1 }, + 734: { global: 1 }, + 735: { global: 1 }, + 736: { global: 1 }, + 737: { global: 1 }, + 738: { global: 1 }, + 739: { global: 1 }, + 740: { global: 1 }, + 741: { global: 1 }, + 742: { global: 1 }, + 743: { global: 1 }, + 744: { rr: 1, rro: 1, lrr: 1 }, + 745: { rr: 1, rro: 1, lrr: 1 }, + 746: { promo: 1, shop: 1, global: 1 }, + 747: { rr: 1, rro: 1, global: 1 }, + 748: { rr: 1, rro: 1, global: 1 }, + 749: { rr: 1, rro: 1, global: 1 }, + 750: { rr: 1, rro: 1, global: 1 }, + 751: { rr: 1, rro: 1, global: 1 }, + 752: { rr: 1, rro: 1, global: 1 }, + 753: { rr: 1, rro: 1, global: 1 }, + 754: { rr: 1, rro: 1, global: 1 }, + 755: { rr: 1, rro: 1, global: 1 }, + 756: { rr: 1, rro: 1, global: 1 }, + 757: { rr: 1, rro: 1, global: 1 }, + 758: { rr: 1, rro: 1, global: 1 }, + 759: { rr: 1, rro: 1, global: 1 }, + 760: { rr: 1, rro: 1, global: 1 }, + 761: { global: 1 }, + 762: { global: 1 }, + 763: { global: 1 }, + 764: { global: 1 }, + 765: { global: 1 }, + 766: { global: 1 }, + 767: { global: 1 }, + 768: { global: 1 }, + 769: { global: 1 }, + 770: { global: 1 }, + 771: { global: 1 }, + 772: { global: 1 }, + 773: { global: 1 }, + 774: { global: 1 }, + 775: { global: 1 }, + 776: { global: 1 }, + 777: { global: 1 }, + 778: { global: 1 }, + 779: { global: 1 }, + 780: { global: 1 }, + 781: { global: 1 }, + 782: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 783: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 784: { rr: 1, rro: 1, global: 1 }, + 785: { rr: 1, rro: 1, global: 1 }, + 786: { rr: 1, rro: 1, global: 1 }, + 787: { rr: 1, rro: 1, global: 1 }, + 788: { rr: 1, rro: 1, global: 1 }, + 789: { rr: 1, rro: 1, global: 1 }, + 790: { rr: 1, rro: 1, global: 1 }, + 791: { rr: 1, rro: 1, global: 1 }, + 792: { rr: 1, rro: 1, global: 1 }, + 793: { rr: 1, rro: 1, global: 1 }, + 794: { global: 1 }, + 795: { global: 1 }, + 796: { global: 1 }, + 797: { global: 1 }, + 798: { global: 1 }, + 799: { global: 1 }, + 800: { global: 1 }, + 801: { rr: 1, rro: 1, lrr: 1 }, + 802: { rr: 1, rro: 1, lrr: 1 }, + 803: { global: 1 }, + 804: { global: 1 }, + 805: { global: 1 }, + 806: { global: 1 }, + 807: { global: 1 }, + 808: { global: 1 }, + 809: { global: 1 }, + 810: { global: 1 }, + 811: { global: 1 }, + 812: { global: 1 }, + 813: { global: 1 }, + 814: { global: 1 }, + 815: { global: 1 }, + 816: { global: 1 }, + 817: { global: 1 }, + 818: { global: 1 }, + 819: { global: 1 }, + 820: { global: 1 }, + 821: { global: 1 }, + 822: { global: 1 }, + 823: { global: 1 }, + 824: { global: 1 }, + 825: { global: 1 }, + 826: { global: 1 }, + 827: { global: 1 }, + 828: { rr: 1, rro: 1, lrr: 1 }, + 829: { rr: 1, rro: 1, lrr: 1 }, + 830: { global: 1 }, + 831: { global: 1 }, + 832: { global: 1 }, + 833: { global: 1 }, + 834: { global: 1 }, + 835: { global: 1 }, + 836: { global: 1 }, + 837: { rr: 1, rro: 1, global: 1 }, + 838: { rr: 1, rro: 1, global: 1 }, + 839: { rr: 1, rro: 1, global: 1 }, + 840: { rr: 1, rro: 1, global: 1 }, + 841: { rr: 1, rro: 1, global: 1 }, + 842: { rr: 1, rro: 1, global: 1 }, + 843: { rr: 1, rro: 1, global: 1 }, + 844: { rr: 1, rro: 1, global: 1 }, + 845: { rr: 1, rro: 1, global: 1 }, + 846: { rr: 1, rro: 1, global: 1 }, + 847: { global: 1 }, + 848: { global: 1 }, + 849: { global: 1 }, + 850: { global: 1 }, + 851: { global: 1 }, + 852: { global: 1 }, + 853: { global: 1 }, + 854: { global: 1 }, + 855: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 856: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 857: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 858: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 859: { global: 1 }, + 860: { global: 1 }, + 861: { global: 1 }, + 862: { global: 1 }, + 863: { special: 1, global: 1, shop: 1 }, + 864: { global: 1 }, + 865: { global: 1 }, + 866: { global: 1 }, + 867: { global: 1 }, + 868: { global: 1 }, + 869: { rr: 1, rro: 1, global: 1 }, + 870: { rr: 1, rro: 1, global: 1 }, + 871: { rr: 1, rro: 1, global: 1 }, + 872: { rr: 1, rro: 1, global: 1 }, + 873: { rr: 1, rro: 1, global: 1 }, + 874: { rr: 1, rro: 1, global: 1 }, + 875: { rr: 1, rro: 1, global: 1 }, + 876: { rr: 1, rro: 1, global: 1 }, + 877: { rr: 1, rro: 1, global: 1 }, + 878: { rr: 1, rro: 1, global: 1 }, + 879: { rr: 1, rro: 1, global: 1 }, + 880: { rr: 1, rro: 1, global: 1 }, + 881: { global: 1 }, + 882: { global: 1 }, + 883: { global: 1 }, + 884: { global: 1 }, + 885: { global: 1 }, + 886: { global: 1 }, + 887: { global: 1 }, + 888: { global: 1 }, + 889: { global: 1 }, + 890: { global: 1 }, + 891: { global: 1 }, + 892: { global: 1 }, + 893: { global: 1 }, + 894: { global: 1 }, + 895: { special: 1, global: 1 }, + 896: { special: 1, global: 1 }, + 897: { global: 1 }, + 898: { global: 1 }, + 899: { global: 1 }, + 900: { global: 1 }, + 901: { global: 1 }, + 902: { global: 1 }, + 903: { global: 1 }, + 904: { global: 1 }, + 905: { rr: 1, rro: 1, global: 1 }, + 906: { rr: 1, rro: 1, global: 1 }, + 907: { rr: 1, rro: 1, global: 1 }, + 908: { rr: 1, rro: 1, global: 1 }, + 909: { rr: 1, rro: 1, global: 1 }, + 910: { rr: 1, rro: 1, global: 1 }, + 911: { rr: 1, rro: 1, global: 1 }, + 912: { rr: 1, rro: 1, global: 1 }, + 913: { rr: 1, rro: 1, global: 1 }, + 914: { rr: 1, rro: 1, global: 1 }, + 915: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 916: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 917: { global: 1 }, + 918: { global: 1 }, + 919: { global: 1 }, + 920: { global: 1 }, + 921: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 922: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 923: { global: 1 }, + 924: { global: 1 }, + 925: { global: 1 }, + 926: { global: 1 }, + 927: { global: 1 }, + 928: { global: 1 }, + 929: { global: 1 }, + 930: { global: 1 }, + 931: { global: 1 }, + 932: { global: 1 }, + 933: { global: 1 }, + 934: { rr: 1, rro: 1, global: 1 }, + 935: { rr: 1, rro: 1, global: 1 }, + 936: { rr: 1, rro: 1, global: 1 }, + 937: { rr: 1, rro: 1, global: 1 }, + 938: { rr: 1, rro: 1, global: 1 }, + 939: { rr: 1, rro: 1, global: 1 }, + 940: { rr: 1, rro: 1, global: 1 }, + 941: { rr: 1, rro: 1, global: 1 }, + 942: { rr: 1, rro: 1, global: 1 }, + 943: { rr: 1, rro: 1, global: 1 }, + 944: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 945: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 946: { global: 1 }, + 947: { global: 1 }, + 948: { global: 1 }, + 949: { global: 1 }, + 950: { global: 1 }, + 951: { global: 1 }, + 952: { global: 1 }, + 953: { global: 1 }, + 954: { global: 1 }, + 955: { global: 1 }, + 956: { global: 1 }, + 957: { global: 1 }, + 958: { global: 1 }, + 959: { global: 1 }, + 960: { global: 1 }, + 961: { global: 1 }, + 962: { global: 1 }, + 963: { global: 1 }, + 964: { global: 1 }, + 965: { global: 1 }, + 966: { global: 1 }, + 967: { global: 1 }, + 968: { global: 1 }, + 969: { global: 1 }, + 970: { global: 1 }, + 971: { global: 1 }, + 972: { global: 1 }, + 973: { global: 1 }, + 974: { global: 1 }, + 975: { rr: 1, rro: 1, lrr: 1 }, + 976: { rr: 1, rro: 1, lrr: 1 }, + 977: { global: 1 }, + 978: { global: 1 }, + 979: { global: 1 }, + 980: { global: 1 }, + 981: { global: 1 }, + 982: { global: 1 }, + 983: { global: 1 }, + 984: { global: 1 }, + 985: { global: 1 }, + 986: { global: 1 }, + 987: { global: 1 }, + 988: { global: 1 }, + 989: { global: 1 }, + 990: { rr: 1, rro: 1, global: 1 }, + 991: { rr: 1, rro: 1, global: 1 }, + 992: { rr: 1, rro: 1, global: 1 }, + 993: { rr: 1, rro: 1, global: 1 }, + 994: { rr: 1, rro: 1, global: 1 }, + 995: { rr: 1, rro: 1, global: 1 }, + 996: { rr: 1, rro: 1, global: 1 }, + 997: { rr: 1, rro: 1, global: 1 }, + 998: { rr: 1, rro: 1, global: 1 }, + 999: { rr: 1, rro: 1, global: 1 }, + 1000: { rr: 1, rro: 1, global: 1 }, + 1001: { rr: 1, rro: 1, global: 1 }, + 1002: { global: 1 }, + 1003: { global: 1 }, + 1004: { global: 1 }, + 1005: { global: 1 }, + 1006: { global: 1 }, + 1007: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1008: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1009: { special: 1 }, + 1010: { global: 1 }, + 1011: { global: 1 }, + 1012: { global: 1 }, + 1013: { global: 1 }, + 1014: { global: 1 }, + 1015: { global: 1 }, + 1016: { global: 1 }, + 1017: { global: 1 }, + 1018: { global: 1 }, + 1019: { global: 1 }, + 1020: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1021: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1022: { special: 1, global: 1, shop: 1 }, + 1023: { global: 1 }, + 1024: { rr: 1, rro: 1, global: 1 }, + 1025: { rr: 1, rro: 1, global: 1 }, + 1026: { rr: 1, rro: 1, global: 1 }, + 1027: { rr: 1, rro: 1, global: 1 }, + 1028: { rr: 1, rro: 1, global: 1 }, + 1029: { rr: 1, rro: 1, global: 1 }, + 1030: { rr: 1, rro: 1, global: 1 }, + 1031: { rr: 1, rro: 1, global: 1 }, + 1032: { rr: 1, rro: 1, global: 1 }, + 1033: { rr: 1, rro: 1, global: 1 }, + 1034: { rr: 1, rro: 1, global: 1 }, + 1035: { rr: 1, rro: 1, global: 1 }, + 1036: { global: 1 }, + 1037: { global: 1 }, + 1038: { global: 1 }, + 1039: { global: 1 }, + 1040: { global: 1 }, + 1041: { global: 1 }, + 1042: { global: 1 }, + 1043: { global: 1 }, + 1044: { rr: 1, rro: 1, global: 1 }, + 1045: { rr: 1, rro: 1, global: 1 }, + 1046: { global: 1 }, + 1047: { global: 1 }, + 1048: { global: 1 }, + 1049: { global: 1 }, + 1050: { global: 1 }, + 1051: { global: 1 }, + 1052: { global: 1 }, + 1053: { rr: 1, rro: 1, lrr: 1 }, + 1054: { rr: 1, rro: 1, lrr: 1 }, + 1055: { global: 1 }, + 1056: { global: 1 }, + 1057: { global: 1 }, + 1058: { global: 1 }, + 1059: { global: 1 }, + 1060: { global: 1 }, + 1061: { global: 1 }, + 1062: { global: 1 }, + 1063: { global: 1 }, + 1064: { global: 1 }, + 1065: { global: 1 }, + 1066: { global: 1 }, + 1067: { global: 1 }, + 1068: { global: 1 }, + 1069: { global: 1 }, + 1070: { global: 1 }, + 1071: { global: 1 }, + 1072: { global: 1 }, + 1073: { global: 1 }, + 1074: { rr: 1, rro: 1, global: 1 }, + 1075: { rr: 1, rro: 1, global: 1 }, + 1076: { rr: 1, rro: 1, global: 1 }, + 1077: { rr: 1, rro: 1, global: 1 }, + 1078: { rr: 1, rro: 1, global: 1 }, + 1079: { rr: 1, rro: 1, global: 1 }, + 1080: { rr: 1, rro: 1, global: 1 }, + 1081: { rr: 1, rro: 1, global: 1 }, + 1082: { rr: 1, rro: 1, global: 1 }, + 1083: { rr: 1, rro: 1, global: 1 }, + 1084: { rr: 1, rro: 1, global: 1 }, + 1085: { rr: 1, rro: 1, global: 1 }, + 1086: { global: 1 }, + 1087: { global: 1 }, + 1088: { global: 1 }, + 1089: { global: 1 }, + 1090: { global: 1 }, + 1091: { global: 1 }, + 1092: { rr: 1, rro: 1, lrr: 1 }, + 1093: { rr: 1, rro: 1, lrr: 1 }, + 1094: { global: 1 }, + 1095: { global: 1 }, + 1096: { global: 1 }, + 1097: { global: 1 }, + 1098: { global: 1 }, + 1099: { rr: 1, rro: 1, lrr: 1 }, + 1100: { rr: 1, rro: 1, lrr: 1 }, + 1101: { global: 1 }, + 1102: { global: 1 }, + 1103: { global: 1 }, + 1104: { global: 1 }, + 1105: { global: 1 }, + 1106: { global: 1 }, + 1107: { global: 1 }, + 1108: { global: 1 }, + 1109: { global: 1 }, + 1110: { global: 1 }, + 1111: { global: 1 }, + 1112: { global: 1 }, + 1113: { global: 1 }, + 1114: { rr: 1, rro: 1, global: 1 }, + 1115: { rr: 1, rro: 1, global: 1 }, + 1116: { rr: 1, rro: 1, global: 1 }, + 1117: { rr: 1, rro: 1, global: 1 }, + 1118: { rr: 1, rro: 1, global: 1 }, + 1119: { rr: 1, rro: 1, global: 1 }, + 1120: { rr: 1, rro: 1, global: 1 }, + 1121: { rr: 1, rro: 1, global: 1 }, + 1122: { rr: 1, rro: 1, global: 1 }, + 1123: { rr: 1, rro: 1, global: 1 }, + 1124: { rr: 1, rro: 1, global: 1 }, + 1125: { rr: 1, rro: 1, global: 1 }, + 1126: { rr: 1, rro: 1, global: 1 }, + 1127: { rr: 1, rro: 1, global: 1 }, + 1128: { rr: 1, rro: 1, global: 1 }, + 1129: { rr: 1, rro: 1, global: 1 }, + 1130: { rr: 1, rro: 1, global: 1 }, + 1131: { rr: 1, rro: 1, global: 1 }, + 1132: { rr: 1, rro: 1, global: 1 }, + 1133: { rr: 1, rro: 1, global: 1 }, + 1134: { rr: 1, rro: 1, lrr: 1 }, + 1135: { rr: 1, rro: 1, lrr: 1 }, + 1136: { global: 1 }, + 1137: { global: 1 }, + 1138: { global: 1 }, + 1139: { global: 1 }, + 1140: { global: 1 }, + 1141: { global: 1 }, + 1146: { global: 1 }, + 1147: { global: 1 }, + 1148: { global: 1 }, + 1149: { global: 1 }, + 1150: { global: 1 }, + 1151: { global: 1 }, + 1152: { global: 1 }, + 1153: { global: 1 }, + 1154: { global: 1 }, + 1155: { global: 1 }, + 1156: { global: 1 }, + 1157: { global: 1 }, + 1158: { global: 1 }, + 1159: { global: 1 }, + 1160: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1161: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1162: { global: 1 }, + 1163: { global: 1 }, + 1164: { global: 1 }, + 1165: { global: 1 }, + 1166: { global: 1 }, + 1167: { global: 1 }, + 1168: { global: 1 }, + 1169: { global: 1 }, + 1170: { global: 1 }, + 1171: { global: 1 }, + 1172: { rr: 1, rro: 1, global: 1 }, + 1173: { rr: 1, rro: 1, global: 1 }, + 1174: { rr: 1, rro: 1, global: 1 }, + 1175: { rr: 1, rro: 1, global: 1 }, + 1176: { rr: 1, rro: 1, global: 1 }, + 1177: { rr: 1, rro: 1, global: 1 }, + 1178: { shop: 1, global: 1 }, + 1179: { shop: 1, global: 1 }, + 1180: { global: 1 }, + 1181: { rr: 1, rro: 1, global: 1 }, + 1182: { rr: 1, rro: 1, global: 1 }, + 1183: { rr: 1, rro: 1, global: 1 }, + 1184: { rr: 1, rro: 1, global: 1 }, + 1185: { rr: 1, rro: 1, global: 1 }, + 1186: { rr: 1, rro: 1, global: 1 }, + 1187: { rr: 1, rro: 1, global: 1 }, + 1188: { rr: 1, rro: 1, global: 1 }, + 1189: { rr: 1, rro: 1, global: 1 }, + 1190: { rr: 1, rro: 1, global: 1 }, + 1191: { rr: 1, rro: 1, global: 1 }, + 1192: { rr: 1, rro: 1, global: 1 }, + 1193: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1194: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1195: { global: 1 }, + 1196: { global: 1 }, + 1198: { global: 1 }, + 1199: { global: 1 }, + 1200: { global: 1 }, + 1201: { global: 1 }, + 1202: { global: 1 }, + 1203: { global: 1 }, + 1204: { global: 1 }, + 1205: { global: 1 }, + 1206: { global: 1 }, + 1207: { rr: 1, rro: 1, global: 1 }, + 1208: { rr: 1, rro: 1, global: 1 }, + 1209: { rr: 1, rro: 1, global: 1 }, + 1210: { rr: 1, rro: 1, global: 1 }, + 1211: { rr: 1, rro: 1, global: 1 }, + 1212: { rr: 1, rro: 1, global: 1 }, + 1213: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1214: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1215: { global: 1 }, + 1216: { global: 1 }, + 1217: { global: 1 }, + 1218: { global: 1 }, + 1219: { global: 1 }, + 1220: { global: 1 }, + 1223: { global: 1 }, + 1224: { global: 1 }, + 1225: { global: 1 }, + 1226: { global: 1 }, + 1227: { global: 1 }, + 1228: { global: 1 }, + 1229: { rr: 1, rro: 1, global: 1 }, + 1230: { rr: 1, rro: 1, global: 1 }, + 1231: { rr: 1, rro: 1, global: 1 }, + 1232: { rr: 1, rro: 1, global: 1 }, + 1233: { rr: 1, rro: 1, global: 1 }, + 1234: { rr: 1, rro: 1, global: 1 }, + 1235: { rr: 1, rro: 1, global: 1 }, + 1236: { rr: 1, rro: 1, global: 1 }, + 1237: { rr: 1, rro: 1, global: 1 }, + 1238: { rr: 1, rro: 1, global: 1 }, + 1239: { rr: 1, rro: 1, global: 1 }, + 1240: { rr: 1, rro: 1, global: 1 }, + 1241: { global: 1 }, + 1242: { global: 1 }, + 1243: { global: 1 }, + 1244: { global: 1 }, + 1248: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1245: { special: 1, global: 1 }, + 1246: { special: 1, global: 1 }, + 1247: { special: 1, global: 1 }, + 1249: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1250: { global: 1 }, + 1251: { global: 1 }, + 1254: { global: 1 }, + 1255: { global: 1 }, + 1256: { global: 1 }, + 1257: { global: 1 }, + 1258: { global: 1 }, + 1259: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1260: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1261: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1262: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1263: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1264: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1265: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1266: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1267: { rr: 1, rro: 1, global: 1 }, + 1268: { rr: 1, rro: 1, global: 1 }, + 1269: { rr: 1, rro: 1, global: 1 }, + 1270: { rr: 1, rro: 1, global: 1 }, + 1271: { rr: 1, rro: 1, global: 1 }, + 1272: { rr: 1, rro: 1, global: 1 }, + 1273: { rr: 1, rro: 1, global: 1 }, + 1274: { rr: 1, rro: 1, global: 1 }, + 1275: { rr: 1, rro: 1, global: 1 }, + 1276: { rr: 1, rro: 1, global: 1 }, + 1277: { rr: 1, rro: 1, global: 1 }, + 1278: { rr: 1, rro: 1, global: 1 }, + 1279: { global: 1 }, + 1280: { global: 1 }, + 1281: { global: 1 }, + 1282: { global: 1 }, + 1283: { global: 1 }, + 1284: { shop: 1, global: 1 }, + 1285: { shop: 1, global: 1 }, + 1286: { global: 1 }, + 1287: { global: 1 }, + 1288: { global: 1 }, + 1289: { global: 1 }, + 1290: { global: 1 }, + 1295: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1296: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1297: { global: 1 }, + 1298: { global: 1 }, + 1299: { global: 1 }, + 1300: { global: 1 }, + 1301: { global: 1 }, + 1302: { global: 1 }, + 1303: { global: 1 }, + 1304: { global: 1 }, + 1305: { global: 1 }, + 1306: { global: 1 }, + 1307: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1308: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1309: { global: 1 }, + 1310: { global: 1 }, + 1313: { rr: 1, rro: 1, global: 1 }, + 1314: { rr: 1, rro: 1, global: 1 }, + 1315: { rr: 1, rro: 1, global: 1 }, + 1316: { rr: 1, rro: 1, global: 1 }, + 1317: { rr: 1, rro: 1, global: 1 }, + 1318: { rr: 1, rro: 1, global: 1 }, + 1319: { rr: 1, rro: 1, global: 1 }, + 1320: { rr: 1, rro: 1, global: 1 }, + 1321: { rr: 1, rro: 1, global: 1 }, + 1322: { rr: 1, rro: 1, global: 1 }, + 1323: { rr: 1, rro: 1, global: 1 }, + 1324: { rr: 1, rro: 1, global: 1 }, + 1325: { global: 1 }, + 1326: { global: 1 }, + 1327: { global: 1 }, + 1328: { global: 1 }, + 1329: { global: 1 }, + 1330: { global: 1 }, + 1331: { global: 1 }, + 1332: { global: 1 }, + 1333: { global: 1 }, + 1334: { global: 1 }, + 1335: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1336: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1337: { global: 1 }, + 1338: { global: 1 }, + 1342: { global: 1 }, + 1343: { global: 1 }, + 1344: { global: 1 }, + 1345: { global: 1 }, + 1346: { global: 1 }, + 1347: { global: 1 }, + 1348: { global: 1 }, + 1349: { global: 1 }, + 1350: { global: 1 }, + 1351: { global: 1 }, + 1352: { global: 1 }, + 1353: { global: 1 }, + 1354: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1355: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1356: { global: 1 }, + 1357: { global: 1 }, + 1358: { global: 1 }, + 1359: { global: 1 }, + 1360: { special: 1 }, + 1361: { rr: 1, rro: 1, global: 1 }, + 1362: { rr: 1, rro: 1, global: 1 }, + 1363: { rr: 1, rro: 1, global: 1 }, + 1364: { rr: 1, rro: 1, global: 1 }, + 1365: { rr: 1, rro: 1, global: 1 }, + 1366: { rr: 1, rro: 1, global: 1 }, + 1367: { rr: 1, rro: 1, global: 1 }, + 1368: { rr: 1, rro: 1, global: 1 }, + 1369: { rr: 1, rro: 1, global: 1 }, + 1370: { rr: 1, rro: 1, global: 1 }, + 1371: { shop: 1, global: 1, global: 1 }, + 1372: { shop: 1, global: 1, global: 1 }, + 1373: { global: 1 }, + 1374: { global: 1 }, + 1377: { global: 1 }, + 1378: { global: 1 }, + 1379: { global: 1 }, + 1380: { global: 1 }, + 1381: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1382: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1383: { global: 1 }, + 1384: { global: 1 }, + 1385: { global: 1 }, + 1386: { global: 1 }, + 1387: { global: 1 }, + 1388: { global: 1 }, + 1389: { global: 1 }, + 1390: { rr: 1, rro: 1, global: 1 }, + 1391: { rr: 1, rro: 1, global: 1 }, + 1392: { global: 1 }, + 1393: { global: 1 }, + 1394: { rr: 1, rro: 1, lrr: 1, }, + 1395: { rr: 1, rro: 1, lrr: 1, }, + 1396: { global: 1 }, + 1397: { global: 1 }, + 1398: { global: 1 }, + 1399: { global: 1 }, + 1400: { global: 1 }, + 1401: { global: 1 }, + 1403: { rr: 1, rro: 1, global: 1 }, + 1404: { rr: 1, rro: 1, global: 1 }, + 1405: { rr: 1, rro: 1, global: 1 }, + 1406: { rr: 1, rro: 1, global: 1 }, + 1407: { rr: 1, rro: 1, global: 1 }, + 1408: { rr: 1, rro: 1, global: 1 }, + 1409: { rr: 1, rro: 1, global: 1 }, + 1410: { rr: 1, rro: 1, global: 1 }, + 1411: { rr: 1, rro: 1, global: 1 }, + 1412: { rr: 1, rro: 1, global: 1 }, + 1413: { rr: 1, rro: 1, global: 1 }, + 1414: { shop: 1 }, + 1415: { global: 1 }, + 1416: { global: 1 }, + 1417: { global: 1 }, + 1418: { global: 1 }, + 1419: { rr: 1, rro: 1, lrr: 1, }, + 1420: { rr: 1, rro: 1, lrr: 1, }, + 1423: { global: 1 }, + 1425: { global: 1 }, + 1426: { global: 1 }, + 1427: { global: 1 }, + 1428: { global: 1 }, + 1429: { rr: 1, rro: 1, lrr: 1, }, + 1430: { rr: 1, rro: 1, lrr: 1, }, + 1433: { rr: 1, rro: 1, global: 1 }, + 1434: { rr: 1, rro: 1, global: 1 }, + 1435: { rr: 1, rro: 1, global: 1 }, + 1436: { rr: 1, rro: 1, global: 1 }, + 1437: { rr: 1, rro: 1, global: 1 }, + 1438: { rr: 1, rro: 1, global: 1 }, + 1439: { rr: 1, rro: 1, global: 1 }, + 1440: { rr: 1, rro: 1, global: 1 }, + 1441: { rr: 1, rro: 1, global: 1 }, + 1442: { rr: 1, rro: 1, global: 1 }, + 1443: { rr: 1, rro: 1, global: 1 }, + 1444: { rr: 1, rro: 1, global: 1 }, + 1445: { rr: 1, rro: 1, global: 1 }, + 1446: { global: 1 }, + 1447: { global: 1 }, + 1448: { global: 1 }, + 1449: { global: 1 }, + 1450: { global: 1 }, + 1451: { global: 1 }, + 1452: { global: 1 }, + 1453: { rr: 1, rro: 1, lrr: 1, }, + 1454: { rr: 1, rro: 1, lrr: 1, }, + 1455: { global: 1 }, + 1456: { global: 1 }, + 1457: { global: 1 }, + 1458: { global: 1 }, + 1459: { global: 1 }, + 1460: { global: 1 }, + 1461: { special: 1 }, + 1466: { rr: 1, rro: 1, lrr: 1 }, + 1467: { rr: 1, rro: 1, lrr: 1 }, + 1468: { global: 1 }, + 1469: { global: 1 }, + 1470: { global: 1 }, + 1471: { global: 1 }, + 1472: { rr: 1, rro: 1, global: 1 }, + 1473: { rr: 1, rro: 1, global: 1 }, + 1474: { rr: 1, rro: 1, global: 1 }, + 1475: { rr: 1, rro: 1, global: 1 }, + 1476: { rr: 1, rro: 1, global: 1 }, + 1477: { rr: 1, rro: 1, global: 1 }, + 1478: { rr: 1, rro: 1, global: 1 }, + 1479: { rr: 1, rro: 1, global: 1 }, + 1480: { rr: 1, rro: 1, global: 1 }, + 1481: { rr: 1, rro: 1, global: 1 }, + 1482: { rr: 1, rro: 1, global: 1 }, + 1483: { rr: 1, rro: 1, global: 1 }, + 1484: { shop: 1, global: 1 }, + 1485: { shop: 1, global: 1 }, + 1486: { global: 1 }, + 1487: { global: 1 }, + 1492: { rr: 1, rro: 1, global: 1 }, + 1493: { global: 1 }, + 1494: { global: 1 }, + 1495: { global: 1 }, + 1496: { global: 1 }, + 1497: { global: 1 }, + 1498: { global: 1 }, + 1499: { global: 1 }, + 1500: { global: 1 }, + 1501: { global: 1 }, + 1502: { global: 1 }, + 1503: { global: 1 }, + 1504: { global: 1 }, + 1505: { global: 1 }, + 1506: { global: 1 }, + 1509: { global: 1 }, + 1510: { global: 1 }, + 1511: { global: 1 }, + 1512: { global: 1 }, + 1513: { rr: 1, rro: 1, lrr: 1 }, + 1514: { rr: 1, rro: 1, lrr: 1 }, + 1517: { global: 1 }, + 1518: { global: 1 }, + 1519: { global: 1 }, + 1520: { global: 1 }, + 1521: { global: 1 }, + 1522: { global: 1 }, + 1523: { rr: 1, rro: 1, lrr: 1 }, + 1524: { rr: 1, rro: 1, lrr: 1 }, + 1525: { global: 1 }, + 1529: { global: 1 }, + 1530: { global: 1 }, + 1531: { rr: 1, rro: 1, global: 1 }, + 1532: { rr: 1, rro: 1, global: 1 }, + 1533: { rr: 1, rro: 1, global: 1 }, + 1534: { rr: 1, rro: 1, global: 1 }, + 1535: { rr: 1, rro: 1, global: 1 }, + 1536: { rr: 1, rro: 1, global: 1 }, + 1537: { rr: 1, rro: 1, global: 1 }, + 1538: { rr: 1, rro: 1, global: 1 }, + 1539: { rr: 1, rro: 1, global: 1 }, + 1540: { rr: 1, rro: 1, global: 1 }, + 1541: { rr: 1, rro: 1, global: 1 }, + 1542: { rr: 1, rro: 1, global: 1 }, + 1543: { rr: 1, rro: 1, global: 1 }, + 1546: { global: 1 }, + 1547: { global: 1 }, + 1548: { global: 1 }, + 1549: { global: 1 }, + 1550: { global: 1 }, + 1551: { global: 1 }, + 1556: { global: 1 }, + 1557: { global: 1 }, + 1558: { global: 1 }, + 1559: { global: 1 }, + 1560: { global: 1 }, + 1561: { global: 1 }, + 1562: { global: 1 }, + 1563: { global: 1 }, + 1564: { global: 1 }, + 1565: { global: 1 }, + 1566: { global: 1 }, + 1567: { rr: 1, rro: 1, lrr: 1 }, + 1568: { rr: 1, rro: 1, lrr: 1 }, + 1569: { special: 1, global: 1 }, + 1570: { rr: 1, rro: 1, global: 1 }, + 1571: { rr: 1, rro: 1, global: 1 }, + 1572: { rr: 1, rro: 1, global: 1 }, + 1573: { rr: 1, rro: 1, global: 1 }, + 1574: { rr: 1, rro: 1, global: 1 }, + 1575: { rr: 1, rro: 1, global: 1 }, + 1576: { rr: 1, rro: 1, global: 1 }, + 1577: { rr: 1, rro: 1, global: 1 }, + 1578: { rr: 1, rro: 1, global: 1 }, + 1579: { rr: 1, rro: 1, global: 1 }, + 1583: { global: 1 }, + 1584: { global: 1 }, + 1587: { rr: 1, rro: 1 }, + 1588: { rr: 1, rro: 1 }, + 1589: { rr: 1, rro: 1, lrr: 1 }, + 1590: { rr: 1, rro: 1, lrr: 1 }, + 1591: { rr: 1, rro: 1, lrr: 1 }, + 1592: { rr: 1, rro: 1, lrr: 1 }, + 1593: { rr: 1, rro: 1 }, + 1604: { global: 1 }, + 1605: { global: 1 }, + 1609: { rr: 1, rro: 1 }, + 1610: { rr: 1, rro: 1 }, + 1611: { rr: 1, rro: 1 }, + 1612: { rr: 1, rro: 1 }, + 1613: { rr: 1, rro: 1 }, + 1614: { rr: 1, rro: 1 }, + 1615: { rr: 1, rro: 1 }, + 1616: { rr: 1, rro: 1 }, + 1617: { rr: 1, rro: 1 }, + 1618: { rr: 1, rro: 1 }, + 1619: { rr: 1, rro: 1 }, + 1620: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1621: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1622: { global: 1 }, + 1623: { global: 1 }, + 1631: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1632: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1633: { global: 1 }, + 1634: { global: 1 }, + 1635: { global: 1 }, + 1636: { global: 1 }, + 1637: { global: 1 }, + 1638: { global: 1 }, + 1639: { global: 1 }, + 1640: { global: 1 }, + 1641: { global: 1 }, + 1642: { global: 1 }, + 1643: { global: 1 }, + 1644: { global: 1 }, + 1645: { global: 1 }, + 1651: { rr: 1, rro: 1, global: 1 }, + 1652: { rr: 1, rro: 1, global: 1 }, + 1653: { rr: 1, rro: 1, global: 1 }, + 1654: { rr: 1, rro: 1, global: 1 }, + 1655: { rr: 1, rro: 1, global: 1 }, + 1656: { rr: 1, rro: 1, global: 1 }, + 1657: { rr: 1, rro: 1, global: 1 }, + 1658: { rr: 1, rro: 1, global: 1 }, + 1659: { rr: 1, rro: 1, global: 1 }, + 1660: { rr: 1, rro: 1, global: 1 }, + 1661: { shop: 1, global: 1 }, + 1662: { shop: 1, global: 1 }, + 1663: { rr: 1, rro: 1 }, + 1664: { rr: 1, rro: 1, lrr: 1 }, + 1665: { rr: 1, rro: 1, lrr: 1 }, + 1668: { global: 1 }, + 1669: { global: 1 }, + 1673: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1674: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1675: { special: 1, global: 1 }, + 1676: { special: 1, global: 1 }, + 1677: { rr: 1, rro: 1, lrr: 1 }, + 1678: { rr: 1, rro: 1, lrr: 1 }, + 1679: { global: 1 }, + 1680: { global: 1 }, + 1681: { rr: 1, rro: 1, global: 1 }, + 1682: { rr: 1, rro: 1, global: 1 }, + 1683: { rr: 1, rro: 1, global: 1 }, + 1684: { rr: 1, rro: 1, global: 1 }, + 1685: { rr: 1, rro: 1, global: 1 }, + 1686: { rr: 1, rro: 1, global: 1 }, + 1687: { rr: 1, rro: 1, global: 1 }, + 1688: { rr: 1, rro: 1, global: 1 }, + 1697: { rr: 1, rro: 1, global: 1 }, + 1698: { rr: 1, rro: 1, global: 1 }, + 1699: { rr: 1, rro: 1, global: 1 }, + 1700: { rr: 1, rro: 1, global: 1 }, + 1701: { rr: 1, rro: 1, global: 1 }, + 1702: { rr: 1, rro: 1, global: 1 }, + 1703: { rr: 1, rro: 1, global: 1 }, + 1704: { rr: 1, rro: 1, global: 1 }, + 1705: { rr: 1, rro: 1, global: 1 }, + 1706: { rr: 1, rro: 1, global: 1 }, + 1707: { rr: 1, rro: 1 }, + 1712: { rr: 1, rro: 1, lrr: 1 }, + 1713: { rr: 1, rro: 1, lrr: 1 }, + 1720: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1721: { rr: 1, rro: 1, lrr: 1, global: 1 }, + 1726: { global: 1 }, + 1727: { global: 1 }, + 1728: { special: 1 }, + 1729: { special: 1 }, + 1730: { rr: 1, rro: 1, lrr: 1 }, + 1731: { rr: 1, rro: 1, lrr: 1 }, + 1740: { rr: 1, rro: 1, global: 1 }, + 1741: { rr: 1, rro: 1, global: 1 }, + 1742: { rr: 1, rro: 1, global: 1 }, + 1743: { rr: 1, rro: 1, global: 1 }, + 1744: { rr: 1, rro: 1, global: 1 }, + 1745: { rr: 1, rro: 1, global: 1 }, + 1746: { rr: 1, rro: 1, global: 1 }, + 1747: { rr: 1, rro: 1, global: 1 }, + 1748: { rr: 1, rro: 1, global: 1 }, + 1749: { rr: 1, rro: 1, global: 1 }, + 1750: { rr: 1, rro: 1, global: 1 }, + 1751: { rr: 1, rro: 1, global: 1 }, + 1752: { rr: 1, rro: 1 }, + 1753: { rr: 1, rro: 1 }, + 1754: { rr: 1, rro: 1 }, + 1755: { rr: 1, rro: 1 }, + 1756: { rr: 1, rro: 1 }, + 1757: { rr: 1, rro: 1 }, + 1758: { rr: 1, rro: 1 }, + 1759: { rr: 1, rro: 1 }, + 1760: { rr: 1, rro: 1 }, + 1761: { rr: 1, rro: 1 }, + 1762: { rr: 1, rro: 1, global: 1 }, + 1763: { rr: 1, rro: 1, global: 1 }, + 1764: { rr: 1, rro: 1 }, + 1769: { rr: 1, rro: 1, lrr: 1 }, + 1770: { rr: 1, rro: 1, lrr: 1 }, + 1777: { rr: 1, rro: 1, lrr: 1 }, + 1778: { rr: 1, rro: 1, lrr: 1 }, + 1793: { rr: 1, rro: 1 }, + 1794: { rr: 1, rro: 1 }, + 1795: { rr: 1, rro: 1 }, + 1796: { rr: 1, rro: 1 }, + 1797: { rr: 1, rro: 1 }, + 1798: { rr: 1, rro: 1 }, + 1799: { rr: 1, rro: 1 }, + 1800: { rr: 1, rro: 1 }, + 1801: { rr: 1, rro: 1 }, + 1802: { rr: 1, rro: 1 }, + 1803: { rr: 1, rro: 1, lrr: 1 }, + 1804: { rr: 1, rro: 1, lrr: 1 }, + 1805: { rr: 1, rro: 1, lrr: 1 }, + 1806: { rr: 1, rro: 1, lrr: 1 }, + 1813: { special: 1 }, + 1816: { rr: 1, rro: 1 }, + 1821: { shop: 1 }, + 1822: { shop: 1 }, + 1823: { rr: 1, rro: 1, lrr: 1 }, + 1824: { rr: 1, rro: 1, lrr: 1 }, + 1847: { rr: 1, rro: 1 }, + 1848: { rr: 1, rro: 1, lrr: 1 }, + 1849: { rr: 1, rro: 1, lrr: 1 }, + 1850: { rr: 1, rro: 1, lrr: 1 }, + 1851: { rr: 1, rro: 1, lrr: 1 }, + 1858: { rr: 1, rro: 1, lrr: 1 }, + 1859: { rr: 1, rro: 1, lrr: 1 }, + 2000: { global: 1 }, + 2001: { global: 1 }, }; \ No newline at end of file diff --git a/common/data/gw.js b/common/data/gw.js index afdf72025..079636f29 100644 --- a/common/data/gw.js +++ b/common/data/gw.js @@ -1 +1,1863 @@ -window.gw=[2017,2017,2017,2017,2019,2019,2019,2019,2020,2020,2020,2020,2022,2022,2022,2022,2018,2018,2018,2018,2021,2021,2021,2021,2021,2021,2820,2412,2105,2105,2102,2102,2123,2123,2184,2122,2121,2106,2106,2207,2164,2804,2146,2146,2024,2024,2821,2819,2215,2163,2162,2016,2145,2145,2129,2129,2128,2128,2216,2180,2174,2147,2161,2161,1926,1926,2077,2077,2078,2078,2013,2013,2013,2015,2015,2014,2014,1652,1652,1652,1652,1652,1652,2210,2210,2210,2210,2210,1657,1657,1657,1657,1657,1657,1861,1861,1861,1861,1861,1851,1851,1851,1851,1851,2292,2292,2292,2292,2292,2333,2333,2333,2333,2333,1857,1857,1857,1857,2823,2822,2790,2204,2784,2202,2700,2786,2788,2789,2201,2796,2787,2177,2791,2797,2354,2183,2203,2355,2206,2341,2217,2790,2204,2784,2202,2700,2786,2788,2789,2201,2796,2787,2177,2791,2797,2354,2183,2203,2355,2206,2341,2217,2816,2824,2181,2179,2205,2209,2219,2185,2178,2176,2208,2218,2182,2818,2353,2817,2529,2526,2527,2528,2220,2529,2526,2527,2528,2220,3873,3873,3873,3873,3873,2529,2526,2527,2528,2220,3062,3062,3056,3056,3060,3060,3057,3057,3061,3061,3058,3058,3748,3748,3747,3747,3744,4005,4005,4035,4035,4027,4027,4039,4039,4029,4029,4143,4143,2184,2146,2215,4659,4659,4916,4916,4925,4925,4926,4929,4960,4928,4927,4926,4929,4960,4928,4927,5143,5209,5209,4707,4707,4864,4864,4863,4863,4861,4861,4862,4862,5166,5166,5100,5100,5101,5101,2210,1851,2078,2790,2204,2784,2202,2700,2786,2788,2789,2201,2796,2787,2177,2791,2797,2354,2183,2203,2355,2206,2341,2217,5589,5506,5505,5872,5871,5870,5168,5168,5819,5820,5801,5801,5801,5801,5801,5359,5359,5982,5982,5978,5978,5979,5979,5981,5981,5980,5980,6114,6114,6113,6113,6484,6484,6488,6488,6489,6659,6659,6661,6661,6664,6664,6665,6662,6663,6663,6873,6873,6871,6872,7269,7269,7273,7273,7273,7273,7273,7273,7273,7273,7273,7273,7291,7291,7310,7310,7207,7207,7209,7209,7208,7208,7211,7211,7210,7210,7311,7311,7588,7574,7591,7590,7589,7588,7574,7591,7590,7589,7576,7573,7573,7572,7575,7577,7577,7731,7731,7732,7732,8286,8286,8440,8440,8439,8438,8883,8883,8882,8882,8881,8881,8880,8880,8873,8884,8884,8885,8886,7577,9032,9032,9031,9031,9033,9033,9034,9034,9035,9035,8946,9247,9248,9249,3574,3574,3558,9875,9876,9881,9882,9877,9877,9880,10005,10004,10003,10003,10445,10445,10834,10834,10837,10837,10837,10833,10833,9878,9878,11071,11071,11072,11072,11073,11073,11074,11074,11075,11075,11070,11070,11460,3061,3061,11529,11530,11532,11531,11533,11538,11537,11538,11537,11536,11535,11550,11549,11534,11539,11540,11541,11542,11543,11539,11540,11541,11542,11543,11545,11546,11563,11545,11546,11563,11544,11562,11544,11562,11642,11642,11791,11791,11787,11787,11790,11790,11788,11788,11789,11789,11775,11775,11776,11806,11806,11786,11960,11960,12015,12015,11949,11949,11950,11950,11951,11951,11952,11952,11953,11953,11948,11948,12067,12067,11774,11774,11773,11773,12098,12098,12100,12099,12136,12137,12132,12132,12131,12131,12424,12424,12138,12138,12134,12135,12648,12648,12649,12649,12650,12650,12651,12651,12647,12647,12775,12781,12782,12780,12776,12774,12774,12805,12805,12806,12807,12794,12794,12868,12878,12878,12888,12888,13148,13137,13138,13136,13133,13133,13134,13134,13135,13135,13396,13396,13396,13396,13396,13315,13315,13568,13568,13567,13567,13688,13688,13749,13749,13947,13947,13948,13949,14421,14420,14257,14257,14296,4349,4860,6065,5085,5304,6955,5190,7435,5311,6924,6051,6430,6030,14295,14294,14303,14303,14312,14312,14399,14399,14419,14398,14405,14405,14404,14404,14403,14403,14402,14402,14401,14401,14400,14400,14660,14660,14749,14749,14749,14829,14829,14828,14827,14980,15002,15002,15111,15149,15149,15150,15150,15151,15191,15191,15190,15190,15189,15189,15187,15187,15188,15188,15442,15442,15603,15603,15441,15441,15853,15853,16015,15597,15597,15598,15598,15647,15650,15649,15646,15648,15647,15650,15649,15646,15648,15601,15621,15652,15651,15602,15600,15600,15622,15622,16021,16021,16034,16034,16036,16035,16035,16215,16215,16216,16216,16387,16387,16375,16375,16372,16372,16538,16617,16617,16616,16616,16655,16655,16656,16656,14303,14312,16658,14294,16729,16729,16728,16728,16726,16726,16863,16960,16960,16961,16961,16962,16962,16963,16963,16964,16964,16965,16965,16966,16966,17123,17127,17125,17126,17124,17922,17920,17921,17923,17349,17347,17348,17364,17363,17350,17475,17475,17474,17474,17476,17476,18004,18004,18182,18182,18185,18185,18183,18183,18184,18184,18187,18187,18567,18567,18769,18769,18770,18772,18771,18794,18794,18812,18812,18811,18811,19171,19171,19172,19172,19173,19286,19287,19288,19289,19289,19296,19297,19298,19299,19300,19290,19291,19292,19293,19294,19295,null,null,19416,19416,19417,19417,19418,19426,19426,19810,19810,19812,19812,19811,19811,19805,19805,19806,19806,19904,19904,19906,19905,20242,20242,20489,20488,20154,20154,20480,20480,20495,20495,20292,20292,20833,20391,20391,20793,21528,21529,21536,21536,21543,21543,21540,21540,21539,21539,21541,21541,21542,21542,21921,21921,21138,21138,22177,22117,22419,22654,22655,22655,22656,22657,22658,19289,22436,22436,22986,22983,22987,23062,23062,22820,22820,23128,23145,23145,23380,23380,23378,23378,23377,23377,23379,23379,23332,23332,23265,23265,23690,23691]; +window.gw=[ + 2017, + 2017, + 2017, + 2017, + 2019, + 2019, + 2019, + 2019, + 2020, + 2020, + 2020, + 2020, + 2022, + 2022, + 2022, + 2022, + 2018, + 2018, + 2018, + 2018, + 2021, + 2021, + 2021, + 2021, + 2021, + 2021, + 2820, + 2412, + 2105, + 2105, + 2102, + 2102, + 2123, + 2123, + 2184, + 2122, + 2121, + 2106, + 2106, + 2207, + 2164, + 2804, + 2146, + 2146, + 2024, + 2024, + 2821, + 2819, + 2215, + 2163, + 2162, + 2016, + 2145, + 2145, + 2129, + 2129, + 2128, + 2128, + 2216, + 2180, + 2174, + 2147, + 2161, + 2161, + 1926, + 1926, + 2077, + 2077, + 2078, + 2078, + 2013, + 2013, + 2013, + 2015, + 2015, + 2014, + 2014, + 1652, + 1652, + 1652, + 1652, + 1652, + 1652, + 2210, + 2210, + 2210, + 2210, + 2210, + 1657, + 1657, + 1657, + 1657, + 1657, + 1657, + 1861, + 1861, + 1861, + 1861, + 1861, + 1851, + 1851, + 1851, + 1851, + 1851, + 2292, + 2292, + 2292, + 2292, + 2292, + 2333, + 2333, + 2333, + 2333, + 2333, + 1857, + 1857, + 1857, + 1857, + 2823, + 2822, + 2790, + 2204, + 2784, + 2202, + 2700, + 2786, + 2788, + 2789, + 2201, + 2796, + 2787, + 2177, + 2791, + 2797, + 2354, + 2183, + 2203, + 2355, + 2206, + 2341, + 2217, + 2790, + 2204, + 2784, + 2202, + 2700, + 2786, + 2788, + 2789, + 2201, + 2796, + 2787, + 2177, + 2791, + 2797, + 2354, + 2183, + 2203, + 2355, + 2206, + 2341, + 2217, + 2816, + 2824, + 2181, + 2179, + 2205, + 2209, + 2219, + 2185, + 2178, + 2176, + 2208, + 2218, + 2182, + 2818, + 2353, + 2817, + 2529, + 2526, + 2527, + 2528, + 2220, + 2529, + 2526, + 2527, + 2528, + 2220, + 3873, + 3873, + 3873, + 3873, + 3873, + 2529, + 2526, + 2527, + 2528, + 2220, + 3062, + 3062, + 3056, + 3056, + 3060, + 3060, + 3057, + 3057, + 3061, + 3061, + 3058, + 3058, + 3748, + 3748, + 3747, + 3747, + 3744, + 4005, + 4005, + 4035, + 4035, + 4027, + 4027, + 4039, + 4039, + 4029, + 4029, + 4143, + 4143, + 2184, + 2146, + 2215, + 4659, + 4659, + 4916, + 4916, + 4925, + 4925, + 4926, + 4929, + 4960, + 4928, + 4927, + 4926, + 4929, + 4960, + 4928, + 4927, + 5143, + 5209, + 5209, + 4707, + 4707, + 4864, + 4864, + 4863, + 4863, + 4861, + 4861, + 4862, + 4862, + 5166, + 5166, + 5100, + 5100, + 5101, + 5101, + 2210, + 1851, + 2078, + 2790, + 2204, + 2784, + 2202, + 2700, + 2786, + 2788, + 2789, + 2201, + 2796, + 2787, + 2177, + 2791, + 2797, + 2354, + 2183, + 2203, + 2355, + 2206, + 2341, + 2217, + 5589, + 5506, + 5505, + 5872, + 5871, + 5870, + 5168, + 5168, + 5819, + 5820, + 5801, + 5801, + 5801, + 5801, + 5801, + 5359, + 5359, + 5982, + 5982, + 5978, + 5978, + 5979, + 5979, + 5981, + 5981, + 5980, + 5980, + 6114, + 6114, + 6113, + 6113, + 6484, + 6484, + 6488, + 6488, + 6489, + 6659, + 6659, + 6661, + 6661, + 6664, + 6664, + 6665, + 6662, + 6663, + 6663, + 6873, + 6873, + 6871, + 6872, + 7269, + 7269, + 7273, + 7273, + 7273, + 7273, + 7273, + 7273, + 7273, + 7273, + 7273, + 7273, + 7291, + 7291, + 7310, + 7310, + 7207, + 7207, + 7209, + 7209, + 7208, + 7208, + 7211, + 7211, + 7210, + 7210, + 7311, + 7311, + 7588, + 7574, + 7591, + 7590, + 7589, + 7588, + 7574, + 7591, + 7590, + 7589, + 7576, + 7573, + 7573, + 7572, + 7575, + 7577, + 7577, + 7731, + 7731, + 7732, + 7732, + 8286, + 8286, + 8440, + 8440, + 8439, + 8438, + 8883, + 8883, + 8882, + 8882, + 8881, + 8881, + 8880, + 8880, + 8873, + 8884, + 8884, + 8885, + 8886, + 7577, + 9032, + 9032, + 9031, + 9031, + 9033, + 9033, + 9034, + 9034, + 9035, + 9035, + 8946, + 9247, + 9248, + 9249, + 3574, + 3574, + 3558, + 9875, + 9876, + 9881, + 9882, + 9877, + 9877, + 9880, + 10005, + 10004, + 10003, + 10003, + 10445, + 10445, + 10834, + 10834, + 10837, + 10837, + 10837, + 10833, + 10833, + 9878, + 9878, + 11071, + 11071, + 11072, + 11072, + 11073, + 11073, + 11074, + 11074, + 11075, + 11075, + 11070, + 11070, + 11460, + 3061, + 3061, + 11529, + 11530, + 11532, + 11531, + 11533, + 11538, + 11537, + 11538, + 11537, + 11536, + 11535, + 11550, + 11549, + 11534, + 11539, + 11540, + 11541, + 11542, + 11543, + 11539, + 11540, + 11541, + 11542, + 11543, + 11545, + 11546, + 11563, + 11545, + 11546, + 11563, + 11544, + 11562, + 11544, + 11562, + 11642, + 11642, + 11791, + 11791, + 11787, + 11787, + 11790, + 11790, + 11788, + 11788, + 11789, + 11789, + 11775, + 11775, + 11776, + 11806, + 11806, + 11786, + 11960, + 11960, + 12015, + 12015, + 11949, + 11949, + 11950, + 11950, + 11951, + 11951, + 11952, + 11952, + 11953, + 11953, + 11948, + 11948, + 12067, + 12067, + 11774, + 11774, + 11773, + 11773, + 12098, + 12098, + 12100, + 12099, + 12136, + 12137, + 12132, + 12132, + 12131, + 12131, + 12424, + 12424, + 12138, + 12138, + 12134, + 12135, + 12648, + 12648, + 12649, + 12649, + 12650, + 12650, + 12651, + 12651, + 12647, + 12647, + 12775, + 12781, + 12782, + 12780, + 12776, + 12774, + 12774, + 12805, + 12805, + 12806, + 12807, + 12794, + 12794, + 12868, + 12878, + 12878, + 12888, + 12888, + 13148, + 13137, + 13138, + 13136, + 13133, + 13133, + 13134, + 13134, + 13135, + 13135, + 13396, + 13396, + 13396, + 13396, + 13396, + 13315, + 13315, + 13568, + 13568, + 13567, + 13567, + 13688, + 13688, + 13749, + 13749, + 13947, + 13947, + 13948, + 13949, + 14421, + 14420, + 14257, + 14257, + 14296, + 4349, + 4860, + 6065, + 5085, + 5304, + 6955, + 5190, + 7435, + 5311, + 6924, + 6051, + 6430, + 6030, + 14295, + 14294, + 14303, + 14303, + 14312, + 14312, + 14399, + 14399, + 14419, + 14398, + 14405, + 14405, + 14404, + 14404, + 14403, + 14403, + 14402, + 14402, + 14401, + 14401, + 14400, + 14400, + 14660, + 14660, + 14749, + 14749, + 14749, + 14829, + 14829, + 14828, + 14827, + 14980, + 15002, + 15002, + 15111, + 15149, + 15149, + 15150, + 15150, + 15151, + 15191, + 15191, + 15190, + 15190, + 15189, + 15189, + 15187, + 15187, + 15188, + 15188, + 15442, + 15442, + 15603, + 15603, + 15441, + 15441, + 15853, + 15853, + 16015, + 15597, + 15597, + 15598, + 15598, + 15647, + 15650, + 15649, + 15646, + 15648, + 15647, + 15650, + 15649, + 15646, + 15648, + 15601, + 15621, + 15652, + 15651, + 15602, + 15600, + 15600, + 15622, + 15622, + 16021, + 16021, + 16034, + 16034, + 16036, + 16035, + 16035, + 16215, + 16215, + 16216, + 16216, + 16387, + 16387, + 16375, + 16375, + 16372, + 16372, + 16538, + 16617, + 16617, + 16616, + 16616, + 16655, + 16655, + 16656, + 16656, + 14303, + 14312, + 16658, + 14294, + 16729, + 16729, + 16728, + 16728, + 16726, + 16726, + 16863, + 16960, + 16960, + 16961, + 16961, + 16962, + 16962, + 16963, + 16963, + 16964, + 16964, + 16965, + 16965, + 16966, + 16966, + 17123, + 17127, + 17125, + 17126, + 17124, + 17920, + 17922, + 17921, + 17923, + 17349, + 17347, + 17348, + 17364, + 17363, + 17350, + 17475, + 17475, + 17474, + 17474, + 17476, + 17476, + 18004, + 18004, + 18182, + 18182, + 18185, + 18185, + 18183, + 18183, + 18184, + 18184, + 18187, + 18187, + 18567, + 18567, + 18769, + 18769, + 18770, + 18772, + 18771, + 18794, + 18794, + 18812, + 18812, + 18811, + 18811, + 19171, + 19171, + 19172, + 19172, + 19173, + 19286, + 19287, + 19288, + 19289, + 19289, + 19296, + 19297, + 19298, + 19299, + 19300, + 19290, + 19291, + 19292, + 19293, + 19294, + 19295, + 26358, + 26358, + 19416, + 19416, + 19417, + 19417, + 19418, + 19426, + 19426, + 19810, + 19810, + 19812, + 19812, + 19811, + 19811, + 19805, + 19805, + 19806, + 19806, + 19904, + 19904, + 19906, + 19905, + 20242, + 20242, + 20489, + 20488, + 20154, + 20154, + 20480, + 20480, + 20495, + 20495, + 20292, + 20292, + 20833, + 20391, + 20391, + 20793, + 21528, + 21529, + 21536, + 21536, + 21543, + 21543, + 21540, + 21540, + 21539, + 21539, + 21541, + 21541, + 21542, + 21542, + 21921, + 21921, + 21138, + 21138, + 22177, + 22117, + 22419, + 22654, + 22655, + 22655, + 22656, + 22657, + 22658, + 19289, + 22659, + 22659, + 22986, + 22983, + 22987, + 23062, + 23062, + 22820, + 22820, + 23128, + 23145, + 23145, + 23380, + 23380, + 23378, + 23378, + 23377, + 23377, + 23379, + 23379, + 23332, + 23332, + 23265, + 23265, + 23690, + 23691, + 24045, + 24045, + 24017, + 24017, + 24018, + 24018, + 24036, + 24162, + 24162, + 24305, + 24306, + 23506, + 23506, + 24564, + 24564, + 24703, + 24703, + 24701, + 24701, + 24699, + 24699, + 24702, + 24702, + 24807, + 24807, + 25016, + 25017, + 25018, + 25019, + 25098, + 25098, + 25133, + 25133, + 25318, + 25336, + 25335, + 25317, + 25316, + 25315, + 25314, + 24998, + 24978, + 25323, + 25330, + 25329, + 25319, + 25320, + 25321, + 25321, + 25321, + 25321, + 25321, + 25313, + 25313, + 25365, + 25365, + 25111, + 25111, + 25488, + 25489, + 25751, + 26489, + 26489, + 26490, + 26833, + 26833, + 26833, + 26833, + 26833, + 26487, + 26487, + 26627, + 26627, + 26464, + 26464, + 26720, + 26720, + 26797, + 26797, + 26850, + 26850, + 26911, + 26911, + 26913, + 26912, + 26912, + 27334, + 27334, + 27466, + 27634, + 27634, + 27635, + 27636, + 27637, + 27620, + 27620, + 27622, + 27622, + 27624, + 28647, + 28647, + 28650, + 29679, + 28723, + 28723, + 28761, + 28761, + 28759, + 28759, + 28756, + 28756, + 28754, + 28754, + 28771, + 28771, + 29445, + 29445, + 29446, + 29446, + 29621, + 29621, + 29622, + 29622, + 29651, + 29651, + 29787, + 29787, + 29915, + 29915, + 29916, + 29916, + 29917, + 30405, + 30405, + 30529, + 30529, + 30530, + 30530, + 30531, + 30531, + 30558, + 30556, + 30554, + 30555, + 30553, + 30552, + 30551, + 30550, + 30771, + 30771, + 30770, + 30770, + 30772, + 30738, + 30738, + 30733, + 30733, + 30734, + 30734, + 30737, + 30737, + 30736, + 30736, + 30744, + 30744, + 30798, + 30798, + 30797, + 30797, + 30796, + 30796, + 32539, + 32539, + 33121, + 33121, + 33122, + 33122, + 33123, + 33396, + 33396, + 33488, + 33488, + 33489, + 33489, + 33490, + 33490, + 33650, + 33650, + 33851, + 33851, + 33850, + 33850, + 33852, + 11949, + 11949, + 11950, + 11950, + 11951, + 11951, + 12878, + 12878, + 33767, + 33767, + 33765, + 33765, + 33764, + 33764, + 33763, + 33763, + 33762, + 33762, + 33766, + 33766, + 34316, + 34316, + 34499, + 34496, + 34497, + 34498, + 34493, + 34493, + 34494, + 34494, + 34495, + 34495, + 34757, + 34756, + 34755, + 34754, + 34753, + 34752, + 34751, + 34750, + 34748, + 34749, + 34747, + 34747, + 34746, + 34746, + 35105, + 35105, + 35076, + 35076, + 35077, + 35077, + 35203, + 35203, + 35202, + 35202, + 35201, + 35201, + 11952, + 11952, + 12648, + 12648, + 11953, + 11953, + 35056, + 35056, + 1861, + 35411, + 35411, + 35305, + 35305, + 35306, + 35306, + 35374, + 35374, + 35412, + 35412, + 35281, + 35281, + 35516, + 35516, + 35525, + 35525, + 35526, + 35778, + 35778, + 36035, + 36035, + 35904, + 35904, + 35906, + 35906, + 35907, + 12650, + 12650, + 12649, + 12649, + 12651, + 12651, + 36068, + 36068, + 36743, + 36744, + 36742, + 36745, + 36721, + 36721, + 36720, + 36720, + 37233, + 37237, + 37194, + 37195, + 37196, + 37154, + 37079, + 37079, + 37122, + 37122, + 37082, + 37082, + 37051, + 37051, + 37052, + 37052, + 37125, + 37125, + 37427, + 37427, + 37426, + 37426, + 37431, + 37432, + 37432, + 38048, + 38048, + 38049, + 38049, + 38050, + 38051, + 38339, + 38341, + 38342, + 38236, + 38236, + 38724, + 38724, + 38723, + 38723, + 38722, + 38722, + 38846, + 38846, + 38773, + 38773, + 38772, + 38772, + 38768, + 38768, + 38771, + 38771, + 38770, + 38770, + 38769, + 38769, + 39054, + 38884, + 38882, + 38883, + 38885, + 39075, + 39075, + 39525, + 39525, + 39527, + 39527, + 39526, + 39529, + 39529, + 39530, + 39530, + 40554, + 40554, + 41278, + 41278, + 41926, + 41926, + 41931, + 41931, + 41932, + 41932, + 43619, + 43619, + 43743, + 43743, + 43751, + 43751, + 43752, + 43752, + 43909, + 43909, + 43907, + 43907, + 43908, + 43908, + 43906, + 43906, + 43894, + 43894, + 43893, + 43893, + 44160, + 44160, + 44167, + 44167, + 44169, + 44168, + 44750, + 44750, + 44751, + 44752, + 44762, + 44762, + 44766, + 44766, + 44770, + 44768, + 44768, + 45630, + 45629, + 45628, + 45561, + 45627, + 45634, + 45633, + 45632, + 45636, + 45635, + 45637, + 45560, + 45767, + 45767, + 45766, + 45766, + 45785, + 45785, + 45836, + 45711, + 45711, + 45758, + 45758, + 45759, + 45759, + 45756, + 45756, + 45757, + 45757, + 45851, + 45851, + 45905, + 45905, + 46259, + 46259, + 46330, + 46330, + 46369, + 46369, + 46657, + 46657, + 46661, + 46661, + 46662, + 46662, + 2017, + 2019, + 2020, + 46852, + 46852, + 47137, + 47139, + 47292, + 47292, + 47253, + 47253, + 47254, + 47254, + 47299, + 47299, + 47302, + 47356, + 47356, + 47362, + 47362, + 47338, + 47338, + 47322, + 47322, + 47321, + 47321, + 5166, + 47389, + 48078, + 48078, + 48077, + 48076, + 48222, + 48222, + 48689, + 48689, + 48806, + 48804, + 49865, + 49865, + 49866, + 49867, + 49836, + 49836, + 50027, + 50027, + 50143, + 50143, + 50182, + 50182, + 50181, + 50181, + 50184, + 50184, + 50183, + 50183, + 50185, + 50185, + 9034, + 2022, + 2018, + 2021, + 50898, + 50898, + 50899, + 50899, + 50813, + 50813, + 50809, + 50809, + 50810, + 50810, + 50811, + 50811, + 51590, + 51594, + 51594, + 51897, + 51897, + 51932, + 51932, + 51929, + 51929, + 51928, + 51927, + 52204, + 52204, + 52178, + 52178, + 52205, + 52205, + 52206, + 52206, + 52207, + 52207, + 52208, + 52208, + 52276, + 52276, + 52180, + 52180, + 52209, + 52209, + 52210, + 52210, + 15191, + 52607, + 52606, + 52604, + 52602, + 52601, + 52600, + 52599, + 52598, + 52492, + 52491, + 52493, + 52494, + 52490, + 52490, + 52628, + 52628, + 52632, + 52634, + 52633, + 52635, + 52663, + 52663, + 53095, + 53095, + 53153, + 53153, + 53572, + 53572, + 53574, + 53573, + 53576, + 53576, + 53589, + 53593, + 53593, + 53592, + 53622, + 53622, + 54006, + 54006, + 54001, + 54001, + 54004, + 54004, + 54003, + 54003, + 53948, + 53948, + 54002, + 54002, + 54006, + 54313, + 54313, + 54305, + 54305, + 54306, + 15622, + 14294, + 22659, + 54674, + 54674, + 54675, + 54675, + 54883, + 54884, + 54885, + 54886, + 54888, + 54889, + 52490, + 55148, + 55148, + 55149, + 55149, + 55425, + 55425, + 55433, + 55743, + 55743, + 55744, + 55744, + 55823, + 55823, + 55766, + 55766, + 55822, + 55822, + 56042, + 56042, + 56043, + 56054, + 56054, + 56056, + 56056, + 56735, + 56735, + 56780, + 56780, + 56779, + 56779, + 56736, + 56945, + 56945, + 57042, + 57042, + 57044, + 57043, + 56812, + 57473, + 57473, + 57474, + 57510, + 57510, + 57823, + 57824, + 57825, + 57875, + 57875, + 57876, + 57876, + 57877, + 57877, + 57878, + 57878, + 57879, + 57879, + 7311, + 58061, + 58061, + 58436, + 58436, + 59328, + 59332, + 59330, + 59480, + 59480, + 59477, + 59477, + 60067, + 60067, + 60337, + 60336, + 60338, + 60339, + 60339, + 60340, + 60341, + 60342, + 60343, + 60344, + 60345, + 60346, + 60347, + 60100, + 60100, + 60688, + 60688, + 60689, + 60679, + 60679, + 60676, + 60676, + 60677, + 60677, + 60675, + 60675, + 60678, + 60678, + 61073, + 61073, + 16960, + 61003, + 61003, + 61261, + 61261, + 61267, + 61267, + 61625, + 61626, + 61627, + 61707, + 61707, + 61811, + 61811, + 61807, + 61807, + 62443, + 62443, + 62644, + 62644, + 62646, + 62646, + 62647, + 62647, + 62645, + 62645, + 62886, + 62886, + 62887, + 62888, + 62896, + 62896, + 63219, + 63219, + 63199, + 63199, + 63200, + 63200, + 63203, + 63203, + 63204, + 63204, + 63205, + 63205, + 11948, + 63214, + 63214, + 63272, + 63272, + 65777, + 65777, + 65970, + 65969, + 60339, + 65966, + 65968, + 65967, + 63375, + 63375, + 64091, + 64091, + 64096, + 64096, + 64234, + 64234, + 65077, + 65077, + 64838, + 64838, + 66571, + 66571, + 66024, + 66024, + 66025, + 66025, + 66094, + 66094, + 66499, + 66499, + 66498, + 66498, + 66497, + 66497, + 66495, + 66495, + 66496, + 66496, + 68240, + 68240, + 65830, + 65830, + 65835, + 65835, + 65833, + 65833, + 65831, + 65831, + 65834, + 65834, + 68239, + 68239, + 35281, + 67113, + 67113, + 67114, + 67115, + 66691, + 66691, + 67128, + 67128, + 68612, + 68612, + 68613, + 68613, + 68472, + 68472, + 68680, + 68680, + 70601, + 70444, + 70443, + 70445, + 70442, + 70552, + 70553, + 70554, + 70556, + 70555, + 70188, + 70188, + 69286, + 69286, + 69404, + 69404, + 69424, + 69424, + 69430, + 69430, + 69439, + 69439, + 72450, + 72450, + 72451, + 72451, + 72510, + 72510, + 71419, + 71419, + 71420, + 71420, + 69787, + 70377, + 70377, + 12647, + 72658, + 72658, + 72660, + 72659, + 72324, + 72324, + 73186, + 73186, + 73957, + 73957, + 74132, + 74132, + 75006, + 75006, + 74384, + 74384, + 74388, + 74388, + 74387, + 74387, + 74386, + 74386, + 74385, + 74385, + 75882, + 75882, + 75881, + 75881, + 75037, + 75037, + 11070, + 78759, + 78759, + 78758, + 78758, + 79258, + 79258, + 79682, + 79682, + 79681, + 79681, + 79745, + 79745, + 80284, + 80284, +]; \ No newline at end of file diff --git a/common/data/json.html b/common/data/json.html new file mode 100644 index 000000000..091e5751c --- /dev/null +++ b/common/data/json.html @@ -0,0 +1,28 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/common/data/matchers.js b/common/data/matchers.js index e67dbab74..c0fbcc7e1 100644 --- a/common/data/matchers.js +++ b/common/data/matchers.js @@ -11,7 +11,7 @@ window.matchers = [ { name: 'Class-boosting captains', target: 'captain', - matcher: /Boosts (ATK|HP|RCV|ATK and HP|ATK and RCV|HP and RCV|ATK, HP and RCV) of[^,]+(Slasher|Striker|Fighter|Shooter|Freedom|Knowledge|Tough|Ambition)/i + matcher: /Boosts (ATK|HP|RCV|ATK and HP|ATK and RCV|HP and RCV|ATK, HP and RCV) of[^,]+(Slasher|Striker|Fighter|Shooter|Free Spirit|Cerebral|Powerhouse|Driven)/i }, { @@ -78,7 +78,14 @@ window.matchers = [ { name: 'Positional captains', target: 'captain', - matcher: /(after scoring|following a chain)/i + matcher: /(after scoring|following a chain|perfect|great|good)/i + }, + + { + name: '"Beneficial" Orb captains', + target: 'captain', + matcher: /"beneficial/i + //matcher: /Makes ((STR|DEX|QCK|PSY|INT|\[RCV\]|\[TND\])|((STR|DEX|QCK|PSY|INT|\[RCV\]|\[TND\]) and (STR|DEX|QCK|PSY|INT|\[RCV\]|\[TND\]))) orbs "beneficial"/i }, { @@ -86,6 +93,12 @@ window.matchers = [ target: 'captain', matcher: /Boosts.+chain multiplier/i }, + + { + name: 'Combo Boost Captains', + target: 'captain', + matcher: /Boosts.+hit in the chain/i + }, { name: 'Cooldown reducers', @@ -116,6 +129,30 @@ window.matchers = [ target: 'captain', matcher: /Protects from defeat/i }, + + { + name: 'End of Turn Damage Dealer', + target: 'captain', + matcher: /deals.+end of each turn/i + }, + + { + name: 'Beli Boosters', + target: 'captain', + matcher: /boosts.+Beli/i + }, + + { + name: 'EXP Boosters', + target: 'captain', + matcher: /boosts.+EXP/i + }, + + { + name: 'Drop Doublers', + target: 'captain', + matcher: /duplicating a drop/i + }, /* * * * * Specials * * * * */ @@ -128,7 +165,7 @@ window.matchers = [ { name: 'Class-boosting specials', target: 'special', - matcher: /Boosts (ATK|HP|RCV|ATK and HP|ATK and RCV|HP and RCV|ATK, HP and RCV) of[^,]+(Slasher|Striker|Fighter|Shooter|Freedom|Knowledge|Tough|Ambition)/i + matcher: /Boosts (ATK|HP|RCV|ATK and HP|ATK and RCV|HP and RCV|ATK, HP and RCV) of[^,]+(Slasher|Striker|Fighter|Shooter|Free Spirit|Cerebral|Powerhouse|Driven)/i }, { @@ -160,11 +197,29 @@ window.matchers = [ target: 'special', matcher: /(Following the activation.+boosts.+ATK|If during that turn.+boosts.+ATK)/i }, + + { + name: 'Color Affinity boosters', + target: 'special', + matcher: /Boosts the Color Affinity/i + }, + + { + name: 'Combo Boost Specials', + target: 'special', + matcher: /Boost.+hit in the chain/i + }, + + { + name: 'RCV boosters', + target: 'special', + matcher: /Boosts RCV/i + }, { name: 'Orb lockers', target: 'special', - matcher: /locks.+orbs/i + matcher: /locks.+orb/i }, { @@ -180,11 +235,18 @@ window.matchers = [ }, { - name: 'Orb controllers', + name: 'Negative to Positive Orb controllers', target: 'special', - matcher: /(Changes.+orbs)/i + matcher: /(Badly Matching orbs into.+Matching orbs)/i, + //include: [ 900, 901, 996, 997, 933, 938, 939 ], }, + { + name: 'Orb controllers', + target: 'special', + matcher: /(Changes.+(orb|orbs))/i + }, + { name: 'Full-board orb controllers', target: 'special', @@ -208,6 +270,13 @@ window.matchers = [ target: 'special', matcher: /switches orbs/i }, + + { + name: 'Orb matchers', + target: 'special', + matcher: /(Changes.+(orb|orbs))[^,]+Matching/i, + include: [ 1036, 1037, 1445, 1369, 1370 ] + }, { name: 'Slot emptiers', @@ -215,17 +284,23 @@ window.matchers = [ matcher: /(Empties|Changes.+into.+\[EMPTY\])/i }, - { + /*{ name: 'Slot fillers', target: 'special', matcher: /(Fills\b|\[EMPTY\] orbs into|Changes.+\[EMPTY\].+into)/i - }, + },*/ { name: 'Delayers', target: 'special', matcher: /delays/i }, + + { + name: 'Single-target damage dealer', + target: 'special', + matcher: /deals.+to one enemy/i + }, { name: 'Multi-target damage dealers', @@ -245,6 +320,12 @@ window.matchers = [ matcher: /Deals.+fixed damage/i }, + { + name: 'Typeless damage dealers', + target: 'special', + matcher: /Deals.+typeless damage/i + }, + { name: 'Health cutters', target: 'special', @@ -263,7 +344,7 @@ window.matchers = [ matcher: /Reduces.+defense/i }, - { + /*{ name: 'Meat producers', target: 'special', matcher: /into( either)?[\s,\[\]A-Zor]+\[RCV\]/ @@ -273,7 +354,7 @@ window.matchers = [ name: 'Meat converters', target: 'special', matcher: /\[RCV\].+into/i - }, + },*/ { name: 'Damage reducers', @@ -286,29 +367,47 @@ window.matchers = [ target: 'special', matcher: /Reduces (any )?damage received.+100%/i }, + + /*{ + name: 'Debuff Reducing Specials', + target: 'special', + matcher: /(reduces|removes) [^,]+(Bind|Despair|Silence|Paralysis|Blindness|Poison|No Healing|Chain Limit).+duration/i + },*/ { name: 'Bind reducers', target: 'special', - matcher: /reduces.+bind.+duration/i, + matcher: /(reduces|removes).+bind.+duration/i }, + { + name: 'Despair reducers', + target: 'special', + matcher: /(reduces|removes).+despair.+duration/i + }, + { name: 'Silence reducers', target: 'special', - matcher: /reduces.+silence.+duration/i, + matcher: /(reduces|removes).+silence.+duration/i + }, + + { + name: 'Paralysis reducers', + target: 'special', + matcher: /(reduces|removes).+Paralysis/i }, { name: 'Block orb removers', target: 'special', - matcher: /(empties.+with \[BLOCK\]|changes.+\[BLOCK\].+into|including.+\[BLOCK\])/i, + matcher: /(empties.+with \[BLOCK\]|changes.+\[BLOCK\].+into|including.+\[BLOCK\])/i }, { name: 'Blindness removers', target: 'special', - matcher: /removes blindness/i + matcher: /(reduces|removes).+blindness/i }, { @@ -332,13 +431,197 @@ window.matchers = [ { name: 'Poison removers', target: 'special', - matcher: /Removes poison/i + matcher: /removes.+poison/i + }, + + { + name: 'Crew positive buff remover', + target: 'special', + matcher: /removes.+positive buffs/i + }, + + { + name: 'Enemy End of Turn buff remover', + target: 'special', + matcher: /removes.+End of Turn/i + }, + + { + name: 'Enemy Enrage buff remover', + target: 'special', + matcher: /removes.+Enrage/i + }, + + { + name: 'Enemy ATK buff remover', + target: 'special', + matcher: /(removes|reduces).+ATK up/i + }, + + { + name: 'Enemy Threshold Damage Reduction remover', + target: 'special', + matcher: /(removes|reduces).+Threshold Damage Reduction/i + }, + + { + name: 'Enemy Percent Damage Reduction remover', + target: 'special', + matcher: /(removes|reduces).+Percent Damage Reduction/i + }, + + { + name: 'Enemy Increased Defense remover', + target: 'special', + matcher: /(removes|reduces).+Increased Defense/i }, { name: 'Zombies', target: 'special', matcher: /Protects from defeat/i - } + }, + + { + name: 'Special cooldown reducer', + target: 'special', + matcher: /reduces special cooldown/i + }, + + { + name: 'Chain Boosters', + target: 'special', + matcher: /Adds.+to Chain/i + }, + + { + name: 'Chain Lockers', + target: 'special', + matcher: /Locks the chain multiplier/i + }, + + { + name: '"Beneficial" Orb Enablers', + target: 'special', + matcher: /"beneficial/i + }, + + /* * * * * Sailor * * * * */ + + { + name: 'Has Sailor Ability', + target: 'sailor', + matcher: /\S/i + }, + + { + name: 'Type-boosting sailors', + target: 'sailor', + matcher: /Boosts base (ATK|HP|RCV|ATK and HP|ATK and RCV|HP and RCV|ATK, HP and RCV) of[^,]+(STR|DEX|QCK|PSY|INT)\b/i + }, + + { + name: 'Class-boosting sailors', + target: 'sailor', + matcher: /Boosts base (ATK|HP|RCV|ATK and HP|ATK and RCV|HP and RCV|ATK, HP and RCV) of[^,]+(Slasher|Striker|Fighter|Shooter|Free Spirit|Cerebral|Powerhouse|Driven)/i + }, + + { + name: 'ATK boosting sailors', + target: 'sailor', + matcher: /Boosts base ATK/i + }, + + { + name: 'HP boosting sailors', + target: 'sailor', + matcher: /Boosts base (HP|ATK and HP|ATK, HP)|Boosts.+and their HP/i + }, + + { + name: 'RCV boosting sailors', + target: 'sailor', + matcher: /Boosts base (RCV|ATK and RCV|HP and RCV|ATK, HP and RCV)|Boosts.+and their RCV/i + }, + + { + name: '"Beneficial" Orb sailors', + target: 'sailor', + matcher: /"beneficial/i + }, + + { + name: 'Paralysis reducers', + target: 'sailor', + matcher: /(reduces|removes|resists).+Paralysis/i + }, + + { + name: 'Blindness removers', + target: 'sailor', + matcher: /(reduces|removes|resists).+blindness/i + }, + + { + name: 'Silence reducers', + target: 'sailor', + matcher: /(reduces|removes|resists).+silence/i + }, + + { + name: 'Special Rewind Restorers', + target: 'sailor', + matcher: /Restores (his|her) own special/i + }, + + /* * * * * Limit Break * * * * */ + + { + name: 'Has Limit Break', + target: 'limit', + matcher: /\S/i + }, + + { + name: 'Enrage Potential Ability', + target: 'limit', + matcher: /Enrage/i + }, + + { + name: 'Reduce No Healing Potential Ability', + target: 'limit', + matcher: /Reduce No Healing/i + }, + + { + name: 'Critical Hit Potential Ability', + target: 'limit', + matcher: /Critical Hit/i + }, + + { + name: 'Slot Bind Self-reduction Potential Ability', + target: 'limit', + matcher: /Slot Bind Self-reduction/i + }, + + { + name: 'Barrier Penetration Potential Ability', + target: 'limit', + matcher: /Barrier Penetration/i + }, + + { + name: 'Pinch Healing Potential Ability', + target: 'limit', + matcher: /Pinch Healing/i + }, + + { + name: 'Damage Reduction Potential Ability', + target: 'limit', + matcher: /Damage Reduction/i + }, ]; diff --git a/common/data/sailors.js b/common/data/sailors.js new file mode 100644 index 000000000..c7e62caed --- /dev/null +++ b/common/data/sailors.js @@ -0,0 +1,357 @@ +window.sailors = { + 311: { + atkStatic: function(p) { return p.percHP <= 30.0 && p.unit.class.has("Cerebral") ? 50 : 0; }, + }, + 312: { + atkStatic: function(p) { return p.percHP <= 30.0 && p.unit.class.has("Cerebral") ? 50 : 0; }, + }, + 360: { + hpStatic: function(p) { return p.unit.class.has("Powerhouse") ? 100 : 0; }, + }, + 361: { + hpStatic: function(p) { return p.unit.class.has("Powerhouse") ? 100 : 0; }, + }, + 364: { + rcvStatic: function(p) { return 10; }, + }, + 365: { + rcvStatic: function(p) { return 10; }, + }, + 450: { + atkStatic: function(p) { return p.unit.class.has("Fighter") ? 20 : 0; }, + }, + 451: { + atkStatic: function(p) { return p.unit.class.has("Fighter") ? 20 : 0; }, + }, + 525: { + rcvStatic: function(p) { return p.unit.type == "PSY" ? 15 : 0; }, + }, + 526: { + rcvStatic: function(p) { return p.unit.type == "PSY" ? 15 : 0; }, + }, + 527: { + rcvStatic: function(p) { return p.percHP <= 30.0 && p.slot == p.sourceSlot ? 50 : 0; }, + }, + 528: { + rcvStatic: function(p) { return p.percHP <= 30.0 && p.slot == p.sourceSlot ? 50 : 0; }, + }, + 553: { + atkStatic: function(p) { return p.unit.class.has("Slasher") ? 20 : 0; }, + }, + 554: { + atkStatic: function(p) { return p.unit.class.has("Slasher") ? 20 : 0; }, + }, + 555: { + rcvStatic: function(p) { return p.unit.class.has("Shooter") ? 10 : 0; }, + }, + 556: { + rcvStatic: function(p) { return p.unit.class.has("Shooter") ? 10 : 0; }, + }, + 559: { + atkStatic: function(p) { return p.unit.class.has("Shooter") ? 20 : 0; }, + }, + 560: { + atkStatic: function(p) { return p.unit.class.has("Shooter") ? 20 : 0; }, + }, + 640: { + atkStatic: function(p) { return p.percHP <= 30.0 && p.unit.class.has("Fighter") ? 100 : 0; }, + }, + 641: { + atkStatic: function(p) { return p.percHP <= 30.0 && p.unit.class.has("Fighter") ? 100 : 0; }, + }, + 644: { + rcvStatic: function(p) { return p.unit.type == "INT" ? 20 : 0; }, + atkStatic: function(p) { return p.unit.type == "INT" ? 20 : 0; }, + }, + 645: { + rcvStatic: function(p) { return p.unit.type == "INT" ? 20 : 0; }, + atkStatic: function(p) { return p.unit.type == "INT" ? 20 : 0; }, + }, + 646: { + hpStatic: function(p) { return p.unit.type == "STR" ? 30 : 0; }, + }, + 647: { + hpStatic: function(p) { return p.unit.type == "STR" ? 30 : 0; }, + }, + 1172: { + rcvStatic: function(p) { return p.unit.type == "PSY" ? 15 : 0; }, + }, + 1173: { + rcvStatic: function(p) { return p.unit.type == "PSY" ? 15 : 0; }, + }, + 1174: { + atkStatic: function(p) { return p.unit.class.has("Slasher") ? 20 : 0; }, + }, + 1175: { + atkStatic: function(p) { return p.unit.class.has("Slasher") ? 20 : 0; }, + }, + 1176: { + rcvStatic: function(p) { return p.percHP <= 30.0 && p.slot == p.sourceSlot ? 50 : 0; }, + }, + 1177: { + rcvStatic: function(p) { return p.percHP <= 30.0 && p.slot == p.sourceSlot ? 50 : 0; }, + }, + 1183: { + atkStatic: function(p) { return p.percHP >= 99.0 && p.unit.type == "PSY" ? 75 : 0; }, + }, + 1184: { + atkStatic: function(p) { return p.percHP >= 99.0 && p.unit.type == "PSY" ? 75 : 0; }, + }, + 1187: { + atkStatic: function(p) { return 20; }, + rcvStatic: function(p) { return 20; }, + hpStatic: function(p) { return 20; }, + }, + 1188: { + atkStatic: function(p) { return 20; }, + rcvStatic: function(p) { return 20; }, + hpStatic: function(p) { return 20; }, + }, + 1189: { + atkStatic: function(p) { return p.unit.type == "QCK" ? 40 : 0; }, + }, + 1190: { + atkStatic: function(p) { return p.unit.type == "QCK" ? 40 : 0; }, + }, + 1209: { + rcvStatic: function(p) { return p.unit.class.has("Shooter") ? 10 : 0; }, + }, + 1210: { + rcvStatic: function(p) { return p.unit.class.has("Shooter") ? 10 : 0; }, + }, + 1211: { + atkStatic: function(p) { return p.unit.class.has("Shooter") ? 20 : 0; }, + }, + 1212: { + atkStatic: function(p) { return p.unit.class.has("Shooter") ? 20 : 0; }, + }, + 1231: { + atkStatic: function(p) { return p.unit.class.has("Striker") ? 50 : 0; }, + }, + 1232: { + atkStatic: function(p) { return p.unit.class.has("Striker") ? 50 : 0; }, + }, + 1233: { + rcvStatic: function(p) { return p.unit.class.has("Slasher") ? 30 : 0; }, + }, + 1234: { + rcvStatic: function(p) { return p.unit.class.has("Slasher") ? 30 : 0; }, + }, + 1255: { + atkStatic: function(p) { return p.percHP <= 30.0 && p.unit.class.has("Fighter") ? 40 : 0; }, + }, + 1256: { + rcvStatic: function(p) { return p.unit.class.has("Driven") ? 10 : 0; }, + atkStatic: function(p) { return p.unit.class.has("Driven") ? 10 : 0; }, + }, + 1271: { + atkStatic: function(p) { return p.captain != null ? p.captain.class.has("Driven") ? 100 : 0 : 0; }, + }, + 1270: { + atkStatic: function(p) { return p.captain != null ? p.captain.class.has("Driven") ? 100 : 0 : 0; }, + }, + 1273: { + hpStatic: function(p) { return 75; }, + }, + 1274: { + hpStatic: function(p) { return 75; }, + }, + 1277: { + rcvAdded: function(p) { return 150; }, + }, + 1278: { + rcvAdded: function(p) { return 150; }, + }, + 1317: { + hpStatic: function(p) { return 75; }, + }, + 1318: { + hpStatic: function(p) { return 75; }, + }, + 1321: { + atkStatic: function(p) { return p.captain != null ? p.captain.class.has("Cerebral") ? p.unit.class.has("Slasher") || p.unit.class.has("Cerebral") ? 75 : 0 : 0 : 0; }, + }, + 1322: { + atkStatic: function(p) { return p.captain != null ? p.captain.class.has("Cerebral") ? p.unit.class.has("Slasher") || p.unit.class.has("Cerebral") ? 75 : 0 : 0 : 0; }, + }, + 1363: { + hpStatic: function(p) { return p.unit.type == "PSY" ? 100 : 0; }, + }, + 1364: { + hpStatic: function(p) { return p.unit.type == "PSY" ? 100 : 0; }, + }, + 1367: { + atkStatic: function(p) { return 50; }, + rcvStatic: function(p) { return 50; }, + hpStatic: function(p) { return 50; }, + }, + 1368: { + atkStatic: function(p) { return 50; }, + rcvStatic: function(p) { return 50; }, + hpStatic: function(p) { return 50; }, + }, + 1377: { + rcvAdded: function(p) { return 125; }, + }, + 1378: { + rcvAdded: function(p) { return 125; }, + }, + 1405: { + atkStatic: function(p) { return p.percHP <= 30.0 && p.unit.class.has("Shooter") ? 100 : 0; }, + rcvStatic: function(p) { return p.percHP <= 30.0 && p.unit.class.has("Shooter") ? 100 : 0; }, + }, + 1406: { + atkStatic: function(p) { return p.percHP <= 30.0 && p.unit.class.has("Shooter") ? 100 : 0; }, + rcvStatic: function(p) { return p.percHP <= 30.0 && p.unit.class.has("Shooter") ? 100 : 0; }, + }, + 1435: { + atkStatic: function(p) { return p.classCount.Powerhouse == 6 ? 150 : 0; }, + }, + 1436: { + atkStatic: function(p) { return p.classCount.Powerhouse == 6 ? 150 : 0; }, + }, + 1443: { + hpStatic: function(p) { return p.classCount.Powerhouse == 6 ? 150 : 0; }, + atkStatic: function(p) { return p.classCount.Powerhouse == 6 ? 50 : 0; }, + }, + 1444: { + hpStatic: function(p) { return p.classCount.Powerhouse == 6 ? 150 : 0; }, + atkStatic: function(p) { return p.classCount.Powerhouse == 6 ? 50 : 0; }, + }, + 1464: { + rcvAdded: function(p) { return 100; }, + }, + 1465: { + rcvAdded: function(p) { return 100; }, + }, + 1476: { + atkStatic: function(p) { return 50; }, + rcvStatic: function(p) { return 50; }, + hpStatic: function(p) { return 50; }, + }, + 1477: { + atkStatic: function(p) { return 50; }, + rcvStatic: function(p) { return 50; }, + hpStatic: function(p) { return 50; }, + }, + 1507: { + atkStatic: function(p) { return 15; }, + }, + 1508: { + atkStatic: function(p) { return 15; }, + }, + 1510: { + atkStatic: function(p) { return p.percHP >= 70.0 && p.unit.class.has("Striker") ? 20 : 0; }, + }, + 1511: { + atkStatic: function(p) { return p.captain != null ? p.captain.class.has("Powerhouse") ? p.unit.class.has("Powerhouse") ? 20 : 0 : 0 : 0; }, + }, + 1523: { + rcvAdded: function(p) { return 124; }, + }, + 1524: { + rcvAdded: function(p) { return 124; }, + }, + 1529: { + atk: function(p) { return p.captain != null ? p.captain.type == "STR" || p.captain.type == "QCK" ? .5 : 1 : 1; }, + }, + 1530: { + atk: function(p) { return p.captain != null ? p.captain.type == "STR" || p.captain.type == "QCK" ? .5 : 1 : 1; }, + }, + 1537: { + hpStatic: function(p) { return p.unit.type == "STR" ? 150 : 0; }, + }, + 1538: { + hpStatic: function(p) { return p.unit.type == "STR" ? 150 : 0; }, + }, + 1539: { + atkStatic: function(p) { return p.unit.type == "INT" ? 50 : 0; }, + }, + 1540: { + atkStatic: function(p) { return p.unit.type == "INT" ? 50 : 0; }, + }, + 1574: { + atkStatic: function(p) { return p.percHP <= 30.0 && p.slot == p.sourceSlot ? 200 : 0; }, + }, + 1575: { + atkStatic: function(p) { return p.percHP <= 30.0 && p.slot == p.sourceSlot ? 200 : 0; }, + }, + 1613: {//not working + staticMult: function(p) { return 2; } + }, + 1614: {//not working + staticMult: function(p) { return 2; } + }, + 1655: { + atkStatic: function(p) { return p.unit.type == "QCK" ? 75 : 0; }, + rcvStatic: function(p) { return p.unit.type == "QCK" ? 75 : 0; }, + }, + 1656: { + atkStatic: function(p) { return p.unit.type == "QCK" ? 75 : 0; }, + rcvStatic: function(p) { return p.unit.type == "QCK" ? 75 : 0; }, + }, + 1681: { + atkStatic: function(p) { return 56; }, + hpStatic: function(p) { return 56; }, + }, + 1682: { + atkStatic: function(p) { return 56; }, + hpStatic: function(p) { return 56; }, + }, + 1699: { + atkStatic: function(p) { return p.unit.class.has("Fighter") ? 75 : 0; }, + }, + 1700: { + atkStatic: function(p) { return p.unit.class.has("Fighter") ? 75 : 0; }, + }, + 1728: { + atkStatic: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 30 : 0; }, + rcvStatic: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 30 : 0; }, + hpStatic: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 30 : 0; }, + }, + 1729: { + atkStatic: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 30 : 0; }, + rcvStatic: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 30 : 0; }, + hpStatic: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 30 : 0; }, + }, + 1705: { + atkStatic: function(p) { return 50; }, + rcvStatic: function(p) { return 50; }, + hpStatic: function(p) { return 50; }, + }, + 1706: { + atkStatic: function(p) { return 50; }, + rcvStatic: function(p) { return 50; }, + hpStatic: function(p) { return 50; }, + }, + 1752: { + atkStatic: function(p) { return p.unit.class.has("Slasher") ? 20 : 0; }, + }, + 1753: { + atkStatic: function(p) { return p.unit.class.has("Slasher") ? 20 : 0; }, + }, + 1754: { + atkStatic: function(p) { return 40; }, + rcvStatic: function(p) { return 40; }, + hpStatic: function(p) { return 40; }, + }, + 1755: { + atkStatic: function(p) { return 40; }, + rcvStatic: function(p) { return 40; }, + hpStatic: function(p) { return 40; }, + }, + 1773: { + atkStatic: function(p) { return p.unit.class.has("Free Spirit") ? 25 : 0; }, + }, + 1774: { + atkStatic: function(p) { return p.unit.class.has("Free Spirit") ? 25 : 0; }, + }, + 1797: { + atkStatic: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 75 : 0; }, + hpStatic: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 75 : 0; }, + }, + 1798: { + atkStatic: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 75 : 0; }, + hpStatic: function(p) { return p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK" ? 75 : 0; }, + }, +}; \ No newline at end of file diff --git a/common/data/ships.js b/common/data/ships.js index 04b900f6a..39e26223c 100644 --- a/common/data/ships.js +++ b/common/data/ships.js @@ -77,9 +77,9 @@ window.ships = [ { // 5 name: 'Miss Love Duck', thumb: 'ship_0006_c.png', - description: 'Reduces damage received by 10%, boosts ATK of each character by 100 units', + description: 'Reduces damage received by 10%, boosts ATK of Striker characters by 100 units', atkStatic: function(p) { - return p.boatLevel < 7 ? 0 : [ 50, 50, 50, 100 ][p.boatLevel - 7]; + return !p.unit.class.has('Striker') ? 0 : [ 0, 0, 0, 0, 0, 0, 50, 50, 50, 100 ][p.boatLevel -1]; } }, @@ -134,7 +134,7 @@ window.ships = [ { // 10 name: 'Aokiji\'s Bike', - thumb: null, + thumb: 'ship_0011_c1.png', description: 'Boosts ATK and HP of Striker characters by 1.5x, greatly reduces the appearance of RCV orbs', atk: function(p) { return !p.unit.class.has('Striker') ? 1 : @@ -148,7 +148,7 @@ window.ships = [ { // 11 name: 'Ace\'s Striker', - thumb: null, + thumb: 'ship_0012_c1.png', description: 'Boosts ATK of Shooter characters by 1.5x and their HP by 1.3x, reduces cooldown of all specials by 1 turn at the start of the fight', atk: function(p) { return !p.unit.class.has('Shooter') ? 1 : @@ -176,6 +176,283 @@ window.ships = [ atk: function(p) { return [ 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.5 ][p.boatLevel - 1]; } - } + }, + + { //14 + name: 'Kuja Pirate Ship', + thumb: 'ship_0015_c1.png', + description: 'Boosts ATK of Free Spirit characters by 1.5x and their HP by 1.35x, reduces the HP of everyone else by 99%. Special: heals the crew by 6,500HP (cooldown: 15 turns).', + atk: function(p) { + return !p.unit.class.has('Free Spirit') ? 1 : + [ 1.2, 1.2, 1.2, 1.2, 1.2, 1.3, 1.3, 1.3, 1.4, 1.5 ][p.boatLevel - 1]; + }, + hp: function(p) { + return !p.unit.class.has('Free Spirit') ? 0.01 : + [ 1.2, 1.2, 1.2, 1.2, 1.2, 1.3, 1.3, 1.3, 1.3, 1.35 ][p.boatLevel - 1]; + } + }, + + { //15 + name: 'Ark Maxim', + thumb: 'ship_0016_c1.png', + description: 'Boosts ATK of QCK and PSY characters by 1.5x and their HP by 1.2x. Special: Deals 56560 fixed Damage to all enemies (cooldown: 17 Turns)', + atk: function(p) { + return p.unit.type == "PSY" || p.unit.type == "QCK" ? [ 1.2, 1.2, 1.2, 1.2, 1.2, 1.3, 1.3, 1.3, 1.4, 1.5 ][p.boatLevel - 1] : 1; + }, + hp: function(p) { + return p.unit.type == "PSY" || p.unit.type == "QCK" ? [ 1, 1, 1, 1, 1, 1.1, 1.1, 1.1, 1.1, 1.2 ][p.boatLevel - 1] : 1; + } + }, + + { // 16 + name: 'Red Force', + thumb: 'ship_0017_c1.png', + description: 'Boosts ATK of Cerebral characters by 1.5x and their HP by 1.35x, Increased Orb Rate for Cerebral characters.', + atk: function(p) { + return !p.unit.class.has('Cerebral') ? 1 : [ 1.0, 1.2, 1.2, 1.2, 1.25, 1.3, 1.4, 1.4, 1.4, 1.5 ][p.boatLevel - 1]; + }, + hp: function(p) { + return !p.unit.class.has('Cerebral') ? 1 : [ 1.1, 1.1, 1.2, 1.2, 1.2, 1.2, 1.2, 1.3, 1.3, 1.35 ][p.boatLevel - 1]; + } + }, + + { // 17 + name: '2nd Anniversary Thousand Sunny', + thumb: 'ship_0018_c1.png', + //description: 'Boosts ATK by 1.5x. At the start of the adventure, all specials start at MAX charge.', + description: 'Boosts ATK by 1.2x.', + atk: function(p) { return 1.2; }, + }, + + { // 18 + name: 'Sun Pirates Ship', + thumb: 'ship_0019_c.png', + description: 'Boosts ATK and HP of Fighter characters depending on the number of Fighters on the team. Sharply reduces ATK and HP of non-Fighter units.', + atk: function(p) { + return !p.unit.class.has('Fighter') ? .05 : + [ p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.01 : p.classCount.Fighter == 3 ? 1.02 : p.classCount.Fighter == 4 ? 1.03 : p.classCount.Fighter == 5 ? 1.04 : p.classCount.Fighter == 6 ? 1.05 : 0, p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.02 : p.classCount.Fighter == 3 ? 1.03 : p.classCount.Fighter == 4 ? 1.04 : p.classCount.Fighter == 5 ? 1.05 : p.classCount.Fighter == 6 ? 1.1 : 0, p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.02 : p.classCount.Fighter == 3 ? 1.03 : p.classCount.Fighter == 4 ? 1.05 : p.classCount.Fighter == 5 ? 1.1 : p.classCount.Fighter == 6 ? 1.15 : 0, p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.02 : p.classCount.Fighter == 3 ? 1.05 : p.classCount.Fighter == 4 ? 1.1 : p.classCount.Fighter == 5 ? 1.15 : p.classCount.Fighter == 6 ? 1.2 : 0, p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.05 : p.classCount.Fighter == 3 ? 1.1 : p.classCount.Fighter == 4 ? 1.15 : p.classCount.Fighter == 5 ? 1.2 : p.classCount.Fighter == 6 ? 1.25 : 0, p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.05 : p.classCount.Fighter == 3 ? 1.1 : p.classCount.Fighter == 4 ? 1.15 : p.classCount.Fighter == 5 ? 1.2 : p.classCount.Fighter == 6 ? 1.3 : 0, p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.1 : p.classCount.Fighter == 3 ? 1.15 : p.classCount.Fighter == 4 ? 1.2 : p.classCount.Fighter == 5 ? 1.25 : p.classCount.Fighter == 6 ? 1.35 : 0, p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.1 : p.classCount.Fighter == 3 ? 1.15 : p.classCount.Fighter == 4 ? 1.2 : p.classCount.Fighter == 5 ? 1.3 : p.classCount.Fighter == 6 ? 1.4 : 0, p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.1 : p.classCount.Fighter == 3 ? 1.15 : p.classCount.Fighter == 4 ? 1.2 : p.classCount.Fighter == 5 ? 1.3 : p.classCount.Fighter == 6 ? 1.45 : 0, p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.1 : p.classCount.Fighter == 3 ? 1.2 : p.classCount.Fighter == 4 ? 1.3 : p.classCount.Fighter == 5 ? 1.4 : p.classCount.Fighter == 6 ? 1.5 : 0][p.boatLevel - 1]; + }, + hp: function(p) { + return !p.unit.class.has('Fighter') ? .05 : + [ p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.01 : p.classCount.Fighter == 3 ? 1.02 : p.classCount.Fighter == 4 ? 1.03 : p.classCount.Fighter == 5 ? 1.04 : p.classCount.Fighter == 6 ? 1.05 : 0, p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.02 : p.classCount.Fighter == 3 ? 1.03 : p.classCount.Fighter == 4 ? 1.04 : p.classCount.Fighter == 5 ? 1.05 : p.classCount.Fighter == 6 ? 1.1 : 0, p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.02 : p.classCount.Fighter == 3 ? 1.03 : p.classCount.Fighter == 4 ? 1.05 : p.classCount.Fighter == 5 ? 1.1 : p.classCount.Fighter == 6 ? 1.15 : 0, p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.02 : p.classCount.Fighter == 3 ? 1.05 : p.classCount.Fighter == 4 ? 1.1 : p.classCount.Fighter == 5 ? 1.15 : p.classCount.Fighter == 6 ? 1.2 : 0, p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.05 : p.classCount.Fighter == 3 ? 1.1 : p.classCount.Fighter == 4 ? 1.15 : p.classCount.Fighter == 5 ? 1.2 : p.classCount.Fighter == 6 ? 1.25 : 0, p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.05 : p.classCount.Fighter == 3 ? 1.1 : p.classCount.Fighter == 4 ? 1.15 : p.classCount.Fighter == 5 ? 1.2 : p.classCount.Fighter == 6 ? 1.3 : 0, p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.1 : p.classCount.Fighter == 3 ? 1.15 : p.classCount.Fighter == 4 ? 1.2 : p.classCount.Fighter == 5 ? 1.25 : p.classCount.Fighter == 6 ? 1.35 : 0, p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.1 : p.classCount.Fighter == 3 ? 1.15 : p.classCount.Fighter == 4 ? 1.2 : p.classCount.Fighter == 5 ? 1.3 : p.classCount.Fighter == 6 ? 1.4 : 0, p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.1 : p.classCount.Fighter == 3 ? 1.15 : p.classCount.Fighter == 4 ? 1.2 : p.classCount.Fighter == 5 ? 1.3 : p.classCount.Fighter == 6 ? 1.45 : 0, p.classCount.Fighter == 1 ? 1 : p.classCount.Fighter == 2 ? 1.1 : p.classCount.Fighter == 3 ? 1.2 : p.classCount.Fighter == 4 ? 1.3 : p.classCount.Fighter == 5 ? 1.4 : p.classCount.Fighter == 6 ? 1.5 : 0][p.boatLevel - 1]; + } + }, + + { // 19 + name: "Doflamingo Ship", + thumb: 'ship_0020_c.png', + description: 'Boosts ATK of Driven Characters by 1.5x and their HP by 1.35x. Makes Perfects easier to Hit for Driven characters. Special: Adds 0.2 to Chain (cooldown MAX: 15 Turns)', + atk: function(p) { return !p.unit.class.has('Driven') ? 1 : [ 1.2, 1.2, 1.3, 1.3, 1.3, 1.3, 1.4, 1.4, 1.4, 1.5][p.boatLevel - 1]}, + hp: function(p) { return !p.unit.class.has('Driven') ? 1 : [ 1.1, 1.1, 1.1, 1.15, 1.2, 1.2, 1.2, 1.2, 1.2, 1.35][p.boatLevel - 1]} + }, + + { // 19.2 + name: "Doflamingo Ship - Special ACTIVATED", + thumb: 'ship_0020_c.png', + description: 'Boosts ATK of Driven Characters by 1.5x and their HP by 1.35x. Makes Perfects easier to Hit for Driven characters. ACTIVATED Special: Adds 0.2 to Chain (cooldown MAX: 15 Turns)', + atk: function(p) { return !p.unit.class.has('Driven') ? 1 : [ 1.2, 1.2, 1.3, 1.3, 1.3, 1.3, 1.4, 1.4, 1.4, 1.5][p.boatLevel - 1]}, + hp: function(p) { return !p.unit.class.has('Driven') ? 1 : [ 1.1, 1.1, 1.1, 1.15, 1.2, 1.2, 1.2, 1.2, 1.2, 1.35][p.boatLevel - 1]} + }, + + { // 20 + name: 'The Rocket Man', + thumb: 'ship_0021_c.png', + description: 'Boosts ATK of Powerhouse characters by 1.55x, and heals at the end of every turn for a variable amount depending on the number of Powerhouse characters on the team. (At MAX, heals 900 per turn with 6 Powerhouse characters) Sharply reduces HP of non-Powerhouse units. Special: Deals 99,999 typeless damage to one unit. (cooldown MAX: 17 Turns)', + atk: function(p) { + return !p.unit.class.has('Powerhouse') ? 1 : [ 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.4, 1.55 ][p.boatLevel - 1]; + }, + hp: function(p) { + return p.unit.class.has('Powerhouse') ? 1 : 0.01; + }, + heal: function(p) { + return p.classCount.Powerhouse == 1 ? 1 : p.classCount.Powerhouse == 2 ? 10 : p.classCount.Powerhouse == 3 ? 20 : p.classCount.Powerhouse == 4 ? 30 : p.classCount.Powerhouse == 5 ? 100 : p.classCount.Powerhouse == 6 ? 900 : 0; + }, + + }, + + { // 21 + name: 'Burning Whitebeard Ship', + thumb: 'ship_0022_c.png', + //description: 'Boosts ATK by 1.5x and HP by 1.4x, reduces HP by 7% at the end of the turn. Special: Cuts the current HP of each enemy by 20% (cooldown: 18 turns).', + description: 'Boosts HP by 1.3x.', + hp: function(p) { + return 1.3; + }, + }, + + { // 22 + name: 'Garp Ship', + thumb: 'ship_0023_c.png', + description: 'Boosts ATK of [STR] and [PSY] characters by 1.5x, and their HP by 1.25x', + atk: function(p) { + return p.unit.type == "PSY" || p.unit.type == "STR" ? [ 1.2, 1.25, 1.25, 1.3, 1.35, 1.35, 1.4, 1.4, 1.45, 1.5 ][p.boatLevel - 1] : 1; + }, + hp: function(p) { + return p.unit.type == "PSY" || p.unit.type == "STR" ? [ 1.1, 1.1, 1.15, 1.15, 1.15, 1.2, 1.2, 1.25, 1.25, 1.25 ][p.boatLevel - 1] : 1; + }, + }, + + { //23 + name: 'Polar Tang', + thumb: 'ship_0024_c.png', + description: 'Boosts ATK of Slashers and Free Spirit characters by 1.5x and their HP by 1.25x. Makes Perfects easier to Hit. Special: Heals for 10k when under 20% HP. (cooldown MAX: 18 turns)', + atk: function(p) { + return !(p.unit.class.has('Slasher') || p.unit.class.has('Free Spirit')) ? 1 : [ 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.4, 1.4, 1.4, 1.5 ][p.boatLevel - 1]; + }, + hp: function(p) { + return !(p.unit.class.has('Slasher') || p.unit.class.has('Free Spirit')) ? 1 : [ 1.1, 1.1, 1.1, 1.1, 1.2, 1.2, 1.2, 1.2, 1.25, 1.25 ][p.boatLevel - 1]; + }, + }, + { // 24 + name: 'New Year\'s Big Top', + thumb: 'ship_0025_c.png', + description: 'Boosts ATK of characters with 20 cost or less by 1.2x', + atk: function(p) { + return p.unit.cost <= 20 ? 1.2 : 1; + } + }, + { // 25 + name: 'Thousand Sunny: Coated', + thumb: 'ship_0026_c.png', + description: 'Boosts ATK by 1.5x. Special: reduces damage received by 50% for 1 turn (cooldown: 16 turns).', + atk: function(p) { + return [ 1.3, 1.3, 1.3, 1.3, 1.35, 1.35, 1.35, 1.4, 1.45, 1.5 ][p.boatLevel - 1]; + } + }, + { // 26 + name: 'Kizaru\'s Cannonball', + thumb: 'ship_0027_c.png', + description: 'Boosts ATK of Shooter characters by 1.55x and their HP by 1.2x, reduces cooldown of Shooter characters specials by 2 turns at the start of the fight. Special: Cuts the current HP of each enemy by 7% (cooldown: 15 turns).', + atk: function(p) { + return !(p.unit.class.has('Shooter')) ? 1 : [ 1.2, 1.2, 1.3, 1.3, 1.3, 1.4, 1.4, 1.4, 1.4, 1.55 ][p.boatLevel - 1]; + }, + hp: function(p) { + return !(p.unit.class.has('Shooter')) ? 1 : [ 1.1, 1.1, 1.1, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ][p.boatLevel - 1]; + } + }, + + { // 27 + name: 'Going Luffy SENPAI!', + thumb: 'ship_0028_c.png', + description: 'Boosts ATK of Striker characters by 1.5x and their HP by 1.2x if there are 6 Striker characters in your crew. Reduces special cooldown of Striker characters by 1 at the start of the adventure. Special: Reduces any damage received above 10,000 HP by 97% (cooldown: 17 turns).', + atk: function(p) { + return !(p.classCount.Striker == 6) ? 1 : !p.unit.class.has('Striker') ? 1 : + [ 1.1, 1.2, 1.2, 1.2, 1.2, 1.3, 1.3, 1.4, 1.4, 1.5 ][p.boatLevel - 1]; + }, + hp: function(p) { + return !(p.classCount.Striker == 6) ? 1 : !p.unit.class.has('Striker') ? 1 : + [ 1.1, 1.1, 1.1, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ][p.boatLevel - 1]; + } + }, + + { //28 + name: "Thriller Bark", + thumb: 'ship_0029_c.png', + description: 'Boosts ATK of [DEX] and [INT] characters by 1.5x and their HP by 1.25x', + atk: function(p) { + return p.unit.type == "DEX" || p.unit.type == "INT" ? [ 1.2, 1.25, 1.25, 1.3, 1.35, 1.35, 1.4, 1.4, 1.45, 1.5 ][p.boatLevel - 1] : 1; + }, + hp: function(p) { + return p.unit.type == "DEX" || p.unit.type == "INT" ? [ 1.1, 1.1, 1.15, 1.15, 1.15, 1.2, 1.2, 1.25, 1.25, 1.25 ][p.boatLevel - 1] : 1; + }, + }, + + { //29 + name: "Karasumaru Ship", + thumb: 'ship_0030_c.png', + //description: 'Boosts ATK and HP of Shooter Only characters by 2x and boosts the ATK of all other characters by 1.5x and their HP by 1.02x. Special: Delays all enemies for 2 turns (cooldown: 12 turns).', + description: 'Boosts ATK and Shooter characters by 1.2x. Special: Delays all enemies for 1 turn (cooldown: 16 turns).', + /*atk: function(p) { + return !(p.unit.class.has('Slasher') || p.unit.class.has('Striker') || p.unit.class.has('Fighter') || p.unit.class.has('Free Spirit') || p.unit.class.has('Cerebral') || p.unit.class.has('Powerhouse') || p.unit.class.has('Driven')) ? 2 : 1.5; + }, + hp: function(p) { + return !(p.unit.class.has('Slasher') || p.unit.class.has('Striker') || p.unit.class.has('Fighter') || p.unit.class.has('Free Spirit') || p.unit.class.has('Cerebral') || p.unit.class.has('Powerhouse') || p.unit.class.has('Driven')) ? 2 : 1.02; + },*/ + atk: function(p) { return p.unit.class.has("Shooter") ? 1.2 : 1; }, + }, + + { //29.2 + name: "Karasumaru Ship - Special ACTIVATED", + thumb: 'ship_0030_c.png', + //description: 'Boosts ATK and HP of Shooter Only characters by 2x and boosts the ATK of all other characters by 1.5x and their HP by 1.02x. Special: Delays all enemies for 2 turns (cooldown: 12 turns).', + description: 'Boosts ATK and Shooter characters by 1.2x. ACTIVATED Special: Delays all enemies for 1 turn (cooldown: 16 turns).', + /*atk: function(p) { + return !(p.unit.class.has('Slasher') || p.unit.class.has('Striker') || p.unit.class.has('Fighter') || p.unit.class.has('Free Spirit') || p.unit.class.has('Cerebral') || p.unit.class.has('Powerhouse') || p.unit.class.has('Driven')) ? 2 : 1.5; + }, + hp: function(p) { + return !(p.unit.class.has('Slasher') || p.unit.class.has('Striker') || p.unit.class.has('Fighter') || p.unit.class.has('Free Spirit') || p.unit.class.has('Cerebral') || p.unit.class.has('Powerhouse') || p.unit.class.has('Driven')) ? 2 : 1.02; + },*/ + atk: function(p) { return p.unit.class.has("Shooter") ? 1.2 : 1; }, + }, + + + + { //30 + name: "3rd Anniversary Thousand Sunny", + thumb: 'ship_0032_c.png', + //description: 'Boosts ATK by 1.5x. At the start of the adventure, all specials start at MAX charge.', + description: 'Boosts ATK by 1.2x.', + atk: function(p) { return 1.2; }, + }, + + + + { //31 + name: "Flying Dutchman", + thumb: 'ship_0033_c.png', + description: 'Boosts ATK by 1.5x. Boosts EXP gained by 1.5x. Special: Reduces the defense of all enemies by 25% for 1 turn (cooldown: 16 turns).', + atk: function(p) { return [ 1.2, 1.2, 1.3, 1.3, 1.4, 1.4, 1.4, 1.4, 1.4, 1.5 ][p.boatLevel - 1]; }, + }, + + + + { //31.2 + name: "Flying Dutchman - Special ACTIVATED", + thumb: 'ship_0033_c.png', + description: 'Boosts ATK by 1.5x. Boosts EXP gained by 1.5x. ACTIVATED Special: Reduces the defense of all enemies by 25% for 1 turn (cooldown: 16 turns).', + atk: function(p) { return [ 1.2, 1.2, 1.3, 1.3, 1.4, 1.4, 1.4, 1.4, 1.4, 1.5 ][p.boatLevel - 1]; }, + }, + + + + { //32 + name: "Marshal D. Teach Pirate Ship", + thumb: 'ship_0034_c.png', + description: 'Boosts HP by 1.25x and reduces special cooldown of all characters by 1 at the start of the adventure. Boosts ATK by 1.55x if you have a Striker, Shooter, Fighter, and Slasher character on your crew.', + atk: function(p) { + return (p.classCount.Striker >= 1 && p.classCount.Fighter >= 1 && p.classCount.Shooter >= 1 && p.classCount.Slasher >= 1) ? [ 1.2, 1.2, 1.25, 1.3, 1.35, 1.4, 1.45, 1.5, 1.5, 1.55 ][p.boatLevel - 1] : 1; + }, + hp: function(p) { + return [ 1.1, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.25 ][p.boatLevel - 1]; + } + }, + + + + { //33 + name: "Revolutionary Black Crow", + thumb: 'ship_0035_c.png', + description: 'Boosts HP by 1.2x and reduces special cooldown of all characters by 1 at the start of the adventure. Boosts ATK of [STR], [DEX] and [QCK] characters by 1.55x if you have a [STR], [DEX] and [QCK] character on your crew.', + atk: function(p) { + return (p.colorCount.STR>=1 && p.colorCount.DEX>=1 && p.colorCount.QCK>=1) ? [ 1.2, 1.2, 1.25, 1.3, 1.35, 1.4, 1.45, 1.5, 1.5, 1.55 ][p.boatLevel - 1] : 1; + }, + hp: function(p) { + return [ 1.1, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ][p.boatLevel - 1]; + } + }, + + + + { //34 + name: "Zunisha", //Levels are placeholders, specific boost of each one is unkown + thumb: null, + description: 'Boost ATK of Powerhouse and Cerebral units by 1.55x and their HP by 1.25x, makes Perfects easier to hit, and makes TND and Meat orbs beneficial to Powerhouse and Cerebral units.', + atk: function(p) { + return !(p.unit.class.has('Powerhouse') || p.unit.class.has('Cerebral')) ? 1 : [ 1.55, 1.55, 1.55, 1.55, 1.55, 1.55, 1.55, 1.55, 1.55, 1.55 ][p.boatLevel - 1]; + }, + hp: function(p) { + return !(p.unit.class.has('Powerhouse') || p.unit.class.has('Cerebral')) ? 1 : [ 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25 ][p.boatLevel - 1]; + }, + }, ]; diff --git a/common/data/specials.js b/common/data/specials.js index 38da34691..9949364d7 100644 --- a/common/data/specials.js +++ b/common/data/specials.js @@ -1,1036 +1,3855 @@ window.specials = { - 18: { - def: function(p) { return 0.5; } - }, - 24: { - def: function(p) { return 0.5; } - }, - 34: { - def: function(p) { return 0; } - }, - 127: { - def: function(p) { return 0.5; } - }, - 137: { - def: function(p) { return 0.5; } - }, - 148: { - def: function(p) { return 0.5; } - }, - 158: { - def: function(p) { return 0.5; } - }, - 206: { - def: function(p) { return 0.5; } - }, - 209: { - atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, - type: "type" - }, - 210: { - atk: function(p) { return p.unit.type == "INT" ? 2 : 1; }, - type: "type" - }, - 222: { - atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, - type: "type" - }, - 223: { - atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; }, - type: "type" - }, - 263: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); } - }, - 267: { - def: function(p) { return 0.5; } - }, - 275: { - def: function(p) { return 0.5; } - }, - 285: { - def: function(p) { return 0.5; } - }, - 295: { - def: function(p) { return 0.5; } - }, - 309: { - def: function(p) { return 0.5; } - }, - 310: { - def: function(p) { return 0.5; } - }, - 313: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, - type: "class" - }, - 314: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, - type: "class" - }, - 323: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); } - }, - 324: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); } - }, - 352: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.75 : 1; }, - type: "class" - }, - 353: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.75 : 1; }, - type: "class" - }, - 382: { - def: function(p) { return 0.5; } - }, - 385: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.25 : 1; }, - type: "class" - }, - 386: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.25 : 1; }, - type: "class" - }, - 391: { - def: function(p) { return 0.2; } - }, - 392: { - def: function(p) { return 0.2; } - }, - 395: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.25); } - }, - 396: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.25); } - }, - 399: { - atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, - type: "type" - }, - 400: { - atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, - type: "type" - }, - 401: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.25 : 1; }, - type: "class" - }, - 402: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.25 : 1; }, - type: "class" - }, - 404: { - rcv: function(p) { return 2; } - }, - 405: { - rcv: function(p) { return 2; } - }, - 406: { - atk: function(p) { return 1.2; }, - type: "type" - }, - 417: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 2); } - }, - 418: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 2); } - }, - 419: { - def: function(p) { return 0.5; } - }, - 423: { - def: function(p) { return 0.5; } - }, - 424: { - def: function(p) { return 0.5; } - }, - 426: { - atk: function(p) { return p.unit.type == "STR" ? 1.05 : 1; }, - type: "type" - }, - 429: { - def: function(p) { return 0.5; } - }, - 430: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); } - }, - 431: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); } - }, - 434: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.25); } - }, - 450: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, - type: "class" - }, - 451: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, - type: "class" - }, - 454: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, - type: "type" - }, - 455: { - atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, - type: "type" - }, - 458: { - atk: function(p) { return 1.5; }, - type: "type" - }, - 459: { - atk: function(p) { return 1.5; }, - type: "type" - }, - 461: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.25 : 1; }, - type: "class" - }, - 462: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.25 : 1; }, - type: "class" - }, - 465: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.25); } - }, - 468: { - rcv: function(p) { return 1.5; } - }, - 470: { - rcv: function(p) { return 1.5; } - }, - 487: { - atk: function(p) { return p.unit.type == "STR" ? 1.2 : 1; }, - type: "type" - }, - 488: { - atk: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; }, - type: "type" - }, - 489: { - atk: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; }, - type: "type" - }, - 490: { - atk: function(p) { return p.unit.type == "STR" ? 1.2 : 1; }, - type: "type" - }, - 491: { - atk: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; }, - type: "type" - }, - 492: { - atk: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; }, - type: "type" - }, - 505: { - atk: function(p) { return p.unit.type == "QCK" ? 1.25 : 1; }, - type: "type" - }, - 506: { - atk: function(p) { return p.unit.type == "QCK" ? 1.25 : 1; }, - type: "type" - }, - 509: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, - type: "class" - }, - 510: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, - type: "class" - }, - 511: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.25 : 1; }, - type: "class" - }, - 514: { - def: function(p) { return 0.5; }, - atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, - type: "type" - }, - 517: { - atk: function(p) { return 1.05; }, - type: "type" - }, - 518: { - atk: function(p) { return 1.05; }, - type: "type" - }, - 519: { - atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, - type: "type" - }, - 520: { - atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, - type: "type" - }, - 529: { - def: function(p) { return 0; } - }, - 530: { - def: function(p) { return 0; } - }, - 533: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); } - }, - 534: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); } - }, - 542: { - rcv: function(p) { return 2; } - }, - 545: { - atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, - type: "type" - }, - 546: { - atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, - type: "type" - }, - 549: { - atk: function(p) { return p.defenseDown ? 1.3 : 1; }, - type: "condition" - }, - 550: { - atk: function(p) { return p.defenseDown ? 1.3 : 1; }, - type: "condition" - }, - 559: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); } - }, - 560: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); } - }, - 568: { - def: function(p) { return 0.5; } - }, - 569: { - def: function(p) { return 0.5; } - }, - 572: { - atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; }, - type: "class", - onActivation: function(p) { p.tdata.lock = Math.max(1, p.tdata.lock); }, - onDeactivation: function(p) { if (p.tdata.lock == 1) p.tdata.lock = 0; } - }, - 574: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.75 : 1; }, - type: "class" - }, - 575: { - atk: function(p) { return p.unit.class.has("Striker") ? 1.75 : 1; }, - type: "class" - }, - 576: { - rcv: function(p) { return 1.5; } - }, - 582: { - atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, - type: "type" - }, - 589: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, - type: "class" - }, - 590: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, - type: "class" - }, - 596: { - def: function(p) { return 0.5; } - }, - 597: { - def: function(p) { return 0.5; } - }, - 600: { - atk: function(p) { return p.unit.type == "PSY" ? 1.3 : 1; }, - type: "type" - }, - 601: { - atk: function(p) { return p.unit.type == "PSY" ? 1.3 : 1; }, - type: "type" - }, - 602: { - atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, - type: "type" - }, - 603: { - atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, - type: "type" - }, - 612: { - atkStatic: function(p) { return 45; }, - rcvStatic: function(p) { return 45; }, - type: "type" - }, - 613: { - atkStatic: function(p) { return 45; }, - rcvStatic: function(p) { return 45; }, - type: "type" - }, - 614: { - def: function(p) { return 0.5; } - }, - 617: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.2 : 1; }, - type: "class" - }, - 622: { - rcvStatic: function(p) { return 100; }, - type: "type" - }, - 632: { - def: function(p) { return 0.5; } - }, - 633: { - def: function(p) { return 0.5; } - }, - 634: { - atk: function(p) { return p.unit.type == "QCK" || p.unit.type == "PSY" ? 1.2 : 1; }, - type: "type" - }, - 635: { - atk: function(p) { return p.unit.type == "QCK" || p.unit.type == "PSY" ? 1.2 : 1; }, - type: "type" - }, - 637: { - atk: function(p) { return 1.3; }, - type: "condition", - warning: "Selected special (%name%) assumes that the enemy has a defense buff active." - }, - 642: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.75); } - }, - 643: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.75); } - }, - 644: { - atk: function(p) { return 1.2; }, - type: "condition", - warning: "Selected special (%name%) assumes that the enemy has been delayed." - }, - 645: { - atk: function(p) { return 1.2; }, - type: "condition", - warning: "Selected special (%name%) assumes that the enemy has been delayed." - }, - 648: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); } - }, - 649: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); } - }, - 650: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); } - }, - 651: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); } - }, - 655: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.25); } - }, - 656: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.25); } - }, - 660: { - def: function(p) { return 0.5; } - }, - 661: { - def: function(p) { return 0.5; } - }, - 665: { - atk: function(p) { return p.defenseDown ? 1.3 : 1; }, - type: "condition" - }, - 666: { - atk: function(p) { return p.defenseDown ? 1.3 : 1; }, - type: "condition" - }, - 668: { - atk: function(p) { return !p.unit.class.has('Freedom') ? 1 : window.specials[668].multiplier; }, - type: "class", - onActivation: function(p) { - var n = (window.specials[668].multiplier == 1.5 ? 1 : 0); - window.specials[668].multiplier = [1.5, 2][n]; - p.scope.notify({ - text: 'Using the ' + [1.5, 2][n] + 'x ATK multiplier. To switch to the ' + [2, 1.5][n] + 'x multiplier, disable and re-enable this special', - name: '667warning' - }); - } - }, - 669: { - atk: function(p) { return !p.unit.class.has('Freedom') ? 1 : window.specials[669].multiplier; }, - type: "class", - onActivation: function(p) { - var n = (window.specials[669].multiplier == 1.5 ? 1 : 0); - window.specials[669].multiplier = [1.5, 2][n]; - p.scope.notify({ - text: 'Using the ' + [1.5, 2][n] + 'x ATK multiplier. To switch to the ' + [2, 1.5][n] + 'x multiplier, disable and re-enable this special', - name: '668warning' - }); - } - }, - 670: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.75 : 1; }, - type: "class" - }, - 671: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.75 : 1; }, - type: "class" - }, - 680: { - atk: function(p) { return p.unit.type == "DEX" ? 1.25 : 1; }, - rcv: function(p) { return p.unit.type == "DEX" ? 1.25 : 1; }, - type: "type" - }, - 681: { - atk: function(p) { return p.unit.type == "DEX" ? 1.25 : 1; }, - rcv: function(p) { return p.unit.type == "DEX" ? 1.25 : 1; }, - type: "type" - }, - 687: { - atk: function(p) { return p.unit.class.has("Freedom") ? 1.3 : 1; }, - type: "class" - }, - 688: { - atk: function(p) { return p.unit.class.has("Freedom") ? 1.3 : 1; }, - type: "class" - }, - 689: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); } - }, - 690: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); } - }, - 710: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.25 : 1; }, - type: "class" - }, - 711: { - atk: function(p) { return p.unit.class.has("Shooter") ? 1.25 : 1; }, - type: "class" - }, - 712: { - atk: function(p) { return p.slot < 2 ? 1.5 : 1; }, - type: "class" - }, - 713: { - atk: function(p) { return p.slot < 2 ? 1.5 : 1; }, - type: "class" - }, - 715: { - atk: function(p) { return p.unit.class.has("Freedom") ? 1.5 : 1; }, - type: "class" - }, - 716: { - atk: function(p) { return p.unit.class.has("Freedom") ? 1.5 : 1; }, - type: "class" - }, - 719: { - atk: function(p) { return p.unit.class.has("Knowledge") ? window.specials[719].multiplier : 1; }, - type: "class", - onActivation: function(p) { - var n = (p.percHP <= 30 ? 2 : 1.5); - window.specials[719].multiplier = n; - p.scope.notify({ - text: 'HP ' + (n == 2 ? 'below' : 'above') + ' 30%, using the ' + n + 'x multiplier.', - name: '719warning' - }); - } - }, - 720: { - atk: function(p) { return p.unit.class.has("Knowledge") ? window.specials[720].multiplier : 1; }, - type: "class", - onActivation: function(p) { - var n = (p.percHP <= 30 ? 2 : 1.5); - window.specials[720].multiplier = n; - p.scope.notify({ - text: 'HP ' + (n == 2 ? 'below' : 'above') + ' 30%, using the ' + n + 'x multiplier.', - name: '720warning' - }); - } - }, - 727: { - def: function(p) { return 0.5; } - }, - 730: { - atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, - type: "type" - }, - 731: { - atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, - type: "type" - }, - 732: { - def: function(p) { return 0.5; } - }, - 733: { - def: function(p) { return 0.5; } - }, - 740: { - atk: function(p) { return 1.3; }, - type: "condition", - warning: "Selected special (%name%) assumes that the enemy has a defense buff active." - }, - 741: { - atk: function(p) { return 1.3; }, - type: "condition", - warning: "Selected special (%name%) assumes that the enemy has a defense buff active." - }, - 742: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.25); } - }, - 743: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.25); } - }, - 753: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.75); } - }, - 754: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.75); } - }, - 755: { - atk: function(p) { return p.unit.class.has("Tough") ? 1.75 : 1; }, - type: "class" - }, - 756: { - atk: function(p) { return p.unit.class.has("Tough") ? 1.75 : 1; }, - type: "class" - }, - 761: { - atk: function(p) { return 1.2; }, - type: "type" - }, - 762: { - atk: function(p) { return p.unit.type == "PSY" ? 1.75 : 1; }, - type: "type" - }, - 770: { - atk: function(p) { return 1.3; }, - type: "condition", - warning: "Selected special (%name%) assumes that the enemy has been delayed." - }, - 771: { - atk: function(p) { return p.unit.class.has("Knowledge") ? 1.75 : 1; }, - type: "type" - }, - 780: { - atk: function(p) { return p.slot == p.sourceSlot ? window.specials[780].multiplier : 1; }, - type: "type", - onActivation: function(p) { - var n = (p.percHP <= 20 ? 2 : (p.percHP <= 50 ? 1.75 : 1.5)); - window.specials[780].multiplier = n; - p.scope.notify({ - text: 'Using the ' + n + 'x multiplier.', - name: '780warning' - }); - } - }, - 781: { - atk: function(p) { return p.slot == p.sourceSlot ? window.specials[781].multiplier : 1; }, - type: "type", - onActivation: function(p) { - var n = (p.percHP <= 20 ? 2 : (p.percHP <= 50 ? 1.75 : 1.5)); - window.specials[781].multiplier = n; - p.scope.notify({ - text: 'Using the ' + n + 'x multiplier.', - name: '781warning' - }); - } - }, - 788: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.75 : 1; }, - type: "class" - }, - 789: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.75 : 1; }, - type: "class" - }, - 790: { - atk: function(p) { return /STR|DEX|QCK/.test(p.unit.type) ? 1.2 : 1; }, - type: "type" - }, - 791: { - atk: function(p) { return /STR|DEX|QCK/.test(p.unit.type) ? 1.2 : 1; }, - type: "type" - }, - 796: { - atk: function(p) { return p.slot == p.sourceSlot ? 1.75 : 1; }, - type: "type" - }, - 797: { - atk: function(p) { return p.slot == p.sourceSlot ? 1.75 : 1; }, - type: "type" - }, - 798: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.75 : 1; }, - type: "class" - }, - 803: { - atk: function(p) { return 1.1; }, - type: "type" - }, - 804: { - atk: function(p) { return 1.1; }, - type: "type" - }, - 805: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.75); } - }, - 806: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.75); } - }, - 807: { - atk: function(p) { return p.defenseDown ? 1.3 : 1; }, - type: "condition" - }, - 808: { - atk: function(p) { return p.defenseDown ? 1.3 : 1; }, - type: "condition" - }, - 809: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); }, - def: function(p) { return 0.2; } - }, - 810: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); }, - def: function(p) { return 0.2; } - }, - 813: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.25); } - }, - 822: { - rcvStatic: function(p) { return 100; }, - type: "type" - }, - 825: { - atkStatic: function(p) { return 200; }, - type: "type" - }, - 826: { - atk: function(p) { return 0.2; }, - type: "type" - }, - 827: { - atk: function(p) { return 1.05; }, - type: "condition", - warning: "Selected special (%name%) assumes that the enemy has been poisoned." - }, - 832: { - atk: function(p) { return p.unit.class.has("Freedom") ? 1.5 : 1; }, - type: "class" - }, - 833: { - atk: function(p) { return p.unit.class.has("Freedom") ? 1.5 : 1; }, - type: "class" - }, - 835: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.75); } - }, - 836: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.75); } - }, - 837: { - atk: function(p) { return p.unit.class.has("Ambition") ? 1.75 : 1; }, - type: "class" - }, - 838: { - atk: function(p) { return p.unit.class.has("Ambition") ? 1.75 : 1; }, - type: "class" - }, - 839: { - atk: function(p) { return p.slot == p.sourceSlot ? 2 : 1; }, - type: "type" - }, - 840: { - atk: function(p) { return p.slot == p.sourceSlot ? 2 : 1; }, - type: "type" - }, - 841: { - atk: function(p) { return 1.25; }, - type: "condition", - warning: "Selected special (%name%) assumes that the enemy has been delayed." - }, - 842: { - atk: function(p) { return 1.25; }, - type: "condition", - warning: "Selected special (%name%) assumes that the enemy has been delayed." - }, - 843: { - atk: function(p) { - if (window.specials[843].stage) return p.unit.class.has("Shooter") ? 1.5 : 1; - else return p.unit.class.has("Shooter") || p.unit.class.has("Slasher") || p.unit.class.has("Striker") ? 1.5 : 1; - }, - type: "class", - onActivation: function(p) { - window.specials[843].multiplier = !window.specials[843].multiplier; - p.scope.notify({ - text: (window.specials[843].multiplier ? - 'Boosting Shooters. To switch to the second multiplier, disable and re-enable this special' : - 'Boosting Shooters, Slashers and Strikers. To switch to the first multiplier, disable and re-enable this special'), - name: '843warning' - }); - } - }, - 844: { - atk: function(p) { - if (window.specials[844].stage) return p.unit.class.has("Shooter") ? 1.5 : 1; - else return p.unit.class.has("Shooter") || p.unit.class.has("Slasher") || p.unit.class.has("Striker") ? 1.5 : 1; - }, - type: "class", - onActivation: function(p) { - window.specials[844].multiplier = !window.specials[844].multiplier; - p.scope.notify({ - text: (window.specials[844].multiplier ? - 'Boosting Shooters. To switch to the second multiplier, disable and re-enable this special' : - 'Boosting Shooters, Slashers and Strikers. To switch to the first multiplier, disable and re-enable this special'), - name: '844warning' - }); - } - }, - 847: { - atk: function(p) { return 1.05; }, - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.15); }, - type: "class" - }, - 848: { - atk: function(p) { return 1.05; }, - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.15); }, - type: "class" - }, - 849: { - def: function() { return 0.5; } - }, - 853: { - atk: function(p) { return p.unit.class("Tough") || p.unit.class.has("Fighter") ? 1.2 : 1; }, - type: "class" - }, - 857: { - rcv: function(p) { return p.unit.type == 'PSY' ? 1.5 : 1; }, - type: "type" - }, - 858: { - rcv: function(p) { return p.unit.type == 'PSY' ? 1.5 : 1; }, - type: "type" - }, - 861: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); } - }, - 862: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); } - }, - 863: { - def: function(p) { return 0.5; } - }, - 864: { - chain: function(p) { return 2.5; }, - chainLimiter: function(p) { return p.chainPosition > 0 ? 2.5 : 1.0; } - }, - 865: { - chain: function(p) { return 2.5; }, - chainLimiter: function(p) { return p.chainPosition > 0 ? 2.5 : 1.0; } - }, - 866: { - atk: function(p) { - return p.unit.class.has("Slasher") || p.unit.class.has("Knowledge") ? 1.3 : 1; - }, - type: "class" - }, - 869: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 2.0); } - }, - 870: { - orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, 1, 2.0); } - }, - 873: { - orb: function(p) { - if (window.specials[873].first) return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); - else return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.75); - }, - type: "class", - onActivation: function(p) { - window.specials[873].first = !window.specials[873].first; - p.scope.notify({ - text: (window.specials[873].first ? - 'Activating the first stage. To switch to the second stage, disable and re-enable this special' : - 'Activating the second stage. To switch to the first stage, disable and re-enable this special'), - name: '873warning' - }); - } - }, - 874: { - orb: function(p) { - if (window.specials[874].first) return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.5); - else return CrunchUtils.getOrbMultiplier(p.orb, 1, 1.75); - }, - type: "class", - onActivation: function(p) { - window.specials[874].first = !window.specials[874].first; - p.scope.notify({ - text: (window.specials[874].first ? - 'Activating the first stage. To switch to the second stage, disable and re-enable this special' : - 'Activating the second stage. To switch to the first stage, disable and re-enable this special'), - name: '874warning' - }); - } - }, - 881: { - atk: function(p) { - return p.unit.class.has("Shooter") || p.unit.class.has("Freedom") ? 1.75 : 1; - }, - type: "class" - }, - 882: { - atk: function(p) { - return p.unit.class.has("Shooter") || p.unit.class.has("Freedom") ? 1.75 : 1; - }, - type: "class" - }, - 883: { - atk: function(p) { return !p.unit.class.has('Tough') ? 1 : window.specials[883].multiplier; }, - type: "class", - onActivation: function(p) { - var n = (window.specials[883].multiplier == 1.5 ? 1 : 0); - window.specials[883].multiplier = [1.5, 2][n]; - p.scope.notify({ - text: 'Using the ' + [1.5, 2][n] + 'x ATK multiplier. To switch to the ' + [2, 1.5][n] + 'x multiplier, disable and re-enable this special', - name: '883warning' - }); - } - }, - 884: { - atk: function(p) { return !p.unit.class.has('Tough') ? 1 : window.specials[884].multiplier; }, - type: "class", - onActivation: function(p) { - var n = (window.specials[884].multiplier == 1.5 ? 1 : 0); - window.specials[884].multiplier = [1.5, 2][n]; - p.scope.notify({ - text: 'Using the ' + [1.5, 2][n] + 'x ATK multiplier. To switch to the ' + [2, 1.5][n] + 'x multiplier, disable and re-enable this special', - name: '884warning' - }); - } - }, - 885: { - atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, - type: "class" - }, - 886: { - atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, - type: "class" - }, - 887: { - def: function(p) { return 0.2; } - }, - 891: { - atk: function(p) { return p.unit.class.has("Tough") ? 1.25 : 1; }, - type: "class" - }, - 902: { - atk: function(p) { return !p.unit.class.has('Tough') ? 1 : window.specials[902].multiplier; }, - type: "class", - onActivation: function(p) { - var n = (window.specials[902].multiplier == 1.5 ? 1 : 0); - window.specials[902].multiplier = [1.5, 2][n]; - p.scope.notify({ - text: 'Using the ' + [1.5, 2][n] + 'x ATK multiplier. To switch to the ' + [2, 1.5][n] + 'x multiplier, disable and re-enable this special', - name: '902warning' - }); - } - }, - 903: { - atk: function(p) { return !p.unit.class.has('Tough') ? 1 : window.specials[903].multiplier; }, - type: "class", - onActivation: function(p) { - var n = (window.specials[903].multiplier == 1.5 ? 1 : 0); - window.specials[903].multiplier = [1.5, 2][n]; - p.scope.notify({ - text: 'Using the ' + [1.5, 2][n] + 'x ATK multiplier. To switch to the ' + [2, 1.5][n] + 'x multiplier, disable and re-enable this special', - name: '902warning' - }); - } - }, - 905: { - atk: function(p) { - if (!window.specials[905].stage) return p.slot == p.sourceSlot ? 1.5 : 1; - if (window.specials[905].stage == 1) return p.unit.class.has("Slasher") ? 1.5 : 1; - if (window.specials[905].stage == 2) return p.unit.class.has("Slasher") ? 1.75 : 1; - }, - type: "class", - stage: -1, - onActivation: function(p) { - window.specials[905].stage = (window.specials[905].stage + 1) % 3; - p.scope.notify({ - text: 'Activating stage #' + (window.specials[905].stage + 1) + '. To move onto the next stage, disable and re-enable this special.', - name: '905warning' - }); - } - }, - 906: { - atk: function(p) { - if (!window.specials[906].stage) return p.slot == p.sourceSlot ? 1.5 : 1; - if (window.specials[906].stage == 1) return p.unit.class.has("Slasher") ? 1.5 : 1; - if (window.specials[906].stage == 2) return p.unit.class.has("Slasher") ? 1.75 : 1; - }, - type: "class", - stage: -1, - onActivation: function(p) { - window.specials[906].stage = (window.specials[906].stage + 1) % 3; - p.scope.notify({ - text: 'Activating stage #' + (window.specials[906].stage + 1) + '. To move onto the next stage, disable and re-enable this special.', - name: '906warning' - }); - } - }, - 909: { - atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, - type: "type" - }, - 910: { - atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, - type: "type" - }, - 911: { - atk: function(p) { - if (!window.specials[911].stage) return p.unit.class.has("Tough") ? 1.2 : 1; - if (window.specials[911].stage == 1) return p.unit.class.has("Tough") ? 2 : 1; - }, - type: "class", - stage: -1, - onActivation: function(p) { - window.specials[911].stage = (window.specials[911].stage + 1) % 2; - p.scope.notify({ - text: 'Activating stage #' + (window.specials[911].stage + 1) + '. To move onto the next stage, disable and re-enable this special.', - name: '911warning' - }); - } - }, - 912: { - atk: function(p) { - if (!window.specials[912].stage) return p.unit.class.has("Tough") ? 1.2 : 1; - if (window.specials[912].stage == 1) return p.unit.class.has("Tough") ? 2 : 1; - }, - type: "class", - stage: -1, - onActivation: function(p) { - window.specials[912].stage = (window.specials[912].stage + 1) % 2; - p.scope.notify({ - text: 'Activating stage #' + (window.specials[912].stage + 1) + '. To move onto the next stage, disable and re-enable this special.', - name: '912warning' - }); - } - }, - 915: { - atk: function(p) { return p.unit.class.has("Knowledge") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Knowledge") ? 1.5 : 1; }, - type: "class" - }, - 916: { - atk: function(p) { return p.unit.class.has("Knowledge") ? 1.5 : 1; }, - rcv: function(p) { return p.unit.class.has("Knowledge") ? 1.5 : 1; }, - type: "class" - } -}; \ No newline at end of file + 13: { + delay: function(p) { return 1; }, + }, + 14: { + delay: function(p) { return 1; }, + }, + 15: { + delay: function(p) { return 1; }, + }, + 16: { + delay: function(p) { return 2; }, + }, + 18: { + def: function(p) { return 0.5; } + }, + 24: { + def: function(p) { return 0.5; } + }, + 34: { + def: function(p) { return 0; } + }, + 127: { + def: function(p) { return 0.5; } + }, + 137: { + def: function(p) { return 0.5; } + }, + 148: { + def: function(p) { return 0.5; } + }, + 158: { + def: function(p) { return 0.5; } + }, + 204: { + delay: function(p) { return 1; }, + }, + 206: { + def: function(p) { return 0.5; } + }, + 209: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + type: "type" + }, + 210: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; }, + type: "type" + }, + 222: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, + type: "type" + }, + 223: { + atk: function(p) { return p.unit.type == "PSY" ? 2 : 1; }, + type: "type" + }, + 263: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 267: { + def: function(p) { return 0.5; } + }, + 275: { + def: function(p) { return 0.5; } + }, + 285: { + def: function(p) { return 0.5; } + }, + 295: { + def: function(p) { return 0.5; } + }, + 309: { + def: function(p) { return 0.5; } + }, + 310: { + def: function(p) { return 0.5; } + }, + 313: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, + type: "class" + }, + 314: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, + type: "class" + }, + 323: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 324: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 352: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.75 : 1; }, + type: "class" + }, + 353: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.75 : 1; }, + type: "class" + }, + 382: { + def: function(p) { return 0.5; } + }, + 385: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.25 : 1; }, + type: "class" + }, + 386: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.25 : 1; }, + type: "class" + }, + 391: { + def: function(p) { return 0.2; } + }, + 392: { + def: function(p) { return 0.2; } + }, + 395: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.25, [p.friendCaptain, p.captain]); } + }, + 396: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.25, [p.friendCaptain, p.captain]); } + }, + 399: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, + type: "type" + }, + 400: { + atk: function(p) { return p.unit.type == "DEX" ? 1.5 : 1; }, + type: "type" + }, + 401: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.25 : 1; }, + type: "class" + }, + 402: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.25 : 1; }, + type: "class" + }, + 404: { + rcv: function(p) { return 2; } + }, + 405: { + rcv: function(p) { return 2; } + }, + 406: { + atk: function(p) { return 1.2; }, + type: "type" + }, + 415: { + delay: function(p) { return 1; }, + }, + 416: { + delay: function(p) { return 1; }, + }, + 417: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]); } + }, + 418: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]); } + }, + 419: { + def: function(p) { return 0.5; } + }, + 423: { + def: function(p) { return 0.5; } + }, + 424: { + def: function(p) { return 0.5; } + }, + 426: { + atk: function(p) { return p.unit.type == "STR" ? 1.05 : 1; }, + type: "type" + }, + 429: { + def: function(p) { return 0.5; } + }, + 430: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 431: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 434: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.25, [p.friendCaptain, p.captain]); } + }, + 450: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, + type: "class" + }, + 451: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, + type: "class" + }, + 454: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, + type: "type" + }, + 455: { + atk: function(p) { return p.unit.type == "STR" ? 1.5 : 1; }, + type: "type" + }, + 458: { + atk: function(p) { return 1.5; }, + type: "type" + }, + 459: { + atk: function(p) { return 1.5; }, + type: "type" + }, + 460: { + delay: function(p) { return 1; }, + }, + 461: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.25 : 1; }, + type: "class" + }, + 462: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.25 : 1; }, + type: "class" + }, + 465: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.25, [p.friendCaptain, p.captain]); } + }, + 466: { + delay: function(p) { return 1; }, + }, + 468: { + rcv: function(p) { return 1.5; } + }, + 470: { + rcv: function(p) { return 1.5; } + }, + 487: { + atk: function(p) { return p.unit.type == "STR" ? 1.2 : 1; }, + type: "type" + }, + 488: { + atk: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; }, + type: "type" + }, + 489: { + atk: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; }, + type: "type" + }, + 490: { + atk: function(p) { return p.unit.type == "STR" ? 1.2 : 1; }, + type: "type" + }, + 491: { + atk: function(p) { return p.unit.type == "QCK" ? 1.2 : 1; }, + type: "type" + }, + 492: { + atk: function(p) { return p.unit.type == "DEX" ? 1.2 : 1; }, + type: "type" + }, + 499: { + delay: function(p) { return 1; }, + }, + 500: { + delay: function(p) { return 1; }, + }, + 505: { + atk: function(p) { return p.unit.type == "QCK" ? 1.25 : 1; }, + type: "type" + }, + 506: { + atk: function(p) { return p.unit.type == "QCK" ? 1.25 : 1; }, + type: "type" + }, + 509: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, + type: "class" + }, + 510: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, + type: "class" + }, + 511: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.25 : 1; }, + type: "class" + }, + 514: { + def: function(p) { return 0.5; }, + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + type: "type" + }, + 517: { + atk: function(p) { return 1.05; }, + type: "type" + }, + 518: { + atk: function(p) { return 1.05; }, + type: "type" + }, + 519: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, + type: "type" + }, + 520: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, + type: "type" + }, + 529: { + def: function(p) { return 0; } + }, + 530: { + def: function(p) { return 0; } + }, + 533: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 534: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 542: { + rcv: function(p) { return 2; } + }, + 545: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, + type: "type" + }, + 546: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, + type: "type" + }, + 549: { + atk: function(p) { return p.defenseDown ? 1.3 : 1; }, + type: "condition" + }, + 550: { + atk: function(p) { return p.defenseDown ? 1.3 : 1; }, + type: "condition" + }, + 552: { + def: function(p) { return 0; } + }, + 555: { + delay: function(p) { return 1; }, + }, + 556: { + delay: function(p) { return 1; }, + }, + 559: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 560: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 568: { + delay: function(p) { return 1; }, + def: function(p) { return 0.5; } + }, + 569: { + delay: function(p) { return 1; }, + def: function(p) { return 0.5; } + }, + 572: { + atk: function(p) { return p.unit.class.has("Fighter") ? 2 : 1; }, + type: "class", + onActivation: function(p) { p.tdata.lock = Math.max(1, p.tdata.lock); }, + onDeactivation: function(p) { if (p.tdata.lock == 1) p.tdata.lock = 0; } + }, + 574: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.75 : 1; }, + type: "class" + }, + 575: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.75 : 1; }, + type: "class" + }, + 576: { + rcv: function(p) { return 1.5; } + }, + 582: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, + type: "type" + }, + 583: { + rcvStatic: function(p) { return p.unit.class.has("Shooter") ? 300: 0; }, + }, + 589: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, + type: "class" + }, + 590: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1; }, + type: "class" + }, + 596: { + def: function(p) { return 0.5; } + }, + 597: { + def: function(p) { return 0.5; } + }, + 600: { + atk: function(p) { return p.unit.type == "PSY" ? 1.3 : 1; }, + type: "type" + }, + 601: { + atk: function(p) { return p.unit.type == "PSY" ? 1.3 : 1; }, + type: "type" + }, + 602: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, + type: "type" + }, + 603: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, + type: "type" + }, + 612: { + atkStatic: function(p) { return 45; }, + rcvStatic: function(p) { return 45; }, + type: "type" + }, + 613: { + atkStatic: function(p) { return 45; }, + rcvStatic: function(p) { return 45; }, + type: "type" + }, + 614: { + def: function(p) { return 0.5; } + }, + 617: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.2 : 1; }, + type: "class" + }, + 622: { + rcvStatic: function(p) { return 100; }, + type: "type" + }, + 632: { + def: function(p) { return 0.5; } + }, + 633: { + def: function(p) { return 0.5; } + }, + 634: { + atk: function(p) { return p.unit.type == "QCK" || p.unit.type == "PSY" ? 1.2 : 1; }, + type: "type" + }, + 635: { + atk: function(p) { return p.unit.type == "QCK" || p.unit.type == "PSY" ? 1.2 : 1; }, + type: "type" + }, + 637: { + atk: function(p) { return 1.3; }, + type: "condition", + warning: "Selected special (%name%) assumes that the enemy has a defense buff active." + }, + 642: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 643: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 644: { + atk: function(p) { return p.delayed > 0 ? 1.2 : 1; }, + type: "condition", + }, + 645: { + atk: function(p) { return p.delayed > 0 ? 1.2 : 1; }, + type: "condition", + }, + 648: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 649: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 650: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 651: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 655: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.25, [p.friendCaptain, p.captain]); } + }, + 656: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.25, [p.friendCaptain, p.captain]); } + }, + 660: { + delay: function(p) { return 1; }, + def: function(p) { return 0.5; } + }, + 661: { + delay: function(p) { return 1; }, + def: function(p) { return 0.5; } + }, + 665: { + atk: function(p) { return p.defenseDown ? 1.3 : 1; }, + type: "condition" + }, + 666: { + atk: function(p) { return p.defenseDown ? 1.3 : 1; }, + type: "condition" + }, + 668: { + atk: function(p) { return !p.unit.class.has('Free Spirit') ? 1 : window.specials[668].multiplier; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[668].multiplier == 1.5 ? 1 : 0); + window.specials[668].multiplier = [1.5, 2][n]; + p.scope.notify({ + text: 'Using the ' + [1.5, 2][n] + 'x ATK multiplier. To switch to the ' + [2, 1.5][n] + 'x multiplier, disable and re-enable this special', + name: '668warning' + }); + } + }, + 669: { + atk: function(p) { return !p.unit.class.has('Free Spirit') ? 1 : window.specials[669].multiplier; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[669].multiplier == 1.5 ? 1 : 0); + window.specials[669].multiplier = [1.5, 2][n]; + p.scope.notify({ + text: 'Using the ' + [1.5, 2][n] + 'x ATK multiplier. To switch to the ' + [2, 1.5][n] + 'x multiplier, disable and re-enable this special', + name: '669warning' + }); + } + }, + 670: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.75 : 1; }, + type: "class" + }, + 671: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.75 : 1; }, + type: "class" + }, + 680: { + atk: function(p) { return p.unit.type == "DEX" ? 1.25 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 1.25 : 1; }, + type: "type" + }, + 681: { + atk: function(p) { return p.unit.type == "DEX" ? 1.25 : 1; }, + rcv: function(p) { return p.unit.type == "DEX" ? 1.25 : 1; }, + type: "type" + }, + 686: { + delay: function(p) { return 1; }, + }, + 687: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.3 : 1; }, + type: "class" + }, + 688: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.3 : 1; }, + type: "class" + }, + 689: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 690: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 710: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.25 : 1; }, + type: "class" + }, + 711: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.25 : 1; }, + type: "class" + }, + 712: { + atk: function(p) { return p.slot < 2 ? 1.5 : 1; }, + type: "class" + }, + 713: { + atk: function(p) { return p.slot < 2 ? 1.5 : 1; }, + type: "class" + }, + 715: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; }, + type: "class" + }, + 716: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; }, + type: "class" + }, + 719: { + atk: function(p) { return p.unit.class.has("Cerebral") ? window.specials[719].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (p.percHP <= 30 ? 2 : 1.5); + window.specials[719].multiplier = n; + p.scope.notify({ + text: 'HP ' + (n == 2 ? 'below' : 'above') + ' 30%, using the ' + n + 'x multiplier.', + name: '719warning' + }); + } + }, + 720: { + atk: function(p) { return p.unit.class.has("Cerebral") ? window.specials[720].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (p.percHP <= 30 ? 2 : 1.5); + window.specials[720].multiplier = n; + p.scope.notify({ + text: 'HP ' + (n == 2 ? 'below' : 'above') + ' 30%, using the ' + n + 'x multiplier.', + name: '720warning' + }); + } + }, + 727: { + def: function(p) { return 0.5; } + }, + 730: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + type: "type" + }, + 731: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + type: "type" + }, + 732: { + def: function(p) { return 0.5; } + }, + 733: { + def: function(p) { return 0.5; } + }, + 740: { + atk: function(p) { return 1.3; }, + type: "condition", + warning: "Selected special (%name%) assumes that the enemy has a defense buff active." + }, + 741: { + atk: function(p) { return 1.3; }, + type: "condition", + warning: "Selected special (%name%) assumes that the enemy has a defense buff active." + }, + 742: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.25, [p.friendCaptain, p.captain]); } + }, + 743: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.25, [p.friendCaptain, p.captain]); } + }, + 753: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 754: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 755: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.75 : 1; }, + type: "class" + }, + 756: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.75 : 1; }, + type: "class" + }, + 761: { + atk: function(p) { return 1.2; }, + type: "type" + }, + 762: { + atk: function(p) { return p.unit.type == "PSY" ? 1.75 : 1; }, + type: "type" + }, + 766: { + delay: function(p) { return 1; }, + }, + 770: { + atk: function(p) { return p.delayed > 0 ? 1.3 : 1; }, + type: "condition", + }, + 771: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.75 : 1; }, + type: "type" + }, + 780: { + atk: function(p) { return p.slot == p.sourceSlot ? window.specials[780].multiplier : 1; }, + type: "type", + onActivation: function(p) { + var n = (p.percHP <= 20 ? 2 : (p.percHP <= 50 ? 1.75 : 1.5)); + window.specials[780].multiplier = n; + p.scope.notify({ + text: 'Using the ' + n + 'x Self Attack boost.', + name: '780warning' + }); + } + }, + 781: { + atk: function(p) { return p.slot == p.sourceSlot ? window.specials[781].multiplier : 1; }, + type: "type", + onActivation: function(p) { + var n = (p.percHP <= 20 ? 2 : (p.percHP <= 50 ? 1.75 : 1.5)); + window.specials[781].multiplier = n; + p.scope.notify({ + text: 'Using the ' + n + 'x Self Attack boost.', + name: '781warning' + }); + } + }, + 782: { + delay: function(p) { return 1; }, + }, + 783: { + delay: function(p) { return 1; }, + }, + 786: { + delay: function(p) { return 1; }, + }, + 787: { + delay: function(p) { return 1; }, + }, + 788: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.75 : 1; }, + type: "class" + }, + 789: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.75 : 1; }, + type: "class" + }, + 790: { + atk: function(p) { return /STR|DEX|QCK/.test(p.unit.type) ? 1.2 : 1; }, + type: "type" + }, + 791: { + atk: function(p) { return /STR|DEX|QCK/.test(p.unit.type) ? 1.2 : 1; }, + type: "type" + }, + 794: { + delay: function(p) { return 1; }, + }, + 795: { + delay: function(p) { return 1; }, + }, + 796: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.75 : 1; }, + type: "type" + }, + 797: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.75 : 1; }, + type: "type" + }, + 798: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.75 : 1; }, + type: "class" + }, + 803: { + atk: function(p) { return 1.1; }, + type: "type" + }, + 804: { + atk: function(p) { return 1.1; }, + type: "type" + }, + 805: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 806: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 807: { + atk: function(p) { return p.defenseDown ? 1.3 : 1; }, + type: "condition" + }, + 808: { + atk: function(p) { return p.defenseDown ? 1.3 : 1; }, + type: "condition" + }, + 809: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); }, + def: function(p) { return 0.2; } + }, + 810: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); }, + def: function(p) { return 0.2; } + }, + 813: { + delay: function(p) { return 1; }, + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.25, [p.friendCaptain, p.captain]); } + }, + 822: { + rcvStatic: function(p) { return 100; }, + type: "type" + }, + 825: { + atkStatic: function(p) { return 200; }, + type: "type" + }, + 826: { + delay: function(p) { return 1; }, + atk: function(p) { return 0.2; }, + type: "type" + }, + 827: { + atk: function(p) { return 1.05; }, + type: "condition", + warning: "Selected special (%name%) assumes that the enemy has been poisoned or STRONGLY Poisoned." + }, + 828: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Driven") ? window.specials[828].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (p.percHP < 20 ? 1.75 : 1); + window.specials[828].multiplier = n; + p.scope.notify({ + text: 'HP ' + (n == 1.75 ? 'below' : 'above') + ' 20%, using the ' + n + 'x multiplier.', + name: '828warning' + }); + } + }, + 829: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Driven") ? window.specials[829].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (p.percHP < 20 ? 1.75 : 1); + window.specials[829].multiplier = n; + p.scope.notify({ + text: 'HP ' + (n == 1.75 ? 'below' : 'above') + ' 20%, using the ' + n + 'x multiplier.', + name: '829warning' + }); + } + }, + 832: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; }, + type: "class" + }, + 833: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; }, + type: "class" + }, + 835: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 836: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 837: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.75 : 1; }, + type: "class" + }, + 838: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.75 : 1; }, + type: "class" + }, + 839: { + atk: function(p) { return p.slot == p.sourceSlot ? 2 : 1; }, + type: "type" + }, + 840: { + atk: function(p) { return p.slot == p.sourceSlot ? 2 : 1; }, + type: "type" + }, + 841: { + delay: function(p) { return 1; }, + atk: function(p) { return p.delayed > 0 ? 1.25 : 1; }, + type: "condition", + }, + 842: { + delay: function(p) { return 1; }, + atk: function(p) { return p.delayed > 0 ? 1.25 : 1; }, + type: "condition", + }, + 843: { + atk: function(p) { + if (window.specials[843].first) return p.unit.class.has("Shooter") ? 1.5 : 1; + else return p.unit.class.has("Shooter") || p.unit.class.has("Slasher") || p.unit.class.has("Striker") ? 1.5 : 1; + }, + type: "class", + onActivation: function(p) { + window.specials[843].first = !window.specials[843].first; + p.scope.notify({ + text: (window.specials[843].first ? + 'Boosting Shooters. To switch to the second multiplier, disable and re-enable this special' : + 'Boosting Shooters, Slashers and Strikers. To switch to the first multiplier, disable and re-enable this special'), + name: '843warning' + }); + } + }, + 844: { + atk: function(p) { + if (window.specials[844].first) return p.unit.class.has("Shooter") ? 1.5 : 1; + else return p.unit.class.has("Shooter") || p.unit.class.has("Slasher") || p.unit.class.has("Striker") ? 1.5 : 1; + }, + type: "class", + onActivation: function(p) { + window.specials[844].first = !window.specials[844].first; + p.scope.notify({ + text: (window.specials[844].first ? + 'Boosting Shooters. To switch to the second multiplier, disable and re-enable this special' : + 'Boosting Shooters, Slashers and Strikers. To switch to the first multiplier, disable and re-enable this special'), + name: '844warning' + }); + } + }, + 847: { + atk: function(p) { return 1.05; }, + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.15, [p.friendCaptain, p.captain]); }, + type: "class" + }, + 848: { + atk: function(p) { return 1.05; }, + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.15, [p.friendCaptain, p.captain]); }, + type: "class" + }, + 849: { + def: function() { return 0.5; } + }, + 853: { + atk: function(p) { return p.unit.class.has("Powerhouse") || p.unit.class.has("Fighter") ? 1.2 : 1; }, + type: "class" + }, + 857: { + rcv: function(p) { return p.unit.type == 'PSY' ? 1.5 : 1; }, + type: "type" + }, + 858: { + rcv: function(p) { return p.unit.type == 'PSY' ? 1.5 : 1; }, + type: "type" + }, + 861: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 862: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 863: { + def: function(p) { return 0.5; } + }, + 864: { + delay: function(p) { return 1; }, + chain: function(p) { return 2.5; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2.5 : 1; + } + }, + 865: { + delay: function(p) { return 1; }, + chain: function(p) { return 2.5; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2.5 : 1; + } + }, + 866: { + atk: function(p) { + return p.unit.class.has("Slasher") || p.unit.class.has("Cerebral") ? 1.3 : 1; + }, + type: "class" + }, + 867: { + delay: function(p) { return 1; }, + }, + 869: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2.0, [p.friendCaptain, p.captain]); } + }, + 870: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2.0, [p.friendCaptain, p.captain]); } + }, + 873: { + orb: function(p) { + if (window.specials[873].first) return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); + else return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); + }, + type: "class", + onActivation: function(p) { + window.specials[873].first = !window.specials[873].first; + p.scope.notify({ + text: (window.specials[873].first ? + 'Activating the first stage. To switch to the second stage, disable and re-enable this special' : + 'Activating the second stage. To switch to the first stage, disable and re-enable this special'), + name: '873warning' + }); + } + }, + 874: { + orb: function(p) { + if (window.specials[874].first) return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); + else return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); + }, + type: "class", + onActivation: function(p) { + window.specials[874].first = !window.specials[874].first; + p.scope.notify({ + text: (window.specials[874].first ? + 'Activating the first stage. To switch to the second stage, disable and re-enable this special' : + 'Activating the second stage. To switch to the first stage, disable and re-enable this special'), + name: '874warning' + }); + } + }, + 881: { + atk: function(p) { + return p.unit.class.has("Shooter") || p.unit.class.has("Free Spirit") ? 1.75 : 1; + }, + rcv: function(p) { return 0.1; }, + type: "class" + }, + 882: { + atk: function(p) { + return p.unit.class.has("Shooter") || p.unit.class.has("Free Spirit") ? 1.75 : 1; + }, + rcv: function(p) { return 0.1; }, + type: "class" + }, + 883: { + atk: function(p) { return !p.unit.class.has('Powerhouse') ? 1 : window.specials[883].multiplier; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[883].multiplier == 1.5 ? 1 : 0); + window.specials[883].multiplier = [1.5, 2][n]; + p.scope.notify({ + text: 'Using the ' + [1.5, 2][n] + 'x ATK multiplier. To switch to the ' + [2, 1.5][n] + 'x multiplier, disable and re-enable this special', + name: '883warning' + }); + } + }, + 884: { + atk: function(p) { return !p.unit.class.has('Powerhouse') ? 1 : window.specials[884].multiplier; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[884].multiplier == 1.5 ? 1 : 0); + window.specials[884].multiplier = [1.5, 2][n]; + p.scope.notify({ + text: 'Using the ' + [1.5, 2][n] + 'x ATK multiplier. To switch to the ' + [2, 1.5][n] + 'x multiplier, disable and re-enable this special', + name: '884warning' + }); + } + }, + 885: { + atk: function(p) { return p.unit.class.has('Fighter') ? window.specials[885].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (p.percHP <= 30 ? 1.5 : 1); + window.specials[885].multiplier = n; + p.scope.notify({ + text: 'Using the ' + n + 'x ATK boost.', + name: '885warning' + }); + } + }, + 886: { + atk: function(p) { return p.unit.class.has('Slasher') ? window.specials[886].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (p.percHP <= 30 ? 1.5 : 1); + window.specials[886].multiplier = n; + p.scope.notify({ + text: 'Using the ' + n + 'x ATK boost.', + name: '886warning' + }); + } + }, + 887: { + def: function(p) { return 0.2; } + }, + 891: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.25 : 1; }, + type: "class" + }, + 902: { + atk: function(p) { return !p.unit.class.has('Powerhouse') ? 1 : window.specials[902].multiplier; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[902].multiplier == 1.5 ? 1 : 0); + window.specials[902].multiplier = [1.5, 2][n]; + p.scope.notify({ + text: 'Using the ' + [1.5, 2][n] + 'x ATK multiplier. To switch to the ' + [2, 1.5][n] + 'x multiplier, disable and re-enable this special', + name: '902warning' + }); + } + }, + 903: { + atk: function(p) { return !p.unit.class.has('Powerhouse') ? 1 : window.specials[903].multiplier; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[903].multiplier == 1.5 ? 1 : 0); + window.specials[903].multiplier = [1.5, 2][n]; + p.scope.notify({ + text: 'Using the ' + [1.5, 2][n] + 'x ATK multiplier. To switch to the ' + [2, 1.5][n] + 'x multiplier, disable and re-enable this special', + name: '902warning' + }); + } + }, + 904: { + delay: function(p) { return 1; }, + }, + 905: { + atk: function(p) { + if (!window.specials[905].stage) return p.slot == p.sourceSlot ? 1.5 : 1; + if (window.specials[905].stage == 1) return p.unit.class.has("Slasher") ? 1.5 : 1; + if (window.specials[905].stage == 2) return p.unit.class.has("Slasher") ? 1.75 : 1; + }, + type: "class", + stage: -1, + onActivation: function(p) { + window.specials[905].stage = (window.specials[905].stage + 1) % 3; + p.scope.notify({ + text: 'Activating stage #' + (window.specials[905].stage + 1) + '. To move onto the next stage, disable and re-enable this special.', + name: '905warning' + }); + } + }, + 906: { + atk: function(p) { + if (!window.specials[906].stage) return p.slot == p.sourceSlot ? 1.5 : 1; + if (window.specials[906].stage == 1) return p.unit.class.has("Slasher") ? 1.5 : 1; + if (window.specials[906].stage == 2) return p.unit.class.has("Slasher") ? 1.75 : 1; + }, + type: "class", + stage: -1, + onActivation: function(p) { + window.specials[906].stage = (window.specials[906].stage + 1) % 3; + p.scope.notify({ + text: 'Activating stage #' + (window.specials[906].stage + 1) + '. To move onto the next stage, disable and re-enable this special.', + name: '906warning' + }); + } + }, + 907: { + delay: function(p) { return 1; }, + }, + 908: { + delay: function(p) { return 1; }, + }, + 909: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, + type: "type" + }, + 910: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, + type: "type" + }, + 911: { + atk: function(p) { + if (!window.specials[911].stage) return p.unit.class.has("Powerhouse") ? 1.2 : 1; + if (window.specials[911].stage == 1) return p.unit.class.has("Powerhouse") ? 2 : 1; + }, + type: "class", + stage: -1, + onActivation: function(p) { + window.specials[911].stage = (window.specials[911].stage + 1) % 2; + p.scope.notify({ + text: 'Activating stage #' + (window.specials[911].stage + 1) + '. To move onto the next stage, disable and re-enable this special.', + name: '911warning' + }); + } + }, + 912: { + atk: function(p) { + if (!window.specials[912].stage) return p.unit.class.has("Powerhouse") ? 1.2 : 1; + if (window.specials[912].stage == 1) return p.unit.class.has("Powerhouse") ? 2 : 1; + }, + type: "class", + stage: -1, + onActivation: function(p) { + window.specials[912].stage = (window.specials[912].stage + 1) % 2; + p.scope.notify({ + text: 'Activating stage #' + (window.specials[912].stage + 1) + '. To move onto the next stage, disable and re-enable this special.', + name: '912warning' + }); + } + }, + 915: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; }, + type: "class" + }, + 916: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; }, + type: "class" + }, + 917: { + delay: function(p) { return 1; }, + }, + 918: { + delay: function(p) { return 1; }, + }, + 921: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 922: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 925: { + atk: function(p) { return p.defenseDown ? 1.3 : 1; }, + type: "condition" + }, + 926: { + atk: function(p) { return p.defenseDown ? 1.3 : 1; }, + type: "condition" + }, + 927: { + atk: function(p) { + return p.unit.class.has("Slasher") || p.unit.class.has("Driven") ? 1.2 : 1; + }, + type: "class" + }, + 928: { + atk: function(p) { return 1.3; }, + type: "condition", + warning: "Selected special (%name%) assumes that the enemy has been poisoned or STRONGLY Poisoned." + }, + 929: { + atk: function(p) { return 1.3; }, + type: "condition", + warning: "Selected special (%name%) assumes that the enemy has been poisoned or STRONGLY Poisoned." + }, + 940: { + atk: function(p) { return p.unit.type == "DEX" ? 1.75 : 1; }, + type: "type" + }, + 941: { + atk: function(p) { return p.unit.type == "DEX" ? 1.75 : 1; }, + type: "type" + }, + 944: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; }, + type: "class" + }, + 945: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; }, + type: "class" + }, + 947: { + atk: function(p) { return p.unit.type == "STR" || p.unit.type == "INT" ? 1.3 : 1; }, + type: "type" + }, + 954: { + def: function(p) { return 0.2; } + }, + 955: { + atk: function(p) { return p.defenseDown ? 1.2 : 1; }, + type: "condition" + }, + 956: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.2 : 1; }, + type: "class" + }, + 961: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.25, [p.friendCaptain, p.captain]); } + }, + 963: { + def: function(p) { return 0; } + }, + 964: { + atk: function(p) { return window.specials[964].multiplier; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[964].multiplier == 1.1 ? 1 : 0); + window.specials[964].multiplier = [1.1, 1.5][n]; + p.scope.notify({ + text: 'Using the ' + [1.1, 1.5][n] + 'x ATK multiplier. To switch to the ' + [1.5, 1.1][n] + 'x multiplier, disable and re-enable this special', + name: '965warning' + }); + } + }, + 965: { + atk: function(p) { return window.specials[965].multiplier; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[965].multiplier == 1.1 ? 1 : 0); + window.specials[965].multiplier = [1.1, 1.5][n]; + p.scope.notify({ + text: 'Using the ' + [1.1, 1.5][n] + 'x ATK multiplier. To switch to the ' + [1.5, 1.1][n] + 'x multiplier, disable and re-enable this special', + name: '965warning' + }); + } + }, + 975: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.3 : 1; }, + atk: function(p) { return p.unit.class.has("Striker") ? 1.3 : 1; }, + type: "class" + }, + 976: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.3 : 1; }, + atk: function(p) { return p.unit.class.has("Striker") ? 1.3 : 1; }, + type: "class" + }, + 977: { + chainAddition: function(p) {return 0.5;} + }, + 978: { + chainAddition: function(p){ return 0.5;} + }, + 984: { + delay: function(p) { return 1; }, + }, + 981: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.75 : 1; }, + type: "type" + }, + 998: { + delay: function(p) { return 1; }, + }, + 999: { + delay: function(p) { return 1; }, + }, + 1005: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.75 : 1; }, + type: "type" + }, + 1006: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.75 : 1; }, + type: "type" + }, + 1010: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.3 : 1; }, + type: "type" + }, + 1011: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.3 : 1; }, + type: "type" + }, + 1013: { + atk: function(p) { return p.delayed > 0 ? 1.2 : 1; }, + type: "condition", + }, + 1015: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + type: "type" + }, + 1016: { + atk: function(p) { return p.unit.type == "INT" ? 1.5 : 1; }, + type: "type" + }, + 1017: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1}, + type: "class" + }, + 1018: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.5 : 1}, + type: "class" + }, + 1023: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.75 : 1}, + type: "class" + }, + 1024: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, window.specials[1024].multiplier, [p.friendCaptain, p.captain]); }, + onActivation: function(p) { + var n = (p.percHP >= 70 ? 1.25 : p.percHP >= 30 ? 1.5 : 1.75); + window.specials[1024].multiplier = n; + p.scope.notify({ + text: 'HP ' + (n == 1.75 ? 'below 30%' : n == 1.5 ? 'between 70% and 30%' : 'above 70%') + ', using the ' + n + 'x Orb boost.', + name: '1024warning' + }); + } + }, + 1025: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, window.specials[1025].multiplier, [p.friendCaptain, p.captain]); }, + onActivation: function(p) { + var n = (p.percHP >= 70 ? 1.25 : p.percHP >= 30 ? 1.5 : 1.75); + window.specials[1025].multiplier = n; + p.scope.notify({ + text: 'HP ' + (n == 1.75 ? 'below 30%' : n == 1.5 ? 'between 70% and 30%' : 'above 70%') + ', using the ' + n + 'x Orb boost.', + name: '1025warning' + }); + } + }, + 1028: { + //TODO + hit: function(n) { return n > 30 ? 1.75 : 1; }, + type: "condition" + }, + 1029: { + //TODO + hit: function(n) { return n > 30 ? 1.75 : 1; }, + type: "condition" + }, + 1030: { + atk: function(p) { return p.slot == p.sourceSlot ? 2.25 : 1; }, + type: "type" + }, + 1031: { + atk: function(p) { return p.slot == p.sourceSlot ? 2.25 : 1; }, + type: "type" + }, + 1040: { + atk: function(p) { return window.specials[1040].multiplier; }, + type: "type", + onActivation: function(p) { + var n = (p.percHP <= 30 ? 1.5 : 1); + window.specials[1040].multiplier = n; + p.scope.notify({ + text: 'Using the ' + n + 'x ATK boost.', + name: '1040warning' + }); + } + }, + 1041: { + atk: function(p) { return window.specials[1041].multiplier; }, + type: "type", + onActivation: function(p) { + var n = (p.percHP <= 30 ? 1.5 : 1); + window.specials[1041].multiplier = n; + p.scope.notify({ + text: 'Using the ' + n + 'x ATK boost.', + name: '1041warning' + }); + } + }, + 1046: { + staticMult: function(p) { return 55; } + }, + 1047: { + staticMult: function(p) { return 55; } + }, + 1055: { + atk: function(p) { return 1.4; }, + type: "condition", + warning: "Selected special (%name%) assumes that the enemy has been STRONGLY Poisoned." + }, + 1056: { + atk: function(p) { return 1.4; }, + type: "condition", + warning: "Selected special (%name%) assumes that the enemy has been STRONGLY Poisoned." + }, + 1059: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 1060: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 1061: { + chain: function(p) { return 2; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2 : 1; + } + }, + 1063: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.3 : 1}, + type: "class" + }, + 1065: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.25, [p.friendCaptain, p.captain]); } + }, + 1066: { + chainAddition: function(p){ return 0.1;} + }, + 1067: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.5 : 1; }, + type: "type" + }, + 1071: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1}, + type: "class" + }, + 1072: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1}, + type: "class" + }, + 1076: { + delay: function(p) { return 1; }, + }, + 1077: { + delay: function(p) { return 1; }, + }, + 1080: { + atk: function(p) { return p.slot == p.sourceSlot ? 2 : 1; }, + type: "type" + }, + 1081: { + atk: function(p) { return p.slot == p.sourceSlot ? 2 : 1; }, + type: "type" + }, + 1082: { + atk: function(p) { return (p.unit.class.has("Striker") || p.unit.class.has("Fighter")) ? window.specials[1082].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (p.percHP >= 70 ? 1.2 : p.percHP >= 30 ? 1.5 : 1.75); + window.specials[1082].multiplier = n; + p.scope.notify({ + text: 'HP ' + (n == 1.75 ? 'below 30%' : n == 1.5 ? 'between 70% and 30%' : 'above 70%') + ', using the ' + n + 'x Attack boost.', + name: '1082warning' + }); + } + }, + 1083: { + atk: function(p) { return (p.unit.class.has("Striker") || p.unit.class.has("Fighter")) ? window.specials[1083].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (p.percHP >= 70 ? 1.2 : p.percHP >= 30 ? 1.5 : 1.75); + window.specials[1083].multiplier = n; + p.scope.notify({ + text: 'HP ' + (n == 1.75 ? 'below 30%' : n == 1.5 ? 'between 70% and 30%' : 'above 70%') + ', using the ' + n + 'x Attack boost.', + name: '1083warning' + }); + } + }, + 1086: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 1087: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 1088: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Driven") ? 1.5 : 1}, + type: "class" + }, + 1089: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Driven") ? 1.5 : 1}, + type: "class" + }, + 1096: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.75 : 1; }, + type: "type" + }, + 1097: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.75 : 1; }, + type: "type" + }, + 1099: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 1100: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 1101: { + atk: function(p) { return p.unit.type == "STR" || p.unit.type == "INT" ? 1.75 : 1; }, + type: "type" + }, + 1102: { + atk: function(p) { return p.unit.type == "STR" || p.unit.type == "INT" ? 1.75 : 1; }, + type: "type" + }, + 1105: { + delay: function(p) { return 1; }, + chainAddition: function(p){ return 0.2;} + }, + 1106: { + delay: function(p) { return 1; }, + chainAddition: function(p){ return 0.2;} + }, + 1107: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.75 : 1; }, + type: "class" + }, + 1108: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.75 : 1; }, + type: "class" + }, + 1111: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.25, [p.friendCaptain, p.captain]); } + }, + 1112: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.25, [p.friendCaptain, p.captain]); } + }, + 1113: { + atk: function(p) { return 1.2; }, + type: "type" + }, + 1114: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, + type: "type" + }, + 1115: { + atk: function(p) { return p.unit.type == "STR" ? 2 : 1; }, + type: "type" + }, + 1122: { + atk: function(p) { return p.slot == p.sourceSlot ? 2.25 : 1; }, + type: "type", + orb: function(p) { return p.slot == p.sourceSlot ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain])} + }, + 1123: { + atk: function(p) { return p.slot == p.sourceSlot ? 2.25 : 1; }, + type: "type", + orb: function(p) { return p.slot == p.sourceSlot ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain])} + }, + 1132: { + atk: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Shooter") ? window.specials[1132].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[1132].multiplier == 1.5 ? 1 : 0); + window.specials[1132].multiplier = [1.5, 1.75][n]; + p.scope.notify({ + text: 'Using the ' + [1.5, 1.75][n] + 'x ATK multiplier. To switch to the ' + [1.75, 1.5][n] + 'x multiplier, disable and re-enable this special', + name: '1132warning' + }); + } + }, + 1133: { + atk: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Shooter") ? window.specials[1133].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[1133].multiplier == 1.5 ? 1 : 0); + window.specials[1133].multiplier = [1.5, 1.75][n]; + p.scope.notify({ + text: 'Using the ' + [1.5, 1.75][n] + 'x ATK multiplier. To switch to the ' + [1.75, 1.5][n] + 'x multiplier, disable and re-enable this special', + name: '1133warning' + }); + } + }, + 1137: { + orb: function(p) { return p.unit.class.has("Free Spirit") ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1138: { + atk: function(p) { return p.unit.class.has("Powerhouse") || p.unit.class.has("Fighter") ? 1.3 : 1}, + type: "class" + }, + 1142: { + delay: function(p) { return 1; }, + }, + 1143: { + delay: function(p) { return 1; }, + }, + 1153: { + def: function(p) { return 0; }, + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.25 : 1}, + type: "class" + }, + 1154: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1}, + type: "class" + }, + 1164: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); }, + rcv: function(p) { return 1.5; } + }, + 1165: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); }, + rcv: function(p) { return 1.5; } + }, + 1168: { + atk: function(p) { return p.unit.type == "STR" ? window.specials[1168].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (p.percHP <= 10 ? 1.75 : p.percHP <= 30 ? 1.5 : p.percHP <= 50 ? 1.25 : 1.1); + window.specials[1168].multiplier = n; + p.scope.notify({ + text: 'HP ' + (n == 1.75 ? 'below' : 'above') + ' ' + (n == 1.75 ? '10%' : n == 1.5 ? '10%' : n == 1.25 ? '30%' : '50%') + ', using the ' + n + 'x multiplier.', + name: '1168warning' + }); + } + }, + 1169: { + atk: function(p) { return p.unit.type == "STR" ? window.specials[1169].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (p.percHP <= 10 ? 1.75 : p.percHP <= 30 ? 1.5 : p.percHP <= 50 ? 1.25 : 1.1); + window.specials[1169].multiplier = n; + p.scope.notify({ + text: 'HP ' + (n == 1.75 ? 'below' : 'above') + ' ' + (n == 1.75 ? '10%' : n == 1.5 ? '10%' : n == 1.25 ? '30%' : '50%') + ', using the ' + n + 'x multiplier.', + name: '1168warning' + }); + } + }, + 1181: { + turnedOn: false, + onActivation: function(p) { + window.specials[1181].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1181].turnedOn = false; + } + }, + 1182: { + turnedOn: false, + onActivation: function(p) { + window.specials[1182].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1182].turnedOn = false; + } + }, + 1193: { + chain: function(p) { return 2.5; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2.5 : 1; + } + }, + 1194: { + chain: function(p) { return 2.5; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2.5 : 1; + } + }, + 1195: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.75 : 1; }, + type: "class" + }, + 1196: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.75 : 1; }, + type: "class" + }, + 1209: { + delay: function(p) { return 1; }, + }, + 1210: { + delay: function(p) { return 1; }, + }, + 1211: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 1212: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 1219: { + atk: function(p) { + if (!window.specials[1219].stage) return p.unit.class.has("Shooter") ? 1.2 : 1; + if (window.specials[1219].stage == 1) return p.unit.class.has("Shooter") ? 1.5 : 1; + if (window.specials[1219].stage == 2) return p.unit.class.has("Shooter") ? 2 : 1; + }, + type: "class", + stage: -1, + onActivation: function(p) { + window.specials[1219].stage = (window.specials[1219].stage + 1) % 3; + p.scope.notify({ + text: 'Activating stage #' + (window.specials[1219].stage + 1) + '. To move onto the next stage, disable and re-enable this special.', + name: '1219warning' + }); + } + }, + 1220: { + atk: function(p) { + if (!window.specials[1220].stage) return p.unit.class.has("Shooter") ? 1.2 : 1; + if (window.specials[1220].stage == 1) return p.unit.class.has("Shooter") ? 1.5 : 1; + if (window.specials[1220].stage == 2) return p.unit.class.has("Shooter") ? 2 : 1; + }, + type: "class", + stage: -1, + onActivation: function(p) { + window.specials[1220].stage = (window.specials[1220].stage + 1) % 3; + p.scope.notify({ + text: 'Activating stage #' + (window.specials[1220].stage + 1) + '. To move onto the next stage, disable and re-enable this special.', + name: '1219warning' + }); + } + }, + 1221: { + turnedOn: false, + onActivation: function(p) { + window.specials[1221].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1221].turnedOn = false; + } + }, + 1222: { + turnedOn: false, + onActivation: function(p) { + window.specials[1222].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1222].turnedOn = false; + } + }, + 1225: { + delay: function(p) { return 1; }, + }, + 1227: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.75 : 1; }, + type: "type" + }, + 1231: { + turnedOn: false, + onActivation: function(p) { + window.specials[1231].turnedOn = true; + p.scope.notify({ + text: 'Only affects damage if Smoker is your captain', + name: '1231warning' + }); + }, + onDeactivation: function(p) { + window.specials[1231].turnedOn = false; + } + }, + 1232: { + turnedOn: false, + onActivation: function(p) { + window.specials[1232].turnedOn = true; + p.scope.notify({ + text: 'Only affects damage if Smoker is your captain', + name: '1232warning' + }); + }, + onDeactivation: function(p) { + window.specials[1232].turnedOn = false; + } + }, + 1233: {//Tashigi + affinity: function(p){ return p.unit.class.has("Slasher") || p.unit.class.has("Cerebral") ? 1.5 : 1; } + }, + 1234: {//Tashigi + affinity: function(p){ return p.unit.class.has("Slasher") || p.unit.class.has("Cerebral") ? 1.5 : 1; } + }, + 1235: { + delay: function(p) { return 1; }, + }, + 1236: { + delay: function(p) { return 1; }, + }, + 1237: { + //TODO + hit: function(n) { return n > 30 ? 2 : 1; }, + type: "condition" + }, + 1238: { + //TODO + hit: function(n) { return n > 30 ? 2 : 1; }, + type: "condition" + }, + 1239: { + turnedOn: [ false, false ], + onActivation: function(p) { + window.specials[1239].turnedOn[p.slot] = true; + p.scope.notify({ + text: 'Only affects damage if Kizaru is your captain', + name: '1239warning' + }); + }, + onDeactivation: function(p) { + window.specials[1239].turnedOn[p.slot] = false; + } + }, + 1240: { + turnedOn: [ false, false ], + onActivation: function(p) { + window.specials[1240].turnedOn[p.slot] = true; + p.scope.notify({ + text: 'Only affects damage if Kizaru is your captain', + name: '1240warning' + }); + }, + onDeactivation: function(p) { + window.specials[1240].turnedOn[p.slot] = false; + } + }, + 1241: { + staticMult: function(p) { return 15; } + }, + 1242: { + staticMult: function(p) { return 15; } + }, + 1245: { + atk: function(p) { return !p.unit.class.has('Fighter') ? 1 : window.specials[1245].multiplier; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[1245].multiplier == 1.3 ? 1 : 0); + window.specials[1245].multiplier = [1.3, 2][n]; + p.scope.notify({ + text: 'Using the ' + [1.3, 2][n] + 'x ATK multiplier. To switch to the ' + [2, 1.3][n] + 'x multiplier, disable and re-enable this special', + name: '1245warning' + }); + } + }, + 1246: { + atk: function(p) { return !p.unit.class.has('Fighter') ? 1 : window.specials[1246].multiplier; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[1246].multiplier == 1.3 ? 1 : 0); + window.specials[1246].multiplier = [1.3, 2][n]; + p.scope.notify({ + text: 'Using the ' + [1.3, 2][n] + 'x ATK multiplier. To switch to the ' + [2, 1.3][n] + 'x multiplier, disable and re-enable this special', + name: '1246warning' + }); + } + }, + 1247: { + atk: function(p) { return !p.unit.class.has('Fighter') ? 1 : window.specials[1247].multiplier; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[1247].multiplier == 1.3 ? 1 : 0); + window.specials[1247].multiplier = [1.3, 2][n]; + p.scope.notify({ + text: 'Using the ' + [1.3, 2][n] + 'x ATK multiplier. To switch to the ' + [2, 1.3][n] + 'x multiplier, disable and re-enable this special', + name: '1247warning' + }); + } + }, + 1250: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + type: "class" + }, + 1251: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + type: "class" + }, + 1253: { + atk: function(p) { return p.unit.type == "STR" ? 1.75 : 1; }, + type: "class" + }, + 1254: { + def: function(p) { return 0.2; } + }, + 1255: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 1256: { + atk: function(p) { return 1.3 }, + type: "condition", + warning: "Selected special (%name%) assumes that the enemy has a defense buff active." + }, + 1259: { + turnedOn: false, + onActivation: function(p) { + window.specials[1259].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1259].turnedOn = false; + } + }, + 1260: { + turnedOn: false, + onActivation: function(p) { + window.specials[1260].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1260].turnedOn = false; + } + }, + 1261: {//Young Senor Pink + affinity: function(p){ return p.unit.class.has("Shooter") || p.unit.class.has("Free Spirit") ? 1.5 : 1; } + }, + 1262: {//Young Senor Pink + affinity: function(p){ return p.unit.class.has("Shooter") || p.unit.class.has("Free Spirit") ? 1.5 : 1; } + }, + 1263: { + atk: function(p) { return p.slot == p.sourceSlot ? 2 : 1; }, + type: "type" + }, + 1264: { + atk: function(p) { return p.slot == p.sourceSlot ? 2 : 1; }, + type: "type" + }, + 1265: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.75 : 1; }, + type: "class" + }, + 1266: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.75 : 1; }, + type: "class" + }, + 1269: { + turnedOn: false, + onActivation: function(p) { + window.specials[1269].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1269].turnedOn = false; + } + }, + 1270: { + turnedOn: false, + onActivation: function(p) { + window.specials[1270].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1270].turnedOn = false; + } + }, + 1271: { + orb: function(p) { return p.unit.class.has("Shooter") ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1272: { + orb: function(p) { return p.unit.class.has("Shooter") ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1273: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, + type: "class" + }, + 1274: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, + type: "class" + }, + 1282: { + atk: function(p) { return 1.2; }, + type: "class", + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.2, [p.friendCaptain, p.captain]); }, + }, + 1283: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; }, + type: "class" + }, + 1286: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, + type: "class" + }, + 1287: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.5 : 1; }, + type: "class" + }, + 1295: { + def: function(p) { return 0; } + }, + 1296: { + def: function(p) { return 0; } + }, + 1297: { + affinity: function(p){ return p.unit.type == "STR" ? 1.75 : 1; } + }, + 1298: { + affinity: function(p){ return p.unit.type == "STR" ? 1.75 : 1; } + }, + 1299: { + atk: function(p) { return p.unit.type == "INT" ? 1.75 : 1; }, + type: "class" + }, + 1300: { + atk: function(p) { return p.unit.type == "INT" ? 1.75 : 1; }, + type: "class" + }, + 1313: { + atk: function(p) { return p.unit.cost >= 50 ? 1.75 : 1; }, + type: "class" + }, + 1314: { + atk: function(p) { return p.unit.cost >= 50 ? 1.75 : 1; }, + type: "class" + }, + 1317: { + delay: function(p) { return 1; }, + def: function(p) { return 0.2; } + }, + 1318: { + delay: function(p) { return 1; }, + def: function(p) { return 0.2; } + }, + 1319: { + atk: function(p) { return 1.5; }, + type: "class" + }, + 1320: { + atk: function(p) { return 1.5; }, + type: "class" + }, + 1321: { + atk: function(p) { return p.delayed > 0 ? 1.5 : 1; }, + type: "condition", + }, + 1322: { + atk: function(p) { return p.delayed > 0 ? 1.5 : 1; }, + type: "condition", + }, + 1323: { + turnedOn: false, + onActivation: function(p) { + window.specials[1323].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1323].turnedOn = false; + } + }, + 1324: { + turnedOn: false, + onActivation: function(p) { + window.specials[1324].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1324].turnedOn = false; + } + }, + 1329: { + affinity: function(p){ return p.unit.class.has("Fighter") || p.unit.class.has("Free Spirit") ? 1.25 : 1; } + }, + 1330: { + turnedOn: false, + onActivation: function(p) { + window.specials[1330].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1330].turnedOn = false; + } + }, + 1335: { + chainAddition: function(p){ return 0.5; } + }, + 1336: { + chainAddition: function(p){ return 0.5; } + }, + 1339: { + chainAddition: function(p) { + if (!window.specials[1339].stage) return 0.2; + if (window.specials[1339].stage == 1) return 0.3; + if (window.specials[1339].stage == 2) return 0.5; + }, + stage: -1, + onActivation: function(p) { + window.specials[1339].stage = (window.specials[1339].stage + 1) % 3; + p.scope.notify({ + text: 'Activating stage #' + (window.specials[1339].stage + 1) + '. To move onto the next stage, disable and re-enable this special.', + name: '1339warning' + }); + } + }, + 1340: { + delay: function(p) { return 1; }, + }, + 1341: { + delay: function(p) { return 1; }, + }, + 1343: { + atk: function(p) { return p.defenseDown ? 1.3 : 1; }, + type: "condition" + }, + 1344: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.3 : 1; }, + type: "class" + }, + 1348: { + atk: function(p) { return 1.2; }, + type: "class", + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.2, [p.friendCaptain, p.captain]); }, + }, + 1349: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.2 : 1; }, + type: "class" + }, + 1351: { + delay: function(p) { return 1; }, + def: function(p) { return 0.5; } + }, + 1353: { + chainAddition: function(p){ return 0.5; } + }, + 1354: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); }, + }, + 1355: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); }, + }, + 1358: { + delay: function(p) { return 1; }, + rcv: function(p){ return 1.75; } + }, + 1359: { + delay: function(p) { return 1; }, + rcv: function(p){ return 1.75; } + }, + 1361: { + atk: function(p) { return !p.unit.class.has('Slasher') ? 1 : p.sourceSlot < 2 ? 2 : 1.75 ; }, + type: "class", + }, + 1362: { + atk: function(p) { return !p.unit.class.has('Slasher') ? 1 : p.sourceSlot < 2 ? 2 : 1.75 ; }, + type: "class", + }, + 1363: { + orb: function(p) { return p.unit.type == "PSY" ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + }, + 1364: { + orb: function(p) { return p.unit.type == "PSY" ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + }, + 1365: { + delay: function(p) { return 1; }, + }, + 1366: { + delay: function(p) { return 1; }, + }, + 1367:{ + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, window.specials[1367].multiplier, [p.friendCaptain, p.captain]); }, + onActivation: function(p) { + var n = (window.specials[1367].multiplier == 1.5 ? 1 : 0); + window.specials[1367].multiplier = [1.5, 1.75][n]; + p.scope.notify({ + text: 'Using the ' + [1.5, 1.75][n] + 'x Orb boost. To switch to the ' + [1.75, 1.5][n] + 'x Orb boost, disable and re-enable this special', + name: '1367warning' + }); + }, + }, + 1368:{ + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, window.specials[1368].multiplier, [p.friendCaptain, p.captain]); }, + onActivation: function(p) { + var n = (window.specials[1368].multiplier == 1.5 ? 1 : 0); + window.specials[1368].multiplier = [1.5, 1.75][n]; + p.scope.notify({ + text: 'Using the ' + [1.5, 1.75][n] + 'x Orb boost. To switch to the ' + [1.75, 1.5][n] + 'x Orb boost, disable and re-enable this special', + name: '1368warning' + }); + }, + }, + 1373: { + delay: function(p) { return 1; }, + }, + 1374: { + delay: function(p) { return 1; }, + }, + 1375: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.5 : 1; }, + type: "type", + orb: function(p) { return p.slot == p.sourceSlot ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain])} + }, + 1376: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.5 : 1; }, + type: "type", + orb: function(p) { return p.slot == p.sourceSlot ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain])} + }, + 1379: { + turnedOn: false, + onActivation: function(p) { + window.specials[1379].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1379].turnedOn = false; + }, + orb: function(p) { return (p.unit.class.has("Free Spirit") || p.unit.class.has("Cerebral")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1380: { + turnedOn: false, + onActivation: function(p) { + window.specials[1380].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1380].turnedOn = false; + }, + orb: function(p) { return (p.unit.class.has("Free Spirit") || p.unit.class.has("Cerebral")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1387: { + delay: function(p) { return 1; }, + }, + 1389: { + orb: function(p) { return p.unit.type == "INT" ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + }, + 1390: { + atk: function(p) { return p.unit.cost <= 40 ? 1.75 : 1; }, + type: "class" + }, + 1391: { + atk: function(p) { return p.unit.cost <= 40 ? 1.75 : 1; }, + type: "class" + }, + 1392: { + atk: function(p) { return p.unit.type == "PSY" ? 1.75 : 1; }, + type: "class" + }, + 1393: { + atk: function(p) { return 1.1; }, + type: "class", + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.1, [p.friendCaptain, p.captain]); }, + }, + 1394: { + atk: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Striker") ? 1.5 : 1; }, + type: "class" + }, + 1395: { + atk: function(p) { return p.unit.class.has("Fighter") || p.unit.class.has("Striker") ? 1.5 : 1; }, + type: "class" + }, + 1396: { + delay: function(p) { return 1; }, + def: function(p) { return 0.2; } + }, + 1397: { + delay: function(p) { return 1; }, + def: function(p) { return 0.2; } + }, + 1400: { + affinity: function(p) { return p.unit.class.has("Shooter") ? window.specials[1400].multiplier : 1; }, + onActivation: function(p) { + var n = (window.specials[1400].multiplier == 1.5 ? 1 : 0); + window.specials[1400].multiplier = [1.5, 1.75][n]; + p.scope.notify({ + text: 'Using the ' + [1.5, 1.75][n] + 'x Affinity boost. To switch to the ' + [1.75, 1.5][n] + 'x Affinity boost, disable and re-enable this special', + name: '1400warning' + }); + }, + }, + 1401: { + affinity: function(p) { return p.unit.class.has("Shooter") ? window.specials[1401].multiplier : 1; }, + onActivation: function(p) { + var n = (window.specials[1401].multiplier == 1.5 ? 1 : 0); + window.specials[1401].multiplier = [1.5, 1.75][n]; + p.scope.notify({ + text: 'Using the ' + [1.5, 1.75][n] + 'x Affinity boost. To switch to the ' + [1.75, 1.5][n] + 'x Affinity boost, disable and re-enable this special', + name: '1401warning' + }); + }, + }, + 1402: { + atk: function(p) { return p.unit.type == "PSY" ? window.specials[1402].multiplier : 1; }, + type: "type", + onActivation: function(p) { + var n = (window.specials[1402].multiplier == 1.3 ? 1 : 0); + window.specials[1402].multiplier = [1.3, 1.5][n]; + p.scope.notify({ + text: 'Using the ' + [1.3, 1.5][n] + 'x Type boost. To switch to the ' + [1.5, 1.3][n] + 'x Type boost, disable and re-enable this special', + name: '1402warning' + }); + }, + }, + 1405: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.75 : 1; }, + type: "class", + orb: function(p) { return p.unit.class.has("Shooter") ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + warning: "Selected special (%name%) assumes that the enemy has Delay Protection." + }, + 1406: { + atk: function(p) { return p.unit.class.has("Shooter") ? 1.75 : 1; }, + type: "class", + orb: function(p) { return p.unit.class.has("Shooter") ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + warning: "Selected special (%name%) assumes that the enemy has Delay Protection." + }, + 1407: { + atk: function(p) { return p.unit.type == "PSY" || p.unit.type == "DEX" ? 2 : 1; }, + type: "type" + }, + 1408: { + atk: function(p) { return p.unit.type == "PSY" || p.unit.type == "DEX" ? 2 : 1; }, + type: "type" + }, + 1409: { + delay: function(p) { return 1; }, + atk: function(p) { + return p.unit.class.has("Slasher") || p.unit.class.has("Free Spirit") ? 1.75 : 1; + }, + type: "class" + }, + 1410: { + delay: function(p) { return 1; }, + atk: function(p) { + return p.unit.class.has("Slasher") || p.unit.class.has("Free Spirit") ? 1.75 : 1; + }, + type: "class" + }, + 1415: { + atk: function(p) { return p.unit.cost <= 30 ? 1.5 : 1; }, + type: "class" + }, + 1416: { + atk: function(p) { return p.unit.cost <= 30 ? 1.5 : 1; }, + type: "class" + }, + 1419: { + atk: function(p) { return p.defenseDown ? 1.5 : 1; }, + type: "condition" + }, + 1420: { + atk: function(p) { return p.defenseDown ? 1.5 : 1; }, + type: "condition" + }, + 1421: { + atk: function(p) { return p.unit.class.has("Driven") ? window.specials[1421].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (p.percHP == 100 ? 2 : 1.5); + window.specials[1421].multiplier = n; + p.scope.notify({ + text: 'HP ' + (n == 2 ? 'equal to' : 'below') + ' 100%, using the ' + n + 'x multiplier.', + name: '1421warning' + }); + } + }, + 1422: { + atk: function(p) { return p.unit.class.has("Driven") ? window.specials[1422].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (p.percHP == 100 ? 2 : 1.5); + window.specials[1422].multiplier = n; + p.scope.notify({ + text: 'HP ' + (n == 2 ? 'equal to' : 'below') + ' 100%, using the ' + n + 'x multiplier.', + name: '1422warning' + }); + } + }, + 1425: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); }, + warning: "Selected special (%name%) assumes that an ally has been inflicted with Bind." + }, + 1426: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); }, + warning: "Selected special (%name%) assumes that an ally has been inflicted with Bind." + }, + 1428: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.75 : 1; }, + type: "class", + warning: "Selected special (%name%) assumes that the enemy has been Delayed." + }, + 1431: { + atk: function(p) { return 1.5; }, + type: "type" + }, + 1432: { + atk: function(p) { return 1.5; }, + type: "type" + }, + 1435: { + delay: function(p) { return 1; }, + }, + 1436: { + delay: function(p) { return 1; }, + }, + 1437: { + atk: function(p) { return p.delayed > 0 ? 1.5 : 1; }, + type: "condition", + orb: function(p) { return p.unit.class.has("Powerhouse") ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + }, + 1438: { + atk: function(p) { return p.delayed > 0 ? 1.5 : 1; }, + type: "condition", + orb: function(p) { return p.unit.class.has("Powerhouse") ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + }, + 1439: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.75 : 1; }, + type: "class" + }, + 1440: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.75 : 1; }, + type: "class" + }, + 1441: { + chain: function(p) { return 2.5; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2.5 : 1; + } + }, + 1442: { + chain: function(p) { return 2.5; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2.5 : 1; + } + }, + 1443: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + type: "class", + orb: function(p) { return p.unit.class.has("Powerhouse") ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + }, + 1444: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.5 : 1; }, + type: "class", + orb: function(p) { return p.unit.class.has("Powerhouse") ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + }, + 1445: { + delay: function(p) { return 1; }, + atk: function(p) { return p.unit.type == "PSY" || p.unit.type == "QCK" ? 1.75 : 1; }, + rcv: function(p) { return p.unit.type == "PSY" || p.unit.type == "QCK" ? 1.75 : 1; }, + type: "type" + }, + 1446: { + delay: function(p) { return 1; }, + }, + 1447: { + atk: function(p) { return p.slot == p.sourceSlot ? window.specials[1447].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[1447].multiplier == 1.2 ? 1 : 0); + window.specials[1447].multiplier = [1.2, 1.5][n]; + p.scope.notify({ + text: 'Using the ' + [1.2, 1.5][n] + 'x ATK multiplier. To switch to the ' + [1.5, 1.2][n] + 'x multiplier, disable and re-enable this special', + name: '1447warning' + }); + } + }, + 1449: { + def: function(p) { return 0.5; } + }, + 1450: { + def: function(p) { return 0.5; } + }, + 1459: { + atk: function(p) { return p.defenseDown ? 1.5 : 1; }, + type: "condition" + }, + 1460: { + atk: function(p) { return p.defenseDown ? 1.5 : 1; }, + type: "condition" + }, + 1461: { + atk: function(p) { return p.unit.type == "QCK" ? 1.5 : 1; }, + type: "type" + }, + 1462: { + turnedOn: false, + onActivation: function(p) { + window.specials[1462].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1462].turnedOn = false; + } + }, + 1463: { + turnedOn: false, + onActivation: function(p) { + window.specials[1463].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1463].turnedOn = false; + } + }, + 1466: { + def: function(p) { return 0; } + }, + 1467: { + def: function(p) { return 0; } + }, + 1468: { + delay: function(p) { return 1; }, + }, + 1469: { + delay: function(p) { return 1; }, + }, + 1476: { + delay: function(p) { return 1; }, + atk: function(p) { + return p.unit.class.has("Striker") || p.unit.class.has("Powerhouse") ? 1.75 : 1; + }, + type: "class" + }, + 1477: { + delay: function(p) { return 1; }, + atk: function(p) { + return p.unit.class.has("Striker") || p.unit.class.has("Powerhouse") ? 1.75 : 1; + }, + type: "class" + }, + 1478: { + atk: function(p) { return p.unit.type == "INT" || p.unit.type == "QCK" ? 2 : 1; }, + type: "type" + }, + 1479: { + atk: function(p) { return p.unit.type == "INT" || p.unit.type == "QCK" ? 2 : 1; }, + type: "type" + }, + 1482: { + atk: function(p) { return window.specials[1482].multiplier; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[1482].multiplier == 1.25 ? 1 : 0); + window.specials[1482].multiplier = [1.25, 1.75][n]; + p.scope.notify({ + text: 'Using the ' + [1.25, 1.75][n] + 'x ATK multiplier. To switch to the ' + [1.75, 1.25][n] + 'x multiplier, disable and re-enable this special', + name: '1482warning' + }); + }, + }, + 1483: { + atk: function(p) { return window.specials[1483].multiplier; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[1483].multiplier == 1.25 ? 1 : 0); + window.specials[1483].multiplier = [1.25, 1.75][n]; + p.scope.notify({ + text: 'Using the ' + [1.25, 1.75][n] + 'x ATK multiplier. To switch to the ' + [1.75, 1.25][n] + 'x multiplier, disable and re-enable this special', + name: '1483warning' + }); + }, + }, + 1484: { + chain: function(p) { return 2.5; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2.5 : 1; + } + }, + 1485: { + chain: function(p) { return 2.5; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2.5 : 1; + } + }, + 1486: { + orb: function(p) { return (p.unit.class.has("Fighter")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1487: { + orb: function(p) { return (p.unit.class.has("Fighter")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1490: { + def: function(p) { return 0.5; } + }, + 1491: { + def: function(p) { return 0.5; } + }, + 1492: {//CHANGE THIS IF THIS ISN'T SABO + atk: function(p) { return !p.unit.class.has('Free Spirit') ? 1 : window.specials[1492].multiplier; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[1492].multiplier == 1.5 ? 1 : window.specials[1492].multiplier == 1.75 ? 2 : 0); + window.specials[1492].multiplier = [1.5, 1.75, 2][n]; + p.scope.notify({ + text: 'Using the ' + [1.5, 1.75, 2][n] + 'x ATK multiplier. To switch to the ' + [1.75, 2, 1.5][n] + 'x multiplier, disable and re-enable this special', + name: '1492warning' + }); + } + }, + 1497: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.5 : 1; }, + type: "type" + }, + 1501: { + atk: function(p) { return 1.3; }, + type: "type" + }, + 1505: { + atk: function(p) { return p.slot == p.sourceSlot ? 2.25 : 1; }, + type: "type" + }, + 1506: { + atk: function(p) { return p.slot == p.sourceSlot ? 2.25 : 1; }, + type: "type" + }, + 1507: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.75 : 1; }, + type: "class" + }, + 1508: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.75 : 1; }, + type: "class" + }, + 1511: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.5 : 1; }, + type: "type" + }, + 1512: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? window.specials[1512].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (p.percHP <= 30 ? 1.5 : 1); + window.specials[1512].multiplier = n; + p.scope.notify({ + text: 'HP ' + (n == 1.5 ? 'below' : 'above') + ' 30%, using the ' + n + 'x multiplier.', + name: '1512warning' + }); + } + }, + 1515: { + turnedOn: false, + onActivation: function(p) { + window.specials[1515].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1515].turnedOn = false; + } + }, + 1516: { + turnedOn: false, + onActivation: function(p) { + window.specials[1516].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1516].turnedOn = false; + } + }, + 1517: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 1518: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 1522: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.75 : 1; }, + type: "type", + }, + 1525: { + delay: function(p) { return 1; }, + atk: function(p) { return p.delayed > 0 ? 1.3 : 1; }, + type: "condition", + }, + 1526: { + atk: function(p) { return p.slot < 2 ? window.specials[1526].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[1526].multiplier == 1.5 ? 1 : 0); + window.specials[1526].multiplier = [1.5, 1.75][n]; + p.scope.notify({ + text: 'Using the ' + [1.5, 1.75][n] + 'x ATK multiplier. To switch to the ' + [1.75, 1.5][n] + 'x multiplier, disable and re-enable this special', + name: '1526warning' + }); + }, + }, + 1527: { + atk: function(p) { return p.slot < 2 ? window.specials[1527].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[1527].multiplier == 1.5 ? 1 : 0); + window.specials[1527].multiplier = [1.5, 1.75][n]; + p.scope.notify({ + text: 'Using the ' + [1.5, 1.75][n] + 'x ATK multiplier. To switch to the ' + [1.75, 1.5][n] + 'x multiplier, disable and re-enable this special', + name: '1527warning' + }); + }, + }, + 1528: { + turnedOn: false, + onActivation: function(p) { + if(p.percHP < 30){ + window.specials[1528].turnedOn = true; + } + }, + onDeactivation: function(p) { + window.specials[1528].turnedOn = false; + } + }, + 1529: { + orb: function(p) { return (p.unit.class.has("Slasher")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, window.specials[1529].multiplier, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + onActivation: function(p) { + var n = (p.percHP >= 50 ? 2.25 : 2); + window.specials[1529].multiplier = n; + p.scope.notify({ + text: 'HP ' + (n == 2.25 ? 'above' : 'below') + ' 50%, using the ' + n + 'x multiplier.', + name: '1529warning' + }); + } + }, + 1530: { + orb: function(p) { return (p.unit.class.has("Slasher")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, window.specials[1530].multiplier, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + onActivation: function(p) { + var n = (p.percHP >= 50 ? 2.25 : 2); + window.specials[1530].multiplier = n; + p.scope.notify({ + text: 'HP ' + (n == 2.25 ? 'above' : 'below') + ' 50%, using the ' + n + 'x multiplier.', + name: '1530warning' + }); + } + }, + 1531: { + delay: function(p) { return 1; }, + chainAddition: function(p) {return window.specials[1531].multiplier;}, + onActivation: function(p) { + var n = (window.specials[1531].multiplier == 0.2 ? 1 : 0); + window.specials[1531].multiplier = [0.2, 0.3][n]; + p.scope.notify({ + text: 'Using the ' + [0.2, 0.3][n] + 'x chain addition. To switch to the ' + [0.3, 0.2][n] + 'x chain addition, disable and re-enable this special', + name: '1531warning' + }); + } + }, + 1532: { + delay: function(p) { return 1; }, + chainAddition: function(p) {return window.specials[1532].multiplier;}, + onActivation: function(p) { + var n = (window.specials[1532].multiplier == 0.2 ? 1 : 0); + window.specials[1532].multiplier = [0.2, 0.3][n]; + p.scope.notify({ + text: 'Using the ' + [0.2, 0.3][n] + 'x chain addition. To switch to the ' + [0.3, 0.2][n] + 'x chain addition, disable and re-enable this special', + name: '1532warning' + }); + } + }, + 1535: { + atk: function(p) { return p.unit.type == "PSY" ? 1.75 : 1; }, + type: "type" + }, + 1536: { + atk: function(p) { return p.unit.type == "PSY" ? 1.75 : 1; }, + type: "type" + }, + 1539: { + def: function(p) { return 0.1; } + }, + 1540: { + def: function(p) { return 0.1; } + }, + 1541: { + chainAddition: function(p) { return 0.5; }, + def: function(p) { return 0; } + }, + 1542: { + chainAddition: function(p){ return 0.5; }, + def: function(p) { return 0; } + }, + 1543: { + delay: function(p) { return 1; }, + }, + 1544: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, + type: "class" + }, + 1545: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, + type: "class" + }, + 1546: { + turnedOn: false, + onActivation: function(p) { + window.specials[1546].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1546].turnedOn = false; + }, + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; }, + type: "class" + }, + 1547: { + turnedOn: false, + onActivation: function(p) { + window.specials[1547].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1547].turnedOn = false; + }, + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; }, + type: "class" + }, + 1548: { + delay: function(p) { return 1; }, + chainAddition: function(p){ return 0.2;} + }, + 1551: { + delay: function(p) { return 1; }, + }, + 1552: { + atk: function(p) { return p.unit.cost == 40 ? 1.75 : 1; }, + type: "class" + }, + 1553: { + atk: function(p) { return p.unit.cost == 40 ? 1.75 : 1; }, + type: "class" + }, + 1554: { + atk: function(p) { return p.unit.type == "DEX" ? 1.35 : 1; }, + orb: function(p) { return p.unit.type == "DEX" ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.35, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + type: "type", + }, + 1555: { + atk: function(p) { return p.unit.type == "DEX" ? 1.35 : 1; }, + orb: function(p) { return p.unit.type == "DEX" ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.35, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + type: "type", + }, + 1556: { + atk: function(p) { return p.slot == p.sourceSlot ? 2 : 1; }, + type: "type", + warning: "Selected special (%name%) assumes that the enemy has over 3,000,000 HP." + }, + 1557: { + turnedOn: false, + onActivation: function(p) { + window.specials[1557].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1557].turnedOn = false; + }, + }, + 1561: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, + type: "class" + }, + 1562: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.75 : 1; }, + type: "class" + }, + 1563: { + chainAddition: function(p) { return 0.3; } + }, + 1564: { + chainAddition: function(p) { return 0.3; } + }, + 1567: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 1568: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 1570: { + staticMult: function(p) { return 80; } + }, + 1571: { + staticMult: function(p) { return 80; } + }, + 1572: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.75 : 1; }, + type: "class" + }, + 1573: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.75 : 1; }, + type: "class" + }, + 1574: { + delay: function(p) { return 1; }, + }, + 1575: { + delay: function(p) { return 1; }, + }, + 1578: { + chainAddition: function(p) {return window.specials[1578].multiplier;}, + onActivation: function(p) { + var n = (window.specials[1578].multiplier == 0.2 ? 1 : window.specials[1578].multiplier == 0.3 ? 2 : 0); + window.specials[1578].multiplier = [0.2, 0.3, 0.5][n]; + p.scope.notify({ + text: 'Using the ' + [0.2, 0.3, 0.5][n] + 'x chain addition. To switch to the ' + [0.3, 0.5, 0.2][n] + 'x chain addition, disable and re-enable this special', + name: '1578warning' + }); + } + }, + 1579: { + chainAddition: function(p) {return window.specials[1579].multiplier;}, + onActivation: function(p) { + var n = (window.specials[1579].multiplier == 0.2 ? 1 : window.specials[1579].multiplier == 0.3 ? 2 : 0); + window.specials[1579].multiplier = [0.2, 0.3, 0.5][n]; + p.scope.notify({ + text: 'Using the ' + [0.2, 0.3, 0.5][n] + 'x chain addition. To switch to the ' + [0.3, 0.5, 0.2][n] + 'x chain addition, disable and re-enable this special', + name: '1579warning' + }); + } + }, + 1580: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 1581: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 1582: { + atk: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; }, + rcv: function(p) { return p.unit.class.has("Cerebral") ? 1.5 : 1; }, + type: "class" + }, + 1583:{ + orb: function(p) { return (p.unit.class.has("Striker")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, window.specials[1583].multiplier, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + onActivation: function(p) { + var n = (window.specials[1583].multiplier == 1.5 ? 1 : 0); + window.specials[1583].multiplier = [1.5, 2][n]; + p.scope.notify({ + text: 'Using the ' + [1.5, 2][n] + 'x Orb boost. To switch to the ' + [2, 1.5][n] + 'x Orb boost, disable and re-enable this special', + name: '1583warning' + }); + }, + }, + 1584:{ + orb: function(p) { return (p.unit.class.has("Striker")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, window.specials[1584].multiplier, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + onActivation: function(p) { + var n = (window.specials[1584].multiplier == 1.5 ? 1 : 0); + window.specials[1584].multiplier = [1.5, 2][n]; + p.scope.notify({ + text: 'Using the ' + [1.5, 2][n] + 'x Orb boost. To switch to the ' + [2, 1.5][n] + 'x Orb boost, disable and re-enable this special', + name: '1584warning' + }); + }, + }, + 1585: { + atk: function(p) { return (p.percHP*p.maxHP/100 < 5000 && (p.unit.class.has("Slasher") || p.unit.class.has("Driven"))) ? 1.75 : 1; }, + rcv: function(p) { return (p.percHP*p.maxHP/100 < 5000 && (p.unit.class.has("Slasher") || p.unit.class.has("Driven"))) ? 1.5 : 1; }, + type: "class" + }, + 1586: { + atk: function(p) { return (p.percHP*p.maxHP/100 < 5000 && (p.unit.class.has("Slasher") || p.unit.class.has("Driven"))) ? 1.75 : 1; }, + rcv: function(p) { return (p.percHP*p.maxHP/100 < 5000 && (p.unit.class.has("Slasher") || p.unit.class.has("Driven"))) ? 1.5 : 1; }, + type: "class" + }, + 1587: { + atk: function(p) { return p.slot == p.sourceSlot ? 2 : 1; }, + type: "type" + }, + 1588: { + atk: function(p) { return p.slot == p.sourceSlot ? 2 : 1; }, + type: "type" + }, + 1591: { + atk: function(p) { + return p.unit.class.has("Fighter") || p.unit.class.has("Free Spirit") ? 1.75 : 1; + }, + type: "class" + }, + 1592: { + atk: function(p) { + return p.unit.class.has("Fighter") || p.unit.class.has("Free Spirit") ? 1.75 : 1; + }, + type: "class" + }, + 1593: { + turnedOn: false, + onActivation: function(p) { + window.specials[1593].turnedOn = true; + p.scope.notify({ + text: 'This does not activate G4 Captain boost, only the "beneficial" Orb Effect, to enable G4\' 4x boost, use the Captain Action checkboxes.', + name: '1593warning' + }); + }, + onDeactivation: function(p) { + window.specials[1593].turnedOn = false; + } + }, + 1594: { + orb: function(p) { return (p.unit.class.has("Powerhouse")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1595: { + orb: function(p) { return (p.unit.class.has("Powerhouse")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1598: { + atk: function(p) { return 1.2 }, + type: "class", + }, + 1599: { + def: function(p) { return 0.5 }, + }, + 1600: { + orb: function(p) { return (p.unit.type == "INT" || p.unit.type == "PSY") ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + }, + 1603: { + delay: function(p) { return 1; }, + }, + 1606: { + delay: function(p) { return 1; }, + def: function(p) { return 0.5 }, + }, + 1607: { + atk: function(p) { return (p.unit.class.has("Shooter")) ? 1.5 : 1; }, + type: "class", + }, + 1613: { + def: function(p) { return 0.5 }, + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 1614: { + def: function(p) { return 0.5 }, + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 1615: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, + type: "class", + orb: function(p) { return p.unit.class.has("Striker") ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1616: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.5 : 1; }, + type: "class", + orb: function(p) { return p.unit.class.has("Striker") ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1617: { + atk: function(p) { return p.unit.type == "STR" || p.unit.type == "INT" || p.unit.type == "DEX" ? 1.75 : 1; }, + type: "type" + }, + 1618: { + atk: function(p) { return p.unit.type == "STR" || p.unit.type == "INT" || p.unit.type == "DEX" ? 1.75 : 1; }, + type: "type" + }, + 1619: { + delay: function(p) { return 1; }, + }, + 1620: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; }, + type: "class", + }, + 1621: { + atk: function(p) { return p.unit.class.has("Striker") ? 2 : 1; }, + type: "class", + }, + 1622: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]); } + }, + 1623: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]); } + }, + 1626: { + atk: function(p) { return p.unit.type == "PSY" ? 1.5 : 1; }, + type: "type" + }, + 1627: { + affinity: function(p){ return p.unit.class.has("Striker") ? window.specials[1627].multiplier : 1; }, + onActivation: function(p) { + var n = (window.specials[1627].multiplier == 1.25 ? 1 : window.specials[1627].multiplier == 1.5 ? 2 : 0); + window.specials[1627].multiplier = [1.25, 1.5, 1.75][n]; + p.scope.notify({ + text: 'Using the ' + [1.25, 1.5, 1.75][n] + 'x affinity boost. To switch to the ' + [1.5, 1.75, 1.25][n] + 'x affinity boost, disable and re-enable this special', + name: '1627warning' + }); + } + }, + 1628: { + affinity: function(p){ return p.unit.class.has("Striker") ? window.specials[1628].multiplier : 1; }, + onActivation: function(p) { + var n = (window.specials[1628].multiplier == 1.25 ? 1 : window.specials[1628].multiplier == 1.5 ? 2 : 0); + window.specials[1628].multiplier = [1.25, 1.5, 1.75][n]; + p.scope.notify({ + text: 'Using the ' + [1.25, 1.5, 1.75][n] + 'x affinity boost. To switch to the ' + [1.5, 1.75, 1.25][n] + 'x affinity boost, disable and re-enable this special', + name: '1628warning' + }); + } + }, + 1631: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.75 : 1; }, + type: "class", + }, + 1632: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 1.75 : 1; }, + type: "class", + }, + 1633: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.25, [p.friendCaptain, p.captain]); } + }, + 1636: { + atk: function(p) { return 1.3; }, + type: "condition", + warning: "Selected special (%name%) assumes that the enemy has been poisoned or STRONGLY Poisoned." + }, + 1637: { + atk: function(p) { return 1.3; }, + type: "condition", + warning: "Selected special (%name%) assumes that the enemy has been poisoned or STRONGLY Poisoned." + }, + 1640: { + turnedOn: false, + onActivation: function(p) { + window.specials[1640].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1640].turnedOn = false; + } + }, + 1641: { + atk: function(p) { return 1.2; }, + type: "condition", + warning: "Selected special (%name%) assumes that the enemy has been poisoned or STRONGLY Poisoned." + }, + 1643: { + atk: function(p) { return p.unit.class.has("Slasher") ? 1.2 : 1; }, + type: "class", + }, + 1650: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 1651: { + turnedOn: false, + onActivation: function(p) { + window.specials[1651].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1651].turnedOn = false; + } + }, + 1652: { + turnedOn: false, + onActivation: function(p) { + window.specials[1652].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1652].turnedOn = false; + } + }, + 1653: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 1654: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 1655: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, + type: "type" + }, + 1656: { + atk: function(p) { return p.unit.type == "QCK" ? 2 : 1; }, + type: "type" + }, + 1657: { + chain: function(p) { return p.captain.class.has("Striker") ? 2.75 : 1; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2.75 : 1; + } + }, + 1658: { + chain: function(p) { return p.captain.class.has("Striker") ? 2.75 : 1; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2.75 : 1; + } + }, + 1661: { + chain: function(p) { return 2.5; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2.5 : 1; + } + }, + 1662: { + chain: function(p) { return 2.5; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2.5 : 1; + } + }, + 1664: { + atk: function(p) { return p.captain.class.has("Shooter") ? p.unit.class.has("Shooter") ? 2 : 1 : 1; }, + type: "class", + }, + 1665: { + atk: function(p) { return p.captain.class.has("Shooter") ? p.unit.class.has("Shooter") ? 2 : 1 : 1; }, + type: "class", + }, + 1666: { + orb: function(p) { return (p.unit.class.has("Powerhouse") || p.unit.class.has("Striker")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, window.specials[1666].multiplier, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + onActivation: function(p) { + var n = (p.percHP <= 70 ? 1 : 1.5); + window.specials[1666].multiplier = n; + p.scope.notify({ + text: 'HP ' + (n == 1.5 ? 'above' : 'below') + ' 70%, using the ' + n + 'x orb boost.', + name: '1666warning' + }); + } + }, + 1667: { + orb: function(p) { return (p.unit.class.has("Powerhouse") || p.unit.class.has("Striker")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, window.specials[1667].multiplier, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + onActivation: function(p) { + var n = (p.percHP <= 70 ? 1 : 1.5); + window.specials[1667].multiplier = n; + p.scope.notify({ + text: 'HP ' + (n == 1.5 ? 'above' : 'below') + ' 70%, using the ' + n + 'x orb boost.', + name: '1667warning' + }); + } + }, + 1668: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.75 : 1; }, + type: "class" + }, + 1669: { + atk: function(p) { return p.unit.class.has("Striker") ? 1.75 : 1; }, + type: "class" + }, + 1670: { + delay: function(p) { return 1; }, + }, + 1671: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 1673: { + def: function(p) { return 0.1; } + }, + 1674: { + def: function(p) { return 0.1; } + }, + 1675: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Driven") ? 1.5 : 1}, + type: "class" + }, + 1676: { + atk: function(p) { return p.unit.class.has("Slasher") || p.unit.class.has("Driven") ? 1.5 : 1}, + type: "class" + }, + 1677: { + affinity: function(p){ return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 1678: { + affinity: function(p){ return p.unit.class.has("Slasher") ? 1.5 : 1; } + }, + 1681: { + chainAddition: function(p) { return window.specials[1681].multiplier; }, + onActivation: function(p) { + var n = (p.slot > 1 ? 0.5 : 0); + window.specials[1681].multiplier = n; + p.scope.notify({ + text: 'Luffy is ' + (n == 0.5 ? 'not captain' : 'captain') + ', using the ' + n + ' Chain Addition.', + name: '1681warning' + }); + } + }, + 1682: { + chainAddition: function(p) { return window.specials[1682].multiplier; }, + onActivation: function(p) { + var n = (p.slot > 1 ? 0.5 : 0); + window.specials[1682].multiplier = n; + p.scope.notify({ + text: 'Luffy is ' + (n == 0.5 ? 'not captain' : 'captain') + ', using the ' + n + ' Chain Addition.', + name: '1682warning' + }); + } + }, + 1683: { + atk: function(p) { return p.defenseDown ? 1.5 : 1; }, + type: "condition" + }, + 1684: { + atk: function(p) { return p.defenseDown ? 1.5 : 1; }, + type: "condition" + }, + 1685: { + delay: function(p) { return 1; }, + }, + 1686: { + delay: function(p) { return 1; }, + }, + 1687: { + def: function(p) { return 0; } + }, + 1688: { + def: function(p) { return 0; } + }, + 1689: { + atk: function(p) { return p.slot == p.sourceSlot ? 2 : 1; }, + type: "type" + }, + 1690: { + atk: function(p) { return p.slot == p.sourceSlot ? 2 : 1; }, + type: "type" + }, + 1691: { + atk: function(p) { return p.defenseDown ? 1.3 : 1; }, + type: "condition" + }, + 1692: { + chainAddition: function(p){ return 0.3; }, + def: function(p) { return 0.5; } + }, + 1693: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.75 : 1; }, + type: "type", + orb: function(p) { return p.slot == p.sourceSlot ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain])} + }, + 1694: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.75 : 1; }, + type: "type", + orb: function(p) { return p.slot == p.sourceSlot ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain])} + }, + 1695: { + orb: function(p) { return (p.unit.class.has("Striker")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1696: { + orb: function(p) { return (p.unit.class.has("Striker")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1699: { + chainAddition: function(p) { return 0.3; } + }, + 1700: { + chainAddition: function(p) { return 0.3; } + }, + 1703: { + atk: function(p) { return 1.75; }, + type: "condition", + warning: "Selected special (%name%) assumes that the enemy has been inflicted with Toxin." + }, + 1704: { + atk: function(p) { return 1.75; }, + type: "condition", + warning: "Selected special (%name%) assumes that the enemy has been inflicted with Toxin." + }, + 1707: { + def: function(p) { return 0; } + }, + 1710: { + orb: function(p) { return (p.unit.class.has("Cerebral")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1711: { + orb: function(p) { return (p.unit.class.has("Cerebral")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1712: { + orb: function(p) { return (p.unit.class.has("Driven")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1713: { + orb: function(p) { return (p.unit.class.has("Driven")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1716: { + atk: function(p) { return p.unit.class.has("Driven") ? window.specials[1716].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (p.percHP <= 30 ? 1.75 : 1); + window.specials[1716].multiplier = n; + p.scope.notify({ + text: 'HP ' + (n == 1.75 ? 'below' : 'above') + ' 30%, using the ' + n + 'x multiplier.', + name: '1716warning' + }); + } + }, + 1718: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.25 : 1}, + type: "class" + }, + 1720: { + chain: function(p) { return p.captain.class.has("Fighter") ? 2.5 : 1; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2.5 : 1; + } + }, + 1721: { + chain: function(p) { return p.captain.class.has("Fighter") ? 2.5 : 1; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2.5 : 1; + } + }, + 1722: { + atk: function(p) { return p.unit.class.has("Striker") ? window.specials[1722].multiplier : 1; }, + type: "type", + onActivation: function(p) { + var n = (p.percHP <= 30 ? 1.5 : 1); + window.specials[1722].multiplier = n; + p.scope.notify({ + text: 'Using the ' + n + 'x multiplier.', + name: '1722warning' + }); + } + }, + 1723: { + atk: function(p) { return p.unit.class.has("Striker") ? window.specials[1723].multiplier : 1; }, + type: "type", + onActivation: function(p) { + var n = (p.percHP <= 30 ? 1.5 : 1); + window.specials[1723].multiplier = n; + p.scope.notify({ + text: 'Using the ' + n + 'x multiplier.', + name: '1723warning' + }); + } + }, + 1724: { + staticMult: function(p) { return 25; } + }, + 1725: { + staticMult: function(p) { return 25; } + }, + 1726: { + staticMult: function(p) { return 55; } + }, + 1727: { + staticMult: function(p) { return 55; } + }, + 1732: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Powerhouse") ? 1.75 : 1}, + warning: "Selected special (%name%) assumes that the enemy has Delay Protection.", + type: "class" + }, + 1733: { + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Powerhouse") ? 1.75 : 1}, + warning: "Selected special (%name%) assumes that the enemy has Delay Protection.", + type: "class" + }, + 1736: { + delay: function(p) { return 1; }, + }, + 1737: { + delay: function(p) { return 1; }, + }, + 1738: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 1739: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 1740: { + def: function(p) { return .2; }, + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Powerhouse") ? 1.75 : 1}, + type: "class" + }, + 1741: { + def: function(p) { return .2; }, + atk: function(p) { return p.unit.class.has("Striker") || p.unit.class.has("Powerhouse") ? 1.75 : 1}, + type: "class" + }, + 1742: { + atk: function(p) { return p.defenseDown ? 1.75 : 1; }, + type: "condition" + }, + 1743: { + atk: function(p) { return p.defenseDown ? 1.75 : 1; }, + type: "condition" + }, + 1744: { + orb: function(p) { return (p.unit.class.has("Shooter")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1745: { + orb: function(p) { return (p.unit.class.has("Shooter")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1746: { + delay: function(p) { return 1; }, + turnedOn: false, + onActivation: function(p) { + window.specials[1746].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1746].turnedOn = false; + } + }, + 1747: { + delay: function(p) { return 1; }, + turnedOn: false, + onActivation: function(p) { + window.specials[1747].turnedOn = true; + }, + onDeactivation: function(p) { + window.specials[1747].turnedOn = false; + } + }, + 1750:{ + orb: function(p) { return (p.unit.class.has("Striker")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, window.specials[1750].multiplier, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + onActivation: function(p) { + var n = (window.specials[1750].multiplier == 1.75 ? 1 : 0); + window.specials[1750].multiplier = [1.75, 2.25][n]; + p.scope.notify({ + text: 'Using the ' + [1.75, 2.25][n] + 'x Orb boost. To switch to the ' + [2.25, 1.75][n] + 'x Orb boost, disable and re-enable this special', + name: '1584warning' + }); + }, + }, + 1751:{ + orb: function(p) { return (p.unit.class.has("Striker")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, window.specials[1751].multiplier, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + onActivation: function(p) { + var n = (window.specials[1751].multiplier == 1.75 ? 1 : 0); + window.specials[1751].multiplier = [1.75, 2.25][n]; + p.scope.notify({ + text: 'Using the ' + [1.75, 2.25][n] + 'x Orb boost. To switch to the ' + [2.25, 1.75][n] + 'x Orb boost, disable and re-enable this special', + name: '1584warning' + }); + }, + }, + 1752: { + atk: function(p) { return !(p.unit.cost <= 30) ? 1 : window.specials[1752].multiplier; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[1752].multiplier == 1.75 ? 1 : 0); + window.specials[1752].multiplier = [1.75, 2][n]; + p.scope.notify({ + text: 'Using the ' + [1.75, 2][n] + 'x ATK multiplier. To switch to the ' + [2, 1.75][n] + 'x multiplier, disable and re-enable this special', + name: '1752warning' + }); + } + }, + 1753: { + atk: function(p) { return !(p.unit.cost <= 30) ? 1 : window.specials[1753].multiplier; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[1753].multiplier == 1.75 ? 1 : 0); + window.specials[1753].multiplier = [1.75, 2][n]; + p.scope.notify({ + text: 'Using the ' + [1.75, 2][n] + 'x ATK multiplier. To switch to the ' + [2, 1.75][n] + 'x multiplier, disable and re-enable this special', + name: '1753warning' + }); + } + }, + 1754: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 1755: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 1758: { + delay: function(p) { return 1; }, + }, + 1759: { + delay: function(p) { return 1; }, + }, + 1762: { + def: function(p) { return .2; }, + }, + 1763: { + def: function(p) { return .2; }, + }, + 1764: { + chain: function(p) { return 2.5; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2.5 : 1; + } + }, + 1765: { + def: function(p) { return .5; }, + }, + 1766: { + def: function(p) { return .5; }, + }, + 1767: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1}, + type: "class" + }, + 1769: { + delay: function(p) { return 1; }, + atk: function(p) { return (p.delayed > 0 && p.captain.class.has("Cerebral")) ? 1.5 : 1; }, + type: "condition", + }, + 1770: { + delay: function(p) { return 1; }, + atk: function(p) { return (p.delayed > 0 && p.captain.class.has("Cerebral")) ? 1.5 : 1; }, + type: "condition", + }, + 1771: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 1772: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 1773: { + orb: function(p) { return p.unit.class.has("Free Spirit") ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1774: { + orb: function(p) { return p.unit.class.has("Free Spirit") ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1777: { + chainAddition: function(p){ return 0.2;} + }, + 1778: { + chainAddition: function(p){ return 0.2;} + }, + 1779: { + chainAddition: function(p) {return 0.5;} + }, + 1780: { + chainAddition: function(p){ return 0.5;} + }, + 1782: { + delay: function(p) { return 1; }, + }, + 1783: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 1784: { + atk: function(p) { return 1.5; }, + type: "type" + }, + 1785: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.25, [p.friendCaptain, p.captain]); } + }, + 1791: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 1792: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]); } + }, + 1793: { + atk: function(p) { return !(p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK") ? 1 : window.specials[1793].multiplier; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[1793].multiplier == 1.75 ? 1 : 0); + window.specials[1793].multiplier = [1.75, 2][n]; + p.scope.notify({ + text: 'Using the ' + [1.75, 2][n] + 'x ATK multiplier. To switch to the ' + [2, 1.75][n] + 'x multiplier, disable and re-enable this special', + name: '1793warning' + }); + } + }, + 1794: { + atk: function(p) { return !(p.unit.type == "STR" || p.unit.type == "DEX" || p.unit.type == "QCK") ? 1 : window.specials[1794].multiplier; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[1794].multiplier == 1.75 ? 1 : 0); + window.specials[1794].multiplier = [1.75, 2][n]; + p.scope.notify({ + text: 'Using the ' + [1.75, 2][n] + 'x ATK multiplier. To switch to the ' + [2, 1.75][n] + 'x multiplier, disable and re-enable this special', + name: '1794warning' + }); + } + }, + 1795: { + delay: function(p) { return 1; }, + }, + 1796: { + delay: function(p) { return 1; }, + }, + 1797: { + atk: function(p) { return p.delayed > 0 ? 1.5 : 1; }, + type: "condition", + }, + 1798: { + atk: function(p) { return p.delayed > 0 ? 1.5 : 1; }, + type: "condition", + }, + 1799: { + atk: function(p) { return p.defenseDown ? 1.75 : 1; }, + type: "condition" + }, + 1800: { + atk: function(p) { return p.defenseDown ? 1.75 : 1; }, + type: "condition" + }, + 1801: { + def: function(p) { return 0.1; } + }, + 1802: { + def: function(p) { return 0.1; } + }, + 1805: { + def: function(p) { return 0.0; }, + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 1806: { + def: function(p) { return 0.0; }, + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]); } + }, + 1807: { + turnedOn: [ false, false ], + onActivation: function(p) { + window.specials[1807].turnedOn[p.slot] = true; + }, + onDeactivation: function(p) { + window.specials[1807].turnedOn[p.slot] = false; + }, + chain: function(p) { return p.captain.class.has("Slasher") ? 2.75 : 1; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2.75 : 1; + }, + orb: function(p) { return p.unit.class.has("Slasher") ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + }, + 1808: { + turnedOn: [ false, false ], + onActivation: function(p) { + window.specials[1808].turnedOn[p.slot] = true; + }, + onDeactivation: function(p) { + window.specials[1808].turnedOn[p.slot] = false; + }, + chain: function(p) { return p.captain.class.has("Slasher") ? 2.75 : 1; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2.75 : 1; + }, + orb: function(p) { return p.unit.class.has("Slasher") ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); }, + }, + 1811: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, + type: "class" + }, + 1812: { + atk: function(p) { return p.unit.class.has("Fighter") ? 1.5 : 1; }, + type: "class" + }, + 1813: { + atk: function(p) { return p.slot == 1 ? 1.5 : 1; }, + type: "class" + }, + 1814: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2 : 1; }, + type: "class" + }, + 1815: { + atk: function(p) { return p.unit.class.has("Powerhouse") ? 2 : 1; }, + type: "class" + }, + 1816: { + atk: function(p) { return p.unit.class.has("Shooter") ? 2 : 1; }, + type: "class" + }, + 1817: { + atk: function(p) { return p.slot > 1 ? 1.2 : 1; }, + type: "class" + }, + 1818: { + atk: function(p) { return p.slot > 1 ? 1.2 : 1; }, + type: "class" + }, + 1819: { + atk: function(p) { return p.slot == p.sourceSlot ? 1.75 : 1; }, + type: "type" + }, + 1825: { + affinity: function(p){ return p.unit.type == "INT" ? 1.75 : 1; } + }, + 1826: { + affinity: function(p){ return p.unit.type == "INT" ? 1.75 : 1; } + }, + 1827: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; }, + type: "type" + }, + 1828: { + atk: function(p) { return p.unit.type == "INT" ? 2 : 1; }, + type: "type" + }, + 1829: { + orb: function(p) { return (p.unit.class.has("Driven") || p.unit.class.has("Cerebral")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1830: { + orb: function(p) { return (p.unit.class.has("Driven") || p.unit.class.has("Cerebral")) ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.75, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1831: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]); } + }, + 1832: { + orb: function(p) { return CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 2, [p.friendCaptain, p.captain]); } + }, + 1835: { + chain: function(p) { return (p.captain.type == "STR" || p.captain.type == "PSY") ? 2.5 : 1; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2.5 : 1; + }, + delay: function(p) { return p.captain.class.has("Powerhouse") ? 1 : 0; }, + }, + 1836: { + chain: function(p) { return (p.captain.type == "STR" || p.captain.type == "PSY") ? 2.5 : 1; }, + chainLimiter: function(p) { + var prev = p.hitcombo[p.hitcombo.length - 1][p.chainPosition - 1] + return p.chainPosition === 0 ? 1 : (prev == 'Good' || prev == 'Great' || prev == 'Perfect') ? 2.5 : 1; + }, + delay: function(p) { return p.captain.class.has("Powerhouse") ? 1 : 0; }, + }, + 1837: { + atk: function(p) { return (p.captain.type == "QCK" || p.captain.type == "PSY") ? 1.75 : 1; }, + type: "class", + }, + 1838: { + atk: function(p) { return (p.captain.type == "QCK" || p.captain.type == "PSY") ? 1.75 : 1; }, + type: "class", + }, + 1839: { + atk: function(p) { return (p.delayed > 0 && (p.captain.type == "DEX" || p.captain.type == "PSY")) ? 1.75 : 1; }, + type: "condition", + staticMult: function(p) { return p.captain.class.has("Powerhouse") ? 40 : 0; } + }, + 1840: { + atk: function(p) { return (p.delayed > 0 && (p.captain.type == "DEX" || p.captain.type == "PSY")) ? 1.75 : 1; }, + type: "condition", + staticMult: function(p) { return p.captain.class.has("Powerhouse") ? 40 : 0; } + }, + 1841: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; }, + type: "class" + }, + 1842: { + atk: function(p) { return p.unit.class.has("Driven") ? 1.5 : 1; }, + type: "class" + }, + 1845: { + def: function(p) { return 0; } + }, + 1846: { + def: function(p) { return 0; } + }, + 1847: { + atk: function(p) { return 1.5; }, + type: "type" + }, + 1850: { + chainAddition: function(p) { return 0.5; } + }, + 1851: { + chainAddition: function(p) { return 0.5; } + }, + 1854: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; }, + type: "class", + orb: function(p) { return p.unit.class.has("Free Spirit") ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1855: { + atk: function(p) { return p.unit.class.has("Free Spirit") ? 1.5 : 1; }, + type: "class", + orb: function(p) { return p.unit.class.has("Free Spirit") ? CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1.5, [p.friendCaptain, p.captain]) : CrunchUtils.getOrbMultiplier(p.orb, p.unit.type, p.unit.class, 1, 1, [p.friendCaptain, p.captain]); } + }, + 1856: { + affinity: function(p){ return p.unit.class.has("Powerhouse") ? 1.25 : 1; } + }, + 1857: { + affinity: function(p){ return p.unit.class.has("Powerhouse") ? 1.25 : 1; } + }, + 1858: { + staticMult: function(p) { return 65; } + }, + 1859: { + staticMult: function(p) { return 65; } + }, + 1861: { + atk: function(p) { return (p.delayed > 0 && (p.captain.class.has("Shooter"))) ? 1.75 : 1; }, + type: "condition", + }, + 1865: {//Urouge FN + atk: function(p) { return p.unit.class.has("Striker") ? window.specials[1865].multiplier : 1; }, + type: "class", + onActivation: function(p) { + var n = (window.specials[1865].multiplier === 1.5 ? 1 : 0); + window.specials[1865].multiplier = [1.5, 1.75][n]; + p.scope.notify({ + text: 'Using the ' + [1.5, 1.75][n] + 'x ATK multiplier. To switch to the ' + [1.75, 1.5][n] + 'x multiplier, disable and re-enable this special', + name: '1865warning' + }); + } + }, + 2000: { + atk: function(p) { return 1.75; }, + type: "class" + }, + 2001: { + atk: function(p) { return 1.75; }, + type: "class" + }, +}; diff --git a/common/data/tandems.js b/common/data/tandems.js index 30b15fa20..8a97534b4 100644 --- a/common/data/tandems.js +++ b/common/data/tandems.js @@ -316,7 +316,17 @@ window.tandems = [ }, { "name": "Giant Pirates' Charge", - "desc": "Deals 3 times the cumulative ATK of all the characters in the tandem to all enemies, boosts ATK of Tough characters by 1.4x until the end of the current turn", + "desc": "Deals 3 times the cumulative ATK of all the characters in the tandem to all enemies, boosts ATK of Powerhouse characters by 1.4x until the end of the current turn", "units": [ 884, 903 ] - } + }, + { + "name": "Kidnapping Trio Rampage", + "desc": "Deals 3,000 fixed damage to all enemies", + "units": [ 954, 955, 956 ] + }, + { + "name": "Snake Pit Dance", + "desc": "Deals 3 times the cumulative ATK of all the characters in the tandem to all enemies, boosts ATK of Powerhouse characters by 1.3x until the end of the current turn", + "units": [ 1056, 1058 ] + }, ]; diff --git a/common/data/units.js b/common/data/units.js index 4456548dd..33fe2cdd4 100644 --- a/common/data/units.js +++ b/common/data/units.js @@ -1,922 +1,2007 @@ window.units = [ - [ "Monkey D. Luffy", "STR", "Fighter", 2, 1, 5, 0, 5, 163, 42, 15, 8, 134, 68, 15, 1 ], - [ "Monkey D. Luffy Gum-Gum Pistol", "STR", "Fighter", 3, 4, 6, 0, 20, 26184, 130, 76, 14, 510, 249, 49, 0.7 ], - [ "Monkey D. Luffy Gum-Gum Bazooka", "STR", "Fighter", 4, 7, 6, 2, 35, 136167, 404, 227, 39, 975, 522, 105, 1 ], - [ "Monkey D. Luffy Gear 2", "STR", [ "Fighter", "Freedom" ], 5, 15, 8, 3, 99, 3000000, 902, 473, 74, 1772, 1313, 227, 1 ], - [ "Roronoa Zoro", "DEX", "Slasher", 3, 4, 6, 0, 20, 26184, 126, 75, 15, 488, 239, 56, 0.7 ], - [ "Roronoa Zoro Three Thousand Worlds", "DEX", [ "Slasher", "Ambition" ], 4, 7, 6, 2, 35, 136167, 426, 222, 37, 899, 515, 120, 1 ], - [ "Roronoa Zoro Pound Phoenix", "DEX", [ "Slasher", "Ambition" ], 4, 9, 4, 2, 50, 392109, 462, 258, 37, 1216, 694, 106, 1 ], - [ "Roronoa Zoro Ashura Ichibugin", "DEX", [ "Slasher", "Ambition" ], 5, 15, 9, 3, 99, 3000000, 724, 667, 39, 2232, 1332, 144, 1 ], - [ "Nami", "INT", "Striker", 3, 4, 4, 0, 20, 26184, 72, 51, 32, 366, 201, 89, 0.7 ], - [ "Nami Tornado Tempo", "INT", [ "Striker", "Knowledge" ], 4, 7, 5, 2, 35, 136167, 336, 192, 62, 783, 453, 160, 1 ], - [ "Nami Mirage Tempo", "INT", [ "Striker", "Knowledge" ], 4, 9, 5, 2, 50, 392109, 348, 201, 75, 840, 543, 219, 1 ], - [ "Nami Thunderbolt Tempo", "INT", [ "Striker", "Knowledge" ], 5, 15, 4, 3, 99, 3000000, 494, 437, 154, 1262, 1088, 387, 1 ], - [ "Usopp", "PSY", "Shooter", 3, 4, 5, 0, 20, 26184, 50, 32, 42, 322, 127, 121, 0.7 ], - [ "Usopp Tabasco Star", "PSY", "Shooter", 4, 7, 6, 2, 35, 136167, 286, 148, 85, 627, 240, 257, 1 ], - [ "Usopp Golden Pound", "PSY", "Shooter", 4, 9, 6, 2, 50, 392109, 444, 237, 47, 1080, 648, 144, 1 ], - [ "Sogeking", "PSY", "Shooter", 5, 15, 7, 3, 99, 3000000, 638, 260, 189, 1506, 690, 479, 1 ], - [ "Sanji", "QCK", "Fighter", 3, 4, 6, 0, 20, 26184, 136, 64, 17, 506, 218, 60, 1 ], - [ "Sanji Plastic Surgery Shot", "QCK", [ "Fighter", "Tough" ], 4, 7, 5, 2, 35, 136167, 486, 207, 32, 907, 496, 125, 1 ], - [ "Chef Sanji Hot Rock Stew", "QCK", [ "Fighter", "Tough" ], 4, 9, 4, 2, 50, 392109, 494, 191, 54, 986, 500, 209, 1 ], - [ "Sanji Diable Jambe Flambe", "QCK", [ "Fighter", "Tough" ], 5, 15, 4, 3, 99, 3000000, 406, 418, 175, 2206, 1030, 249, 1 ], - [ "Tony Tony Chopper", "PSY", "Fighter", 3, 4, 5, 0, 20, 26184, 52, 40, 39, 294, 144, 120, 1 ], - [ "Tony Tony Chopper Heavy Point", "PSY", [ "Fighter", "Freedom" ], 4, 9, 5, 2, 50, 392109, 306, 213, 78, 754, 622, 207, 1 ], - [ "Tony Tony Chopper Brain Point", "INT", [ "Fighter", "Knowledge" ], 4, 9, 5, 2, 50, 392109, 258, 198, 91, 520, 454, 302, 1 ], - [ "Tony Tony Chopper Arm Point", "STR", [ "Fighter", "Tough" ], 4, 9, 4, 2, 50, 392109, 356, 260, 54, 868, 820, 122, 1 ], - [ "Tony Tony Chopper Horn Point", "QCK", "Fighter", 4, 9, 6, 2, 50, 392109, 414, 306, 29, 958, 856, 95, 1 ], - [ "Tony Tony Chopper Guard Point", "DEX", [ "Fighter", "Tough" ], 4, 9, 6, 2, 50, 392109, 394, 178, 75, 1320, 408, 184, 1 ], - [ "Higuma", "QCK", "Slasher", 2, 8, 5, 0, 35, 45389, 132, 87, 29, 692, 323, 99, 1 ], - [ "Master of the Near Sea", "STR", "Fighter", 2, 20, 5, 0, 35, 90778, 500, 350, 80, 550, 400, 100, 1.5 ], - [ "Iron-Mace Alvida", "STR", [ "Striker", "Tough" ], 3, 10, 5, 0, 50, 392109, 184, 154, 5, 1412, 755, 61, 1 ], - [ "Iron-Mace Alvida Smooth-Smooth Fruit", "STR", [ "Striker", "Freedom" ], 4, 15, 6, 1, 99, 3000000, 766, 625, 135, 1668, 999, 369, 1 ], - [ "Coby", "PSY", "Fighter", 2, 4, 5, 0, 25, 50439, 70, 25, 32, 166, 70, 120, 1 ], - [ "Cabin Boy Coby", "PSY", [ "Fighter", "Ambition" ], 3, 9, 5, 3, 50, 392109, 130, 49, 100, 524, 155, 216, 1 ], - [ "Helmeppo", "INT", "Shooter", 2, 4, 5, 0, 25, 50439, 62, 62, 21, 308, 242, 39, 1 ], - [ "Cabin Boy Helmeppo", "INT", [ "Fighter", "Ambition" ], 3, 8, 5, 3, 50, 392109, 234, 210, 29, 770, 485, 130, 1 ], - [ "Axe-Hand Morgan", "STR", [ "Slasher", "Ambition" ], 2, 9, 5, 0, 50, 261406, 133, 100, 5, 1554, 747, 35, 1 ], - [ "Mohji & Richie", "PSY", [ "Fighter", "Ambition" ], 2, 9, 6, 1, 50, 261406, 150, 135, 10, 1072, 559, 55, 1 ], - [ "Cabaji the Acrobat", "DEX", [ "Slasher", "Ambition" ], 2, 9, 6, 1, 50, 261406, 134, 77, 32, 824, 458, 130, 1 ], - [ "Buggy", "INT", [ "Slasher", "Ambition" ], 3, 8, 5, 0, 35, 136167, 200, 107, 22, 818, 446, 85, 1 ], - [ "Buggy the Clown", "INT", [ "Slasher", "Ambition" ], 4, 11, 5, 2, 70, 1066998, 714, 342, 58, 1666, 757, 135, 1 ], - [ "Gaimon", "PSY", "Shooter", 2, 3, 6, 0, 50, 261406, 133, 5, 14, 1303, 85, 121, 1.5 ], - [ "Siam", "INT", "Slasher", 2, 9, 6, 0, 50, 261406, 112, 112, 24, 724, 499, 133, 1 ], - [ "Butchie", "STR", [ "Slasher", "Tough" ], 2, 9, 6, 0, 50, 261406, 132, 117, 19, 872, 530, 98, 1 ], - [ "One-Two Django", "DEX", "Slasher", 2, 8, 5, 0, 35, 90778, 118, 64, 39, 556, 271, 139, 1 ], - [ "Dancing Django", "DEX", "Slasher", 3, 11, 5, 2, 70, 1066998, 476, 218, 98, 1155, 555, 228, 1 ], - [ "Captain Kuro", "QCK", [ "Slasher", "Knowledge" ], 3, 10, 7, 0, 70, 1066998, 144, 111, 31, 1102, 640, 151, 1 ], - [ "Kuro of a Hundred Plans", "QCK", [ "Slasher", "Knowledge" ], 4, 15, 8, 2, 99, 3000000, 978, 558, 122, 2074, 1057, 282, 1 ], - [ "Yosaku", "STR", "Slasher", 2, 5, 6, 1, 40, 134812, 100, 43, 19, 439, 439, 99, 1.5 ], - [ "Johnny", "QCK", "Slasher", 2, 7, 6, 1, 40, 134812, 100, 42, 20, 421, 421, 108, 1.5 ], - [ "Iron Fist Fullbody", "STR", "Fighter", 2, 3, 6, 0, 15, 7532, 103, 100, 49, 153, 160, 84, 0.7 ], - [ "Patty", "STR", "Slasher", 2, 9, 5, 0, 50, 261406, 140, 65, 35, 872, 314, 170, 1 ], - [ "Carne", "QCK", "Slasher", 2, 9, 5, 0, 50, 261406, 94, 91, 34, 650, 428, 169, 1 ], - [ "Chef Zeff", "DEX", "Fighter", 3, 10, 5, 1, 50, 392109, 142, 118, 29, 908, 698, 164, 1.5 ], - [ "Gin", "QCK", "Shooter", 2, 8, 5, 0, 35, 90778, 148, 94, 24, 618, 363, 98, 1 ], - [ "Gin the Man-Demon", "QCK", "Striker", 3, 11, 6, 1, 70, 1066998, 558, 300, 57, 1152, 792, 209, 1 ], - [ "Pearl", "STR", [ "Striker", "Tough" ], 2, 8, 5, 0, 35, 90778, 198, 84, 19, 956, 296, 64, 1 ], - [ "Fire Pearl", "STR", [ "Striker", "Tough" ], 3, 11, 4, 1, 70, 1066998, 820, 226, 38, 1904, 656, 129, 1 ], - [ "Don Krieg", "INT", [ "Shooter", "Ambition" ], 3, 10, 6, 0, 50, 392109, 214, 97, 24, 1454, 632, 95, 1 ], - [ "Don Krieg Poison Gas Bomb MH5", "INT", [ "Shooter", "Ambition" ], 4, 15, 4, 2, 99, 3000000, 1276, 553, 74, 2734, 1057, 172, 1 ], - [ "Nezumi", "INT", [ "Shooter", "Knowledge" ], 2, 6, 6, 0, 30, 28779, 55, 55, 55, 150, 130, 204, 0.7 ], - [ "Momoo", "STR", "Fighter", 3, 18, 4, 0, 50, 392109, 600, 400, 120, 1000, 500, 150, 1.5 ], - [ "Choo", "INT", [ "Shooter", "Tough" ], 3, 9, 5, 1, 50, 392109, 110, 71, 49, 768, 492, 256, 1 ], - [ "Kuroobi", "STR", [ "Fighter", "Tough" ], 3, 9, 4, 1, 50, 392109, 160, 157, 10, 1200, 759, 76, 1 ], - [ "Hatchan", "DEX", [ "Slasher", "Tough" ], 3, 8, 8, 1, 35, 136167, 88, 88, 47, 588, 387, 143, 1 ], - [ "Six-Sword Hachi", "DEX", [ "Slasher", "Tough" ], 4, 11, 8, 2, 70, 1066998, 542, 338, 88, 986, 638, 288, 1 ], - [ "Arlong", "STR", [ "Slasher", "Tough" ], 3, 10, 5, 0, 50, 392109, 104, 152, 24, 936, 930, 82, 1 ], - [ "Enraged Arlong Shark On Tooth", "STR", [ "Slasher", "Tough" ], 4, 15, 4, 1, 99, 3000000, 832, 832, 55, 1974, 1491, 154, 1 ], - [ "Tashigi", "QCK", [ "Slasher", "Knowledge" ], 3, 9, 5, 1, 50, 392109, 102, 102, 41, 690, 483, 272, 1 ], - [ "Tashigi Navy HQ Ensign", "QCK", [ "Slasher", "Knowledge" ], 4, 15, 5, 2, 99, 3000000, 632, 431, 222, 1434, 921, 434, 1.5 ], - [ "Smoker", "DEX", [ "Striker", "Ambition" ], 3, 9, 5, 1, 50, 392109, 110, 113, 36, 944, 575, 199, 1 ], - [ "Smoker the White Hunter", "DEX", [ "Striker", "Ambition" ], 4, 15, 5, 2, 99, 3000000, 872, 515, 154, 1736, 1070, 334, 1.5 ], - [ "Miss Wednesday", "PSY", "Slasher", 3, 9, 5, 0, 35, 136167, 22, 10, 74, 190, 127, 216, 0.7 ], - [ "Nefertari Vivi", "PSY", "Slasher", 4, 13, 5, 1, 70, 1066998, 138, 102, 183, 682, 454, 350, 1 ], - [ "Princess Vivi", "PSY", [ "Slasher", "Freedom" ], 5, 20, 6, 3, 99, 4000000, 602, 414, 280, 908, 747, 477, 1.5 ], - [ "Portgas D. Ace", "QCK", [ "Fighter", "Freedom" ], 4, 13, 6, 3, 70, 1066998, 252, 144, 40, 1802, 545, 199, 1.5 ], - [ "Portgas D. Ace Flame Mirror", "QCK", [ "Fighter", "Freedom" ], 5, 20, 6, 4, 99, 4000000, 1728, 501, 140, 2886, 1020, 279, 1.5 ], - [ "Shanks", "PSY", [ "Slasher", "Knowledge" ], 4, 13, 5, 3, 70, 1066998, 186, 159, 46, 1010, 725, 271, 1.5 ], - [ "Red-Haired Shanks", "PSY", [ "Slasher", "Knowledge" ], 5, 20, 4, 4, 99, 4000000, 898, 670, 222, 2118, 990, 417, 1 ], - [ "Red Robber Penguin", "STR", "Evolver", 1, 1, 5, 0, 1, 0, 20, 10, 20, 20, 10, 20, 1 ], - [ "Blue Robber Penguin", "QCK", "Evolver", 1, 1, 5, 0, 1, 0, 20, 10, 20, 20, 10, 20, 1 ], - [ "Green Robber Penguin", "DEX", "Evolver", 1, 1, 5, 0, 1, 0, 20, 10, 20, 20, 10, 20, 1 ], - [ "Yellow Robber Penguin", "PSY", "Evolver", 1, 1, 5, 0, 1, 0, 20, 10, 20, 20, 10, 20, 1 ], - [ "Black Robber Penguin", "INT", "Evolver", 1, 1, 5, 0, 1, 0, 20, 10, 20, 20, 10, 20, 1 ], - [ "Rainbow Robber Penguin", "INT", "Evolver", 3, 1, 5, 0, 1, 0, 20, 20, 50, 20, 20, 50, 1 ], - [ "Red Pirate Penguin", "STR", "Evolver", 2, 3, 6, 0, 1, 0, 30, 20, 180, 30, 20, 180, 1 ], - [ "Blue Pirate Penguin", "QCK", "Evolver", 2, 3, 6, 0, 1, 0, 30, 20, 180, 30, 20, 180, 1 ], - [ "Green Pirate Penguin", "DEX", "Evolver", 2, 3, 6, 0, 1, 0, 30, 20, 180, 30, 20, 180, 1 ], - [ "Yellow Pirate Penguin", "PSY", "Evolver", 2, 3, 6, 0, 1, 0, 30, 20, 180, 30, 20, 180, 1 ], - [ "Black Pirate Penguin", "INT", "Evolver", 2, 3, 6, 0, 1, 0, 30, 20, 180, 30, 20, 180, 1 ], - [ "Red Hermit Crab", "STR", "Evolver", 1, 1, 5, 0, 1, 0, 50, 180, 0, 50, 180, 0, 1 ], - [ "Blue Hermit Crab", "QCK", "Evolver", 1, 1, 5, 0, 1, 0, 50, 180, 0, 50, 180, 0, 1 ], - [ "Green Hermit Crab", "DEX", "Evolver", 1, 1, 5, 0, 1, 0, 50, 180, 0, 50, 180, 0, 1 ], - [ "Yellow Hermit Crab", "PSY", "Evolver", 1, 1, 5, 0, 1, 0, 50, 180, 0, 50, 180, 0, 1 ], - [ "Black Hermit Crab", "INT", "Evolver", 1, 1, 5, 0, 1, 0, 50, 180, 0, 50, 180, 0, 1 ], - [ "Rainbow Hermit Crab", "INT", "Evolver", 2, 3, 5, 0, 1, 0, 50, 280, 0, 50, 150, 0, 1 ], - [ "Red Armored Crab", "STR", "Evolver", 2, 2, 5, 0, 1, 0, 50, 300, 0, 50, 300, 0, 1 ], - [ "Blue Armored Crab", "QCK", "Evolver", 2, 2, 5, 0, 1, 0, 50, 300, 0, 50, 300, 0, 1 ], - [ "Green Armored Crab", "DEX", "Evolver", 2, 2, 5, 0, 1, 0, 50, 300, 0, 50, 300, 0, 1 ], - [ "Yellow Armored Crab", "PSY", "Evolver", 2, 2, 5, 0, 1, 0, 50, 300, 0, 50, 300, 0, 1 ], - [ "Black Armored Crab", "INT", "Evolver", 2, 2, 5, 0, 1, 0, 50, 300, 0, 50, 300, 0, 1 ], - [ "Red Striped Dragon", "STR", "Evolver", 3, 12, 4, 0, 1, 0, 500, 500, 50, 500, 500, 50, 1 ], - [ "Blue Striped Dragon", "QCK", "Evolver", 3, 12, 4, 0, 1, 0, 500, 500, 50, 500, 500, 50, 1 ], - [ "Green Striped Dragon", "DEX", "Evolver", 3, 12, 4, 0, 1, 0, 500, 500, 50, 500, 500, 50, 1 ], - [ "Yellow Striped Dragon", "PSY", "Evolver", 3, 12, 4, 0, 1, 0, 500, 500, 50, 500, 500, 50, 1 ], - [ "Black Striped Dragon", "INT", "Evolver", 3, 12, 4, 0, 1, 0, 500, 500, 50, 500, 500, 50, 1 ], - [ "Red Treasure Turtle", "STR", "Booster", 3, 1, 6, 0, 1, 0, 100, 10, 10, 100, 10, 10, 1 ], - [ "Blue Treasure Turtle", "QCK", "Booster", 3, 1, 6, 0, 1, 0, 100, 10, 10, 100, 10, 10, 1 ], - [ "Green Treasure Turtle", "DEX", "Booster", 3, 1, 6, 0, 1, 0, 100, 10, 10, 100, 10, 10, 1 ], - [ "Yellow Treasure Turtle", "PSY", "Booster", 3, 1, 6, 0, 1, 0, 100, 10, 10, 100, 10, 10, 1 ], - [ "Black Treasure Turtle", "INT", "Booster", 3, 1, 6, 0, 1, 0, 100, 10, 10, 100, 10, 10, 1 ], - [ "Red Daimyo Turtle", "STR", "Booster", 4, 2, 5, 0, 1, 0, 500, 20, 20, 500, 20, 20, 1 ], - [ "Blue Daimyo Turtle", "QCK", "Booster", 4, 2, 5, 0, 1, 0, 500, 20, 20, 500, 20, 20, 1 ], - [ "Green Daimyo Turtle", "DEX", "Booster", 4, 2, 5, 0, 1, 0, 500, 20, 20, 500, 20, 20, 1 ], - [ "Yellow Daimyo Turtle", "PSY", "Booster", 4, 2, 5, 0, 1, 0, 500, 20, 20, 500, 20, 20, 1 ], - [ "Black Daimyo Turtle", "INT", "Booster", 4, 2, 5, 0, 1, 0, 500, 20, 20, 500, 20, 20, 1 ], - [ "Sea Pony", "PSY", "Evolver", 1, 2, 5, 0, 1, 0, 20, 20, 20, 20, 20, 10, 1 ], - [ "Sea Colt", "PSY", "Evolver", 2, 4, 5, 0, 1, 0, 50, 50, 50, 50, 50, 20, 1 ], - [ "Sea Horse", "PSY", "Evolver", 3, 6, 4, 0, 1, 0, 100, 100, 100, 100, 100, 40, 1 ], - [ "Sea Stallion", "PSY", "Evolver", 4, 8, 4, 0, 1, 0, 150, 150, 150, 150, 150, 60, 1 ], - [ "Sword Bandit", "DEX", "Slasher", 1, 1, 5, 0, 20, 8728, 77, 41, 9, 348, 140, 41, 1 ], - [ "Pistol Bandit", "STR", "Shooter", 1, 1, 5, 0, 20, 8728, 17, 14, 28, 105, 57, 104, 1 ], - [ "Fighter Group Cabin Boy Red Pirates", "STR", "Fighter", 1, 2, 6, 0, 10, 2330, 79, 54, 6, 327, 141, 17, 1 ], - [ "Fighter Group Cabin Boy Blue Pirates", "QCK", "Fighter", 1, 2, 6, 0, 10, 2330, 85, 51, 6, 349, 133, 16, 1 ], - [ "Fighter Group Cabin Boy Green Pirates", "DEX", "Fighter", 1, 2, 6, 0, 10, 2330, 85, 54, 5, 357, 138, 13, 1 ], - [ "Fighter Group Cabin Boy Yellow Pirates", "PSY", "Fighter", 1, 2, 6, 0, 10, 2330, 77, 49, 8, 315, 126, 24, 1 ], - [ "Fighter Group Cabin Boy Black Pirates", "INT", "Fighter", 1, 2, 6, 0, 10, 2330, 83, 61, 3, 345, 153, 10, 1 ], - [ "Slasher Group Cabin Boy Red Pirates", "STR", "Slasher", 1, 3, 6, 0, 15, 7532, 69, 47, 10, 333, 134, 28, 1 ], - [ "Slasher Group Cabin Boy Blue Pirates", "QCK", "Slasher", 1, 3, 6, 0, 15, 7532, 75, 41, 11, 347, 118, 31, 1 ], - [ "Slasher Group Cabin Boy Green Pirates", "DEX", "Slasher", 1, 3, 6, 0, 15, 7532, 69, 44, 11, 341, 115, 33, 1 ], - [ "Slasher Group Cabin Boy Yellow Pirates", "PSY", "Slasher", 1, 3, 6, 0, 15, 7532, 63, 38, 14, 325, 114, 35, 1 ], - [ "Slasher Group Cabin Boy Black Pirates", "INT", "Slasher", 1, 3, 6, 0, 15, 7532, 65, 49, 10, 341, 136, 25, 1 ], - [ "Striker Group Cabin Boy Red Pirates", "STR", "Striker", 1, 1, 6, 0, 10, 2330, 77, 49, 12, 281, 114, 27, 0.7 ], - [ "Striker Group Cabin Boy Blue Pirates", "QCK", "Striker", 1, 1, 6, 0, 10, 2330, 79, 45, 13, 281, 105, 30, 0.7 ], - [ "Striker Group Cabin Boy Green Pirates", "DEX", "Striker", 1, 1, 6, 0, 10, 2330, 73, 45, 14, 255, 103, 35, 0.7 ], - [ "Striker Group Cabin Boy Yellow Pirates", "PSY", "Striker", 1, 1, 6, 0, 10, 2330, 67, 42, 16, 253, 101, 36, 0.7 ], - [ "Striker Group Cabin Boy Black Pirates", "INT", "Striker", 1, 1, 6, 0, 10, 2330, 73, 57, 10, 261, 127, 26, 0.7 ], - [ "Shooter Group Cabin Boy Red Pirates", "STR", "Shooter", 1, 3, 6, 0, 10, 2330, 41, 19, 24, 129, 57, 78, 0.7 ], - [ "Shooter Group Cabin Boy Blue Pirates", "QCK", "Shooter", 1, 3, 6, 0, 10, 2330, 39, 17, 25, 125, 53, 80, 0.7 ], - [ "Shooter Group Cabin Boy Green Pirates", "DEX", "Shooter", 1, 3, 6, 0, 10, 2330, 37, 15, 26, 123, 51, 81, 0.7 ], - [ "Shooter Group Cabin Boy Yellow Pirates", "PSY", "Shooter", 1, 3, 6, 0, 10, 2330, 35, 13, 27, 107, 47, 85, 0.7 ], - [ "Shooter Group Cabin Boy Black Pirates", "INT", "Shooter", 1, 3, 6, 0, 10, 2330, 41, 22, 23, 139, 64, 74, 0.7 ], - [ "Cannoneer Cabin Boy", "INT", "Shooter", 1, 4, 5, 0, 20, 17456, 98, 80, 1, 523, 280, 3, 1 ], - [ "Fighter Group Crew Red Pirates", "STR", "Fighter", 2, 6, 5, 0, 30, 57558, 200, 103, 10, 707, 428, 29, 1 ], - [ "Fighter Group Crew Blue Pirates", "QCK", "Fighter", 2, 6, 5, 0, 30, 57558, 220, 93, 10, 727, 412, 31, 1 ], - [ "Fighter Group Crew Green Pirates", "DEX", "Fighter", 2, 6, 5, 0, 30, 57558, 212, 100, 9, 717, 417, 31, 1 ], - [ "Fighter Group Crew Yellow Pirates", "PSY", "Fighter", 2, 6, 5, 0, 30, 57558, 190, 90, 16, 695, 398, 41, 1 ], - [ "Fighter Group Crew Black Pirates", "INT", "Fighter", 2, 6, 5, 0, 30, 57558, 202, 108, 8, 695, 440, 27, 1 ], - [ "Slasher Group Crew Red Pirates", "STR", "Slasher", 2, 7, 5, 0, 35, 90778, 178, 90, 19, 645, 406, 79, 1 ], - [ "Slasher Group Crew Blue Pirates", "QCK", "Slasher", 2, 7, 5, 0, 35, 90778, 184, 75, 23, 659, 372, 88, 1 ], - [ "Slasher Group Crew Green Pirates", "DEX", "Slasher", 2, 7, 5, 0, 35, 90778, 162, 83, 24, 665, 375, 86, 1 ], - [ "Slasher Group Crew Yellow Pirates", "PSY", "Slasher", 2, 7, 5, 0, 35, 90778, 152, 73, 29, 629, 369, 94, 1 ], - [ "Slasher Group Crew Black Pirates", "INT", "Slasher", 2, 7, 5, 0, 35, 90778, 176, 100, 16, 695, 384, 78, 1 ], - [ "Striker Group Crew Red Pirates", "STR", "Striker", 2, 5, 5, 0, 25, 33626, 174, 85, 21, 473, 320, 71, 0.7 ], - [ "Striker Group Crew Blue Pirates", "QCK", "Striker", 2, 5, 5, 0, 25, 33626, 190, 74, 22, 483, 309, 73, 0.7 ], - [ "Striker Group Crew Green Pirates", "DEX", "Striker", 2, 5, 5, 0, 25, 33626, 176, 75, 24, 429, 318, 79, 0.7 ], - [ "Striker Group Crew Yellow Pirates", "PSY", "Striker", 2, 5, 5, 0, 25, 33626, 182, 69, 25, 439, 289, 87, 0.7 ], - [ "Striker Group Crew Black Pirates", "INT", "Striker", 2, 5, 5, 0, 25, 33626, 188, 87, 18, 465, 342, 65, 0.7 ], - [ "Shooter Group Crew Red Pirates", "STR", "Shooter", 2, 7, 5, 0, 30, 57558, 75, 23, 60, 289, 118, 202, 1 ], - [ "Shooter Group Crew Blue Pirates", "QCK", "Shooter", 2, 7, 5, 0, 30, 57558, 75, 20, 61, 299, 110, 203, 1 ], - [ "Shooter Group Crew Green Pirates", "DEX", "Shooter", 2, 7, 5, 0, 30, 57558, 65, 19, 63, 281, 113, 205, 1 ], - [ "Shooter Group Crew Yellow Pirates", "PSY", "Shooter", 2, 7, 5, 0, 30, 57558, 55, 15, 66, 227, 98, 219, 1 ], - [ "Shooter Group Crew Black Pirates", "INT", "Shooter", 2, 7, 5, 0, 30, 57558, 75, 29, 58, 299, 155, 198, 1 ], - [ "Cannoneer Skilled", "INT", "Shooter", 2, 12, 5, 0, 50, 261406, 203, 105, 3, 1350, 550, 30, 1 ], - [ "Bodyguard, ‘Sunglasses'", "DEX", "Shooter", 1, 4, 5, 0, 20, 8728, 115, 50, 30, 370, 180, 90, 0.7 ], - [ "Bearded Bodyguard", "QCK", "Shooter", 1, 4, 5, 0, 20, 8728, 105, 70, 25, 370, 210, 80, 0.7 ], - [ "Knuckle Punk Black Cat Pirates", "STR", "Fighter", 2, 6, 6, 0, 25, 33626, 30, 129, 2, 267, 612, 3, 1 ], - [ "Saber Punk Black Cat Pirates", "DEX", "Slasher", 2, 6, 5, 0, 25, 33626, 42, 120, 3, 295, 592, 5, 1 ], - [ "Halberd Punk Black Cat Pirates", "QCK", "Striker", 2, 6, 5, 0, 25, 33626, 32, 122, 4, 277, 598, 6, 1 ], - [ "Pistol Punk Black Cat Pirates", "PSY", "Shooter", 2, 6, 5, 0, 25, 33626, 30, 117, 6, 269, 569, 17, 1 ], - [ "Cannoneer Punk Black Cat Pirates", "INT", "Shooter", 2, 6, 5, 0, 25, 33626, 26, 137, 0, 267, 621, 0, 1 ], - [ "Fighter Group Leader", "STR", "Fighter", 3, 7, 6, 1, 40, 202218, 208, 97, 23, 982, 457, 104, 1 ], - [ "Slasher Group Leader", "DEX", "Slasher", 3, 7, 5, 1, 45, 286773, 166, 82, 35, 922, 397, 184, 1 ], - [ "Striker Group Leader", "QCK", "Striker", 3, 7, 5, 1, 35, 136167, 200, 80, 30, 828, 291, 135, 1 ], - [ "Shooter Group Leader", "PSY", "Shooter", 3, 7, 5, 1, 40, 202218, 128, 41, 55, 508, 253, 251, 1 ], - [ "Assassin Master", "INT", "Shooter", 3, 7, 5, 1, 50, 392109, 224, 119, 13, 1532, 557, 79, 1 ], - [ "Karate Fishman Arlong crewmember", "STR", "Fighter", 2, 7, 6, 0, 30, 57558, 70, 49, 24, 547, 258, 116, 0.7 ], - [ "Sword Fishman Arlong crewmember", "DEX", "Slasher", 2, 7, 5, 0, 30, 57558, 92, 44, 22, 585, 245, 114, 0.7 ], - [ "Spear Fishman Arlong crewmember", "QCK", "Striker", 2, 7, 5, 0, 30, 57558, 82, 46, 23, 553, 246, 119, 0.7 ], - [ "Pistol Fishman Arlong crewmember", "PSY", "Shooter", 2, 7, 5, 0, 30, 57558, 72, 36, 28, 523, 216, 134, 0.7 ], - [ "Knuckle Apprentice Navy", "STR", "Fighter", 1, 3, 6, 0, 15, 7532, 105, 66, 6, 317, 203, 17, 1 ], - [ "Saber Apprentice Navy", "DEX", "Slasher", 1, 4, 6, 0, 20, 17456, 45, 75, 13, 293, 194, 44, 1 ], - [ "Halberd Apprentice Navy", "QCK", "Striker", 1, 3, 6, 0, 15, 7532, 73, 70, 10, 305, 158, 34, 1 ], - [ "Pistol Apprentice Navy", "PSY", "Shooter", 1, 3, 6, 0, 15, 7532, 49, 16, 32, 105, 72, 96, 1 ], - [ "Cannoneer Apprentice Navy", "INT", "Shooter", 1, 5, 5, 0, 25, 33626, 93, 90, 0, 400, 350, 1, 1 ], - [ "Knuckle Seaman Navy", "STR", "Fighter", 2, 5, 5, 0, 25, 33626, 139, 96, 17, 523, 289, 43, 1 ], - [ "Saber Seaman Navy", "DEX", "Slasher", 2, 6, 5, 0, 35, 90778, 75, 101, 26, 512, 322, 84, 1 ], - [ "Halberd Seaman Navy", "QCK", "Striker", 2, 5, 5, 0, 25, 33626, 105, 92, 24, 407, 290, 62, 1 ], - [ "Pistol Seaman Navy", "PSY", "Shooter", 2, 6, 5, 0, 25, 33626, 75, 23, 52, 139, 100, 170, 1 ], - [ "Cannoneer Seaman Navy", "INT", "Shooter", 2, 10, 5, 0, 40, 134812, 143, 140, 1, 620, 660, 2, 1.5 ], - [ "Red Elder Turtle", "STR", "Booster", 5, 4, 4, 0, 1, 0, 1000, 30, 30, 1000, 30, 30, 1 ], - [ "Blue Elder Turtle", "QCK", "Booster", 5, 4, 4, 0, 1, 0, 1000, 30, 30, 1000, 30, 30, 1 ], - [ "Green Elder Turtle", "DEX", "Booster", 5, 4, 4, 0, 1, 0, 1000, 30, 30, 1000, 30, 30, 1 ], - [ "Yellow Elder Turtle", "PSY", "Booster", 5, 4, 4, 0, 1, 0, 1000, 30, 30, 1000, 30, 30, 1 ], - [ "Black Elder Turtle", "INT", "Booster", 5, 4, 4, 0, 1, 0, 1000, 30, 30, 1000, 30, 30, 1 ], - [ "Knuckle Ensign Navy HQ", "STR", "Fighter", 3, 9, 6, 1, 50, 392109, 474, 237, 30, 898, 490, 107, 1 ], - [ "Saber Ensign Navy HQ", "DEX", "Slasher", 3, 9, 6, 1, 50, 392109, 424, 229, 51, 800, 467, 131, 1 ], - [ "Halberd Ensign Navy HQ", "QCK", "Striker", 3, 9, 6, 1, 50, 392109, 400, 220, 48, 916, 442, 120, 1 ], - [ "Pistol Ensign Navy HQ", "PSY", "Shooter", 3, 9, 6, 1, 50, 392109, 121, 70, 145, 275, 191, 320, 1 ], - [ "Bazooka Ensign Navy HQ", "INT", "Shooter", 3, 12, 5, 1, 70, 1066998, 480, 460, 1, 1300, 850, 3, 1 ], - [ "Mr. 5 Nez-Palm Cannon", "STR", "Fighter", 3, 11, 5, 1, 35, 136167, 82, 142, 31, 752, 602, 124, 1 ], - [ "Mr. 5 Breeze Breath Bomb", "STR", "Shooter", 4, 15, 5, 2, 70, 1066998, 688, 520, 92, 1120, 943, 180, 1 ], - [ "Miss Valentine", "QCK", "Fighter", 3, 11, 5, 1, 35, 136167, 120, 114, 34, 860, 488, 144, 1 ], - [ "Miss Valentine 10,000 Kilo Guillotine", "QCK", "Fighter", 4, 15, 5, 2, 70, 1066998, 804, 426, 104, 1324, 787, 198, 1 ], - [ "Mr. 3", "INT", [ "Slasher", "Knowledge" ], 3, 11, 4, 1, 35, 136167, 196, 100, 26, 926, 515, 120, 1 ], - [ "Mr. 3 Extra Special Candelabra", "INT", [ "Slasher", "Knowledge" ], 4, 15, 4, 2, 70, 1066998, 600, 449, 120, 1394, 818, 176, 1 ], - [ "Miss Goldenweek", "DEX", [ "Striker", "Freedom" ], 3, 11, 5, 1, 35, 136167, 51, 51, 81, 301, 301, 305, 1 ], - [ "Miss Goldenweek Colors Trap: Calming Green", "DEX", [ "Striker", "Freedom" ], 4, 15, 5, 2, 70, 1066998, 264, 264, 268, 412, 390, 530, 1 ], - [ "Mr. 2 Bon Clay", "PSY", [ "Fighter", "Freedom" ], 3, 11, 5, 1, 35, 136167, 94, 93, 46, 690, 403, 201, 1 ], - [ "Mr. 2 Bon Clay Bombardier Arabesque", "PSY", [ "Fighter", "Freedom" ], 4, 15, 4, 2, 70, 1066998, 599, 348, 169, 935, 709, 302, 1 ], - [ "Miss All Sunday Baroque Works VP", "INT", [ "Fighter", "Knowledge" ], 4, 15, 6, 1, 50, 392109, 368, 128, 96, 772, 478, 252, 0.7 ], - [ "Nico Robin", "INT", [ "Fighter", "Knowledge" ], 5, 20, 6, 2, 99, 3000000, 736, 430, 214, 1865, 1055, 338, 1 ], - [ "Mr. 9", "QCK", "Striker", 2, 10, 5, 0, 35, 90778, 106, 88, 33, 490, 313, 136, 0.7 ], - [ "Mr. 9 Hot Blooded Bat", "QCK", "Striker", 3, 13, 5, 3, 70, 1066998, 408, 249, 99, 1011, 590, 240, 0.7 ], - [ "Laboon", "STR", [ "Fighter", "Tough" ], 3, 18, 5, 1, 50, 392109, 650, 300, 150, 1100, 500, 200, 1 ], - [ "Laboon (Luffy's drawing)", "STR", [ "Fighter", "Tough" ], 4, 22, 5, 2, 99, 3000000, 1000, 400, 160, 2500, 850, 250, 1 ], - [ "Neptunian Squid", "DEX", "Striker", 3, 18, 8, 1, 50, 392109, 600, 280, 130, 900, 480, 180, 1.5 ], - [ "Monkey D. Luffy Gum-Gum Balloon", "STR", [ "Fighter", "Freedom" ], 4, 15, 6, 2, 50, 392109, 490, 178, 29, 1492, 655, 63, 1 ], - [ "Monkey D. Luffy Gear Third", "STR", [ "Fighter", "Freedom" ], 5, 22, 4, 2, 99, 4000000, 1374, 585, 50, 2960, 1303, 105, 1 ], - [ "Roronoa Zoro Streaming Wolf Swords", "DEX", [ "Slasher", "Ambition" ], 4, 15, 5, 2, 50, 392109, 598, 136, 5, 1902, 582, 19, 1 ], - [ "Roronoa Zoro Lion's Song", "DEX", [ "Slasher", "Ambition" ], 5, 22, 6, 3, 99, 4000000, 1882, 538, 10, 3558, 1038, 32, 1 ], - [ "Nami Fine Tempo", "INT", [ "Striker", "Knowledge" ], 4, 15, 5, 2, 50, 392109, 454, 133, 50, 1062, 421, 102, 1 ], - [ "Nami Happiness Punch", "INT", [ "Striker", "Knowledge" ], 5, 22, 4, 3, 99, 4000000, 1044, 377, 94, 1990, 949, 168, 1 ], - [ "Usopp Usopp Hammer", "PSY", "Striker", 3, 12, 5, 1, 35, 136167, 188, 101, 40, 778, 388, 191, 1 ], - [ "Usopp Impact", "PSY", "Shooter", 4, 18, 6, 2, 70, 1066998, 733, 361, 97, 1185, 669, 265, 1 ], - [ "Mr. Prince Mutton Shot", "QCK", [ "Fighter", "Knowledge" ], 3, 12, 4, 1, 35, 136167, 276, 108, 32, 1144, 457, 107, 1 ], - [ "Mr. Prince Veau Shot", "QCK", [ "Fighter", "Knowledge" ], 4, 18, 5, 2, 70, 1066998, 1101, 422, 93, 1600, 792, 161, 1 ], - [ "Dracule Mihawk", "DEX", "Slasher", 4, 30, 4, 1, 70, 1066998, 324, 201, 1, 1998, 814, 7, 1 ], - [ "Hawk Eyes Mihawk", "DEX", "Slasher", 5, 50, 4, 1, 99, 5000000, 1916, 782, 5, 3760, 1285, 15, 1 ], - [ "Escapee Morgan", "STR", [ "Slasher", "Ambition" ], 3, 17, 5, 1, 70, 711332, 1427, 699, 27, 1600, 1000, 35, 1 ], - [ "Double Crosser Django", "PSY", [ "Slasher", "Freedom" ], 3, 11, 5, 1, 70, 1066998, 446, 219, 103, 930, 665, 230, 1 ], - [ "Double Ironfist Fullbody", "STR", [ "Fighter", "Freedom" ], 3, 11, 6, 1, 70, 1066998, 150, 150, 80, 890, 809, 187, 1 ], - [ "Hina", "QCK", [ "Fighter", "Knowledge" ], 3, 12, 5, 1, 50, 392109, 154, 73, 42, 1176, 495, 187, 1 ], - [ "Black Cage Hina", "QCK", [ "Fighter", "Knowledge" ], 4, 18, 4, 2, 99, 3000000, 1088, 422, 149, 2270, 905, 300, 1 ], - [ "Mr. 8", "PSY", [ "Shooter", "Knowledge" ], 2, 10, 5, 0, 35, 90778, 178, 55, 32, 530, 248, 151, 1 ], - [ "Mr. 8 Igarappapa", "PSY", [ "Shooter", "Knowledge" ], 3, 13, 5, 1, 70, 1066998, 500, 186, 120, 1286, 433, 230, 1 ], - [ "Miss Monday", "STR", [ "Fighter", "Tough" ], 2, 10, 4, 0, 35, 90778, 66, 126, 27, 350, 500, 97, 1 ], - [ "Miss Monday Superhuman Brass Knuckles", "STR", [ "Fighter", "Tough" ], 3, 13, 4, 1, 70, 1066998, 270, 422, 71, 506, 1005, 186, 1 ], - [ "Knuckle Millions Baroque Works", "STR", "Fighter", 2, 5, 6, 0, 25, 33626, 185, 89, 21, 532, 352, 50, 1 ], - [ "Saber Millions Baroque Works", "DEX", "Slasher", 2, 5, 6, 0, 25, 33626, 161, 77, 29, 486, 294, 77, 1 ], - [ "Polearm Millions Baroque Works", "QCK", "Striker", 2, 5, 6, 0, 25, 33626, 197, 74, 24, 620, 278, 60, 1 ], - [ "Pistol Millions Baroque Works", "PSY", "Shooter", 2, 5, 6, 0, 25, 33626, 159, 51, 40, 476, 224, 102, 1 ], - [ "Bazooka Millions Baroque Works", "INT", "Shooter", 2, 5, 4, 0, 25, 33626, 203, 113, 10, 640, 388, 20, 1 ], - [ "Knuckle Billions Baroque Works", "STR", "Fighter", 3, 9, 5, 1, 50, 261406, 466, 301, 32, 850, 580, 85, 1 ], - [ "Saber Billions Baroque Works", "DEX", "Slasher", 3, 9, 5, 1, 50, 261406, 410, 257, 56, 798, 508, 120, 1 ], - [ "Halberd Billions Baroque Works", "QCK", "Striker", 3, 9, 5, 1, 50, 261406, 560, 230, 40, 996, 477, 95, 1 ], - [ "Pistol Billions Baroque Works", "PSY", "Shooter", 3, 9, 5, 1, 50, 261406, 402, 187, 82, 698, 400, 172, 1 ], - [ "Bazooka Billions Baroque Works", "INT", "Shooter", 3, 9, 4, 1, 50, 261406, 550, 319, 12, 1020, 655, 32, 1 ], - [ "Chopper Man", "PSY", "Fighter", 4, 10, 6, 5, 50, 130703, 250, 250, 125, 500, 500, 250, 1 ], - [ "Tony Tony Chopper Pre-Rampage", "STR", "Fighter", 4, 30, 6, 1, 70, 1066998, 280, 180, 300, 1808, 851, 0, 1 ], - [ "Tony Tony Chopper Post-Rampage", "STR", [ "Fighter", "Tough" ], 5, 50, 4, 2, 99, 5000000, 1808, 851, -350, 3660, 1500, -900, 1 ], - [ "Marco", "PSY", [ "Fighter", "Tough" ], 4, 18, 6, 3, 50, 392109, 172, 125, 64, 1030, 676, 220, 1 ], - [ "Marco the Phoenix", "PSY", [ "Fighter", "Tough" ], 5, 28, 4, 4, 99, 4000000, 951, 618, 180, 2258, 1100, 390, 1 ], - [ "Jozu", "QCK", [ "Fighter", "Tough" ], 4, 18, 4, 3, 50, 392109, 412, 109, 27, 1820, 596, 98, 1 ], - [ "Diamond Jozu", "QCK", [ "Fighter", "Tough" ], 5, 28, 4, 4, 99, 4000000, 1748, 524, 69, 3300, 987, 231, 1 ], - [ "Vista", "INT", [ "Slasher", "Tough" ], 4, 18, 5, 3, 50, 392109, 290, 206, 15, 1388, 806, 100, 1 ], - [ "Flower Sword Vista", "INT", [ "Slasher", "Tough" ], 5, 28, 5, 4, 99, 4000000, 1314, 732, 72, 2840, 1325, 185, 1 ], - [ "Izo", "DEX", [ "Shooter", "Knowledge" ], 4, 18, 4, 3, 50, 392109, 232, 130, 50, 1300, 634, 172, 1 ], - [ "Flintlock Pistols Izo", "DEX", [ "Shooter", "Knowledge" ], 5, 28, 5, 4, 99, 4000000, 1224, 585, 136, 2550, 1068, 319, 1 ], - [ "Blamenco", "STR", [ "Striker", "Freedom" ], 4, 18, 4, 3, 50, 392109, 204, 192, 34, 1150, 775, 150, 1 ], - [ "Blamenco the Mallet", "STR", [ "Striker", "Freedom" ], 5, 28, 4, 4, 99, 4000000, 1086, 726, 112, 2488, 1252, 268, 1 ], - [ "Edward Newgate", "STR", [ "Striker", "Tough" ], 5, 40, 4, 4, 70, 1422664, 1338, 522, 80, 3220, 1060, 156, 1 ], - [ "Whitebeard", "STR", [ "Striker", "Tough" ], 6, 55, 4, 5, 99, 5000000, 3148, 978, 110, 3900, 1360, 235, 1 ], - [ "Training Coby", "PSY", [ "Striker", "Ambition" ], 3, 12, 5, 1, 50, 261406, 90, 81, 55, 780, 514, 218, 0.7 ], - [ "Petty Officer Coby", "PSY", [ "Fighter", "Ambition" ], 4, 18, 6, 2, 99, 3000000, 701, 485, 191, 1926, 984, 340, 1 ], - [ "Training Helmeppo", "INT", [ "Striker", "Ambition" ], 3, 12, 5, 1, 50, 261406, 108, 93, 43, 890, 605, 185, 0.7 ], - [ "Sergeant Helmeppo", "INT", [ "Slasher", "Ambition" ], 4, 18, 5, 2, 99, 3000000, 807, 555, 150, 1998, 1060, 260, 1 ], - [ "Rainbow Pirate Penguin", "INT", "Evolver", 4, 6, 6, 0, 1, 0, 200, 100, 300, 200, 100, 300, 1 ], - [ "Rainbow Striped Dragon", "INT", "Evolver", 4, 20, 4, 0, 1, 0, 1500, 800, 100, 1500, 800, 100, 1 ], - [ "White Chase Smoker", "DEX", [ "Striker", "Ambition" ], 5, 20, 5, 3, 99, 2000000, 1644, 1012, 298, 2215, 1282, 338, 1.5 ], - [ "Armed Fighter Unit Red Pirates", "STR", "Fighter", 3, 12, 5, 1, 60, 449516, 644, 388, 19, 1055, 781, 33, 0.7 ], - [ "Armed Fighter Unit Blue Pirates", "QCK", "Fighter", 3, 12, 5, 1, 60, 449516, 679, 369, 21, 1106, 750, 36, 0.7 ], - [ "Armed Fighter Unit Green Pirates", "DEX", "Fighter", 3, 12, 5, 1, 60, 449516, 663, 380, 22, 1082, 770, 34, 0.7 ], - [ "Armed Fighter Unit Yellow Pirates", "PSY", "Fighter", 3, 12, 5, 1, 60, 449516, 622, 358, 35, 1030, 725, 58, 0.7 ], - [ "Armed Fighter Unit Black Pirates", "INT", "Fighter", 3, 12, 5, 1, 60, 449516, 633, 405, 18, 1044, 800, 30, 0.7 ], - [ "Armed Slasher Unit Red Pirates", "STR", "Slasher", 3, 12, 5, 1, 60, 449516, 583, 380, 69, 990, 658, 99, 0.7 ], - [ "Armed Slasher Unit Blue Pirates", "QCK", "Slasher", 3, 12, 5, 1, 60, 449516, 618, 339, 74, 1068, 592, 119, 0.7 ], - [ "Armed Slasher Unit Green Pirates", "DEX", "Slasher", 3, 12, 5, 1, 60, 449516, 602, 358, 80, 1017, 616, 122, 0.7 ], - [ "Armed Slasher Unit Yellow Pirates", "PSY", "Slasher", 3, 12, 5, 1, 60, 449516, 566, 333, 84, 944, 572, 149, 0.7 ], - [ "Armed Slasher Unit Black Pirates", "INT", "Slasher", 3, 12, 5, 1, 60, 449516, 590, 381, 59, 983, 660, 109, 0.7 ], - [ "Armed Striker Unit Red Pirates", "STR", "Striker", 3, 12, 5, 1, 60, 449516, 473, 320, 71, 946, 640, 142, 0.7 ], - [ "Armed Striker Unit Blue Pirates", "QCK", "Striker", 3, 12, 5, 1, 60, 449516, 483, 309, 73, 976, 618, 146, 0.7 ], - [ "Armed Striker Unit Green Pirates", "DEX", "Striker", 3, 12, 5, 1, 60, 449516, 429, 318, 79, 858, 636, 158, 0.7 ], - [ "Armed Striker Unit Yellow Pirates", "PSY", "Striker", 3, 12, 5, 1, 60, 449516, 439, 289, 87, 878, 578, 176, 0.7 ], - [ "Armed Striker Unit Black Pirates", "INT", "Striker", 3, 12, 5, 1, 60, 449516, 465, 342, 65, 930, 684, 130, 0.7 ], - [ "Armed Shooter Unit Red Pirates", "STR", "Shooter", 3, 12, 5, 1, 60, 449516, 271, 102, 180, 481, 355, 301, 0.7 ], - [ "Armed Shooter Unit Blue Pirates", "QCK", "Shooter", 3, 12, 5, 1, 60, 449516, 280, 96, 181, 530, 302, 312, 0.7 ], - [ "Armed Shooter Unit Green Pirates", "DEX", "Shooter", 3, 12, 5, 1, 60, 449516, 273, 99, 182, 502, 312, 314, 0.7 ], - [ "Armed Shooter Unit Yellow Pirates", "PSY", "Shooter", 3, 12, 5, 1, 60, 449516, 201, 88, 205, 427, 284, 348, 0.7 ], - [ "Armed Shooter Unit Black Pirates", "INT", "Shooter", 3, 12, 5, 1, 60, 449516, 280, 137, 174, 500, 400, 297, 0.7 ], - [ "Skilled Gunner", "INT", "Shooter", 3, 15, 5, 2, 70, 711332, 1280, 500, 20, 1550, 850, 40, 0.7 ], - [ "Mr. 13 & Ms. Friday The Unluckies", "INT", "Shooter", 3, 13, 7, 3, 50, 392109, 44, 44, 44, 596, 893, 130, 0.7 ], - [ "Dorry", "PSY", [ "Slasher", "Tough" ], 4, 25, 4, 2, 70, 1422664, 450, 370, 102, 1662, 783, 153, 1.5 ], - [ "Broggy", "INT", [ "Slasher", "Tough" ], 4, 25, 4, 2, 70, 1422664, 440, 411, 88, 1634, 875, 117, 1.5 ], - [ "Triceratops", "QCK", "Fighter", 2, 25, 4, 0, 50, 392109, 500, 200, 50, 965, 700, 50, 1.5 ], - [ "Rex", "STR", "Fighter", 2, 25, 4, 0, 50, 392109, 300, 300, 50, 520, 900, 50, 1.5 ], - [ "Brontosaurus", "DEX", "Fighter", 2, 25, 4, 0, 50, 392109, 400, 250, 50, 755, 755, 50, 1.5 ], - [ "Tsuru", "INT", [ "Shooter", "Knowledge" ], 3, 12, 4, 2, 50, 392109, 140, 26, 60, 880, 400, 266, 1 ], - [ "Great Advisor Tsuru", "INT", [ "Shooter", "Knowledge" ], 4, 18, 6, 3, 99, 4000000, 808, 337, 224, 1151, 1210, 366, 1 ], - [ "Momonga", "PSY", [ "Slasher", "Knowledge" ], 3, 11, 5, 2, 70, 1066998, 420, 398, 98, 632, 815, 255, 1 ], - [ "Onigumo", "DEX", [ "Slasher", "Ambition" ], 3, 11, 8, 2, 70, 1066998, 482, 434, 63, 944, 920, 131, 1 ], - [ "Red Plated Lobster", "STR", "Evolver", 3, 7, 4, 0, 1, 0, 50, 550, 0, 50, 550, 0, 1 ], - [ "Blue Plated Lobster", "QCK", "Evolver", 3, 7, 4, 0, 1, 0, 50, 550, 0, 50, 550, 0, 1 ], - [ "Green Plated Lobster", "DEX", "Evolver", 3, 7, 4, 0, 1, 0, 50, 550, 0, 50, 550, 0, 1 ], - [ "Yellow Plated Lobster", "PSY", "Evolver", 3, 7, 4, 0, 1, 0, 50, 550, 0, 50, 550, 0, 1 ], - [ "Black Plated Lobster", "INT", "Evolver", 3, 7, 4, 0, 1, 0, 50, 550, 0, 50, 550, 0, 1 ], - [ "Monkey D. Garp", "PSY", [ "Fighter", "Tough" ], 4, 30, 4, 1, 70, 1066998, 280, 145, 50, 1442, 722, 131, 1 ], - [ "Garp the Fist", "PSY", [ "Fighter", "Tough" ], 5, 50, 4, 2, 99, 5000000, 1377, 685, 105, 2852, 1220, 225, 1 ], - [ "Trafalgar Law", "DEX", [ "Slasher", "Freedom" ], 4, 18, 4, 3, 70, 1066998, 104, 125, 73, 876, 702, 238, 1 ], - [ "Trafalgar Law ROOM", "DEX", [ "Slasher", "Freedom" ], 5, 28, 4, 4, 99, 4000000, 817, 655, 190, 2052, 1300, 370, 1 ], - [ "Basil Hawkins", "INT", [ "Slasher", "Knowledge" ], 4, 18, 4, 3, 70, 1066998, 200, 200, 7, 1165, 750, 127, 1 ], - [ "Basil Hawkins the Magician", "INT", [ "Striker", "Knowledge" ], 5, 28, 6, 4, 99, 4000000, 1095, 717, 85, 2480, 1295, 255, 1 ], - [ "Killer", "QCK", [ "Striker", "Knowledge" ], 4, 18, 6, 3, 70, 1066998, 180, 250, 0, 1228, 895, -50, 1 ], - [ "Massacre Soldier Killer", "QCK", [ "Striker", "Knowledge" ], 5, 28, 4, 4, 99, 4000000, 1120, 811, 0, 2570, 1449, -200, 1 ], - [ "Urouge", "PSY", [ "Striker", "Tough" ], 4, 18, 4, 3, 70, 1066998, 108, 108, 35, 1290, 798, 108, 1 ], - [ "Mad Monk Urouge", "PSY", [ "Striker", "Tough" ], 5, 28, 5, 4, 99, 4000000, 1202, 730, 75, 2071, 1343, 200, 1 ], - [ "Bepo", "STR", [ "Fighter", "Tough" ], 4, 18, 4, 3, 70, 1066998, 120, 105, 80, 820, 690, 246, 1 ], - [ "Bepo the Martial Artist", "STR", [ "Fighter", "Tough" ], 5, 28, 6, 4, 99, 4000000, 755, 640, 198, 1880, 1200, 405, 1 ], - [ "Kalifa", "DEX", [ "Fighter", "Knowledge" ], 3, 12, 5, 1, 50, 392109, 116, 65, 51, 850, 540, 227, 1 ], - [ "Beautiful Secretary Kalifa", "DEX", [ "Fighter", "Knowledge" ], 4, 18, 6, 2, 99, 3000000, 788, 488, 177, 1728, 963, 378, 1 ], - [ "Paulie", "DEX", "Striker", 3, 12, 5, 1, 50, 392109, 162, 102, 31, 882, 705, 166, 1 ], - [ "Paulie Dock One Foreman/Mast Specialist", "DEX", "Striker", 4, 18, 4, 2, 99, 3000000, 812, 617, 130, 2300, 1070, 231, 1 ], - [ "Rob Lucci", "QCK", [ "Slasher", "Tough" ], 3, 12, 4, 1, 50, 392109, 132, 126, 28, 1192, 721, 106, 1 ], - [ "Rob Lucci Dock One Sawyer, Treenail Specialist", "QCK", [ "Slasher", "Tough" ], 4, 18, 6, 2, 99, 3000000, 1107, 654, 69, 2220, 1203, 177, 1 ], - [ "Kaku", "QCK", "Striker", 3, 12, 5, 1, 50, 392109, 172, 79, 37, 1233, 635, 131, 0.7 ], - [ "Kaku Dock One Carpentry Specialist", "QCK", [ "Striker", "Freedom" ], 4, 18, 4, 2, 99, 3000000, 1132, 552, 98, 2517, 988, 213, 0.7 ], - [ "Lulu", "QCK", "Shooter", 3, 12, 6, 2, 70, 1066998, 290, 168, 88, 985, 682, 223, 1 ], - [ "Wapol", "STR", [ "Fighter", "Freedom" ], 3, 8, 4, 1, 50, 392109, 330, 128, 20, 1440, 488, 98, 1 ], - [ "Wapol House", "STR", [ "Shooter", "Freedom" ], 4, 15, 4, 2, 99, 3000000, 1390, 423, 77, 2940, 835, 142, [ 1, 1, 0.7 ] ], - [ "Dalton", "QCK", [ "Slasher", "Knowledge" ], 3, 7, 5, 1, 35, 90778, 192, 110, 45, 751, 390, 140, 0.7 ], - [ "Dalton Bison", "QCK", [ "Slasher", "Knowledge" ], 4, 11, 4, 2, 70, 1066998, 690, 322, 102, 1155, 620, 290, 0.7 ], - [ "Chess", "DEX", "Shooter", 3, 7, 6, 0, 35, 90778, 186, 90, 31, 668, 296, 121, 1 ], - [ "Kuromarimo", "DEX", "Striker", 3, 7, 5, 0, 35, 90778, 72, 144, 24, 366, 488, 108, 1 ], - [ "Chessmarimo", "DEX", "Striker", 4, 11, 7, 2, 70, 1066998, 525, 396, 145, 1290, 840, 185, 1 ], - [ "Dr. Kureha", "PSY", [ "Slasher", "Knowledge" ], 3, 20, 5, 2, 50, 392109, 35, 32, 88, 200, 200, 510, 1.5 ], - [ "Lapin", "INT", "Fighter", 2, 15, 5, 0, 35, 90778, 200, 200, 25, 550, 550, 53, 1.5 ], - [ "Lapin Adult", "INT", [ "Fighter", "Tough" ], 3, 20, 4, 2, 70, 1066998, 380, 480, 38, 1100, 950, 100, 1.5 ], - [ "Franky", "PSY", [ "Shooter", "Freedom" ], 3, 12, 4, 1, 50, 392109, 128, 128, 28, 1220, 680, 112, 1 ], - [ "Dismantler Franky", "PSY", [ "Shooter", "Freedom" ], 4, 20, 5, 2, 99, 3000000, 1138, 637, 71, 2453, 1032, 198, 1 ], - [ "Kiwi", "PSY", "Slasher", 3, 13, 4, 1, 50, 392109, 77, 77, 77, 777, 444, 265, 1 ], - [ "Mozu", "PSY", "Slasher", 3, 13, 4, 1, 50, 392109, 77, 77, 77, 555, 555, 265, 1 ], - [ "Kraken Surume", "STR", [ "Striker", "Tough" ], 3, 12, 6, 1, 50, 392109, 99, 99, 188, 1440, 685, 133, 1 ], - [ "Kraken Monster of the North", "STR", [ "Striker", "Tough" ], 4, 20, 8, 2, 99, 3000000, 1355, 602, 118, 2700, 1111, 33, 1 ], - [ "Red Jeweled Porc", "STR", "Booster", 2, 2, 4, 0, 10, 2330, 45, 27, 7, 129, 77, 15, 1 ], - [ "Blue Jeweled Porc", "QCK", "Booster", 2, 2, 4, 0, 10, 2330, 49, 21, 9, 145, 65, 19, 1 ], - [ "Green Jeweled Porc", "DEX", "Booster", 2, 2, 4, 0, 10, 2330, 47, 25, 8, 133, 72, 17, 1 ], - [ "Yellow Jeweled Porc", "PSY", "Booster", 2, 2, 4, 0, 10, 2330, 44, 19, 12, 120, 58, 28, 1 ], - [ "Black Jeweled Porc", "INT", "Booster", 2, 2, 4, 0, 10, 2330, 42, 30, 7, 119, 88, 14, 1 ], - [ "Ruby Jeweled Porc", "STR", "Booster", 3, 5, 4, 0, 1, 0, 169, 97, 22, 169, 97, 22, 1 ], - [ "Sapphire Jeweled Porc", "QCK", "Booster", 3, 5, 4, 0, 1, 0, 185, 85, 26, 185, 85, 26, 1 ], - [ "Emerald Jeweled Porc", "DEX", "Booster", 3, 5, 4, 0, 1, 0, 173, 92, 24, 173, 92, 24, 1 ], - [ "Topaz Jeweled Porc", "PSY", "Booster", 3, 5, 4, 0, 1, 0, 160, 78, 35, 160, 78, 35, 1 ], - [ "Amethyst Jeweled Porc", "INT", "Booster", 3, 5, 4, 0, 1, 0, 159, 108, 21, 159, 108, 21, 1 ], - [ "Zephyr", "INT", [ "Shooter", "Tough" ], 4, 30, 7, 1, 70, 1066998, 320, 133, 4, 1588, 699, 29, 1 ], - [ "Zephyr NEO Navy Commander", "INT", [ "Shooter", "Tough" ], 5, 50, 4, 2, 99, 5000000, 1550, 680, 11, 3702, 1252, 88, 1 ], - [ "Ain", "QCK", [ "Shooter", "Knowledge" ], 3, 8, 6, 1, 35, 136167, 96, 87, 47, 688, 421, 195, 1 ], - [ "Ain NEO Navy Vice Admiral", "QCK", [ "Shooter", "Knowledge" ], 4, 13, 4, 2, 70, 1066998, 620, 377, 155, 908, 679, 285, 1 ], - [ "Eustass Kid", "STR", [ "Striker", "Ambition" ], 4, 18, 4, 3, 70, 1066998, 233, 141, 12, 1221, 721, 32, 1 ], - [ "Captain Kid", "STR", [ "Striker", "Ambition" ], 5, 28, 4, 4, 99, 4000000, 1138, 651, 21, 3515, 1298, 69, 1 ], - [ "Scratchmen Apoo", "DEX", [ "Shooter", "Freedom" ], 4, 18, 5, 3, 70, 1066998, 209, 122, 39, 1126, 652, 184, 1 ], - [ "Roar of the Sea Scratchmen Apoo", "DEX", [ "Shooter", "Freedom" ], 5, 28, 5, 4, 99, 4000000, 1085, 580, 144, 2801, 1111, 300, 1 ], - [ "X Drake", "INT", [ "Striker", "Tough" ], 4, 18, 5, 3, 70, 1066998, 242, 112, 32, 1515, 688, 88, 1 ], - [ "Red Flag X Drake", "INT", [ "Fighter", "Tough" ], 5, 28, 6, 4, 99, 4000000, 1432, 611, 57, 3580, 1098, 132, 1 ], - [ "Jewelry Bonney", "PSY", [ "Fighter", "Freedom" ], 4, 18, 4, 3, 70, 1066998, 277, 80, 44, 1370, 440, 220, 1 ], - [ "Big Eater Jewelry Bonney", "PSY", [ "Fighter", "Freedom" ], 5, 28, 5, 4, 99, 4000000, 1248, 401, 158, 3000, 720, 400, 1 ], - [ "Capone Bege", "QCK", [ "Shooter", "Freedom" ], 4, 18, 6, 3, 70, 1066998, 199, 102, 34, 1050, 755, 153, 1 ], - [ "Capone Gang Bege", "QCK", [ "Shooter", "Freedom" ], 5, 28, 4, 4, 99, 4000000, 893, 682, 110, 2122, 1323, 313, 1 ], - [ "Silvers Rayleigh", "INT", [ "Fighter", "Knowledge" ], 5, 30, 4, 3, 70, 1066998, 488, 302, 168, 1518, 826, 309, 1 ], - [ "Dark King Rayleigh", "INT", [ "Fighter", "Knowledge" ], 6, 55, 4, 4, 99, 5000000, 1462, 777, 277, 3001, 1300, 500, 1 ], - [ "Giant Slasher Red Pirates", "STR", "Slasher", 2, 8, 6, 0, 30, 57558, 297, 163, 41, 579, 363, 41, 1.5 ], - [ "Giant Shooter Blue Pirates", "QCK", "Shooter", 2, 8, 4, 0, 30, 57558, 350, 129, 53, 619, 303, 68, 1.5 ], - [ "Giant Warrior Green Pirates", "DEX", "Striker", 2, 8, 4, 0, 30, 57558, 313, 155, 55, 561, 340, 77, 1.5 ], - [ "Giant Fighter Yellow Pirates", "PSY", "Fighter", 2, 8, 5, 0, 30, 57558, 308, 151, 52, 575, 332, 67, 1.5 ], - [ "Giant Striker Black Pirates", "INT", "Striker", 2, 8, 6, 0, 30, 57558, 330, 133, 42, 614, 313, 54, 1.5 ], - [ "Giant Imperial Slasher Red Pirates", "STR", "Slasher", 3, 13, 4, 1, 60, 674274, 490, 334, 46, 1179, 668, 109, 1.5 ], - [ "Giant Imperial Shooter Blue Pirates", "QCK", "Shooter", 3, 13, 4, 1, 60, 674274, 528, 281, 64, 1235, 562, 135, 1.5 ], - [ "Female Giant Imperial Warrior Green Pirates", "DEX", "Striker", 3, 13, 4, 1, 60, 674274, 472, 310, 72, 1132, 620, 143, 1.5 ], - [ "Giant Imperial Fighter Yellow Pirates", "PSY", "Fighter", 3, 13, 4, 1, 60, 674274, 488, 302, 61, 1170, 604, 132, 1.5 ], - [ "Giant Imperial Striker Black Pirates", "INT", "Striker", 3, 13, 4, 1, 60, 674274, 525, 311, 49, 1213, 622, 119, 1.5 ], - [ "Sea Cat", "PSY", "Fighter", 3, 10, 4, 1, 50, 392109, 77, 7, 33, 777, 77, 333, 1 ], - [ "Kung Fu Dugong", "STR", "Fighter", 3, 7, 5, 1, 20, 26184, 25, 225, 45, 50, 355, 95, 0.7 ], - [ "Kung Fu Dugong Faithful Apprentice", "STR", "Fighter", 4, 11, 8, 3, 50, 392109, 25, 305, 55, 75, 825, 225, 0.7 ], - [ "Banana Gator", "QCK", "Fighter", 3, 10, 4, 0, 50, 392109, 552, 334, 80, 922, 534, 155, 1 ], - [ "Sandora Dragon", "DEX", "Fighter", 3, 10, 4, 0, 50, 392109, 511, 285, 120, 811, 485, 190, 1 ], - [ "Mr. 0 Baroque Works CEO", "INT", [ "Striker", "Knowledge" ], 3, 10, 5, 2, 50, 392109, 194, 110, 23, 1088, 659, 147, 1.5 ], - [ "Sir Crocodile", "INT", [ "Striker", "Knowledge" ], 4, 18, 4, 3, 99, 3000000, 995, 582, 112, 2210, 1220, 208, 1.5 ], - [ "Hogback", "INT", [ "Fighter", "Knowledge" ], 3, 12, 6, 1, 50, 392109, 210, 72, 33, 1251, 595, 118, 1 ], - [ "Doctor Hogback", "INT", [ "Fighter", "Knowledge" ], 4, 20, 4, 2, 99, 3000000, 1180, 550, 72, 2741, 945, 189, 1 ], - [ "Cindry", "PSY", "Shooter", 3, 12, 5, 1, 50, 392109, 76, 58, 60, 806, 458, 259, 0.7 ], - [ "Victoria Cindry", "PSY", "Shooter", 4, 20, 4, 2, 99, 3000000, 622, 398, 231, 1402, 661, 478, 0.7 ], - [ "Emporio Ivankov", "QCK", [ "Fighter", "Freedom" ], 4, 30, 4, 3, 70, 1066998, 302, 125, 53, 1682, 512, 161, 1 ], - [ "Emporio Ivankov Queen of Kamabakka Queendom", "QCK", [ "Fighter", "Freedom" ], 5, 50, 4, 4, 99, 5000000, 1642, 470, 132, 3030, 1155, 290, 1 ], - [ "Perona", "DEX", [ "Shooter", "Ambition" ], 3, 10, 4, 1, 50, 392109, 134, 44, 55, 944, 422, 222, 1 ], - [ "Ghost Princess Perona", "DEX", [ "Shooter", "Ambition" ], 4, 18, 4, 2, 99, 3000000, 887, 377, 198, 1598, 791, 430, 1 ], - [ "Kumacy", "STR", [ "Fighter", "Tough" ], 3, 11, 6, 1, 70, 1066998, 500, 255, 0, 1660, 904, 0, 1 ], - [ "Dog Penguin", "QCK", "Fighter", 3, 11, 4, 1, 50, 392109, 986, 500, 54, 1420, 722, 0, 1 ], - [ "Miss Merry Christmas", "QCK", "Fighter", 3, 11, 5, 1, 35, 136167, 220, 51, 42, 980, 422, 147, 1 ], - [ "Miss Merry Christmas Human Mole", "QCK", "Fighter", 4, 15, 4, 2, 70, 1066998, 910, 348, 113, 1401, 690, 233, 1 ], - [ "Mr. 4", "STR", [ "Shooter", "Tough" ], 3, 11, 4, 1, 35, 136167, 250, 110, 14, 1046, 590, 80, 1 ], - [ "Mr. 4 and Lassoo the Dog-Gun", "STR", [ "Shooter", "Tough" ], 4, 15, 6, 2, 70, 1066998, 980, 522, 43, 1606, 910, 110, 1 ], - [ "Miss Doublefinger", "DEX", [ "Striker", "Knowledge" ], 3, 11, 8, 1, 35, 136167, 115, 87, 44, 770, 501, 158, 1 ], - [ "Miss Doublefinger Human Spike", "DEX", [ "Striker", "Knowledge" ], 4, 15, 4, 2, 70, 1066998, 720, 435, 120, 1081, 701, 288, 1 ], - [ "Mr. 1", "STR", [ "Slasher", "Knowledge" ], 3, 11, 4, 1, 35, 136167, 255, 156, 1, 1152, 744, 10, 1 ], - [ "Mr. 1 Human Sword", "STR", [ "Slasher", "Knowledge" ], 4, 15, 5, 2, 70, 1066998, 1021, 652, 2, 1880, 1042, 15, 1 ], - [ "Rebecca", "QCK", "Slasher", 4, 14, 5, 2, 70, 1422664, 242, 115, 108, 1525, 707, 345, 1 ], - [ "Absalom", "STR", [ "Shooter", "Tough" ], 3, 12, 6, 1, 50, 392109, 158, 93, 35, 1330, 602, 126, 1 ], - [ "Absalom of the Graveyard", "STR", [ "Shooter", "Tough" ], 4, 20, 7, 2, 99, 3000000, 1271, 545, 77, 2601, 1008, 192, 1 ], - [ "General Zombie", "INT", "Fighter", 3, 12, 5, 1, 70, 1066998, 920, 352, 0, 2610, 605, 0, 1 ], - [ "Jigoro of the Wind", "DEX", "Slasher", 3, 9, 6, 1, 50, 392109, 426, 258, 37, 1348, 744, 0, 1 ], - [ "Sir Crocodile Warlord of the Sea", "INT", [ "Slasher", "Knowledge" ], 5, 30, 4, 4, 99, 4000000, 1088, 659, 147, 2980, 1380, 150, 1 ], - [ "Jimbe", "QCK", [ "Fighter", "Tough" ], 4, 15, 4, 3, 70, 1066998, 266, 101, 35, 1590, 660, 118, 1 ], - [ "Jimbe Warlord of the Sea", "QCK", [ "Fighter", "Tough" ], 5, 30, 4, 4, 99, 4000000, 1522, 622, 70, 3055, 1092, 250, 1 ], - [ "Bartholomew Kuma", "STR", [ "Shooter", "Tough" ], 4, 15, 4, 3, 70, 1066998, 290, 110, 33, 1525, 692, 118, 1 ], - [ "Bartholomew Kuma Warlord of the Sea", "STR", [ "Shooter", "Tough" ], 5, 30, 4, 4, 99, 4000000, 1445, 644, 82, 2734, 1205, 262, 1 ], - [ "Gecko Moria", "INT", [ "Striker", "Ambition" ], 4, 15, 4, 3, 70, 1066998, 355, 102, 15, 1928, 677, 33, 1 ], - [ "Gecko Moria Warlord of the Sea", "INT", [ "Striker", "Ambition" ], 5, 30, 4, 4, 99, 4000000, 1845, 612, 33, 3900, 1120, 118, 1 ], - [ "Boa Hancock", "QCK", [ "Fighter", "Freedom" ], 5, 30, 4, 4, 70, 1066998, 416, 251, 197, 1595, 859, 340, 1 ], - [ "Boa Hancock Warlord of the Sea", "QCK", [ "Fighter", "Freedom" ], 6, 55, 4, 5, 99, 5000000, 1512, 782, 301, 2860, 1320, 515, 1 ], - [ "Donquixote Doflamingo", "DEX", [ "Slasher", "Ambition" ], 4, 30, 4, 1, 70, 1066998, 200, 186, 30, 1061, 790, 145, 1 ], - [ "Donquixote Doflamingo Warlord of the Sea", "DEX", [ "Slasher", "Ambition" ], 5, 50, 5, 2, 99, 4000000, 932, 721, 118, 2311, 1500, 255, 1 ], - [ "Sanji Parage Shot: The Storm", "QCK", [ "Fighter", "Tough" ], 4, 10, 5, 2, 99, 2000000, 486, 207, 32, 2015, 900, 217, 0.7 ], - [ "Monkey D. Luffy Gum-Gum Bazooka: Supremacy", "STR", [ "Fighter", "Freedom" ], 4, 15, 6, 2, 99, 2000000, 404, 227, 39, 1748, 1250, 192, 1 ], - [ "Roronoa Zoro Three Thousand Worlds: The Final Stroke", "DEX", [ "Slasher", "Ambition" ], 4, 15, 6, 2, 99, 2000000, 426, 222, 37, 2175, 1188, 132, 1 ], - [ "Nami Mirage Tempo: The Heavens", "INT", [ "Striker", "Knowledge" ], 4, 15, 5, 2, 99, 2000000, 348, 201, 75, 1260, 988, 361, 1 ], - [ "Brook", "QCK", [ "Slasher", "Freedom" ], 3, 12, 5, 1, 50, 392109, 220, 43, 45, 1190, 430, 208, 1 ], - [ "Humming Swordsman Brook", "QCK", [ "Slasher", "Freedom" ], 4, 20, 4, 2, 99, 3000000, 1138, 368, 162, 2108, 980, 332, 1 ], - [ "Ryuma", "PSY", "Slasher", 4, 18, 5, 2, 99, 3000000, 1138, 368, 162, 2005, 1088, 162, 1 ], - [ "Masira", "STR", "Fighter", 3, 10, 4, 1, 50, 392109, 525, 212, 12, 1120, 655, 95, 1 ], - [ "Shoujou", "DEX", "Shooter", 3, 10, 4, 1, 50, 392109, 655, 132, 23, 1334, 401, 144, 1 ], - [ "Montblanc Cricket", "PSY", [ "Shooter", "Freedom" ], 3, 12, 4, 1, 50, 392109, 488, 145, 54, 1050, 525, 155, 1.5 ], - [ "South Bird and Forest Residents", "DEX", "Fighter", 3, 8, 6, 1, 50, 261406, 752, 383, 121, 929, 423, 161, 1.5 ], - [ "Bellamy", "DEX", [ "Fighter", "Ambition" ], 3, 10, 4, 1, 35, 136167, 131, 152, 24, 769, 692, 89, 1 ], - [ "Bellamy the Hyena", "DEX", [ "Fighter", "Ambition" ], 4, 15, 6, 2, 70, 1066998, 726, 600, 67, 1072, 986, 170, 1 ], - [ "Sarquiss", "QCK", "Slasher", 3, 10, 5, 1, 50, 392109, 220, 92, 22, 1440, 424, 68, 1 ], - [ "Elizabeth", "DEX", [ "Fighter", "Freedom" ], 4, 12, 4, 2, 70, 1422664, 881, 422, 155, 1485, 700, 198, 1.5 ], - [ "Caroline", "INT", [ "Fighter", "Freedom" ], 4, 18, 6, 2, 99, 3000000, 772, 389, 177, 1890, 915, 300, [ 1.5, 1.5, 0.7 ] ], - [ "Sanji Kamabakka Queendom Traditional Fighting Style", "QCK", "Fighter", 3, 10, 4, 2, 50, 392109, 221, 58, 29, 1229, 622, 130, [ 0.7, 0.7, 1.5 ] ], - [ "Sanji Candy", "QCK", [ "Fighter", "Freedom" ], 4, 18, 4, 3, 99, 3000000, 1155, 545, 76, 1802, 951, 357, [ 0.7, 0.7, 1.5 ] ], - [ "Perona - Sweets", "DEX", [ "Shooter", "Ambition" ], 4, 11, 4, 2, 50, 392109, 168, 98, 58, 928, 412, 231, 1.5 ], - [ "Ghost Princess Perona - Sweets", "DEX", [ "Shooter", "Ambition" ], 5, 20, 4, 3, 99, 3000000, 856, 359, 186, 1568, 741, 466, 1.5 ], - [ "Nefertari Vivi - Love", "PSY", [ "Slasher", "Freedom" ], 4, 11, 5, 2, 50, 392109, 138, 102, 183, 889, 358, 256, 1.5 ], - [ "Princess Vivi - Love", "PSY", [ "Slasher", "Freedom" ], 5, 20, 6, 3, 99, 3000000, 844, 297, 213, 1440, 683, 322, 1.5 ], - [ "Cowboy and Bourbon Jr. Supersonic Duck Squadron", "QCK", "Evolver", 3, 9, 5, 0, 35, 90778, 150, 80, 35, 755, 334, 155, 1 ], - [ "Stomp and Ivan X Supersonic Duck Squadron", "DEX", "Evolver", 3, 9, 5, 0, 35, 90778, 126, 98, 33, 719, 361, 152, 1 ], - [ "Centaur and Hikoichi Supersonic Duck Squadron", "STR", "Evolver", 3, 9, 5, 0, 35, 90778, 102, 119, 30, 693, 383, 149, 1 ], - [ "Karoo", "PSY", "Striker", 3, 6, 4, 1, 20, 26184, 178, 86, 40, 229, 155, 100, 1 ], - [ "Captain Karoo and the Supersonic Duck Squadron", "PSY", "Striker", 4, 18, 7, 2, 99, 3000000, 378, 383, 138, 1412, 702, 461, 1.5 ], - [ "Marshall D. Teach", "STR", [ "Shooter", "Ambition" ], 4, 30, 6, 1, 70, 1066998, 235, 166, 30, 1402, 790, 23, 1 ], - [ "Blackbeard", "STR", [ "Shooter", "Ambition" ], 5, 50, 4, 2, 99, 5000000, 1338, 744, 18, 3140, 1418, 83, 1 ], - [ "Thatch", "QCK", [ "Slasher", "Knowledge" ], 4, 18, 5, 3, 50, 522812, 208, 103, 63, 1246, 626, 188, 1 ], - [ "Twin-Blade Thatch", "QCK", [ "Slasher", "Knowledge" ], 5, 28, 4, 4, 99, 4000000, 1184, 575, 146, 2505, 1190, 302, 1 ], - [ "Namule", "DEX", [ "Fighter", "Tough" ], 4, 18, 4, 3, 50, 522812, 155, 133, 40, 1081, 822, 142, 1 ], - [ "One-Hit Namule", "DEX", [ "Fighter", "Tough" ], 5, 28, 4, 4, 99, 4000000, 999, 755, 117, 2398, 1303, 262, 1 ], - [ "Rakuyo", "PSY", [ "Striker", "Ambition" ], 4, 18, 4, 3, 50, 522812, 161, 122, 65, 1000, 733, 193, 1 ], - [ "Morning Star Rakuyo", "PSY", [ "Striker", "Ambition" ], 5, 28, 4, 4, 99, 4000000, 945, 681, 122, 2001, 1320, 337, 1 ], - [ "Fossa", "STR", [ "Slasher", "Ambition" ], 4, 18, 4, 3, 50, 522812, 150, 160, 34, 1120, 831, 132, 1 ], - [ "Fossa the Blazing Katana", "STR", [ "Slasher", "Ambition" ], 5, 28, 4, 4, 99, 4000000, 1059, 788, 95, 2454, 1388, 228, 1 ], - [ "Curiel", "INT", [ "Shooter", "Ambition" ], 4, 18, 6, 3, 50, 522812, 202, 153, 48, 1159, 818, 134, 1 ], - [ "Heavy Specialist Curiel", "INT", [ "Shooter", "Ambition" ], 5, 28, 5, 4, 99, 4000000, 1092, 762, 99, 2470, 1359, 252, 1 ], - [ "Sengoku", "PSY", [ "Fighter", "Knowledge" ], 5, 30, 4, 4, 70, 1066998, 610, 278, 157, 2020, 758, 228, 1 ], - [ "Sengoku the Buddha", "PSY", [ "Fighter", "Knowledge" ], 6, 54, 4, 5, 99, 5000000, 1962, 711, 191, 3429, 1338, 389, 1 ], - [ "Criminal Galdino Mr. 3", "PSY", [ "Slasher", "Knowledge" ], 3, 12, 4, 2, 70, 1066998, 588, 333, 133, 1033, 687, 233, 1 ], - [ "Fugitive Bentham Mr. 2 Bon Clay", "DEX", [ "Fighter", "Freedom" ], 3, 12, 5, 1, 50, 392109, 178, 104, 32, 980, 529, 187, 1 ], - [ "Prison Break Expert Mr. 2 Bon Clay", "DEX", [ "Fighter", "Freedom" ], 4, 20, 4, 2, 99, 3000000, 921, 460, 146, 1830, 978, 323, 1 ], - [ "Satori", "PSY", [ "Shooter", "Knowledge" ], 4, 15, 4, 2, 70, 1066998, 479, 190, 158, 1422, 576, 272, 1 ], - [ "Shura", "INT", "Striker", 4, 15, 4, 2, 70, 1066998, 330, 420, 93, 1030, 1002, 175, 1 ], - [ "Gedatsu", "QCK", "Fighter", 4, 15, 4, 2, 70, 1066998, 622, 378, 53, 2020, 703, 108, 1 ], - [ "Braham", "DEX", [ "Shooter", "Freedom" ], 3, 15, 5, 1, 70, 1066998, 374, 283, 96, 1202, 684, 202, 1 ], - [ "Yama", "STR", "Fighter", 3, 13, 6, 1, 50, 392109, 800, 228, 1, 1700, 608, 2, 1 ], - [ "Yellow White Beret Skypiea Guard", "PSY", "Shooter", 2, 3, 6, 0, 20, 17456, 51, 23, 45, 330, 166, 89, 1 ], - [ "Black White Beret Skypiea Guard", "INT", "Shooter", 2, 3, 6, 0, 20, 17456, 49, 38, 40, 320, 197, 80, 1 ], - [ "Yellow White Beret Captain Skypiea Guard", "PSY", "Shooter", 3, 9, 5, 1, 50, 261406, 270, 128, 69, 845, 433, 198, 1 ], - [ "Black White Beret Captain Skypiea Guard", "INT", "Shooter", 3, 9, 5, 1, 50, 261406, 259, 142, 65, 837, 498, 177, 1 ], - [ "Eneru's Elect: Red Guard Skypiea Enforcer", "STR", "Slasher", 2, 8, 6, 0, 50, 261406, 388, 202, 87, 890, 503, 121, 1 ], - [ "Eneru's Elect: Blue Guard Skypiea Enforcer", "QCK", "Slasher", 2, 8, 6, 0, 50, 261406, 438, 155, 90, 962, 413, 139, 1 ], - [ "Eneru's Elect: Green Guard Skypiea Enforcer", "DEX", "Slasher", 2, 8, 6, 0, 50, 261406, 410, 179, 88, 926, 464, 128, 1 ], - [ "Eneru's Elect: Yellow Guard Skypiea Enforcer", "PSY", "Slasher", 2, 8, 6, 0, 50, 261406, 377, 140, 110, 859, 396, 170, 1 ], - [ "Eneru's Elect: Black Guard Skypiea Enforcer", "INT", "Slasher", 2, 8, 6, 0, 50, 261406, 390, 200, 80, 912, 501, 115, 1 ], - [ "Red Striker Skypiea Enforcer", "STR", "Striker", 2, 6, 4, 0, 30, 57558, 12, 55, 25, 311, 445, 70, 1 ], - [ "Blue Striker Skypiea Enforcer", "QCK", "Striker", 2, 6, 4, 0, 30, 57558, 20, 47, 27, 343, 420, 73, 1 ], - [ "Green Striker Skypiea Enforcer", "DEX", "Striker", 2, 6, 4, 0, 30, 57558, 16, 51, 26, 325, 435, 71, 1 ], - [ "Yellow Striker Skypiea Enforcer", "PSY", "Striker", 2, 6, 4, 0, 30, 57558, 12, 47, 30, 322, 418, 80, 1 ], - [ "Black Striker Skypiea Enforcer", "INT", "Striker", 2, 6, 4, 0, 30, 57558, 16, 54, 24, 329, 442, 68, 1 ], - [ "Red Striker Elite Skypiea Enforcer", "STR", "Striker", 3, 12, 5, 1, 60, 449516, 243, 359, 45, 510, 804, 157, 1 ], - [ "Blue Striker Elite Skypiea Enforcer", "QCK", "Striker", 3, 12, 5, 1, 60, 449516, 278, 340, 48, 562, 772, 159, 1 ], - [ "Green Striker Elite Skypiea Enforcer", "DEX", "Striker", 3, 12, 5, 1, 60, 449516, 265, 350, 46, 536, 788, 158, 1 ], - [ "Yellow Striker Elite Skypiea Enforcer", "PSY", "Striker", 3, 12, 5, 1, 60, 449516, 242, 338, 53, 505, 760, 166, 1 ], - [ "Black Striker Elite Skypiea Enforcer", "INT", "Striker", 3, 12, 5, 1, 60, 449516, 250, 358, 45, 520, 802, 156, 1 ], - [ "Red Nomad Shandian Warrior", "STR", "Striker", 2, 6, 5, 0, 30, 57558, 79, 45, 26, 494, 302, 87, 1 ], - [ "Blue Nomad Shandian Warrior", "QCK", "Striker", 2, 6, 5, 0, 30, 57558, 92, 36, 30, 538, 268, 94, 1 ], - [ "Green Nomad Shandian Warrior", "DEX", "Striker", 2, 6, 5, 0, 30, 57558, 85, 40, 28, 517, 289, 89, 1 ], - [ "Red Nomad Adept Shandian Warrior", "STR", "Striker", 3, 12, 5, 1, 60, 449516, 438, 228, 60, 864, 642, 162, 1 ], - [ "Blue Nomad Adept Shandian Warrior", "QCK", "Striker", 3, 12, 5, 1, 60, 449516, 460, 187, 63, 948, 570, 172, 1 ], - [ "Green Nomad Adept Shandian Warrior", "DEX", "Striker", 3, 12, 5, 1, 60, 449516, 449, 201, 61, 900, 606, 168, 1 ], - [ "Yellow Hunter Shandian Warrior", "PSY", "Shooter", 2, 5, 4, 0, 30, 57558, 38, 20, 41, 210, 115, 201, 1 ], - [ "Black Hunter Shandian Warrior", "INT", "Shooter", 2, 5, 4, 0, 30, 57558, 40, 25, 39, 214, 128, 196, 1 ], - [ "Yellow Hunter Adept Shandian Warrior", "PSY", "Shooter", 3, 11, 4, 1, 60, 449516, 150, 60, 160, 502, 258, 365, 1 ], - [ "Black Hunter Adept Shandian Warrior", "INT", "Shooter", 3, 11, 4, 1, 60, 449516, 152, 66, 153, 508, 271, 359, 1 ], - [ "Portgas D. Ace Mt. Corvo's Brothers 3", "QCK", [ "Fighter", "Freedom" ], 4, 10, 4, 2, 35, 90778, 144, 66, 60, 632, 347, 248, 0.7 ], - [ "Portgas D. Ace Mt. Corvo's Brothers 3, Cup of Sworn Brotherhood", "QCK", [ "Fighter", "Freedom" ], 5, 18, 4, 3, 70, 1066998, 571, 295, 200, 1072, 559, 385, 0.7 ], - [ "Bellmere", "DEX", "Shooter", 3, 9, 5, 1, 35, 136167, 60, 39, 68, 426, 291, 283, 1 ], - [ "Bellmere Nami and Nojiko's Mother", "DEX", "Shooter", 4, 15, 4, 2, 70, 1066998, 377, 249, 240, 810, 483, 400, 1 ], - [ "Kaya", "PSY", [ "Shooter", "Knowledge" ], 3, 9, 6, 1, 35, 136167, 115, 50, 72, 370, 180, 330, 1.5 ], - [ "Kaya A Rich Young Girl from Syrup Village", "PSY", [ "Shooter", "Knowledge" ], 4, 15, 5, 2, 70, 1066998, 331, 151, 275, 405, 250, 550, 1.5 ], - [ "Hotori and Kotori", "INT", "Fighter", 3, 9, 6, 1, 35, 136167, 242, 74, 27, 1055, 455, 122, 1 ], - [ "Hotori and Kotori Skypiea Vice Head Enforcers", "INT", "Fighter", 4, 15, 4, 2, 70, 1066998, 989, 385, 92, 1959, 601, 151, 1 ], - [ "Pell", "QCK", [ "Slasher", "Tough" ], 3, 9, 6, 1, 35, 136167, 175, 70, 40, 1000, 427, 142, 1 ], - [ "Pell The Guardian Falcon of Alabasta", "QCK", [ "Slasher", "Tough" ], 4, 15, 4, 2, 70, 1066998, 941, 358, 104, 1585, 695, 186, 1 ], - [ "Chaka", "STR", [ "Slasher", "Tough" ], 3, 9, 5, 1, 35, 136167, 173, 120, 21, 822, 615, 109, 1 ], - [ "Chaka The Guardian Jackal of Alabasta", "STR", [ "Slasher", "Tough" ], 4, 15, 4, 2, 70, 1066998, 740, 531, 81, 1160, 923, 180, 1 ], - [ "Sir Crocodile, the Strongest Prisoner Mr. 0, Ex-Baroque Works Leader", "QCK", [ "Striker", "Knowledge" ], 3, 13, 5, 1, 50, 392109, 213, 108, 24, 1161, 565, 135, 1 ], - [ "Sir Crocodile, the Strongest Prisoner Ex-Warlord", "QCK", [ "Striker", "Knowledge" ], 4, 20, 4, 2, 99, 3000000, 1101, 500, 100, 2200, 1150, 188, 1 ], - [ "Daz Bones, Convict Mr. 1", "INT", [ "Slasher", "Knowledge" ], 4, 16, 4, 2, 70, 1066998, 255, 156, 242, 1710, 1011, 55, 1 ], - [ "Sabo Mt. Corvo's Brothers 3", "PSY", [ "Striker", "Freedom" ], 4, 10, 5, 2, 35, 90778, 32, 32, 32, 522, 288, 286, 0.7 ], - [ "Sabo Mt. Corvo's Brothers 3, Cup of Sworn Brotherhood", "PSY", [ "Striker", "Freedom" ], 5, 18, 4, 3, 70, 1066998, 440, 233, 242, 951, 460, 450, 0.7 ], - [ "Nico Robin Tropical", "INT", [ "Fighter", "Knowledge" ], 4, 15, 6, 2, 99, 2000000, 368, 128, 96, 1910, 715, 292, 1 ], - [ "Heracles'n", "PSY", [ "Shooter", "Knowledge" ], 4, 30, 6, 2, 70, 1066998, 330, 89, 34, 1698, 569, 160, 1 ], - [ "Heracles'n the Hero of the Forest", "PSY", [ "Shooter", "Knowledge" ], 5, 50, 4, 3, 99, 5000000, 1622, 480, 108, 3188, 1010, 300, 1 ], - [ "Usopp'n", "PSY", "Shooter", 4, 10, 5, 1, 50, 261406, 444, 237, 47, 1080, 648, 144, 1 ], - [ "Usopp'n, Pupil of Heracles'n", "PSY", [ "Shooter", "Tough" ], 5, 20, 4, 5, 99, 2000000, 1280, 648, 0, 2550, 700, -41, 1 ], - [ "Monkey D. Luffy, Merveille's Adventurer", "STR", [ "Fighter", "Freedom" ], 4, 17, 4, 3, 70, 1066998, 242, 148, 28, 1505, 744, 106, 1 ], - [ "Monkey D. Luffy, Straw Hat Pirates' Attack", "STR", [ "Fighter", "Freedom" ], 5, 27, 8, 4, 99, 4000000, 1438, 676, 72, 2722, 1411, 176, 1 ], - [ "Sanji, Merveille's Adventurer", "INT", [ "Fighter", "Tough" ], 4, 17, 4, 3, 70, 1066998, 268, 115, 32, 1545, 698, 122, 1 ], - [ "Sanji, Straw Hat Pirates' Attack", "INT", [ "Fighter", "Tough" ], 5, 27, 5, 4, 99, 4000000, 1471, 630, 86, 2834, 1224, 226, 1 ], - [ "Nami, Merveille's Adventurer", "QCK", [ "Striker", "Knowledge" ], 4, 17, 5, 3, 70, 1066998, 190, 81, 57, 1051, 602, 230, 1 ], - [ "Nami and Billy the Thunder Bird", "QCK", [ "Striker", "Knowledge" ], 5, 27, 6, 4, 99, 4000000, 979, 540, 191, 1980, 1000, 455, 1 ], - [ "Brook, Merveille's Adventurer", "PSY", [ "Slasher", "Freedom" ], 4, 17, 6, 3, 70, 1066998, 249, 101, 40, 1530, 684, 133, 1 ], - [ "Brook, Straw Hat Pirates' Attack", "PSY", [ "Slasher", "Freedom" ], 5, 27, 4, 4, 99, 4000000, 1461, 636, 100, 2788, 1243, 234, 1 ], - [ "Chopper, Merveille's Adventurer", "DEX", [ "Shooter", "Knowledge" ], 4, 17, 5, 3, 70, 1066998, 196, 98, 51, 1170, 624, 212, 1 ], - [ "Chopper, Straw Hat Pirates' Attack", "DEX", [ "Shooter", "Knowledge" ], 5, 27, 4, 4, 99, 4000000, 1110, 571, 179, 2212, 1099, 368, 1 ], - [ "Shanks Black Clad Redhead", "PSY", [ "Slasher", "Knowledge" ], 5, 30, 4, 4, 70, 1066998, 478, 285, 185, 1650, 780, 291, 1 ], - [ "Shanks Black Clad Emperor", "PSY", [ "Slasher", "Knowledge" ], 6, 55, 5, 5, 99, 5000000, 1537, 736, 261, 3140, 1400, 418, 1 ], - [ "Nico Robin Cherry Blossoms Falling", "DEX", [ "Fighter", "Knowledge" ], 4, 11, 4, 2, 50, 392109, 171, 55, 65, 976, 328, 252, 1 ], - [ "Nico Robin Cherry Blossoms in Full Bloom", "DEX", [ "Fighter", "Knowledge" ], 5, 19, 6, 3, 99, 3000000, 913, 271, 209, 1925, 747, 384, 1 ], - [ "Brook Cherry Blossom Hair", "QCK", [ "Slasher", "Freedom" ], 4, 12, 5, 2, 50, 392109, 211, 108, 40, 1267, 448, 163, 1 ], - [ "Brook Cherry Blossom Melody", "QCK", [ "Slasher", "Freedom" ], 5, 20, 4, 3, 99, 3000000, 1199, 379, 131, 2311, 885, 281, 1 ], - [ "Nami Blossom Cloud", "DEX", [ "Shooter", "Knowledge" ], 4, 12, 5, 2, 50, 392109, 127, 53, 73, 812, 303, 287, 1 ], - [ "Nami Blossom Climate", "DEX", [ "Shooter", "Knowledge" ], 5, 20, 4, 3, 99, 3000000, 750, 247, 241, 1783, 670, 445, 1 ], - [ "Domino", "PSY", [ "Fighter", "Knowledge" ], 3, 13, 4, 1, 50, 392109, 32, 20, 80, 713, 366, 318, 1 ], - [ "Domino, Impel Down's Head Jailer", "PSY", [ "Fighter", "Knowledge" ], 4, 20, 5, 2, 99, 3000000, 634, 301, 265, 1800, 694, 449, 1 ], - [ "Minorhinoceros", "STR", [ "Striker", "Tough" ], 3, 30, 6, 0, 70, 1066998, 1055, 655, 0, 2122, 815, -250, 1 ], - [ "Basilisk", "DEX", [ "Fighter", "Tough" ], 3, 12, 4, 1, 70, 1066998, 612, 289, 31, 1525, 644, 128, 1 ], - [ "Ohm", "STR", [ "Slasher", "Knowledge" ], 4, 16, 4, 2, 70, 1066998, 770, 480, -600, 2200, 1050, -600, 1 ], - [ "Nola Giant Snake", "PSY", [ "Fighter", "Tough" ], 3, 20, 4, 1, 50, 392109, 1000, 180, 71, 2100, 455, 101, 0.7 ], - [ "Wyper", "DEX", [ "Shooter", "Freedom" ], 3, 9, 4, 2, 35, 136167, 212, 105, 20, 981, 567, 99, 1 ], - [ "Wyper Descendant of Great Warrior Calgara", "DEX", [ "Shooter", "Freedom" ], 4, 15, 4, 3, 70, 1066998, 914, 490, 70, 1598, 804, 155, 1 ], - [ "Eneru", "PSY", [ "Shooter", "Ambition" ], 3, 12, 4, 2, 50, 392109, 177, 141, 58, 951, 615, 185, 1 ], - [ "Kami Eneru", "PSY", [ "Shooter", "Ambition" ], 4, 20, 4, 3, 99, 3000000, 880, 542, 143, 1530, 1290, 318, 1 ], - [ "Monkey D. Luffy Mt. Corvo's Brothers 3", "STR", [ "Fighter", "Freedom" ], 4, 10, 4, 2, 35, 136167, 100, 28, 77, 551, 267, 261, 1 ], - [ "Monkey D. Luffy Mt. Corvo's Brothers 3, Cup of Sworn Brotherhood", "STR", [ "Fighter", "Freedom" ], 5, 18, 4, 3, 70, 1778330, 479, 209, 231, 1058, 541, 397, 1 ], - [ "Sadi-chan", "INT", [ "Striker", "Freedom" ], 3, 12, 4, 1, 50, 392109, 31, 60, 66, 681, 550, 263, 1 ], - [ "Sadi-chan, Impel Down's Chief Guard", "INT", [ "Striker", "Freedom" ], 4, 20, 6, 2, 99, 3000000, 618, 488, 202, 1505, 997, 388, 1 ], - [ "Minokoala", "STR", [ "Fighter", "Tough" ], 3, 30, 5, 0, 70, 1066998, 1400, 602, 0, 1977, 812, -100, 1 ], - [ "Manticore", "QCK", [ "Fighter", "Tough" ], 3, 15, 4, 1, 70, 1066998, 313, 245, 24, 999, 770, 112, 1 ], - [ "Roronoa Zoro, Merveille's Adventurer", "DEX", [ "Slasher", "Ambition" ], 4, 17, 5, 3, 70, 1066998, 270, 124, 23, 1585, 715, 98, 1 ], - [ "Roronoa Zoro, Straw Hat Pirates' Attack", "DEX", [ "Slasher", "Ambition" ], 5, 27, 4, 4, 99, 4000000, 1531, 646, 60, 2900, 1321, 171, 1 ], - [ "Usopp, Merveille's Adventurer", "QCK", "Shooter", 4, 17, 6, 3, 70, 1066998, 224, 90, 47, 1222, 593, 208, 1 ], - [ "Usopp, Straw Hat Pirates' Attack", "QCK", "Shooter", 5, 27, 5, 4, 99, 4000000, 1167, 542, 174, 2301, 954, 376, 1 ], - [ "Nico Robin, Merveille's Adventurer", "INT", [ "Fighter", "Knowledge" ], 4, 17, 4, 3, 70, 1066998, 213, 96, 45, 1147, 626, 216, 1 ], - [ "Nico Robin, Straw Hat Pirates' Attack", "INT", [ "Fighter", "Knowledge" ], 5, 27, 4, 4, 99, 4000000, 1098, 551, 180, 2076, 1099, 400, 1 ], - [ "Franky, Merveille's Adventurer", "STR", [ "Shooter", "Freedom" ], 4, 17, 6, 3, 70, 1066998, 244, 140, 21, 1590, 738, 95, 1 ], - [ "Franky, Straw Hat Pirates' Attack", "STR", [ "Shooter", "Freedom" ], 5, 27, 5, 4, 99, 4000000, 1525, 660, 50, 2801, 1395, 161, 1 ], - [ "Portgas D. Ace Black Clad Flame Fist", "DEX", [ "Shooter", "Freedom" ], 5, 30, 6, 4, 70, 1066998, 515, 264, 152, 1922, 758, 253, 1 ], - [ "Portgas D. Ace Black Clad Whitebeard 2nd Div. Commander", "DEX", [ "Shooter", "Freedom" ], 6, 55, 4, 5, 99, 5000000, 1877, 702, 214, 3818, 1352, 321, 1 ], - [ "Porche", "PSY", "Shooter", 3, 10, 6, 1, 50, 392109, 33, 29, 58, 536, 338, 300, 1 ], - [ "Capote", "QCK", "Striker", 3, 10, 5, 1, 50, 392109, 124, 48, 36, 1188, 482, 139, 1 ], - [ "Hamburg", "DEX", [ "Striker", "Tough" ], 3, 10, 5, 1, 50, 392109, 103, 58, 32, 1024, 620, 122, 1 ], - [ "Pickles", "QCK", [ "Fighter", "Tough" ], 3, 10, 4, 1, 50, 392109, 130, 51, 25, 1202, 603, 98, 1 ], - [ "Big Bun", "STR", [ "Slasher", "Tough" ], 3, 15, 6, 1, 70, 1066998, 180, 105, 2, 1895, 850, 3, 1 ], - [ "Foxy", "INT", [ "Fighter", "Freedom" ], 3, 10, 5, 2, 35, 136167, 106, 51, 30, 788, 433, 175, 1 ], - [ "The Silver Fox Foxy", "INT", [ "Fighter", "Freedom" ], 4, 18, 5, 3, 70, 1066998, 725, 373, 144, 1212, 698, 266, 1 ], - [ "Monkey D. Luffy Davy Back Fight: Afro", "STR", [ "Fighter", "Tough" ], 3, 12, 6, 1, 50, 392109, 465, 232, 36, 984, 585, 110, 1.5 ], - [ "Monkey D. Luffy Davy Back Fight: Combat", "STR", [ "Fighter", "Tough" ], 4, 20, 4, 2, 99, 3000000, 862, 492, 70, 1978, 1170, 220, 1.5 ], - [ "Usopp Davy Back Fight: Cornerman", "DEX", "Shooter", 4, 13, 5, 2, 70, 1066998, 61, 30, 75, 1361, 354, 310, 1 ], - [ "Tony Tony Chopper Davy Back Fight: Mask", "PSY", [ "Fighter", "Knowledge" ], 3, 10, 4, 2, 70, 1066998, 83, 27, 70, 1176, 483, 280, 0.7 ], - [ "Aokiji", "INT", [ "Striker", "Freedom" ], 4, 30, 4, 2, 70, 1066998, 232, 160, 32, 1142, 712, 157, 1 ], - [ "Aokiji the Freezing Man", "INT", [ "Striker", "Freedom" ], 5, 50, 4, 3, 99, 5000000, 1093, 644, 122, 2465, 1435, 251, 1 ], - [ "Tea Time Nami", "INT", [ "Striker", "Knowledge" ], 4, 18, 4, 2, 99, 2000000, 454, 133, 50, 1473, 703, 373, 0.7 ], - [ "Monkey D. Luffy Voyage Log: Straw Hat Pirates", "STR", [ "Fighter", "Freedom" ], 5, 30, 4, 3, 70, 1066998, 390, 290, 150, 1559, 840, 290, 1.5 ], - [ "Monkey D. Luffy Voyage Dream: Pirate King", "STR", [ "Fighter", "Freedom" ], 6, 55, 4, 4, 99, 5000000, 1490, 776, 250, 3440, 1430, 351, 1 ], - [ "Roronoa Zoro Voyage Log: Straw Hat Pirates", "QCK", [ "Slasher", "Ambition" ], 4, 12, 4, 2, 50, 392109, 230, 110, 35, 1388, 651, 132, 1 ], - [ "Roronoa Zoro Voyage Dream: Master Swordsman", "QCK", [ "Slasher", "Ambition" ], 5, 20, 4, 3, 99, 3000000, 1329, 777, 90, 2250, 1118, 201, 1 ], - [ "Genbou", "STR", [ "Shooter", "Freedom" ], 3, 15, 4, 1, 70, 1066998, 271, 91, 15, 1855, 711, 54, 0.7 ], - [ "Kamakiri", "QCK", [ "Striker", "Freedom" ], 3, 15, 5, 1, 70, 1066998, 195, 84, 30, 1669, 691, 101, 0.7 ], - [ "Raki", "INT", "Shooter", 4, 18, 4, 2, 99, 3000000, 158, 55, 51, 1544, 668, 460, 0.7 ], - [ "Aisa", "PSY", "Fighter", 3, 11, 5, 2, 50, 392109, 32, 15, 80, 223, 109, 475, 0.7 ], - [ "Nojiko", "PSY", [ "Striker", "Knowledge" ], 3, 9, 5, 1, 35, 136167, 125, 57, 60, 398, 277, 293, 1 ], - [ "Nojiko Nami's Sister", "PSY", [ "Fighter", "Knowledge" ], 4, 15, 6, 2, 70, 1066998, 330, 233, 253, 709, 382, 438, 1 ], - [ "Crocus", "INT", [ "Striker", "Knowledge" ], 3, 9, 4, 1, 35, 136167, 202, 60, 41, 886, 301, 203, 1 ], - [ "Crocus, Twin Cape's Lighthouse Keeper", "INT", [ "Striker", "Knowledge" ], 4, 15, 5, 2, 70, 1066998, 820, 249, 160, 1224, 509, 320, 1 ], - [ "Koza", "QCK", "Slasher", 3, 9, 5, 1, 35, 136167, 179, 69, 33, 939, 423, 158, 1 ], - [ "Koza Rebel Leader", "QCK", "Slasher", 4, 15, 4, 2, 70, 1066998, 872, 375, 114, 1440, 681, 225, 1 ], - [ "Crimson Hime Turtle", "STR", "Booster", 6, 20, 6, 0, 1, 0, 2000, 100, 50, 2000, 100, 50, 1 ], - [ "Azure Hime Turtle", "QCK", "Booster", 6, 20, 6, 0, 1, 0, 2000, 100, 50, 2000, 100, 50, 1 ], - [ "Jade Hime Turtle", "DEX", "Booster", 6, 20, 6, 0, 1, 0, 2000, 100, 50, 2000, 100, 50, 1 ], - [ "Amber Hime Turtle", "PSY", "Booster", 6, 20, 6, 0, 1, 0, 2000, 100, 50, 2000, 100, 50, 1 ], - [ "Onyx Hime Turtle", "INT", "Booster", 6, 20, 6, 0, 1, 0, 2000, 100, 50, 2000, 100, 50, 1 ], - [ "Tony Tony Chopper Voyage Log: Straw Hat Pirates", "STR", [ "Fighter", "Tough" ], 4, 12, 4, 2, 50, 392109, 220, 95, 46, 1324, 589, 186, 0.7 ], - [ "Tony Tony Chopper Voyage Dream: Great Doctor", "STR", [ "Fighter", "Tough" ], 5, 20, 6, 3, 99, 3000000, 1280, 542, 151, 1980, 1002, 301, 0.7 ], - [ "Buggy the Pirate Apprentice", "INT", [ "Slasher", "Ambition" ], 3, 12, 6, 1, 50, 392109, 155, 74, 42, 872, 411, 162, 1 ], - [ "Buggy, Roger Pirates", "INT", [ "Slasher", "Ambition" ], 4, 19, 5, 2, 99, 3000000, 813, 358, 123, 1602, 709, 290, 1 ], - [ "Shanks the Pirate Apprentice", "PSY", [ "Slasher", "Freedom" ], 3, 12, 4, 1, 50, 392109, 155, 74, 42, 903, 488, 230, 1 ], - [ "Shanks, Roger Pirates", "PSY", [ "Slasher", "Freedom" ], 4, 18, 6, 3, 99, 3000000, 825, 440, 193, 1964, 920, 354, 1 ], - [ "Eneru 200,000,000 Volt Amaru", "QCK", [ "Striker", "Ambition" ], 4, 30, 6, 2, 70, 1066998, 155, 163, 38, 1369, 724, 128, 1 ], - [ "Eneru, Lightning Incarnate 200,000,000 Volt Amaru", "QCK", [ "Striker", "Ambition" ], 5, 50, 5, 3, 99, 5000000, 1288, 670, 90, 2524, 1470, 234, 1 ], - [ "Sanji Voyage Log: Straw Hat Pirates", "DEX", [ "Fighter", "Tough" ], 4, 12, 4, 2, 50, 392109, 240, 103, 36, 1462, 620, 134, 0.7 ], - [ "Sanji Voyage Dream: All Blue", "DEX", [ "Fighter", "Tough" ], 5, 20, 6, 3, 99, 3000000, 1413, 577, 100, 2350, 1052, 208, 0.7 ], - [ "Zeff the Pirate", "DEX", [ "Fighter", "Tough" ], 3, 13, 5, 1, 50, 392109, 185, 112, 24, 1210, 663, 128, 1 ], - [ "Red Leg Zeff, Captain of the Cook Pirates", "DEX", [ "Fighter", "Tough" ], 4, 20, 4, 2, 99, 3000000, 1152, 599, 81, 2000, 1088, 258, 1 ], - [ "Thug Patty", "STR", "Shooter", 3, 10, 4, 1, 50, 522812, 155, 120, 25, 1080, 648, 132, 0.7 ], - [ "Thug Carne", "QCK", "Slasher", 3, 10, 6, 1, 50, 522812, 153, 91, 35, 1054, 571, 162, 0.7 ], - [ "Hiking Bear", "INT", "Fighter", 2, 7, 5, 0, 35, 90778, 129, 32, 8, 1410, 225, 30, 0.7 ], - [ "Purinpurin", "PSY", "Shooter", 2, 7, 6, 0, 35, 90778, 38, 14, 29, 544, 194, 193, 0.7 ], - [ "Brook Voyage Log: Straw Hat Pirates", "DEX", [ "Slasher", "Freedom" ], 4, 12, 6, 2, 50, 392109, 208, 99, 29, 1326, 603, 168, 0.7 ], - [ "Brook Voyage Dream: Promised Meeting", "DEX", [ "Slasher", "Freedom" ], 5, 20, 6, 3, 99, 3000000, 1276, 560, 132, 2117, 1009, 279, 0.7 ], - [ "Zambai", "PSY", "Shooter", 3, 16, 4, 2, 70, 1066998, 230, 90, 48, 1580, 702, 168, 1 ], - [ "Demolisher Axeman", "STR", [ "Slasher", "Tough" ], 3, 20, 6, 1, 60, 899032, 1200, 500, 15, 1500, 900, 35, 1.5 ], - [ "Demolisher Spearman", "STR", [ "Striker", "Tough" ], 3, 20, 6, 1, 60, 899032, 1200, 500, 16, 1700, 800, 38, 1.5 ], - [ "Demolisher Gunner", "STR", [ "Shooter", "Tough" ], 3, 20, 6, 1, 60, 899032, 1200, 500, 14, 1300, 1000, 32, 1.5 ], - [ "Street Punk: Brawler Red Bounty Hunter", "STR", "Fighter", 3, 13, 6, 1, 60, 674274, 102, 85, 28, 1158, 790, 90, 1 ], - [ "Street Punk: Brawler Green Bounty Hunter", "DEX", "Fighter", 3, 13, 6, 1, 60, 674274, 108, 75, 32, 1175, 754, 102, 1 ], - [ "Street Punk: Blade Blue Bounty Hunter", "QCK", "Slasher", 3, 13, 5, 1, 60, 674274, 153, 66, 40, 1215, 653, 128, 1 ], - [ "Street Punk: Blade Red Bounty Hunter", "STR", "Slasher", 3, 13, 5, 1, 60, 674274, 149, 73, 33, 1193, 690, 115, 1 ], - [ "Street Punk: Bullet Green Bounty Hunter", "DEX", "Shooter", 3, 13, 5, 1, 60, 674274, 92, 45, 51, 938, 500, 255, 1 ], - [ "Street Punk: Bullet Yellow Bounty Hunter", "PSY", "Shooter", 3, 13, 5, 1, 60, 674274, 86, 38, 55, 900, 467, 274, 1 ], - [ "Street Punk: Nails Yellow Bounty Hunter", "PSY", "Striker", 3, 13, 4, 1, 60, 674274, 71, 102, 33, 878, 854, 119, 1 ], - [ "Street Punk: Nails Black Bounty Hunter", "INT", "Striker", 3, 13, 4, 1, 60, 674274, 71, 108, 29, 877, 890, 107, 1 ], - [ "Street Punk: Gatling Black Bounty Hunter", "INT", "Shooter", 3, 13, 6, 1, 60, 674274, 133, 90, 3, 1556, 765, 15, 1 ], - [ "Street Punk: Gatling Blue Bounty Hunter", "QCK", "Shooter", 3, 13, 6, 1, 60, 674274, 150, 84, 5, 1602, 745, 16, 1 ], - [ "Tilestone", "STR", [ "Shooter", "Tough" ], 3, 12, 4, 2, 70, 1066998, 153, 98, 30, 1521, 800, 101, 1 ], - [ "Franky Franky Family", "INT", "Fighter", 3, 17, 5, 2, 70, 1066998, 203, 103, 23, 1712, 831, 85, 1 ], - [ "Kaku Cipher Pol No. 9", "QCK", [ "Slasher", "Tough" ], 3, 12, 5, 2, 50, 392109, 175, 80, 36, 1224, 643, 120, 1 ], - [ "Kaku: Six Powers Cipher Pol No. 9", "QCK", [ "Slasher", "Tough" ], 4, 20, 4, 3, 99, 3000000, 1144, 577, 93, 2523, 1000, 196, 1 ], - [ "Rob Lucci Cipher Pol No. 9", "STR", [ "Fighter", "Tough" ], 3, 12, 4, 2, 50, 392109, 121, 153, 20, 1121, 792, 64, 1 ], - [ "Rob Lucci: Six Powers Cipher Pol No. 9", "STR", [ "Fighter", "Tough" ], 4, 20, 6, 3, 99, 3000000, 1064, 743, 51, 2284, 1289, 134, 1 ], - [ "Keimi", "QCK", "Fighter", 3, 12, 4, 1, 50, 392109, 90, 23, 62, 960, 352, 273, [ 0.7, 1, 0.7 ] ], - [ "Keimi, Takoyaki Stand Assistant", "QCK", "Fighter", 4, 18, 5, 2, 99, 3000000, 900, 295, 231, 1731, 698, 455, 0.7 ], - [ "Pappug", "INT", "Fighter", 3, 12, 5, 1, 50, 392109, 77, 30, 77, 895, 505, 214, 0.7 ], - [ "Hatchan, Takoyaki Stand Owner", "PSY", [ "Slasher", "Tough" ], 3, 16, 6, 2, 99, 3000000, 134, 88, 41, 1788, 888, 187, 0.7 ], - [ "Doma", "QCK", "Slasher", 4, 18, 4, 3, 70, 1066998, 89, 144, 43, 1098, 733, 187, 0.7 ], - [ "Bohemian Knight Doma", "QCK", "Slasher", 5, 29, 4, 4, 99, 4000000, 1020, 695, 150, 2134, 1268, 328, 0.7 ], - [ "DeCalvan Brothers", "DEX", "Fighter", 4, 18, 6, 3, 70, 1066998, 240, 89, 28, 1880, 668, 73, 0.7 ], - [ "DeCalvan Brothers Brothers' Bond", "DEX", "Fighter", 5, 29, 5, 4, 99, 4000000, 1824, 602, 50, 3330, 1183, 158, 0.7 ], - [ "Squard", "PSY", [ "Striker", "Tough" ], 4, 18, 5, 3, 70, 1066998, 198, 190, 0, 1351, 810, 0, 0.7 ], - [ "Maelstrom Spider Squard", "PSY", [ "Striker", "Tough" ], 5, 29, 5, 4, 99, 4000000, 960, 755, -1, 2755, 1434, -150, 0.7 ], - [ "Whitey Bay", "INT", [ "Slasher", "Ambition" ], 4, 18, 5, 3, 70, 1066998, 109, 93, 44, 1140, 600, 223, 0.7 ], - [ "Ice Witch Whitey Bay", "INT", [ "Slasher", "Ambition" ], 5, 29, 5, 4, 99, 4000000, 1094, 561, 171, 2278, 993, 399, 0.7 ], - [ "Little Oars Jr.", "STR", [ "Shooter", "Tough" ], 4, 20, 6, 3, 70, 1066998, 251, 166, 1, 1900, 734, 3, 0.7 ], - [ "Little Oars Jr. Charging!", "STR", [ "Shooter", "Tough" ], 5, 30, 4, 4, 99, 4000000, 1533, 801, 2, 4000, 1300, 9, 0.7 ], - [ "Marco Whitebeard 1st Div. Commander", "QCK", [ "Fighter", "Tough" ], 5, 30, 4, 4, 50, 392109, 455, 268, 177, 1612, 777, 303, 0.7 ], - [ "Marco the Phoenix Whitebeard 1st Div. Commander", "QCK", [ "Fighter", "Tough" ], 6, 55, 4, 5, 99, 5000000, 1555, 734, 258, 3013, 1402, 455, 0.7 ], - [ "Nami Voyage Log: Straw Hat Pirates", "INT", [ "Striker", "Knowledge" ], 4, 12, 4, 2, 50, 392109, 143, 65, 50, 998, 498, 254, 0.7 ], - [ "Nami Voyage Dream: World Map", "INT", [ "Striker", "Knowledge" ], 5, 20, 4, 3, 99, 3000000, 922, 434, 198, 1890, 900, 380, 0.7 ], - [ "Iron Mask Duval", "DEX", [ "Shooter", "Ambition" ], 3, 10, 4, 1, 35, 226945, 132, 133, 25, 725, 505, 77, 1 ], - [ "Duval, Head of the Flying Fish Riders", "DEX", [ "Shooter", "Ambition" ], 4, 30, 5, 2, 60, 1123790, 664, 424, 44, 1448, 723, 103, 1 ], - [ "Duval, Head of the Rosy Life Riders", "DEX", [ "Shooter", "Freedom" ], 5, 50, 8, 3, 99, 5000000, 1420, 658, 103, 2608, 1113, 308, 1 ], - [ "Pirate Arlong", "STR", [ "Slasher", "Tough" ], 3, 12, 6, 1, 50, 392109, 159, 144, 14, 1332, 700, 89, 1 ], - [ "Arlong, Sun Pirates", "STR", [ "Slasher", "Tough" ], 4, 20, 4, 2, 99, 3000000, 1261, 633, 45, 2020, 1389, 171, 1 ], - [ "Kuroobi, Sun Pirates", "STR", [ "Fighter", "Tough" ], 3, 10, 6, 1, 50, 392109, 160, 103, 9, 1233, 744, 70, 1 ], - [ "Choo, Sun Pirates", "INT", [ "Shooter", "Tough" ], 3, 10, 5, 1, 50, 392109, 75, 72, 22, 1002, 552, 178, 1 ], - [ "Monkey D. Luffy Swim Ring", "QCK", "Fighter", 4, 15, 6, 2, 99, 2000000, 144, 69, 31, 2232, 933, 242, 1 ], - [ "Usopp Voyage Log: Straw Hat Pirates", "QCK", "Striker", 4, 12, 6, 2, 50, 392109, 155, 67, 47, 1085, 513, 235, 0.7 ], - [ "Usopp Voyage Dream: Brave Sea Warrior", "QCK", "Striker", 5, 20, 4, 3, 99, 3000000, 1024, 468, 185, 2012, 938, 344, 0.7 ], - [ "Nami Holiday", "PSY", [ "Striker", "Knowledge" ], 4, 15, 5, 2, 99, 2000000, 70, 30, 100, 1334, 673, 396, 0.7 ], - [ "Nefertari Vivi, Princess of the Alabasta Kingdom", "PSY", [ "Striker", "Freedom" ], 3, 9, 6, 1, 35, 136167, 11, 11, 11, 285, 104, 225, 1 ], - [ "Nefertari Vivi, Vice-Leader of the Suna Suna Clan", "PSY", [ "Fighter", "Freedom" ], 4, 15, 6, 2, 70, 1066998, 243, 51, 187, 593, 269, 488, 1 ], - [ "Koza, Alabasta Citizen", "QCK", [ "Striker", "Freedom" ], 3, 9, 5, 1, 35, 136167, 53, 53, 3, 503, 274, 151, 1 ], - [ "Koza, Leader of the Suna Suna Clan", "QCK", [ "Striker", "Freedom" ], 4, 15, 4, 2, 70, 1066998, 445, 230, 123, 1000, 503, 341, 1 ], - [ "Nefertari Cobra, King of the Alabasta Kingdom", "PSY", "Fighter", 3, 15, 5, 2, 70, 1066998, 523, 294, 31, 1402, 571, 211, 1 ], - [ "Sabo", "PSY", [ "Freedom", "Striker" ], 5, 30, 5, 4, 70, 1066998, 369, 279, 169, 1498, 821, 305, 1.5 ], - [ "Sabo the Revolutionary", "PSY", [ "Freedom", "Striker" ], 6, 55, 4, 5, 99, 5000000, 1440, 752, 252, 2985, 1422, 451, 1.5 ], - [ "Koala", "DEX", [ "Fighter", "Freedom" ], 4, 18, 4, 3, 70, 1066998, 94, 122, 48, 996, 644, 226, 1.5 ], - [ "Koala the Revolutionary", "DEX", [ "Fighter", "Freedom" ], 5, 29, 4, 4, 99, 4000000, 931, 600, 185, 1934, 1212, 392, 1.5 ], - [ "Hack", "STR", [ "Fighter", "Tough" ], 4, 18, 4, 3, 70, 1066998, 188, 136, 21, 1241, 721, 151, 1.5 ], - [ "Hack the Revolutionary", "STR", [ "Fighter", "Tough" ], 5, 29, 5, 4, 99, 4000000, 1185, 668, 115, 2387, 1324, 259, 1.5 ], - [ "Emporio Ivankov, Newkama Kenpo Instructor", "INT", [ "Freedom", "Fighter" ], 4, 18, 4, 3, 70, 1066998, 206, 99, 32, 1343, 653, 157, 1.5 ], - [ "Emporio Ivankov the Revolutionary", "INT", [ "Freedom", "Fighter" ], 5, 29, 7, 4, 99, 4000000, 1285, 593, 142, 2774, 1212, 241, 1.5 ], - [ "Inazuma", "QCK", [ "Slasher", "Knowledge" ], 4, 18, 4, 3, 70, 1066998, 179, 58, 47, 1300, 449, 232, 1.5 ], - [ "Inazuma the Revolutionary", "QCK", [ "Slasher", "Knowledge" ], 5, 29, 6, 4, 99, 4000000, 1244, 400, 199, 2559, 833, 380, 1.5 ], - [ "Nico Robin Voyage Log: Straw Hat Pirates", "PSY", [ "Fighter", "Knowledge" ], 4, 12, 6, 2, 50, 392109, 155, 62, 58, 1032, 484, 262, 1 ], - [ "Nico Robin Voyage Dream: 100-Year Void", "PSY", [ "Fighter", "Knowledge" ], 5, 20, 6, 3, 99, 3000000, 970, 423, 220, 1924, 857, 390, 1 ], - [ "Ice Cream Loving Nami", "DEX", [ "Striker", "Knowledge" ], 4, 12, 6, 1, 50, 392109, 141, 43, 53, 966, 422, 242, 1 ], - [ "Lemon Ice Cream Loving Nami", "DEX", [ "Striker", "Knowledge" ], 5, 20, 4, 2, 99, 3000000, 900, 366, 200, 1802, 768, 402, 1 ], - [ "Ice Cream Loving Robin", "PSY", [ "Fighter", "Knowledge" ], 4, 12, 6, 1, 50, 392109, 147, 61, 46, 988, 491, 218, 0.7 ], - [ "Chocolate Ice Cream Loving Robin", "PSY", [ "Fighter", "Knowledge" ], 5, 20, 4, 2, 99, 3000000, 943, 443, 172, 1903, 842, 361, 1 ], - [ "Ice Cream Loving Perona", "INT", [ "Shooter", "Ambition" ], 4, 12, 5, 1, 50, 392109, 99, 67, 52, 901, 527, 233, 1 ], - [ "Strawberry Ice Cream Loving Perona", "INT", [ "Shooter", "Ambition" ], 5, 20, 4, 2, 99, 3000000, 848, 462, 182, 1689, 877, 385, 1 ], - [ "Vivi's Breather", "QCK", [ "Slasher", "Freedom" ], 4, 12, 4, 2, 70, 1066998, 102, 37, 91, 1028, 497, 343, 1 ], - [ "Calgara", "STR", [ "Freedom", "Striker" ], 3, 12, 6, 1, 50, 392109, 94, 115, 0, 1203, 692, 0, 1 ], - [ "Calgara, the Great Warrior of Shandia", "STR", [ "Freedom", "Striker" ], 4, 20, 4, 2, 99, 3000000, 1145, 633, 0, 2401, 1300, 90, 1 ], - [ "Montblanc Noland", "INT", [ "Slasher", "Knowledge" ], 3, 12, 5, 1, 50, 392109, 102, 74, 49, 1028, 502, 212, 1 ], - [ "Montblanc Noland, Explorer and Admiral of the Lvneel Kingdom", "INT", [ "Slasher", "Knowledge" ], 4, 20, 4, 2, 99, 3000000, 949, 442, 170, 1982, 890, 326, 1 ], - [ "Halberd Corporal Navy HQ", "DEX", "Striker", 2, 7, 5, 0, 35, 90778, 70, 32, 21, 601, 301, 98, 1 ], - [ "Pistol Corporal Navy HQ", "QCK", "Shooter", 2, 7, 6, 0, 35, 90778, 58, 28, 28, 498, 286, 121, 1 ], - [ "Saber Corporal Navy HQ", "PSY", "Slasher", 2, 7, 5, 0, 35, 90778, 51, 34, 22, 466, 330, 111, 1 ], - [ "Bazooka Corporal Navy HQ", "STR", "Shooter", 2, 7, 4, 0, 35, 90778, 62, 50, 14, 598, 404, 64, 1 ], - [ "Knuckle Corporal Navy HQ", "INT", "Fighter", 2, 7, 6, 0, 35, 90778, 55, 48, 22, 522, 392, 82, 1 ], - [ "Halberd Major Navy HQ", "DEX", "Striker", 3, 13, 6, 1, 70, 1066998, 554, 250, 61, 1358, 645, 170, 1 ], - [ "Pistol Major Navy HQ", "QCK", "Shooter", 3, 13, 5, 1, 70, 1066998, 444, 244, 96, 1002, 568, 259, 1 ], - [ "Saber Major Navy HQ", "PSY", "Slasher", 3, 13, 6, 1, 70, 1066998, 411, 275, 86, 989, 737, 208, 1 ], - [ "Bazooka Major Navy HQ", "STR", "Shooter", 3, 13, 6, 1, 70, 1066998, 547, 362, 44, 1301, 833, 117, 1 ], - [ "Knuckle Major Navy HQ", "INT", "Fighter", 3, 13, 5, 1, 70, 1066998, 462, 351, 49, 1244, 876, 112, 1 ], - [ "Oimo", "PSY", [ "Striker", "Tough" ], 3, 25, 5, 2, 70, 1778330, 452, 223, 23, 1602, 742, 98, 1 ], - [ "Kashi", "INT", [ "Slasher", "Tough" ], 3, 25, 6, 2, 70, 1778330, 426, 242, 21, 1551, 798, 87, 1 ], - [ "Watchdog Unit of the Law", "QCK", "Slasher", 3, 13, 4, 1, 70, 1066998, 122, 43, 40, 1211, 488, 251, 1 ], - [ "Just Juryman", "STR", "Striker", 3, 13, 4, 1, 70, 1066998, 108, 129, 34, 990, 900, 144, 1 ], - [ "Three-Headed Baskerville", "DEX", "Slasher", 3, 13, 4, 3, 70, 1066998, 102, 78, 38, 1109, 595, 232, 1 ], - [ "Blueno, Cipher Pol No.9", "STR", [ "Fighter", "Tough" ], 3, 12, 5, 2, 50, 392109, 166, 102, 32, 1338, 502, 124, 1 ], - [ "Blueno Rokushiki, Cipher Pol No.9", "STR", [ "Fighter", "Tough" ], 4, 20, 4, 3, 99, 3000000, 1281, 452, 100, 2466, 921, 221, 1 ], - [ "Nico Robin the Devil Child", "PSY", [ "Fighter", "Knowledge" ], 3, 10, 6, 2, 50, 392109, 110, 63, 32, 1002, 494, 209, 1 ], - [ "Nico Robin, Straw Hat Pirates", "PSY", [ "Fighter", "Knowledge" ], 4, 16, 5, 3, 99, 3000000, 938, 430, 155, 1892, 881, 351, 1 ], - [ "Franky Voyage Log: Straw Hat Pirates", "PSY", [ "Shooter", "Freedom" ], 4, 12, 4, 2, 50, 392109, 242, 100, 34, 1330, 597, 151, 1 ], - [ "Franky Voyage Dream: Ship of the Seven Seas", "PSY", [ "Shooter", "Freedom" ], 5, 20, 6, 3, 99, 3000000, 1259, 550, 112, 2372, 1100, 231, 1 ], - [ "Gan Fall", "QCK", "Striker", 3, 12, 6, 1, 50, 392109, 80, 40, 48, 930, 452, 185, 1.5 ], - [ "Gan Fall the Knight of the Sky", "QCK", "Striker", 4, 20, 4, 2, 99, 3000000, 884, 401, 151, 1704, 1202, 300, 1.5 ], - [ "Pierre", "DEX", "Fighter", 3, 12, 4, 1, 50, 392109, 69, 32, 38, 920, 480, 182, 1 ], - [ "Konis", "PSY", "Freedom", 3, 9, 5, 2, 35, 136167, 58, 10, 32, 503, 190, 232, 1 ], - [ "Konis, Skypiean Maiden", "PSY", "Freedom", 4, 15, 4, 3, 70, 1066998, 458, 145, 196, 912, 388, 387, 1 ], - [ "Dracule Mihawk Warlord of the Sea", "INT", "Slasher", 5, 30, 4, 4, 70, 1066998, 623, 328, 10, 1921, 850, 58, 1.5 ], - [ "Dracule Mihawk, World's Strongest Swordsman", "INT", "Slasher", 6, 55, 5, 4, 99, 5000000, 1857, 799, 31, 3900, 1490, 120, 1.5 ], - [ "Sir Crocodile Logia Warlord of the Sea", "DEX", [ "Knowledge", "Striker" ], 5, 30, 4, 4, 70, 1066998, 500, 293, 104, 1780, 831, 226, 1.5 ], - [ "Sir Crocodile Logia Former Warlord of the Sea", "DEX", [ "Knowledge", "Striker" ], 6, 55, 4, 4, 99, 5000000, 1724, 765, 174, 3621, 1435, 310, 1.5 ], - [ "Jerry", "STR", [ "Fighter", "Freedom" ], 3, 9, 5, 1, 35, 136167, 72, 100, 32, 492, 380, 104, 1 ], - [ "Jerry, Cipher Pol No.6", "STR", [ "Fighter", "Freedom" ], 4, 15, 8, 2, 70, 1066998, 439, 323, 70, 1000, 712, 212, 1 ], - [ "T-Bone", "PSY", [ "Slasher", "Knowledge" ], 3, 12, 6, 1, 50, 392109, 99, 78, 42, 958, 542, 162, 1 ], - [ "Ship Cutter T-Bone, Navy HQ Captain", "PSY", [ "Slasher", "Knowledge" ], 4, 20, 4, 3, 99, 3000000, 900, 493, 133, 1700, 1100, 300, 1 ], - [ "Nefertari Vivi Voyage Log: Princess of Alabasta", "QCK", [ "Slasher", "Freedom" ], 4, 12, 6, 2, 50, 392109, 98, 51, 62, 855, 424, 288, 1 ], - [ "Nefertari Vivi Voyage Dream: Queen of the Pirates", "QCK", [ "Slasher", "Freedom" ], 5, 20, 4, 3, 99, 3000000, 800, 371, 258, 1591, 777, 474, 1 ], - [ "Monkey D. Luffy Gum-Gum Gatling", "DEX", [ "Freedom", "Fighter" ], 4, 15, 8, 3, 99, 2000000, 212, 100, 46, 1777, 795, 270, 0.7 ], - [ "Kalifa, Cipher Pol No.9", "DEX", [ "Fighter", "Knowledge" ], 3, 12, 5, 2, 50, 392109, 89, 39, 55, 952, 448, 217, 1 ], - [ "Kalifa Rokushiki, Cipher Pol No.9", "DEX", [ "Fighter", "Knowledge" ], 4, 20, 5, 3, 99, 3000000, 900, 401, 174, 1894, 970, 302, 1 ], - [ "Jabra, Cipher Pol No.9", "INT", [ "Fighter", "Tough" ], 3, 12, 4, 2, 50, 392109, 190, 92, -200, 1334, 572, -200, 1 ], - [ "Jabra Rokushiki, Cipher Pol No.9", "INT", [ "Fighter", "Tough" ], 4, 20, 4, 3, 99, 3000000, 1272, 521, -200, 2720, 1250, -200, 1 ], - [ "Fukuro, Cipher Pol No.9", "STR", [ "Fighter", "Tough" ], 3, 9, 4, 2, 35, 136167, 114, 52, 30, 1123, 408, 122, 1 ], - [ "Fukuro Rokushiki, Cipher Pol No.9", "STR", [ "Fighter", "Tough" ], 4, 15, 6, 3, 70, 1066998, 1077, 362, 97, 1850, 690, 177, 1 ], - [ "Kumadori, Cipher Pol No.9", "PSY", [ "Striker", "Tough" ], 3, 9, 5, 2, 35, 136167, 102, 60, 29, 1055, 442, 119, 1 ], - [ "Kumadori Rokushiki, Cipher Pol No.9", "PSY", [ "Striker", "Tough" ], 4, 15, 4, 3, 70, 1066998, 1000, 398, 88, 1792, 755, 165, 1 ], - [ "Kaku Human-Beast, Ox-Ox Fruit Model: Giraffe", "STR", [ "Slasher", "Tough" ], 4, 20, 6, 3, 99, 4000000, 1220, 692, 43, 2526, 1200, 114, 1 ], - [ "Lucci Human-Beast, Cat-Cat Fruit Model: Leopard", "QCK", [ "Fighter", "Tough" ], 4, 20, 4, 3, 99, 4000000, 1032, 703, 56, 2200, 1302, 140, 1 ], - [ "Spandam", "INT", "Slasher", 4, 7, 5, 1, 35, 136167, 52, 25, 25, 258, 196, 89, 1 ], - [ "Franky, Straw Hat Pirates", "INT", [ "Fighter", "Freedom" ], 4, 18, 4, 3, 99, 3000000, 1623, 765, 70, 2505, 1149, 130, 1 ], - [ "Nero", "QCK", [ "Shooter", "Ambition" ], 3, 9, 6, 1, 35, 136167, 59, 112, 20, 324, 543, 83, 0.7 ], - [ "Nero, Cipher Pol No.9", "QCK", [ "Shooter", "Ambition" ], 4, 15, 5, 2, 70, 1066998, 277, 489, 51, 755, 1050, 145, 0.7 ], - [ "Wanze", "DEX", "Freedom", 3, 11, 4, 1, 50, 392109, 202, 44, 40, 1124, 367, 212, 1 ], - [ "Wanze, Cipher Pol No.7", "DEX", "Freedom", 4, 18, 5, 2, 99, 3000000, 1059, 312, 170, 2051, 674, 363, 1 ], - [ "Portgas D. Ace, Record of the Voyage - Whitebeard Pirates", "QCK", [ "Freedom", "Fighter" ], 4, 12, 5, 2, 50, 392109, 141, 71, 36, 1121, 585, 189, 1.5 ], - [ "Portgas D. Ace Voyage Dream: Pirate Summit", "QCK", [ "Freedom", "Fighter" ], 5, 20, 4, 3, 99, 4000000, 1063, 524, 140, 2181, 1100, 258, 1.5 ], - [ "Megalo and Princess Shirahoshi", "QCK", "Fighter", 4, 15, 4, 3, 70, 1066998, 1251, 271, 150, 2001, 600, 241, 1 ], - [ "Rob Lucci, CP9's Dark Justice", "STR", [ "Tough", "Fighter" ], 5, 30, 4, 4, 70, 1066998, 496, 300, 89, 1656, 800, 245, 1.5 ], - [ "Rob Lucci, CP9's Strongest Generation", "STR", [ "Tough", "Fighter" ], 6, 55, 6, 4, 99, 5000000, 1611, 762, 220, 3230, 1456, 382, 1.5 ], - [ "Kaku, CP9's Dark Justice", "DEX", [ "Slasher", "Tough" ], 4, 17, 6, 3, 70, 1066998, 151, 132, 28, 1183, 713, 178, 1 ], - [ "Kaku, CP9's Strongest Generation", "DEX", [ "Slasher", "Tough" ], 5, 27, 8, 4, 99, 4000000, 1124, 666, 147, 2440, 1325, 272, 1 ], - [ "Kalifa, CP9's Dark Justice", "QCK", [ "Knowledge", "Fighter" ], 4, 17, 5, 3, 70, 1066998, 98, 60, 63, 963, 545, 270, 1 ], - [ "Kalifa, CP9's Strongest Generation", "QCK", [ "Knowledge", "Fighter" ], 5, 27, 5, 4, 99, 4000000, 912, 498, 238, 1964, 933, 473, 1 ], - [ "Jabra, CP9's Dark Justice", "QCK", [ "Tough", "Freedom" ], 4, 17, 5, 3, 70, 1066998, 224, 112, 21, 1650, 702, 89, 1 ], - [ "Jabra, CP9's Strongest Generation", "QCK", [ "Tough", "Freedom" ], 5, 27, 4, 4, 99, 4000000, 1601, 657, 55, 3003, 1299, 166, 1 ], - [ "Blueno, CP9's Dark Justice", "INT", [ "Tough", "Freedom" ], 4, 16, 5, 3, 70, 1066998, 245, 94, 23, 1832, 644, 91, 1 ], - [ "Blueno, CP9's Strongest Generation", "INT", [ "Tough", "Freedom" ], 5, 26, 4, 4, 99, 4000000, 1779, 600, 56, 3502, 1045, 168, 1 ], - [ "Fukuro, CP9's Dark Justice", "PSY", [ "Tough", "Fighter" ], 4, 16, 4, 3, 70, 1066998, 151, 97, 46, 1140, 651, 203, 1 ], - [ "Fukuro, CP9's Strongest Generation", "PSY", [ "Tough", "Fighter" ], 5, 26, 8, 4, 99, 4000000, 1093, 603, 165, 2415, 1051, 353, 1 ], - [ "Kumadori, CP9's Dark Justice", "STR", [ "Tough", "Striker" ], 4, 16, 4, 3, 70, 1066998, 162, 89, 47, 1167, 612, 212, 1 ], - [ "Kumadori, CP9's Strongest Generation", "STR", [ "Tough", "Striker" ], 5, 26, 7, 4, 99, 4000000, 1110, 560, 170, 2479, 1018, 355, 1 ], - [ "Monkey D. Luffy Halloween Monster", "DEX", [ "Fighter", "Freedom" ], 4, 20, 6, 3, 99, 3000000, 85, 41, 26, 1920, 1080, 185, 1 ], - [ "Usopp Lying Wolf", "PSY", "Shooter", 4, 20, 5, 3, 99, 3000000, 51, 23, 46, 1444, 673, 400, 1 ], - [ "Franky Frankenstein", "STR", [ "Shooter", "Freedom" ], 4, 20, 4, 3, 99, 3000000, 82, 43, 22, 1903, 1121, 170, 1 ], - [ "Nami Jackie 'o Lantern", "QCK", [ "Striker", "Knowledge" ], 4, 20, 4, 3, 99, 3000000, 47, 25, 49, 1342, 699, 416, 1 ], - [ "Tony Tony Chopper Lil' Vampire", "INT", [ "Fighter", "Knowledge" ], 4, 20, 6, 3, 99, 3000000, 56, 33, 38, 1548, 763, 358, 1 ], - [ "Roronoa Zoro Jack the Ripper", "QCK", [ "Slasher", "Ambition" ], 4, 20, 6, 3, 99, 3000000, 90, 39, 13, 2094, 1063, 131, 1 ], - [ "Nico Robin Devil Girl", "DEX", [ "Fighter", "Knowledge" ], 4, 20, 4, 3, 99, 3000000, 53, 35, 34, 1500, 889, 320, 1 ], - [ "Sanji Ghost Knight", "PSY", "Fighter", 4, 20, 4, 3, 99, 3000000, 92, 36, 28, 2088, 936, 221, 1 ], - [ "Brook Cowardly Skeleton", "INT", [ "Slasher", "Freedom" ], 4, 20, 4, 3, 99, 3000000, 62, 35, 26, 1921, 948, 210, 1 ], - [ "Dalmatian, Navy HQ Vice Admiral", "STR", [ "Fighter", "Tough" ], 4, 20, 5, 3, 99, 4000000, 241, 186, 35, 2171, 1275, 189, 1.5 ], - [ "Momonga, Navy HQ Vice Admiral", "PSY", [ "Knowledge", "Slasher" ], 4, 20, 6, 3, 99, 4000000, 298, 142, 20, 2618, 1111, 163, 1.5 ], - [ "Onigumo, Navy HQ Vice Admiral", "DEX", [ "Slasher", "Ambition" ], 4, 20, 8, 3, 99, 4000000, 213, 118, 54, 2000, 1021, 318, 1.5 ], - [ "Shu", "INT", [ "Fighter", "Freedom" ], 3, 12, 4, 2, 70, 1066998, 56, 89, 23, 943, 969, 150, 1 ], - [ "Very Good", "QCK", [ "Freedom", "Striker" ], 3, 12, 4, 2, 70, 1066998, 203, 57, 15, 1808, 703, 103, 1 ], - [ "Strawberry, Navy HQ Vice Admiral", "PSY", [ "Knowledge", "Slasher" ], 3, 16, 6, 2, 99, 3000000, 142, 64, 33, 1883, 943, 178, 1 ], - [ "Lucky Roo", "PSY", [ "Shooter", "Freedom" ], 3, 13, 6, 2, 35, 136167, 303, 169, 30, 904, 460, 98, 0.7 ], - [ "Lucky Roo of the Red Hair Pirates", "PSY", [ "Shooter", "Freedom" ], 4, 20, 5, 3, 70, 1778330, 842, 412, 70, 1606, 789, 188, 0.7 ], - [ "Rebecca, Prisoner Gladiator", "QCK", "Striker", 4, 18, 5, 1, 50, 392109, 193, 112, 51, 1003, 503, 201, 1 ], - [ "Rebecca, Colosseum's Exclusive Gladiator", "QCK", "Striker", 5, 30, 4, 3, 99, 3000000, 920, 441, 150, 1947, 853, 374, 1 ], - [ "Urouge, Captain of the Fallen Monk Pirates", "STR", [ "Fighter", "Striker" ], 4, 25, 5, 2, 70, 1066998, 702, 340, 38, 1580, 790, 121, 1.5 ], - [ "Mad Monk Urouge, Captain of the Fallen Monk Pirates", "STR", [ "Fighter", "Striker" ], 5, 40, 5, 3, 99, 4000000, 1512, 755, 83, 2824, 1324, 203, 1.5 ], - [ "Tashigi: Flower of Justice", "INT", [ "Slasher", "Knowledge" ], 4, 13, 5, 2, 50, 392109, 132, 65, 49, 999, 495, 205, 1 ], - [ "Tashigi Marine Officer: Flower of Justice", "INT", [ "Slasher", "Knowledge" ], 5, 20, 5, 3, 99, 3000000, 932, 428, 164, 1804, 890, 378, 1 ], - [ "Gen-san", "STR", [ "Slasher", "Knowledge" ], 3, 9, 5, 2, 35, 136167, 211, 45, 33, 930, 288, 190, 1 ], - [ "Genzo, Cocoyasi Village Resident", "STR", [ "Slasher", "Knowledge" ], 4, 15, 4, 3, 70, 1066998, 879, 242, 143, 1324, 501, 299, 1 ], - [ "Dr. Hiluluk", "PSY", [ "Shooter", "Freedom" ], 3, 9, 6, 2, 35, 136167, 231, 63, 5, 1248, 461, 84, 1 ], - [ "Dr. Hiluluk, Quack Doctor", "PSY", [ "Shooter", "Freedom" ], 4, 15, 5, 3, 70, 1066998, 1233, 451, 84, 1248, 518, 312, 1 ], - [ "Kuina", "DEX", "Striker", 3, 9, 6, 2, 35, 136167, 54, 41, 70, 503, 264, 251, 1 ], - [ "Kuina, Shimotsuki Village's Girl Swordsman", "DEX", [ "Slasher", "Ambition" ], 4, 15, 5, 3, 70, 1066998, 448, 220, 213, 917, 582, 338, 1 ], - [ "Tamanegi, Piiman & Ninjin", "QCK", [ "Striker", "Freedom" ], 3, 9, 4, 3, 35, 136167, 80, 10, 66, 716, 142, 249, 1 ], - [ "Tamanegi, Piiman & Ninjin, the Usopp Pirates", "QCK", [ "Striker", "Freedom" ], 4, 15, 6, 3, 70, 1066998, 654, 77, 180, 1200, 333, 350, 1 ], - [ "Iceburg", "INT", [ "Shooter", "Knowledge" ], 3, 9, 6, 2, 35, 136167, 155, 69, 38, 790, 392, 167, 1 ], - [ "Iceburg, Mayor of W7 and President of Galley-La Company", "INT", [ "Shooter", "Knowledge" ], 4, 16, 4, 3, 70, 1066998, 723, 343, 122, 1401, 702, 224, 1 ], - [ "Monkey D. Luffy Star of Hope", "INT", [ "Slasher", "Tough" ], 4, 30, 4, 1, 70, 1066998, 259, 179, 0, 1400, 763, 0, 1.5 ], - [ "Nightmare Luffy Warrior of Hope", "INT", [ "Fighter", "Tough" ], 5, 50, 4, 2, 99, 5000000, 1331, 711, 0, 3020, 1520, 0, 1.5 ], - [ "Breed", "INT", "Knowledge", 3, 13, 6, 1, 50, 392109, 59, 25, 59, 867, 418, 275, 1.5 ], - [ "Breed, User of the Peto-Peto Fruit", "INT", [ "Knowledge", "Tough" ], 4, 20, 4, 3, 99, 3000000, 867, 818, 200, 2002, 1311, 180, 1.5 ], - [ "Kung Fu Dugong, Sea Animal Pirates", "PSY", [ "Fighter", "Tough" ], 4, 18, 5, 2, 70, 1778330, 50, 355, 95, 450, 1115, 225, 1.5 ], - [ "Sea Lapin, Sea Animal Pirates", "QCK", [ "Fighter", "Tough" ], 3, 15, 4, 1, 70, 711332, 209, 76, 14, 1757, 724, 112, 1 ], - [ "Octopus Boxer, Sea Animal Pirates", "STR", [ "Fighter", "Tough" ], 3, 15, 8, 1, 70, 711332, 99, 91, 2, 1563, 846, 93, 1 ], - [ "Mr. 2 Bon Clay Voyage Log: B.W.", "PSY", [ "Fighter", "Freedom" ], 4, 13, 5, 2, 50, 392109, 109, 57, 32, 1033, 513, 212, 1 ], - [ "Mr. 2 Bon Clay Voyage Dream: Okama Way", "PSY", [ "Fighter", "Freedom" ], 5, 20, 4, 3, 99, 3000000, 970, 448, 181, 1914, 922, 362, 1 ], - [ "Hina, Navy HQ Captain", "DEX", [ "Fighter", "Knowledge" ], 4, 18, 5, 1, 50, 392109, 188, 128, 48, 977, 544, 191, 1 ], - [ "Black Cage Hina, Navy HQ Captain", "DEX", [ "Fighter", "Knowledge" ], 5, 30, 5, 3, 99, 3000000, 920, 488, 159, 1901, 912, 357, 1 ], - [ "Smoker, Navy HQ Captain", "INT", [ "Striker", "Ambition" ], 4, 25, 6, 2, 70, 1066998, 710, 309, 44, 1600, 703, 146, 1.5 ], - [ "Smoker the White Hunter, Navy HQ Captain", "INT", [ "Striker", "Ambition" ], 5, 40, 5, 3, 99, 4000000, 1549, 640, 112, 2727, 1289, 234, 1.5 ], - [ "Pure White Angel Wedding Nami", "PSY", [ "Striker", "Knowledge" ], 3, 13, 5, 1, 50, 392109, 60, 33, 49, 933, 419, 268, 1 ], - [ "Pure White Goddess Wedding Nami", "PSY", [ "Striker", "Knowledge" ], 4, 20, 4, 2, 99, 3000000, 877, 362, 221, 1772, 799, 409, 1 ], - [ "Lola, Thriller Bark Bride", "STR", [ "Slasher", "Tough" ], 3, 11, 6, 1, 50, 261406, 103, 69, 31, 1101, 559, 91, 1 ], - [ "Courting Lola, Thriller Bark Bride", "STR", [ "Slasher", "Tough" ], 4, 18, 8, 2, 99, 2000000, 1032, 513, 52, 2018, 1009, 147, 1 ], - [ "Risky Brothers", "DEX", [ "Slasher", "Freedom" ], 3, 9, 4, 2, 50, 392109, 30, 15, 40, 707, 368, 287, 1 ], - [ "Cerberus", "QCK", [ "Fighter", "Tough" ], 3, 14, 5, 2, 50, 392109, 233, 108, 52, 1151, 781, 0, 1 ], - [ "Tararan", "INT", [ "Knowledge", "Tough" ], 3, 14, 7, 2, 50, 392109, 325, 76, 48, 1385, 696, 0, 1 ], - [ "Bear-Skin Rug", "DEX", [ "Fighter", "Tough" ], 3, 14, 5, 2, 50, 392109, 203, 52, 155, 1074, 609, 74, 1 ], - [ "Gecko Moriah, Thriller Bark's Mysterious Four", "INT", [ "Freedom", "Ambition" ], 3, 12, 6, 2, 50, 392109, 205, 92, 0, 1422, 504, 0, 1 ], - [ "Gecko Moriah, Ruler of Thriller Bark", "INT", [ "Freedom", "Ambition" ], 4, 20, 4, 3, 99, 3000000, 1355, 451, 0, 2603, 913, 0, 1.5 ], - [ "Soldier Zombie Boastful Shadow", "STR", "Fighter", 2, 7, 6, 0, 35, 90778, 85, 39, 92, 990, 622, 27, 1 ], - [ "Soldier Zombie Quick Shadow", "QCK", "Fighter", 2, 7, 6, 0, 35, 90778, 77, 30, 92, 944, 590, 43, 1 ], - [ "Soldier Zombie Vile Shadow", "DEX", "Fighter", 2, 7, 6, 0, 35, 90778, 92, 28, 92, 1032, 574, 35, 1 ], - [ "Soldier Zombie Hateful Shadow", "INT", "Fighter", 2, 7, 6, 0, 35, 90778, 71, 40, 92, 903, 648, 29, 1 ], - [ "Soldier Zombie Proud Shadow", "PSY", "Fighter", 2, 7, 6, 0, 35, 90778, 70, 24, 92, 887, 551, 72, 1 ], - [ "Tricky Wild Zombie", "DEX", "Tough", 3, 12, 4, 1, 50, 392109, 75, 74, 132, 899, 720, 71, 1 ], - [ "Brainy Wild Zombie", "INT", "Tough", 3, 12, 4, 1, 50, 392109, 71, 86, 132, 823, 771, 65, 1 ], - [ "Hearty Wild Zombie", "PSY", "Tough", 3, 12, 4, 1, 50, 392109, 70, 70, 132, 801, 700, 94, 1 ], - [ "General Zombie Herculean Shadow", "STR", [ "Slasher", "Tough" ], 3, 20, 6, 1, 70, 1066998, 99, 59, 29, 1702, 813, 0, 1 ], - [ "General Zombie Peculiar Shadow", "DEX", [ "Slasher", "Tough" ], 3, 20, 6, 1, 70, 1066998, 102, 57, 29, 1727, 802, 0, 1 ], - [ "General Zombie Swift Shadow", "QCK", [ "Slasher", "Tough" ], 3, 20, 6, 1, 70, 1066998, 113, 54, 29, 1768, 789, 0, 1 ], - [], - [], - [ "Basil Hawkins, Captain of the Hawkins Pirates", "DEX", [ "Knowledge", "Striker" ], 4, 25, 6, 2, 70, 1066998, 639, 298, 69, 1219, 745, 201, 1 ], - [ "Basil Hawkins the Magician, Captain of the Hawkins Pirates", "DEX", [ "Knowledge", "Striker" ], 5, 40, 4, 3, 99, 4000000, 1157, 690, 147, 2239, 1278, 347, 1 ], - [ "Wyper, Warrior of Shandia", "STR", [ "Shooter", "Freedom" ], 4, 18, 6, 1, 50, 392109, 229, 151, 10, 1198, 611, 33, 1 ], - [ "Berserker Wyper, Warrior of Shandia", "STR", [ "Shooter", "Freedom" ], 5, 30, 5, 3, 99, 3000000, 1140, 543, 15, 2095, 1260, 99, 1 ], - [ "Mr. 7 & Miss Father's Day", "QCK", [ "Shooter", "Ambition" ], 4, 20, 6, 2, 70, 1778330, 68, 42, 105, 1085, 625, 315, 1 ], - [ "Tyrant Bartholomew Kuma", "STR", [ "Knowledge", "Tough" ], 4, 30, 4, 2, 70, 1066998, 260, 170, 90, 1201, 623, 190, 1 ], - [ "Tyrant Bartholomew Kuma, Government's Human Weapon", "STR", [ "Knowledge", "Tough" ], 5, 50, 7, 3, 99, 5000000, 1159, 572, 190, 3090, 1435, 90, 1 ], - [ "Caesar Clown", "DEX", [ "Ambition", "Knowledge" ], 4, 18, 5, 3, 70, 1066998, 71, 141, 71, 989, 740, 204, 1 ], - [ "Master Caesar", "DEX", [ "Ambition", "Knowledge" ], 5, 30, 4, 4, 99, 4000000, 941, 695, 177, 2000, 1383, 343, 1 ], - [ "Vergo", "INT", [ "Striker", "Tough" ], 4, 18, 6, 3, 70, 1066998, 282, 150, 19, 1515, 782, 89, 1 ], - [ "Vergo, Donquixote Pirates", "INT", [ "Striker", "Tough" ], 5, 30, 4, 4, 99, 4000000, 1464, 730, 60, 3003, 1410, 140, 1 ], - [ "Monet", "PSY", [ "Freedom", "Knowledge" ], 4, 18, 4, 3, 70, 1066998, 130, 87, 47, 1078, 593, 241, 1 ], - [ "Monet, Donquixote Pirates", "PSY", [ "Freedom", "Knowledge" ], 5, 30, 4, 4, 99, 4000000, 1020, 540, 199, 2131, 1001, 433, 1 ], - [ "Baby 5", "STR", [ "Shooter", "Striker" ], 4, 18, 5, 3, 70, 1066998, 114, 142, 53, 892, 743, 230, 1 ], - [ "Baby 5, Donquixote Pirates", "STR", [ "Shooter", "Striker" ], 5, 30, 6, 4, 99, 4000000, 850, 692, 185, 1929, 1352, 349, 1 ], - [ "Buffalo", "QCK", [ "Shooter", "Freedom" ], 4, 18, 9, 3, 70, 1066998, 96, 96, 49, 1111, 666, 196, 1 ], - [ "Buffalo, Donquixote Pirates", "QCK", [ "Shooter", "Freedom" ], 5, 30, 10, 4, 99, 4000000, 1050, 600, 173, 2769, 1096, 296, 1 ], - [ "Tom, Tom's Workers", "DEX", [ "Fighter", "Tough" ], 3, 12, 6, 1, 50, 392109, 159, 95, 30, 1103, 614, 141, 1 ], - [ "Legendary Shipwright Tom, Tom's Workers", "DEX", [ "Fighter", "Tough" ], 4, 20, 4, 2, 99, 3000000, 1059, 572, 100, 2207, 1029, 266, 1 ], - [ "Cutty Flam, Tom's Workers", "STR", [ "Shooter", "Ambition" ], 3, 13, 6, 2, 70, 1066998, 24, 138, 15, 924, 932, 139, 1 ], - [ "Iceburg, Tom's Workers", "QCK", [ "Striker", "Knowledge" ], 3, 13, 6, 2, 70, 1066998, 58, 60, 36, 1098, 694, 203, 1 ], - [ "Tin-Plate Wapol", "STR", [ "Shooter", "Ambition" ], 3, 12, 6, 2, 70, 1066998, 160, 78, 26, 1304, 800, 99, 1 ], - [ "Slim-up Wapol", "QCK", [ "Shooter", "Ambition" ], 4, 20, 5, 2, 99, 3000000, 837, 505, 95, 1923, 867, 247, 1 ], - [ "Robson", "PSY", [ "Fighter", "Tough" ], 3, 9, 6, 1, 50, 392109, 155, 22, 36, 1574, 318, 151, 1 ], - [ "Chopper Playing in the Snow", "DEX", [ "Fighter", "Tough" ], 4, 15, 5, 2, 99, 2000000, 130, 30, 50, 1920, 614, 293, 1 ], - [ "Trafalgar Law Holy Night Gentleman", "DEX", [ "Slasher", "Freedom" ], 4, 12, 6, 3, 50, 392109, 182, 93, 43, 995, 489, 198, 1 ], - [ "Trafalgar Law Holy Night Nobleman", "DEX", [ "Slasher", "Freedom" ], 5, 19, 4, 3, 99, 4000000, 945, 460, 151, 2003, 1030, 313, 1 ], - [ "Jewelry Bonney Ravenous Spoiled Santa", "PSY", [ "Fighter", "Freedom" ], 4, 12, 5, 3, 50, 392109, 190, 50, 54, 1003, 403, 213, 1 ], - [ "Jewelry Bonney Ravenous Greedy Santa", "PSY", [ "Fighter", "Freedom" ], 5, 19, 4, 3, 99, 4000000, 848, 354, 178, 2380, 769, 338, 1 ], - [ "Coby, Navy HQ Petty Officer", "PSY", [ "Fighter", "Ambition" ], 4, 18, 5, 2, 50, 392109, 267, 98, 27, 1193, 561, 158, 1 ], - [ "War Hero Coby, Navy HQ Petty Officer", "PSY", [ "Fighter", "Ambition" ], 5, 30, 4, 3, 99, 3000000, 1121, 500, 104, 2239, 1048, 261, 1 ], - [ "Lady Alvida, Lovely Beauty", "QCK", [ "Striker", "Freedom" ], 4, 18, 5, 1, 50, 392109, 240, 92, 31, 1030, 534, 197, 1 ], - [ "Lady Alvida, Peerless Beauty", "QCK", [ "Striker", "Freedom" ], 5, 30, 6, 3, 99, 3000000, 967, 466, 148, 2092, 1000, 307, 1 ], - [ "Snowy World Nami", "QCK", [ "Striker", "Knowledge" ], 4, 15, 5, 2, 99, 2000000, 77, 33, 78, 1459, 674, 349, 1 ], - [ "Boa Hancock, Captain of the Kuja Pirates", "PSY", [ "Shooter", "Freedom" ], 4, 30, 4, 2, 70, 1066998, 153, 138, 57, 1020, 633, 201, 1 ], - [ "Empress Boa Hancock, Captain of the Kuja Pirates", "PSY", [ "Shooter", "Freedom" ], 5, 50, 4, 3, 99, 5000000, 943, 589, 161, 2055, 1378, 375, 1 ], - [ "Nico Robin Cien Fleur Wing: The Storm", "INT", [ "Knowledge", "Slasher" ], 4, 15, 4, 2, 99, 2000000, 238, 203, 83, 1518, 1061, 290, 1 ], - [ "Usopp Tabasco Star: The Storm", "DEX", "Shooter", 4, 15, 7, 2, 99, 2000000, 258, 152, 94, 1866, 704, 343, 1 ], - [ "Tony Tony Chopper Heavy Gong: The Storm", "STR", [ "Tough", "Knowledge" ], 4, 15, 4, 2, 99, 2000000, 303, 168, 70, 2171, 900, 231, 1 ], - [ "Donquixote Doflamingo, Donquixote Pirates", "QCK", [ "Ambition", "Knowledge" ], 5, 30, 6, 4, 70, 1066998, 390, 311, 77, 1510, 830, 258, 1 ], - [ "Heavenly Yaksha Donquixote Doflamingo", "QCK", [ "Ambition", "Knowledge" ], 6, 55, 4, 4, 99, 5000000, 1446, 780, 230, 2800, 1530, 405, 1 ], - [ "Sugar", "QCK", [ "Freedom", "Knowledge" ], 4, 18, 4, 3, 70, 1066998, 102, 55, 68, 952, 420, 321, 1 ], - [ "Sugar, Donquixote Pirates", "QCK", [ "Freedom", "Knowledge" ], 5, 30, 5, 4, 99, 4000000, 896, 342, 274, 1905, 790, 532, 1 ], - [ "Señor Pink", "PSY", [ "Freedom", "Fighter" ], 4, 18, 4, 3, 70, 1066998, 292, 103, 24, 1524, 657, 142, 1 ], - [ "Señor Pink, Donquixote Pirates", "PSY", [ "Freedom", "Fighter" ], 5, 30, 4, 4, 99, 4000000, 1478, 600, 100, 2800, 1242, 241, 1 ], - [ "Trebol", "INT", [ "Knowledge", "Ambition" ], 4, 18, 5, 3, 70, 1066998, 103, 150, 42, 941, 770, 201, 1 ], - [ "Trebol, Donquixote Pirates", "INT", [ "Knowledge", "Ambition" ], 5, 30, 6, 4, 99, 4000000, 889, 721, 148, 1967, 1381, 334, 1 ], - [ "Jora", "DEX", [ "Freedom", "Ambition" ], 4, 18, 4, 3, 70, 1066998, 236, 66, 41, 1463, 494, 204, 1 ], - [ "Jora, Donquixote Pirates", "DEX", [ "Freedom", "Ambition" ], 5, 30, 4, 4, 99, 4000000, 1404, 443, 146, 2887, 880, 347, 1 ], - [ "Lao-G", "STR", [ "Fighter", "Ambition" ], 4, 18, 5, 3, 70, 1066998, 117, 129, 37, 1025, 783, 181, [ 1.5, 0.7, 1.5 ] ], - [ "Lao-G, Donquixote Pirates", "STR", [ "Fighter", "Ambition" ], 5, 30, 4, 4, 99, 4000000, 968, 721, 143, 2021, 1420, 293, [ 1.5, 0.7, 1.5 ] ], - [ "Scratchmen Apoo, Captain of the On Air Pirates", "QCK", [ "Shooter", "Freedom" ], 4, 25, 5, 2, 70, 1066998, 646, 261, 83, 1247, 693, 220, 1 ], - [ "Roar of the Sea Scratchmen Apoo, Captain of the On Air Pirates", "QCK", [ "Shooter", "Freedom" ], 5, 40, 4, 3, 99, 4000000, 1188, 639, 175, 2309, 1190, 351, 1 ], - [ "Dorry, Giant Warrior Pirates", "INT", [ "Slasher", "Tough" ], 4, 18, 6, 1, 50, 392109, 261, 120, 20, 1420, 503, 90, 1 ], - [ "Dorry the Blue Ogre", "INT", [ "Slasher", "Tough" ], 5, 30, 4, 3, 99, 3000000, 1366, 449, 64, 2640, 1000, 156, 1 ], - [ "Jimbe, Shark Soldier", "PSY", [ "Fighter", "Tough" ], 4, 20, 4, 2, 99, 3000000, 84, 34, 29, 1990, 1020, 298, 1 ], - [ "Mr. 1, West Blue Swordsman", "STR", [ "Slasher", "Knowledge" ], 4, 17, 6, 2, 99, 2000000, 45, 24, 19, 2024, 1044, 118, 1.5 ], - [ "Buggy, Cheerfully Crazy", "QCK", [ "Ambition", "Freedom" ], 4, 17, 5, 2, 99, 2000000, 32, 19, 30, 1790, 694, 285, 1.5 ], - [ "Hollow Hollow Ghost", "PSY", "Freedom", 2, 6, 4, 0, 35, 90778, 40, 20, 100, 150, 90, 190, 1 ], - [ "Perona, Thriller Bark's Mysterious Four", "DEX", [ "Shooter", "Ambition" ], 3, 12, 4, 1, 50, 392109, 59, 31, 38, 797, 392, 271, 1 ], - [ "Perona, Giant Ghost Princess", "DEX", [ "Shooter", "Ambition" ], 4, 20, 5, 3, 99, 3000000, 772, 381, 159, 1909, 960, 271, 1 ], - [ "Doctor Hogback, Thriller Bark's Mysterious Four", "INT", [ "Fighter", "Knowledge" ], 3, 15, 5, 2, 70, 1066998, 148, 75, 30, 1492, 535, 247, 1 ], - [ "Absalom of the Graveyard, Thriller Bark's Mysterious Four", "STR", [ "Shooter", "Tough" ], 3, 15, 6, 2, 70, 1066998, 156, 102, 13, 1803, 813, 96, 1 ], - [ "Oars, Special Zombie", "STR", [ "Fighter", "Tough" ], 4, 50, 4, 2, 99, 4000000, 1500, 700, 0, 2700, 1440, -500, 1 ], - [ "Gecko Moria, Shadow's Asgard", "INT", [ "Ambition", "Tough" ], 5, 30, 4, 3, 99, 4000000, 1000, 500, -500, 3180, 1430, -999, 1 ], - [ "Brook, Gentleman Skeleton", "DEX", [ "Slasher", "Freedom" ], 3, 10, 5, 1, 50, 392109, 148, 96, 37, 1067, 491, 196, 1 ], - [ "Brook, Straw Hat Pirates", "DEX", [ "Slasher", "Freedom" ], 4, 16, 6, 3, 99, 3000000, 1000, 442, 140, 1990, 847, 316, 1 ], - [ "Sir Crocodile, Sand General", "STR", [ "Knowledge", "Ambition" ], 4, 20, 5, 2, 99, 3000000, 89, 41, 24, 2142, 1149, 208, 1 ], - [ "Mr. 3, Makeshift Musician", "QCK", [ "Striker", "Knowledge" ], 4, 17, 4, 2, 99, 2000000, 24, 14, 33, 1703, 622, 312, 1.5 ], - [ "Mr. 2 Bon Clay, Dubious Samurai", "INT", [ "Fighter", "Freedom" ], 4, 17, 4, 2, 99, 2000000, 42, 20, 22, 1810, 804, 235, 1.5 ], - [ "Fresh Franky, Health Comes First", "DEX", [ "Shooter", "Freedom" ], 4, 25, 6, 2, 70, 1066998, 659, 244, 85, 1330, 659, 211, 1 ], - [ "Cyborg Franky", "DEX", [ "Shooter", "Freedom" ], 5, 40, 8, 3, 99, 4000000, 1269, 618, 167, 2515, 1172, 323, 1 ], - [ "Broggy, Giant Warrior Pirates", "PSY", [ "Slasher", "Tough" ], 4, 18, 5, 1, 50, 392109, 261, 120, 20, 1354, 539, 90, 1 ], - [ "Broggy the Red Ogre", "PSY", [ "Slasher", "Tough" ], 5, 30, 4, 3, 99, 3000000, 1292, 463, 64, 2460, 1090, 156, 1 ], - [ "Yokozuna", "STR", [ "Fighter", "Tough" ], 4, 20, 4, 2, 70, 1778330, 520, 170, 45, 1852, 700, 162, 1 ], - [ "Roronoa Zoro, the Swordsman Who Wanders Kuraigana Island", "STR", [ "Slasher", "Ambition" ], 4, 18, 6, 3, 70, 1066998, 200, 142, 15, 1492, 750, 101, 1 ], - [ "Roronoa Zoro, Pupil of the World's Strongest Swordsman", "STR", [ "Slasher", "Ambition" ], 5, 30, 5, 4, 99, 4000000, 1403, 687, 67, 2830, 1390, 190, 1 ], - [ "Nico Robin, Tequila Wolf Inmate", "INT", [ "Knowledge", "Fighter" ], 4, 18, 4, 3, 70, 1066998, 131, 91, 43, 1021, 679, 217, 1 ], - [ "Nico Robin, Light of the Revolution", "INT", [ "Knowledge", "Fighter" ], 5, 30, 4, 4, 99, 4000000, 946, 593, 178, 2011, 1156, 400, 1 ], - [ "Tony Tony Chopper, Torino Kingdom's Peace Mediator", "PSY", [ "Fighter", "Knowledge" ], 4, 18, 6, 3, 70, 1066998, 187, 70, 42, 1300, 504, 220, 1 ], - [ "Chopper Mask, the Hero Who Protects the World", "PSY", [ "Fighter", "Knowledge" ], 5, 30, 4, 4, 99, 4000000, 1234, 447, 170, 2500, 912, 404, 1 ], - [ "Sanji, Kamabakka Queendom Fugitive", "DEX", [ "Tough", "Fighter" ], 4, 18, 4, 3, 70, 1066998, 212, 124, 20, 1575, 701, 127, 1 ], - [ "Sanji, the Cook of Love Who Laid His Manliness on the Line", "DEX", [ "Tough", "Fighter" ], 5, 30, 4, 4, 99, 4000000, 1498, 634, 85, 2926, 1349, 201, 1 ], - [ "Brook, Harahetternia's Demon Lord", "QCK", [ "Freedom", "Slasher" ], 4, 18, 6, 3, 70, 1066998, 159, 90, 39, 1281, 597, 201, 1 ], - [ "Brook, BONE to be Wild!!!", "QCK", [ "Freedom", "Slasher" ], 5, 30, 4, 4, 99, 4000000, 1220, 531, 150, 2392, 1137, 352, 1 ], - [ "Nico Robin, Bride of Ohara", "QCK", [ "Knowledge", "Fighter" ], 4, 12, 4, 2, 50, null, 72, 38, 43, 899, 409, 105, 1 ], - [ "Beautiful and Talented Woman Wedding Robin", "QCK", [ "Knowledge", "Fighter" ], 5, 20, 4, 3, 99, null, 826, 327, 143, null, null, null, 0 ], - [ "Marguerite", "QCK", "Shooter", 3, 13, 4, 1, 50, 392109, 80, 53, 37, 920, 577, 207, 1 ], - [ "Marguerite, Warrior Defending Her Country", "QCK", "Shooter", 4, 20, 5, 2, 99, 3000000, 854, 516, 145, 1563, 1070, 335, 0 ], - [ "Aphelandra", "QCK", "Slasher", 3, 15, 6, 1, 70, 1066998, 98, 42, 32, 2001, 604, 141, 1 ], - [ "Sweet Pea", "STR", [ "Tough", "Shooter" ], 3, 15, 4, 2, 70, 1066998, 210, 157, 26, 1041, 1041, 155, 1 ] -]; \ No newline at end of file + [ "Monkey D. Luffy", "STR", "Fighter", 2, 1, 5, 0, 5, 163, 42, 15, 8, 134, 68, 15, 1 ], + [ "Monkey D. Luffy Gum-Gum Pistol", "STR", "Fighter", 3, 4, 6, 0, 20, 26184, 130, 76, 14, 510, 249, 49, 0.7 ], + [ "Monkey D. Luffy Gum-Gum Bazooka", "STR", "Fighter", 4, 7, 6, 2, 35, 136167, 404, 227, 39, 975, 522, 105, 1 ], + [ "Monkey D. Luffy Gear 2", "STR", [ "Fighter", "Free Spirit" ], 5, 15, 8, 3, 99, 3000000, 902, 473, 74, 1772, 1313, 227, 1 ], + [ "Roronoa Zoro", "DEX", "Slasher", 3, 4, 6, 0, 20, 26184, 126, 75, 15, 488, 239, 56, 0.7 ], + [ "Roronoa Zoro Three Thousand Worlds", "DEX", [ "Slasher", "Driven" ], 4, 7, 6, 2, 35, 136167, 426, 222, 37, 899, 515, 120, 1 ], + [ "Roronoa Zoro Pound Phoenix", "DEX", [ "Slasher", "Driven" ], 4, 9, 4, 2, 50, 392109, 462, 258, 37, 1216, 694, 106, 1 ], + [ "Roronoa Zoro Ashura Ichibugin", "DEX", [ "Slasher", "Driven" ], 5, 15, 9, 3, 99, 3000000, 724, 667, 39, 2232, 1332, 144, 1 ], + [ "Nami", "INT", "Striker", 3, 4, 4, 0, 20, 26184, 72, 51, 32, 366, 201, 89, 0.7 ], + [ "Nami Tornado Tempo", "INT", [ "Striker", "Cerebral" ], 4, 7, 5, 2, 35, 136167, 336, 192, 62, 783, 453, 160, 1 ], + [ "Nami Mirage Tempo", "INT", [ "Striker", "Cerebral" ], 4, 9, 5, 2, 50, 392109, 348, 201, 75, 840, 543, 219, 1 ], + [ "Nami Thunderbolt Tempo", "INT", [ "Striker", "Cerebral" ], 5, 15, 4, 3, 99, 3000000, 494, 437, 154, 1262, 1088, 387, 1 ], + [ "Usopp", "PSY", "Shooter", 3, 4, 5, 0, 20, 26184, 50, 32, 42, 322, 127, 121, 0.7 ], + [ "Usopp Tabasco Star", "PSY", "Shooter", 4, 7, 6, 2, 35, 136167, 286, 148, 85, 627, 240, 257, 1 ], + [ "Usopp Golden Pound", "PSY", "Shooter", 4, 9, 6, 2, 50, 392109, 444, 237, 47, 1080, 648, 144, 1 ], + [ "Sogeking", "PSY", "Shooter", 5, 15, 7, 3, 99, 3000000, 638, 260, 189, 1506, 690, 479, 1 ], + [ "Sanji", "QCK", "Fighter", 3, 4, 6, 0, 20, 26184, 136, 64, 17, 506, 218, 60, 1 ], + [ "Sanji Plastic Surgery Shot", "QCK", [ "Fighter", "Powerhouse" ], 4, 7, 5, 2, 35, 136167, 486, 207, 32, 907, 496, 125, 1 ], + [ "Chef Sanji Hot Rock Stew", "QCK", [ "Fighter", "Powerhouse" ], 4, 9, 4, 2, 50, 392109, 494, 191, 54, 986, 500, 209, 1 ], + [ "Sanji Diable Jambe Flambe", "QCK", [ "Fighter", "Powerhouse" ], 5, 15, 4, 3, 99, 3000000, 406, 418, 175, 2206, 1030, 249, 1 ], + [ "Tony Tony Chopper", "PSY", "Fighter", 3, 4, 5, 0, 20, 26184, 52, 40, 39, 294, 144, 120, 1 ], + [ "Tony Tony Chopper Heavy Point", "PSY", [ "Fighter", "Free Spirit" ], 4, 9, 5, 2, 50, 392109, 306, 213, 78, 754, 622, 207, 1 ], + [ "Tony Tony Chopper Brain Point", "INT", [ "Fighter", "Cerebral" ], 4, 9, 5, 2, 50, 392109, 258, 198, 91, 520, 454, 302, 1 ], + [ "Tony Tony Chopper Arm Point", "STR", [ "Fighter", "Powerhouse" ], 4, 9, 4, 2, 50, 392109, 356, 260, 54, 868, 820, 122, 1 ], + [ "Tony Tony Chopper Horn Point", "QCK", "Fighter", 4, 9, 6, 2, 50, 392109, 414, 306, 29, 958, 856, 95, 1 ], + [ "Tony Tony Chopper Guard Point", "DEX", [ "Fighter", "Powerhouse" ], 4, 9, 6, 2, 50, 392109, 394, 178, 75, 1320, 408, 184, 1 ], + [ "Higuma", "QCK", "Slasher", 2, 8, 5, 0, 35, 45389, 132, 87, 29, 692, 323, 99, 1 ], + [ "Master of the Near Sea", "STR", "Fighter", 2, 20, 5, 0, 35, 90778, 500, 350, 80, 550, 400, 100, 1.5 ], + [ "Iron-Mace Alvida", "STR", [ "Striker", "Powerhouse" ], 3, 10, 5, 0, 50, 392109, 184, 154, 5, 1412, 755, 61, 1 ], + [ "Iron-Mace Alvida Smooth-Smooth Fruit", "STR", [ "Striker", "Free Spirit" ], 4, 15, 6, 1, 99, 3000000, 766, 625, 135, 1668, 999, 369, 1 ], + [ "Coby", "PSY", "Fighter", 2, 4, 5, 0, 25, 50439, 70, 25, 32, 166, 70, 120, 1 ], + [ "Cabin Boy Coby", "PSY", [ "Fighter", "Driven" ], 3, 9, 5, 3, 50, 392109, 130, 49, 100, 524, 155, 216, 1 ], + [ "Helmeppo", "INT", "Shooter", 2, 4, 5, 0, 25, 50439, 62, 62, 21, 308, 242, 39, 1 ], + [ "Cabin Boy Helmeppo", "INT", [ "Fighter", "Driven" ], 3, 8, 5, 3, 50, 392109, 234, 210, 29, 770, 485, 130, 1 ], + [ "Axe-Hand Morgan", "STR", [ "Slasher", "Driven" ], 2, 9, 5, 0, 50, 261406, 133, 100, 5, 1554, 747, 35, 1 ], + [ "Mohji & Richie", "PSY", [ "Fighter", "Driven" ], 2, 9, 6, 1, 50, 261406, 150, 135, 10, 1072, 559, 55, 1 ], + [ "Cabaji the Acrobat", "DEX", [ "Slasher", "Driven" ], 2, 9, 6, 1, 50, 261406, 134, 77, 32, 824, 458, 130, 1 ], + [ "Buggy", "INT", [ "Slasher", "Driven" ], 3, 8, 5, 0, 35, 136167, 200, 107, 22, 818, 446, 85, 1 ], + [ "Buggy the Clown", "INT", [ "Slasher", "Driven" ], 4, 11, 5, 2, 70, 1066998, 714, 342, 58, 1666, 757, 135, 1 ], + [ "Gaimon", "PSY", "Shooter", 2, 3, 6, 0, 50, 261406, 133, 5, 14, 1303, 85, 121, 1.5 ], + [ "Siam", "INT", "Slasher", 2, 9, 6, 0, 50, 261406, 112, 112, 24, 724, 499, 133, 1 ], + [ "Butchie", "STR", [ "Slasher", "Powerhouse" ], 2, 9, 6, 0, 50, 261406, 132, 117, 19, 872, 530, 98, 1 ], + [ "One-Two Django", "DEX", "Slasher", 2, 8, 5, 0, 35, 90778, 118, 64, 39, 556, 271, 139, 1 ], + [ "Dancing Django", "DEX", "Slasher", 3, 11, 5, 2, 70, 1066998, 476, 218, 98, 1155, 555, 228, 1 ], + [ "Captain Kuro", "QCK", [ "Slasher", "Cerebral" ], 3, 10, 7, 0, 70, 1066998, 144, 111, 31, 1102, 640, 151, 1 ], + [ "Kuro of a Hundred Plans", "QCK", [ "Slasher", "Cerebral" ], 4, 15, 8, 2, 99, 3000000, 978, 558, 122, 2074, 1057, 282, 1 ], + [ "Yosaku", "STR", "Slasher", 2, 5, 6, 1, 40, 134812, 100, 43, 19, 439, 439, 99, 1.5 ], + [ "Johnny", "QCK", "Slasher", 2, 7, 6, 1, 40, 134812, 100, 42, 20, 421, 421, 108, 1.5 ], + [ "Iron Fist Fullbody", "STR", "Fighter", 2, 3, 6, 0, 15, 7532, 103, 100, 49, 153, 160, 84, 0.7 ], + [ "Patty", "STR", "Slasher", 2, 9, 5, 0, 50, 261406, 140, 65, 35, 872, 314, 170, 1 ], + [ "Carne", "QCK", "Slasher", 2, 9, 5, 0, 50, 261406, 94, 91, 34, 650, 428, 169, 1 ], + [ "Chef Zeff", "DEX", "Fighter", 3, 10, 5, 1, 50, 392109, 142, 118, 29, 908, 698, 164, 1.5 ], + [ "Gin", "QCK", "Shooter", 2, 8, 5, 0, 35, 90778, 148, 94, 24, 618, 363, 98, 1 ], + [ "Gin the Man-Demon", "QCK", "Striker", 3, 11, 6, 1, 70, 1066998, 558, 300, 57, 1152, 792, 209, 1 ], + [ "Pearl", "STR", [ "Striker", "Powerhouse" ], 2, 8, 5, 0, 35, 90778, 198, 84, 19, 956, 296, 64, 1 ], + [ "Fire Pearl", "STR", [ "Striker", "Powerhouse" ], 3, 11, 4, 1, 70, 1066998, 820, 226, 38, 1904, 656, 129, 1 ], + [ "Don Krieg", "INT", [ "Shooter", "Driven" ], 3, 10, 6, 0, 50, 392109, 214, 97, 24, 1454, 632, 95, 1 ], + [ "Don Krieg Poison Gas Bomb MH5", "INT", [ "Shooter", "Driven" ], 4, 15, 4, 2, 99, 3000000, 1276, 553, 74, 2734, 1057, 172, 1 ], + [ "Nezumi", "INT", [ "Shooter", "Cerebral" ], 2, 6, 6, 0, 30, 28779, 55, 55, 55, 150, 130, 204, 0.7 ], + [ "Momoo", "STR", "Fighter", 3, 18, 4, 0, 50, 392109, 600, 400, 120, 1000, 500, 150, 1.5 ], + [ "Choo", "INT", [ "Shooter", "Powerhouse" ], 3, 9, 5, 1, 50, 392109, 110, 71, 49, 768, 492, 256, 1 ], + [ "Kuroobi", "STR", [ "Fighter", "Powerhouse" ], 3, 9, 4, 1, 50, 392109, 160, 157, 10, 1200, 759, 76, 1 ], + [ "Hatchan", "DEX", [ "Slasher", "Powerhouse" ], 3, 8, 8, 1, 35, 136167, 88, 88, 47, 588, 387, 143, 1 ], + [ "Six-Sword Hachi", "DEX", [ "Slasher", "Powerhouse" ], 4, 11, 8, 2, 70, 1066998, 542, 338, 88, 986, 638, 288, 1 ], + [ "Arlong", "STR", [ "Slasher", "Powerhouse" ], 3, 10, 5, 0, 50, 392109, 104, 152, 24, 936, 930, 82, 1 ], + [ "Enraged Arlong Shark On Tooth", "STR", [ "Slasher", "Powerhouse" ], 4, 15, 4, 1, 99, 3000000, 832, 832, 55, 1974, 1491, 154, 1 ], + [ "Tashigi", "QCK", [ "Slasher", "Cerebral" ], 3, 9, 5, 1, 50, 392109, 102, 102, 41, 690, 483, 272, 1 ], + [ "Tashigi Navy HQ Ensign", "QCK", [ "Slasher", "Cerebral" ], 4, 15, 5, 2, 99, 3000000, 632, 431, 222, 1434, 921, 434, 1.5 ], + [ "Smoker", "DEX", [ "Striker", "Driven" ], 3, 9, 5, 1, 50, 392109, 110, 113, 36, 944, 575, 199, 1 ], + [ "Smoker the White Hunter", "DEX", [ "Striker", "Driven" ], 4, 15, 5, 2, 99, 3000000, 872, 515, 154, 1736, 1070, 334, 1.5 ], + [ "Miss Wednesday", "PSY", "Slasher", 3, 9, 5, 0, 35, 136167, 22, 10, 74, 190, 127, 216, 0.7 ], + [ "Nefertari Vivi", "PSY", "Slasher", 4, 13, 5, 1, 70, 1066998, 138, 102, 183, 682, 454, 350, 1 ], + [ "Princess Vivi", "PSY", [ "Slasher", "Free Spirit" ], 5, 20, 6, 3, 99, 4000000, 602, 414, 280, 908, 747, 477, 1.5 ], + [ "Portgas D. Ace", "QCK", [ "Fighter", "Free Spirit" ], 4, 13, 6, 3, 70, 1066998, 252, 144, 40, 1802, 545, 199, 1.5 ], + [ "Portgas D. Ace Flame Mirror", "QCK", [ "Fighter", "Free Spirit" ], 5, 20, 6, 4, 99, 4000000, 1728, 501, 140, 2886, 1020, 279, 1.5 ], + [ "Shanks", "PSY", [ "Slasher", "Cerebral" ], 4, 13, 5, 3, 70, 1066998, 186, 159, 46, 1010, 725, 271, 1.5 ], + [ "Red-Haired Shanks", "PSY", [ "Slasher", "Cerebral" ], 5, 20, 4, 4, 99, 4000000, 898, 670, 222, 2118, 990, 417, 1 ], + [ "Red Robber Penguin", "STR", "Evolver", 1, 1, 5, 0, 1, 0, 20, 10, 20, 20, 10, 20, 1 ], + [ "Blue Robber Penguin", "QCK", "Evolver", 1, 1, 5, 0, 1, 0, 20, 10, 20, 20, 10, 20, 1 ], + [ "Green Robber Penguin", "DEX", "Evolver", 1, 1, 5, 0, 1, 0, 20, 10, 20, 20, 10, 20, 1 ], + [ "Yellow Robber Penguin", "PSY", "Evolver", 1, 1, 5, 0, 1, 0, 20, 10, 20, 20, 10, 20, 1 ], + [ "Black Robber Penguin", "INT", "Evolver", 1, 1, 5, 0, 1, 0, 20, 10, 20, 20, 10, 20, 1 ], + [ "Rainbow Robber Penguin", "INT", "Evolver", 3, 1, 5, 0, 1, 0, 20, 20, 50, 20, 20, 50, 1 ], + [ "Red Pirate Penguin", "STR", "Evolver", 2, 3, 6, 0, 1, 0, 30, 20, 180, 30, 20, 180, 1 ], + [ "Blue Pirate Penguin", "QCK", "Evolver", 2, 3, 6, 0, 1, 0, 30, 20, 180, 30, 20, 180, 1 ], + [ "Green Pirate Penguin", "DEX", "Evolver", 2, 3, 6, 0, 1, 0, 30, 20, 180, 30, 20, 180, 1 ], + [ "Yellow Pirate Penguin", "PSY", "Evolver", 2, 3, 6, 0, 1, 0, 30, 20, 180, 30, 20, 180, 1 ], + [ "Black Pirate Penguin", "INT", "Evolver", 2, 3, 6, 0, 1, 0, 30, 20, 180, 30, 20, 180, 1 ], + [ "Red Hermit Crab", "STR", "Evolver", 1, 1, 5, 0, 1, 0, 50, 180, 0, 50, 180, 0, 1 ], + [ "Blue Hermit Crab", "QCK", "Evolver", 1, 1, 5, 0, 1, 0, 50, 180, 0, 50, 180, 0, 1 ], + [ "Green Hermit Crab", "DEX", "Evolver", 1, 1, 5, 0, 1, 0, 50, 180, 0, 50, 180, 0, 1 ], + [ "Yellow Hermit Crab", "PSY", "Evolver", 1, 1, 5, 0, 1, 0, 50, 180, 0, 50, 180, 0, 1 ], + [ "Black Hermit Crab", "INT", "Evolver", 1, 1, 5, 0, 1, 0, 50, 180, 0, 50, 180, 0, 1 ], + [ "Rainbow Hermit Crab", "INT", "Evolver", 2, 3, 5, 0, 1, 0, 50, 280, 0, 50, 150, 0, 1 ], + [ "Red Armored Crab", "STR", "Evolver", 2, 2, 5, 0, 1, 0, 50, 300, 0, 50, 300, 0, 1 ], + [ "Blue Armored Crab", "QCK", "Evolver", 2, 2, 5, 0, 1, 0, 50, 300, 0, 50, 300, 0, 1 ], + [ "Green Armored Crab", "DEX", "Evolver", 2, 2, 5, 0, 1, 0, 50, 300, 0, 50, 300, 0, 1 ], + [ "Yellow Armored Crab", "PSY", "Evolver", 2, 2, 5, 0, 1, 0, 50, 300, 0, 50, 300, 0, 1 ], + [ "Black Armored Crab", "INT", "Evolver", 2, 2, 5, 0, 1, 0, 50, 300, 0, 50, 300, 0, 1 ], + [ "Red Striped Dragon", "STR", "Evolver", 3, 12, 4, 0, 1, 0, 500, 500, 50, 500, 500, 50, 1 ], + [ "Blue Striped Dragon", "QCK", "Evolver", 3, 12, 4, 0, 1, 0, 500, 500, 50, 500, 500, 50, 1 ], + [ "Green Striped Dragon", "DEX", "Evolver", 3, 12, 4, 0, 1, 0, 500, 500, 50, 500, 500, 50, 1 ], + [ "Yellow Striped Dragon", "PSY", "Evolver", 3, 12, 4, 0, 1, 0, 500, 500, 50, 500, 500, 50, 1 ], + [ "Black Striped Dragon", "INT", "Evolver", 3, 12, 4, 0, 1, 0, 500, 500, 50, 500, 500, 50, 1 ], + [ "Red Treasure Turtle", "STR", "Booster", 3, 1, 6, 0, 1, 0, 100, 10, 10, 100, 10, 10, 1 ], + [ "Blue Treasure Turtle", "QCK", "Booster", 3, 1, 6, 0, 1, 0, 100, 10, 10, 100, 10, 10, 1 ], + [ "Green Treasure Turtle", "DEX", "Booster", 3, 1, 6, 0, 1, 0, 100, 10, 10, 100, 10, 10, 1 ], + [ "Yellow Treasure Turtle", "PSY", "Booster", 3, 1, 6, 0, 1, 0, 100, 10, 10, 100, 10, 10, 1 ], + [ "Black Treasure Turtle", "INT", "Booster", 3, 1, 6, 0, 1, 0, 100, 10, 10, 100, 10, 10, 1 ], + [ "Red Daimyo Turtle", "STR", "Booster", 4, 2, 5, 0, 1, 0, 500, 20, 20, 500, 20, 20, 1 ], + [ "Blue Daimyo Turtle", "QCK", "Booster", 4, 2, 5, 0, 1, 0, 500, 20, 20, 500, 20, 20, 1 ], + [ "Green Daimyo Turtle", "DEX", "Booster", 4, 2, 5, 0, 1, 0, 500, 20, 20, 500, 20, 20, 1 ], + [ "Yellow Daimyo Turtle", "PSY", "Booster", 4, 2, 5, 0, 1, 0, 500, 20, 20, 500, 20, 20, 1 ], + [ "Black Daimyo Turtle", "INT", "Booster", 4, 2, 5, 0, 1, 0, 500, 20, 20, 500, 20, 20, 1 ], + [ "Sea Pony", "PSY", "Evolver", 1, 2, 5, 0, 1, 0, 20, 20, 20, 20, 20, 10, 1 ], + [ "Sea Colt", "PSY", "Evolver", 2, 4, 5, 0, 1, 0, 50, 50, 50, 50, 50, 20, 1 ], + [ "Sea Horse", "PSY", "Evolver", 3, 6, 4, 0, 1, 0, 100, 100, 100, 100, 100, 40, 1 ], + [ "Sea Stallion", "PSY", "Evolver", 4, 8, 4, 0, 1, 0, 150, 150, 150, 150, 150, 60, 1 ], + [ "Sword Bandit", "DEX", "Slasher", 1, 1, 5, 0, 20, 8728, 77, 41, 9, 348, 140, 41, 1 ], + [ "Pistol Bandit", "STR", "Shooter", 1, 1, 5, 0, 20, 8728, 17, 14, 28, 105, 57, 104, 1 ], + [ "Fighter Group Cabin Boy Red Pirates", "STR", "Fighter", 1, 2, 6, 0, 10, 2330, 79, 54, 6, 327, 141, 17, 1 ], + [ "Fighter Group Cabin Boy Blue Pirates", "QCK", "Fighter", 1, 2, 6, 0, 10, 2330, 85, 51, 6, 349, 133, 16, 1 ], + [ "Fighter Group Cabin Boy Green Pirates", "DEX", "Fighter", 1, 2, 6, 0, 10, 2330, 85, 54, 5, 357, 138, 13, 1 ], + [ "Fighter Group Cabin Boy Yellow Pirates", "PSY", "Fighter", 1, 2, 6, 0, 10, 2330, 77, 49, 8, 315, 126, 24, 1 ], + [ "Fighter Group Cabin Boy Black Pirates", "INT", "Fighter", 1, 2, 6, 0, 10, 2330, 83, 61, 3, 345, 153, 10, 1 ], + [ "Slasher Group Cabin Boy Red Pirates", "STR", "Slasher", 1, 3, 6, 0, 15, 7532, 69, 47, 10, 333, 134, 28, 1 ], + [ "Slasher Group Cabin Boy Blue Pirates", "QCK", "Slasher", 1, 3, 6, 0, 15, 7532, 75, 41, 11, 347, 118, 31, 1 ], + [ "Slasher Group Cabin Boy Green Pirates", "DEX", "Slasher", 1, 3, 6, 0, 15, 7532, 69, 44, 11, 341, 115, 33, 1 ], + [ "Slasher Group Cabin Boy Yellow Pirates", "PSY", "Slasher", 1, 3, 6, 0, 15, 7532, 63, 38, 14, 325, 114, 35, 1 ], + [ "Slasher Group Cabin Boy Black Pirates", "INT", "Slasher", 1, 3, 6, 0, 15, 7532, 65, 49, 10, 341, 136, 25, 1 ], + [ "Striker Group Cabin Boy Red Pirates", "STR", "Striker", 1, 1, 6, 0, 10, 2330, 77, 49, 12, 281, 114, 27, 0.7 ], + [ "Striker Group Cabin Boy Blue Pirates", "QCK", "Striker", 1, 1, 6, 0, 10, 2330, 79, 45, 13, 281, 105, 30, 0.7 ], + [ "Striker Group Cabin Boy Green Pirates", "DEX", "Striker", 1, 1, 6, 0, 10, 2330, 73, 45, 14, 255, 103, 35, 0.7 ], + [ "Striker Group Cabin Boy Yellow Pirates", "PSY", "Striker", 1, 1, 6, 0, 10, 2330, 67, 42, 16, 253, 101, 36, 0.7 ], + [ "Striker Group Cabin Boy Black Pirates", "INT", "Striker", 1, 1, 6, 0, 10, 2330, 73, 57, 10, 261, 127, 26, 0.7 ], + [ "Shooter Group Cabin Boy Red Pirates", "STR", "Shooter", 1, 3, 6, 0, 10, 2330, 41, 19, 24, 129, 57, 78, 0.7 ], + [ "Shooter Group Cabin Boy Blue Pirates", "QCK", "Shooter", 1, 3, 6, 0, 10, 2330, 39, 17, 25, 125, 53, 80, 0.7 ], + [ "Shooter Group Cabin Boy Green Pirates", "DEX", "Shooter", 1, 3, 6, 0, 10, 2330, 37, 15, 26, 123, 51, 81, 0.7 ], + [ "Shooter Group Cabin Boy Yellow Pirates", "PSY", "Shooter", 1, 3, 6, 0, 10, 2330, 35, 13, 27, 107, 47, 85, 0.7 ], + [ "Shooter Group Cabin Boy Black Pirates", "INT", "Shooter", 1, 3, 6, 0, 10, 2330, 41, 22, 23, 139, 64, 74, 0.7 ], + [ "Cannoneer Cabin Boy", "INT", "Shooter", 1, 4, 5, 0, 20, 17456, 98, 80, 1, 523, 280, 3, 1 ], + [ "Fighter Group Crew Red Pirates", "STR", "Fighter", 2, 6, 5, 0, 30, 57558, 200, 103, 10, 707, 428, 29, 1 ], + [ "Fighter Group Crew Blue Pirates", "QCK", "Fighter", 2, 6, 5, 0, 30, 57558, 220, 93, 10, 727, 412, 31, 1 ], + [ "Fighter Group Crew Green Pirates", "DEX", "Fighter", 2, 6, 5, 0, 30, 57558, 212, 100, 9, 717, 417, 31, 1 ], + [ "Fighter Group Crew Yellow Pirates", "PSY", "Fighter", 2, 6, 5, 0, 30, 57558, 190, 90, 16, 695, 398, 41, 1 ], + [ "Fighter Group Crew Black Pirates", "INT", "Fighter", 2, 6, 5, 0, 30, 57558, 202, 108, 8, 695, 440, 27, 1 ], + [ "Slasher Group Crew Red Pirates", "STR", "Slasher", 2, 7, 5, 0, 35, 90778, 178, 90, 19, 645, 406, 79, 1 ], + [ "Slasher Group Crew Blue Pirates", "QCK", "Slasher", 2, 7, 5, 0, 35, 90778, 184, 75, 23, 659, 372, 88, 1 ], + [ "Slasher Group Crew Green Pirates", "DEX", "Slasher", 2, 7, 5, 0, 35, 90778, 162, 83, 24, 665, 375, 86, 1 ], + [ "Slasher Group Crew Yellow Pirates", "PSY", "Slasher", 2, 7, 5, 0, 35, 90778, 152, 73, 29, 629, 369, 94, 1 ], + [ "Slasher Group Crew Black Pirates", "INT", "Slasher", 2, 7, 5, 0, 35, 90778, 176, 100, 16, 695, 384, 78, 1 ], + [ "Striker Group Crew Red Pirates", "STR", "Striker", 2, 5, 5, 0, 25, 33626, 174, 85, 21, 473, 320, 71, 0.7 ], + [ "Striker Group Crew Blue Pirates", "QCK", "Striker", 2, 5, 5, 0, 25, 33626, 190, 74, 22, 483, 309, 73, 0.7 ], + [ "Striker Group Crew Green Pirates", "DEX", "Striker", 2, 5, 5, 0, 25, 33626, 176, 75, 24, 429, 318, 79, 0.7 ], + [ "Striker Group Crew Yellow Pirates", "PSY", "Striker", 2, 5, 5, 0, 25, 33626, 182, 69, 25, 439, 289, 87, 0.7 ], + [ "Striker Group Crew Black Pirates", "INT", "Striker", 2, 5, 5, 0, 25, 33626, 188, 87, 18, 465, 342, 65, 0.7 ], + [ "Shooter Group Crew Red Pirates", "STR", "Shooter", 2, 7, 5, 0, 30, 57558, 75, 23, 60, 289, 118, 202, 1 ], + [ "Shooter Group Crew Blue Pirates", "QCK", "Shooter", 2, 7, 5, 0, 30, 57558, 75, 20, 61, 299, 110, 203, 1 ], + [ "Shooter Group Crew Green Pirates", "DEX", "Shooter", 2, 7, 5, 0, 30, 57558, 65, 19, 63, 281, 113, 205, 1 ], + [ "Shooter Group Crew Yellow Pirates", "PSY", "Shooter", 2, 7, 5, 0, 30, 57558, 55, 15, 66, 227, 98, 219, 1 ], + [ "Shooter Group Crew Black Pirates", "INT", "Shooter", 2, 7, 5, 0, 30, 57558, 75, 29, 58, 299, 155, 198, 1 ], + [ "Cannoneer Skilled", "INT", "Shooter", 2, 12, 5, 0, 50, 261406, 203, 105, 3, 1350, 550, 30, 1 ], + [ "Bodyguard, \"Sunglasses\"", "DEX", "Shooter", 1, 4, 5, 0, 20, 8728, 115, 50, 30, 370, 180, 90, 0.7 ], + [ "Bearded Bodyguard", "QCK", "Shooter", 1, 4, 5, 0, 20, 8728, 105, 70, 25, 370, 210, 80, 0.7 ], + [ "Knuckle Punk Black Cat Pirates", "STR", "Fighter", 2, 6, 6, 0, 25, 33626, 30, 129, 2, 267, 612, 3, 1 ], + [ "Saber Punk Black Cat Pirates", "DEX", "Slasher", 2, 6, 5, 0, 25, 33626, 42, 120, 3, 295, 592, 5, 1 ], + [ "Halberd Punk Black Cat Pirates", "QCK", "Striker", 2, 6, 5, 0, 25, 33626, 32, 122, 4, 277, 598, 6, 1 ], + [ "Pistol Punk Black Cat Pirates", "PSY", "Shooter", 2, 6, 5, 0, 25, 33626, 30, 117, 6, 269, 569, 17, 1 ], + [ "Cannoneer Punk Black Cat Pirates", "INT", "Shooter", 2, 6, 5, 0, 25, 33626, 26, 137, 0, 267, 621, 0, 1 ], + [ "Fighter Group Leader", "STR", "Fighter", 3, 7, 6, 1, 40, 202218, 208, 97, 23, 982, 457, 104, 1 ], + [ "Slasher Group Leader", "DEX", "Slasher", 3, 7, 5, 1, 45, 286773, 166, 82, 35, 922, 397, 184, 1 ], + [ "Striker Group Leader", "QCK", "Striker", 3, 7, 5, 1, 35, 136167, 200, 80, 30, 828, 291, 135, 1 ], + [ "Shooter Group Leader", "PSY", "Shooter", 3, 7, 5, 1, 40, 202218, 128, 41, 55, 508, 253, 251, 1 ], + [ "Assassin Master", "INT", "Shooter", 3, 7, 5, 1, 50, 392109, 224, 119, 13, 1532, 557, 79, 1 ], + [ "Karate Fishman Arlong crewmember", "STR", "Fighter", 2, 7, 6, 0, 30, 57558, 70, 49, 24, 547, 258, 116, 0.7 ], + [ "Sword Fishman Arlong crewmember", "DEX", "Slasher", 2, 7, 5, 0, 30, 57558, 92, 44, 22, 585, 245, 114, 0.7 ], + [ "Spear Fishman Arlong crewmember", "QCK", "Striker", 2, 7, 5, 0, 30, 57558, 82, 46, 23, 553, 246, 119, 0.7 ], + [ "Pistol Fishman Arlong crewmember", "PSY", "Shooter", 2, 7, 5, 0, 30, 57558, 72, 36, 28, 523, 216, 134, 0.7 ], + [ "Knuckle Apprentice Navy", "STR", "Fighter", 1, 3, 6, 0, 15, 7532, 105, 66, 6, 317, 203, 17, 1 ], + [ "Saber Apprentice Navy", "DEX", "Slasher", 1, 4, 6, 0, 20, 17456, 45, 75, 13, 293, 194, 44, 1 ], + [ "Halberd Apprentice Navy", "QCK", "Striker", 1, 3, 6, 0, 15, 7532, 73, 70, 10, 305, 158, 34, 1 ], + [ "Pistol Apprentice Navy", "PSY", "Shooter", 1, 3, 6, 0, 15, 7532, 49, 16, 32, 105, 72, 96, 1 ], + [ "Cannoneer Apprentice Navy", "INT", "Shooter", 1, 5, 5, 0, 25, 33626, 93, 90, 0, 400, 350, 1, 1 ], + [ "Knuckle Seaman Navy", "STR", "Fighter", 2, 5, 5, 0, 25, 33626, 139, 96, 17, 523, 289, 43, 1 ], + [ "Saber Seaman Navy", "DEX", "Slasher", 2, 6, 5, 0, 35, 90778, 75, 101, 26, 512, 322, 84, 1 ], + [ "Halberd Seaman Navy", "QCK", "Striker", 2, 5, 5, 0, 25, 33626, 105, 92, 24, 407, 290, 62, 1 ], + [ "Pistol Seaman Navy", "PSY", "Shooter", 2, 6, 5, 0, 25, 33626, 75, 23, 52, 139, 100, 170, 1 ], + [ "Cannoneer Seaman Navy", "INT", "Shooter", 2, 10, 5, 0, 40, 134812, 143, 140, 1, 620, 660, 2, 1.5 ], + [ "Red Elder Turtle", "STR", "Booster", 5, 4, 4, 0, 1, 0, 1000, 30, 30, 1000, 30, 30, 1 ], + [ "Blue Elder Turtle", "QCK", "Booster", 5, 4, 4, 0, 1, 0, 1000, 30, 30, 1000, 30, 30, 1 ], + [ "Green Elder Turtle", "DEX", "Booster", 5, 4, 4, 0, 1, 0, 1000, 30, 30, 1000, 30, 30, 1 ], + [ "Yellow Elder Turtle", "PSY", "Booster", 5, 4, 4, 0, 1, 0, 1000, 30, 30, 1000, 30, 30, 1 ], + [ "Black Elder Turtle", "INT", "Booster", 5, 4, 4, 0, 1, 0, 1000, 30, 30, 1000, 30, 30, 1 ], + [ "Knuckle Ensign Navy HQ", "STR", "Fighter", 3, 9, 6, 1, 50, 392109, 474, 237, 30, 898, 490, 107, 1 ], + [ "Saber Ensign Navy HQ", "DEX", "Slasher", 3, 9, 6, 1, 50, 392109, 424, 229, 51, 800, 467, 131, 1 ], + [ "Halberd Ensign Navy HQ", "QCK", "Striker", 3, 9, 6, 1, 50, 392109, 400, 220, 48, 916, 442, 120, 1 ], + [ "Pistol Ensign Navy HQ", "PSY", "Shooter", 3, 9, 6, 1, 50, 392109, 121, 70, 145, 275, 191, 320, 1 ], + [ "Bazooka Ensign Navy HQ", "INT", "Shooter", 3, 12, 5, 1, 70, 1066998, 480, 460, 1, 1300, 850, 3, 1 ], + [ "Mr. 5 Nez-Palm Cannon", "STR", "Fighter", 3, 11, 5, 1, 35, 136167, 82, 142, 31, 752, 602, 124, 1 ], + [ "Mr. 5 Breeze Breath Bomb", "STR", "Shooter", 4, 15, 5, 2, 70, 1066998, 688, 520, 92, 1120, 943, 180, 1 ], + [ "Miss Valentine", "QCK", "Fighter", 3, 11, 5, 1, 35, 136167, 120, 114, 34, 860, 488, 144, 1 ], + [ "Miss Valentine 10,000 Kilo Guillotine", "QCK", "Fighter", 4, 15, 5, 2, 70, 1066998, 804, 426, 104, 1324, 787, 198, 1 ], + [ "Mr. 3", "INT", [ "Slasher", "Cerebral" ], 3, 11, 4, 1, 35, 136167, 196, 100, 26, 926, 515, 120, 1 ], + [ "Mr. 3 Extra Special Candelabra", "INT", [ "Slasher", "Cerebral" ], 4, 15, 4, 2, 70, 1066998, 600, 449, 120, 1394, 818, 176, 1 ], + [ "Miss Goldenweek", "DEX", [ "Striker", "Free Spirit" ], 3, 11, 5, 1, 35, 136167, 51, 51, 81, 301, 301, 305, 1 ], + [ "Miss Goldenweek Colors Trap: Calming Green", "DEX", [ "Striker", "Free Spirit" ], 4, 15, 5, 2, 70, 1066998, 264, 264, 268, 412, 390, 530, 1 ], + [ "Mr. 2 Bon Clay", "PSY", [ "Fighter", "Free Spirit" ], 3, 11, 5, 1, 35, 136167, 94, 93, 46, 690, 403, 201, 1 ], + [ "Mr. 2 Bon Clay Bombardier Arabesque", "PSY", [ "Fighter", "Free Spirit" ], 4, 15, 4, 2, 70, 1066998, 599, 348, 169, 935, 709, 302, 1 ], + [ "Miss All Sunday Baroque Works VP", "INT", [ "Fighter", "Cerebral" ], 4, 15, 6, 1, 50, 392109, 368, 128, 96, 772, 478, 252, 0.7 ], + [ "Nico Robin", "INT", [ "Fighter", "Cerebral" ], 5, 20, 6, 2, 99, 3000000, 736, 430, 214, 1865, 1055, 338, 1 ], + [ "Mr. 9", "QCK", "Striker", 2, 10, 5, 0, 35, 90778, 106, 88, 33, 490, 313, 136, 0.7 ], + [ "Mr. 9 Hot Blooded Bat", "QCK", "Striker", 3, 13, 5, 3, 70, 1066998, 408, 249, 99, 1011, 590, 240, 0.7 ], + [ "Laboon", "STR", [ "Fighter", "Powerhouse" ], 3, 18, 5, 1, 50, 392109, 650, 300, 150, 1100, 500, 200, 1 ], + [ "Laboon (Luffy's drawing)", "STR", [ "Fighter", "Powerhouse" ], 4, 22, 5, 2, 99, 3000000, 1000, 400, 160, 2500, 850, 250, 1 ], + [ "Neptunian Squid", "DEX", "Striker", 3, 18, 8, 1, 50, 392109, 600, 280, 130, 900, 480, 180, 1.5 ], + [ "Monkey D. Luffy, Gum-Gum Balloon", "STR", [ "Fighter", "Free Spirit" ], 4, 15, 6, 2, 50, 392109, 490, 178, 29, 1492, 655, 63, 1 ], + [ "Monkey D. Luffy, Gear Third", "STR", [ "Fighter", "Free Spirit" ], 5, 22, 4, 2, 99, 4000000, 1374, 585, 50, 2960, 1303, 105, 1 ], + [ "Roronoa Zoro, Streaming Wolf Swords", "DEX", [ "Slasher", "Driven" ], 4, 15, 5, 2, 50, 392109, 598, 136, 5, 1902, 582, 19, 1 ], + [ "Roronoa Zoro, Lion's Song", "DEX", [ "Slasher", "Driven" ], 5, 22, 6, 3, 99, 4000000, 1882, 538, 10, 3558, 1038, 32, 1 ], + [ "Nami, Fine Tempo", "INT", [ "Striker", "Cerebral" ], 4, 15, 5, 2, 50, 392109, 454, 133, 50, 1062, 421, 102, 1 ], + [ "Nami, Happiness Punch", "INT", [ "Striker", "Cerebral" ], 5, 22, 4, 3, 99, 4000000, 1044, 377, 94, 1990, 949, 168, 1 ], + [ "Usopp, Usopp Hammer", "PSY", "Striker", 3, 12, 5, 1, 35, 136167, 188, 101, 40, 778, 388, 191, 1 ], + [ "Usopp, Impact", "PSY", "Shooter", 4, 18, 6, 2, 70, 1066998, 733, 361, 97, 1185, 669, 265, 1 ], + [ "Mr. Prince, Mutton Shot", "QCK", [ "Fighter", "Cerebral" ], 3, 12, 4, 1, 35, 136167, 276, 108, 32, 1144, 457, 107, 1 ], + [ "Mr. Prince, Veau Shot", "QCK", [ "Fighter", "Cerebral" ], 4, 18, 5, 2, 70, 1066998, 1101, 422, 93, 1600, 792, 161, 1 ], + [ "Dracule Mihawk", "DEX", "Slasher", 4, 30, 4, 1, 70, 1066998, 324, 201, 1, 1998, 814, 7, 1 ], + [ "Hawk Eyes Mihawk", "DEX", "Slasher", 5, 50, 4, 1, 99, 5000000, 1916, 782, 5, 3760, 1285, 15, 1 ], + [ "Escapee Morgan", "STR", [ "Slasher", "Driven" ], 3, 17, 5, 1, 70, 711332, 1427, 699, 27, 1600, 1000, 35, 1 ], + [ "Double Crosser Django", "PSY", [ "Slasher", "Free Spirit" ], 3, 11, 5, 1, 70, 1066998, 446, 219, 103, 930, 665, 230, 1 ], + [ "Double Ironfist Fullbody", "STR", [ "Fighter", "Free Spirit" ], 3, 11, 6, 1, 70, 1066998, 150, 150, 80, 890, 809, 187, 1 ], + [ "Hina", "QCK", [ "Fighter", "Cerebral" ], 3, 12, 5, 1, 50, 392109, 154, 73, 42, 1176, 495, 187, 1 ], + [ "Black Cage Hina", "QCK", [ "Fighter", "Cerebral" ], 4, 18, 4, 2, 99, 3000000, 1088, 422, 149, 2270, 905, 300, 1 ], + [ "Mr. 8", "PSY", [ "Shooter", "Cerebral" ], 2, 10, 5, 0, 35, 90778, 178, 55, 32, 530, 248, 151, 1 ], + [ "Mr. 8 Igarappapa", "PSY", [ "Shooter", "Cerebral" ], 3, 13, 5, 1, 70, 1066998, 500, 186, 120, 1286, 433, 230, 1 ], + [ "Miss Monday", "STR", [ "Fighter", "Powerhouse" ], 2, 10, 4, 0, 35, 90778, 66, 126, 27, 350, 500, 97, 1 ], + [ "Miss Monday Superhuman Brass Knuckles", "STR", [ "Fighter", "Powerhouse" ], 3, 13, 4, 1, 70, 1066998, 270, 422, 71, 506, 1005, 186, 1 ], + [ "Knuckle Millions Baroque Works", "STR", "Fighter", 2, 5, 6, 0, 25, 33626, 185, 89, 21, 532, 352, 50, 1 ], + [ "Saber Millions Baroque Works", "DEX", "Slasher", 2, 5, 6, 0, 25, 33626, 161, 77, 29, 486, 294, 77, 1 ], + [ "Polearm Millions Baroque Works", "QCK", "Striker", 2, 5, 6, 0, 25, 33626, 197, 74, 24, 620, 278, 60, 1 ], + [ "Pistol Millions Baroque Works", "PSY", "Shooter", 2, 5, 6, 0, 25, 33626, 159, 51, 40, 476, 224, 102, 1 ], + [ "Bazooka Millions Baroque Works", "INT", "Shooter", 2, 5, 4, 0, 25, 33626, 203, 113, 10, 640, 388, 20, 1 ], + [ "Knuckle Billions Baroque Works", "STR", "Fighter", 3, 9, 5, 1, 50, 261406, 466, 301, 32, 850, 580, 85, 1 ], + [ "Saber Billions Baroque Works", "DEX", "Slasher", 3, 9, 5, 1, 50, 261406, 410, 257, 56, 798, 508, 120, 1 ], + [ "Halberd Billions Baroque Works", "QCK", "Striker", 3, 9, 5, 1, 50, 261406, 560, 230, 40, 996, 477, 95, 1 ], + [ "Pistol Billions Baroque Works", "PSY", "Shooter", 3, 9, 5, 1, 50, 261406, 402, 187, 82, 698, 400, 172, 1 ], + [ "Bazooka Billions Baroque Works", "INT", "Shooter", 3, 9, 4, 1, 50, 261406, 550, 319, 12, 1020, 655, 32, 1 ], + [ "Chopper Man", "PSY", "Fighter", 4, 10, 6, 5, 50, 130703, 250, 250, 125, 500, 500, 250, 1 ], + [ "Tony Tony Chopper Pre-Rampage", "STR", "Fighter", 4, 30, 6, 1, 70, 1066998, 280, 180, 300, 1808, 851, 0, 1 ], + [ "Tony Tony Chopper Post-Rampage", "STR", [ "Fighter", "Powerhouse" ], 5, 50, 4, 2, 99, 5000000, 1808, 851, -350, 3660, 1500, -900, 1 ], + [ "Marco", "PSY", [ "Fighter", "Powerhouse" ], 4, 18, 6, 3, 50, 392109, 172, 125, 64, 1030, 676, 220, 1 ], + [ "Marco the Phoenix", "PSY", [ "Fighter", "Powerhouse" ], 5, 28, 4, 4, 99, 4000000, 951, 618, 180, 2258, 1100, 390, 1 ], + [ "Jozu", "QCK", [ "Fighter", "Powerhouse" ], 4, 18, 4, 3, 50, 392109, 412, 109, 27, 1820, 596, 98, 1 ], + [ "Diamond Jozu", "QCK", [ "Fighter", "Powerhouse" ], 5, 28, 4, 4, 99, 4000000, 1748, 524, 69, 3300, 987, 231, 1 ], + [ "Vista", "INT", [ "Slasher", "Powerhouse" ], 4, 18, 5, 3, 50, 392109, 290, 206, 15, 1388, 806, 100, 1 ], + [ "Flower Sword Vista", "INT", [ "Slasher", "Powerhouse" ], 5, 28, 5, 4, 99, 4000000, 1314, 732, 72, 2840, 1325, 185, 1 ], + [ "Izo", "DEX", [ "Shooter", "Cerebral" ], 4, 18, 4, 3, 50, 392109, 232, 130, 50, 1300, 634, 172, 1 ], + [ "Flintlock Pistols Izo", "DEX", [ "Shooter", "Cerebral" ], 5, 28, 5, 4, 99, 4000000, 1224, 585, 136, 2550, 1068, 319, 1 ], + [ "Blamenco", "STR", [ "Striker", "Free Spirit" ], 4, 18, 4, 3, 50, 392109, 204, 192, 34, 1150, 775, 150, 1 ], + [ "Blamenco the Mallet", "STR", [ "Striker", "Free Spirit" ], 5, 28, 4, 4, 99, 4000000, 1086, 726, 112, 2488, 1252, 268, 1 ], + [ "Edward Newgate", "STR", [ "Striker", "Powerhouse" ], 5, 40, 4, 4, 70, 1422664, 1338, 522, 80, 3220, 1060, 156, 1 ], + [ "Whitebeard", "STR", [ "Striker", "Powerhouse" ], 6, 55, 4, 5, 99, 5000000, 3148, 978, 110, 3900, 1360, 235, 1 ], + [ "Training Coby", "PSY", [ "Striker", "Driven" ], 3, 12, 5, 1, 50, 261406, 90, 81, 55, 780, 514, 218, 0.7 ], + [ "Petty Officer Coby", "PSY", [ "Fighter", "Driven" ], 4, 18, 6, 2, 99, 3000000, 701, 485, 191, 1926, 984, 340, 1 ], + [ "Training Helmeppo", "INT", [ "Striker", "Driven" ], 3, 12, 5, 1, 50, 261406, 108, 93, 43, 890, 605, 185, 0.7 ], + [ "Sergeant Helmeppo", "INT", [ "Slasher", "Driven" ], 4, 18, 5, 2, 99, 3000000, 807, 555, 150, 1998, 1060, 260, 1 ], + [ "Rainbow Pirate Penguin", "INT", "Evolver", 4, 6, 6, 0, 1, 0, 200, 100, 300, 200, 100, 300, 1 ], + [ "Rainbow Striped Dragon", "INT", "Evolver", 4, 20, 4, 0, 1, 0, 1500, 800, 100, 1500, 800, 100, 1 ], + [ "White Chase Smoker", "DEX", [ "Striker", "Driven" ], 5, 20, 5, 3, 99, 2000000, 1644, 1012, 298, 2215, 1282, 338, 1.5 ], + [ "Armed Fighter Unit Red Pirates", "STR", "Fighter", 3, 12, 5, 1, 60, 449516, 644, 388, 19, 1055, 781, 33, 0.7 ], + [ "Armed Fighter Unit Blue Pirates", "QCK", "Fighter", 3, 12, 5, 1, 60, 449516, 679, 369, 21, 1106, 750, 36, 0.7 ], + [ "Armed Fighter Unit Green Pirates", "DEX", "Fighter", 3, 12, 5, 1, 60, 449516, 663, 380, 22, 1082, 770, 34, 0.7 ], + [ "Armed Fighter Unit Yellow Pirates", "PSY", "Fighter", 3, 12, 5, 1, 60, 449516, 622, 358, 35, 1030, 725, 58, 0.7 ], + [ "Armed Fighter Unit Black Pirates", "INT", "Fighter", 3, 12, 5, 1, 60, 449516, 633, 405, 18, 1044, 800, 30, 0.7 ], + [ "Armed Slasher Unit Red Pirates", "STR", "Slasher", 3, 12, 5, 1, 60, 449516, 583, 380, 69, 990, 658, 99, 0.7 ], + [ "Armed Slasher Unit Blue Pirates", "QCK", "Slasher", 3, 12, 5, 1, 60, 449516, 618, 339, 74, 1068, 592, 119, 0.7 ], + [ "Armed Slasher Unit Green Pirates", "DEX", "Slasher", 3, 12, 5, 1, 60, 449516, 602, 358, 80, 1017, 616, 122, 0.7 ], + [ "Armed Slasher Unit Yellow Pirates", "PSY", "Slasher", 3, 12, 5, 1, 60, 449516, 566, 333, 84, 944, 572, 149, 0.7 ], + [ "Armed Slasher Unit Black Pirates", "INT", "Slasher", 3, 12, 5, 1, 60, 449516, 590, 381, 59, 983, 660, 109, 0.7 ], + [ "Armed Striker Unit Red Pirates", "STR", "Striker", 3, 12, 5, 1, 60, 449516, 473, 320, 71, 946, 640, 142, 0.7 ], + [ "Armed Striker Unit Blue Pirates", "QCK", "Striker", 3, 12, 5, 1, 60, 449516, 483, 309, 73, 976, 618, 146, 0.7 ], + [ "Armed Striker Unit Green Pirates", "DEX", "Striker", 3, 12, 5, 1, 60, 449516, 429, 318, 79, 858, 636, 158, 0.7 ], + [ "Armed Striker Unit Yellow Pirates", "PSY", "Striker", 3, 12, 5, 1, 60, 449516, 439, 289, 87, 878, 578, 176, 0.7 ], + [ "Armed Striker Unit Black Pirates", "INT", "Striker", 3, 12, 5, 1, 60, 449516, 465, 342, 65, 930, 684, 130, 0.7 ], + [ "Armed Shooter Unit Red Pirates", "STR", "Shooter", 3, 12, 5, 1, 60, 449516, 271, 102, 180, 481, 355, 301, 0.7 ], + [ "Armed Shooter Unit Blue Pirates", "QCK", "Shooter", 3, 12, 5, 1, 60, 449516, 280, 96, 181, 530, 302, 312, 0.7 ], + [ "Armed Shooter Unit Green Pirates", "DEX", "Shooter", 3, 12, 5, 1, 60, 449516, 273, 99, 182, 502, 312, 314, 0.7 ], + [ "Armed Shooter Unit Yellow Pirates", "PSY", "Shooter", 3, 12, 5, 1, 60, 449516, 201, 88, 205, 427, 284, 348, 0.7 ], + [ "Armed Shooter Unit Black Pirates", "INT", "Shooter", 3, 12, 5, 1, 60, 449516, 280, 137, 174, 500, 400, 297, 0.7 ], + [ "Skilled Gunner", "INT", "Shooter", 3, 15, 5, 2, 70, 711332, 1280, 500, 20, 1550, 850, 40, 0.7 ], + [ "Mr. 13 & Ms. Friday The Unluckies", "INT", "Shooter", 3, 13, 7, 3, 50, 392109, 44, 44, 44, 596, 893, 130, 0.7 ], + [ "Dorry", "PSY", [ "Slasher", "Powerhouse" ], 4, 25, 4, 2, 70, 1422664, 450, 370, 102, 1662, 783, 153, 1.5 ], + [ "Broggy", "INT", [ "Slasher", "Powerhouse" ], 4, 25, 4, 2, 70, 1422664, 440, 411, 88, 1634, 875, 117, 1.5 ], + [ "Triceratops", "QCK", "Fighter", 2, 25, 4, 0, 50, 392109, 500, 200, 50, 965, 700, 50, 1.5 ], + [ "Rex", "STR", "Fighter", 2, 25, 4, 0, 50, 392109, 300, 300, 50, 520, 900, 50, 1.5 ], + [ "Brontosaurus", "DEX", "Fighter", 2, 25, 4, 0, 50, 392109, 400, 250, 50, 755, 755, 50, 1.5 ], + [ "Tsuru", "INT", [ "Shooter", "Cerebral" ], 3, 12, 4, 2, 50, 392109, 140, 26, 60, 880, 400, 266, 1 ], + [ "Great Advisor Tsuru", "INT", [ "Shooter", "Cerebral" ], 4, 18, 6, 3, 99, 4000000, 808, 337, 224, 1151, 1210, 366, 1 ], + [ "Momonga", "PSY", [ "Slasher", "Cerebral" ], 3, 11, 5, 2, 70, 1066998, 420, 398, 98, 632, 815, 255, 1 ], + [ "Onigumo", "DEX", [ "Slasher", "Driven" ], 3, 11, 8, 2, 70, 1066998, 482, 434, 63, 944, 920, 131, 1 ], + [ "Red Plated Lobster", "STR", "Evolver", 3, 7, 4, 0, 1, 0, 50, 550, 0, 50, 550, 0, 1 ], + [ "Blue Plated Lobster", "QCK", "Evolver", 3, 7, 4, 0, 1, 0, 50, 550, 0, 50, 550, 0, 1 ], + [ "Green Plated Lobster", "DEX", "Evolver", 3, 7, 4, 0, 1, 0, 50, 550, 0, 50, 550, 0, 1 ], + [ "Yellow Plated Lobster", "PSY", "Evolver", 3, 7, 4, 0, 1, 0, 50, 550, 0, 50, 550, 0, 1 ], + [ "Black Plated Lobster", "INT", "Evolver", 3, 7, 4, 0, 1, 0, 50, 550, 0, 50, 550, 0, 1 ], + [ "Monkey D. Garp", "PSY", [ "Fighter", "Powerhouse" ], 4, 30, 4, 1, 70, 1066998, 280, 145, 50, 1442, 722, 131, 1 ], + [ "Garp the Fist", "PSY", [ "Fighter", "Powerhouse" ], 5, 50, 4, 2, 99, 5000000, 1377, 685, 105, 2852, 1220, 225, 1 ], + [ "Trafalgar Law", "DEX", [ "Slasher", "Free Spirit" ], 4, 18, 4, 3, 70, 1066998, 104, 125, 73, 876, 702, 238, 1 ], + [ "Trafalgar Law, ROOM", "DEX", [ "Slasher", "Free Spirit" ], 5, 28, 4, 4, 99, 4000000, 817, 655, 190, 2052, 1300, 370, 1 ], + [ "Basil Hawkins", "INT", [ "Slasher", "Cerebral" ], 4, 18, 4, 3, 70, 1066998, 200, 200, 7, 1165, 750, 127, 1 ], + [ "Basil Hawkins the Magician", "INT", [ "Striker", "Cerebral" ], 5, 28, 6, 4, 99, 4000000, 1095, 717, 85, 2480, 1295, 255, 1 ], + [ "Killer", "QCK", [ "Striker", "Cerebral" ], 4, 18, 6, 3, 70, 1066998, 180, 250, 0, 1228, 895, -50, 1 ], + [ "Massacre Soldier Killer", "QCK", [ "Striker", "Cerebral" ], 5, 28, 4, 4, 99, 4000000, 1120, 811, 0, 2570, 1449, -200, 1 ], + [ "Urouge", "PSY", [ "Striker", "Powerhouse" ], 4, 18, 4, 3, 70, 1066998, 108, 108, 35, 1290, 798, 108, 1 ], + [ "Mad Monk Urouge", "PSY", [ "Striker", "Powerhouse" ], 5, 28, 5, 4, 99, 4000000, 1202, 730, 75, 2071, 1343, 200, 1 ], + [ "Bepo", "STR", [ "Fighter", "Powerhouse" ], 4, 18, 4, 3, 70, 1066998, 120, 105, 80, 820, 690, 246, 1 ], + [ "Bepo the Martial Artist", "STR", [ "Fighter", "Powerhouse" ], 5, 28, 6, 4, 99, 4000000, 755, 640, 198, 1880, 1200, 405, 1 ], + [ "Kalifa", "DEX", [ "Fighter", "Cerebral" ], 3, 12, 5, 1, 50, 392109, 116, 65, 51, 850, 540, 227, 1 ], + [ "Beautiful Secretary Kalifa", "DEX", [ "Fighter", "Cerebral" ], 4, 18, 6, 2, 99, 3000000, 788, 488, 177, 1728, 963, 378, 1 ], + [ "Paulie", "DEX", "Striker", 3, 12, 5, 1, 50, 392109, 162, 102, 31, 882, 705, 166, 1 ], + [ "Paulie Dock One Foreman/Mast Specialist", "DEX", "Striker", 4, 18, 4, 2, 99, 3000000, 812, 617, 130, 2300, 1070, 231, 1 ], + [ "Rob Lucci", "QCK", [ "Slasher", "Powerhouse" ], 3, 12, 4, 1, 50, 392109, 132, 126, 28, 1192, 721, 106, 1 ], + [ "Rob Lucci Dock One Sawyer, Treenail Specialist", "QCK", [ "Slasher", "Powerhouse" ], 4, 18, 6, 2, 99, 3000000, 1107, 654, 69, 2220, 1203, 177, 1 ], + [ "Kaku", "QCK", "Striker", 3, 12, 5, 1, 50, 392109, 172, 79, 37, 1233, 635, 131, 0.7 ], + [ "Kaku Dock One Carpentry Specialist", "QCK", [ "Striker", "Free Spirit" ], 4, 18, 4, 2, 99, 3000000, 1132, 552, 98, 2517, 988, 213, 0.7 ], + [ "Lulu", "QCK", "Shooter", 3, 12, 6, 2, 70, 1066998, 290, 168, 88, 985, 682, 223, 1 ], + [ "Wapol", "STR", [ "Fighter", "Free Spirit" ], 3, 8, 4, 1, 50, 392109, 330, 128, 20, 1440, 488, 98, 1 ], + [ "Wapol House", "STR", [ "Shooter", "Free Spirit" ], 4, 15, 4, 2, 99, 3000000, 1390, 423, 77, 2940, 835, 142, [ 1, 1, 0.7 ] ], + [ "Dalton", "QCK", [ "Slasher", "Cerebral" ], 3, 7, 5, 1, 35, 90778, 192, 110, 45, 751, 390, 140, 0.7 ], + [ "Dalton Bison", "QCK", [ "Slasher", "Cerebral" ], 4, 11, 4, 2, 70, 1066998, 690, 322, 102, 1155, 620, 290, 0.7 ], + [ "Chess", "DEX", "Shooter", 3, 7, 6, 0, 35, 90778, 186, 90, 31, 668, 296, 121, 1 ], + [ "Kuromarimo", "DEX", "Striker", 3, 7, 5, 0, 35, 90778, 72, 144, 24, 366, 488, 108, 1 ], + [ "Chessmarimo", "DEX", "Striker", 4, 11, 7, 2, 70, 1066998, 525, 396, 145, 1290, 840, 185, 1 ], + [ "Dr. Kureha", "PSY", [ "Slasher", "Cerebral" ], 3, 20, 5, 2, 50, 392109, 35, 32, 88, 200, 200, 510, 1.5 ], + [ "Lapin", "INT", "Fighter", 2, 15, 5, 0, 35, 90778, 200, 200, 25, 550, 550, 53, 1.5 ], + [ "Lapin Adult", "INT", [ "Fighter", "Powerhouse" ], 3, 20, 4, 2, 70, 1066998, 380, 480, 38, 1100, 950, 100, 1.5 ], + [ "Franky", "PSY", [ "Shooter", "Free Spirit" ], 3, 12, 4, 1, 50, 392109, 128, 128, 28, 1220, 680, 112, 1 ], + [ "Dismantler Franky", "PSY", [ "Shooter", "Free Spirit" ], 4, 20, 5, 2, 99, 3000000, 1138, 637, 71, 2453, 1032, 198, 1 ], + [ "Kiwi", "PSY", "Slasher", 3, 13, 4, 1, 50, 392109, 77, 77, 77, 777, 444, 265, 1 ], + [ "Mozu", "PSY", "Slasher", 3, 13, 4, 1, 50, 392109, 77, 77, 77, 555, 555, 265, 1 ], + [ "Kraken Surume", "STR", [ "Striker", "Powerhouse" ], 3, 12, 6, 1, 50, 392109, 99, 99, 188, 1440, 685, 133, 1 ], + [ "Kraken Monster of the North", "STR", [ "Striker", "Powerhouse" ], 4, 20, 8, 2, 99, 3000000, 1355, 602, 118, 2700, 1111, 33, 1 ], + [ "Red Jeweled Porc", "STR", "Booster", 2, 2, 4, 0, 10, 2330, 45, 27, 7, 129, 77, 15, 1 ], + [ "Blue Jeweled Porc", "QCK", "Booster", 2, 2, 4, 0, 10, 2330, 49, 21, 9, 145, 65, 19, 1 ], + [ "Green Jeweled Porc", "DEX", "Booster", 2, 2, 4, 0, 10, 2330, 47, 25, 8, 133, 72, 17, 1 ], + [ "Yellow Jeweled Porc", "PSY", "Booster", 2, 2, 4, 0, 10, 2330, 44, 19, 12, 120, 58, 28, 1 ], + [ "Black Jeweled Porc", "INT", "Booster", 2, 2, 4, 0, 10, 2330, 42, 30, 7, 119, 88, 14, 1 ], + [ "Ruby Jeweled Porc", "STR", "Booster", 3, 5, 4, 0, 1, 0, 169, 97, 22, 169, 97, 22, 1 ], + [ "Sapphire Jeweled Porc", "QCK", "Booster", 3, 5, 4, 0, 1, 0, 185, 85, 26, 185, 85, 26, 1 ], + [ "Emerald Jeweled Porc", "DEX", "Booster", 3, 5, 4, 0, 1, 0, 173, 92, 24, 173, 92, 24, 1 ], + [ "Topaz Jeweled Porc", "PSY", "Booster", 3, 5, 4, 0, 1, 0, 160, 78, 35, 160, 78, 35, 1 ], + [ "Amethyst Jeweled Porc", "INT", "Booster", 3, 5, 4, 0, 1, 0, 159, 108, 21, 159, 108, 21, 1 ], + [ "Zephyr", "INT", [ "Shooter", "Powerhouse" ], 4, 30, 7, 1, 70, 1066998, 320, 133, 4, 1588, 699, 29, 1 ], + [ "Zephyr, NEO Marines Leader", "INT", [ "Shooter", "Powerhouse" ], 5, 50, 4, 2, 99, 5000000, 1550, 680, 11, 3702, 1252, 88, 1 ], + [ "Ain", "QCK", [ "Shooter", "Cerebral" ], 3, 8, 6, 1, 35, 136167, 96, 87, 47, 688, 421, 195, 1 ], + [ "Ain NEO Marines", "QCK", [ "Shooter", "Cerebral" ], 4, 13, 4, 2, 70, 1066998, 620, 377, 155, 908, 679, 285, 1 ], + [ "Eustass Kid", "STR", [ "Striker", "Driven" ], 4, 18, 4, 3, 70, 1066998, 233, 141, 12, 1221, 721, 32, 1 ], + [ "Captain Kid", "STR", [ "Striker", "Driven" ], 5, 28, 4, 4, 99, 4000000, 1138, 651, 21, 3515, 1298, 69, 1 ], + [ "Scratchmen Apoo", "DEX", [ "Shooter", "Free Spirit" ], 4, 18, 5, 3, 70, 1066998, 209, 122, 39, 1126, 652, 184, 1 ], + [ "Roar of the Sea Scratchmen Apoo", "DEX", [ "Shooter", "Free Spirit" ], 5, 28, 5, 4, 99, 4000000, 1085, 580, 144, 2801, 1111, 300, 1 ], + [ "X Drake", "INT", [ "Striker", "Powerhouse" ], 4, 18, 5, 3, 70, 1066998, 242, 112, 32, 1515, 688, 88, 1 ], + [ "Red Flag X Drake", "INT", [ "Fighter", "Powerhouse" ], 5, 28, 6, 4, 99, 4000000, 1432, 611, 57, 3580, 1098, 132, 1 ], + [ "Jewelry Bonney", "PSY", [ "Fighter", "Free Spirit" ], 4, 18, 4, 3, 70, 1066998, 277, 80, 44, 1370, 440, 220, 1 ], + [ "Big Eater Jewelry Bonney", "PSY", [ "Fighter", "Free Spirit" ], 5, 28, 5, 4, 99, 4000000, 1248, 401, 158, 3000, 720, 400, 1 ], + [ "Capone Bege", "QCK", [ "Shooter", "Free Spirit" ], 4, 18, 6, 3, 70, 1066998, 199, 102, 34, 1050, 755, 153, 1 ], + [ "Capone Gang Bege", "QCK", [ "Shooter", "Free Spirit" ], 5, 28, 4, 4, 99, 4000000, 893, 682, 110, 2122, 1323, 313, 1 ], + [ "Silvers Rayleigh", "INT", [ "Fighter", "Cerebral" ], 5, 30, 4, 3, 70, 1066998, 488, 302, 168, 1518, 826, 309, 1 ], + [ "Dark King Rayleigh", "INT", [ "Fighter", "Cerebral" ], 6, 55, 4, 4, 99, 5000000, 1462, 777, 277, 3001, 1300, 500, 1 ], + [ "Giant Slasher Red Pirates", "STR", "Slasher", 2, 8, 6, 0, 30, 57558, 297, 163, 41, 579, 363, 41, 1.5 ], + [ "Giant Shooter Blue Pirates", "QCK", "Shooter", 2, 8, 4, 0, 30, 57558, 350, 129, 53, 619, 303, 68, 1.5 ], + [ "Giant Warrior Green Pirates", "DEX", "Striker", 2, 8, 4, 0, 30, 57558, 313, 155, 55, 561, 340, 77, 1.5 ], + [ "Giant Fighter Yellow Pirates", "PSY", "Fighter", 2, 8, 5, 0, 30, 57558, 308, 151, 52, 575, 332, 67, 1.5 ], + [ "Giant Striker Black Pirates", "INT", "Striker", 2, 8, 6, 0, 30, 57558, 330, 133, 42, 614, 313, 54, 1.5 ], + [ "Giant Imperial Slasher Red Pirates", "STR", "Slasher", 3, 13, 4, 1, 60, 674274, 490, 334, 46, 1179, 668, 109, 1.5 ], + [ "Giant Imperial Shooter Blue Pirates", "QCK", "Shooter", 3, 13, 4, 1, 60, 674274, 528, 281, 64, 1235, 562, 135, 1.5 ], + [ "Female Giant Imperial Warrior Green Pirates", "DEX", "Striker", 3, 13, 4, 1, 60, 674274, 472, 310, 72, 1132, 620, 143, 1.5 ], + [ "Giant Imperial Fighter Yellow Pirates", "PSY", "Fighter", 3, 13, 4, 1, 60, 674274, 488, 302, 61, 1170, 604, 132, 1.5 ], + [ "Giant Imperial Striker Black Pirates", "INT", "Striker", 3, 13, 4, 1, 60, 674274, 525, 311, 49, 1213, 622, 119, 1.5 ], + [ "Sea Cat", "PSY", "Fighter", 3, 10, 4, 1, 50, 392109, 77, 7, 33, 777, 77, 333, 1 ], + [ "Kung Fu Dugong", "STR", "Fighter", 3, 7, 5, 1, 20, 26184, 25, 225, 45, 50, 355, 95, 0.7 ], + [ "Kung Fu Dugong Faithful Apprentice", "STR", "Fighter", 4, 11, 8, 3, 50, 392109, 25, 305, 55, 75, 825, 225, 0.7 ], + [ "Banana Gator", "QCK", "Fighter", 3, 10, 4, 0, 50, 392109, 552, 334, 80, 922, 534, 155, 1 ], + [ "Sandora Dragon", "DEX", "Fighter", 3, 10, 4, 0, 50, 392109, 511, 285, 120, 811, 485, 190, 1 ], + [ "Mr. 0 Baroque Works CEO", "INT", [ "Striker", "Cerebral" ], 3, 10, 5, 2, 50, 392109, 194, 110, 23, 1088, 659, 147, 1.5 ], + [ "Sir Crocodile", "INT", [ "Striker", "Cerebral" ], 4, 18, 4, 3, 99, 3000000, 995, 582, 112, 2210, 1220, 208, 1.5 ], + [ "Hogback", "INT", [ "Fighter", "Cerebral" ], 3, 12, 6, 1, 50, 392109, 210, 72, 33, 1251, 595, 118, 1 ], + [ "Doctor Hogback", "INT", [ "Fighter", "Cerebral" ], 4, 20, 4, 2, 99, 3000000, 1180, 550, 72, 2741, 945, 189, 1 ], + [ "Cindry", "PSY", "Shooter", 3, 12, 5, 1, 50, 392109, 76, 58, 60, 806, 458, 259, 0.7 ], + [ "Victoria Cindry", "PSY", "Shooter", 4, 20, 4, 2, 99, 3000000, 622, 398, 231, 1402, 661, 478, 0.7 ], + [ "Emporio Ivankov", "QCK", [ "Fighter", "Free Spirit" ], 4, 30, 4, 3, 70, 1066998, 302, 125, 53, 1682, 512, 161, 1 ], + [ "Emporio Ivankov Queen of Kamabakka Queendom", "QCK", [ "Fighter", "Free Spirit" ], 5, 50, 4, 4, 99, 5000000, 1642, 470, 132, 3030, 1155, 290, 1 ], + [ "Perona", "DEX", [ "Shooter", "Driven" ], 3, 10, 4, 1, 50, 392109, 134, 44, 55, 944, 422, 222, 1 ], + [ "Ghost Princess Perona", "DEX", [ "Shooter", "Driven" ], 4, 18, 4, 2, 99, 3000000, 887, 377, 198, 1598, 791, 430, 1 ], + [ "Kumacy", "STR", [ "Fighter", "Powerhouse" ], 3, 11, 6, 1, 70, 1066998, 500, 255, 0, 1660, 904, 0, 1 ], + [ "Dog Penguin", "QCK", "Fighter", 3, 11, 4, 1, 50, 392109, 986, 500, 54, 1420, 722, 0, 1 ], + [ "Miss Merry Christmas", "QCK", "Fighter", 3, 11, 5, 1, 35, 136167, 220, 51, 42, 980, 422, 147, 1 ], + [ "Miss Merry Christmas Human Mole", "QCK", "Fighter", 4, 15, 4, 2, 70, 1066998, 910, 348, 113, 1401, 690, 233, 1 ], + [ "Mr. 4", "STR", [ "Shooter", "Powerhouse" ], 3, 11, 4, 1, 35, 136167, 250, 110, 14, 1046, 590, 80, 1 ], + [ "Mr. 4 and Lassoo the Dog-Gun", "STR", [ "Shooter", "Powerhouse" ], 4, 15, 6, 2, 70, 1066998, 980, 522, 43, 1606, 910, 110, 1 ], + [ "Miss Doublefinger", "DEX", [ "Striker", "Cerebral" ], 3, 11, 8, 1, 35, 136167, 115, 87, 44, 770, 501, 158, 1 ], + [ "Miss Doublefinger Human Spike", "DEX", [ "Striker", "Cerebral" ], 4, 15, 4, 2, 70, 1066998, 720, 435, 120, 1081, 701, 288, 1 ], + [ "Mr. 1", "STR", [ "Slasher", "Cerebral" ], 3, 11, 4, 1, 35, 136167, 255, 156, 1, 1152, 744, 10, 1 ], + [ "Mr. 1 Human Sword", "STR", [ "Slasher", "Cerebral" ], 4, 15, 5, 2, 70, 1066998, 1021, 652, 2, 1880, 1042, 15, 1 ], + [ "Rebecca", "QCK", "Slasher", 4, 14, 5, 2, 70, 1422664, 242, 115, 108, 1525, 707, 345, 1 ], + [ "Absalom", "STR", [ "Shooter", "Powerhouse" ], 3, 12, 6, 1, 50, 392109, 158, 93, 35, 1330, 602, 126, 1 ], + [ "Absalom of the Graveyard", "STR", [ "Shooter", "Powerhouse" ], 4, 20, 7, 2, 99, 3000000, 1271, 545, 77, 2601, 1008, 192, 1 ], + [ "General Zombie", "INT", "Fighter", 3, 12, 5, 1, 70, 1066998, 920, 352, 0, 2610, 605, 0, 1 ], + [ "Jigoro of the Wind", "DEX", "Slasher", 3, 9, 6, 1, 50, 392109, 426, 258, 37, 1348, 744, 0, 1 ], + [ "Sir Crocodile Warlord of the Sea", "INT", [ "Slasher", "Cerebral" ], 5, 30, 4, 4, 99, 4000000, 1088, 659, 147, 2980, 1380, 150, 1 ], + [ "Jinbe", "QCK", [ "Fighter", "Powerhouse" ], 4, 15, 4, 3, 70, 1066998, 266, 101, 35, 1590, 660, 118, 1 ], + [ "Jinbe, Warlord of the Sea", "QCK", [ "Fighter", "Powerhouse" ], 5, 30, 4, 4, 99, 4000000, 1522, 622, 70, 3055, 1092, 250, 1 ], + [ "Bartholomew Kuma", "STR", [ "Shooter", "Powerhouse" ], 4, 15, 4, 3, 70, 1066998, 290, 110, 33, 1525, 692, 118, 1 ], + [ "Bartholomew Kuma Warlord of the Sea", "STR", [ "Shooter", "Powerhouse" ], 5, 30, 4, 4, 99, 4000000, 1445, 644, 82, 2734, 1205, 262, 1 ], + [ "Gecko Moria", "INT", [ "Striker", "Driven" ], 4, 15, 4, 3, 70, 1066998, 355, 102, 15, 1928, 677, 33, 1 ], + [ "Gecko Moria Warlord of the Sea", "INT", [ "Striker", "Driven" ], 5, 30, 4, 4, 99, 4000000, 1845, 612, 33, 3900, 1120, 118, 1 ], + [ "Boa Hancock", "QCK", [ "Fighter", "Free Spirit" ], 5, 30, 4, 4, 70, 1066998, 416, 251, 197, 1595, 859, 340, 1 ], + [ "Boa Hancock Warlord of the Sea", "QCK", [ "Fighter", "Free Spirit" ], 6, 55, 4, 5, 99, 5000000, 1512, 782, 301, 2860, 1320, 515, 1 ], + [ "Donquixote Doflamingo", "DEX", [ "Slasher", "Driven" ], 4, 30, 4, 1, 70, 1066998, 200, 186, 30, 1061, 790, 145, 1 ], + [ "Donquixote Doflamingo, Warlord of the Sea", "DEX", [ "Slasher", "Driven" ], 5, 50, 5, 2, 99, 4000000, 932, 721, 118, 2311, 1500, 255, 1 ], + [ "Sanji Parage Shot: The Storm", "QCK", [ "Fighter", "Powerhouse" ], 4, 10, 5, 2, 99, 2000000, 486, 207, 32, 2015, 900, 217, 0.7 ], + [ "Monkey D. Luffy Gum-Gum Bazooka: Supremacy", "STR", [ "Fighter", "Free Spirit" ], 4, 15, 6, 2, 99, 2000000, 404, 227, 39, 1748, 1250, 192, 1 ], + [ "Roronoa Zoro Three Thousand Worlds: The Final Stroke", "DEX", [ "Slasher", "Driven" ], 4, 15, 6, 2, 99, 2000000, 426, 222, 37, 2175, 1188, 132, 1 ], + [ "Nami Mirage Tempo: The Heavens", "INT", [ "Striker", "Cerebral" ], 4, 15, 5, 2, 99, 2000000, 348, 201, 75, 1260, 988, 361, 1 ], + [ "Brook", "QCK", [ "Slasher", "Free Spirit" ], 3, 12, 5, 1, 50, 392109, 220, 43, 45, 1190, 430, 208, 1 ], + [ "Humming Swordsman Brook", "QCK", [ "Slasher", "Free Spirit" ], 4, 20, 4, 2, 99, 3000000, 1138, 368, 162, 2108, 980, 332, 1 ], + [ "Ryuma", "PSY", "Slasher", 4, 18, 5, 2, 99, 3000000, 1138, 368, 162, 2005, 1088, 162, 1 ], + [ "Masira", "STR", "Fighter", 3, 10, 4, 1, 50, 392109, 525, 212, 12, 1120, 655, 95, 1 ], + [ "Shoujou", "DEX", "Shooter", 3, 10, 4, 1, 50, 392109, 655, 132, 23, 1334, 401, 144, 1 ], + [ "Montblanc Cricket", "PSY", [ "Shooter", "Free Spirit" ], 3, 12, 4, 1, 50, 392109, 488, 145, 54, 1050, 525, 155, 1.5 ], + [ "South Bird and Forest Residents", "DEX", "Fighter", 3, 8, 6, 1, 50, 261406, 752, 383, 121, 929, 423, 161, 1.5 ], + [ "Bellamy", "DEX", [ "Fighter", "Driven" ], 3, 10, 4, 1, 35, 136167, 131, 152, 24, 769, 692, 89, 1 ], + [ "Bellamy the Hyena", "DEX", [ "Fighter", "Driven" ], 4, 15, 6, 2, 70, 1066998, 726, 600, 67, 1072, 986, 170, 1 ], + [ "Sarquiss", "QCK", "Slasher", 3, 10, 5, 1, 50, 392109, 220, 92, 22, 1440, 424, 68, 1 ], + [ "Elizabeth", "DEX", [ "Fighter", "Free Spirit" ], 4, 12, 4, 2, 70, 1422664, 881, 422, 155, 1485, 700, 198, 1.5 ], + [ "Caroline", "INT", [ "Fighter", "Free Spirit" ], 4, 18, 6, 2, 99, 3000000, 772, 389, 177, 1890, 915, 300, [ 1.5, 1.5, 0.7 ] ], + [ "Sanji Kamabakka Queendom Traditional Fighting Style", "QCK", "Fighter", 3, 10, 4, 2, 50, 392109, 221, 58, 29, 1229, 622, 130, [ 0.7, 0.7, 1.5 ] ], + [ "Sanji Candy", "QCK", [ "Fighter", "Free Spirit" ], 4, 18, 4, 3, 99, 3000000, 1155, 545, 76, 1802, 951, 357, [ 0.7, 0.7, 1.5 ] ], + [ "Perona - Sweets", "DEX", [ "Shooter", "Driven" ], 4, 11, 4, 2, 50, 392109, 168, 98, 58, 928, 412, 231, 1.5 ], + [ "Ghost Princess Perona - Sweets", "DEX", [ "Shooter", "Driven" ], 5, 20, 4, 3, 99, 3000000, 856, 359, 186, 1568, 741, 466, 1.5 ], + [ "Nefertari Vivi - Love", "PSY", [ "Slasher", "Free Spirit" ], 4, 11, 5, 2, 50, 392109, 138, 102, 183, 889, 358, 256, 1.5 ], + [ "Princess Vivi - Love", "PSY", [ "Slasher", "Free Spirit" ], 5, 20, 6, 3, 99, 3000000, 844, 297, 213, 1440, 683, 322, 1.5 ], + [ "Cowboy and Bourbon Jr. Supersonic Duck Squadron", "QCK", "Evolver", 3, 9, 5, 0, 35, 90778, 150, 80, 35, 755, 334, 155, 1 ], + [ "Stomp and Ivan X Supersonic Duck Squadron", "DEX", "Evolver", 3, 9, 5, 0, 35, 90778, 126, 98, 33, 719, 361, 152, 1 ], + [ "Centaur and Hikoichi Supersonic Duck Squadron", "STR", "Evolver", 3, 9, 5, 0, 35, 90778, 102, 119, 30, 693, 383, 149, 1 ], + [ "Karoo", "PSY", "Striker", 3, 6, 4, 1, 20, 26184, 178, 86, 40, 229, 155, 100, 1 ], + [ "Captain Karoo and the Supersonic Duck Squadron", "PSY", "Striker", 4, 18, 7, 2, 99, 3000000, 378, 383, 138, 1412, 702, 461, 1.5 ], + [ "Marshall D. Teach", "STR", [ "Shooter", "Driven" ], 4, 30, 6, 1, 70, 1066998, 235, 166, 30, 1402, 790, 23, 1 ], + [ "Blackbeard", "STR", [ "Shooter", "Driven" ], 5, 50, 4, 2, 99, 5000000, 1338, 744, 18, 3140, 1418, 83, 1 ], + [ "Thatch", "QCK", [ "Slasher", "Cerebral" ], 4, 18, 5, 3, 50, 522812, 208, 103, 63, 1246, 626, 188, 1 ], + [ "Twin-Blade Thatch", "QCK", [ "Slasher", "Cerebral" ], 5, 28, 4, 4, 99, 4000000, 1184, 575, 146, 2505, 1190, 302, 1 ], + [ "Namule", "DEX", [ "Fighter", "Powerhouse" ], 4, 18, 4, 3, 50, 522812, 155, 133, 40, 1081, 822, 142, 1 ], + [ "One-Hit Namule", "DEX", [ "Fighter", "Powerhouse" ], 5, 28, 4, 4, 99, 4000000, 999, 755, 117, 2398, 1303, 262, 1 ], + [ "Rakuyo", "PSY", [ "Striker", "Driven" ], 4, 18, 4, 3, 50, 522812, 161, 122, 65, 1000, 733, 193, 1 ], + [ "Morning Star Rakuyo", "PSY", [ "Striker", "Driven" ], 5, 28, 4, 4, 99, 4000000, 945, 681, 122, 2001, 1320, 337, 1 ], + [ "Fossa", "STR", [ "Slasher", "Driven" ], 4, 18, 4, 3, 50, 522812, 150, 160, 34, 1120, 831, 132, 1 ], + [ "Fossa the Blazing Katana", "STR", [ "Slasher", "Driven" ], 5, 28, 4, 4, 99, 4000000, 1059, 788, 95, 2454, 1388, 228, 1 ], + [ "Curiel", "INT", [ "Shooter", "Driven" ], 4, 18, 6, 3, 50, 522812, 202, 153, 48, 1159, 818, 134, 1 ], + [ "Heavy Artillery Curiel", "INT", [ "Shooter", "Driven" ], 5, 28, 5, 4, 99, 4000000, 1092, 762, 99, 2470, 1359, 252, 1 ], + [ "Sengoku", "PSY", [ "Fighter", "Cerebral" ], 5, 30, 4, 4, 70, 1066998, 610, 278, 157, 2020, 758, 228, 1 ], + [ "Sengoku the Buddha", "PSY", [ "Fighter", "Cerebral" ], 6, 54, 4, 5, 99, 5000000, 1962, 711, 191, 3429, 1338, 389, 1 ], + [ "Galdino the Criminal, Mr. 3", "PSY", [ "Slasher", "Cerebral" ], 3, 12, 4, 2, 70, 1066998, 588, 333, 133, 1033, 687, 233, 1 ], + [ "Escapee Bentham, Mr. 2 Bon Clay", "DEX", [ "Fighter", "Free Spirit" ], 3, 12, 5, 1, 50, 392109, 178, 104, 32, 980, 529, 187, 1 ], + [ "Master Escape Artist Bentham, Mr. 2 Bon Clay", "DEX", [ "Fighter", "Free Spirit" ], 4, 20, 4, 2, 99, 3000000, 921, 460, 146, 1830, 978, 323, 1 ], + [ "Satori", "PSY", [ "Shooter", "Cerebral" ], 4, 15, 4, 2, 70, 1066998, 479, 190, 158, 1422, 576, 272, 1 ], + [ "Shura", "INT", "Striker", 4, 15, 4, 2, 70, 1066998, 330, 420, 93, 1030, 1002, 175, 1 ], + [ "Gedatsu", "QCK", "Fighter", 4, 15, 4, 2, 70, 1066998, 622, 378, 53, 2020, 703, 108, 1 ], + [ "Braham", "DEX", [ "Shooter", "Free Spirit" ], 3, 15, 5, 1, 70, 1066998, 374, 283, 96, 1202, 684, 202, 1 ], + [ "Yama", "STR", "Fighter", 3, 13, 6, 1, 50, 392109, 800, 228, 1, 1700, 608, 2, 1 ], + [ "Yellow White Beret, Skypiea Guard", "PSY", "Shooter", 2, 3, 6, 0, 20, 17456, 51, 23, 45, 330, 166, 89, 1 ], + [ "Black White Beret, Skypiea Guard", "INT", "Shooter", 2, 3, 6, 0, 20, 17456, 49, 38, 40, 320, 197, 80, 1 ], + [ "Yellow White Beret Captain, Skypiea Guard", "PSY", "Shooter", 3, 9, 5, 1, 50, 261406, 270, 128, 69, 845, 433, 198, 1 ], + [ "Black White Beret Captain, Skypiea Guard", "INT", "Shooter", 3, 9, 5, 1, 50, 261406, 259, 142, 65, 837, 498, 177, 1 ], + [ "Eneru's Elect: Red Guard, Skypiea Enforcer", "STR", "Slasher", 2, 8, 6, 0, 50, 261406, 388, 202, 87, 890, 503, 121, 1 ], + [ "Eneru's Elect: Blue Guard, Skypiea Enforcer", "QCK", "Slasher", 2, 8, 6, 0, 50, 261406, 438, 155, 90, 962, 413, 139, 1 ], + [ "Eneru's Elect: Green Guard, Skypiea Enforcer", "DEX", "Slasher", 2, 8, 6, 0, 50, 261406, 410, 179, 88, 926, 464, 128, 1 ], + [ "Eneru's Elect: Yellow Guard, Skypiea Enforcer", "PSY", "Slasher", 2, 8, 6, 0, 50, 261406, 377, 140, 110, 859, 396, 170, 1 ], + [ "Eneru's Elect: Black Guard, Skypiea Enforcer", "INT", "Slasher", 2, 8, 6, 0, 50, 261406, 390, 200, 80, 912, 501, 115, 1 ], + [ "Red Striker, Skypiea Enforcer", "STR", "Striker", 2, 6, 4, 0, 30, 57558, 12, 55, 25, 311, 445, 70, 1 ], + [ "Blue Striker, Skypiea Enforcer", "QCK", "Striker", 2, 6, 4, 0, 30, 57558, 20, 47, 27, 343, 420, 73, 1 ], + [ "Green Striker, Skypiea Enforcer", "DEX", "Striker", 2, 6, 4, 0, 30, 57558, 16, 51, 26, 325, 435, 71, 1 ], + [ "Yellow Striker, Skypiea Enforcer", "PSY", "Striker", 2, 6, 4, 0, 30, 57558, 12, 47, 30, 322, 418, 80, 1 ], + [ "Black Striker, Skypiea Enforcer", "INT", "Striker", 2, 6, 4, 0, 30, 57558, 16, 54, 24, 329, 442, 68, 1 ], + [ "Red Striker Elite, Skypiea Enforcer", "STR", "Striker", 3, 12, 5, 1, 60, 449516, 243, 359, 45, 510, 804, 157, 1 ], + [ "Blue Striker Elite, Skypiea Enforcer", "QCK", "Striker", 3, 12, 5, 1, 60, 449516, 278, 340, 48, 562, 772, 159, 1 ], + [ "Green Striker Elite, Skypiea Enforcer", "DEX", "Striker", 3, 12, 5, 1, 60, 449516, 265, 350, 46, 536, 788, 158, 1 ], + [ "Yellow Striker Elite, Skypiea Enforcer", "PSY", "Striker", 3, 12, 5, 1, 60, 449516, 242, 338, 53, 505, 760, 166, 1 ], + [ "Black Striker Elite, Skypiea Enforcer", "INT", "Striker", 3, 12, 5, 1, 60, 449516, 250, 358, 45, 520, 802, 156, 1 ], + [ "Red Nomad, Shandian Warrior", "STR", "Striker", 2, 6, 5, 0, 30, 57558, 79, 45, 26, 494, 302, 87, 1 ], + [ "Blue Nomad, Shandian Warrior", "QCK", "Striker", 2, 6, 5, 0, 30, 57558, 92, 36, 30, 538, 268, 94, 1 ], + [ "Green Nomad, Shandian Warrior", "DEX", "Striker", 2, 6, 5, 0, 30, 57558, 85, 40, 28, 517, 289, 89, 1 ], + [ "Red Nomad Adept, Shandian Warrior", "STR", "Striker", 3, 12, 5, 1, 60, 449516, 438, 228, 60, 864, 642, 162, 1 ], + [ "Blue Nomad Adept, Shandian Warrior", "QCK", "Striker", 3, 12, 5, 1, 60, 449516, 460, 187, 63, 948, 570, 172, 1 ], + [ "Green Nomad Adept, Shandian Warrior", "DEX", "Striker", 3, 12, 5, 1, 60, 449516, 449, 201, 61, 900, 606, 168, 1 ], + [ "Yellow Hunter, Shandian Warrior", "PSY", "Shooter", 2, 5, 4, 0, 30, 57558, 38, 20, 41, 210, 115, 201, 1 ], + [ "Black Hunter, Shandian Warrior", "INT", "Shooter", 2, 5, 4, 0, 30, 57558, 40, 25, 39, 214, 128, 196, 1 ], + [ "Yellow Hunter Adept, Shandian Warrior", "PSY", "Shooter", 3, 11, 4, 1, 60, 449516, 150, 60, 160, 502, 258, 365, 1 ], + [ "Black Hunter Adept, Shandian Warrior", "INT", "Shooter", 3, 11, 4, 1, 60, 449516, 152, 66, 153, 508, 271, 359, 1 ], + [ "Portgas D. Ace, Mt. Corvo's Brothers 3", "QCK", [ "Fighter", "Free Spirit" ], 4, 10, 4, 2, 35, 90778, 144, 66, 60, 632, 347, 248, 0.7 ], + [ "Portgas D. Ace, Mt. Corvo's Brothers 3, Cup of Sworn Brotherhood", "QCK", [ "Fighter", "Free Spirit" ], 5, 18, 4, 3, 70, 1066998, 571, 295, 200, 1072, 559, 385, 0.7 ], + [ "Bellmere", "DEX", "Shooter", 3, 9, 5, 1, 35, 136167, 60, 39, 68, 426, 291, 283, 1 ], + [ "Bellmere, Nami and Nojiko's Mother", "DEX", "Shooter", 4, 15, 4, 2, 70, 1066998, 377, 249, 240, 810, 483, 400, 1 ], + [ "Kaya", "PSY", [ "Shooter", "Cerebral" ], 3, 9, 6, 1, 35, 136167, 115, 50, 72, 370, 180, 330, 1.5 ], + [ "Kaya, A rich young girl from Syrup Village", "PSY", [ "Shooter", "Cerebral" ], 4, 15, 5, 2, 70, 1066998, 331, 151, 275, 405, 250, 550, 1.5 ], + [ "Hotori and Kotori", "INT", "Fighter", 3, 9, 6, 1, 35, 136167, 242, 74, 27, 1055, 455, 122, 1 ], + [ "Hotori and Kotori, Skypiea Vice Head Enforcers", "INT", "Fighter", 4, 15, 4, 2, 70, 1066998, 989, 385, 92, 1959, 601, 151, 1 ], + [ "Pell", "QCK", [ "Slasher", "Powerhouse" ], 3, 9, 6, 1, 35, 136167, 175, 70, 40, 1000, 427, 142, 1 ], + [ "Pell, The guardian falcon of Alabasta", "QCK", [ "Slasher", "Powerhouse" ], 4, 15, 4, 2, 70, 1066998, 941, 358, 104, 1585, 695, 186, 1 ], + [ "Chaka", "STR", [ "Slasher", "Powerhouse" ], 3, 9, 5, 1, 35, 136167, 173, 120, 21, 822, 615, 109, 1 ], + [ "Chaka, The guardian jackal of Alabasta", "STR", [ "Slasher", "Powerhouse" ], 4, 15, 4, 2, 70, 1066998, 740, 531, 81, 1160, 923, 180, 1 ], + [ "Sir Crocodile, the Strongest Prisoner, Mr. 0, Ex-Baroque Works Leader", "QCK", [ "Striker", "Cerebral" ], 3, 13, 5, 1, 50, 392109, 213, 108, 24, 1161, 565, 135, 1 ], + [ "Sir Crocodile, the Strongest Prisoner, Ex-Seven Warlords Member", "QCK", [ "Striker", "Cerebral" ], 4, 20, 4, 2, 99, 3000000, 1101, 500, 100, 2200, 1150, 188, 1 ], + [ "Daz Bones, Convict, Mr. 1", "INT", [ "Slasher", "Cerebral" ], 4, 16, 4, 2, 70, 1066998, 255, 156, 242, 1710, 1011, 55, 1 ], + [ "Sabo Mt. Corvo's Brothers 3", "PSY", [ "Striker", "Free Spirit" ], 4, 10, 5, 2, 35, 90778, 32, 32, 32, 522, 288, 286, 0.7 ], + [ "Sabo Mt. Corvo's Brothers 3, Cup of Sworn Brotherhood", "PSY", [ "Striker", "Free Spirit" ], 5, 18, 4, 3, 70, 1066998, 440, 233, 242, 951, 460, 450, 0.7 ], + [ "Nico Robin Tropical", "INT", [ "Fighter", "Cerebral" ], 4, 15, 6, 2, 99, 2000000, 368, 128, 96, 1910, 715, 292, 1 ], + [ "Heracles-un", "PSY", [ "Shooter", "Cerebral" ], 4, 30, 6, 2, 70, 1066998, 330, 89, 34, 1698, 569, 160, 1 ], + [ "Heracles-un, Hero of the Forest", "PSY", [ "Shooter", "Cerebral" ], 5, 50, 4, 3, 99, 5000000, 1622, 480, 108, 3188, 1010, 300, 1 ], + [ "Usopp-un", "PSY", "Shooter", 4, 10, 5, 1, 50, 261406, 444, 237, 47, 1080, 648, 144, 1 ], + [ "Usopp-un, Hercules' Student", "PSY", [ "Shooter", "Powerhouse" ], 5, 20, 4, 5, 99, 2000000, 1280, 648, 0, 2550, 700, -41, 1 ], + [ "Monkey D. Luffy, Merveille's Adventurer", "STR", [ "Fighter", "Free Spirit" ], 4, 17, 4, 3, 70, 1066998, 242, 148, 28, 1505, 744, 106, 1 ], + [ "Monkey D. Luffy, Straw Hat Pirates' Attack", "STR", [ "Fighter", "Free Spirit" ], 5, 27, 8, 4, 99, 4000000, 1438, 676, 72, 2722, 1411, 176, 1 ], + [ "Sanji, Merveille's Adventurer", "INT", [ "Fighter", "Powerhouse" ], 4, 17, 4, 3, 70, 1066998, 268, 115, 32, 1545, 698, 122, 1 ], + [ "Sanji, Straw Hat Pirates' Attack", "INT", [ "Fighter", "Powerhouse" ], 5, 27, 5, 4, 99, 4000000, 1471, 630, 86, 2834, 1224, 226, 1 ], + [ "Nami, Merveille's Adventurer", "QCK", [ "Striker", "Cerebral" ], 4, 17, 5, 3, 70, 1066998, 190, 81, 57, 1051, 602, 230, 1 ], + [ "Nami and Billy the Thunder Bird", "QCK", [ "Striker", "Cerebral" ], 5, 27, 6, 4, 99, 4000000, 979, 540, 191, 1980, 1000, 455, 1 ], + [ "Brook, Merveille's Adventurer", "PSY", [ "Slasher", "Free Spirit" ], 4, 17, 6, 3, 70, 1066998, 249, 101, 40, 1530, 684, 133, 1 ], + [ "Brook, Straw Hat Pirates' Attack", "PSY", [ "Slasher", "Free Spirit" ], 5, 27, 4, 4, 99, 4000000, 1461, 636, 100, 2788, 1243, 234, 1 ], + [ "Chopper, Merveille's Adventurer", "DEX", [ "Shooter", "Cerebral" ], 4, 17, 5, 3, 70, 1066998, 196, 98, 51, 1170, 624, 212, 1 ], + [ "Chopper, Straw Hat Pirates' Attack", "DEX", [ "Shooter", "Cerebral" ], 5, 27, 4, 4, 99, 4000000, 1110, 571, 179, 2212, 1099, 368, 1 ], + [ "Shanks, Black Clad Redhead", "PSY", [ "Slasher", "Cerebral" ], 5, 30, 4, 4, 70, 1066998, 478, 285, 185, 1650, 780, 291, 1 ], + [ "Shanks, Black Clad Emperor", "PSY", [ "Slasher", "Cerebral" ], 6, 55, 5, 5, 99, 5000000, 1537, 736, 261, 3140, 1400, 418, 1 ], + [ "Nico Robin Cherry Blossoms Falling", "DEX", [ "Fighter", "Cerebral" ], 4, 11, 4, 2, 50, 392109, 171, 55, 65, 976, 328, 252, 1 ], + [ "Nico Robin Cherry Blossoms in Full Bloom", "DEX", [ "Fighter", "Cerebral" ], 5, 19, 6, 3, 99, 3000000, 913, 271, 209, 1925, 747, 384, 1 ], + [ "Brook Cherry Blossom Hair", "QCK", [ "Slasher", "Free Spirit" ], 4, 12, 5, 2, 50, 392109, 211, 108, 40, 1267, 448, 163, 1 ], + [ "Brook Cherry Blossom Melody", "QCK", [ "Slasher", "Free Spirit" ], 5, 20, 4, 3, 99, 3000000, 1199, 379, 131, 2311, 885, 281, 1 ], + [ "Nami Blossom Cloud", "DEX", [ "Shooter", "Cerebral" ], 4, 12, 5, 2, 50, 392109, 127, 53, 73, 812, 303, 287, 1 ], + [ "Nami Blossom Climate", "DEX", [ "Shooter", "Cerebral" ], 5, 20, 4, 3, 99, 3000000, 750, 247, 241, 1783, 670, 445, 1 ], + [ "Domino", "PSY", [ "Fighter", "Cerebral" ], 3, 13, 4, 1, 50, 392109, 32, 20, 80, 713, 366, 318, 1 ], + [ "Domino, Impel Down Vice Head Jailer", "PSY", [ "Fighter", "Cerebral" ], 4, 20, 5, 2, 99, 3000000, 634, 301, 265, 1800, 694, 449, 1 ], + [ "Minorhinoceros", "STR", [ "Striker", "Powerhouse" ], 3, 30, 6, 0, 70, 1066998, 1055, 655, 0, 2122, 815, -250, 1 ], + [ "Basilisk", "DEX", [ "Fighter", "Powerhouse" ], 3, 12, 4, 1, 70, 1066998, 612, 289, 31, 1525, 644, 128, 1 ], + [ "Ohm", "STR", [ "Slasher", "Cerebral" ], 4, 16, 4, 2, 70, 1066998, 770, 480, -600, 2200, 1050, -600, 1 ], + [ "Nola, Giant Snake", "PSY", [ "Fighter", "Powerhouse" ], 3, 20, 4, 1, 50, 392109, 1000, 180, 71, 2100, 455, 101, 0.7 ], + [ "Wyper", "DEX", [ "Shooter", "Free Spirit" ], 3, 9, 4, 2, 35, 136167, 212, 105, 20, 981, 567, 99, 1 ], + [ "Wyper, Descendant of Great Warrior Calgara", "DEX", [ "Shooter", "Free Spirit" ], 4, 15, 4, 3, 70, 1066998, 914, 490, 70, 1598, 804, 155, 1 ], + [ "Eneru", "PSY", [ "Shooter", "Driven" ], 3, 12, 4, 2, 50, 392109, 177, 141, 58, 951, 615, 185, 1 ], + [ "Kami Eneru", "PSY", [ "Shooter", "Driven" ], 4, 20, 4, 3, 99, 3000000, 880, 542, 143, 1530, 1290, 318, 1 ], + [ "Monkey D. Luffy, Mt. Corvo's Brothers 3", "STR", [ "Fighter", "Free Spirit" ], 4, 10, 4, 2, 35, 136167, 100, 28, 77, 551, 267, 261, 1 ], + [ "Monkey D. Luffy, Mt. Corvo's Brothers 3, Cup of Sworn Brotherhood", "STR", [ "Fighter", "Free Spirit" ], 5, 18, 4, 3, 70, 1778330, 479, 209, 231, 1058, 541, 397, 1 ], + [ "Sadie", "INT", [ "Striker", "Free Spirit" ], 3, 12, 4, 1, 50, 392109, 31, 60, 66, 681, 550, 263, 1 ], + [ "Sadie, Impel Down Chief Jailer", "INT", [ "Striker", "Free Spirit" ], 4, 20, 6, 2, 99, 3000000, 618, 488, 202, 1505, 997, 388, 1 ], + [ "Minokoala", "STR", [ "Fighter", "Powerhouse" ], 3, 30, 5, 0, 70, 1066998, 1400, 602, 0, 1977, 812, -100, 1 ], + [ "Manticore", "QCK", [ "Fighter", "Powerhouse" ], 3, 15, 4, 1, 70, 1066998, 313, 245, 24, 999, 770, 112, 1 ], + [ "Roronoa Zoro, Merveille's Adventurer", "DEX", [ "Slasher", "Driven" ], 4, 17, 5, 3, 70, 1066998, 270, 124, 23, 1585, 715, 98, 1 ], + [ "Roronoa Zoro, Straw Hat Pirates' Attack", "DEX", [ "Slasher", "Driven" ], 5, 27, 4, 4, 99, 4000000, 1531, 646, 60, 2900, 1321, 171, 1 ], + [ "Usopp, Merveille's Adventurer", "QCK", "Shooter", 4, 17, 6, 3, 70, 1066998, 224, 90, 47, 1222, 593, 208, 1 ], + [ "Usopp, Straw Hat Pirates' Attack", "QCK", "Shooter", 5, 27, 5, 4, 99, 4000000, 1167, 542, 174, 2301, 954, 376, 1 ], + [ "Nico Robin, Merveille's Adventurer", "INT", [ "Fighter", "Cerebral" ], 4, 17, 4, 3, 70, 1066998, 213, 96, 45, 1147, 626, 216, 1 ], + [ "Nico Robin, Straw Hat Pirates' Attack", "INT", [ "Fighter", "Cerebral" ], 5, 27, 4, 4, 99, 4000000, 1098, 551, 180, 2076, 1099, 400, 1 ], + [ "Franky, Merveille's Adventurer", "STR", [ "Shooter", "Free Spirit" ], 4, 17, 6, 3, 70, 1066998, 244, 140, 21, 1590, 738, 95, 1 ], + [ "Franky, Straw Hat Pirates' Attack", "STR", [ "Shooter", "Free Spirit" ], 5, 27, 5, 4, 99, 4000000, 1525, 660, 50, 2801, 1395, 161, 1 ], + [ "Portgas D. Ace, Black Clad Flame Fist", "DEX", [ "Shooter", "Free Spirit" ], 5, 30, 6, 4, 70, 1066998, 515, 264, 152, 1922, 758, 253, 1 ], + [ "Portgas D. Ace, Black Clad Division Commander", "DEX", [ "Shooter", "Free Spirit" ], 6, 55, 4, 5, 99, 5000000, 1877, 702, 214, 3818, 1352, 321, 1 ], + [ "Porche", "PSY", "Shooter", 3, 10, 6, 1, 50, 392109, 33, 29, 58, 536, 338, 300, 1 ], + [ "Capote", "QCK", "Striker", 3, 10, 5, 1, 50, 392109, 124, 48, 36, 1188, 482, 139, 1 ], + [ "Hamburg", "DEX", [ "Striker", "Powerhouse" ], 3, 10, 5, 1, 50, 392109, 103, 58, 32, 1024, 620, 122, 1 ], + [ "Pickles", "QCK", [ "Fighter", "Powerhouse" ], 3, 10, 4, 1, 50, 392109, 130, 51, 25, 1202, 603, 98, 1 ], + [ "Big Bun", "STR", [ "Slasher", "Powerhouse" ], 3, 15, 6, 1, 70, 1066998, 180, 105, 2, 1895, 850, 3, 1 ], + [ "Foxy", "INT", [ "Fighter", "Free Spirit" ], 3, 10, 5, 2, 35, 136167, 106, 51, 30, 788, 433, 175, 1 ], + [ "The Silver Fox Foxy", "INT", [ "Fighter", "Free Spirit" ], 4, 18, 5, 3, 70, 1066998, 725, 373, 144, 1212, 698, 266, 1 ], + [ "Monkey D. Luffy, Davy Back Fight: Afro", "STR", [ "Fighter", "Powerhouse" ], 3, 12, 6, 1, 50, 392109, 465, 232, 36, 984, 585, 110, 1.5 ], + [ "Monkey D. Luffy, Davy Back Fight: Combat", "STR", [ "Fighter", "Powerhouse" ], 4, 20, 4, 2, 99, 3000000, 862, 492, 70, 1978, 1170, 220, 1.5 ], + [ "Usopp, Davy Back Fight: Cornerman", "DEX", "Shooter", 4, 13, 5, 2, 70, 1066998, 61, 30, 75, 1361, 354, 310, 1 ], + [ "Tony Tony Chopper, Davy Back Fight: Mask", "PSY", [ "Fighter", "Cerebral" ], 3, 10, 4, 2, 70, 1066998, 83, 27, 70, 1176, 483, 280, 0.7 ], + [ "Aokiji", "INT", [ "Striker", "Free Spirit" ], 4, 30, 4, 2, 70, 1066998, 232, 160, 32, 1142, 712, 157, 1 ], + [ "Aokiji, Ice Human", "INT", [ "Striker", "Free Spirit" ], 5, 50, 4, 3, 99, 5000000, 1093, 644, 122, 2465, 1435, 251, 1 ], + [ "Tea Time Nami", "INT", [ "Striker", "Cerebral" ], 4, 18, 4, 2, 99, 2000000, 454, 133, 50, 1473, 703, 373, 0.7 ], + [ "Monkey D. Luffy, Voyage Log: Straw Hat Pirates", "STR", [ "Fighter", "Free Spirit" ], 5, 30, 4, 3, 70, 1066998, 390, 290, 150, 1559, 840, 290, 1.5 ], + [ "Monkey D. Luffy, Voyage Dream: Pirate King", "STR", [ "Fighter", "Free Spirit" ], 6, 55, 4, 4, 99, 5000000, 1490, 776, 250, 3440, 1430, 351, 1 ], + [ "Roronoa Zoro, Voyage Log: Straw Hat Pirates", "QCK", [ "Slasher", "Driven" ], 4, 12, 4, 2, 50, 392109, 230, 110, 35, 1388, 651, 132, 1 ], + [ "Roronoa Zoro, Voyage Dream: Master Swordsman", "QCK", [ "Slasher", "Driven" ], 5, 20, 4, 3, 99, 3000000, 1329, 777, 90, 2250, 1118, 201, 1 ], + [ "Genbou", "STR", [ "Shooter", "Free Spirit" ], 3, 15, 4, 1, 70, 1066998, 271, 91, 15, 1855, 711, 54, 0.7 ], + [ "Kamakiri", "QCK", [ "Striker", "Free Spirit" ], 3, 15, 5, 1, 70, 1066998, 195, 84, 30, 1669, 691, 101, 0.7 ], + [ "Raki", "INT", "Shooter", 4, 18, 4, 2, 99, 3000000, 158, 55, 51, 1544, 668, 460, 0.7 ], + [ "Aisa", "PSY", "Fighter", 3, 11, 5, 2, 50, 392109, 32, 15, 80, 223, 109, 475, 0.7 ], + [ "Nojiko", "PSY", [ "Striker", "Cerebral" ], 3, 9, 5, 1, 35, 136167, 125, 57, 60, 398, 277, 293, 1 ], + [ "Nojiko, Nami's Sister", "PSY", [ "Fighter", "Cerebral" ], 4, 15, 6, 2, 70, 1066998, 330, 233, 253, 709, 382, 438, 1 ], + [ "Crocus", "INT", [ "Striker", "Cerebral" ], 3, 9, 4, 1, 35, 136167, 202, 60, 41, 886, 301, 203, 1 ], + [ "Crocus, Twin Cape Lighthouse Keeper", "INT", [ "Striker", "Cerebral" ], 4, 15, 5, 2, 70, 1066998, 820, 249, 160, 1224, 509, 320, 1 ], + [ "Koza", "QCK", "Slasher", 3, 9, 5, 1, 35, 136167, 179, 69, 33, 939, 423, 158, 1 ], + [ "Koza, Rebel Leader", "QCK", "Slasher", 4, 15, 4, 2, 70, 1066998, 872, 375, 114, 1440, 681, 225, 1 ], + [ "Crimson Hime Turtle", "STR", "Booster", 6, 20, 6, 0, 1, 0, 2000, 100, 50, 2000, 100, 50, 1 ], + [ "Azure Hime Turtle", "QCK", "Booster", 6, 20, 6, 0, 1, 0, 2000, 100, 50, 2000, 100, 50, 1 ], + [ "Jade Hime Turtle", "DEX", "Booster", 6, 20, 6, 0, 1, 0, 2000, 100, 50, 2000, 100, 50, 1 ], + [ "Amber Hime Turtle", "PSY", "Booster", 6, 20, 6, 0, 1, 0, 2000, 100, 50, 2000, 100, 50, 1 ], + [ "Onyx Hime Turtle", "INT", "Booster", 6, 20, 6, 0, 1, 0, 2000, 100, 50, 2000, 100, 50, 1 ], + [ "Tony Tony Chopper, Voyage Log: Straw Hat Pirates", "STR", [ "Fighter", "Powerhouse" ], 4, 12, 4, 2, 50, 392109, 220, 95, 46, 1324, 589, 186, 0.7 ], + [ "Tony Tony Chopper, Voyage Dream: Great Doctor", "STR", [ "Fighter", "Powerhouse" ], 5, 20, 6, 3, 99, 3000000, 1280, 542, 151, 1980, 1002, 301, 0.7 ], + [ "Buggy, Pirate Apprentice", "INT", [ "Slasher", "Driven" ], 3, 12, 6, 1, 50, 392109, 155, 74, 42, 872, 411, 162, 1 ], + [ "Buggy, Roger Pirates", "INT", [ "Slasher", "Driven" ], 4, 19, 5, 2, 99, 3000000, 813, 358, 123, 1602, 709, 290, 1 ], + [ "Shanks, Pirate Apprentice", "PSY", [ "Slasher", "Free Spirit" ], 3, 12, 4, 1, 50, 392109, 155, 74, 42, 903, 488, 230, 1 ], + [ "Shanks, Roger Pirates", "PSY", [ "Slasher", "Free Spirit" ], 4, 18, 6, 3, 99, 3000000, 825, 440, 193, 1964, 920, 354, 1 ], + [ "Eneru, 200,000,000 Volt Amaru", "QCK", [ "Striker", "Driven" ], 4, 30, 6, 2, 70, 1066998, 155, 163, 38, 1369, 724, 128, 1 ], + [ "Eneru, Lightning Incarnate, 200,000,000 Volt Amaru", "QCK", [ "Striker", "Driven" ], 5, 50, 5, 3, 99, 5000000, 1288, 670, 90, 2524, 1470, 234, 1 ], + [ "Sanji Voyage Log: Straw Hat Pirates", "DEX", [ "Fighter", "Powerhouse" ], 4, 12, 4, 2, 50, 392109, 240, 103, 36, 1462, 620, 134, 0.7 ], + [ "Sanji Voyage Dream: All Blue", "DEX", [ "Fighter", "Powerhouse" ], 5, 20, 6, 3, 99, 3000000, 1413, 577, 100, 2350, 1052, 208, 0.7 ], + [ "Pirate Zeff", "DEX", [ "Fighter", "Powerhouse" ], 3, 13, 5, 1, 50, 392109, 185, 112, 24, 1210, 663, 128, 1 ], + [ "Red-Leg Zeff, Cook Pirates Captain", "DEX", [ "Fighter", "Powerhouse" ], 4, 20, 4, 2, 99, 3000000, 1152, 599, 81, 2000, 1088, 258, 1 ], + [ "Gangster Patty", "STR", "Shooter", 3, 10, 4, 1, 50, 522812, 155, 120, 25, 1080, 648, 132, 0.7 ], + [ "Gangster Carne", "QCK", "Slasher", 3, 10, 6, 1, 50, 522812, 153, 91, 35, 1054, 571, 162, 0.7 ], + [ "Hiking Bear", "INT", "Fighter", 2, 7, 5, 0, 35, 90778, 129, 32, 8, 1410, 225, 30, 0.7 ], + [ "Purinpurin", "PSY", "Shooter", 2, 7, 6, 0, 35, 90778, 38, 14, 29, 544, 194, 193, 0.7 ], + [ "Brook Voyage Log: Straw Hat Pirates", "DEX", [ "Slasher", "Free Spirit" ], 4, 12, 6, 2, 50, 392109, 208, 99, 29, 1326, 603, 168, 0.7 ], + [ "Brook Voyage Dream: Promised Meeting", "DEX", [ "Slasher", "Free Spirit" ], 5, 20, 6, 3, 99, 3000000, 1276, 560, 132, 2117, 1009, 279, 0.7 ], + [ "Zambai", "PSY", "Shooter", 3, 16, 4, 2, 70, 1066998, 230, 90, 48, 1580, 702, 168, 1 ], + [ "Demolisher Axeman", "STR", [ "Slasher", "Powerhouse" ], 3, 20, 6, 1, 60, 899032, 1200, 500, 15, 1500, 900, 35, 1.5 ], + [ "Demolisher Spearman", "STR", [ "Striker", "Powerhouse" ], 3, 20, 6, 1, 60, 899032, 1200, 500, 16, 1700, 800, 38, 1.5 ], + [ "Demolisher Gunner", "STR", [ "Shooter", "Powerhouse" ], 3, 20, 6, 1, 60, 899032, 1200, 500, 14, 1300, 1000, 32, 1.5 ], + [ "Street Punk: Brawler, Red Bounty Hunter", "STR", "Fighter", 3, 13, 6, 1, 60, 674274, 102, 85, 28, 1158, 790, 90, 1 ], + [ "Street Punk: Brawler, Green Bounty Hunter", "DEX", "Fighter", 3, 13, 6, 1, 60, 674274, 108, 75, 32, 1175, 754, 102, 1 ], + [ "Street Punk: Blade, Blue Bounty Hunter", "QCK", "Slasher", 3, 13, 5, 1, 60, 674274, 153, 66, 40, 1215, 653, 128, 1 ], + [ "Street Punk: Blade, Red Bounty Hunter", "STR", "Slasher", 3, 13, 5, 1, 60, 674274, 149, 73, 33, 1193, 690, 115, 1 ], + [ "Street Punk: Bullet, Green Bounty Hunter", "DEX", "Shooter", 3, 13, 5, 1, 60, 674274, 92, 45, 51, 938, 500, 255, 1 ], + [ "Street Punk: Bullet, Yellow Bounty Hunter", "PSY", "Shooter", 3, 13, 5, 1, 60, 674274, 86, 38, 55, 900, 467, 274, 1 ], + [ "Street Punk: Nails, Yellow Bounty Hunter", "PSY", "Striker", 3, 13, 4, 1, 60, 674274, 71, 102, 33, 878, 854, 119, 1 ], + [ "Street Punk: Nails, Black Bounty Hunter", "INT", "Striker", 3, 13, 4, 1, 60, 674274, 71, 108, 29, 877, 890, 107, 1 ], + [ "Street Punk: Gatling, Black Bounty Hunter", "INT", "Shooter", 3, 13, 6, 1, 60, 674274, 133, 90, 3, 1556, 765, 15, 1 ], + [ "Street Punk: Gatling, Blue Bounty Hunter", "QCK", "Shooter", 3, 13, 6, 1, 60, 674274, 150, 84, 5, 1602, 745, 16, 1 ], + [ "Tilestone", "STR", [ "Shooter", "Powerhouse" ], 3, 12, 4, 2, 70, 1066998, 153, 98, 30, 1521, 800, 101, 1 ], + [ "Franky, Franky Family", "INT", "Fighter", 3, 17, 5, 2, 70, 1066998, 203, 103, 23, 1712, 831, 85, 1 ], + [ "Kaku, Cipher Pol No. 9", "QCK", [ "Slasher", "Powerhouse" ], 3, 12, 5, 2, 50, 392109, 175, 80, 36, 1224, 643, 120, 1 ], + [ "Kaku: Six Powers, Cipher Pol No. 9", "QCK", [ "Slasher", "Powerhouse" ], 4, 20, 4, 3, 99, 3000000, 1144, 577, 93, 2523, 1000, 196, 1 ], + [ "Rob Lucci, Cipher Pol No. 9", "STR", [ "Fighter", "Powerhouse" ], 3, 12, 4, 2, 50, 392109, 121, 153, 20, 1121, 792, 64, 1 ], + [ "Rob Lucci: Six Powers, Cipher Pol No. 9", "STR", [ "Fighter", "Powerhouse" ], 4, 20, 6, 3, 99, 3000000, 1064, 743, 51, 2284, 1289, 134, 1 ], + [ "Camie", "QCK", "Fighter", 3, 12, 4, 1, 50, 392109, 90, 23, 62, 960, 352, 273, [ 0.7, 1, 0.7 ] ], + [ "Camie, Takoyaki Shop Clerk", "QCK", "Fighter", 4, 18, 5, 2, 99, 3000000, 900, 295, 231, 1731, 698, 455, 0.7 ], + [ "Pappagu", "INT", "Fighter", 3, 12, 5, 1, 50, 392109, 77, 30, 77, 895, 505, 214, 0.7 ], + [ "Hatchan, Takoyaki Shop Manager", "PSY", [ "Slasher", "Powerhouse" ], 3, 16, 6, 2, 99, 3000000, 134, 88, 41, 1788, 888, 187, 0.7 ], + [ "Doma", "QCK", "Slasher", 4, 18, 4, 3, 70, 1066998, 89, 144, 43, 1098, 733, 187, 0.7 ], + [ "Bohemian Knight Doma", "QCK", "Slasher", 5, 29, 4, 4, 99, 4000000, 1020, 695, 150, 2134, 1268, 328, 0.7 ], + [ "DeCalvan Brothers", "DEX", "Fighter", 4, 18, 6, 3, 70, 1066998, 240, 89, 28, 1880, 668, 73, 0.7 ], + [ "DeCalvan Brothers, Brothers' Bond", "DEX", "Fighter", 5, 29, 5, 4, 99, 4000000, 1824, 602, 50, 3330, 1183, 158, 0.7 ], + [ "Squard", "PSY", [ "Striker", "Powerhouse" ], 4, 18, 5, 3, 70, 1066998, 198, 190, 0, 1351, 810, 0, 0.7 ], + [ "Maelstrom Spider Squard", "PSY", [ "Striker", "Powerhouse" ], 5, 29, 5, 4, 99, 4000000, 960, 755, -1, 2755, 1434, -150, 0.7 ], + [ "Whitey Bay", "INT", [ "Slasher", "Driven" ], 4, 18, 5, 3, 70, 1066998, 109, 93, 44, 1140, 600, 223, 0.7 ], + [ "Ice Witch Whitey Bay", "INT", [ "Slasher", "Driven" ], 5, 29, 5, 4, 99, 4000000, 1094, 561, 171, 2278, 993, 399, 0.7 ], + [ "Little Oars Jr.", "STR", [ "Shooter", "Powerhouse" ], 4, 20, 6, 3, 70, 1066998, 251, 166, 1, 1900, 734, 3, 0.7 ], + [ "Little Oars Jr., Charging!", "STR", [ "Shooter", "Powerhouse" ], 5, 30, 4, 4, 99, 4000000, 1533, 801, 2, 4000, 1300, 9, 0.7 ], + [ "Marco, Whitebeard 1st Div. Commander", "QCK", [ "Fighter", "Powerhouse" ], 5, 30, 4, 4, 50, 392109, 455, 268, 177, 1612, 777, 303, 0.7 ], + [ "Marco the Phoenix Whitebeard 1st Div. Commander", "QCK", [ "Fighter", "Powerhouse" ], 6, 55, 4, 5, 99, 5000000, 1555, 734, 258, 3013, 1402, 455, 0.7 ], + [ "Nami Voyage Log: Straw Hat Pirates", "INT", [ "Striker", "Cerebral" ], 4, 12, 4, 2, 50, 392109, 143, 65, 50, 998, 498, 254, 0.7 ], + [ "Nami Voyage Dream: World Map", "INT", [ "Striker", "Cerebral" ], 5, 20, 4, 3, 99, 3000000, 922, 434, 198, 1890, 900, 380, 0.7 ], + [ "Iron Mask Duval", "DEX", [ "Shooter", "Driven" ], 3, 10, 4, 1, 35, 226945, 132, 133, 25, 725, 505, 77, 1 ], + [ "Duval, Flying Fish Riders Leader", "DEX", [ "Shooter", "Driven" ], 4, 30, 5, 2, 60, 1123790, 664, 424, 44, 1448, 723, 103, 1 ], + [ "Duval, Rosy Life Riders Leader", "DEX", [ "Shooter", "Free Spirit" ], 5, 50, 8, 3, 99, 5000000, 1420, 658, 103, 2608, 1113, 308, 1 ], + [ "Arlong the Pirate", "STR", [ "Slasher", "Powerhouse" ], 3, 12, 6, 1, 50, 392109, 159, 144, 14, 1332, 700, 89, 1 ], + [ "Arlong, Sun Pirates", "STR", [ "Slasher", "Powerhouse" ], 4, 20, 4, 2, 99, 3000000, 1261, 633, 45, 2020, 1389, 171, 1 ], + [ "Kuroobi, Sun Pirates", "STR", [ "Fighter", "Powerhouse" ], 3, 10, 6, 1, 50, 392109, 160, 103, 9, 1233, 744, 70, 1 ], + [ "Choo, Sun Pirates", "INT", [ "Shooter", "Powerhouse" ], 3, 10, 5, 1, 50, 392109, 75, 72, 22, 1002, 552, 178, 1 ], + [ "Monkey D. Luffy Swim Ring", "QCK", "Fighter", 4, 15, 6, 2, 99, 2000000, 144, 69, 31, 2232, 933, 242, 1 ], + [ "Usopp Voyage Log: Straw Hat Pirates", "QCK", "Striker", 4, 12, 6, 2, 50, 392109, 155, 67, 47, 1085, 513, 235, 0.7 ], + [ "Usopp Voyage Dream: Brave Sea Warrior", "QCK", "Striker", 5, 20, 4, 3, 99, 3000000, 1024, 468, 185, 2012, 938, 344, 0.7 ], + [ "Nami Holiday", "PSY", [ "Striker", "Cerebral" ], 4, 15, 5, 2, 99, 2000000, 70, 30, 100, 1334, 673, 396, 0.7 ], + [ "Nefeltari Vivi, Princess of Alabasta Kingdom", "PSY", [ "Striker", "Free Spirit" ], 3, 9, 6, 1, 35, 136167, 11, 11, 11, 285, 104, 225, 1 ], + [ "Nefeltari Vivi, Sand-Sand Band Sub-Leader", "PSY", [ "Fighter", "Free Spirit" ], 4, 15, 6, 2, 70, 1066998, 243, 51, 187, 593, 269, 488, 1 ], + [ "Koza, Alabasta Citizen", "QCK", [ "Striker", "Free Spirit" ], 3, 9, 5, 1, 35, 136167, 53, 53, 3, 503, 274, 151, 1 ], + [ "Koza, Sand-Sand Band Leader", "QCK", [ "Striker", "Free Spirit" ], 4, 15, 4, 2, 70, 1066998, 445, 230, 123, 1000, 503, 341, 1 ], + [ "Nefeltari Cobra, King of Alabasta Kingdom", "PSY", "Fighter", 3, 15, 5, 2, 70, 1066998, 523, 294, 31, 1402, 571, 211, 1 ], + [ "Sabo", "PSY", [ "Free Spirit", "Striker" ], 5, 30, 5, 4, 70, 1066998, 369, 279, 169, 1498, 821, 305, 1.5 ], + [ "Sabo the Revolutionary", "PSY", [ "Free Spirit", "Striker" ], 6, 55, 4, 5, 99, 5000000, 1440, 752, 252, 2985, 1422, 451, 1.5 ], + [ "Koala", "DEX", [ "Fighter", "Free Spirit" ], 4, 18, 4, 3, 70, 1066998, 94, 122, 48, 996, 644, 226, 1.5 ], + [ "Koala the Revolutionary", "DEX", [ "Fighter", "Free Spirit" ], 5, 29, 4, 4, 99, 4000000, 931, 600, 185, 1934, 1212, 392, 1.5 ], + [ "Hack", "STR", [ "Fighter", "Powerhouse" ], 4, 18, 4, 3, 70, 1066998, 188, 136, 21, 1241, 721, 151, 1.5 ], + [ "Hack, Revolutionary Army", "STR", [ "Fighter", "Powerhouse" ], 5, 29, 5, 4, 99, 4000000, 1185, 668, 115, 2387, 1324, 259, 1.5 ], + [ "Emporio Ivankov, New Kama Karate Master", "INT", [ "Free Spirit", "Fighter" ], 4, 18, 4, 3, 70, 1066998, 206, 99, 32, 1343, 653, 157, 1.5 ], + [ "Emporio Ivankov, Revolutionary Army", "INT", [ "Free Spirit", "Fighter" ], 5, 29, 7, 4, 99, 4000000, 1285, 593, 142, 2774, 1212, 241, 1.5 ], + [ "Inazuma", "QCK", [ "Slasher", "Cerebral" ], 4, 18, 4, 3, 70, 1066998, 179, 58, 47, 1300, 449, 232, 1.5 ], + [ "Inazuma the Revolutionary", "QCK", [ "Slasher", "Cerebral" ], 5, 29, 6, 4, 99, 4000000, 1244, 400, 199, 2559, 833, 380, 1.5 ], + [ "Nico Robin Voyage Log: Straw Hat Pirates", "PSY", [ "Fighter", "Cerebral" ], 4, 12, 6, 2, 50, 392109, 155, 62, 58, 1032, 484, 262, 1 ], + [ "Nico Robin Voyage Dream: 100-Year Void", "PSY", [ "Fighter", "Cerebral" ], 5, 20, 6, 3, 99, 3000000, 970, 423, 220, 1924, 857, 390, 1 ], + [ "Ice Cream-Loving Nami", "DEX", [ "Striker", "Cerebral" ], 4, 12, 6, 1, 50, 392109, 141, 43, 53, 966, 422, 242, 1 ], + [ "Ice Cream-Loving Nami, Lemon Ice Cream", "DEX", [ "Striker", "Cerebral" ], 5, 20, 4, 2, 99, 3000000, 900, 366, 200, 1802, 768, 402, 1 ], + [ "Ice Cream-Loving Robin", "PSY", [ "Fighter", "Cerebral" ], 4, 12, 6, 1, 50, 392109, 147, 61, 46, 988, 491, 218, 0.7 ], + [ "Ice Cream-Loving Robin, Chocolate Ice Cream", "PSY", [ "Fighter", "Cerebral" ], 5, 20, 4, 2, 99, 3000000, 943, 443, 172, 1903, 842, 361, 1 ], + [ "Ice Cream-Loving Perona", "INT", [ "Shooter", "Driven" ], 4, 12, 5, 1, 50, 392109, 99, 67, 52, 901, 527, 233, 1 ], + [ "Ice Cream-Loving Perona, Strawberry Ice Cream", "INT", [ "Shooter", "Driven" ], 5, 20, 4, 2, 99, 3000000, 848, 462, 182, 1689, 877, 385, 1 ], + [ "Vivi's Breather", "QCK", [ "Slasher", "Free Spirit" ], 4, 12, 4, 2, 70, 1066998, 102, 37, 91, 1028, 497, 343, 1 ], + [ "Calgara", "STR", [ "Free Spirit", "Striker" ], 3, 12, 6, 1, 50, 392109, 94, 115, 0, 1203, 692, 0, 1 ], + [ "Calgara, Great Shandia Warrior", "STR", [ "Free Spirit", "Striker" ], 4, 20, 4, 2, 99, 3000000, 1145, 633, 0, 2401, 1300, 90, 1 ], + [ "Mont Blanc Noland", "INT", [ "Slasher", "Cerebral" ], 3, 12, 5, 1, 50, 392109, 102, 74, 49, 1028, 502, 212, 1 ], + [ "Mont Blanc Noland, Lvneel Kingdom Explorer", "INT", [ "Slasher", "Cerebral" ], 4, 20, 4, 2, 99, 3000000, 949, 442, 170, 1982, 890, 326, 1 ], + [ "Naginata Corporal, Navy HQ", "DEX", "Striker", 2, 7, 5, 0, 35, 90778, 70, 32, 21, 601, 301, 98, 1 ], + [ "Rifle Corporal, Navy HQ", "QCK", "Shooter", 2, 7, 6, 0, 35, 90778, 58, 28, 28, 498, 286, 121, 1 ], + [ "Saber Corporal, Navy HQ", "PSY", "Slasher", 2, 7, 5, 0, 35, 90778, 51, 34, 22, 466, 330, 111, 1 ], + [ "Bazooka Corporal, Navy HQ", "STR", "Shooter", 2, 7, 4, 0, 35, 90778, 62, 50, 14, 598, 404, 64, 1 ], + [ "Knuckle Corporal, Navy HQ", "INT", "Fighter", 2, 7, 6, 0, 35, 90778, 55, 48, 22, 522, 392, 82, 1 ], + [ "Naginata Major, Navy HQ", "DEX", "Striker", 3, 13, 6, 1, 70, 1066998, 554, 250, 61, 1358, 645, 170, 1 ], + [ "Rifle Major, Navy HQ", "QCK", "Shooter", 3, 13, 5, 1, 70, 1066998, 444, 244, 96, 1002, 568, 259, 1 ], + [ "Saber Major, Navy HQ", "PSY", "Slasher", 3, 13, 6, 1, 70, 1066998, 411, 275, 86, 989, 737, 208, 1 ], + [ "Bazooka Major, Navy HQ", "STR", "Shooter", 3, 13, 6, 1, 70, 1066998, 547, 362, 44, 1301, 833, 117, 1 ], + [ "Knuckle Major, Navy HQ", "INT", "Fighter", 3, 13, 5, 1, 70, 1066998, 462, 351, 49, 1244, 876, 112, 1 ], + [ "Oimo", "PSY", [ "Striker", "Powerhouse" ], 3, 25, 5, 2, 70, 1778330, 452, 223, 23, 1602, 742, 98, 1 ], + [ "Kashii", "INT", [ "Slasher", "Powerhouse" ], 3, 25, 6, 2, 70, 1778330, 426, 242, 21, 1551, 798, 87, 1 ], + [ "Watchdog Unit of the Law", "QCK", "Slasher", 3, 13, 4, 1, 70, 1066998, 122, 43, 40, 1211, 488, 251, 1 ], + [ "Righteous Juror", "STR", "Striker", 3, 13, 4, 1, 70, 1066998, 108, 129, 34, 990, 900, 144, 1 ], + [ "Three-Headed Baskerville", "DEX", "Slasher", 3, 13, 4, 3, 70, 1066998, 102, 78, 38, 1109, 595, 232, 1 ], + [ "Blueno, Cipher Pol No. 9", "STR", [ "Fighter", "Powerhouse" ], 3, 12, 5, 2, 50, 392109, 166, 102, 32, 1338, 502, 124, 1 ], + [ "Blueno: Six Powers, Cipher Pol No. 9", "STR", [ "Fighter", "Powerhouse" ], 4, 20, 4, 3, 99, 3000000, 1281, 452, 100, 2466, 921, 221, 1 ], + [ "Nico Robin, Devil Child", "PSY", [ "Fighter", "Cerebral" ], 3, 10, 6, 2, 50, 392109, 110, 63, 32, 1002, 494, 209, 1 ], + [ "Nico Robin, Straw Hat Pirates", "PSY", [ "Fighter", "Cerebral" ], 4, 16, 5, 3, 99, 3000000, 938, 430, 155, 1892, 881, 351, 1 ], + [ "Franky Voyage Log: Straw Hat Pirates", "PSY", [ "Shooter", "Free Spirit" ], 4, 12, 4, 2, 50, 392109, 242, 100, 34, 1330, 597, 151, 1 ], + [ "Franky Voyage Dream: Ship of the Seven Seas", "PSY", [ "Shooter", "Free Spirit" ], 5, 20, 6, 3, 99, 3000000, 1259, 550, 112, 2372, 1100, 231, 1 ], + [ "Ganfor", "QCK", "Striker", 3, 12, 6, 1, 50, 392109, 80, 40, 48, 930, 452, 185, 1.5 ], + [ "Ganfor, Sky Knight", "QCK", "Striker", 4, 20, 4, 2, 99, 3000000, 884, 401, 151, 1704, 1202, 300, 1.5 ], + [ "Pierre", "DEX", "Fighter", 3, 12, 4, 1, 50, 392109, 69, 32, 38, 920, 480, 182, 1 ], + [ "Conis", "PSY", "Free Spirit", 3, 9, 5, 2, 35, 136167, 58, 10, 32, 503, 190, 232, 1 ], + [ "Conis, Skypiea Girl", "PSY", "Free Spirit", 4, 15, 4, 3, 70, 1066998, 458, 145, 196, 912, 388, 387, 1 ], + [ "Dracule Mihawk, Warlord of the Sea", "INT", "Slasher", 5, 30, 4, 4, 70, 1066998, 623, 328, 10, 1921, 850, 58, 1.5 ], + [ "\"Hawk Eyes\" Mihawk, World's Strongest Swordsman", "INT", "Slasher", 6, 55, 5, 4, 99, 5000000, 1857, 799, 31, 3900, 1490, 120, 1.5 ], + [ "Sir Crocodile: Logia, Warlord of the Sea", "DEX", [ "Cerebral", "Striker" ], 5, 30, 4, 4, 70, 1066998, 500, 293, 104, 1780, 831, 226, 1.5 ], + [ "Sir Crocodile: Logia, Ex-Warlord of the Sea", "DEX", [ "Cerebral", "Striker" ], 6, 55, 4, 4, 99, 5000000, 1724, 765, 174, 3621, 1435, 310, 1.5 ], + [ "Jerry", "STR", [ "Fighter", "Free Spirit" ], 3, 9, 5, 1, 35, 136167, 72, 100, 32, 492, 380, 104, 1 ], + [ "Jerry, Cipher Pol No. 6", "STR", [ "Fighter", "Free Spirit" ], 4, 15, 8, 2, 70, 1066998, 439, 323, 70, 1000, 712, 212, 1 ], + [ "T-Bone", "PSY", [ "Slasher", "Cerebral" ], 3, 12, 6, 1, 50, 392109, 99, 78, 42, 958, 542, 162, 1 ], + [ "Ship Cutter T-Bone, Marine Captain", "PSY", [ "Slasher", "Cerebral" ], 4, 20, 4, 3, 99, 3000000, 900, 493, 133, 1700, 1100, 300, 1 ], + [ "Nefertari Vivi Voyage Log: Princess of Alabasta", "QCK", [ "Slasher", "Free Spirit" ], 4, 12, 6, 2, 50, 392109, 98, 51, 62, 855, 424, 288, 1 ], + [ "Nefertari Vivi Voyage Dream: Queen of the Pirates", "QCK", [ "Slasher", "Free Spirit" ], 5, 20, 4, 3, 99, 3000000, 800, 371, 258, 1591, 777, 474, 1 ], + [ "Monkey D. Luffy Gum-Gum Gatling", "DEX", [ "Free Spirit", "Fighter" ], 4, 15, 8, 3, 99, 2000000, 212, 100, 46, 1777, 795, 270, 0.7 ], + [ "Kalifa, Cipher Pol No. 9", "DEX", [ "Fighter", "Cerebral" ], 3, 12, 5, 2, 50, 392109, 89, 39, 55, 952, 448, 217, 1 ], + [ "Kalifa: Six Powers, Cipher Pol No. 9", "DEX", [ "Fighter", "Cerebral" ], 4, 20, 5, 3, 99, 3000000, 900, 401, 174, 1894, 970, 302, 1 ], + [ "Jabra, Cipher Pol No. 9", "INT", [ "Fighter", "Powerhouse" ], 3, 12, 4, 2, 50, 392109, 190, 92, -200, 1334, 572, -200, 1 ], + [ "Jabra: Six Powers, Cipher Pol No. 9", "INT", [ "Fighter", "Powerhouse" ], 4, 20, 4, 3, 99, 3000000, 1272, 521, -200, 2720, 1250, -200, 1 ], + [ "Fukuro, Cipher Pol No. 9", "STR", [ "Fighter", "Powerhouse" ], 3, 9, 4, 2, 35, 136167, 114, 52, 30, 1123, 408, 122, 1 ], + [ "Fukuro: Six Powers, Cipher Pol No. 9", "STR", [ "Fighter", "Powerhouse" ], 4, 15, 6, 3, 70, 1066998, 1077, 362, 97, 1850, 690, 177, 1 ], + [ "Kumadori, Cipher Pol No. 9", "PSY", [ "Striker", "Powerhouse" ], 3, 9, 5, 2, 35, 136167, 102, 60, 29, 1055, 442, 119, 1 ], + [ "Kumadori: Six Powers, Cipher Pol No. 9", "PSY", [ "Striker", "Powerhouse" ], 4, 15, 4, 3, 70, 1066998, 1000, 398, 88, 1792, 755, 165, 1 ], + [ "Kaku: Beastman, Ox-Ox Fruit, Model: Giraffe", "STR", [ "Slasher", "Powerhouse" ], 4, 20, 6, 3, 99, 4000000, 1220, 692, 43, 2526, 1200, 114, 1 ], + [ "Lucci: Beastman, Cat-Cat Fruit, Model: Leopard", "QCK", [ "Fighter", "Powerhouse" ], 4, 20, 4, 3, 99, 4000000, 1032, 703, 56, 2200, 1302, 140, 1 ], + [ "Spandam", "INT", "Slasher", 4, 7, 5, 1, 35, 136167, 52, 25, 25, 258, 196, 89, 1 ], + [ "Franky, Straw Hat Pirates", "INT", [ "Fighter", "Free Spirit" ], 4, 18, 4, 3, 99, 3000000, 1623, 765, 70, 2505, 1149, 130, 1 ], + [ "Nero", "QCK", [ "Shooter", "Driven" ], 3, 9, 6, 1, 35, 136167, 59, 112, 20, 324, 543, 83, 0.7 ], + [ "Nero, Cipher Pol No. 9", "QCK", [ "Shooter", "Driven" ], 4, 15, 5, 2, 70, 1066998, 277, 489, 51, 755, 1050, 145, 0.7 ], + [ "Wanze", "DEX", "Free Spirit", 3, 11, 4, 1, 50, 392109, 202, 44, 40, 1124, 367, 212, 1 ], + [ "Wanze, Cipher Pol No. 7", "DEX", "Free Spirit", 4, 18, 5, 2, 99, 3000000, 1059, 312, 170, 2051, 674, 363, 1 ], + [ "Portgas D. Ace, Record of the Voyage - Whitebeard Pirates", "QCK", [ "Free Spirit", "Fighter" ], 4, 12, 5, 2, 50, 392109, 141, 71, 36, 1121, 585, 189, 1.5 ], + [ "Portgas D. Ace Voyage Dream: Pirate Summit", "QCK", [ "Free Spirit", "Fighter" ], 5, 20, 4, 3, 99, 4000000, 1063, 524, 140, 2181, 1100, 258, 1.5 ], + [ "Megalo and Princess Shirahoshi", "QCK", "Fighter", 4, 15, 4, 3, 70, 1066998, 1251, 271, 150, 2001, 600, 241, 1 ], + [ "Rob Lucci, CP9 Dark Justice", "STR", [ "Powerhouse", "Fighter" ], 5, 30, 4, 4, 70, 1066998, 496, 300, 89, 1656, 800, 245, 1.5 ], + [ "Rob Lucci, CP9's Strongest", "STR", [ "Powerhouse", "Fighter" ], 6, 55, 6, 4, 99, 5000000, 1611, 762, 220, 3230, 1456, 382, 1.5 ], + [ "Kaku, CP9 Dark Justice", "DEX", [ "Slasher", "Powerhouse" ], 4, 17, 6, 3, 70, 1066998, 151, 132, 28, 1183, 713, 178, 1 ], + [ "Kaku, CP9's Strongest", "DEX", [ "Slasher", "Powerhouse" ], 5, 27, 8, 4, 99, 4000000, 1124, 666, 147, 2440, 1325, 272, 1 ], + [ "Kalifa, CP9 Dark Justice", "QCK", [ "Cerebral", "Fighter" ], 4, 17, 5, 3, 70, 1066998, 98, 60, 63, 963, 545, 270, 1 ], + [ "Kalifa, CP9's Strongest", "QCK", [ "Cerebral", "Fighter" ], 5, 27, 5, 4, 99, 4000000, 912, 498, 238, 1964, 933, 473, 1 ], + [ "Jabra, CP9 Dark Justice", "QCK", [ "Powerhouse", "Free Spirit" ], 4, 17, 5, 3, 70, 1066998, 224, 112, 21, 1650, 702, 89, 1 ], + [ "Jabra, CP9's Strongest", "QCK", [ "Powerhouse", "Free Spirit" ], 5, 27, 4, 4, 99, 4000000, 1601, 657, 55, 3003, 1299, 166, 1 ], + [ "Blueno, CP9 Dark Justice", "INT", [ "Powerhouse", "Free Spirit" ], 4, 16, 5, 3, 70, 1066998, 245, 94, 23, 1832, 644, 91, 1 ], + [ "Blueno, CP9's Strongest", "INT", [ "Powerhouse", "Free Spirit" ], 5, 26, 4, 4, 99, 4000000, 1779, 600, 56, 3502, 1045, 168, 1 ], + [ "Fukuro, CP9 Dark Justice", "PSY", [ "Powerhouse", "Fighter" ], 4, 16, 4, 3, 70, 1066998, 151, 97, 46, 1140, 651, 203, 1 ], + [ "Fukuro, CP9's Strongest", "PSY", [ "Powerhouse", "Fighter" ], 5, 26, 8, 4, 99, 4000000, 1093, 603, 165, 2415, 1051, 353, 1 ], + [ "Kumadori, CP9 Dark Justice", "STR", [ "Powerhouse", "Striker" ], 4, 16, 4, 3, 70, 1066998, 162, 89, 47, 1167, 612, 212, 1 ], + [ "Kumadori, CP9's Strongest", "STR", [ "Powerhouse", "Striker" ], 5, 26, 7, 4, 99, 4000000, 1110, 560, 170, 2479, 1018, 355, 1 ], + [ "Monkey D. Luffy, Halloween Monster", "DEX", [ "Fighter", "Free Spirit" ], 4, 20, 6, 3, 99, 3000000, 85, 41, 26, 1920, 1080, 185, 1 ], + [ "Usopp, Lying Wolf", "PSY", "Shooter", 4, 20, 5, 3, 99, 3000000, 51, 23, 46, 1444, 673, 400, 1 ], + [ "Franky, Frankenstein", "STR", [ "Shooter", "Free Spirit" ], 4, 20, 4, 3, 99, 3000000, 82, 43, 22, 1903, 1121, 170, 1 ], + [ "Nami, Jackie 'o Lantern", "QCK", [ "Striker", "Cerebral" ], 4, 20, 4, 3, 99, 3000000, 47, 25, 49, 1342, 699, 416, 1 ], + [ "Tony Tony Chopper, Lil' Vampire", "INT", [ "Fighter", "Cerebral" ], 4, 20, 6, 3, 99, 3000000, 56, 33, 38, 1548, 763, 358, 1 ], + [ "Roronoa Zoro, Jack the Ripper", "QCK", [ "Slasher", "Driven" ], 4, 20, 6, 3, 99, 3000000, 90, 39, 13, 2094, 1063, 131, 1 ], + [ "Nico Robin, Devil Girl", "DEX", [ "Fighter", "Cerebral" ], 4, 20, 4, 3, 99, 3000000, 53, 35, 34, 1500, 889, 320, 1 ], + [ "Sanji, Ghost Knight", "PSY", "Fighter", 4, 20, 4, 3, 99, 3000000, 92, 36, 28, 2088, 936, 221, 1 ], + [ "Brook, Cowardly Skeleton", "INT", [ "Slasher", "Free Spirit" ], 4, 20, 4, 3, 99, 3000000, 62, 35, 26, 1921, 948, 210, 1 ], + [ "Dalmatian, Marine Vice Admiral", "STR", [ "Fighter", "Powerhouse" ], 4, 20, 5, 3, 99, 4000000, 241, 186, 35, 2171, 1275, 189, 1.5 ], + [ "Momonga, Marine Vice Admiral", "PSY", [ "Cerebral", "Slasher" ], 4, 20, 6, 3, 99, 4000000, 298, 142, 20, 2618, 1111, 163, 1.5 ], + [ "Onigumo, Marine Vice Admiral", "DEX", [ "Slasher", "Driven" ], 4, 20, 8, 3, 99, 4000000, 213, 118, 54, 2000, 1021, 318, 1.5 ], + [ "Shu", "INT", [ "Fighter", "Free Spirit" ], 3, 12, 4, 2, 70, 1066998, 56, 89, 23, 943, 969, 150, 1 ], + [ "Berry Good", "QCK", [ "Free Spirit", "Striker" ], 3, 12, 4, 2, 70, 1066998, 203, 57, 15, 1808, 703, 103, 1 ], + [ "Strawberry, Marine Vice Admiral", "PSY", [ "Cerebral", "Slasher" ], 3, 16, 6, 2, 99, 3000000, 142, 64, 33, 1883, 943, 178, 1 ], + [ "Lucky Roo", "PSY", [ "Shooter", "Free Spirit" ], 3, 13, 6, 2, 35, 136167, 303, 169, 30, 904, 460, 98, 0.7 ], + [ "Lucky Roo of the Red Hair Pirates", "PSY", [ "Shooter", "Free Spirit" ], 4, 20, 5, 3, 70, 1778330, 842, 412, 70, 1606, 789, 188, 0.7 ], + [ "Rebecca, Imprisoned Swordsman", "QCK", "Striker", 4, 18, 5, 1, 50, 392109, 193, 112, 51, 1003, 503, 201, 1 ], + [ "Rebecca, Coliseum's Exclusive Gladiator", "QCK", "Striker", 5, 30, 4, 3, 99, 3000000, 920, 441, 150, 1947, 853, 374, 1 ], + [ "Urouge, Fallen Monk Pirates Captain", "STR", [ "Fighter", "Striker" ], 4, 25, 5, 2, 70, 1066998, 702, 340, 38, 1580, 790, 121, 1.5 ], + [ "Mad Monk Urouge, Fallen Monk Pirates Captain", "STR", [ "Fighter", "Striker" ], 5, 40, 5, 3, 99, 4000000, 1512, 755, 83, 2824, 1324, 203, 1.5 ], + [ "Tashigi: Flower of Justice", "INT", [ "Slasher", "Cerebral" ], 4, 13, 5, 2, 50, 392109, 132, 65, 49, 999, 495, 205, 1 ], + [ "Tashigi Marine Officer: Flower of Justice", "INT", [ "Slasher", "Cerebral" ], 5, 20, 5, 3, 99, 3000000, 932, 428, 164, 1804, 890, 378, 1 ], + [ "Gen-san", "STR", [ "Slasher", "Cerebral" ], 3, 9, 5, 2, 35, 136167, 211, 45, 33, 930, 288, 190, 1 ], + [ "Genzo, Cocoyasi Village Resident", "STR", [ "Slasher", "Cerebral" ], 4, 15, 4, 3, 70, 1066998, 879, 242, 143, 1324, 501, 299, 1 ], + [ "Dr. Hiriluk", "PSY", [ "Shooter", "Free Spirit" ], 3, 9, 6, 2, 35, 136167, 231, 63, 5, 1248, 461, 84, 1 ], + [ "Dr. Hiriluk, Quack Doctor", "PSY", [ "Shooter", "Free Spirit" ], 4, 15, 5, 3, 70, 1066998, 1233, 451, 84, 1248, 518, 312, 1 ], + [ "Kuina", "DEX", "Striker", 3, 9, 6, 2, 35, 136167, 54, 41, 70, 503, 264, 251, 1 ], + [ "Kuina, Shimotsuki Village's Girl Swordsman", "DEX", [ "Slasher", "Driven" ], 4, 15, 5, 3, 70, 1066998, 448, 220, 213, 917, 582, 338, 1 ], + [ "Onion, Pepper & Carrot", "QCK", [ "Striker", "Free Spirit" ], 3, 9, 4, 3, 35, 136167, 80, 10, 66, 716, 142, 249, 1 ], + [ "Onion, Pepper & Carrot, the Usopp Pirates", "QCK", [ "Striker", "Free Spirit" ], 4, 15, 6, 3, 70, 1066998, 654, 77, 180, 1200, 333, 350, 1 ], + [ "Iceburg", "INT", [ "Shooter", "Cerebral" ], 3, 9, 6, 2, 35, 136167, 155, 69, 38, 790, 392, 167, 1 ], + [ "Iceburg, Mayor of W7 and President of Galley-La Company", "INT", [ "Shooter", "Cerebral" ], 4, 16, 4, 3, 70, 1066998, 723, 343, 122, 1401, 702, 224, 1 ], + [ "Monkey D. Luffy Star of Hope", "INT", [ "Slasher", "Powerhouse" ], 4, 30, 4, 1, 70, 1066998, 259, 179, 0, 1400, 763, 0, 1.5 ], + [ "Nightmare Luffy Warrior of Hope", "INT", [ "Fighter", "Powerhouse" ], 5, 50, 4, 2, 99, 5000000, 1331, 711, 0, 3020, 1520, 0, 1.5 ], + [ "Breed", "INT", "Cerebral", 3, 13, 6, 1, 50, 392109, 59, 25, 59, 867, 418, 275, 1.5 ], + [ "Breed, Pet-Pet Fruit User", "INT", [ "Cerebral", "Powerhouse" ], 4, 20, 4, 3, 99, 3000000, 867, 818, 200, 2002, 1311, 180, 1.5 ], + [ "Kung Fu Dugong, Sea Animal Pirates", "PSY", [ "Fighter", "Powerhouse" ], 4, 18, 5, 2, 70, 1778330, 50, 355, 95, 450, 1115, 225, 1.5 ], + [ "Sea Lapahn, Sea Animal Pirates", "QCK", [ "Fighter", "Powerhouse" ], 3, 15, 4, 1, 70, 711332, 209, 76, 14, 1757, 724, 112, 1 ], + [ "Octopus Boxer, Sea Animal Pirates", "STR", [ "Fighter", "Powerhouse" ], 3, 15, 8, 1, 70, 711332, 99, 91, 2, 1563, 846, 93, 1 ], + [ "Mr. 2 Bon Clay Voyage Log: B.W.", "PSY", [ "Fighter", "Free Spirit" ], 4, 13, 5, 2, 50, 392109, 109, 57, 32, 1033, 513, 212, 1 ], + [ "Mr. 2 Bon Clay Voyage Dream: Okama Way", "PSY", [ "Fighter", "Free Spirit" ], 5, 20, 4, 3, 99, 3000000, 970, 448, 181, 1914, 922, 362, 1 ], + [ "Hina, Navy HQ Captain", "DEX", [ "Fighter", "Cerebral" ], 4, 18, 5, 1, 50, 392109, 188, 128, 48, 977, 544, 191, 1 ], + [ "Black Cage Hina, Navy HQ Captain", "DEX", [ "Fighter", "Cerebral" ], 5, 30, 5, 3, 99, 3000000, 920, 488, 159, 1901, 912, 357, 1 ], + [ "Smoker, Navy HQ Captain", "INT", [ "Striker", "Driven" ], 4, 25, 6, 2, 70, 1066998, 710, 309, 44, 1600, 703, 146, 1.5 ], + [ "Smoker the White Hunter, Navy HQ Captain", "INT", [ "Striker", "Driven" ], 5, 40, 5, 3, 99, 4000000, 1549, 640, 112, 2727, 1289, 234, 1.5 ], + [ "Angel in White Nami, Wedding", "PSY", [ "Striker", "Cerebral" ], 3, 13, 5, 1, 50, 392109, 60, 33, 49, 933, 419, 268, 1 ], + [ "Goddess in White Nami, Wedding", "PSY", [ "Striker", "Cerebral" ], 4, 20, 4, 2, 99, 3000000, 877, 362, 221, 1772, 799, 409, 1 ], + [ "Lola, Thriller Bark Bride", "STR", [ "Slasher", "Powerhouse" ], 3, 11, 6, 1, 50, 261406, 103, 69, 31, 1101, 559, 91, 1 ], + [ "Loveseeking Lola, Thriller Bark Bride", "STR", [ "Slasher", "Powerhouse" ], 4, 18, 8, 2, 99, 2000000, 1032, 513, 52, 2018, 1009, 147, 1 ], + [ "Risky Brothers", "DEX", [ "Slasher", "Free Spirit" ], 3, 9, 4, 2, 50, 392109, 30, 15, 40, 707, 368, 287, 1 ], + [ "Cerberus", "QCK", [ "Fighter", "Powerhouse" ], 3, 14, 5, 2, 50, 392109, 233, 108, 52, 1151, 781, 0, 1 ], + [ "Taralan", "INT", [ "Cerebral", "Powerhouse" ], 3, 14, 7, 2, 50, 392109, 325, 76, 48, 1385, 696, 0, 1 ], + [ "Bear Skin Rug", "DEX", [ "Fighter", "Powerhouse" ], 3, 14, 5, 2, 50, 392109, 203, 52, 155, 1074, 609, 74, 1 ], + [ "Gecko Moria, Thriller Bark Demon", "INT", [ "Free Spirit", "Driven" ], 3, 12, 6, 2, 50, 392109, 205, 92, 0, 1422, 504, 0, 1 ], + [ "Gecko Moria, Thriller Bark Ruler", "INT", [ "Free Spirit", "Driven" ], 4, 20, 4, 3, 99, 3000000, 1355, 451, 0, 2603, 913, 0, 1.5 ], + [ "Strong Soldier Zombie", "STR", "Fighter", 2, 7, 6, 0, 35, 90778, 85, 39, 92, 990, 622, 27, 1 ], + [ "Speedy Soldier Zombie", "QCK", "Fighter", 2, 7, 6, 0, 35, 90778, 77, 30, 92, 944, 590, 43, 1 ], + [ "Crafty Soldier Zombie", "DEX", "Fighter", 2, 7, 6, 0, 35, 90778, 92, 28, 92, 1032, 574, 35, 1 ], + [ "Hate-Filled Soldier Zombie", "INT", "Fighter", 2, 7, 6, 0, 35, 90778, 71, 40, 92, 903, 648, 29, 1 ], + [ "Egotistical Soldier Zombie", "PSY", "Fighter", 2, 7, 6, 0, 35, 90778, 70, 24, 92, 887, 551, 72, 1 ], + [ "Tricky Wild Zombie", "DEX", "Powerhouse", 3, 12, 4, 1, 50, 392109, 75, 74, 132, 899, 720, 71, 1 ], + [ "Brainy Wild Zombie", "INT", "Powerhouse", 3, 12, 4, 1, 50, 392109, 71, 86, 132, 823, 771, 65, 1 ], + [ "Heartful Wild Zombie", "PSY", "Powerhouse", 3, 12, 4, 1, 50, 392109, 70, 70, 132, 801, 700, 94, 1 ], + [ "Powerful General Zombie", "STR", [ "Slasher", "Powerhouse" ], 3, 20, 6, 1, 70, 1066998, 99, 59, 29, 1702, 813, 0, 1 ], + [ "Sneaky General Zombie", "DEX", [ "Slasher", "Powerhouse" ], 3, 20, 6, 1, 70, 1066998, 102, 57, 29, 1727, 802, 0, 1 ], + [ "Blazing General Zombie", "QCK", [ "Slasher", "Powerhouse" ], 3, 20, 6, 1, 70, 1066998, 113, 54, 29, 1768, 789, 0, 1 ], + ["Trafalgar Law, the Boy from the White City", "PSY", ["Slasher", "Driven"], 4, 10, 4, 3, 35, 90778, 442, 60, 0, 455, 497, 222, 1], + ["Trafalgar Law, the Boy Saved by Fate", "PSY", ["Slasher", "Driven"], 5, 18, 5, 3, 70, 1066998, 442, 424, 149, 696, 762, 390, 1], + [ "Basil Hawkins, Hawkins Pirates Captain", "DEX", [ "Cerebral", "Striker" ], 4, 25, 6, 2, 70, 1066998, 639, 298, 69, 1219, 745, 201, 1 ], + [ "Basil Hawkins the Magician, Hawkins Pirates Captain", "DEX", [ "Cerebral", "Striker" ], 5, 40, 4, 3, 99, 4000000, 1157, 690, 147, 2239, 1278, 347, 1 ], + [ "Wyper, Shandian Warrior", "STR", [ "Shooter", "Free Spirit" ], 4, 18, 6, 1, 50, 392109, 229, 151, 10, 1198, 611, 33, 1 ], + [ "Berserker Wyper, Shandian Warrior", "STR", [ "Shooter", "Free Spirit" ], 5, 30, 5, 3, 99, 3000000, 1140, 543, 15, 2095, 1260, 99, 1 ], + [ "Mr. 7 and Ms. Father's Day", "QCK", [ "Shooter", "Driven" ], 4, 20, 6, 2, 70, 1778330, 68, 42, 105, 1085, 625, 315, 1 ], + [ "Tyrant Bartholomew Kuma", "STR", [ "Cerebral", "Powerhouse" ], 4, 30, 4, 2, 70, 1066998, 260, 170, 90, 1201, 623, 190, 1 ], + [ "Tyrant Bartholomew Kuma, Government Human Weapon", "STR", [ "Cerebral", "Powerhouse" ], 5, 50, 7, 3, 99, 5000000, 1159, 572, 190, 3090, 1435, 90, 1 ], + [ "Caesar Clown", "DEX", [ "Driven", "Cerebral" ], 4, 18, 5, 3, 70, 1066998, 71, 141, 71, 989, 740, 204, 1 ], + [ "Master Caesar", "DEX", [ "Driven", "Cerebral" ], 5, 30, 4, 4, 99, 4000000, 941, 695, 177, 2000, 1383, 343, 1 ], + [ "Vergo", "INT", [ "Striker", "Powerhouse" ], 4, 18, 6, 3, 70, 1066998, 282, 150, 19, 1515, 782, 89, 1 ], + [ "Vergo, Donquixote Pirates", "INT", [ "Striker", "Powerhouse" ], 5, 30, 4, 4, 99, 4000000, 1464, 730, 60, 3003, 1410, 140, 1 ], + [ "Monet", "PSY", [ "Free Spirit", "Cerebral" ], 4, 18, 4, 3, 70, 1066998, 130, 87, 47, 1078, 593, 241, 1 ], + [ "Monet, Donquixote Pirates", "PSY", [ "Free Spirit", "Cerebral" ], 5, 30, 4, 4, 99, 4000000, 1020, 540, 199, 2131, 1001, 433, 1 ], + [ "Baby 5", "STR", [ "Shooter", "Striker" ], 4, 18, 5, 3, 70, 1066998, 114, 142, 53, 892, 743, 230, 1 ], + [ "Baby 5, Donquixote Pirates", "STR", [ "Shooter", "Striker" ], 5, 30, 6, 4, 99, 4000000, 850, 692, 185, 1929, 1352, 349, 1 ], + [ "Buffalo", "QCK", [ "Shooter", "Free Spirit" ], 4, 18, 9, 3, 70, 1066998, 96, 96, 49, 1111, 666, 196, 1 ], + [ "Buffalo, Donquixote Pirates", "QCK", [ "Shooter", "Free Spirit" ], 5, 30, 10, 4, 99, 4000000, 1050, 600, 173, 2769, 1096, 296, 1 ], + [ "Tom, Tom's Workers", "DEX", [ "Fighter", "Powerhouse" ], 3, 12, 6, 1, 50, 392109, 159, 95, 30, 1103, 614, 141, 1 ], + [ "Legendary Shipwright Tom, Tom's Workers", "DEX", [ "Fighter", "Powerhouse" ], 4, 20, 4, 2, 99, 3000000, 1059, 572, 100, 2207, 1029, 266, 1 ], + [ "Cutty Flam, Tom's Workers", "STR", [ "Shooter", "Driven" ], 3, 13, 6, 2, 70, 1066998, 24, 138, 15, 924, 932, 139, 1 ], + [ "Iceburg, Tom's Workers", "QCK", [ "Striker", "Cerebral" ], 3, 13, 6, 2, 70, 1066998, 58, 60, 36, 1098, 694, 203, 1 ], + [ "Wapol of Tin", "STR", [ "Shooter", "Driven" ], 3, 12, 6, 2, 70, 1066998, 160, 78, 26, 1304, 800, 99, 1 ], + [ "Slimmed-down Wapol", "QCK", [ "Shooter", "Driven" ], 4, 20, 5, 2, 99, 3000000, 837, 505, 95, 1923, 867, 247, 1 ], + [ "Robson", "PSY", [ "Fighter", "Powerhouse" ], 3, 9, 6, 1, 50, 392109, 155, 22, 36, 1574, 318, 151, 1 ], + [ "Chopper's Snow Day", "DEX", [ "Fighter", "Powerhouse" ], 4, 15, 5, 2, 99, 2000000, 130, 30, 50, 1920, 614, 293, 1 ], + [ "Trafalgar Law Holy Night Gentleman", "DEX", [ "Slasher", "Free Spirit" ], 4, 12, 6, 3, 50, 392109, 182, 93, 43, 995, 489, 198, 1 ], + [ "Trafalgar Law Holy Night Nobleman", "DEX", [ "Slasher", "Free Spirit" ], 5, 19, 4, 3, 99, 4000000, 945, 460, 151, 2003, 1030, 313, 1 ], + [ "Jewelry Bonney Ravenous Spoiled Santa", "PSY", [ "Fighter", "Free Spirit" ], 4, 12, 5, 3, 50, 392109, 190, 50, 54, 1003, 403, 213, 1 ], + [ "Jewelry Bonney Ravenous Greedy Santa", "PSY", [ "Fighter", "Free Spirit" ], 5, 19, 4, 3, 99, 4000000, 848, 354, 178, 2380, 769, 338, 1 ], + [ "Coby, Navy HQ Petty Officer", "PSY", [ "Fighter", "Driven" ], 4, 18, 5, 2, 50, 392109, 267, 98, 27, 1193, 561, 158, 1 ], + [ "War Hero Coby, Navy HQ Petty Officer", "PSY", [ "Fighter", "Driven" ], 5, 30, 4, 3, 99, 3000000, 1121, 500, 104, 2239, 1048, 261, 1 ], + [ "Lady Alvida, Lovely Beauty", "QCK", [ "Striker", "Free Spirit" ], 4, 18, 5, 1, 50, 392109, 240, 92, 31, 1030, 534, 197, 1 ], + [ "Lady Alvida, Peerless Beauty", "QCK", [ "Striker", "Free Spirit" ], 5, 30, 6, 3, 99, 3000000, 967, 466, 148, 2092, 1000, 307, 1 ], + [ "Snowscape Nami", "QCK", [ "Striker", "Cerebral" ], 4, 15, 5, 2, 99, 2000000, 77, 33, 78, 1459, 674, 349, 1 ], + [ "Boa Hancock, Kuja Pirates Captain", "PSY", [ "Shooter", "Free Spirit" ], 4, 30, 4, 2, 70, 1066998, 153, 138, 57, 1020, 633, 201, 1 ], + [ "Empress Boa Hancock, Kuja Pirates Captain", "PSY", [ "Shooter", "Free Spirit" ], 5, 50, 4, 3, 99, 5000000, 943, 589, 161, 2055, 1378, 375, 1 ], + [ "Nico Robin Cien Fleur Wing: The Storm", "INT", [ "Cerebral", "Slasher" ], 4, 15, 4, 2, 99, 2000000, 238, 203, 83, 1518, 1061, 290, 1 ], + [ "Usopp Tabasco Star: The Storm", "DEX", "Shooter", 4, 15, 7, 2, 99, 2000000, 258, 152, 94, 1866, 704, 343, 1 ], + [ "Tony Tony Chopper Heavy Gong: The Storm", "STR", [ "Powerhouse", "Cerebral" ], 4, 15, 4, 2, 99, 2000000, 303, 168, 70, 2171, 900, 231, 1 ], + [ "Donquixote Doflamingo, Donquixote Pirates", "QCK", [ "Driven", "Cerebral" ], 5, 30, 6, 4, 70, 1066998, 390, 311, 77, 1510, 830, 258, 1 ], + [ "Heavenly Yaksha Donquixote Doflamingo", "QCK", [ "Driven", "Cerebral" ], 6, 55, 4, 4, 99, 5000000, 1446, 780, 230, 2800, 1530, 405, 1 ], + [ "Sugar", "QCK", [ "Free Spirit", "Cerebral" ], 4, 18, 4, 3, 70, 1066998, 102, 55, 68, 952, 420, 321, 1 ], + [ "Sugar, Donquixote Pirates", "QCK", [ "Free Spirit", "Cerebral" ], 5, 30, 5, 4, 99, 4000000, 896, 342, 274, 1905, 790, 532, 1 ], + [ "Señor Pink", "PSY", [ "Free Spirit", "Fighter" ], 4, 18, 4, 3, 70, 1066998, 292, 103, 24, 1524, 657, 142, 1 ], + [ "Señor Pink, Donquixote Pirates", "PSY", [ "Free Spirit", "Fighter" ], 5, 30, 4, 4, 99, 4000000, 1478, 600, 100, 2800, 1242, 241, 1 ], + [ "Trebol", "INT", [ "Cerebral", "Driven" ], 4, 18, 5, 3, 70, 1066998, 103, 150, 42, 941, 770, 201, 1 ], + [ "Trebol, Donquixote Pirates", "INT", [ "Cerebral", "Driven" ], 5, 30, 6, 4, 99, 4000000, 889, 721, 148, 1967, 1381, 334, 1 ], + [ "Giolla", "DEX", [ "Free Spirit", "Driven" ], 4, 18, 4, 3, 70, 1066998, 236, 66, 41, 1463, 494, 204, 1 ], + [ "Giolla, Donquixote Pirates", "DEX", [ "Free Spirit", "Driven" ], 5, 30, 4, 4, 99, 4000000, 1404, 443, 146, 2887, 880, 347, 1 ], + [ "Lao G.", "STR", [ "Fighter", "Driven" ], 4, 18, 5, 3, 70, 1066998, 117, 129, 37, 1025, 783, 181, [ 1.5, 0.7, 1.5 ] ], + [ "Lao G., Donquixote Pirates", "STR", [ "Fighter", "Driven" ], 5, 30, 4, 4, 99, 4000000, 968, 721, 143, 2021, 1420, 293, [ 1.5, 0.7, 1.5 ] ], + [ "Scratchmen Apoo, Captain of the On Air Pirates", "QCK", [ "Shooter", "Free Spirit" ], 4, 25, 5, 2, 70, 1066998, 646, 261, 83, 1247, 693, 220, 1 ], + [ "Roar of the Sea Scratchmen Apoo, Captain of the On Air Pirates", "QCK", [ "Shooter", "Free Spirit" ], 5, 40, 4, 3, 99, 4000000, 1188, 639, 175, 2309, 1190, 351, 1 ], + [ "Dorry, Giant Warrior Pirates", "INT", [ "Slasher", "Powerhouse" ], 4, 18, 6, 1, 50, 392109, 261, 120, 20, 1420, 503, 90, 1 ], + [ "Dorry the Blue Ogre", "INT", [ "Slasher", "Powerhouse" ], 5, 30, 4, 3, 99, 3000000, 1366, 449, 64, 2640, 1000, 156, 1 ], + [ "Jinbe, Shark Soldier", "PSY", [ "Fighter", "Powerhouse" ], 4, 20, 4, 2, 99, 3000000, 84, 34, 29, 1990, 1020, 298, 1 ], + [ "Mr. 1, West Blue Swordsman", "STR", [ "Slasher", "Cerebral" ], 4, 17, 6, 2, 99, 2000000, 45, 24, 19, 2024, 1044, 118, 1.5 ], + [ "Buggy, Cheerfully Crazy", "QCK", [ "Driven", "Free Spirit" ], 4, 17, 5, 2, 99, 2000000, 32, 19, 30, 1790, 694, 285, 1.5 ], + [ "Horo Horo Ghost", "PSY", "Free Spirit", 2, 6, 4, 0, 35, 90778, 40, 20, 100, 150, 90, 190, 1 ], + [ "Perona, Thriller Bark Demon", "DEX", [ "Shooter", "Driven" ], 3, 12, 4, 1, 50, 392109, 59, 31, 38, 797, 392, 271, 1 ], + [ "Perona, Giant Ghost Princess", "DEX", [ "Shooter", "Driven" ], 4, 20, 5, 3, 99, 3000000, 772, 381, 159, 1909, 960, 271, 1 ], + [ "Doctor Hogback, Thriller Bark Demon", "INT", [ "Fighter", "Cerebral" ], 3, 15, 5, 2, 70, 1066998, 148, 75, 30, 1492, 535, 247, 1 ], + [ "Absalom of the Graveyard, Thriller Bark Demon", "STR", [ "Shooter", "Powerhouse" ], 3, 15, 6, 2, 70, 1066998, 156, 102, 13, 1803, 813, 96, 1 ], + [ "Oars, Special Zombie", "STR", [ "Fighter", "Powerhouse" ], 4, 50, 4, 2, 99, 4000000, 1500, 700, 0, 2700, 1440, -500, 1 ], + [ "Gecko Moria, Shadows' Asgard", "INT", [ "Driven", "Powerhouse" ], 5, 30, 4, 3, 99, 4000000, 1000, 500, -500, 3180, 1430, -999, 1 ], + [ "Brook, Gentlemanly Skeleton", "DEX", [ "Slasher", "Free Spirit" ], 3, 10, 5, 1, 50, 392109, 148, 96, 37, 1067, 491, 196, 1 ], + [ "Brook, Straw Hat Pirates", "DEX", [ "Slasher", "Free Spirit" ], 4, 16, 6, 3, 99, 3000000, 1000, 442, 140, 1990, 847, 316, 1 ], + [ "Sir Crocodile, Sand General", "STR", [ "Cerebral", "Driven" ], 4, 20, 5, 2, 99, 3000000, 89, 41, 24, 2142, 1149, 208, 1 ], + [ "Mr. 3, Makeshift Musician", "QCK", [ "Striker", "Cerebral" ], 4, 17, 4, 2, 99, 2000000, 24, 14, 33, 1703, 622, 312, 1.5 ], + [ "Mr. 2 Bon Clay, Dubious Samurai", "INT", [ "Fighter", "Free Spirit" ], 4, 17, 4, 2, 99, 2000000, 42, 20, 22, 1810, 804, 235, 1.5 ], + [ "Fresh Franky, Health Comes First", "DEX", [ "Shooter", "Free Spirit" ], 4, 25, 6, 2, 70, 1066998, 659, 244, 85, 1330, 659, 211, 1 ], + [ "Cyborg Franky", "DEX", [ "Shooter", "Free Spirit" ], 5, 40, 8, 3, 99, 4000000, 1269, 618, 167, 2515, 1172, 323, 1 ], + [ "Broggy, Giant Warrior Pirates", "PSY", [ "Slasher", "Powerhouse" ], 4, 18, 5, 1, 50, 392109, 261, 120, 20, 1354, 539, 90, 1 ], + [ "Broggy the Red Ogre", "PSY", [ "Slasher", "Powerhouse" ], 5, 30, 4, 3, 99, 3000000, 1292, 463, 64, 2460, 1090, 156, 1 ], + [ "Yokozuna", "STR", [ "Fighter", "Powerhouse" ], 4, 20, 4, 2, 70, 1778330, 520, 170, 45, 1852, 700, 162, 1 ], + [ "Roronoa Zoro, Gloom Island Swordsman", "STR", [ "Slasher", "Driven" ], 4, 18, 6, 3, 70, 1066998, 200, 142, 15, 1492, 750, 101, 1 ], + [ "Roronoa Zoro, Pupil of the World's Strongest Swordsman", "STR", [ "Slasher", "Driven" ], 5, 30, 5, 4, 99, 4000000, 1403, 687, 67, 2830, 1390, 190, 1 ], + [ "Nico Robin, Tequila Wolf Inmate", "INT", [ "Cerebral", "Fighter" ], 4, 18, 4, 3, 70, 1066998, 131, 91, 43, 1021, 679, 217, 1 ], + [ "Nico Robin, Flame of the Revolution", "INT", [ "Cerebral", "Fighter" ], 5, 30, 4, 4, 99, 4000000, 946, 593, 178, 2011, 1156, 400, 1 ], + [ "Tony Tony Chopper, Birdie Kingdom Peace Broker", "PSY", [ "Fighter", "Cerebral" ], 4, 18, 6, 3, 70, 1066998, 187, 70, 42, 1300, 504, 220, 1 ], + [ "Chopper Mask, Defender of Peace", "PSY", [ "Fighter", "Cerebral" ], 5, 30, 4, 4, 99, 4000000, 1234, 447, 170, 2500, 912, 404, 1 ], + [ "Sanji, Kamabakka Kingdom Escapee", "DEX", [ "Powerhouse", "Fighter" ], 4, 18, 4, 3, 70, 1066998, 212, 124, 20, 1575, 701, 127, 1 ], + [ "Sanji, Chef of Love", "DEX", [ "Powerhouse", "Fighter" ], 5, 30, 4, 4, 99, 4000000, 1498, 634, 85, 2926, 1349, 201, 1 ], + [ "Brook, Harahetternia's Demon Lord", "QCK", [ "Free Spirit", "Slasher" ], 4, 18, 6, 3, 70, 1066998, 159, 90, 39, 1281, 597, 201, 1 ], + [ "Brook, BONE to be Wild!!!", "QCK", [ "Free Spirit", "Slasher" ], 5, 30, 4, 4, 99, 4000000, 1220, 531, 150, 2392, 1137, 352, 1 ], + [ "Nico Robin, Bride of Ohara", "QCK", [ "Cerebral", "Fighter" ], 4, 12, 4, 2, 50, 392109, 72, 38, 43, 899, 409, 105, 1 ], + [ "Beautiful and Talented Woman Wedding Robin", "QCK", [ "Cerebral", "Fighter" ], 5, 20, 4, 3, 99, 3000000, 826, 327, 143, 1851, 812, 371, 1 ], + [ "Marguerite", "QCK", "Shooter", 3, 13, 4, 1, 50, 392109, 80, 53, 37, 920, 577, 207, 1 ], + [ "Marguerite, Gaurdian Warrior", "QCK", "Shooter", 4, 20, 5, 2, 99, 3000000, 854, 516, 145, 1563, 1070, 335, 1 ], + [ "Aphelandra", "QCK", "Slasher", 3, 15, 6, 1, 70, 1066998, 98, 42, 32, 2001, 604, 141, 1 ], + [ "Sweetpea", "STR", [ "Powerhouse", "Shooter" ], 3, 15, 4, 2, 70, 1066998, 210, 157, 26, 1041, 1041, 155, 1 ], + [ "Boa Hancock, Bride of the Island of Women", "INT", [ "Shooter", "Free Spirit" ], 4 , 13 , 4 , 2 , 50 ,392109, 142 , 91 , 46 ,912,556,153,1], + [ "Empress in Love Hancock, Wedding", "INT", [ "Shooter", "Free Spirit" ], 5 , 20 , 4 , 3 , 99 ,3000000, 832 , 497 , 106 ,1913,1012,294,1], + [ "Captain Kid of the South Blue", "STR", [ "Striker", "Driven" ], 4, 25, 4, 2, 70, 1066998, 710, 309, 44,1600,703,146,1], + [ "Captain Kid, Kid Pirates Captain", "STR", [ "Striker", "Driven" ], 5, 40, 4, 3, 99, 4000000, 1549, 640, 112,2727,1319,224,1], + [ "Secuurity Chief Miss Sadie", "QCK", [ "Striker", "Free Spirit" ],4, 18, 6, 1, 50,392109, 413, 246, 88, 977, 544, 191, 1], + [ "Secuurity Chief Miss Sadie, Jailer Beasts Commander", "QCK", ["Striker", "Free Spirit"], 5, 30, 4, 3, 99, 3000000, 920, 488, 159, 1901, 912, 357, 1], + [ "Doberman, Navy HQ Vice Admiral", "INT", [ "Slasher", "Driven" ], 4, 20, 6, 2, 70, 1778330, 200, 210, 71, 1085, 951, 205, 1], + [ "Hannyabal", "DEX", ["Driven", "Striker"],3, 13, 6, 1, 50, 392109, 157, 44, 39, 1412, 497, 151, 1], + [ "Hannyabal, Impel Down Vice Warden", "DEX", [ "Driven", "Striker" ],4, 20, 4, 2, 99, 3000000, 1333, 429, 102, 2603, 940, 205, 1], + [ "Saldeath", "INT", [ "Striker", "Cerebral" ], 3, 15, 4, 2, 70, 1066998, 34, 25, 34, 1095, 501, 274, 1], + [ "Blugori", "DEX", [ "Powerhouse", "Slasher" ], 3, 11, 4, 0, 50, 392109, 103, 99, 1, 1119, 999, 31, 1], + [ "Pica", "PSY", [ "Powerhouse","Driven" ], 4, 30, 4, 1, 70, 1066998, 300, 99, 5, 1730, 630, 6, 1], + [ "Pica, Donquixote Pirates", "PSY", [ "Powerhouse", "Driven" ], 5, 50, 4, 2, 99, 5000000, 1660, 552, 5, 4050, 1180, 9, 1], + [ "Knight of the Sea Jinbe", "INT", [ "Fighter", "Powerhouse" ], 5, 30, 5, 4, 70, 1066998, 572, 268, 102, 1841, 797, 229, 1], + [ "Knight of the Sea Jinbe, Warlord of the Sea", "INT", [ "Fighter", "Powerhouse" ], 6, 55, 4, 5, 99, 5000000, 1787, 733, 179, 3400, 1440, 347, 1], + [ "Monkey D. Luffy, Summit War Survivor", "QCK", [ "Fighter", "Free Spirit" ], 4, 18, 7, 3, 70, 1066998, 151, 150, 21, 1220, 764, 149, 1], + [ "Monkey D. Luffy, Crew's Promise: 3D2Y", "QCK", [ "Fighter", "Free Spirit" ], 5, 30, 4, 4, 99, 4000000, 1173, 712, 99, 2406, 1415, 257, 1], + [ "Nami, Weather Researcher", "PSY", [ "Striker", "Cerebral" ], 4, 18, 4, 3, 70, 1066998, 141, 80, 48, 1102, 584, 233, 1], + [ "Nami, Weatheria's Cat Burglar", "PSY", [ "Striker", "Cerebral" ], 5, 30, 5, 4, 99, 4000000, 1037, 522, 189, 2119, 1081, 413, 1], + [ "Usopp, Bowin Islands Food Addict", "DEX", "Fighter", 4, 18, 6, 3, 70, 1066998, 271, 52, 34, 1748, 453, 172, 1], + [ "Usopp, Swindling Forest's Resolute Warrior", "DEX", "Shooter", 5, 30, 4, 4, 99, 4000000, 1669, 398, 131, 3239, 800, 323, 1], + [ "Franky, Mech-Animal Fighting Cyborg", "STR", [ "Free Spirit", "Shooter" ], 4, 18, 4, 3, 70, 1066998, 220, 112, 22, 1603, 686, 131, 1], + [ "Cyborg Franky, Sacred Beast of Baldimore", "STR", [ "Free Spirit", "Shooter" ], 5, 30, 4, 4, 99, 4000000, 1535, 635, 88, 2810, 1249, 244, 1], + [ "Perona, Malicious Old Castle Bride", "PSY", [ "Shooter", "Driven" ], 4, 13, 4, 2, 50, 392109, 59, 34, 47, 814, 392, 223, 1], + [ "Fancy Princess Wedding Perona", "PSY", [ "Shooter", "Driven" ], 5, 20, 5, 3, 99, 3000000, 740, 333, 172, 1787, 787, 390, 1], + [ "Rakuyo, Whitebeard 7th Div. Commander", "INT", [ "Striker", "Powerhouse" ], 4, 25, 6, 3, 99, 3000000, 58, 27, 33, 2077, 1055, 218, 1], + [ "Fossa, Whitebeard 15th Div. Commander", "INT", [ "Slasher", "Powerhouse" ], 4, 25, 6, 3, 99, 3000000, 48, 35, 20, 1910, 1231, 187, 1], + [ "Curiel, Whitebeard 10th Div. Commander", "STR", [ "Shooter", "Powerhouse" ], 4, 25, 5, 3, 99, 3000000, 33, 39, 30, 1706, 1251, 212, 1], + [ "Thatch, Whitebeard 4th Div. Commander", "PSY", [ "Slasher", "Cerebral" ], 4, 25, 5, 3, 99, 3000000, 80, 37, 37, 1995, 1088, 227, 1], + [ "Ace, Whitebeard 2nd Div. Commander", "PSY", [ "Free Spirit", "Fighter" ], 4, 25, 5, 2, 70, 1066998, 606, 313, 54, 1496, 744, 152, 1], + [ "Fire Fist Ace, Whitebeard 2nd Div. Commander", "PSY", [ "Free Spirit", "Fighter" ], 5, 40, 4, 3, 99, 4000000, 1431, 690, 110, 2599, 1271, 271, 1], + [ "Ben Beckman", "DEX", [ "Striker", "Shooter" ], 3, 13, 6, 1, 35, 136167, 131, 98, 25, 935, 375, 163, 1], + [ "Ben Beckman, Red Hair Pirates", "DEX", [ "Striker", "Shooter" ], 4, 20, 4, 2, 70, 1778330, 867, 329, 122, 1403, 800, 229, 1], + [ "Gyaro", "QCK", [ "Slasher", "Powerhouse" ], 3, 7, 6, 2, 50, 392109, 950, 427, 36, 1420, 627, 98, 1], + [ "Macro", "PSY", [ "Shooter", "Powerhouse" ], 3, 7, 4, 2, 50, 392109, 972, 390, 44, 1447, 591, 110, 1], + [ "Tansui", "INT", [ "Fighter", "Powerhouse" ], 3, 7, 4, 2, 50, 392109, 933, 468, 31, 1368, 701, 84, 1], + [ "Quick-Draw Gunman, Blue Bodyguard", "QCK", "Shooter", 3, 11, 6, 1, 60, 1123790, 72, 57, 59, 743, 556, 265, 1], + [ "Scheming Gunman, Black Bodyguard", "INT", "Shooter", 3, 11, 6, 1, 60, 1123790, 64, 64, 57, 709, 597, 257, 1], + [ "Technical Gunman, Green Bodyguard", "DEX", "Shooter", 3, 11, 6, 1, 60, 1123790, 80, 69, 51, 785, 640, 230, 1], + [ "Quick-Strike Gunman, Blue Bodyguard", "QCK", "Shooter", 3, 11, 6, 1, 60, 1123790, 84, 66, 52, 805, 612, 236, 1], + [ "Strong-Arm Gunman, Red Bodyguard", "STR", "Shooter", 3, 11, 6, 1, 60, 1123790, 82, 80, 44, 821, 700, 204, 1], + [ "Bold Gunman, Yellow Bodyguard", "PSY", "Shooter", 3, 11, 6, 1, 60, 1123790, 89, 73, 46, 855, 656, 213, 1], + [ "Saint Charlos", "STR", "Shooter", 6, 99, 7, 0, 99, 1000000, 5, 320, -500, 25, 554, -400, 1], + [ "Saint Roswald", "DEX", "Shooter", 6, 99, 7, 0, 99, 1000000, 6, 334, -600, 30, 601, -500, 1], + [ "Saint Shalria", "QCK", "Shooter", 6, 99, 7, 0, 99, 1000000, 4, 293, -400, 20, 503, -300, 1], + [ "Eustass Kid, Supernova", "QCK", [ "Driven", "Striker" ], 4, 20, 5, 3, 99, 3000000, 462, 299, 19, 2301, 1205, 128, 1], + [ "Trafalgar Law, Supernova", "INT", [ "Slasher", "Free Spirit" ], 4, 20, 4, 3, 99, 3000000, 440, 244, 41, 2035, 1013, 243, 1], + [ "Pacifista PX-1", "DEX", [ "Shooter", "Powerhouse" ], 4, 40, 4, 0, 70, 1422664, 2000, 1000, -100, 2009, 1016, 1, 1], + [ "Pacifista PX-2", "PSY", [ "Shooter", "Powerhouse" ], 4, 40, 4, 0, 70, 1422664, 2000, 1000, -100, 2009, 1016, 1, 1], + [ "Pacifista PX-3", "QCK", [ "Shooter", "Powerhouse" ], 4, 40, 4, 0, 70, 1422664, 2000, 1000, -100, 2009, 1016, 1, 1], + [ "Pacifista PX-4", "STR", [ "Shooter", "Powerhouse" ], 4, 40, 4, 0, 70, 1422664, 2000, 1000, -100, 2009, 1016, 1, 1], + [ "Pacifista PX-5", "INT", [ "Shooter", "Powerhouse" ], 4, 40, 4, 0, 70, 1422664, 2000, 1000, -100, 2009, 1016, 1, 1], + [ "Sentomaru", "PSY", [ "Fighter", "Powerhouse" ], 3, 12, 5, 1, 50, 392109, 105, 38, 10, 1202, 557, 137, 1], + [ "Sentomaru, Marine Science Unit Commander", "PSY", [ "Fighter", "Powerhouse" ], 4, 20, 4, 3, 99, 3000000, 1125, 497, 92, 2209, 1000, 214, 1], + [ "Smoker, Wild Lone Wolf", "DEX", ["Striker", "Driven"], 4, 10, 6, 3, 35, 90778, 210, 86, 100, 610, 286, 273, 1], + [ "Smoker, Solitary Lone Wolf", "DEX", ["Striker", "Driven"], 5, 18, 4, 3, 70, 1066998, 556, 240, 241, 1128, 556, 379, 1], + [ "Kizaru", "QCK", ["Shooter", "Fighter"], 4, 30, 4, 2, 70, 1066998, 221, 169, 36, 1241, 741, 160, 1], + [ "Kizaru, Light Human", "QCK", ["Shooter", "Fighter"], 5, 50, 5, 3, 99, 5000000, 1179, 665, 130, 2506, 1410, 277, 1], + [ "Izo Whitebeard 16th Div. Commander", "PSY", ["Shooter", "Cerebral"], 4, 25, 6, 3, 99, 3000000, 37, 22, 39, 1910, 990, 300, 1 ], + [ "Blamenco Whitebeard 6th Div. Commander", "DEX", ["Striker", "Free Spirit"], 4, 25, 4, 3, 99, 3000000, 66, 40, 18, 2394, 1268, 126, 1 ], + [ "Namule Whitebeard 8th Div. Commander", "PSY", ["Fighter", "Powerhouse"], 4, 25, 4, 3, 99, 3000000, 49, 48, 26, 2148, 1305, 154, 1 ], + [ "Vista Whitebeard 5th Div. Commander", "QCK", ["Slasher", "Powerhouse"], 4, 25, 5, 2, 70, 1066998, 694, 277, 48, 1603, 700, 141, 1 ], + [ "Flower Sword Vista Whitebeard 5th Div. Commander", "QCK", ["Slasher", "Powerhouse"], 5, 40, 4, 3, 99, 4000000, 1534, 634, 98, 2830, 1257, 228, 1 ], + [ "Paulie Galley-La Company Dock One Foreman","PSY",["Striker","Powerhouse"], 4, 30, 6, 2, 99, 3000000, 321, 132, 30, 2404, 1024, 243, 1 ], + [ "Demalo Black & Chocolat, Impostor Straw Hat Pirates","STR","Driven", 3, 5, 6, 0, 20, 17456, 94, 33, 15, 571, 280, 77, 1], + [ "Cocoa & Nora Gitsune, Impostor Straw Hat Pirates","INT","Driven", 3, 5, 6, 0, 20, 17456, 79, 21, 28, 489, 224, 110, 1], + [ "Manjaro & Drip, Impostor Straw Hat Pirates","DEX","Driven", 3, 5, 6, 0, 20, 17456, 44, 34, 21, 387, 308, 97, 1], + [ "Mounblutain & Turco, Impostor Straw Hat Pirates","PSY","Driven", 3, 5, 6, 0, 20, 17456, 103, 23, 18, 612, 258 , 79, 1], + [ "Impostor Straw Hats","STR",["Driven","Shooter"], 4, 15, 8, 3, 50, 653515, 561, 330, 36, 1288, 604, 110, 1], + [ "Machvise","INT",["Free Spirit","Powerhouse"], 4, 18, 4, 3, 70, 1066998, 203, 127, 34, 1589, 716, 105, 1 ], + [ "Machvise, Donquixote Pirates","INT",["Free Spirit","Powerhouse"], 5, 30, 4, 4, 99, 4000000, 1523, 643, 49, 2882, 1280, 217, 1 ], + [ "Gladius","QCK",["Shooter","Driven"], 4, 18, 6, 3, 70, 1066998, 102, 161, 32, 1079, 813, 154, 1 ], + [ "Gladius, Donquixote Pirates","QCK",["Shooter","Driven"], 5, 30, 4, 4, 99, 4000000, 1000, 767, 101, 2375, 1371, 271, 1 ], + [ "Violet","PSY",["Fighter","Cerebral"], 4, 18, 5, 3, 70, 1066998, 147, 48, 77, 1157, 451, 274, 1 ], + [ "Violet, Donquixote Pirates","PSY",["Fighter","Cerebral"], 5, 30, 4, 4, 99, 4000000, 1095, 400, 220, 2217, 813, 483, 1 ], + [ "Dellinger","DEX",["Powerhouse","Fighter"], 4, 18, 6, 3, 70, 1066998, 91, 147, 51, 999, 755, 192, 1 ], + [ "Dellinger, Donquixote Pirates","DEX",["Powerhouse","Fighter"], 5, 30, 4, 4, 99, 4000000, 933, 692, 143, 2087, 1362, 324, 1 ], + [ "Diamante","STR",["Driven","Striker"], 4, 18, 6, 3, 70, 1066998, 698, 452, 48, 1500, 866, 90, 1 ], + [ "Diamante, Donquixote Pirates","STR",["Driven","Striker"], 5, 30, 5, 4, 99, 4000000, 1443, 812, 50, 2840, 1421, 174, 1 ], + [ "Corazon, Donquixote Pirates","DEX",["Free Spirit","Cerebral"], 5, 30, 4, 4, 70, 1066998, 406, 196, 155, 1503, 694, 320, 1 ], + [ "Donquixote Rosinante","DEX",["Free Spirit","Cerebral"], 6, 55, 4, 5, 99, 5000000, 1428, 628, 272, 2746, 1222, 555, 1 ], + [ "Bepo, Heart Pirates", "STR", ["Fighter", "Powerhouse"], 3, 12, 4, 1, 50, 392109, 96, 53, 46, 1003, 525, 213, 1], + [ "Bepo the Martial Artist, Heart Pirates", "STR", ["Fighter", "Powerhouse"], 4, 20, 4, 2, 99, 3000000, 921, 461, 162, 1803, 1054, 307, 1], + [ "Sachi & Penguin, Heart Pirates", "QCK", ["Fighter", "Free Spirit"], 4, 15, 5, 2, 70, 1066998, 92, 37, 36, 1059, 701, 231, 1], + [ "Jean Bart", "STR", ["Powerhouse", "Fighter"], 3, 12, 5, 1, 50, 392109, 194, 55, 13, 1404, 541, 96, 1], + [ "Jean Bart, Heart Pirates", "STR", ["Powerhouse", "Fighter"], 4, 20, 4, 2, 99, 3000000, 1337, 488, 44, 2614, 1069, 153, 1], + [ "Monet Cold Season Cherry Blossoms","QCK",["Free Spirit","Cerebral"], 4, 13, 6, 2, 50, 392109, 67, 37, 55, 884, 428, 204, 1], + [ "Monet Coldest Season Cherry Blossoms","QCK",["Free Spirit","Cerebral"], 5, 20, 6, 3, 99, 3000000, 831, 366, 162, 1660, 869, 384, 1], + [ "Kizuna BOOST Luffy", "STR", ["Fighter","Powerhouse"], 4, 20, 6, 2, 99, 3000000, 465, 232, 36, 1978, 1170, 220, 1 ], + [ "Count Butler", "INT", ["Driven","Cerebral"], 3, 12, 4, 1, 50, 392109, 103, 25, 41, 1172, 377, 220, 1 ], + [ "Count Butler, King's Power", "INT", ["Driven","Powerhouse"], 4, 20, 5, 2, 99, 3000000, 1175, 606, 50, 2152, 1100, 220, 1 ], + [ "President Heaby", "QCK", ["Slasher","Driven"], 3, 15, 6, 1, 70, 1422664, 118, 78, 32, 1221, 799, 203, 1 ], + [ "General Hotdog", "DEX", ["Fighter","Driven"], 3, 15, 4, 1, 70, 1422664, 105, 86, 24, 1147, 890, 181, 1 ], + [ "Tony Tony Chopper, Animal King", "PSY", ["Fighter","Powerhouse"], 4, 16, 4, 2, 70, 1422664, 63, 40, 44, 1154, 719, 280, 1 ], + [ "Capone Bege, Captain of the Firetank Pirates", "INT", ["Shooter","Driven"], 4, 25, 4, 2, 70, 1066998, 494, 313, 80, 962, 749, 244, 1], + [ "Capone \"Gang\" Bege, Captain of the Firetank Pirates", "INT", ["Shooter","Driven"], 5, 40, 6, 3, 99, 4000000, 900, 688, 197, 1903, 1361, 379, 1], + [ "Brownbeard", "PSY", ["Slasher","Driven"], 4, 18, 6, 2, 50, 392109, 230, 101, 33, 1202, 504, 137, 1], + [ "Brownbeard, Alligator Centaur", "PSY", ["Slasher","Powerhouse"], 5, 30, 6, 2, 99, 3000000, 1127, 444, 90, 2500, 1000, 220, 1], + [ "Peeply Lulu Galley-La Company Dock One Foreman ", "DEX", "Slasher", 4, 20, 6, 2, 70, 1778330, 155, 93, 40, 1184, 720, 280, 1], + [ "Sugar Cherry Tree", "INT", ["Shooter","Cerebral"], 4, 13, 7, 2, 50, 392109, 41, 24, 64, 799, 355, 249, 1], + [ "Sugar Cherry", "INT", ["Shooter","Cerebral"], 5, 20, 5, 3, 99, 3000000, 731, 300, 198, 1621, 717, 442, 1], + [ "Monkey D. Luffy Road to Pirate King", "PSY", ["Fighter","Free Spirit"], 4, 15, 4, 2, 99, 2000000, 200, 56, 55, 2000, 1000, 300, 1 ], + [ "Portgas D. Ace Dream that Lead to the Pirate King", "INT", [ "Shooter", "Free Spirit" ], 4, 20, 5, 2, 99, 2000000, 159, 98, 41, 1773, 1310, 221, 1.5 ], + [ "Don Chinjao", "INT", [ "Powerhouse","Fighter" ], 4, 18, 6, 3, 70, 1066998, 226, 187, 17, 1505, 808, 100, 1 ], + [ "Don Chinjao, Kano Kingdom Gang", "INT", [ "Powerhouse","Striker" ], 5, 30, 4, 4, 99, 4000000, 1433, 746, 68, 2818, 1424, 185, 1 ], + [ "Blue Gilly", "QCK", [ "Fighter","Free Spirit" ], 4, 18, 6, 3, 70, 1066998, 197, 138, 37, 1330, 689, 162, 1 ], + [ "Blue Gilly, Jiaokungdo Fighter", "QCK", [ "Fighter","Free Spirit" ], 5, 30, 7, 4, 99, 4000000, 1253, 630, 129, 2552, 1300, 277, 1 ], + [ "Funk Brothers", "DEX", [ "Fighter","Driven" ], 4, 18, 5, 3, 70, 1066998, 60, 172, 44, 937, 824, 109, 1 ], + [ "Funk Brothers, Mogaro Kingdom Assassins", "DEX", [ "Fighter","Driven" ], 5, 30, 8, 4, 99, 4000000, 1500, 824, 77, 2920, 1251, 226, 1 ], + [ "Hajrudin", "PSY", [ "Powerhouse","Fighter" ], 4, 18, 5, 3, 70, 1066998, 201, 177, 38, 1403, 795, 116, 1 ], + [ "Hajrudin, Pirate Mercenary", "PSY", [ "Powerhouse","Fighter" ], 5, 30, 4, 4, 99, 4000000, 1337, 740, 57, 2700, 1402, 205, 1 ], + [ "Abdullah and Jeet", "STR", [ "Slasher","Striker" ], 4, 18, 6, 3, 70, 1066998, 143, 143, 52, 1003, 722, 208, 1 ], + [ "Abdullah and Jeet, Former Bounty Hunters", "STR", [ "Slasher","Striker" ], 5, 30, 6, 4, 99, 4000000, 920, 673, 156, 1970, 1345, 343, 1 ], + [ "Bartolomeo", "STR", [ "Striker","Driven" ], 5, 30, 4, 4, 70, 1066998, 403, 278, 58, 1623, 813, 232, 1 ], + [ "Man-Eating Bartolomeo", "STR", [ "Striker","Driven" ], 6, 55, 4, 5, 99, 5000000, 1550, 769, 181, 3505, 1431, 341, 1 ], + [ "Emporio Ivankov Queen of the Secret Garden", "QCK", [ "Free Spirit","Fighter" ], 3, 12, 5, 1, 50, 392109, 161, 39, 39, 1198, 492, 202, 1 ], + [ "Emporio Ivankov Queen of the Garden of Miracles", "QCK", [ "Free Spirit","Fighter" ], 4, 20, 4, 2, 99, 3000000, 1120, 443, 141, 2007, 906, 322, 1 ], + [ "Inazuma Maiden of the Secret Garden", "DEX", [ "Free Spirit","Fighter" ], 3, 7, 6, 1, 35, 136167, 39, 22, 30, 797, 321, 149, 1 ], + [ "Inazuma Maiden Planning to Change ", "DEX", [ "Free Spirit","Fighter" ], 4, 15, 4, 2, 99, 1066998, 730, 267, 100, 1209, 694, 229, 1 ], + [ "Jozu Whitebeard 3rd Div. Commander", "STR", [ "Fighter", "Powerhouse" ], 4, 25, 6, 2, 70, 1066998, 626, 252, 60, 1464, 700, 169, 1 ], + [ "\"Diamond\" Jozu Whitebeard 3rd Div. Commander", "STR", [ "Fighter", "Powerhouse" ], 5, 40, 5, 3, 99, 4000000, 1392, 640, 120, 2748, 1299, 249, 1 ], + [ "Killer, Kid Pirates", "DEX", [ "Striker", "Slasher" ], 4, 25, 6, 2, 70, 1066998, 455, 310, 36, 949, 797, 113, 1 ], + [ "\"Massacre Soldier\" Killer, Kid Pirates", "DEX", [ "Striker", "Slasher" ], 5, 40, 4, 3, 99, 4000000, 887, 728, 64, 1879, 1424, 189, 1 ], + [ "Trafalgar Law, Worst Generation", "PSY", [ "Slasher", "Free Spirit" ], 5, 30, 4, 4, 70, 1066998, 549, 341, 138, 1378, 813, 297, 1 ], + [ "Trafalgar Law Warlord of the Sea", "PSY", [ "Slasher", "Free Spirit" ], 6, 55, 6, 5, 99, 5000000, 1302, 747, 241, 2790, 1484, 470, 1 ], + [ "Sabo, Dragon Claw", "DEX", [ "Free Spirit", "Fighter" ], 4, 30, 5, 2, 70, 1066998, 233, 140, 34, 1296, 686, 186, 1 ], + [ "Sabo, Revolutionary Army Chief of Staff", "DEX", [ "Free Spirit", "Fighter" ], 5, 50, 4, 3, 99, 5000000, 1228, 602, 142, 2484, 1325, 340, 1 ], + [ "Nico Olvia", "PSY", [ "Shooter", "Cerebral" ], 3, 12, 6, 1, 50, 392109, 77, 29, 59, 883, 404, 274, 1 ], + [ "Nico Olvia, Archaeologist of Ohara", "PSY", [ "Shooter", "Cerebral" ], 4, 20, 4, 2, 99, 3000000, 800, 339, 223, 1602, 713, 461, 1 ], + [ "Jaguar D. Saul", "PSY", [ "Powerhouse", "Free Spirit" ], 3, 12, 5, 1, 50, 392109, 173, 56, 29, 1353, 514, 157, 1 ], + [ "Jaguar D. Saul, Navy HQ Vice Admiral", "PSY", [ "Powerhouse", "Free Spirit" ], 4, 20, 4, 2, 99, 3000000, 1278, 441, 110, 2448, 929, 236, 1 ], + [ "Nico Robin, Girl of Ohara", "QCK", [ "Cerebral", "Fighter" ], 3, 9, 4, 2, 50, 392109, 38, 18, 94, 522, 273, 378, 1 ], + [ "Hina, Graceful Honor Student", "QCK", [ "Striker", "Cerebral" ], 4, 10, 5, 3, 35, 90778, 85, 27, 55, 511, 220, 257, 1 ], + [ "Hina, Polite Honor Student", "QCK", [ "Striker", "Cerebral" ], 5, 18, 5, 3, 70, 1066998, 501, 198, 259, 1044, 500, 414, 1 ], + [ "Boa Sandersonia", "DEX", [ "Fighter" ], 3, 12, 6, 1, 50, 392109, 249, 72, 47, 1040, 500, 176, 1 ], + [ "Boa Sandersonia, Kuja Pirates", "DEX", [ "Striker", "Powerhouse" ], 4, 20, 4, 3, 99, 3000000, 1043, 442, 137, 1772, 905, 318, 1 ], + [ "Boa Marigold", "STR", [ "Striker" ], 3, 12, 5, 1, 50, 392109, 183, 40, 31, 1062, 517, 158, 1 ], + [ "Boa Marigold, Kuja Pirates", "STR", [ "Slasher", "Powerhouse" ], 4, 20, 4, 3, 99, 3000000, 1003, 470, 110, 1892, 947, 284, 1 ], + [ "Marguerite, Female Warrior", "PSY", [ "Shooter" ], 3, 9, 4, 1, 35, 136167, 136, 72, 62, 699, 401, 189, 1 ], + [ "Marguerite, Kuja Warrior", "PSY", [ "Shooter" ], 4, 15, 5, 2, 70, 1066998, 642, 339, 143, 1003, 713, 301, 1 ], + [ "Kikyo", "QCK", [ "Shooter" ], 4, 14, 5, 2, 70, 1066998, 132, 94, 56, 999, 741, 262, 1 ], + [ "Gloriosa", "INT", [ "Cerebral", "Fighter" ], 3, 14, 4, 2, 60, 674274, 586, 351, 79, 612, 378, 400, 1 ], + [ "Destructive Archer, Kuja Warriors", "STR", [ "Shooter" ], 3, 10, 5, 1, 60, 674274, 62, 31, 40, 933, 574, 252, 1 ], + [ "Sneaky Archer, Kuja Warriors", "INT", [ "Shooter" ], 3, 10, 5, 1, 60, 674274, 58, 28, 44, 901, 549, 266, 1 ], + [ "Wise Swordswoman, Kuja Warriors", "INT", "Slasher", 3, 10, 4, 1, 60, 674274, 65, 98, 25, 787, 880, 174, 1 ], + [ "Bright Swordswoman, Kuja Warriors", "PSY", "Slasher", 3, 10, 4, 1, 60, 674274, 63, 90, 30, 762, 843, 191, 1 ], + [ "Proficient Fighter, Kuja Warriors", "DEX", [ "Fighter", "Powerhouse" ], 3, 10, 6, 1, 60, 674274, 120, 50, 26, 1204, 668, 175, 1 ], + [ "Nimble Fighter, Kuja Warriors", "QCK", [ "Fighter", "Powerhouse" ], 3, 10, 6, 1, 60, 674274, 128, 47, 24, 1261, 649, 170, 1 ], + [ "Shuraiya Bascud", "DEX", [ "Fighter", "Driven" ], 3, 9, 5, 2, 35, 136167, 402, 190, 65, 879, 410, 127, 1 ], + [ "\"Pirate Executioner\" Shuraiya Bascud", "DEX", [ "Fighter", "Driven" ], 4, 15, 4, 2, 70, 1066998, 812, 358, 80, 1474, 742, 188, 1 ], + [ "Gasparde", "STR", [ "Powerhouse", "Fighter" ], 3, 12, 5, 1, 50, 392109, 129, 67, 18, 1494, 571, 101, 1 ], + [ "Gasparde, Gasparde Pirates", "STR", [ "Powerhouse", "Striker" ], 4, 20, 5, 4, 99, 3000000, 1437, 516, 63, 2501, 1002, 198, 1 ], + [ "Needless", "QCK", [ "Slasher", "Driven" ], 3, 14, 6, 1, 70, 1066998, 88, 120, 37, 973, 802, 223, 1 ], + [ "Ricky", "INT", [ "Cerebral", "Striker" ], 4, 18, 6, 3, 70, 1066998, 207, 102, 62, 1177, 524, 246, 1 ], + [ "Ricky, Mystery Swordsman", "INT", [ "Cerebral", "Striker" ], 5, 30, 6, 4, 99, 4000000, 1102, 467, 199, 2689, 900, 395, 1 ], + [ "Leo", "QCK", [ "Striker", "Free Spirit" ], 4, 18, 5, 3, 70, 1066998, 131, 142, 54, 979, 700, 222, 1 ], + [ "Leo, Tontatta Corps Leader", "QCK", [ "Striker", "Free Spirit" ], 5, 30, 4, 4, 99, 4000000, 918, 637, 177, 1934, 1351, 371, 1 ], + [ "Mansherry", "PSY", "Striker", 4, 18, 6, 3, 70, 1066998, 100, 94, 86, 717, 416, 307, 1 ], + [ "Mansherry, Princess of the Tontatta Tribe", "PSY", [ "Striker", "Free Spirit" ], 5, 28, 4, 4, 99, 4000000, 642, 371, 260, 1510, 642, 557, 1 ], + [ "Kyros", "DEX", [ "Slasher", "Powerhouse" ], 4, 18, 4, 3, 70, 1066998, 192, 152, 43, 1106, 713, 189, 1 ], + [ "Kyros, Former Captain of the Riku Royal Army", "DEX", [ "Slasher", "Powerhouse" ], 5, 30, 4, 4, 99, 4000000, 1042, 657, 143, 2377, 1373, 290, 1 ], + [ "Don Sai", "STR", [ "Striker", "Fighter" ], 4, 18, 4, 3, 70, 1066998, 130, 130, 31, 1300, 673, 130, 1 ], + [ "Don Sai, Kano Kingdom Gang", "STR", [ "Striker", "Fighter" ], 5, 30, 4, 4, 99, 4000000, 1231, 631, 87, 3013, 1300, 202, 1 ], + [ "Fujitora", "INT", [ "Driven", "Powerhouse" ], 5, 30, 4, 4, 70, 1066998, 430, 250, 77, 1890, 754, 204, 1 ], + [ "Issho", "INT", [ "Driven", "Powerhouse" ], 6, 55, 4, 5, 99, 5000000, 1820, 700, 201, 3809, 1380, 325, 1 ], + [ "Musshuru", "INT", [ "Driven", "Fighter" ], 3, 16, 6, 2, 50, 392109, 103, 110, 34, 729, 530, 189, 1 ], + [ "Musshuru, Poison Spore Human", "INT", [ "Driven", "Striker" ], 4, 26, 4, 3, 99, 3000000, 667, 472, 131, 1419, 1142, 302, 1 ], + [ "Saga", "QCK", [ "Slasher", "Driven" ], 3, 16, 5, 2, 50, 392109, 143, 115, 21, 977, 551, 141, 1 ], + [ "Saga, Cursed Holy Sword", "QCK", [ "Slasher", "Driven" ], 4, 26, 4, 3, 99, 3000000, 912, 497, 93, 1952, 1093, 220, 1 ], + [ "X Drake, Captain of the Drake Pirates", "PSY", [ "Cerebral", "Slasher" ], 4, 25, 5, 2, 70, 1066998, 545, 220, 52, 1353, 693, 179, 1 ], + [ "\"Red Flag\" X Drake, Captain of the Drake Pirates", "PSY", [ "Cerebral", "Powerhouse" ], 5, 40, 4, 3, 99, 4000000, 1297, 631, 130, 2599, 1230, 300, 1 ], + [ "Rebecca, Parasol Rhytm", "PSY", [ "Striker", "Free Spirit" ], 4, 10, 6, 2, 35, 90778, 59, 14, 79, 462, 130, 328, 1 ], + [ "Rebecca, Rainbow Melody", "PSY", [ "Striker", "Free Spirit" ], 5, 17, 4, 3, 70, 1066998, 400, 93, 262, 896, 300, 505, 1 ], + [ "Dr. Indigo", "DEX", [ "Cerebral", "Shooter" ], 3, 12, 4, 1, 50, 392109, 66, 36, 41, 965, 497, 209, 1 ], + [ "Dr. Indigo, Golden Lion Pirates", "DEX", [ "Cerebral", "Shooter" ], 4, 20, 4, 2, 99, 3000000, 903, 432, 163, 1796, 911, 352, 1 ], + [ "Commander Scarlet", "INT", [ "Powerhouse", "Free Spirit" ], 3, 12, 5, 1, 50, 392109, 121, 47, 5, 1323, 520, 59, 1 ], + [ "Commander Scarlet, Golden Lion Pirates", "INT", [ "Powerhouse", "Free Spirit" ], 4, 20, 4, 2, 99, 3000000, 1271, 467, 30, 2302, 980, 92, 1 ], + [ "Billy", "PSY", [ "Shooter", "Powerhouse" ], 3, 10, 4, 2, 50, 392109, 54, 99, 40, 556, 803, 217, 1 ], + [ "Coby, Petty Officer in the Rain", "DEX", [ "Fighter", "Cerebral" ], 4, 13, 6, 2, 50, 392109, 79, 50, 47, 963, 471, 178, 1 ], + [ "Coby, Petty Officer Sparkling with Dew", "DEX", [ "Fighter", "Cerebral" ], 5, 20, 4, 3, 99, 3000000, 897, 429, 134, 1946, 995, 344, 1 ], + [ "Black Arm Zephyr", "STR", [ "Fighter", "Driven" ], 4, 25, 5, 2, 70, 1066998, 545, 404, 0, 1384, 822, 0, 1 ], + [ "Black Arm Zephyr, Former Navy HQ Admiral", "STR", [ "Fighter", "Driven" ], 5, 40, 4, 3, 99, 4000000, 1318, 749, 0, 2620, 1500, 0, 1 ], + [ "Ain, NEO Marines", "INT", [ "Slasher", "Cerebral" ], 4, 18, 5, 2, 50, 392109, 197, 101, 54, 1078, 492, 217, 1 ], + [ "Ain, Zephyr's Last Pupil", "INT", [ "Slasher", "Cerebral" ], 5, 30, 4, 3, 99, 3000000, 1019, 447, 169, 1986, 870, 357, 1 ], + [ "Binz, NEO Marines", "DEX", [ "Striker", "Free Spirit" ], 4, 18, 4, 2, 50, 392109, 220, 122, 32, 1164, 541, 167, 1 ], + [ "Binz, Zephyr's Last Pupil", "DEX", [ "Striker", "Free Spirit" ], 5, 30, 4, 3, 99, 3000000, 1091, 484, 115, 2107, 1042, 280, 1 ], + [ "Shiki the Golden Lion", "STR", [ "Driven", "Slasher" ], 4, 30, 4, 2, 70, 1066998, 244, 164, 39, 1274, 709, 177, 1 ], + [ "Shiki the Golden Lion, Golden Lion Pirates", "STR", [ "Driven", "Slasher" ], 5, 50, 4, 3, 99, 5000000, 1218, 638, 138, 2424, 1407, 292, 1 ], + [ "Nami, Rejuvenated Navigator", "PSY", [ "Cerebral", "Fighter" ], 3, 9, 5, 2, 50, 392109, 46, 27, 39, 770, 389, 266, 1 ], + [ "Nami, Mischievous Tevern Idol", "PSY", [ "Cerebral", "Striker" ], 4, 18, 4, 3, 99, 3000000, 718, 322, 220, 1505, 707, 426, 1 ], + [ "Nico Robin, Rejuvenated Archaeologist", "QCK", [ "Cerebral", "Fighter" ], 3, 12, 6, 2, 50, 392109, 95, 39, 24, 992, 524, 162, 1 ], + [ "Nico Robin, Fetching Tavern Dancer", "QCK", [ "Cerebral", "Fighter" ], 4, 20, 4, 3, 99, 3000000, 921, 468, 119, 1789, 941, 346, 1 ], + [ "Chopper, Rejuvenated Doctor", "INT", [ "Striker", "Cerebral" ], 3, 9, 4, 2, 50, 392109, 67, 55, 49, 524, 506, 300, 1 ], + [ "Monkey D. Luffy, Dream Chaser", "STR", [ "Fighter", "Free Spirit" ], 4, 17, 4, 3, 70, 1066998, 242, 148, 28, 1505, 744, 106, 1 ], + [ "Monkey D. Luffy, A Pirate Who Lives By His Code", "STR", [ "Fighter", "Free Spirit" ], 5, 27, 8, 4, 99, 4000000, 1438, 676, 72, 2722, 1411, 176, 1 ], + [ "Sanji, Dream Chaser", "INT", [ "Fighter", "Powerhouse" ], 4, 17, 4, 3, 70, 1066998, 268, 115, 32, 1545, 698, 122, 1 ], + [ "Sanji, A Pirate Who Lives By His Code", "INT", [ "Fighter", "Powerhouse" ], 5, 27, 5, 4, 99, 4000000, 1471, 630, 86, 2834, 1224, 226, 1 ], + [ "Nami, Dream Chaser", "QCK", [ "Striker", "Cerebral" ], 4, 17, 5, 3, 70, 1066998, 190, 81, 57, 1051, 602, 230, 1 ], + [ "Nami, A Pirate Who Lives By Her Code", "QCK", [ "Striker", "Cerebral" ], 5, 27, 6, 4, 99, 4000000, 979, 540, 191, 1980, 1000, 455, 1 ], + [ "Monkey D. Luffy, Wakes of the Endless Dream, Straw Hat Crew", "STR", [ "Fighter", "Free Spirit" ], 5, 30, 4, 3, 70, 1066998, 390, 290, 150, 1559, 840, 290, 1 ], + [ "Monkey D. Luffy, A Vow in the Great Age of Pirates - Pirate King", "STR", [ "Fighter", "Free Spirit" ], 6, 55, 4, 4, 99, 5000000, 1490, 776, 250, 3440, 1430, 351, 1 ], + [ "Cavendish", "QCK", [ "Slasher", "Driven" ], 5, 30, 4, 4, 70, 1066998, 504, 277, 148, 1603, 808, 287, 1 ], + [ "White Knight Cavendish", "QCK", [ "Slasher", "Driven" ], 6, 55, 4, 5, 99, 5000000, 1541, 749, 231, 2970, 1460, 438, 1 ], + [ "Suleiman", "PSY", [ "Slasher", "Cerebral" ], 4, 18, 6, 3, 70, 1066998, 102, 151, 34, 981, 780, 201, 1 ], + [ "Suleiman the Beheader", "PSY", [ "Slasher", "Cerebral" ], 5, 30, 7, 4, 99, 4000000, 903, 713, 144, 2000, 1410, 336, 1 ], + [ "Orlumbus", "DEX", [ "Powerhouse", "Striker" ], 4, 18, 4, 3, 70, 1066998, 201, 102, 22, 1461, 668, 152, 1 ], + [ "Orlumbus, Massacre Ruler", "DEX", [ "Powerhouse", "Striker" ], 5, 30, 6, 4, 99, 4000000, 1389, 584, 103, 3065, 1180, 231, 1 ], + [ "Dagama", "INT", [ "Slasher", "Driven" ], 4, 18, 6, 3, 70, 1066998, 177, 52, 31, 1332, 554, 213, 1 ], + [ "Dagama, Prodence Kingdom Tactician", "INT", [ "Slasher", "Driven" ], 5, 30, 5, 4, 99, 4000000, 1255, 490, 150, 2940, 978, 320, 1 ], + [ "Elizabello II", "STR", [ "Powerhouse", "Fighter" ], 4, 18, 5, 3, 70, 1066998, 123, 157, 20, 1137, 800, 177, 1 ], + [ "Elizabello II, King of Prodence Kingdom", "STR", [ "Powerhouse", "Fighter" ], 5, 30, 4, 4, 99, 4000000, 1070, 724, 131, 2152, 1400, 303, 1 ], + [ "Ideo", "QCK", [ "Shooter", "Fighter" ], 4, 18, 5, 3, 70, 1066998, 151, 120, 29, 1230, 679, 180, 1 ], + [ "Destruction Cannon Ideo", "QCK", [ "Shooter", "Fighter" ], 5, 30, 5, 4, 99, 4000000, 1171, 603, 123, 2404, 1318, 294, 1 ], + [ "Tashigi, Brash Kendo Girl", "INT", [ "Striker", "Cerebral" ], 4, 10, 6, 3, 35, 90778, 91, 25, 56, 600, 232, 291, 1 ], + [ "Tashigi, Dream Kendo Girl", "INT", [ "Striker", "Cerebral" ], 5, 18, 4, 3, 70, 1066998, 523, 177, 252, 1088, 483, 418, 1 ], + [ "Fukuro, Secret Intelligence Agency CP9", "QCK", [ "Powerhouse", "Fighter" ], 4, 20, 8, 2, 99, 2000000, 73, 32, 38, 1462, 730, 342, 1 ], + [ "Jabra, Secret Intelligence Agency CP9", "STR", [ "Powerhouse", "Free Spirit" ], 4, 25, 6, 3, 99, 3000000, 76, 59, 29, 1992, 1210, 210, 1 ], + [ "Blueno, Secret Intelligence Agency CP9", "PSY", [ "Powerhouse", "Fighter" ], 4, 20, 4, 2, 99, 2000000, 99, 30, 19, 2330, 712, 193, 1 ], + [ "Kumadori, Secret Intelligence Agency CP9", "DEX", [ "Powerhouse", "Striker" ], 4, 20, 4, 2, 99, 2000000, 84, 35, 32, 1707, 803, 277, 1 ], + [ "Gecko Moria, Lord of Florian Triangle", "DEX", [ "Slasher", "Driven" ], 4, 25, 4, 2, 70, 1066998, 689, 223, 31, 1505, 700, 112, 1 ], + [ "Gecko Moria, Ruler of Florian Triangle", "DEX", [ "Slasher", "Driven" ], 5, 40, 4, 3, 99, 4000000, 1419, 629, 79, 3023, 1211, 229, 1 ], + [ "Foxy, Nuisance of Donut Race", "STR", [ "Free Spirit", "Fighter" ], 3, 16, 5, 2, 50, 392109, 165, 94, 44, 949, 503, 162, 1 ], + [ "Foxy, Cowardly Fighter", "STR", [ "Free Spirit", "Shooter" ], 4, 26, 4, 3, 99, 3000000, 867, 424, 120, 1877, 942, 313, 1 ], + [ "Porche, Flower Cheerleader", "PSY", [ "Shooter", "Striker" ], 3, 10, 6, 2, 35, 136167, 129, 62, 40, 658, 372, 170, 1 ], + [ "Porche, Cutie Baton", "PSY", [ "Shooter", "Slasher" ], 4, 20, 4, 3, 70, 1066998, 591, 314, 121, 1103, 656, 330, 1 ], + [ "Uniformed Suppressor Jailer", "STR", [ "Shooter", "Cerebral" ], 3, 12, 6, 1, 60, 449516, 40, 21, 30, 858, 663, 242, 1 ], + [ "Uniformed Emergency Jailer", "QCK", [ "Shooter", "Cerebral" ], 3, 12, 6, 1, 60, 449516, 52, 20, 31, 894, 640, 246, 1 ], + [ "Uniformed Perimeter Jailer", "DEX", [ "Shooter", "Cerebral" ], 3, 12, 6, 1, 60, 449516, 54, 19, 31, 877, 651, 244, 1 ], + [ "Contemplative Guard", "INT", [ "Striker", "Driven" ], 3, 12, 6, 1, 60, 449516, 55, 39, 20, 994, 727, 177, 1 ], + [ "All-Action Guard", "PSY", [ "Striker", "Driven" ], 3, 12, 6, 1, 60, 449516, 92, 33, 22, 1003, 691, 192, 1 ], + [ "Minotaur", "PSY", [ "Striker", "Powerhouse" ], 3, 30, 5, 1, 70, 1066998, 549, 237, -400, 2225, 885, -400, 1 ], + [ "Minozebra", "INT", [ "Striker", "Powerhouse" ], 3, 30, 6, 1, 70, 1066998, 563, 229, -200, 2050, 835, -200, 1 ], + [ "Sphinx", "STR", [ "Fighter", "Powerhouse" ], 3, 30, 4, 1, 70, 1066998, 622, 339, -300, 2455, 905, -300, 1 ], + [ "Saldeath, Chief Guard", "DEX", [ "Cerebral", "Fighter" ], 3, 15, 4, 2, 70, 1066998, 163, 131, 57, 912, 686, 309, 1 ], + [ "Army Wolf", "QCK", "Fighter", 2, 8, 6, 0, 50, 261406, 36, 31, 21, 794, 585, 173, 1 ], + [ "Under Warden Hannyabal", "PSY", [ "Driven", "Striker" ], 3, 9, 6, 1, 35, 136167, 70, 31, 29, 824, 412, 128, 1 ], + [ "Under Warden Hannyabal, Undersea Prison - Impel Down", "PSY", [ "Driven", "Striker" ], 4, 16, 4, 3, 70, 1066998, 749, 352, 100, 1590, 755, 190, 1 ], + [ "Chief Warden Magellan", "STR", [ "Powerhouse", "Shooter" ], 3, 18, 4, 1, 50, 392109, 154, 56, -250, 1093, 470, -250, 1 ], + [ "Chief Warden Magellan, Undersea Prison - Impel Down", "STR", [ "Powerhouse", "Shooter" ], 4, 30, 5, 3, 99, 3000000, 1014, 470, -250, 3000, 1159, -300, 1 ], + [ "Koala, Beach Angel", "QCK", [ "Fighter", "Free Spirit" ], 4, 13, 6, 2, 50, 392109, 133, 79, 37, 994, 479, 187, 1 ], + [ "Koala, Goddess of Paradise", "QCK", [ "Fighter", "Free Spirit" ], 5, 20, 4, 3, 99, 3000000, 902, 412, 123, 1822, 984, 359, 1 ], + [ "Gild. Tesoro", "PSY", [ "Cerebral", "Driven" ], 4, 30, 5, 5, 99, 3000000, 187, 156, 56, 1756, 1094, 268, 1 ], + [ "Gild. Tesoro, Gold Ship Casino King", "PSY", [ "Cerebral", "Driven" ], 5, 50, 4, 5, 99, 2000000, 1756, 1094, 268, 2256, 1300, 306, 1 ], + [ "Carina", "DEX", [ "Cerebral", "Slasher" ], 3, 10, 5, 1, 35, 136167, 98, 54, 58, 652, 394, 185, 1 ], + [ "Carina, Gold Ship Songstress", "DEX", [ "Cerebral", "Slasher" ], 4, 20, 5, 3, 70, 1066998, 597, 321, 132, 1074, 719, 306, 1 ], + [ "Baccarat", "INT", [ "Fighter", "Striker" ], 3, 12, 5, 2, 50, 392109, 44, 31, 123, 888, 444, 222, 1 ], + [ "Baccarat, Gran Tesoro Concierge", "INT", [ "Fighter", "Striker" ], 4, 20, 4, 2, 99, 3000000, 777, 333, 222, 1552, 777, 456, 1 ], + [ "Dice", "STR", [ "Free Spirit", "Powerhouse" ], 3, 12, 5, 2, 50, 392109, 84, 58, -500, 1624, 484, -500, 1 ], + [ "Dice, Gran Tesoro Dealer", "STR", [ "Free Spirit", "Powerhouse" ], 4, 20, 4, 2, 99, 3000000, 1493, 410, -500, 3035, 1005, -500, 1 ], + [ "Mr. Tanaka", "QCK", [ "Shooter", "Free Spirit" ], 3, 12, 5, 2, 50, 392109, 54, 62, 32, 924, 528, 188, 1 ], + [ "Mr. Tanaka, Gran Tesoro Security", "QCK", [ "Shooter", "Free Spirit" ], 4, 20, 4, 2, 99, 3000000, 849, 449, 131, 1706, 1089, 305, 1 ], + [ "Brook, Dream Chaser", "PSY", [ "Slasher", "Free Spirit" ], 4, 17, 6, 3, 70, 1066998, 249, 101, 40, 1530, 684, 133, 1 ], + [ "Brook, A Pirate Who Lives By His Code", "PSY", [ "Slasher", "Free Spirit" ], 5, 27, 4, 4, 99, 4000000, 1461, 636, 100, 2788, 1243, 234, 1 ], + [ "Roronoa Zoro, Dream Chaser", "DEX", [ "Slasher", "Driven" ], 4, 17, 5, 3, 70, 1066998, 270, 124, 23, 1585, 715, 98, 1 ], + [ "Roronoa Zoro, A Pirate Who Lives By His Code", "DEX", [ "Slasher", "Driven" ], 5, 27, 4, 4, 99, 4000000, 1531, 646, 60, 2900, 1321, 171, 1 ], + [ "Chopper, Dream Chaser", "DEX", [ "Shooter", "Cerebral" ], 4, 17, 5, 3, 70, 1066998, 196, 98, 51, 1170, 624, 212, 1 ], + [ "Chopper, A Pirate Who Lives By His Code", "DEX", [ "Shooter", "Cerebral" ], 5, 27, 4, 4, 99, 4000000, 1110, 571, 179, 2212, 1099, 368, 1 ], + [ "Oars", "STR", [ "Fighter", "Powerhouse" ], 4, 30, 4, 1, 70, 1066998, 902, 473, 74, 2018, 1028, -444, 1 ], + [ "Oars, the Devil", "STR", [ "Fighter", "Powerhouse" ], 5, 50, 4, 2, 99, 4000000, 1920, 977, -444, 4400, 1402, -444, 1 ], + [ "Rainbow Armor Crab", "INT", "Evolver", 3, 4, 5, 0, 1, 0, 30, 500, 0, 30, 500, 0, 1 ], + [ "Blenheim", "DEX", [ "Slasher", "Powerhouse" ], 4, 18, 6, 3, 70, 1066998, 206, 106, 19, 1051, 624, 95, 1 ], + [ "Blenheim, The Cutlass", "DEX", [ "Slasher", "Powerhouse" ], 5, 30, 6, 4, 99, 4000000, 949, 512, 44, 2643, 1355, 224, 1 ], + [ "Kingdew", "PSY", [ "Fighter", "Powerhouse" ], 4, 18, 5, 3, 70, 1066998, 232, 94, 38, 1123, 522, 161, 1 ], + [ "Kingdew, Twin Fist Gauntlets", "PSY", [ "Fighter", "Powerhouse" ], 5, 30, 4, 4, 99, 4000000, 1031, 432, 113, 2670, 1180, 308, 1 ], + [ "Haruta", "INT", [ "Slasher", "Cerebral" ], 4, 18, 5, 3, 70, 1066998, 132, 103, 34, 920, 583, 177, 1 ], + [ "Haruta, Gale Small Swordsman", "INT", [ "Slasher", "Cerebral" ], 5, 30, 4, 4, 99, 4000000, 833, 490, 123, 2025, 1309, 372, 1 ], + [ "Atmos", "STR", [ "Slasher", "Powerhouse" ], 4, 18, 6, 3, 70, 1066998, 255, 99, 13, 1242, 534, 89, 1 ], + [ "Atmos, The Water Buffalo", "STR", [ "Slasher", "Powerhouse" ], 5, 30, 5, 4, 99, 4000000, 1159, 440, 41, 3552, 1238, 132, 1 ], + [ "Speed Jil", "QCK", [ "Striker", "Driven" ], 4, 18, 6, 3, 70, 1066998, 242, 86, 30, 1198, 500, 148, 1 ], + [ "Speed Jil, Shield and Lance", "QCK", [ "Striker", "Driven" ], 5, 30, 4, 4, 99, 4000000, 1110, 412, 99, 2905, 1152, 288, 1 ], + [ "Aokiji, Navy HQ's Strongest Forces", "QCK", [ "Striker", "Shooter" ], 5, 30, 4, 3, 70, 1066998, 362, 271, 103, 1599, 800, 240, 1 ], + [ "Kuzan", "QCK", [ "Striker", "Shooter" ], 6, 55, 4, 4, 99, 5000000, 1524, 740, 196, 3300, 1466, 392, 1 ], + [ "Boa Hancock, Beachgoing Empress", "DEX", [ "Fighter", "Free Spirit" ], 4, 13, 4, 2, 50, 392109, 181, 132, 47, 945, 539, 181, 1 ], + [ "Boa Hancock, Maiden Drowned in Love", "DEX", [ "Fighter", "Free Spirit" ], 5, 20, 4, 3, 99, 3000000, 863, 448, 144, 1724, 1132, 326, 1 ], + [ "Ganfor, Former God of Skypiea", "PSY", "Striker", 4, 18, 6, 2, 50, 392109, 222, 122, 22, 1122, 622, 122, 1 ], + [ "Ganfor, God of Skypiea", "PSY", "Striker", 5, 30, 4, 3, 99, 3000000, 1111, 611, 111, 2122, 1222, 222, 1 ], + [ "Ohm, Sky Breeder", "INT", [ "Cerebral", "Powerhouse" ], 4, 20, 6, 3, 70, 1778330, 197, 169, -200, 1710, 1170, -150, 1 ], + [ "Jewelry Bonney, Splashing Sapphire", "STR", [ "Fighter", "Free Spirit" ], 4, 12, 6, 1, 50, 392109, 388, 212, 86, 1006, 559, 194, 1 ], + [ "Jewelry Bonney, Pearl White Gleam", "STR", [ "Fighter", "Free Spirit" ], 5, 20, 4, 2, 99, 3000000, 929, 500, 149, 2000, 989, 301, 1 ], + [ "Violet, Stirring Summer Vacation", "QCK", [ "Fighter", "Cerebral" ], 4, 12, 5, 1, 50, 392109, 109, 58, 55, 923, 480, 243, 1 ], + [ "Violet, Blushing Summer Vacation", "QCK", [ "Fighter", "Cerebral" ], 5, 20, 4, 2, 99, 3000000, 855, 420, 192, 1654, 837, 404, 1 ], + [ "Yorki", "PSY", [ "Slasher", "Free Spirit" ], 3, 12, 6, 1, 50, 392109, 102, 91, 36, 902, 584, 201, 1 ], + [ "Calico Yorki", "PSY", [ "Slasher", "Free Spirit" ], 4, 20, 4, 3, 99, 3000000, 840, 516, 170, 1583, 1153, 315, 1 ], + [ "Rumbar Pirates Brook", "QCK", [ "Slasher", "Free Spirit" ], 3, 12, 5, 1, 50, 392109, 139, 80, 31, 1006, 528, 184, 1 ], + [ "Rumbar Pirates Musical Swordsman Brook", "QCK", [ "Slasher", "Free Spirit" ], 4, 20, 4, 2, 99, 3000000, 942, 466, 139, 1894, 984, 299, 1 ], + [ "Rumbar Pirates Laboon", "STR", "Fighter", 3, 9, 6, 1, 50, 392109, 155, 55, 23, 1302, 570, 151, 1 ], + [ "Nico Robin, Dream Chaser", "INT", [ "Fighter", "Cerebral" ], 4, 17, 4, 3, 70, 1066998, 213, 96, 45, 1147, 626, 216, 1 ], + [ "Nico Robin, A Pirate Who Lives By Her Code", "INT", [ "Fighter", "Cerebral" ], 5, 27, 4, 4, 99, 4000000, 1098, 551, 180, 2076, 1099, 400, 1 ], + [ "Usopp, Dream Chaser", "QCK", "Shooter", 4, 17, 6, 3, 70, 1066998, 224, 90, 47, 1222, 593, 208, 1 ], + [ "Usopp, A Pirate Who Lives By His Code", "QCK", "Shooter", 5, 27, 5, 4, 99, 4000000, 1167, 542, 174, 2301, 954, 376, 1 ], + [ "Franky, Dream Chaser", "STR", [ "Shooter", "Free Spirit" ], 4, 17, 6, 3, 70, 1066998, 244, 140, 21, 1590, 738, 95, 1 ], + [ "Franky, A Pirate Who Lives By His Code", "STR", [ "Shooter", "Free Spirit" ], 5, 27, 5, 4, 99, 4000000, 1525, 660, 50, 2801, 1395, 161, 1 ], + [ "Baby 5, Dolphin Floatie", "STR", [ "Slasher", "Striker" ], 4, 13, 4, 2, 50, 392109, 101, 103, 34, 910, 563, 177, 1 ], + [ "Baby 5, Dolphin Rider", "STR", [ "Slasher", "Striker" ], 5, 20, 4, 3, 99, 3000000, 843, 489, 130, 1624, 1212, 309, 1 ], + [ "Gairam, World Pirates", "DEX", [ "Shooter", "Striker" ], 4, 20, 6, 2, 99, 3000000, 85, 35, 15, 1735, 1135, 175, 1 ], + [ "Sebastian, World Pirates", "QCK", [ "Powerhouse", "Striker" ], 4, 20, 6, 2, 99, 3000000, 108, 58, 0, 2258, 1258, 0, 1 ], + [ "Nightin, World Pirates", "PSY", [ "Fighter", "Cerebral" ], 4, 20, 4, 2, 99, 3000000, 64, 27, 32, 1654, 987, 321, 1 ], + [ "Boa Hancock, Amazon Lily Princess", "STR", [ "Shooter", "Free Spirit" ], 4, 20, 4, 3, 99, 3000000, 72, 42, 22, 1692, 1202, 262, 1 ], + [ "Byrnndi World", "INT", [ "Shooter", "Driven" ], 4, 25, 4, 2, 70, 1066998, 472, 331, 19, 1093, 809, 97, 1 ], + [ "Byrnndi World, Captain of the World Pirates", "INT", [ "Shooter", "Driven" ], 5, 40, 4, 3, 99, 4000000, 1011, 744, 52, 1990, 1483, 170, 1 ], + [ "Oars Jr.", "STR", [ "Slasher", "Powerhouse" ], 4, 16, 6, 2, 50, 392109, 266, 119, 9, 1306, 548, 47, 1 ], + [ "Oars Jr. of the Whitebeard Pirates", "STR", [ "Slasher", "Powerhouse" ], 5, 26, 4, 3, 99, 3000000, 1241, 482, 31, 2802, 1171, 90, 1 ], + [ "Bastille", "INT", [ "Slasher", "Driven" ], 3, 15, 4, 2, 70, 1066998, 265, 169, 1, 1725, 1102, 9, 1 ], + [ "Yamakaji", "STR", [ "Slasher", "Driven" ], 3, 15, 5, 2, 70, 1066998, 340, 128, 24, 1978, 800, 99, 1 ], + [ "Hina, Black Cage Corps", "INT", [ "Fighter", "Cerebral" ], 3, 15, 5, 2, 70, 1066998, 205, 105, 61, 1355, 707, 253, 1 ], + [ "Smoker, Navy Headquarters Commodore", "PSY", [ "Striker", "Driven" ], 3, 15, 6, 2, 70, 1066998, 241, 160, 33, 1552, 1032, 132, 1 ], + [ "Dracule Mihawk, Hawkeyes", "QCK", "Slasher", 4, 30, 4, 3, 99, 3000000, 167, 124, 6, 2119, 1390, 132, 1 ], + [ "Kizaru, Navy Headquarters Admiral", "DEX", [ "Shooter", "Fighter" ], 4, 30, 4, 3, 99, 3000000, 166, 109, 50, 2084, 1252, 209, 1 ], + [ "Sentomaru, Navy HQ Officer", "INT", [ "Striker", "Slasher" ], 4, 15, 6, 3, 50, 392109, 251, 96, 30, 1603, 442, 140, 1 ], + [ "Sentomaru of the Axe, Navy HQ Officer", "INT", [ "Striker", "Slasher" ], 5, 30, 4, 4, 99, 4000000, 1524, 376, 90, 3205, 1006, 362, 1 ], + [ "Smoker, G-5 Unit 01", "DEX", [ "Striker", "Driven" ], 4, 15, 6, 3, 50, 392109, 178, 159, 22, 1324, 659, 99, 1 ], + [ "Smoker, G-5 Navy HQ Vice Admiral", "DEX", [ "Striker", "Driven" ], 5, 30, 4, 4, 99, 4000000, 1257, 594, 44, 2738, 1430, 196, 1 ], + [ "Tashigi, G-5 Unit 01", "QCK", [ "Slasher", "Cerebral" ], 4, 15, 6, 3, 50, 392109, 109, 89, 60, 1061, 403, 230, 1 ], + [ "Tashigi, G-5 Navy HQ Captain ", "QCK", [ "Slasher", "Cerebral" ], 5, 30, 5, 4, 99, 4000000, 998, 339, 185, 1990, 937, 479, 1 ], + [ "Maynard, Navy HQ Vice Admiral", "PSY", [ "Slasher", "Powerhouse" ], 4, 15, 5, 3, 50, 392109, 120, 140, 34, 1172, 614, 153, 1 ], + [ "Maynard the Pursuer, Navy HQ Vice Admiral", "PSY", [ "Slasher", "Powerhouse" ], 5, 30, 4, 4, 99, 4000000, 1100, 549, 101, 2201, 1380, 303, 1 ], + [ "Bastille, Navy HQ Vice Admiral", "STR", [ "Slasher", "Driven" ], 4, 15, 6, 3, 50, 392109, 139, 123, 26, 1293, 594, 133, 1 ], + [ "\"Shark Cutter\" Bastille, Navy HQ Vice Admiral", "STR", [ "Slasher", "Driven" ], 5, 30, 7, 4, 99, 4000000, 1222, 519, 83, 2606, 1313, 259, 1 ], + [ "Kizaru, Navy HQ's Strongest Forces", "PSY", [ "Slasher", "Shooter" ], 5, 30, 6, 3, 70, 1066998, 316, 293, 101, 1376, 841, 279, 1 ], + [ "Borsalino", "PSY", [ "Slasher", "Shooter" ], 6, 55, 4, 4, 99, 5000000, 1321, 776, 231, 2590, 1489, 500, 1 ], + [ "Koala, Fishman Karate Assistant Instructor", "STR", [ "Fighter", "Free Spirit" ], 3, 12, 4, 1, 50, 392109, 33, 40, 49, 764, 543, 196, 1 ], + [ "Koala, Revolutionary Army Fishman Karate Assistant Instructor", "STR", [ "Fighter", "Free Spirit" ], 4, 20, 4, 3, 99, 3000000, 700, 481, 137, 1426, 1190, 357, 1 ], + [ "Hack, Fishman Karate Instructor", "INT", [ "Fighter", "Powerhouse" ], 3, 12, 6, 1, 50, 392109, 79, 55, 12, 904, 570, 91, 1 ], + [ "Hack, Revolutionary Army Fishman Karate Instructor", "INT", [ "Fighter", "Powerhouse" ], 4, 20, 5, 2, 99, 3000000, 849, 523, 51, 1872, 1201, 172, 1 ], + [ "\"Straw Hat\" Monkey D. Luffy, Marineford Flight ", "QCK", [ "Fighter", "Striker" ], 5, 25, 4, 3, 99, 3000000, 340, 195, 22, 1890, 1242, 309, 1 ], + [ "\"Fire Fist\" Portgas D. Ace, On the Execution Platform", "STR", [ "Fighter", "Shooter" ], 4, 12, 4, 0, 35, 136167, 79, 30, 2, 590, 302, 5, 1 ], + [ "\"Fire Fist\" Portgas D. Ace, Marineford Flight", "STR", [ "Fighter", "Shooter" ], 5, 25, 4, 3, 99, 4000000, 1403, 793, 121, 2120, 1281, 246, 1 ], + [ "Marco, Collar Fluttering in the Autumn Breeze", "DEX", [ "Fighter", "Powerhouse" ], 4, 13, 4, 2, 50, 392109, 142, 79, 40, 940, 504, 201, 1 ], + [ "Marco, Tipsy Kimono", "DEX", [ "Fighter", "Powerhouse" ], 5, 20, 4, 3, 99, 3000000, 870, 452, 164, 1804, 1017, 374, 1 ], + [ "Marco, Whitebeard Pirates", "QCK", [ "Fighter", "Powerhouse" ], 4, 25, 4, 2, 70, 1066998, 740, 322, 100, 1377, 684, 187, 1 ], + [ "Whitebeard Pirates Marco, Revival of Flame", "QCK", [ "Fighter", "Powerhouse" ], 5, 40, 4, 3, 99, 4000000, 1309, 620, 142, 2370, 1236, 335, 1 ], + [ "\"Bohemian Knight\" Doma, Subordinates of the Whitebeard Pirates", "INT", "Slasher", 4, 30, 6, 3, 99, 3000000, 201, 102, 21, 2001, 1201, 251, 1 ], + [ "\"Sky Rider\" Shura", "DEX", "Striker", 4, 20, 4, 2, 70, 1778330, 254, 240, 48, 1092, 1029, 179, 1 ], + [ "Maelstrom Spider Squard, Subordinates of the Whitebeard Pirates", "QCK", [ "Striker", "Slasher" ], 4, 25, 6, 3, 99, 3000000, 96, 69, -48, 2096, 1246, 96, 1 ], + [ "Decalvan Brothers, Subordinates of the Whitebeard Pirates", "PSY", "Fighter", 4, 25, 8, 3, 99, 3000000, 122, 52, 22, 2525, 1122, 152, 1 ], + [ "\"Ice Witch\" Whitey Bay, Subordinates of the Whitebeard Pirates", "DEX", [ "Slasher", "Driven" ], 4, 25, 6, 3, 99, 3000000, 81, 31, 31, 1931, 913, 301, 1 ], + [ "Edward Newgate, Rival of the Pirate King", "PSY", [ "Powerhouse", "Striker" ], 4, 30, 4, 2, 70, 1778330, 1116, 587, 51, 1744, 894, 103, 1 ], + [ "\"Whitebeard\" Edward Newgate, Grand Pirate", "PSY", [ "Powerhouse", "Striker" ], 5, 50, 4, 3, 99, 5000000, 1597, 762, 70, 2702, 1570, 170, 1 ], + [ "Donquixote Doflamingo, Pirates of the \"North Blue\"", "STR", [ "Cerebral", "Driven" ], 4, 20, 4, 3, 70, 711332, 142, 109, 44, 1024, 679, 201, 1 ], + [ "Donquixote Doflamingo, Darkness of the \"North Blue\"", "STR", [ "Cerebral", "Driven" ], 5, 30, 4, 4, 99, 4000000, 941, 603, 152, 1997, 1418, 344, 1 ], + [ "Señor Pink, Pirates of the \"North Blue\"", "INT", [ "Shooter", "Free Spirit" ], 4, 20, 6, 3, 70, 711332, 277, 66, 31, 1526, 503, 174, 1 ], + [ "Señor Pink, Darkness of the \"North Blue\"", "INT", [ "Shooter", "Free Spirit" ], 5, 30, 4, 4, 99, 4000000, 1472, 440, 130, 3050, 990, 310, 1 ], + [ "Vergo, Pirates of the \"North Blue\"", "QCK", [ "Powerhouse", "Fighter" ], 4, 20, 5, 3, 70, 711332, 208, 98, 9, 1250, 559, 48, 1 ], + [ "Vergo, Darkness of the \"North Blue\"", "QCK", [ "Powerhouse", "Fighter" ], 5, 30, 6, 4, 99, 4000000, 1250, 559, 48, 2694, 1389, 139, 1 ], + [ "Ace, Wasting Time Until Twilight", "STR", [ "Free Spirit", "Shooter" ], 4, 13, 6, 2, 50, 392109, 152, 90, 30, 961, 584, 174, 1 ], + [ "Ace, Face Glowing in the Moonlight", "STR", [ "Free Spirit", "Shooter" ], 5, 20, 4, 3, 99, 3000000, 890, 541, 130, 1948, 1187, 289, 1 ], + [ "Marshall D. Teach, Captain of the Blackbeard Pirates", "DEX", [ "Driven", "Powerhouse" ], 5, 30, 4, 3, 70, 1066998, 429, 287, 39, 1674, 854, 127, 1 ], + [ "Blackbeard, Captain of the Blackbeard Pirates", "DEX", [ "Driven", "Powerhouse" ], 6, 55, 4, 4, 99, 5000000, 1600, 789, 73, 3350, 1520, 244, 1 ], + [ "Laffitte", "DEX", [ "Shooter", "Driven" ], 4, 15, 6, 3, 50, 392109, 109, 92, 51, 995, 506, 202, 1 ], + [ "\"Demon Sheriff\" Laffitte", "DEX", [ "Shooter", "Driven" ], 5, 30, 4, 4, 99, 4000000, 917, 415, 152, 2094, 1132, 406, 1 ], + [ "Van Augur", "QCK", [ "Shooter", "Cerebral" ], 4, 15, 4, 3, 50, 392109, 99, 130, 48, 903, 620, 183, 1 ], + [ "\"The Supersonic\" Van Augur", "QCK", [ "Shooter", "Cerebral" ], 5, 30, 6, 4, 99, 4000000, 831, 578, 140, 1890, 1371, 357, 1 ], + [ "Jesus Burgess", "STR", [ "Fighter", "Powerhouse" ], 4, 15, 6, 3, 50, 392109, 187, 122, 1, 1520, 603, 1, 1 ], + [ "\"Champion\" Jesus Burgess", "STR", [ "Fighter", "Powerhouse" ], 5, 30, 4, 4, 99, 4000000, 1439, 522, 1, 3870, 1368, 1, 1 ], + [ "Shiryu", "INT", [ "Driven", "Slasher" ], 4, 15, 6, 3, 50, 392109, 132, 142, -300, 1244, 689, -300, 1 ], + [ "Shiryu of the Rain", "INT", [ "Driven", "Slasher" ], 5, 30, 4, 4, 99, 4000000, 1168, 622, -300, 2500, 1490, -300, 1 ], + [ "Doc Q", "PSY", [ "Slasher", "Striker" ], 4, 15, 4, 3, 50, 392109, 52, 131, 89, 703, 624, 254, 1 ], + [ "\"Grim Reaper\" Doc Q", "PSY", [ "Slasher", "Striker" ], 5, 30, 4, 4, 99, 4000000, 609, 549, 201, 1403, 1290, 491, 1 ], + [ "John Giant", "DEX", [ "Slasher", "Driven" ], 3, 15, 6, 3, 70, 1066998, 301, 92, 59, 1794, 709, 140, 1 ], + [ "Aokiji, Navy HQ Admiral", "PSY", [ "Slasher", "Free Spirit" ], 4, 30, 4, 3, 99, 3000000, 257, 129, 58, 2206, 1152, 227, 1 ], + [ "Garp, Navy HQ Vice Admiral", "STR", [ "Fighter", "Powerhouse" ], 4, 30, 5, 3, 99, 3000000, 171, 64, 62, 2094, 1002, 266, 1 ], + [ "Sengoku Navy HQ Fleet Admiral", "INT", [ "Cerebral", "Fighter" ], 4, 30, 5, 3, 99, 3000000, 213, 96, 95, 1942, 972, 304, 1 ], + [ "Akainu Navy HQ Admiral", "INT", [ "Driven", "Fighter" ], 4, 30, 5, 3, 99, 3000000, 133, 100, 0, 2000, 1381, 0, 1 ], + [ "Monkey D. Luffy, Wild Pirate", "PSY", [ "Striker", "Powerhouse" ], 4, 15, 6, 3, 50, 392109, 226, 154, 51, 1104, 602, 143, 1 ], + [ "Monkey D. Luffy, Pioneer Of Land", "PSY", [ "Striker", "Powerhouse" ], 5, 30, 4, 4, 99, 4000000, 1002, 501, 88, 2491, 1325, 261, 1 ], + [ "Baby 5, Girl of Spider Miles", "PSY", [ "Fighter", "Shooter" ], 3, 9, 5, 1, 50, 392109, 19, 29, 35, 399, 204, 194, 1 ], + [ "Baby 5, Member of Donquixote Family", "PSY", [ "Striker", "Shooter" ], 4, 15, 4, 3, 99, 3000000, 274, 158, 146, 784, 579, 372, 1 ], + [ "Trafalgar Law, Boy of Spider Miles", "DEX", [ "Driven", "Slasher" ], 3, 9, 6, 1, 50, 392109, 28, 64, 14, 368, 493, 90, 1 ], + [ "Trafalgar Law, Member of Donquixote Family", "DEX", [ "Driven", "Shooter" ], 4, 15, 4, 3, 99, 3000000, 312, 420, 51, 892, 890, 242, 1 ], + [ "Buffalo, Member of Donquixote Family", "INT", [ "Shooter", "Free Spirit" ], 3, 13, 4, 2, 99, 3000000, 69, 22, 30, 1306, 470, 249, 1 ], + [ "Lao G, Jio-Ken User", "DEX", [ "Driven", "Fighter" ], 4, 25, 7, 2, 70, 1066998, 210, 222, 49, 1070, 777, 147, 1 ], + [ "Lao G, Diamante Military Leader", "DEX", [ "Driven", "Fighter" ], 5, 40, 4, 3, 99, 4000000, 970, 700, 107, 2070, 1357, 270, 1 ], + [ "Boa Sandersonia, Kuja Warrior", "PSY", "Fighter", 3, 16, 4, 2, 50, 392109, 93, 39, 39, 693, 393, 193, 1 ], + [ "Boa Sandersonia, Three Gorgon Sisters, Second Daughter", "PSY", [ "Powerhouse", "Striker" ], 4, 26, 4, 3, 99, 3000000, 693, 393, 139, 1839, 993, 329, 1 ], + [ "Kalifa, Glamorous Mummy", "STR", [ "Fighter", "Cerebral" ], 4, 13, 5, 2, 50, 392109, 96, 83, 44, 836, 422, 277, 1 ], + [ "Kalifa, Glamorous Mummy Halloween Night - Masquerade", "STR", [ "Fighter", "Cerebral" ], 5, 20, 5, 3, 99, 3000000, 759, 351, 229, 1655, 839, 464, 1 ], + [ "Akainu", "STR", [ "Driven", "Fighter" ], 4, 30, 4, 2, 70, 1066998, 286, 216, 0, 1618, 816, 49, 1 ], + [ "Akainu, Magma Man", "STR", [ "Driven", "Fighter" ], 5, 50, 4, 3, 99, 5000000, 1518, 716, 44, 3168, 1444, 99, 1 ], + [ "Rebecca, Lovely Monster Cat", "INT", "Fighter", 4, 12, 7, 1, 50, 392109, 87, 43, 38, 961, 453, 221, 1 ], + [ "Rebecca, Lovely Monster Cat Halloween Night - Masquerade", "INT", "Fighter", 5, 20, 5, 3, 99, 3000000, 900, 391, 168, 1862, 912, 361, 1 ], + [ "Inmate Buggy", "QCK", [ "Slasher", "Driven" ], 3, 12, 4, 1, 50, 392109, 72, 33, 28, 923, 424, 187, 1 ], + [ "Inmate Buggy the Clown, Jailbreak Alliance", "QCK", [ "Slasher", "Driven" ], 4, 20, 4, 3, 99, 3000000, 852, 371, 130, 1903, 854, 340, 1 ], + [ "Prison Escapee Galdino", "INT", [ "Cerebral", "Striker" ], 3, 12, 5, 1, 50, 392109, 79, 29, 31, 998, 380, 195, 1 ], + [ "Prison Escapee Galdino, Jailbreak Alliance", "INT", [ "Cerebral", "Striker" ], 4, 20, 4, 3, 99, 3000000, 932, 323, 138, 2052, 753, 357, 1 ], + [ "Little Succubus Sugar", "DEX", [ "Cerebral", "Slasher" ], 4, 12, 6, 1, 50, 392109, 70, 32, 50, 912, 409, 250, 1 ], + [ "Little Succubus Sugar, Halloween Night - Masquerade", "DEX", [ "Cerebral", "Slasher" ], 5, 20, 4, 3, 99, 3000000, 844, 358, 209, 1768, 843, 407, 1 ], + [ "Bartolomeo, Full Moon Wolf", "QCK", [ "Driven", "Fighter" ], 4, 13, 5, 2, 50, 392109, 106, 99, 33, 1171, 557, 158, 1 ], + [ "Bartolomeo, Full Moon Wolf Halloween Night - Masquerade", "QCK", [ "Driven", "Striker" ], 5, 20, 4, 4, 99, 3000000, 1109, 472, 109, 2149, 1242, 247, 1 ], + [ "Kinemon", "STR", [ "Slasher", "Free Spirit" ], 4, 25, 6, 4, 70, 1066998, 609, 399, 62, 1142, 779, 177, 1 ], + [ "Foxfire Kinemon", "STR", [ "Slasher", "Free Spirit" ], 5, 40, 4, 5, 99, 4000000, 1095, 708, 131, 2075, 1433, 321, 1 ], + [ "Boa Marigold, Kuja Warrior", "INT", [ "Slasher", "Powerhouse" ], 3, 16, 5, 2, 50, 392109, 245, 116, 24, 1209, 462, 99, 1 ], + [ "Boa Marigold, Three Gorgon Sisters, Third Daughter", "INT", [ "Slasher", "Powerhouse" ], 4, 26, 4, 3, 99, 3000000, 1136, 411, 57, 2854, 1033, 169, 1 ], + [ "Akainu, Navy HQ's Strongest Forces", "STR", [ "Driven", "Powerhouse" ], 5, 30, 4, 3, 70, 1066998, 442, 300, 18, 1700, 881, 49, 1 ], + [ "Sakazuki", "STR", [ "Driven", "Powerhouse" ], 6, 55, 4, 4, 99, 5000000, 1642, 835, 32, 3500, 1600, 99, 1 ], + [ "Coby of the Grand Line, Navy HQ Master Chief Petty Officer", "PSY", [ "Fighter", "Driven" ], 4, 15, 5, 3, 50, 392109, 103, 94, 48, 941, 511, 209, 1 ], + [ "Coby, Student of the 'Hero of the Navy', Navy HQ Master Chief Petty Officer", "PSY", [ "Fighter", "Driven" ], 5, 30, 4, 4, 99, 4000000, 877, 447, 164, 2024, 1151, 414, 1 ], + [ "Monkey D. Garp, Navy HQ Vice Admiral", "STR", [ "Powerhouse", "Free Spirit" ], 4, 15, 5, 3, 50, 392109, 106, 144, 29, 959, 677, 151, 1 ], + [ "\"Garp the Fist\", Navy HQ Vice Admiral", "STR", [ "Powerhouse", "Free Spirit" ], 5, 30, 5, 4, 99, 4000000, 901, 602, 106, 2110, 1474, 290, 1 ], + [ "Tsuru, Navy HQ Vice Admiral", "QCK", [ "Cerebral", "Shooter" ], 4, 15, 4, 3, 50, 392109, 292, 205, 89, 902, 534, 213, 1 ], + [ "\"Grand Staff Officer\" Tsuru, Navy HQ Vice Admiral", "QCK", [ "Cerebral", "Shooter" ], 5, 30, 4, 4, 99, 4000000, 832, 467, 175, 1960, 1252, 419, 1 ], + [ "Momonga, Monster Slash of the Great Commander", "DEX", [ "Cerebral", "Slasher" ], 4, 15, 6, 3, 50, 392109, 136, 120, 35, 993, 591, 172, 1 ], + [ "Momonga, Monster Slash of the Great Commander, Navy Vice Admiral", "DEX", [ "Cerebral", "Slasher" ], 5, 30, 4, 4, 99, 4000000, 939, 529, 133, 2342, 1296, 330, 1 ], + [ "Onigumo, Swordsman of the Eight-Sword Style", "INT", [ "Driven", "Slasher" ], 4, 15, 6, 3, 50, 392109, 172, 136, 5, 1294, 638, 99, 1 ], + [ "Onigumo, Swordsman of the Eight-Sword Style, Navy Vice Admiral", "INT", [ "Driven", "Slasher" ], 5, 30, 4, 4, 99, 4000000, 1243, 572, 46, 2598, 1383, 225, 1 ], + [ "Royal Vampire Corazon", "PSY", [ "Cerebral", "Free Spirit" ], 4, 12, 6, 1, 50, 392109, 84, 51, 33, 935, 526, 206, 1 ], + [ "Royal Vampire Corazon, Halloween Night - Masquerade", "PSY", [ "Cerebral", "Free Spirit" ], 5, 20, 4, 3, 99, 3000000, 869, 467, 170, 1840, 1014, 337, 1 ], + [ "Leo, Tontatta Tribe - Tonta Corps", "DEX", [ "Striker", "Free Spirit" ], 3, 12, 5, 1, 50, 392109, 40, 40, 40, 888, 518, 180, 1 ], + [ "Warrior Leo, Tontatta Tribe - Tonta Corps", "DEX", [ "Striker", "Free Spirit" ], 4, 20, 4, 3, 99, 3000000, 810, 472, 140, 1724, 1134, 281, 1 ], + [ "Wicca", "QCK", [ "Fighter", "Free Spirit" ], 3, 15, 8, 2, 70, 1066998, 101, 88, 11, 1017, 888, 219, 1 ], + [ "Gancho", "INT", [ "Striker", "Cerebral" ], 3, 15, 6, 2, 70, 1066998, 158, 129, 84, 1008, 629, 334, 1 ], + [ "Mansherry, Daughter of the Tontatta Tribe", "PSY", [ "Striker", "Free Spirit" ], 3, 12, 6, 1, 50, 392109, 20, 10, 30, 666, 333, 270, 1], + [ "Mansherry, Princess of Tontatta Kingdom", "PSY", [ "Striker", "Free Spirit" ], 4, 20, 4, 3, 99, 3000000, 606, 303, 234, 1472, 604, 497, 1], + [ "Cub", "STR", [ "Striker", "Powerhouse" ], 3, 15, 6, 2, 70, 1066998, 64, 37, 16, 1604, 964, 106, 1], + [ "Bian", "DEX", [ "Striker", "Free Spirit" ], 3, 15, 4, 2, 70, 1066998, 38, 28, 28, 888, 789, 288, 1], + [ "Sabo, One Act with You", "INT", [ "Striker", "Free Spirit" ], 4, 13, 6, 2, 50, 392109, 203, 142, 32, 1106, 574, 171, 1], + [ "Sabo, Phantom of the Theatre", "INT", [ "Striker", "Free Spirit" ], 5, 20, 4, 4, 99, 3000000, 1035, 501, 126, 2191, 1281, 307, 1], + [ "Kanjuro", "PSY", [ "Striker", "Free Spirit" ], 4, 25, 6, 4, 70, 1066998, 554, 261, 35, 1275, 707, 183, 1], + [ "Evening Shower Kanjuro", "PSY", [ "Striker", "Free Spirit" ], 5, 40, 4, 5, 99, 4000000, 1209, 645, 133, 2414, 1253, 330, 1], + [ "Tony Tony Chopper Jump Point", "DEX", [ "Fighter", "Powerhouse" ], 4, 20, 5, 2, 99, 3000000, 162, 91, 29, 2334, 892, 296, 1], + [ "Gedatsu, Skypean Priest", "QCK", [ "Driven", "Free Spirit" ], 4, 16, 4, 2, 50, 392109, 109, 122, 38, 753, 505, 193, 1], + [ "\"Sky Boss\" Gedatsu, Skypean Priest", "QCK", [ "Driven", "Free Spirit" ], 5, 26, 4, 3, 99, 3000000, 692, 448, 142, 1443, 1220, 288, 1], + [ "Curly Dadan", "PSY", [ "Slasher", "Powerhouse" ], 3, 12, 6, 2, 50, 392109, 144, 62, 33, 1844, 703, 151, 1], + [ "Porchemy", "DEX", [ "Fighter", "Driven" ], 3, 13, 6, 1, 50, 392109, 125, 106, 6, 1734, 891, 34, 1], + [ "Bluejam", "STR", [ "Shooter", "Driven" ], 3, 13, 5, 1, 70, 1066998, 131, 133, 1, 1809, 1043, 9, 1], + [ "Jinbe, Fishman Pirates Captain", "STR", [ "Fighter", "Powerhouse" ], 4, 30, 5, 3, 99, 3000000, 304, 161, 56, 2329, 1144, 229, 1], + [ "Heracles'n, Highwayman of the Forest, Teacher of Amazing Weapons", "DEX", [ "Cerebral", "Shooter" ], 4, 20, 4, 3, 99, 3000000, 142, 91, 43, 2095, 899, 303, 1], + [ "Birdie Kingdom Roc", "PSY", [ "Fighter", "Powerhouse" ], 3, 13, 4, 1, 70, 1066998, 109, 66, 12, 1487, 706, 127, 1], + [ "Humandrills", "STR", [ "Slasher", "Powerhouse" ], 3, 13, 6, 1, 70, 1066998, 133, 112, 0, 1600, 1020, 0, 1], + [ "Haredas", "PSY", [ "Cerebral", "Shooter" ], 3, 13, 4, 1, 70, 1066998, 21, 40, 32, 377, 505, 394, 1], + [ "Long Arm Kingdom Tribesman", "QCK", [ "Driven", "Slasher" ], 3, 13, 5, 1, 70, 1066998, 98, 71, 29, 1377, 709, 181, 1], + [ "Tequila Wolf Guard", "INT", "Shooter", 3, 9, 7, 1, 70, 1066998, 51, 38, 21, 1103, 505, 193, 1], + [ "Ivankov, New Kama King", "DEX", [ "Fighter", "Free Spirit" ], 4, 20, 8, 3, 99, 3000000, 123, 95, 41, 2034, 935, 299, 1], + [ "Rayleigh, Crew of the Pirate King", "QCK", [ "Fighter", "Cerebral" ], 4, 30, 6, 3, 99, 3000000, 201, 189, 75, 2037, 1264, 294, 1], + [ "Silvers Rayleigh, Master of Sleepless Street", "DEX", [ "Fighter", "Cerebral" ], 4, 13, 5, 3, 50, 392109, 144, 97, 33, 905, 601, 179, 1 ], + [ "Silvers Rayleigh, Shimmering in Limelight", "DEX", [ "Fighter", "Cerebral" ], 5, 20, 4, 4, 99, 3000000, 832, 550, 133, 1922, 1209, 301, 1 ], + [ "Pekoms", "STR", [ "Powerhouse", "Fighter" ], 3, 12, 5, 2, 50, 392109, 99, 66, 33, 909, 666, 156, 1 ], + [ "Pekoms, Big Mom Pirates", "STR", [ "Powerhouse", "Fighter" ], 4, 20, 5, 3, 99, 3000000, 866, 651, 133, 1766, 1303, 233, 1 ], + [ "Baron Tamago", "INT", [ "Cerebral", "Striker" ], 3, 12, 5, 2, 50, 392109, 39, 33, 36, 715, 515, 199, 1 ], + [ "Baron Tamago, Big Mom Pirates", "INT", [ "Cerebral", "Striker" ], 4, 20, 4, 3, 99, 3000000, 651, 466, 165, 1651, 1012, 315, 1 ], + [ "Luffy, Winter Island Adventure", "QCK", [ "Fighter", "Free Spirit" ], 4, 15, 6, 3, 99, 2000000, 103, 54, 33, 2005, 945, 286, 1 ], + [ "Roronoa Zoro, Gathering of the Straw Hats", "DEX", [ "Driven", "Slasher" ], 5, 30, 6, 3, 70, 1066998, 409, 291, 44, 1661, 826, 163, 1 ], + [ "Roronoa Zoro, Reunion of the Straw Hat Pirates", "DEX", [ "Driven", "Slasher" ], 6, 55, 4, 5, 99, 5000000, 1587, 751, 111, 3603, 1518, 294, 1 ], + [ "Franky, Gathering of the Straw Hats", "PSY", [ "Shooter", "Free Spirit" ], 4, 15, 4, 3, 50, 392109, 309, 158, 19, 1325, 544, 138, 1 ], + [ "Franky, Reunion of the Straw Hat Pirates", "PSY", [ "Shooter", "Free Spirit" ], 5, 30, 4, 4, 99, 4000000, 1249, 467, 77, 3030, 1332, 221, 1 ], + [ "Nami, Gathering of the Straw Hats", "INT", [ "Cerebral", "Striker" ], 4, 15, 5, 3, 50, 392109, 189, 106, 36, 995, 498, 203, 1 ], + [ "Nami, Reunion of the Straw Hat Pirates", "INT", [ "Cerebral", "Striker" ], 5, 30, 4, 4, 99, 4000000, 921, 431, 156, 2171, 1109, 440, 1 ], + [ "Sanji, Gathering of the Straw Hats", "STR", [ "Fighter", "Powerhouse" ], 4, 15, 4, 3, 50, 392109, 242, 162, 24, 1182, 556, 148, 1 ], + [ "Sanji, Reunion of the Straw Hat Pirates", "STR", [ "Fighter", "Powerhouse" ], 5, 30, 4, 4, 99, 4000000, 1112, 500, 99, 2603, 1437, 260, 1 ], + [ "Tony Tony Chopper, Gathering of the Straw Hats", "QCK", [ "Striker", "Powerhouse" ], 4, 15, 6, 3, 50, 392109, 202, 109, 31, 1062, 503, 186, 1 ], + [ "Tony Tony Chopper, Reunion of the Straw Hat Pirates", "QCK", [ "Striker", "Powerhouse" ], 5, 30, 4, 4, 99, 4000000, 990, 434, 137, 2377, 1188, 379, 1 ], + [ "Roronoa Zoro, Wild Pirate", "QCK", [ "Slasher", "Powerhouse" ], 4, 15, 4, 3, 50, 392109, 244, 144, 22, 1122, 596, 77, 1 ], + [ "Roronoa Zoro, Pioneer of Land", "QCK", [ "Slasher", "Powerhouse" ], 5, 30, 4, 4, 99, 4000000, 1022, 499, 55, 2711, 1322, 161, 1 ], + [ "Magellan", "INT", [ "Striker", "Shooter" ], 4, 30, 6, 1, 70, 1066998, 210, 107, 29, 1226, 659, 102, 1 ], + [ "Magellan, Chief Warden of Impel Down", "INT", [ "Striker", "Shooter" ], 5, 50, 5, 2, 99, 5000000, 1149, 590, 57, 2605, 1316, 207, 1 ], + [ "Dellinger, Blood Thirsty Half-Fishman Fighting Fish", "QCK", [ "Powerhouse", "Fighter" ], 4, 25, 5, 2, 70, 1066998, 499, 366, 47, 1134, 749, 171, 1 ], + [ "Dellinger, Combatant of the Diamante Army", "QCK", [ "Powerhouse", "Fighter" ], 5, 40, 7, 3, 99, 4000000, 1062, 668, 109, 2060, 1429, 300, 1 ], + [ "Marguerite, Amazon Lily Archer", "DEX", [ "Shooter", "Slasher" ], 4, 16, 5, 2, 50, 392109, 93, 72, 62, 895, 520, 206, 1 ], + [ "Marguerite, Ambition of the Kuja Pirates", "DEX", [ "Shooter", "Slasher" ], 5, 26, 5, 3, 99, 3000000, 830, 452, 143, 1759, 974, 403, 1 ], + [ "Shanks, Captain of the Red Hair Pirates", "INT", [ "Cerebral", "Free Spirit" ], 4, 30, 4, 2, 70, 1778330, 1094, 514, 126, 1674, 767, 242, 1 ], + [ "\"Red Hair\" Shanks, Captain of the Red Hair Pirates", "INT", [ "Cerebral", "Free Spirit" ], 5, 50, 4, 3, 99, 5000000, 1600, 692, 200, 2552, 1440, 353, 1 ], + [ "Tashigi, Silent Night Star", "PSY", [ "Slasher", "Cerebral" ], 4, 13, 6, 3, 50, 392109, 109, 74, 55, 802, 474, 244, 1 ], + [ "Tashigi, Holy Night Heroine", "PSY", [ "Slasher", "Cerebral" ], 5, 20, 5, 4, 99, 3000000, 742, 416, 198, 1764, 909, 426, 1 ], + [ "Toy Soldier", "QCK", [ "Striker", "Shooter" ], 3, 13, 5, 2, 50, 392109, 81, 72, 28, 867, 611, 186, 1 ], + [ "Toy Soldier, Thunder Soldier", "QCK", [ "Striker", "Shooter" ], 4, 20, 4, 4, 99, 3000000, 792, 557, 151, 1552, 1300, 300, 1 ], + [ "Rebecca, Surviving Bloodline of the Former Royal Family", "PSY", [ "Striker", "Free Spirit" ], 3, 9, 5, 1, 35, 136167, 70, 27, 40, 502, 301, 197, 1 ], + [ "Rebecca, Target from the Former Royal Family's Bloodline", "PSY", [ "Striker", "Free Spirit" ], 4, 15, 4, 3, 70, 1066998, 441, 239, 153, 819, 492, 348, 1 ], + [ "Monkey D. Luffy, Gum Gum Elephant: Elephant Gun", "STR", [ "Fighter", "Free Spirit" ], "5+", 30, 4, 3, 99, 3000000, 1005, 560, 113, 2255, 1499, 284, 1 ], + [ "Roronoa Zoro, Unfortunate Port Bird: Yakkoudori", "DEX", [ "Slasher", "Driven" ], "5+", 30, 4, 3, 99, 3000000, 803, 669, 55, 2501, 1434, 233, 1 ], + [ "Nami, Weather Egg: Thunder Breed Tempo", "INT", [ "Striker", "Cerebral" ], "5+", 30, 4, 3, 99, 3000000, 705, 496, 181, 1970, 1200, 420, 1 ], + [ "Buggy Clown, Captain of the Buggy Pirates", "INT", [ "Driven", "Shooter" ], 5, 30, 5, 3, 70, 1066998, 296, 199, 133, 1310, 577, 299, 1 ], + [ "Captain Buggy", "INT", [ "Driven", "Shooter" ],6, 40, 5, 5, 99, 5000000, 1244, 504, 220, 2506, 1149, 491, 1 ], + [ "Sentomaru, Wall of the Sabaody Archipelagos", "PSY", [ "Slasher", "Striker" ], 4, 20, 5, 3, 99, 3000000, 166, 48, 33, 2805, 955, 201, 1 ], + [ "Demalo Black", "INT", [ "Shooter", "Driven" ], 4, 15, 7, 1, 99, 3000000, 102, 105, 49, 1187, 688, 251, 1 ], + [ "Baby 5, Dressed for the Shirne", "QCK", [ "Slasher", "Striker" ], 4, 13, 6, 2, 50, 392109, 164, 130, 40, 993, 561, 206, 1 ], + [ "Baby 5, Awkward Kimono", "QCK", [ "Slasher", "Striker" ], 5, 20, 4, 3, 99, 3000000, 920, 540, 149, 1912, 1239, 369, 1 ], + [ "Tashigi Shambles", "DEX", [ "Striker", "Driven" ], 3, 11, 6, 1, 50, 392109, 103, 34, 23, 1034, 543, 113, 1 ], + [ "Tashigi Shambles, 7 Foot Jitte", "DEX", [ "Striker", "Driven" ], 4, 19, 5, 3, 99, 3000000, 914, 463, 103, 2134, 1043, 231, 1 ], + [ "Smoker Shambles", "QCK", [ "Slasher", "Cerebral" ], 3, 11, 6, 1, 50, 392109, 76, 26, 41, 886, 466, 186, 1 ], + [ "Smoker Shambles, Autumn Rain", "QCK", [ "Slasher", "Cerebral" ], 4, 19, 4, 3, 99, 3000000, 706, 416, 160, 1606, 910, 361, 1 ], + [ "Gladius, Pop-Pop Man", "STR", [ "Driven", "Shooter" ], 4, 25, 7, 2, 70, 1066998, 186, 168, 39, 1088, 786, 98, 1 ], + [ "Gladius, Pica Military Executive", "STR", [ "Driven", "Shooter" ], 5, 40, 4, 3, 99, 4000000, 986, 698, 86, 2188, 1419, 208, 1 ], + [ "Dalton, Drum Island Civilian Escort Team Leader", "PSY", [ "Slasher", "Cerebral" ], 4, 20, 6, 2, 70, 1778330, 160, 106, 19, 1061, 961, 235, 1 ], + [ "Monkey D. Luffy, Gathering of the Straw Hats", "QCK", [ "Fighter", "Free Spirit" ], 5, 30, 4, 3, 70, 1066998, 313, 300, 70, 1422, 840, 210, 1 ], + [ "Monkey D. Luffy, Reunion of the Straw Hat Pirates", "QCK", [ "Fighter", "Free Spirit" ], 6, 55, 4, 5, 99, 5000000, 1369, 762, 168, 3080, 1550, 390, 1 ], + [ "Usopp, Gathering of the Straw Hats", "PSY", "Shooter", 4, 15, 4, 3, 50, 392109, 255, 99, 31, 1201, 481, 182, 1 ], + [ "Usopp, Reunion of the Straw Hat Pirates", "PSY", "Shooter", 5, 30, 4, 4, 99, 4000000, 1147, 446, 144, 2712, 1142, 340, 1 ], + [ "Nico Robin, Gathering of the Straw Hats", "DEX", [ "Fighter", "Cerebral" ], 4, 15, 4, 3, 50, 392109, 182, 119, 33, 992, 524, 200, 1 ], + [ "Nico Robin, Reunion of the Straw Hat Pirates", "DEX", [ "Fighter", "Cerebral" ], 5, 30, 4, 4, 99, 4000000, 946, 479, 165, 2151, 1257, 403, 1 ], + [ "Brook, Gathering of the Straw Hats", "INT", [ "Slasher", "Free Spirit" ], 4, 15, 6, 3, 50, 392109, 220, 117, 27, 1248, 532, 167, 1 ], + [ "Brook, Reunion of the Straw Hat Pirates", "INT", [ "Slasher", "Free Spirit" ], 5, 30, 4, 4, 99, 4000000, 1176, 482, 131, 2421, 1317, 329, 1 ], + [ "Tony Tony Chopper: Walk Point, Gathering of the Straw Hats", "STR", [ "Fighter", "Powerhouse" ], 4, 15, 4, 3, 50, 392109, 233, 77, 34, 1362, 439, 170, 1 ], + [ "Tony Tony Chopper: Monster Point, Reunion of the Straw Hat Pirates", "STR", [ "Fighter", "Powerhouse" ], 5, 30, 4, 4, 99, 4000000, 1362, 515, 0, 3000, 1499, 170, 1 ], + [ "Whitebeard: Four Emperors", "STR", [ "Striker", "Powerhouse" ], "6+", 65, 4, 5, 99, 5000000, 3148, 996, 142, 3806, 1558, 347, 1 ], + [ "Sanji, Making Food and Drinks", "INT", [ "Fighter", "Powerhouse" ], 4, 20, 5, 3, 99, 3000000, 557, 363, 32, 2276, 1200, 210, 1 ], + [ "Sengoku, Wise Warrior", "PSY", [ "Fighter", "Cerebral" ], 3, 13, 5, 1, 50, 392109, 106, 42, 30, 990, 503, 151, 1 ], + [ "Sengoku the Buddha, Wise Warrior", "PSY", [ "Fighter", "Cerebral" ], 4, 20, 5, 3, 99, 3000000, 920, 440, 100, 2059, 1059, 304, 1 ], + [ "Ronse", "STR", [ "Slasher", "Powerhouse" ], 4, 15, 6, 1, 70, 1066998, 106, 59, 1, 2018, 901, 3, 1 ], + [ "Stainless", "INT", [ "Slasher", "Cerebral" ], 4, 15, 5, 2, 70, 1066998, 82, 57, 20, 1408, 874, 202, 1 ], + [ "Rob Lucci, Inviting Hakama", "INT", [ "Fighter", "Powerhouse" ], 4, 13, 5, 2, 50, 392109, 152, 93, 13, 1202, 556, 73, 1 ], + [ "Rob Lucci, Home of Happi", "INT", [ "Fighter", "Powerhouse" ], 5, 20, 5, 3, 99, 3000000, 1129, 499, 42, 2299, 1333, 152, 1 ], + [ "Diamante, Ripple-Ripple Man", "INT", [ "Driven", "Striker" ], 4, 25, 5, 2, 70, 1066998, 505, 388, 12, 1202, 770, 91, 1 ], + [ "Diamante, Donquiote Family Executive", "INT", [ "Driven", "Slasher" ], 5, 40, 4, 3, 99, 4000000, 1131, 711, 47, 2400, 1457, 168, 1 ], + [ "T-Bone, Navy HQ Colonel", "QCK", [ "Cerebral", "Slasher" ], 4, 26, 4, 3, 99, 3000000, 99, 98, 50, 1752, 1199, 300, 1 ], + [ "Gin, Krieg Pirates Combat Commander", "DEX", "Striker", 4, 20, 4, 2, 70, 1778330, 110, 69, 32, 1228, 801, 191, 1 ], + [ "Don Sai, Happo Navy", "QCK", [ "Fighter", "Striker" ], 3, 13, 5, 1, 50, 392109, 105, 59, 19, 1205, 620, 106, 1], + [ "Don Sai, Happo Navy's 13th Leader", "QCK", [ "Fighter", "Striker" ], 4, 20, 4, 3, 99, 3000000, 1123, 527, 57, 2192, 1301, 181, 1], + [ "Boo, Happo Navy", "QCK", [ "Fighter", "Driven" ], 4, 15, 6, 3, 70, 1066998, 305, 159, 29, 1672, 1005, 111, 1], + [ "Jean Ango", "DEX", [ "Slasher" , "Shooter" ], 3, 13, 6, 2, 70, 1066998, 158, 173, 21, 1055, 1196, 73, 1 ], + [ "Mansherry, February's Favorite", "DEX", [ "Striker", "Free Spirit" ], 4, 13, 6, 2, 50, 392109, 42, 24, 66, 890, 329, 261, 1 ], + [ "Mansherry, March's Courage", "DEX", [ "Striker", "Free Spirit" ], 5, 20, 4, 4, 99, 3000000, 803, 251, 213, 1777, 656, 486, 1 ], + [ "Shogun Franky", "PSY", [ "Free Spirit", "Powerhouse" ], 4, 30, 4, 2, 70, 1066998, 400, 165, 20, 1550, 736, 102, 1 ], + [ "Iron Pirate General Franky", "PSY", [ "Free Spirit", "Powerhouse" ], 5, 50, 7, 3, 99, 5000000, 1487, 667, 67, 3330, 1400, 181, 1 ], + [ "Hody Jones, New Fishman Pirates Captain", "INT", [ "Powerhouse", "Shooter" ], 5, 30, 4, 3, 70, 1066998, 700, 240, 10, 1976, 789, 95, 1 ], + [ "Hody Jones, the Ghost of Fishman District", "INT", [ "Powerhouse", "Shooter" ], 6, 55, 4, 5, 99, 5000000, 1921, 731, 32, 4444, 1480, 140, 1 ], + [ "Hyouzou, New Fishman Pirates", "QCK", [ "Powerhouse", "Slasher" ], 4, 15, 6, 3, 50, 392109, 206, 151, -333, 1394, 671, -333, 1 ], + [ "Hyouzou, Ghosts of Fishman District", "QCK", [ "Powerhouse", "Slasher" ], 5, 30, 9, 4, 99, 4000000, 1319, 613, -333, 2941, 1468, -333, 1 ], + [ "Ikaros Much, New Fishman Pirates", "PSY", [ "Powerhouse", "Striker" ], 4, 15, 5, 3, 50, 392109, 223, 94, 27, 1206, 501, 138, 1 ], + [ "Ikaros Much, Ghosts of Fishman District", "PSY", [ "Powerhouse", "Striker" ], 5, 30, 8, 4, 99, 4000000, 1132, 429, 99, 2506, 1292, 303, 1 ], + [ "Daruma, New Fishman Pirates", "DEX", [ "Powerhouse", "Fighter" ], 4, 15, 4, 3, 50, 392109, 174, 133, 21, 1002, 606, 105, 1 ], + [ "Daruma, Ghosts of Fishman District", "DEX", [ "Powerhouse", "Fighter" ], 5, 30, 4, 4, 99, 4000000, 931, 531, 55, 2341, 1430, 270, 1 ], + [ "Zeo, New Fishman Pirate", "INT", [ "Powerhouse", "Striker" ], 4, 15, 4, 3, 50, 392109, 202, 80, 24, 1159, 522, 139, 1 ], + [ "Zeo, Ghosts of Fishman District", "INT", [ "Powerhouse", "Striker" ], 5, 30, 6, 4, 99, 4000000, 1078, 441, 96, 2424, 1362, 279, 1 ], + [ "Dosun, New Fishman Pirates", "STR", [ "Powerhouse", "Striker" ], 4, 15, 6, 3, 50, 392109, 302, 79, 18, 1440, 509, 96, 1 ], + [ "Dosun, Ghosts of Fishman District", "STR", [ "Powerhouse", "Striker" ], 5, 30, 7, 4, 99, 4000000, 1369, 430, 50, 3059, 1333, 189, 1 ], + [ "Boa Hancock: Snake Princess", "QCK", [ "Free Spirit", "Shooter" ], "6+", 65, 4, 5, 99, 5000000, 1559, 803, 303, 3002, 1480, 507, 1 ], + [ "Usopp, Platanus: Shuriken", "PSY", [ "Shooter" ], "5+", 30, 4, 3, 99, 3000000, 770, 292, 189, 2022, 972, 480, 1 ], + [ "Sanji, Grill Shot", "QCK", [ "Fighter", "Powerhouse" ], "5+", 30, 4, 3, 99, 3000000, 550, 515, 175, 2709, 1337, 251, 1 ], + [ "Tony Tony Chopper, Heavy Gong", "PSY", [ "Fighter", "Free Spirit" ], "5+", 30, 4, 2, 50, 392109, 699, 490, 90, 2336, 1236, 346, 1 ], + [ "Violet, Dancing Woman", "DEX", [ "Fighter", "Cerebral" ], 3, 13, 6, 2, 50, 392109, 88, 43, 89, 804, 403, 234, 1 ], + [ "Violet, Chased Woman", "DEX", [ "Fighter", "Cerebral" ], 4, 20, 6, 3, 99, 3000000, 643, 349, 184, 1594, 843, 403, 1 ], + [ "Sanji, Disguised Man on a Road to Love", "DEX", [ "Fighter", "Powerhouse" ], 3, 13, 4, 2, 50, 392109, 103, 56, 23, 1023, 567, 103, 1 ], + [ "Sanji, Escort of a Nearby Town", "DEX", [ "Fighter", "Powerhouse" ], 4, 20, 4, 3, 99, 3000000, 923, 543, 92, 2030, 1203, 208, 1 ], + [ "Marguerite, Unrest on the 13th", "STR", [ "Shooter", "Free Spirit" ], 4, 13, 4, 2, 50, 392109, 44, 42, 50, 903, 452, 230, 1 ], + [ "Marguerite, Celebration of the 14th", "STR", [ "Shooter", "Free Spirit" ], 5, 20, 5, 4, 99, 3000000, 831, 377, 188, 1755, 1081, 348, 1 ], + [ "Don Chinjao, Happo Navy", "PSY", [ "Striker", "Powerhouse" ], 4, 25, 5, 2, 70, 1066998, 613, 321, 24, 1249, 660, 134, 1 ], + [ "Don Chinjao, Happo Navy's 12th Leader", "PSY", [ "Fighter", "Powerhouse" ], 5, 40, 7, 3, 99, 4000000, 1177, 576, 77, 2707, 1367, 212, 1 ], + [ "Klahadore the Butler", "INT", [ "Slasher", "Cerebral" ], 3, 16, 6, 2, 50, 392109, 109, 109, 30, 892, 557, 187, 1 ], + [ "Pirate Kuro of a Hundred Plans", "INT", [ "Slasher", "Cerebral" ], 4, 26, 10, 3, 99, 3000000, 805, 489, 131, 1664, 1299, 310, 1 ], + [ "Miss Valentine, Kilo Human", "STR", [ "Fighter", "Free Spirit" ], 3, 10, 5, 2, 35, 136167, 92, 49, 26, 755, 390, 148, 1 ], + [ "Miss Valentine, Baroque Works Officer Agent", "STR", [ "Fighter", "Free Spirit" ], 4, 20, 4, 3, 70, 1066998, 687, 319, 90, 1402, 774, 250, 1 ], + [ "Zoro's Winter Training", "QCK", [ "Slasher", "Driven" ], 4, 20, 6, 3, 99, 2000000, 111, 49, 22, 2303, 919, 244, 1 ], + [ "Break Time Luffy", "PSY", [ "Fighter", "Free Spirit" ], 4, 12, 4, 2, 50, 392109, 132, 94, 26, 968, 505, 146, 1 ], + [ "Luffy's Tea Party", "PSY", [ "Fighter", "Free Spirit" ], 5, 20, 8, 3, 99, 3000000, 881, 409, 98, 2051, 1138, 276, 1 ], + [ "Break Time Chopper", "INT", [ "Shooter", "Powerhouse" ], 4, 12, 6, 2, 50, 392109, 121, 76, 44, 920, 401, 197, 1 ], + [ "Chopper's Tea Party", "INT", [ "Shooter", "Powerhouse" ], 5, 20, 4, 3, 99, 3000000, 841, 315, 150, 1906, 999, 347, 1 ], + [ "Cavendish, God of White Day", "PSY", [ "Slasher", "Driven" ], 4, 13, 6, 2, 50, 392109, 94, 48, 33, 1077, 476, 176, 1 ], + [ "Cavendish, Daydream of White Day", "PSY", [ "Slasher", "Driven" ], 5, 20, 4, 4, 99, 3000000, 1003, 421, 129, 1953, 1101, 311, 1 ], + [ "Sentomaru, Navy HQ", "STR", [ "Fighter", "Powerhouse" ], 3, 13, 6, 2, 50, 392109, 95, 45, 21, 1055, 595, 101, 1 ], + [ "Sentomaru of the Axe, Navy HQ", "STR", [ "Striker", "Powerhouse" ], 4, 20, 6, 3, 99, 3000000, 945, 485, 95, 2170, 1150, 205, 1 ], + [ "Lip \"Service\" Doughty", "STR", [ "Slasher", "Powerhouse" ], 3, 15, 6, 1, 70, 1066998, 140, 115, 11, 1310, 850, 139, 1 ], + [ "\"Gashed\" Albion", "DEX", [ "Slasher", "Driven" ], 3, 15, 4, 1, 70, 1066998, 120, 110, 12, 985, 840, 198, 1 ], + [ "Shirahoshi-hime", "PSY", "Striker", 5, 30, 4, 3, 70, 1066998, 433, 131, 60, 1296, 620, 286, 1 ], + [ "Shirahoshi-hime, Ryugu Kingdom Princess", "PSY", "Striker", 6, 55, 4, 5, 99, 5000000, 1238, 558, 233, 2650, 1202, 560, 1 ], + [ "Neptune", "STR", [ "Powerhouse", "Free Spirit" ], 4, 15, 5, 3, 50, 392109, 171, 149, 25, 1176, 667, 118, 1 ], + [ "Neptune, Ryugu Kingdom King", "STR", [ "Powerhouse", "Free Spirit" ], 5, 30, 4, 4, 99, 4000000, 1099, 601, 52, 2604, 1450, 229, 1 ], + [ "Fukaboshi", "PSY", [ "Powerhouse", "Striker" ], 4, 15, 6, 3, 50, 392109, 202, 91, 33, 1176, 496, 181, 1 ], + [ "Fukaboshi, Ryugu Kingdom Prince", "PSY", [ "Powerhouse", "Striker" ], 5, 30, 7, 4, 99, 4000000, 1125, 423, 133, 2554, 1206, 323, 1 ], + [ "Caribou, Caribou Pirates Captain", "QCK", [ "Driven", "Slasher" ], 4, 15, 6, 3, 50, 392109, 144, 144, 22, 1042, 651, 149, 1 ], + [ "Wet Haired Caribou, Caribou Pirates Captain", "QCK", [ "Driven", "Shooter" ], 5, 30, 10, 4, 99, 4000000, 959, 579, 89, 2340, 1484, 257, 1 ], + [ "Vander Decken IX, Lord of the Ghost Ship", "DEX", [ "Slasher", "Shooter" ], 4, 15, 6, 3, 50, 392109, 123, 119, 29, 1000, 589, 171, 1 ], + [ "Vander Decken IX, Captain of the Flying Pirates", "DEX", [ "Slasher", "Shooter" ], 5, 30, 5, 4, 99, 4000000, 929, 532, 132, 2198, 1393, 316, 1 ], + [ "Madame Shyarly", "INT", [ "Fighter", "Cerebral" ], 4, 15, 5, 3, 50, 392109, 91, 89, 44, 935, 478, 232, 1 ], + [ "Madame Shyarly, Fortune Teller", "INT", [ "Fighter", "Cerebral" ], 5, 30, 8, 4, 99, 4000000, 878, 422, 154, 1976, 999, 486, 1 ], + [ "Sanji, Wild Pirates", "STR", [ "Slasher", "Powerhouse" ], 4, 15, 6, 3, 50, 392109, 242, 133, 49, 1225, 573, 138, 1 ], + [ "Sanji, Pioneer Of Land", "STR", [ "Slasher", "Powerhouse" ], 5, 30, 4, 4, 99, 4000000, 1141, 494, 84, 2625, 1289, 250, 1 ], + [ "Ideo, XXX Rank Boxer", "DEX", [ "Shooter", "Fighter" ], 4, 25, 6, 2, 70, 1066998, 505, 350, 41, 1158, 717, 166, 1 ], + [ "Destruction Cannon Ideo, XXX Rank Boxer", "DEX", [ "Shooter", "Fighter" ], 5, 40, 4, 3, 99, 4000000, 1087, 640, 119, 2099, 1399, 302, 1 ], + [ "Don Krieg, Krieg Pirates Fleet Admiral", "STR", [ "Driven", "Shooter" ], 3, 16, 7, 2, 50, 392109, 177, 106, 14, 1271, 540, 55, 1 ], + [ "Don Krieg, East Blue Supreme Ruler", "STR", [ "Driven", "Shooter" ], 4, 26, 8, 3, 99, 3000000, 1200, 476, 30, 2707, 1225, 106, 1 ], + [ "Mr. 5, Bomb Human", "QCK", "Shooter", 3, 10, 6, 2, 35, 136167, 101, 56, 21, 808, 401, 74, 1 ], + [ "Mr. 5, Baroque Works Officer Agent", "QCK", "Shooter", 4, 20, 6, 3, 70, 1066998, 733, 325, 44, 1618, 818, 198, 1 ], + [ "Sabo, True Power of the Mera Mera no Mi", "PSY", [ "Fighter", "Free Spirit" ], "6+", 65, 4, 5, 99, 5000000, 1534, 777, 277, 3234, 1534, 452, 1 ], + [ "Rough Fishman Outlaw", "STR", [ "Powerhouse", "Striker" ], 3, 12, 6, 1, 60, 449516, 73, 42, 13, 1173, 749, 143, 1 ], + [ "Fast-paced Fishman Outlaw", "QCK", [ "Powerhouse", "Striker" ], 3, 12, 6, 1, 60, 449516, 71, 37, 16, 1167, 701, 169, 1 ], + [ "Skilled Fishman Outlaw", "DEX", [ "Powerhouse", "Striker" ], 3, 12, 6, 1, 60, 449516, 67, 40, 15, 1143, 737, 157, 1 ], + [ "Surefire Bombardment Fishman Outlaw", "INT", [ "Powerhouse", "Shooter" ], 3, 12, 6, 1, 60, 449516, 63, 43, 17, 1137, 750, 173, 1 ], + [ "One Shot Bombardment Fishman Outlaw", "PSY", [ "Powerhouse", "Shooter" ], 3, 12, 6, 1, 60, 449516, 57, 47, 14, 1093, 773, 153, 1 ], + [ "Durable Fishman Guard", "STR", [ "Powerhouse", "Striker" ], 3, 12, 6, 1, 60, 449516, 83, 35, 18, 1247, 697, 174, 1 ], + [ "Agile Fishman Guard", "QCK", [ "Powerhouse", "Striker" ], 3, 12, 6, 1, 60, 449516, 79, 30, 22, 1237, 673, 183, 1 ], + [ "Clever Fishman Guard", "DEX", [ "Powerhouse", "Striker" ], 3, 12, 6, 1, 60, 449516, 77, 33, 20, 1217, 683, 117, 1 ], + [ "Caribou", "INT", [ "Driven", "Shooter" ], 3, 15, 6, 2, 70, 1066998, 194, 87, 14, 1647, 974, 74, 1 ], + [ "Coribou", "PSY", [ "Driven", "Striker" ], 3, 15, 6, 2, 70, 1066998, 152, 75, 25, 1425, 852, 152, 1 ], + [ "Hammond", "QCK", [ "Powerhouse", "Shooter" ], 3, 15, 4, 2, 70, 1066998, 217, 71, 17, 1701, 817, 117, 1 ], + [ "Vander Decken IX", "DEX", [ "Driven", "Slasher" ], 4, 20, 5, 3, 99, 3000000, 182, 102, 15, 2218, 1182, 188, 1 ], + [ "Hody Jones", "STR", [ "Powerhouse", "Shooter" ], 3, 18, 6, 1, 50, 392109, 141, 69, 0, 1041, 594, 31, 1 ], + [ "Hody Jones, Awakened", "STR", [ "Powerhouse", "Shooter" ], 4, 30, 6, 3, 99, 3000000, 1014, 494, 29, 2741, 1294, 104, 1 ], + [ "Break Time Sanji", "QCK", [ "Fighter", "Powerhouse" ], 4, 12, 4, 2, 50, 392109, 153, 90, 23, 1030, 489, 122, 1 ], + [ "Sanji's Tea Party", "QCK", [ "Fighter", "Powerhouse" ], 5, 20, 6, 3, 99, 3000000, 949, 402, 90, 2200, 1130, 247, 1 ], + [ "Haruta, Whitebeard 12th Div. Commander", "INT", [ "Cerebral", "Slasher" ], 4, 25, 6, 3, 99, 3000000, 40, 49, 34, 2012, 1212, 212, 1 ], + [ "Speed Jil, Whitebeard 14th Div. Commander ", "INT", [ "Driven", "Striker" ], 4, 25, 6, 3, 99, 3000000, 49, 50, 30, 2140, 1214, 188, 1 ], + [ "Atmos, Whitebeard 13th Div. Commander", "PSY", [ "Powerhouse", "Slasher" ], 4, 25, 6, 3, 99, 3000000, 51, 35, 35, 2213, 1113, 213, 1 ], + [ "Kingdew, Whitebeard 11th Div. Commander", "STR", [ "Powerhouse", "Fighter" ], 4, 25, 6, 3, 99, 3000000, 45, 60, 26, 2119, 1311, 160, 1 ], + [ "Sanji, Early Spring Adventure", "DEX", [ "Fighter", "Powerhouse" ], 4, 13, 6, 2, 50, 392109, 89, 52, 39, 1032, 490, 192, 1 ], + [ "Sanji's Handmade Anniversary Gift", "DEX", [ "Fighter", "Powerhouse" ], 5, 20, 7, 4, 99, 3000000, 956, 434, 151, 1858, 1157, 332, 1 ], + [ "Break Time Brook", "STR", [ "Slasher", "Free Spirit" ], 4, 12, 6, 2, 50, 392109, 124, 84, 30, 979, 465, 151, 1 ], + [ "Brook's Tea Party", "STR", [ "Slasher", "Free Spirit" ], 5, 20, 4, 3, 99, 3000000, 912, 393, 106, 2059, 1122, 247, 1 ], + [ "Bellamy the Hyena, Former Captain of the Bellamy Pirates", "QCK", [ "Fighter", "Driven" ], 4, 30, 4, 1, 70, 1066998, 177, 120, 32, 979, 701, 197, 1 ], + [ "Bellamy the Hyena, Bullet of Dressrosa", "QCK", [ "Fighter", "Driven" ], 5, 50, 4, 2, 99, 5000000, 901, 624, 151, 2024, 1300, 313, 1 ], + [ "Curly Dadan, Mt. Corvo Brigade", "PSY", [ "Powerhouse", "Slasher" ], 3, 13, 6, 2, 50, 392109, 121, 76, 7, 1254, 606, 39, 1 ], + [ "Curly Dadan, Head of the Dadan Family", "PSY", [ "Powerhouse", "Slasher" ], 4, 20, 4, 3, 99, 3000000, 1080, 578, 36, 2394, 912, 247, 1 ], + [ "Dogra", "QCK", "Slasher", 3, 15, 6, 1, 70, 1066998, 120, 83, 33, 1314, 660, 201, 1 ], + [ "Portgas D. Ace, Hidden Demon's Child", "DEX", [ "Striker", "Free Spirit" ], 4, 15, 6, 2, 70, 1066998, 108, 103, 31, 1134, 870, 191, 1 ], + [ "Tony Tony Chopper, A Big Dream in a Flask", "PSY", "Cerebral", 4, 13, 8, 2, 50, 392109, 93, 42, 42, 1224, 391, 211, 1 ], + [ "Tony Tony Chopper, Spring Scenery on the Winter Island", "PSY", [ "Cerebral", "Free Spirit" ], 5, 20, 4, 4, 99, 3000000, 1120, 361, 193, 2011, 908, 391, 1 ], + [ "Suleiman the Beheader, Battle of Dias Class-A War Criminal", "QCK", [ "Slasher", "Cerebral" ], 5, 40, 6, 3, 99, 4000000, 174, 147, 47, 2087, 1347, 247, 1 ], + [ "Arlong, Arlong Pirates Captain", "INT", [ "Striker", "Shooter" ], 3, 16, 4, 2, 50, 392109, 173, 153, 23, 935, 853, 75, 1 ], + [ "Arlong the Saw, Arlong Pirates Captain", "INT", [ "Striker", "Shooter" ], 4, 26, 4, 3, 99, 3000000, 853, 735, 55, 2053, 1479, 153, 1 ], + [ "Blenheim, Whitebeard 9th Div. Commander", "PSY", [ "Powerhouse", "Slasher" ], 4, 26, 6, 3, 99, 3000000, 168, 98, 29, 1959, 1246, 248, 1 ], + [ "Cavendish, Beautiful Pirates Captain", "QCK", [ "Slasher", "Free Spirit" ], 4, 30, 6, 2, 70, 1778330, 1072, 535, 131, 1588, 801, 249, 1 ], + [ "Cavendish of Hakuba, Beautiful Pirates Captain", "QCK", [ "Slasher", "Free Spirit" ], 5, 50, 5, 3, 99, 5000000, 1500, 737, 202, 2487, 1477, 361, 1 ], + [ "Usoland", "DEX", "Shooter", 5, 30, 6, 3, 70, 1066998, 466, 139, 51, 1551, 637, 220, 1 ], + [ "God Usopp", "DEX", "Shooter", 6, 55, 4, 5, 99, 5000000, 1493, 566, 162, 3141, 1291, 441, 1 ], + [ "Rayleigh, Straw Hat Pirates Companion", "QCK", [ "Slasher", "Cerebral" ], 4, 15, 6, 3, 50, 392109, 141, 107, 32, 1034, 566, 197, 1 ], + [ "Rayleigh, Straw Hat Pirates Accomplice", "QCK", [ "Slasher", "Cerebral" ], 5, 30, 4, 4, 99, 4000000, 957, 500, 147, 2350, 1298, 351, 1 ], + [ "Duval, Straw Hat Pirates Companion", "PSY", [ "Slasher", "Free Spirit" ], 4, 15, 6, 3, 50, 392109, 189, 90, 20, 1324, 501, 131, 1 ], + [ "Duval, Straw Hat Pirates Accomplice", "PSY", [ "Slasher", "Free Spirit" ], 5, 30, 6, 4, 99, 4000000, 1246, 430, 86, 3000, 1120, 267, 1 ], + [ "Heracles'n, Straw Hat Pirates Companion", "STR", [ "Striker", "Shooter" ], 4, 15, 6, 3, 50, 392109, 102, 137, 26, 989, 620, 148, 1 ], + [ "Heracles'n, Straw Hat Pirates Accomplice", "STR", [ "Striker", "Shooter" ], 5, 30, 4, 4, 99, 4000000, 923, 547, 91, 2091, 1403, 328, 1 ], + [ "Perona, Straw Hat Pirates Companion", "INT", [ "Shooter", "Driven" ], 4, 15, 4, 3, 50, 392109, 97, 78, 44, 948, 479, 221, 1 ], + [ "Perona, Straw Hat Pirates Accomplice", "INT", [ "Shooter", "Driven" ], 5, 30, 4, 4, 99, 4000000, 885, 416, 167, 1969, 1001, 481, 1 ], + [ "Elizabeth, Straw Hat Pirates Companion", "DEX", [ "Fighter", "Free Spirit" ], 4, 15, 6, 3, 50, 392109, 77, 55, 33, 888, 444, 222, 1 ], + [ "Elizabeth, Straw Hat Pirates Accomplice", "DEX", [ "Fighter", "Free Spirit" ], 5, 30, 8, 4, 99, 4000000, 821, 380, 157, 2681, 810, 381, 1 ], + [ "Captain Usopp, Usopp's Great Manly Adventure ~Chapter II~", "DEX", "Shooter", "6+", 65, 4, 5, 99, 5000000, 1556, 577, 179, 3410, 1341, 481, 1 ], + [ "Koala, Cherry Blossom Meeting", "INT", [ "Fighter", "Free Spirit" ], 4, 13, 6, 3, 50, 392109, 87, 63, 45, 922, 521, 205, 1 ], + [ "Koala, Cherry Blossom Mouth", "INT", [ "Fighter", "Free Spirit" ], 5, 20, 4, 4, 99, 3000000, 873, 463, 173, 1701, 1205, 358, 1 ], + [ "Soul King", "QCK", [ "Slasher", "Free Spirit" ], 3, 13, 6, 2, 50, 392109, 100, 43, 38, 1094, 434, 182, 1 ], + [ "\"Soul King\" Brook the Pirate", "QCK", [ "Slasher", "Free Spirit" ], 4, 20, 8, 4, 99, 3000000, 1043, 434, 143, 2043, 1043, 304, 1 ], + [ "Long Arm Tribe of Tehna Gehna Kingdom, \"Soul King\" Managers", "STR", [ "Shooter", "Driven" ], 3, 13, 6, 2, 70, 1066998, 52, 31, 40, 962, 775, 226, 1 ], + [ "Nico Robin, Mil Fluer: Campo de Flores", "PSY", [ "Fighter", "Cerebral" ], "5+", 30, 4, 3, 99, 3000000, 979, 487, 171, 2105, 1187, 401, 1 ], + [ "Franky, Rocket Launcher", "INT", [ "Shooter", "Free Spirit" ], "5+", 30, 4, 3, 99, 3000000, 1655, 803, 91, 2687, 1359, 244, 1 ], + [ "Brook, Song of Scratches: Blizzard Slash", "DEX", [ "Slasher", "Free Spirit" ], "5+", 30, 6, 3, 99, 3000000, 1043, 481, 187, 2204, 1277, 351, 1 ], + [ "Hajrudin, Elbaf Warriors \"New Generation\"", "STR", [ "Powerhouse", "Striker" ], 4, 25, 4, 1, 70, 1066998, 551, 299, 21, 1306, 757, 139, 1 ], + [ "Pirate Mercenary Hajrudin, Elbaf Warriors \"New Generation\"", "STR", [ "Powerhouse", "Striker" ], 5, 40, 5, 3, 99, 4000000, 1225, 683, 89, 2840, 1381, 206, 1 ], + [ "Ryuma, Samurai General Zombie", "DEX", "Slasher", 3, 16, 6, 1, 50, 392109, 131, 111, 0, 1094, 525, 99, 1 ], + [ "Swordsman Ryuma, Samurai General Zombie", "DEX", "Slasher", 4, 26, 6, 3, 99, 3000000, 1031, 450, 99, 2017, 1192, 244, 1 ], + [ "Wadatsumi", "STR", [ "Powerhouse", "Fighter" ], 3, 30, 6, 2, 70, 1066998, 436, 106, 0, 3000, 801, 0, 1 ], + [ "Zeo", "PSY", [ "Striker", "Shooter" ], 3, 15, 4, 2, 70, 1066998, 91, 62, 31, 1135, 882, 261, 1 ], + [ "Ikaros", "DEX", [ "Powerhouse", "Shooter" ], 3, 15, 10, 2, 70, 1066998, 99, 49, 33, 1231, 809, 270, 1 ], + [ "Hyouzou", "STR", [ "Powerhouse", "Slasher" ], 3, 15, 6, 2, 70, 1066998, 106, 99, -555, 1931, 1255, -555, 1 ], + [ "Daruma", "QCK", [ "Powerhouse", "Fighter" ], 3, 15, 4, 2, 70, 1066998, 70, 83, 24, 1039, 1191, 173, 1 ], + [ "Dosun", "INT", [ "Powerhouse", "Striker" ], 3, 15, 4, 2, 70, 1066998, 101, 77, 18, 1465, 1092, 133, 1 ], + [ "Hody Jones, Rampage", "QCK", [ "Powerhouse", "Shooter" ], 5, 30, 4, 4, 99, 4000000, 1115, 660, 0, 3115, 1395, -150, 1 ], + [ "\"The Fighting King\" Elizabello II", "STR", [ "Fighter", "Powerhouse" ], 3, 13, 6, 2, 50, 392109, 91, 48, 19, 1021, 602, 99, 1 ], + [ "\"The Fighting King\" Elizabello II, Prodence Kingdom", "STR", [ "Fighter", "Powerhouse" ], 4, 20, 4, 4, 99, 3000000, 931, 495, 90, 2151, 1200, 192, 1 ], + [ "Tactician Dagama", "DEX", [ "Driven", "Cerebral" ], 3, 13, 4, 2, 50, 392109, 101, 45, 70, 1012, 511, 160, 1 ], + [ "Tactician Dagama, Prodence Kingdom", "DEX", [ "Driven", "Cerebral" ], 4, 20, 6, 4, 99, 3000000, 912, 451, 99, 2022, 1011, 276, 1 ], + [ "Boa Hancock, Maiden Warrior", "QCK", [ "Free Spirit", "Fighter" ], 4, 10, 5, 3, 35, 136167, 92, 33, 83, 603, 304, 289, 1 ], + [ "Boa Hancock, A Glimpse of a Princess", "QCK", [ "Free Spirit", "Fighter" ], 5, 18, 4, 5, 70, 1066998, 534, 255, 249, 1030, 603, 436, 1 ], + [ "Trafalgar Law, Straw Hat • Heart Pirates Alliance", "INT", [ "Free Spirit", "Striker" ], 4, 15, 4, 4, 99, 2000000, 197, 109, 15, 2017, 1230, 245, 1 ], + [ "Inuarashi", "STR", [ "Slasher", "Cerebral" ], 5, 30, 6, 3, 70, 1066998, 357, 247, 34, 1291, 829, 210, 1 ], + [ "\"King of the Day\" Inuarashi", "STR", [ "Slasher", "Cerebral" ], 6, 55, 4, 5, 99, 5000000, 1220, 754, 153, 2978, 1535, 389, 1 ], + [ "Wanda", "QCK", [ "Slasher", "Cerebral" ], 4, 15, 6, 3, 50, 392109, 135, 103, 38, 1019, 547, 213, 1 ], + [ "Ruler's Aide Wanda", "QCK", [ "Slasher", "Cerebral" ], 5, 30, 4, 4, 99, 4000000, 938, 470, 167, 2177, 1243, 367, 1 ], + [ "Sicilian", "INT", [ "Slasher", "Cerebral" ], 4, 15, 6, 3, 50, 392109, 142, 155, 19, 1202, 658, 127, 1 ], + [ "Full Power Sicilian", "INT", [ "Slasher", "Cerebral" ], 5, 30, 4, 4, 99, 4000000, 1130, 589, 86, 2559, 1457, 212, 1 ], + [ "Kinemon, Wano Country Samurai", "DEX", [ "Slasher", "Free Spirit" ], 4, 15, 6, 3, 50, 392109, 135, 130, 22, 1133, 601, 166, 1 ], + [ "Foxfire Kinemon, Wano Country Samurai", "DEX", [ "Slasher", "Free Spirit" ], 5, 30, 4, 4, 99, 4000000, 1066, 530, 119, 2349, 1377, 294, 1 ], + [ "Momonosuke", "PSY", [ "Striker", "Free Spirit" ], 4, 13, 6, 3, 50, 392109, 102, 76, 60, 830, 309, 269, 1 ], + [ "Momonosuke, Child of Wano Country", "PSY", [ "Striker", "Free Spirit" ], 5, 28, 4, 4, 99, 4000000, 761, 238, 200, 1922, 690, 535, 1 ], + [ "Trafalgar Law, Punk Hazard Resident", "DEX", [ "Free Spirit", "Slasher" ], 3, 13, 4, 2, 50, 392109, 149, 56, 25, 894, 453, 150, 1 ], + [ "Trafalgar Law, Second Salvation God", "DEX", [ "Free Spirit", "Fighter" ], 4, 20, 4, 4, 99, 3000000, 801, 423, 134, 1884, 1155, 251, 1 ], + [ "Monet, Snow-Snow Fruit Snow Woman", "PSY", [ "Cerebral", "Free Spirit" ], 4, 15, 4, 2, 70, 1066998, 96, 83, 45, 1062, 666, 271, 1 ], + [ "Admiral Orlumbus, Yonta Maria Grand Fleet", "PSY", [ "Striker", "Fighter" ], 4, 25, 5, 1, 70, 1066998, 624, 303, 22, 1425, 613, 119, 1 ], + [ "Massacre Ruler Orlumbus, Yonta Maria Grand Fleet Admiral", "PSY", [ "Striker", "Fighter" ], 5, 40, 6, 3, 99, 4000000, 1354, 544, 67, 3012, 1243, 200, 1 ], + [ "Helmeppo, Navy HQ Sergeant", "QCK", [ "Slasher", "Driven" ], 3, 16, 6, 1, 50, 392109, 124, 77, 23, 905, 492, 136, 1 ], + [ "Brave Compannion Helmeppo, Navy HQ Chief Petty Officer", "QCK", [ "Slasher", "Driven" ], 4, 26, 6, 3, 99, 3000000, 817, 420, 89, 1971, 1016, 322, 1 ], + [ "Sanji, Vinsmoke Family's 3rd Son", "INT", [ "Fighter", "Powerhouse" ], 5, 30, 6, 3, 70, 1066998, 369, 222, 31, 1323, 784, 200, 1 ], + [ "Sanji, Germa Kingdom Prince", "INT", [ "Fighter", "Powerhouse" ], 6, 55, 6, 5, 99, 5000000, 1251, 726, 147, 3233, 1506, 354, 1 ], + [ "Shanks, Celebrate the Long Cruise", "QCK", [ "Cerebral", "Slasher" ], 4, 15, 6, 3, 50, 392109, 143, 144, 29, 1152, 626, 206, 1 ], + [ "Red Hair Shanks, Celebrate the Long Cruise", "QCK", [ "Cerebral", "Slasher" ], 5, 30, 5, 5, 99, 4000000, 1076, 548, 145, 2326, 1323, 362, 1 ], + [ "Boa Hancock, Celebrate the Long Cruise", "INT", [ "Fighter", "Free Spirit" ], 4, 15, 6, 3, 50, 392109, 141, 121, 36, 1134, 589, 233, 1 ], + [ "\"Empress\" Boa Hancock, Celebrate the Long Cruise", "INT", [ "Fighter", "Free Spirit" ], 5, 30, 7, 5, 99, 4000000, 1087, 529, 187, 2195, 1289, 401, 1 ], + [ "Monkey D. Luffy, Gear 4th - Boundman", "PSY", [ "Fighter", "Free Spirit" ], "6+", 65, 4, 5, 99, 5000000, 1402, 777, 177, 3380, 1600, 400, 1 ], + [ "Fujitora, Navy HQ Greatest Military Power", "PSY", [ "Powerhouse", "Slasher" ], 4, 30, 6, 2, 70, 1066998, 303, 165, 29, 1344, 700, 144, 1 ], + [ "Gravity Blade Fujitora, Navy HQ Greatest Military Power", "PSY", [ "Powerhouse", "Slasher" ], 5, 50, 4, 3, 99, 5000000, 1268, 634, 109, 2825, 1420, 254, 1 ], + [ "Shirahoshi", "INT", "Striker", 3, 13, 6, 2, 50, 392109, 62, 45, 35, 690, 360, 215, 1 ], + [ "Princess Shirahoshi, Ryugu Kingdom", "INT", "Striker", 4, 20, 4, 3, 99, 3000000, 620, 330, 200, 1536, 858, 408, 1 ], + [ "Ryuboshi", "STR", [ "Powerhouse", "Slasher" ], 3, 15, 6, 1, 70, 1066998, 123, 87, 29, 1362, 699, 180, 1 ], + [ "Manboshi", "QCK", [ "Powerhouse", "Slasher" ], 3, 15, 6, 1, 70, 1066998, 79, 90, 40, 864, 768, 240, 1 ], + [ "Monkey D. Luffy, Straw Hat • Heart Pirates Alliance", "PSY", [ "Fighter", "Free Spirit" ], 4, 15, 4, 4, 99, 2000000, 209, 113, 12, 2105, 1244, 224, 1 ], + [ "Shiryu, Blackbeard Pirates", "INT", [ "Slasher", "Driven" ], 4, 25, 6, 3, 70, 1066998, 444, 444, -300, 1099, 750, -300, 1 ], + [ "Shiryu of the Rain, Blackbeard Pirates", "INT", [ "Slasher", "Driven" ], 5, 40, 5, 5, 99, 4000000, 1020, 670, -300, 3000, 1505, -300, 1 ], + [ "Thunder Lord McGuy", "STR", [ "Slasher", "Cerebral" ], 4, 26, 6, 3, 99, 3000000, 151, 90, 98, 1760, 1190, 257, 1 ], + [ "Portgas D. Ace, Luffy's \"Brother\"", "STR", [ "Free Spirit", "Shooter" ], 3, 8, 5, 2, 50, 261406, 50, 30, 10, 950, 500, 150, 1 ], + [ "Portgas D. Ace, Whitebeard's \"Son\"", "STR", [ "Free Spirit", "Shooter" ], 4, 15, 4, 3, 99, 2000000, 880, 410, 110, 1850, 1090, 260, 1 ], + [ "Laffitte, Blackbeard Pirates", "PSY", [ "Shooter", "Cerebral" ], 4, 25, 7, 4, 99, 3000000, 93, 49, 29, 2044, 949, 323, 1 ], + [ "Van Augur, BlackBeard Pirates", "DEX", [ "Shooter", "Driven" ], 4, 25, 5, 4, 99, 3000000, 87, 55, 22, 2006, 1050, 280, 1 ], + [ "Doc Q, BlackBeard Pirates", "INT", [ "Free Spirit", "Shooter" ], 4, 25, 4, 4, 99, 3000000, 51, 59, 31, 1502, 1138, 340, 1 ], + [ "Kami Enel, Endless Dreams of Arch Enemies", "QCK", [ "Shooter", "Striker" ], 5, 30, 4, 3, 70, 1066998, 350, 219, 56, 1256, 756, 236, 1 ], + [ "Kami Enel, Clash of the Great Pirate Era [Fairy Vearth]", "QCK", [ "Shooter", "Striker" ], 6, 55, 4, 5, 99, 5000000, 1189, 681, 170, 2890, 1503, 414, 1 ], + [ "Bartholomew Kuma, Endless Dreams of Arch Enemies", "PSY", [ "Shooter", "Cerebral" ], 4, 15, 5, 3, 50, 392109, 212, 123, 25, 1400, 554, 114, 1 ], + [ "Bartholomew Kuma, Clash of the Great Pirate Era [Crew Obliterator]", "PSY", [ "Shooter", "Cerebral" ], 5, 30, 4, 4, 99, 4000000, 1323, 489, 69, 3035, 1300, 220, 1 ], + [ "Rob Lucci, Endless Dreams of Arch Enemies", "DEX", [ "Fighter", "Slasher" ], 4, 15, 4, 3, 50, 392109, 155, 160, 19, 1256, 690, 94, 1 ], + [ "Rob Lucci, Clash of the Great Pirate Era [Dark Justice]", "DEX", [ "Fighter", "Slasher" ], 5, 30, 4, 4, 99, 4000000, 1189, 621, 56, 2814, 1490, 177, 1 ], + [ "Mr.0, Endless Dreams of Arch Enemies", "INT", [ "Striker", "Driven" ], 4, 15, 5, 3, 50, 392109, 147, 144, 22, 1201, 604, 109, 1 ], + [ "Mr. 0, Clash of the Great Pirate Era [Utopia]", "INT", [ "Striker", "Driven" ], 5, 30, 4, 4, 99, 4000000, 1131, 540, 59, 2760, 1457, 197, 1 ], + [ "Gecko Moria, Endless Dreams of Arch Enemies", "STR", [ "Driven", "Slasher" ], 4, 15, 6, 3, 50, 392109, 190, 150, 0, 1390, 699, 0, 1 ], + [ "Gecko Moria, Clash of the Great Pirate Era [The Strongest Crew]", "STR", [ "Driven", "Fighter" ], 5, 30, 4, 4, 99, 4000000, 1328, 620, 0, 3002, 1501, 0, 1 ], + [ "\"Dark King\" Silvers Rayleigh, Right Hand of the Pirate King", "INT", [ "Slasher", "Fighter" ], "6+", 65, 5, 4, 99, 5000000, 1500, 800, 300, 3121, 1472, 515, 1 ], + [ "Eustass Kid, Wakes of an Endless Dream, Kid Pirates", "STR", [ "Striker", "Driven" ], 4, 20, 4, 3, 70, 1066998, 281, 190, 30, 1424, 690, 151, 1 ], + [ "Eustass Kid, A Vow in the Great Age of Pirates - Pirate King", "STR", [ "Striker", "Driven" ], 5, 30, 5, 4, 99, 4000000, 1339, 620, 109, 2795, 1324, 287, 1 ], + [ "Donquixote Doflamingo [Neo]", "INT", [ "Slasher", "Driven" ], 4, 30, 4, 2, 70, 1066998, 184, 191, 31, 1030, 794, 149, 1 ], + [ "Donquixote Doflamingo [Neo], Warlord of the Sea", "INT", [ "Slasher", "Driven" ], 5, 50, 5, 3, 99, 4000000, 889, 726, 121, 2287, 1510, 262, 1 ], + [ "Hyouzou, Fishman Pirates Bodyguard", "QCK", [ "Powerhouse", "Slasher" ], 4, 20, 6, 4, 99, 3000000, 85, 58, 27, 1980, 1088, 345, 1 ], + [ "Daruma, Deep Sea Fishman Pirates", "STR", [ "Powerhouse", "Fighter" ], 4, 20, 4, 4, 99, 3000000, 48, 53, 24, 1405, 985, 320, 1 ], + [ "Dosun, Deep Sea Fishman Pirates", "PSY", [ "Powerhouse", "Striker" ], 4, 20, 6, 4, 99, 3000000, 91, 60, 21, 2050, 1155, 274, 1 ], + [ "Machvise, Super Weight Human", "DEX", [ "Striker", "Free Spirit" ], 4, 25, 4, 3, 70, 1066998, 140, 70, 16, 1540, 590, 98, 1 ], + [ "Machvise, Diamante Military Leader", "DEX", [ "Striker", "Free Spirit" ], 5, 40, 4, 4, 99, 4000000, 1310, 490, 77, 3110, 1198, 186, 1 ], + [ "Ikaros, Deep Sea Fishman Pirates", "INT", [ "Striker", "Powerhouse" ], 3, 16, 5, 2, 50, 392109, 93, 54, 24, 920, 446, 151, 1 ], + [ "Ikaros Much, The Rebellious Fishman Pirates", "INT", [ "Striker", "Powerhouse" ], 4, 26, 4, 3, 99, 3000000, 876, 409, 104, 2231, 1142, 199, 1 ], + [ "Fisher Tiger", "PSY", [ "Powerhouse", "Fighter" ], 4, 20, 5, 3, 70, 1066998, 140, 198, 36, 1323, 707, 180, 1 ], + [ "Fisher Tiger, Captain of the Sun Pirates", "PSY", [ "Powerhouse", "Fighter" ], 5, 30, 4, 4, 99, 4000000, 1250, 630, 132, 2522, 1386, 313, 1 ], + [ "Dragon of Punk Hazard", "STR", [ "Powerhouse", "Shooter" ], 3, 15, 4, 2, 70, 1066998, 159, 220, 18, 1117, 883, 177, 1 ], + [ "Rock and Scotch", "INT", [ "Shooter", "Powerhouse" ], 3, 15, 7, 2, 99, 3000000, 192, 210, 13, 1541, 1260, 104, 1 ], + [ "Brownbeard, Punk Hazard Centaur Patrol Unit Leader", "PSY", [ "Slasher", "Powerhouse" ], 3, 15, 6, 2, 99, 3000000, 89, 70, 17, 1431, 1132, 177, 1 ], + [ "Caesar Clown, Former Government Scientist", "QCK", [ "Shooter", "Cerebral" ], 3, 13, 4, 1, 50, 392109, 81, 54, 25, 989, 565, 187, 1 ], + [ "Master Caesar Clown, Former Government Scientist", "QCK", [ "Cerebral", "Shooter" ], 4, 20, 5, 3, 99, 3000000, 913, 498, 125, 1813, 1220, 301, 1 ], + [ "Punk Hazard Gas Mask Patrol Soldier [STR]", "STR", [ "Shooter", "Free Spirit" ], 3, 12, 8, 1, 60, 449516, 57, 38, 12, 1148, 770, 123, 1 ], + [ "Punk Hazard Gas Mask Patrol Soldier [QCK]", "QCK", [ "Shooter", "Free Spirit" ], 3, 12, 8, 1, 60, 449516, 51, 33, 13, 1025, 671, 187, 1 ], + [ "Punk Hazard Gas Mask Patrol Soldier [DEX]", "DEX", [ "Shooter", "Free Spirit" ], 3, 12, 8, 1, 60, 449516, 54, 36, 15, 1093, 727, 147, 1 ], + [ "Punk Hazard Gas Mask Patrol Soldier [INT]", "INT", [ "Shooter", "Free Spirit" ], 3, 12, 8, 1, 60, 449516, 57, 37, 17, 1147, 756, 143, 1 ], + [ "Punk Hazard Gas Mask Patrol Soldier [PSY]", "PSY", [ "Shooter", "Free Spirit" ], 3, 12, 8, 1, 60, 449516, 63, 32, 15, 1263, 643, 157, 1 ], + [ "Strong Leg Centaur, Punk Hazard Patrol Troop Corps", "STR", [ "Slasher", "Powerhouse" ], 3, 12, 6, 1, 60, 449516, 62, 35, 15, 1247, 717, 154, 1 ], + [ "Nimble-footed Centaur, Punk Hazard Patrol Troop Corps", "QCK", [ "Slasher", "Powerhouse" ], 3, 12, 6, 1, 60, 449516, 57, 34, 18, 1141, 684, 182, 1 ], + [ "Skilled Footwork Centaur, Punk Hazard Patrol Troop Corps", "DEX", [ "Slasher", "Powerhouse" ], 3, 12, 6, 1, 60, 449516, 59, 35, 16, 1182, 700, 169, 1 ], + [ "Pica [Neo]", "STR", [ "Powerhouse", "Driven" ], 4, 30, 4, 2, 70, 1066998, 270, 129, 1, 1700, 660, 2, 1 ], + [ "Pica [Neo], Donquixote Pirates", "STR", [ "Powerhouse", "Driven" ], 5, 50, 4, 3, 99, 5000000, 1630, 582, 1, 4020, 1210, 5, 1 ], + [ "Giolla, Art Human", "STR", [ "Shooter", "Free Spirit" ], 3, 13, 4, 3, 50, 392109, 73, 55, 13, 700, 505, 165, 1 ], + [ "Giolla, Trebol Army", "STR", [ "Shooter", "Free Spirit" ], 4, 20, 4, 4, 99, 3000000, 653, 456, 157, 2040, 936, 298, 1 ], + [ "Brook, Psychedelic Arts", "DEX", [ "Slasher", "Free Spirit" ], 4, 20, 6, 4, 99, 3000000, 203, 130, 29, 1830, 1140, 265, 1 ], + [ "Nekomamushi", "PSY", [ "Striker", "Powerhouse" ], 5, 30, 7, 3, 70, 1066998, 475, 167, 38, 1593, 666, 189, 1 ], + [ "\"King of the Night\" Nekomamushi", "PSY", [ "Striker", "Powerhouse" ], 6, 55, 4, 5, 99, 5000000, 1509, 613, 132, 3404, 1451, 352, 1 ], + [ "Pedro", "INT", [ "Slasher", "Cerebral" ], 4, 15, 5, 3, 50, 392109, 110, 148, 58, 957, 620, 213, 1 ], + [ "Pedro of the Treetops", "INT", [ "Slasher", "Cerebral" ], 5, 30, 4, 4, 99, 4000000, 878, 544, 162, 2009, 1438, 325, 1 ], + [ "Carrot", "QCK", [ "Fighter", "Free Spirit" ], 4, 15, 6, 3, 50, 392109, 113, 99, 60, 1006, 539, 220, 1 ], + [ "Ruler's Aide Carrot", "QCK", [ "Fighter", "Free Spirit" ], 5, 30, 4, 4, 99, 4000000, 941, 461, 171, 2041, 1250, 390, 1 ], + [ "Kanjuro, Wano Country Samurai", "DEX", [ "Striker", "Free Spirit" ], 4, 15, 4, 3, 50, 392109, 133, 116, 44, 1100, 574, 196, 1 ], + [ "Evening Shower Kanjuro, Wano Country Samurai", "DEX", [ "Striker", "Free Spirit" ], 5, 30, 4, 4, 99, 4000000, 1026, 511, 144, 2306, 1301, 329, 1 ], + [ "Raizo", "STR", [ "Shooter", "Free Spirit" ], 4, 15, 6, 3, 50, 392109, 129, 133, 34, 1126, 604, 152, 1 ], + [ "Raizo of the Mist", "STR", [ "Shooter", "Free Spirit" ], 5, 30, 8, 4, 99, 4000000, 1067, 526, 110, 2353, 1363, 290, 1 ], + [ "Corazon, Wish to Remove the Rain", "QCK", [ "Free Spirit", "Cerebral" ], 4, 15, 6, 3, 50, 392109, 225, 111, 60, 1167, 465, 187, 1 ], + [ "Corazon, Silencing the Rain", "QCK", [ "Free Spirit", "Cerebral" ], 5, 30, 4, 4, 99, 4000000, 1076, 411, 178, 2511, 1022, 320, 1 ], + [ "Rob Lucci \"Life Return\", CP9's Strongest", "STR", [ "Powerhouse", "Fighter" ], "6+", 65, 4, 4, 99, 5000000, 1704, 790, 230, 3480, 1570, 390, 1 ], + [ "Aokiji, \"One-on-One Fight\" Opponent", "STR", [ "Shooter", "Slasher" ], 4, 20, 7, 3, 70, 1066998, 126, 130, 49, 1220, 724, 195, 1 ], + [ "Aokiji, \"One-on-One Fight\" Winner", "STR", [ "Shooter", "Striker" ], 5, 30, 4, 4, 99, 4000000, 1174, 655, 155, 2364, 1406, 336, 1 ], + [ "Kyros, Undefeated Gladiator", "QCK", [ "Powerhouse", "Striker" ], 4, 25, 4, 3, 70, 1066998, 245, 178, 34, 1320, 701, 177, 1 ], + [ "Kyros, Riku Royal Army Commander", "QCK", [ "Powerhouse", "Striker" ], 5, 40, 4, 5, 99, 4000000, 1220, 670, 157, 2710, 1390, 225, 1 ], + [ "Aokiji [Neo]", "DEX", [ "Striker", "Free Spirit" ], 4, 30, 4, 2, 70, 1066998, 239, 157, 34, 1150, 710, 161, 1 ], + [ "Aokiji [Neo], Ice Human", "DEX", [ "Striker", "Free Spirit" ], 5, 50, 4, 3, 99, 5000000, 1099, 640, 126, 2500, 1430, 254, 1 ], + [ "Madame Shyarly, Mermaid Cafe Manager", "DEX", [ "Cerebral", "Fighter" ], 4, 20, 6, 3, 99, 3000000, 154, 105, 29, 1950, 1140, 315, 1 ], + [ "Camie, Mermaid Cafe", "QCK", [ "Free Spirit", "Fighter" ], 4, 20, 4, 3, 99, 3000000, 122, 52, 38, 1850, 946, 350, 1 ], + [ "Pappagu, \"Criminal Brand Company\" President and Super Famous Celebrity Fashion Desginer", "PSY", [ "Fighter", "Powerhouse" ], 3, 13, 8, 3, 70, 1066998, 108, 41, 21, 920, 855, 180, 1 ], + [ "Perona, Dark Beach Princess", "QCK", [ "Shooter", "Driven" ], 4, 15, 4, 3, 50, 392109, 128, 77, 50, 946, 490, 210, 1 ], + [ "Perona, Audacious Swimsuit Princess", "QCK", [ "Shooter", "Driven" ], 5, 30, 4, 4, 99, 4000000, 873, 406, 173, 1904, 1003, 436, 1 ], + [ "Roronoa Zoro, Young Swordsman", "PSY", [ "Slasher", "Driven" ], 4, 15, 6, 2, 50, 392109, 152, 104, 24, 1008, 604, 131, 1 ], + [ "Roronoa Zoro, Rain Soaked Samurai", "PSY", [ "Slasher", "Driven" ], 5, 30, 4, 3, 99, 4000000, 931, 536, 85, 2094, 1193, 257, 1 ], + [ "Trafalgar Law, Wakes of an Endless Dream, Heart Pirates", "INT", [ "Slasher", "Free Spirit" ], 4, 20, 5, 3, 70, 1066998, 110, 137, 51, 1193, 733, 204, 1 ], + [ "Trafalgar Law, A Vow in the Great Age of Pirates - Free Spirit", "INT", [ "Slasher", "Free Spirit" ], 5, 30, 4, 4, 99, 4000000, 1109, 660, 164, 2177, 1423, 361, 1 ], + [ "Dracule Mihawk [Neo]", "QCK", [ "Slasher", "Free Spirit" ], 4, 30, 4, 1, 70, 1066998, 328, 194, 3, 2009, 804, 9, 1 ], + [ "Hawk Eyes Mihawk [Neo]", "QCK", [ "Slasher", "Free Spirit" ], 5, 50, 4, 2, 99, 5000000, 1934, 778, 13, 3794, 1280, 24, 1 ], + [ "Monkey D. Luffy, Celebrate 20th Anniversary Cruise", "STR", [ "Fighter", "Free Spirit" ], 4, 15, 6, 3, 50, 392109, 654, 420, 39, 1206, 719, 175, 1 ], + [ "Monkey D. Luffy, 20th Anniversary Memorial Treasure", "STR", [ "Fighter", "Free Spirit" ], 5, 30, 8, 5, 99, 4000000, 1033, 587, 113, 2440, 1406, 279, 1 ], + [ "Nico Robin, Celebrate 20th Anniversary Cruise", "QCK", [ "Fighter", "Cerebral" ], 4, 15, 5, 3, 50, 392109, 601, 335, 66, 1043, 604, 257, 1 ], + [ "Nico Robin, 20th Anniversary Memorial Treasure", "QCK", [ "Fighter", "Cerebral" ], 5, 30, 4, 5, 99, 4000000, 878, 478, 189, 2126, 1200, 404, 1 ], + [ "Usopp, Celebrate 20th Anniversary Cruise", "INT", "Shooter", 4, 15, 6, 3, 50, 392109, 707, 324, 49, 1313, 587, 209, 1 ], + [ "Usopp, 20th Anniversary Memorial Treasure", "INT", "Shooter", 5, 30, 4, 5, 99, 4000000, 1146, 432, 148, 2550, 1184, 336, 1 ], + [ "Franky, Celebrate 20th Anniversary Cruise", "DEX", [ "Fighter", "Free Spirit" ], 4, 15, 6, 3, 50, 392109, 794, 385, 30, 1599, 687, 126, 1 ], + [ "Franky, 20th Anniversary Memorial Treasure", "DEX", [ "Fighter", "Free Spirit" ], 5, 30, 10, 5, 99, 4000000, 1487, 559, 69, 3095, 1255, 205, 1 ], + [ "Eustass Kid, Supernova Born from the South Blue", "INT", [ "Striker", "Driven" ], 3, 13, 4, 2, 50, 392109, 125, 61, 40, 757, 579, 155, 1 ], + [ "Captain Kid, Supernova Born from the South Blue", "INT", [ "Striker", "Driven" ], 4, 20, 5, 3, 99, 3000000, 740, 565, 144, 2154, 1406, 204, 1 ], + [ "Heat", "STR", [ "Shooter", "Driven" ], 3, 15, 4, 3, 70, 1066998, 133, 66, 45, 1201, 955, 122, 1 ], + [ "Wire", "DEX", [ "Striker", "Driven" ], 3, 15, 6, 3, 70, 1066998, 145, 55, 41, 1449, 896, 101, 1 ], + [ "Inuarashi, Mokomo Dukedom", "PSY", [ "Slasher", "Cerebral" ], 4, 25, 6, 3, 70, 1066998, 545, 303, 36, 1241, 751, 190, 1 ], + [ "\"Ruler of Day\" Inuarashi, Mokomo Dukedom", "PSY", [ "Slasher", "Cerebral" ], 5, 40, 4, 5, 99, 4000000, 1188, 688, 148, 2330, 1405, 301, 1 ], + [ "Demon Bamboo Vergo", "DEX", [ "Fighter", "Striker" ], 4, 30, 4, 1, 70, 1066998, 280, 158, 34, 1253, 697, 152, 1 ], + [ "Demon Bamboo Vergo, Donquiote Family Senior Executive", "DEX", [ "Fighter", "Striker" ], 5, 50, 5, 2, 99, 5000000, 1016, 626, 108, 2265, 1402, 245, 1 ], + [ "Magellan, Prison Ruler", "DEX", [ "Striker", "Shooter" ], 5, 30, 6, 3, 70, 1066998, 480, 220, 24, 1552, 755, 145, 1 ], + [ "Magellan, Hell's Ruler", "DEX", [ "Striker", "Shooter" ], 6, 55, 5, 5, 99, 5000000, 1470, 700, 99, 3527, 1499, 291, 1 ], + [ "Jinbe, \"Eternal Hell\" Prisoner", "PSY", [ "Fighter", "Powerhouse" ], 4, 15, 6, 3, 50, 392109, 156, 137, 30, 1120, 674, 196, 1 ], + [ "Jinbe, Hell's Warlord of the Sea", "PSY", [ "Fighter", "Powerhouse" ], 5, 30, 4, 4, 99, 4000000, 1056, 620, 132, 2188, 1392, 320, 1 ], + [ "Emporio Ivankov, \"Newkama Land\" Prisoner", "QCK", [ "Free Spirit", "Cerebral" ], 4, 15, 6, 3, 50, 392109, 166, 110, 37, 1200, 634, 208, 1 ], + [ "Emporio Ivankov, Hell's Revolutionary Army Officer", "QCK", [ "Free Spirit", "Cerebral" ], 5, 30, 4, 4, 99, 4000000, 1148, 550, 176, 2389, 1244, 340, 1 ], + [ "Hannyabal, Ruler's Confidant", "INT", [ "Driven", "Striker" ], 4, 15, 6, 3, 50, 392109, 198, 125, 20, 1340, 669, 101, 1 ], + [ "Hannyabal, Now the Ruler's Trusted Retainer", "INT", [ "Driven", "Striker" ], 5, 30, 4, 4, 99, 4000000, 1277, 589, 57, 2910, 1309, 221, 1 ], + [ "Mr. 2 Bon Clay, \"Starvation Hell\" Prisoner", "STR", [ "Free Spirit", "Fighter" ], 4, 15, 6, 3, 50, 392109, 172, 98, 40, 1210, 596, 212, 1 ], + [ "Mr. 2 Bon Clay, A Friend in Hell", "STR", [ "Free Spirit", "Fighter" ], 5, 30, 7, 4, 99, 4000000, 1145, 542, 170, 2402, 1202, 355, 1 ], + [ "Red Hair Shanks, Four Emperors", "PSY", [ "Slasher", "Cerebral" ], "6+", 65, 5, 5, 99, 5000000, 1574, 752, 277, 3204, 1510, 464, 1 ], + [ "Nami, Midsummer Heartbeat", "QCK", [ "Cerebral", "Fighter" ], 4, 12, 6, 2, 50, 261406, 72, 72, 72, 906, 402, 196, 1 ], + [ "Nami, Midsummer Excitement", "QCK", [ "Cerebral", "Striker" ], 5, 20, 4, 3, 99, 3000000, 832, 334, 142, 1903, 940, 386, 1 ], + [ "Nico Robin, Healthful Beauty", "PSY", [ "Fighter", "Cerebral" ], 4, 12, 5, 2, 50, 261406, 72, 72, 72, 920, 417, 179, 1 ], + [ "Nico Robin, Cultural Symbol", "PSY", [ "Fighter", "Cerebral" ], 5, 20, 4, 3, 99, 3000000, 851, 366, 133, 1949, 1007, 355, 1 ], + [ "Akainu, Summit War Coverfire", "DEX", [ "Powerhouse", "Driven" ], 4, 20, 5, 3, 70, 1066998, 138, 150, 23, 1255, 760, 143, 1 ], + [ "Akainu, Summit War Hellfire", "DEX", [ "Powerhouse", "Driven" ], 5, 30, 4, 4, 99, 4000000, 1187, 724, 99, 2506, 1505, 251, 1 ], + [ "Monet, Incarnation of Ice and Snow", "INT", [ "Free Spirit", "Cerebral" ], 4, 20, 4, 2, 70, 1066998, 131, 103, 67, 1830, 719, 220, 1 ], + [ "Vergo, G-5 Navy Base Commander", "QCK", [ "Striker", "Fighter" ], 4, 20, 6, 3, 99, 3000000, 275, 203, 75, 1650, 1219, 300, 1 ], + [ "Caesar Clown, Shinokuni Ruler", "STR", [ "Driven", "Fighter" ], 5, 30, 4, 4, 99, 4000000, 1097, 717, 130, 2194, 1435, 260, 1 ], + [ "Vegapunk's Dragon (Small)", "QCK", [ "Shooter", "Driven" ], 3, 15, 4, 2, 70, 1066998, 238, 125, 45, 1429, 750, 152, 1 ], + [ "Buffalo, Donquixote Pirates' Combatant", "DEX", [ "Free Spirit", "Driven" ], 4, 20, 8, 2, 70, 1066998, 191, 81, 55, 1731, 755, 220, 1 ], + [ "Baby 5, Donquixote Pirates' Servant and Assassin", "PSY", [ "Shooter", "Slasher" ], 4, 20, 8, 2, 70, 1066998, 154, 111, 47, 1239, 1161, 171, 1 ], + [ "Jinbe", "QCK", [ "Striker", "Fighter" ], 4, 20, 6, 3, 70, 1066998, 158, 113, 39, 1284, 698, 178, 1 ], + [ "\"Boss\" Jinbe, Ryugu Kingdom Neptune's Soldier", "QCK", [ "Fighter", "Powerhouse" ], 5, 30, 4, 4, 99, 4000000, 1220, 614, 132, 2594, 1330, 320, 1 ], + [ "Sea God Neptune", "PSY", [ "Striker", "Cerebral" ], 3, 13, 6, 2, 50, 392109, 159, 56, 51, 611, 498, 189, 1 ], + [ "Sea God Neptune, King of Ryugu Kingdom", "PSY", [ "Striker", "Cerebral" ], 4, 20, 4, 3, 99, 3000000, 598, 445, 175, 1737, 1011, 324, 1 ], + [ "Fukaboshi, Neptune Family Three Brothers - The First Son", "QCK", [ "Striker", "Powerhouse" ], 3, 13, 6, 2, 50, 392019, 166, 52, 44, 655, 588, 164, 1 ], + [ "Fukaboshi, Top Three of the Royal Army", "QCK", [ "Striker", "Powerhouse" ], 4, 20, 6, 3, 99, 3000000, 617, 512, 155, 2015, 1201, 238, 1 ], + [ "Sabo [Neo], Dragon Claw", "PSY", [ "Fighter", "Free Spirit" ], 4, 30, 5, 3, 70, 1066998, 238, 135, 37, 1305, 676, 190, 1 ], + [ "Sabo [Neo], Revolutionary Army Chief of Staff", "PSY", [ "Fighter", "Free Spirit" ], 5, 50, 4, 4, 99, 5000000, 1235, 595, 147, 2494, 1305, 345, 1 ], + [ "Tashigi, Beach Captain", "STR", [ "Slasher", "Cerebral" ], 4, 12, 6, 2, 50, 392109, 72, 72, 72, 870, 469, 201, 1 ], + [ "Tashigi, Holiday Captain-chan", "STR", [ "Slasher", "Cerebral" ], 5, 20, 4, 3, 99, 4000000, 813, 400, 151, 1770, 1090, 357, 1 ], + [ "Nefeltari Vivi, Dazzling Pure White", "INT", [ "Free Spirit", "Striker" ], 4, 20, 4, 3, 70, 1066998, 130, 73, 51, 957, 484, 214, 1 ], + [ "Nefeltari Vivi, Alluring Sensation", "INT", [ "Free Spirit", "Striker" ], 5, 30, 5, 4, 99, 4000000, 889, 403, 157, 1990, 996, 445, 1 ], + [ "Nekomamushi, Guardian of the Whale Forest", "STR", [ "Striker", "Powerhouse" ], 4, 25, 6, 3, 70, 1066998, 563, 292, 38, 1285, 747, 205, 1 ], + [ "\"Ruler of Night\" Nekomamushi, Guardian of the Whale Forest", "STR", [ "Striker", "Powerhouse" ], 5, 40, 4, 5, 99, 4000000, 1200, 678, 149, 2440, 1375, 315, 1 ], + [ "Sugar, Hobby Hobby Fruit Ability User", "STR", [ "Cerebral", "Fighter" ], 3, 13, 4, 2, 50, 392109, 150, 102, 30, 646, 367, 220, 1 ], + [ "Sugar, Trebol Army Special Executive", "STR", [ "Cerebral", "Fighter" ], 4, 20, 4, 3, 99, 3000000, 597, 311, 203, 1830, 975, 320, 1 ], + [ "Trebol, Sticky Sticky Fruit Ability User", "INT", [ "Cerebral", "Driven" ], 3, 13, 5, 2, 50, 392109, 230, 156, 9, 1020, 519, 107, 1 ], + [ "Trebol, Donquiote Family Elite Executive", "INT", [ "Cerebral", "Driven" ], 4, 20, 4, 3, 99, 3000000, 975, 476, 97, 2540, 1220, 120, 1 ], + [ "Bellamy the Hyena [Neo], Former Captain of the Bellamy Pirates", "STR", [ "Fighter", "Driven" ], 4, 30, 4, 1, 70, 1066998, 173, 125, 31, 977, 711, 194, 1 ], + [ "Bellamy the Hyena [Neo], Bullet of Dressrosa", "STR", [ "Fighter", "Driven" ], 5, 50, 4, 3, 99, 5000000, 893, 634, 149, 2014, 1320, 308, 1 ], + [ "Boa Sandersonia, Strawhat Luffy's Cooperator", "DEX", [ "Striker", "Powerhouse" ], 4, 15, 6, 3, 50, 392109, 187, 118, 30, 1148, 531, 169, 1 ], + [ "Boa Sandersonia, Strawhat Luffy's Accomplice", "DEX", [ "Striker", "Powerhouse" ], 5, 30, 7, 4, 99, 4000000, 1085, 459, 126, 2503, 1267, 320, 1 ], + [ "Boa Marigold, Strawhat Luffy's Cooperator", "STR", [ "Striker", "Powerhouse" ], 4, 15, 5, 3, 50, 392109, 190, 126, 25, 1155, 556, 147, 1 ], + [ "Boa Marigold, Strawhat Luffy's Accomplice", "STR", [ "Striker", "Powerhouse" ], 5, 30, 5, 4, 99, 4000000, 1091, 477, 103, 2520, 1319, 294, 1 ], + [ "Marguerite, Strawhat Luffy's Cooperator", "INT", "Shooter", 4, 15, 5, 3, 50, 392109, 144, 94, 41, 1031, 488, 203, 1 ], + [ "Marguerite, Strawhat Luffy's Accomplice", "INT", "Shooter", 5, 30, 4, 4, 99, 4000000, 974, 434, 162, 2062, 1063, 450, 1 ], + [ "Boa Hancock, Strawhat Luffy's Cooperator", "PSY", [ "Shooter", "Fighter" ], 5, 30, 4, 3, 70, 1066998, 294, 255, 77, 1326, 790, 189, 1 ], + [ "Boa Hancock, Strawhat Luffy's Accomplice", "PSY", [ "Shooter", "Free Spirit" ], 6, 55, 4, 5, 99, 5000000, 1265, 734, 230, 2795, 1430, 478, 1 ], + [ "Bepo, Strawhat Luffy's Cooperator", "QCK", [ "Fighter", "Powerhouse" ], 4, 15, 5, 3, 50, 392109, 169, 108, 33, 1100, 501, 191, 1 ], + [ "Bepo, Strawhat Luffy's Accomplice", "QCK", [ "Fighter", "Powerhouse" ], 5, 30, 4, 4, 99, 4000000, 1054, 446, 151, 2357, 1129, 384, 1 ], + [ "\"Surgeon of Death\" Trafalgar Law, Search for \"Joker\"", "QCK", [ "Striker", "Slasher" ], 5, 30, 4, 3, 70, 1066998, 429, 232, 49, 1560, 775, 202, 1 ], + [ "\"Warlord of the Sea\" Trafalgar Law, Aim for \"Joker\"", "QCK", [ "Striker", "Slasher" ], 6, 55, 4, 5, 99, 5000000, 1482, 703, 152, 3003, 1502, 401, 1 ], + [ "Roronoa Zoro, Celebrate 20th Anniversary Cruise", "INT", [ "Slasher", "Driven" ], 4, 15, 6, 3, 50, 392109, 669, 404, 32, 1240, 710, 159, 1 ], + [ "Roronoa Zoro, 20th Anniversary Memorial Treasure", "INT", [ "Slasher", "Driven" ], 5, 30, 4, 5, 99, 4000000, 1043, 554, 94, 2503, 1400, 269, 1 ], + [ "Sanji, Celebrate 20th Anniversary Cruise", "PSY", [ "Fighter", "Powerhouse" ], 4, 15, 6, 3, 50, 392109, 650, 394, 41, 1230, 698, 200, 1 ], + [ "Sanji, 20th Anniversary Memorial Treasure", "PSY", [ "Fighter", "Powerhouse" ], 5, 30, 4, 5, 99, 4000000, 1032, 574, 137, 2417, 1353, 305, 1 ], + [ "Nami, Celebrate 20th Anniversary Cruise", "STR", [ "Striker", "Cerebral" ], 4, 15, 4, 3, 50, 392109, 598, 303, 80, 1001, 554, 287, 1 ], + [ "Nami, 20th Anniversary Memorial Treasure", "STR", [ "Striker", "Cerebral" ], 5, 30, 6, 5, 99, 4000000, 820, 420, 220, 2076, 1179, 417, 1 ], + [ "Brook, Celebrate 20th Anniversary Cruise", "QCK", [ "Free Spirit", "Slasher" ], 4, 15, 7, 3, 50, 392109, 642, 387, 42, 1187, 670, 223, 1 ], + [ "Brook, 20th Anniversary Memorial Treasure", "QCK", [ "Free Spirit", "Slasher" ], 5, 30, 4, 5, 99, 4000000, 1076, 569, 148, 2274, 1336, 333, 1 ], + [ "Tony Tony Chopper, Celebrate 20th Anniversary Cruise", "DEX", [ "Fighter", "Cerebral" ], 4, 15, 6, 3, 50, 392109, 644, 343, 44, 1184, 589, 240, 1 ], + [ "Tony Tony Chopper, 20th Anniversary Memorial Treasure", "DEX", [ "Fighter", "Cerebral" ], 5, 30, 4, 5, 99, 4000000, 1023, 474, 187, 2330, 1258, 351, 1 ], + [ "Rob Lucci, World Government Monster", "QCK", [ "Powerhouse", "Shooter" ], 5, 30, 4, 3, 70, 1066998, 398, 231, 33, 1358, 769, 197, 1 ], + [ "Human Beast Lucci, World Government Monster", "QCK", [ "Powerhouse", "Shooter" ], 6, 55, 4, 5, 99, 5000000, 1287, 722, 141, 3205, 1540, 323, 1 ], + [ "Kuzan, Former Navy HQ Greatest Military Power", "QCK", [ "Shooter", "Striker" ], "6+", 65, 4, 4, 99, 5000000, 1558, 751, 198, 3478, 1501, 420, 1 ], + [ "Longleg Blue Gilly", "DEX", [ "Fighter", "Free Spirit" ], 3, 13, 6, 1, 50, 392109, 120, 98, 17, 1110, 585, 90, 1 ], + [ "Longleg Blue Gilly, Jao Kun Do Martial Artist", "DEX", [ "Fighter", "Free Spirit" ], 4, 20, 4, 3, 99, 3000000, 972, 480, 88, 2208, 1185, 187, 1 ], + [ "Assassin Funk Brothers", "QCK", [ "Fighter", "Driven" ], 3, 15, 5, 2, 70, 1066998, 134, 68, 43, 1204, 964, 118, 1 ], + [ "Abdullah & Jeet, Vicious Criminals", "STR", [ "Slasher", "Striker" ], 3, 15, 7, 2, 70, 1066998, 152, 53, 41, 1452, 888, 102, 1 ], + [ "Ben Beckman, Red Hair Pirates First Mate", "INT", [ "Cerebral", "Striker" ], 4, 20, 6, 3, 70, 1066998, 129, 120, 38, 1190, 735, 209, 1 ], + [ "Ben Beckman, \"Four Emperors\" Red Hair's Right Hand Man", "INT", [ "Cerebral", "Striker" ], 5, 30, 4, 4, 99, 4000000, 1126, 672, 136, 2295, 1384, 367, 1 ], + [ "Tyrant Bartholomew Kuma [Neo]", "INT", [ "Cerebral", "Powerhouse" ], 4, 30, 4, 2, 70, 1066998, 258, 171, 90, 1189, 629, 190, 1 ], + [ "Tyrant Bartholomew Kuma [Neo], Government Human Weapon", "INT", [ "Cerebral", "Powerhouse" ], 5, 50, 7, 4, 99, 5000000, 1147, 578, 190, 3070, 1445, 90, 1 ], + [ "\"Samurai\" Kinemon", "INT", [ "Free Spirit", "Slasher" ], 3, 13, 6, 2, 50, 392109, 184, 106, 24, 990, 621, 78, 1 ], + [ "\"Samurai\" Foxfire Kinemon", "INT", [ "Free Spirit", "Slasher" ], 4, 20, 4, 3, 99, 3000000, 890, 560, 65, 2058, 1245, 192, 1 ], + [ "\"Samurai\" Momonosuke", "QCK", [ "Free Spirit", "Striker" ], 3, 9, 5, 2, 35, 136167, 54, 45, 6, 622, 427, 80, 1 ], + [ "\"Dragon\" Momonosuke", "QCK", [ "Free Spirit", "Striker" ], 4, 15, 4, 3, 70, 1066998, 646, 259, 80, 1596, 747, 160, 1 ], + [ "Kizaru, Emissary of the Holy Land", "QCK", [ "Free Spirit", "Shooter" ], 4, 20, 5, 3, 70, 1066998, 160, 114, 38, 1292, 700, 177, 1 ], + [ "Kizaru, A Visit from the Holy Land", "QCK", [ "Free Spirit", "Shooter" ], 5, 30, 7, 4, 99, 4000000, 1230, 1342, 315, 2613, 1342, 315, 1 ], + [ "Kizaru [Neo]", "DEX", [ "Fighter", "Shooter" ], 4, 30, 4, 2, 70, 1066998, 217, 171, 37, 1221, 746, 162, 1 ], + [ "Kizaru [Neo], Light Human", "DEX", [ "Fighter", "Shooter" ], 5, 50, 5, 4, 99, 5000000, 1164, 670, 132, 2486, 1415, 279, 1 ], + [ "Fighting Fish", "STR", [ "Fighter", "Powerhouse" ], 3, 15, 4, 2, 70, 1066998, 177, 122, 24, 1239, 854, 171, 1 ], + [ "Don Chinjao", "QCK", [ "Fighter", "Striker" ], 4, 20, 4, 2, 99, 3000000, 669, 652, 67, 1339, 1305, 135, 1 ], + [ "Hajrudin", "STR", [ "Fighter", "Powerhouse" ], 4, 20, 5, 2, 99, 4000000, 521, 301, 0, 2084, 1205, 0, 1 ], + [ "Fujitora", "INT", [ "Slasher", "Shooter" ], 4, 20, 5, 2, 99, 3000000, 896, 425, 30, 2690, 1276, 120, 1 ], + [ "Spartan", "PSY", [ "Fighter", "Driven" ], 3, 15, 6, 2, 70, 1066998, 415, 247, 20, 1660, 991, 93, 1 ], + [ "Donquixote Pirates Member, Fighting Corps Low Class Soldier", "STR", [ "Shooter", "Driven" ], 3, 12, 7, 1, 60, 449516, 99, 49, 12, 1543, 756, 123, 1 ], + [ "Donquixote Pirates Member, Special Attack Corps Low Class Soldier", "QCK", [ "Shooter", "Driven" ], 3, 12, 7, 1, 60, 449516, 118, 43, 9, 1656, 602, 124, 1 ], + [ "Donquixote Pirates Member, Special Forces Low Class Soldier", "DEX", [ "Shooter", "Driven" ], 3, 12, 7, 1, 60, 449516, 70, 46, 10, 1120, 746, 167, 1 ], + [ "Donquixote Pirates Member, Reconnaissance Corps Low Class Soldier", "INT", [ "Shooter", "Driven" ], 3, 12, 7, 1, 60, 449516, 83, 56, 10, 1170, 791, 143, 1 ], + [ "Donquixote Pirates Member, Secret Intelligence Corps Low Class Soldier", "PSY", [ "Shooter", "Driven" ], 3, 12, 7, 1, 60, 449516, 89, 39, 9, 1336, 663, 161, 1 ], + [ "Lucy, Corrida Colosseum C Block's Mysterious Gladiator", "DEX", [ "Fighter", "Free Spirit" ], 4, 25, 4, 3, 70, 1066998, 425, 365, 54, 1001, 699, 145, 1 ], + [ "Lucy, Corrida Colosseum C Block's Bold Opportunist", "DEX", [ "Fighter", "Free Spirit" ], 5, 40, 4, 5, 99, 4000000, 912, 613, 99, 2059, 1500, 271, 1 ], + [ "Lucy, Corrida Colosseum Final Round Lucky Adventurer", "STR", [ "Striker", "Fighter" ], 5, 30, 4, 3, 70, 1066998, 394, 237, 61, 1394, 798, 242, 1 ], + [ "Lucy, Corrida Colosseum Champion", "STR", [ "Striker", "Fighter" ], 6, 55, 4, 5, 99, 5000000, 1306, 720, 194, 3020, 1539, 390, 1 ], + [ "Mr. Diamante, Hero of the Corrida Colosseum", "QCK", [ "Driven", "Slasher" ], 4, 15, 6, 3, 50, 392109, 151, 155, 22, 1234, 692, 101, 1 ], + [ "Diamante, Dressrosa Current King's Family Member", "QCK", [ "Driven", "Slasher" ], 5, 30, 7, 4, 99, 4000000, 1156, 604, 69, 2401, 1487, 230, 1 ], + [ "Jesus Burgess, Corrida Colosseum A Block's \"Champion\"", "DEX", [ "Fighter", "Driven" ], 4, 15, 5, 3, 50, 392109, 209, 143, 29, 1164, 633, 120, 1 ], + [ "Jesus Burgess, The Hidden Shadow within the Birdcage", "DEX", [ "Fighter", "Driven" ], 5, 30, 4, 4, 99, 4000000, 1093, 554, 86, 2743, 1364, 238, 1 ], + [ "Cavendish, Corrida Colosseum D Block's \"Hakuba\"", "DEX", [ "Driven", "Slasher" ], 4, 15, 5, 3, 50, 392109, 133, 153, 40, 1172, 679, 167, 1 ], + [ "Cavendish, The Rebel within the Birdcage", "DEX", [ "Driven", "Slasher" ], 5, 30, 4, 4, 99, 4000000, 1099, 622, 132, 2046, 1466, 314, 1 ], + [ "Bartolomeo, Corrida Colosseum B Block's \"Cannibal\"", "QCK", [ "Fighter", "Driven" ], 4, 15, 5, 3, 50, 392109, 226, 115, 31, 1305, 546, 139, 1 ], + [ "Bartolomeo, The Rebel within the Birdcage", "QCK", [ "Striker", "Driven" ], 5, 30, 4, 4, 99, 4000000, 1221, 487, 99, 2789, 1289, 251, 1 ], + [ "Roronoa Zoro, East Blue Pirate", "DEX", [ "Slasher", "Driven" ], 4, 12, 5, 3, 50, 261406, 157, 96, 22, 957, 555, 134, 1 ], + [ "Roronoa Zoro, East Blue Swordsman", "DEX", [ "Slasher", "Driven" ], 5, 20, 4, 4, 99, 2000000, 886, 478, 79, 2014, 1111, 270, 1 ], + [ "Buggy the Clown, The Uncuttable Chop-Chop Man", "QCK", [ "Shooter", "Driven" ], 4, 12, 5, 3, 50, 261406, 166, 87, 29, 987, 509, 151, 1 ], + [ "Captain Buggy, The Uncuttable Chop-Chop Man", "QCK", [ "Shooter", "Driven" ], 5, 20, 4, 4, 99, 2000000, 920, 447, 112, 2143, 1000, 304, 1 ], + [ "Dracule Mihawk, The Strongest Swordsman Standing on Top of the World", "STR", "Slasher", 4, 30, 6, 1, 50, 130703, 324, 157, 23, 974, 456, 94, 1 ], + [ "Hawk Eyes Mihawk, The Strongest Swordsman Standing on Top of the World", "STR", "Slasher", 5, 60, 4, 1, 99, 5000000, 847, 332, 57, 2990, 1403, 186, 1 ], + [ "Wanda, Mokomo Dukedom", "PSY", [ "Slasher", "Free Spirit" ], 3, 13, 6, 2, 50, 392109, 184, 106, 24, 740, 530, 150, 1 ], + [ "Kingsbird Wanda, Mokomo Dukedom", "PSY", [ "Slasher", "Free Spirit" ], 4, 20, 4, 3, 99, 3000000, 714, 501, 137, 2042, 1139, 230, 1 ], + [ "Carrot, Mokomo Dukedom", "DEX", [ "Fighter", "Slasher" ], 3, 13, 6, 2, 50, 392109, 104, 130, 6, 726, 768, 73, 1 ], + [ "Kingsbird Carrot, Mokomo Dukedom", "DEX", [ "Fighter", "Slasher" ], 4, 20, 5, 3, 99, 3000000, 689, 729, 65, 2166, 1220, 189, 1 ], + [ "Koala, Revolutionary Army's Secret Task Force", "PSY", [ "Fighter", "Free Spirit" ], 4, 15, 4, 4, 99, 2000000, 238, 82, 18, 2422, 1012, 249, 1 ], + [ "Vinsmoke Sanji", "STR", [ "Powerhouse", "Fighter" ], 4, 30, 4, 2, 70, 1066998, 225, 176, 37, 1194, 749, 198, 1 ], + [ "Vinsmoke Sanji, Germa Kingdom", "STR", [ "Powerhouse", "Fighter" ], 5, 50, 4, 3, 99, 4000000, 1099, 677, 157, 2267, 1468, 346, 1 ], + [ "Portgas D. Ace, The Sun that will Destroy the Darkness", "DEX", [ "Shooter", "Free Spirit" ], "6+", 65, 4, 5, 99, 5000000, 1911, 711, 215, 3922, 1466, 358, 1 ], + [ "King Riku", "INT", [ "Cerebral", "Striker" ], 3, 13, 6, 2, 50, 392109, 150, 102, 30, 720, 396, 198, 1 ], + [ "Riku Doldo III", "INT", [ "Cerebral", "Striker" ], 4, 20, 4, 3, 99, 3000000, 612, 354, 189, 2066, 992, 275, 1 ], + [ "Tank Lepanto", "DEX", [ "Powerhouse", "Striker" ], 3, 15, 5, 1, 70, 1066998, 199, 112, 8, 1674, 1011, 24, 1 ], + [ "Scarlet", "PSY", [ "Free Spirit", "Fighter" ], 4, 20, 5, 3, 99, 3000000, 741, 128, 252, 1920, 630, 420, 1 ], + [ "Sanji, Stage Costume Pirate", "STR", [ "Fighter", "Powerhouse" ], 4, 13, 7, 3, 50, 261406, 184, 106, 50, 830, 475, 301, 1 ], + [ "Sanji, Mr. Prince's Stage Costume", "STR", [ "Fighter", "Powerhouse" ], 5, 20, 4, 4, 99, 2000000, 815, 450, 297, 1602, 1231, 550, 1 ], + [ "Byrnndi World, Wielder of the More-More Fruit", "STR", [ "Shooter", "Driven" ], 4, 20, 4, 3, 70, 1066998, 162, 135, 33, 1332, 742, 157, 1 ], + [ "Byrnndi World, World Destroyer", "STR", [ "Shooter", "Driven" ], 5, 30, 4, 4, 99, 4000000, 1185, 688, 122, 2462, 1408, 319, 1 ], + [ "Akainu [Neo]", "INT", [ "Driven", "Fighter" ], 4, 30, 4, 2, 70, 1066998, 284, 217, 0, 1612, 819, 49, 1 ], + [ "Akainu [Neo], Magma Man", "INT", [ "Driven", "Fighter" ], 5, 50, 4, 4, 99, 5000000, 1506, 717, 44, 3156, 1450, 99, 1 ], + [ "Sicilian, Mokomo Dukedom", "INT", [ "Slasher", "Powerhouse" ], 4, 25, 4, 3, 70, 1066998, 537, 299, 40, 1181, 787, 209, 1 ], + [ "Full Power Sicilian, Mokomo Dukedom", "INT", [ "Slasher", "Powerhouse" ], 5, 40, 4, 5, 99, 4000000, 1122, 690, 158, 2270, 1421, 328, 1 ], + [ "Caesar Clown, Ruler of the Atmosphere", "INT", [ "Cerebral", "Driven" ], 4, 30, 4, 1, 70, 1066998, 61, 181, 65, 890, 780, 182, 1 ], + [ "Master Caesar, Ruler of the Atmosphere", "INT", [ "Cerebral", "Driven" ], 5, 50, 4, 2, 99, 5000000, 848, 735, 162, 1811, 1404, 324, 1 ], + [ "Vinsmoke Judge", "PSY", [ "Powerhouse", "Driven" ], 5, 30, 5, 3, 70, 1066998, 808, 177, 12, 1906, 782, 162, 1 ], + [ "Vinsmoke Judge, Germa 66 Science Combat Force", "PSY", [ "Powerhouse", "Driven" ], 6, 55, 5, 5, 99, 5000000, 1602, 740, 138, 4212, 1510, 201, 1 ], + [ "Vinsmoke Reiju", "INT", [ "Powerhouse", "Cerebral" ], 4, 15, 4, 3, 50, 392109, 202, 76, 41, 920, 434, 252, 1 ], + [ "Vinsmoke Reiju, Germa 66 Science Combat Force", "INT", [ "Powerhouse", "Cerebral" ], 5, 30, 4, 4, 99, 4000000, 822, 336, 201, 1984, 1312, 432, 1 ], + [ "Vinsmoke Ichiji", "STR", [ "Powerhouse", "Fighter" ], 4, 15, 6, 3, 50, 392109, 268, 82, 28, 1346, 647, 110, 1 ], + [ "Vinsmoke Ichiji, Germa 66 Science Combat Force", "STR", [ "Powerhouse", "Fighter" ], 5, 30, 4, 4, 99, 4000000, 1120, 544, 82, 2912, 1421, 241, 1 ], + [ "Vinsmoke Niji", "QCK", [ "Powerhouse", "Fighter" ], 4, 15, 5, 3, 50, 392109, 250, 79, 32, 1332, 630, 118, 1 ], + [ "Vinsmoke Niji, Germa 66 Science Combat Force", "QCK", [ "Powerhouse", "Fighter" ], 5, 30, 4, 4, 99, 4000000, 1112, 500, 98, 2834, 1382, 267, 1 ], + [ "Vinsmoke Yonji", "DEX", [ "Powerhouse", "Fighter" ], 4, 15, 6, 3, 50, 392109, 218, 77, 38, 1128, 492, 198, 1 ], + [ "Vinsmoke Yonji, Germa 66 Science Combat Force", "DEX", [ "Powerhouse", "Fighter" ], 5, 30, 4, 4, 99, 4000000, 982, 403, 152, 2406, 1341, 352, 1 ], + [ "Caribou, Next Generation Supernova", "DEX", [ "Driven", "Striker" ], 3, 13, 4, 2, 50, 392109, 296, 392, 0, 740, 980, 0, 1 ], + [ "Wet Haired Caribou, Next Generation Supernova", "DEX", [ "Driven", "Shooter" ], 4, 20, 6, 3, 99, 3000000, 723, 921, -300, 1598, 1402, -300, 1 ], + [ "Coribou, Next Generation Supernova", "STR", [ "Driven", "Striker" ], 3, 13, 6, 2, 50, 392109, 130, 102, 26, 534, 489, 198, 1 ], + [ "Blood-Splatterer Coribou, Next Generation Supernova", "STR", [ "Driven", "Striker" ], 4, 20, 4, 3, 99, 3000000, 520, 430, 178, 1806, 879, 356, 1 ], + [ "Garp, Hero of the Marines", "STR", [ "Fighter", "Free Spirit" ], 4, 30, 4, 2, 70, 1778330, 1015, 494, 0, 1852, 688, 5, 1 ], + [ "Garp the Fist, Hero of the Marines", "STR", [ "Fighter", "Free Spirit" ], 5, 50, 4, 3, 99, 5000000, 1773, 611, 3, 3750, 1550, 10, 1 ], + [ "Sengoku the Buddha, Marine Fleet Admiral", "INT", [ "Fighter", "Cerebral" ], "6+", 54, 4, 5, 99, 5000000, 1998, 729, 194, 3696, 1458, 398, 1 ], + [ "Akainu, Trembling Calamity", "STR", [ "Powerhouse", "Driven" ], 4, 12, 5, 3, 50, 261406, 210, 105, 10, 1212, 690, 48, 1 ], + [ "Sakazuki, Trembling Calamity", "STR", [ "Powerhouse", "Driven" ], 5, 20, 4, 4, 99, 2000000, 1014, 621, 24, 2662, 1312, 99, 1 ], + [ "Squard, Treacherous \"Son\"", "DEX", [ "Slasher", "Driven" ], 4, 12, 6, 3, 50, 261406, 182, 92, 19, 1010, 512, 141, 1 ], + [ "Maelstrom Spider Squard, Treacherous \"Son\"", "DEX", [ "Slasher", "Driven" ], 5, 20, 4, 4, 99, 2000000, 950, 482, 81, 1992, 1098, 282, 1 ], + [ "Adventure Mode Whitebeard", "INT", [ "Powerhouse", "Striker" ], 4, 30, 4, 1, 50, 130703, 335, 144, 25, 1044, 421, 100, null ], + [ "Adventure Mode Whitebeard, Evolved", "INT", [ "Powerhouse", "Striker" ], 5, 60, 4, 1, 99, 5000000, 920, 320, 69, 3064, 1390, 203, null ], + [ "Scracthmen Apoo, Supernova", "STR", [ "Free Spirit", "Shooter" ], 3, 13, 3, 6, 50, 130703, 141, 69, 27, 1134, 622, 109, 1 ], + [ "\"Roar of the Sea\" Scracthmen Apoo, Supernova", "STR", [ "Free Spirit", "Slasher" ], 4, 20, 4, 4, 99, 1000000, 1067, 534, 95, 2136, 1211, 221, 1 ], + [ "X Drake, Supernova", "PSY", [ "Powerhouse", "Cerebral" ], 3, 13, 3, 6, 50, 130703, 199, 112, 10, 1674, 611, 50, 1 ], + [ "\"Red Flag\" X Drake, Supernova", "PSY", [ "Powerhouse", "Cerebral" ], 4, 20, 5, 4, 99, 1000000, 1472, 567, 30, 2978, 1267, 50, 1 ], + [ "Leo", "INT", [ "Striker", "Powerhouse" ], 4, 20, null, null, 70, 1066998, null, null, null, null, null, null, null ], + [ "Warrior Leo, Courageous Dwarf", "INT", [ "Striker", "Powerhouse" ], 5, 30, 4, 5, 99, 4000000, 1, 1, 1, 2233, 1422, 354, null ], + [ "Raizo Colo", "QCK", [ "Shooter", "Free Spirit" ], 4, 25, null, null, null, null, null, null, null, null, null, null, null ], + [ "Raizo Colo Evolved", "QCK", [ "Shooter", "Free Spirit" ], 5, 40, 4, 5, 99, 4000000, 1, 1, 1, 2322, 1519, 372, null ], + [ "Kinemon Neo Colo", "PSY", [ "Slasher", "Free Spirit" ], 4, 25, null, null, null, null, null, null, null, null, null, null, null ], + [ "Kinemon Neo Colo Evolved", "PSY", [ "Slasher", "Free Spirit" ], 5, 40, 4, 5, 99, 4000000, 1, 1, 1, 2071, 1430, 324, null ], + [ "Urouge, Supernova", "DEX", [ "Striker", "Free Spirit" ], 3, 13, null, null, null, null, null, null, null, null, null, null, null ], + [ "\"Mad Monk\" Urouge, Supernova", "DEX", [ "Striker", "Free Spirit" ], 4, 20, 4, 4, 99, null, 1, 1, 1, 2036, 1311, 204, null ], + [ "Basil Hawkins, Supernova", "QCK", [ "Slasher", "Cerebral" ], 3, 13, null, null, null, null, null, null, null, null, null, null, null ], + [ "\"The Magician\" Basil Hawkins, Supernova ", "QCK", [ "Striker", "Cerebral" ], 4, 20, 7, 4, 99, null, 1, 1, 1, 2078, 1079, 287, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], + [ "Silvers Rayleigh, First Mate of the Roger Pirates", "STR", [ "Slasher", "Cerebral" ], 4, 30, 6, 1, 70, 1066998, 224, 151, 40, 1258, 714, 194, null ], + [ "Dark King Rayleigh, First Mate of the Roger Pirates", "STR", [ "Slasher", "Cerebral" ], 5, 50, 5, 3, 99, 5000000, 1190, 650, 143, 2510, 1315, 353, null ], + ]; + +// [ "Name", "Type", [ "Class1", "Class2" ], null, null, null, null, null, null, null, null, null, null, null, null, null ], +// or [ "Name", "Type", "Class1", null, null, null, null, null, null, null, null, null, null, null, null, null ], +// [ "Name", "Type", [ "Class1", "Class2" ], Stars, Cost, Combo, Sockets, maxLVL, EXPToMax, lvl1HP, lvl1ATK, lvl1RCV, MAXHP, MAXATK, MAXRCV, Growth Rate ], diff --git a/common/data/version.js b/common/data/version.js index 163593770..3eb7ab903 100644 --- a/common/data/version.js +++ b/common/data/version.js @@ -1 +1 @@ -window.dbVersion = 35; +window.dbVersion = 36; diff --git a/common/data/zombies.js b/common/data/zombies.js index 2414e3467..62150061f 100644 --- a/common/data/zombies.js +++ b/common/data/zombies.js @@ -179,9 +179,17 @@ window.zombies = { type: 'healer', multiplier: 2 }, + 828: { //Kid Law + type: 'zombie', + threshold: 0.5 + }, + 829: { //Kid Law Evolution + type: 'zombie', + threshold: 0.3 + }, 841: { // Monet type: 'healer', - multiplier: 5 + multiplier: 3 }, 842: { // Monet type: 'healer', @@ -200,7 +208,291 @@ window.zombies = { threshold: 0.5 }, 912: { // SH Sanji + type: 'healer', + multiplier: 2 + }, + 949: { //Fortnight Thatch + type: 'healer', + multiplier: 2 + }, + 965: {//Saint Charloss + type: 'healer', + amount: 500 + }, + 1008: {//Sakura Monet + type: 'healer', + multiplier: 3 + }, + 1014: {//Tony Tony Chopper, Animal King + type: 'healer', + multiplier: 2 + }, + 1052: {//Kid Robin + type: 'healer', + amount: 1000 + }, + 1062: {//Gloriosa + type: 'healer', + multiplier: 2 + }, + 1078: {//Mansherry + type: 'healer', + multiplier: 3 + }, + 1079: {//Mansherry + type: 'healer', + multiplier: 4 + }, + 1133: { + type: 'healer', + multiplier: 2 + }, + 1141: {//Story Moira + type: 'healer', + multiplier: 3 + }, + 1157: {// Story Hannyabal + type: 'zombie', + threshold: 0.5 + }, + 1195: {//Colo Ganfor + type: 'healer', + multiplier: 2 + }, + 1196: {//Colo Ganfor + type: 'healer', + multiplier: 5 + }, + 1241: {//Fortnight Koala + type: 'healer', + multiplier: 1 + }, + 1242: {//Fortnight Koala + type: 'healer', + multiplier: 2 + }, + 1250: {//Colo Marco + type: 'healer', + multiplier: 2.5 + }, + 1251: {//Colo Marco + type: 'healer', + multiplier: 2.5 + }, + 1269: {//Laffitte + type: 'healer', + multiplier: 3 + }, + 1270: {//Laffitte + type: 'healer', + multiplier: 3 + }, + 1305: {//Halloween Sugar + type: 'healer', + amount: 500 + }, + 1305: {//Halloween Sugar + type: 'healer', + amount: 1000 + }, + 1309: {//Colo Kinemon + type: 'healer', + multiplier: 1 + }, + 1310: {//Colo Kinemon + type: 'healer', + multiplier: 2 + }, + 1330: {//Gancho + type: 'healer', + multiplier: 2 + }, + 1331: {//Mansherry + type: 'healer', + multiplier: 2 + }, + 1332: {//Mansherry + type: 'healer', + multiplier: 3 + }, + 1358: {//Rayleigh + type: 'healer', + multiplier: 1.5 + }, + 1359: {//Rayleigh + type: 'healer', + multiplier: 1.5 + }, + 1409: { // New World Brook + type: 'zombie', + threshold: 0.5 + }, + 1410: { // New World Brook + type: 'zombie', + threshold: 0.5 + }, + 1423: { // Colo T-Bone + type: 'healer', + amount: 918 + }, + 1455: { // Colo Don Chinjao + type: 'healer', + amount: 120 + }, + 1456: { // Colo Don Chinjao + type: 'healer', + amount: 120 + }, + 1463: { // White Day Luffy + type: 'healer', + multiplier: 1.5 + }, + 1465: { // White Day Chopper + type: 'zombie', + threshold: 0.5 + }, + 1466: { // White Day Chopper + type: 'zombie', + threshold: 0.5 + }, + 1472: { // Shirahoshi + type: 'healer', + multiplier: 5 + }, + 1473: { // Shirahoshi + type: 'healer', + multiplier: 5 + }, + 1508: { // White Day Sanji + type: 'healer', + multiplier: 2 + }, + 1516: { // White Day Brook + type: 'healer', + multiplier: 2 + }, + 1523: { // Spring Chopper + type: 'healer', + amount: 1000 + }, + 1524: { // Spring Chopper + type: 'healer', + amount: 1224 + }, + 1549: { // 5+ Robin + type: 'healer', + multiplier: 3 + }, + 1551: { // 5+ Brook + type: 'healer', + amount: 430 + }, + 1555: { // Coliseum Ryuma + type: 'healer', + multiplier: 2 + }, + 1577: { // Kin'emon + type: 'healer', + multiplier: 3 + }, + 1578: { // Momonosuke + type: 'zombie', + threshold: 0.3 + }, + 1579: { // Momonosuke + type: 'zombie', + threshold: 0.3 + }, + 1605: { // Training Forest Ace + type: 'healer', + amount: 500 + }, + 1616: { // Crocodile + type: 'healer', + multiplier: 1.5 + }, + 1661: { // Corazon + type: 'healer', + amount: 300 + }, + 1662: { // Corazon + type: 'healer', + amount: 300 + }, + 1702: { // Ivankov + type: 'healer', + multiplier: 2 + }, + 1704: { // Hannyabal + type: 'healer', + multiplier: 2 + }, + 1708: { // Nami + type: 'healer', + multiplier: 3 + }, + 1709: { // Nami type: 'healer', multiplier: 4 - } + }, + 1714: { // Monet + type: 'healer', + multiplier: 2 + }, + 1728: { // Tashigi + type: 'healer', + multiplier: 2 + }, + 1729: { // Tashigi + type: 'healer', + multiplier: 3 + }, + 1734: { // Sugar + type: 'healer', + multiplier: 3 + }, + 1735: { // Sugar + type: 'healer', + multiplier: 3 + }, + 1746: { // Boa + type: 'healer', + amount: 1000 + }, + 1747: { // Boa + type: 'healer', + amount: 1000 + }, + 1756: { // Nami + type: 'healer', + multiplier: 2 + }, + 1757: { // Nami + type: 'healer', + multiplier: 5 + }, + 1778: { // Kizaru + type: 'healer', + multiplier: 1.5 + }, + 1785: { // Spartan + type: 'healer', + multiplier: 3 + }, + 1821: { // Sanji + type: 'healer', + multiplier: 1 + }, + 1822: { // Sanji + type: 'healer', + multiplier: 2 + }, + 1857: { // X Drake + type: 'healer', + amount: 200 + }, + 2001: { // Rayleigh CHANGE THIS WHEN YOU CHANGE RAYLEIGH + type: 'healer', + multiplier: 2 + }, }; diff --git a/common/js/directives.js b/common/js/directives.js index 3bd224d23..7ec43b930 100644 --- a/common/js/directives.js +++ b/common/js/directives.js @@ -4,6 +4,7 @@ var notes = { captainProportional: "The exact multiplier used to compute the damage is proportional to the " + "crew's remaining HP and is higher the #1 the HP is. The multiplier is calculated as #2. " + "At full health the boost is equal to #3x, with 1 HP left to #4x.", + captainFixed:"The multiplier is #1 unless #2, in which case it is #3.", fixed: "Fixed damage means it entirely bypasses the enemy's defense.", gOrbs: "Characters with [G] orbs will deal 1.5x their normal damage. [G] orbs are affected by orb boosters.", noFixedPerc: "Specials that deal fixed damage or cut a percentage of the enemy's HP are not " + @@ -11,13 +12,21 @@ var notes = { orb: "Orb amplification only affects matching and opposite orbs and works both ways: " + "matching orbs will deal #1 more damage and opposite orbs will deal #1 less damage.", poison: "Poison deals 0.5x character's ATK in fixed damage at the end of each turn.", - random: "Estimated random damage range: between #1 HP and #2 HP.", + random: "Estimated random damage range: between #1 HP and #2 HP #3.", + randomHeal: "Estimated random recovery range: between #1 HP and #2 HP.", randomHits: "The target of each of the #1 hits is chosen randomly.", specialProportional: "The exact multiplier used to compute the damage is proportional to the " + "crew's remaining HP and is higher the #1 the HP is. The multiplier is calculated as: #2.", stages: "The special can be used as soon as the first stage is reached.", + silence: "This is called 'Special Bind' in-game and refers to effects that prevent you from activating Special Abilities.", + rewind: "Some enemies can increase your cooldown by 1/2 turns, this Sailor Ability decreases that by #1 turn.", + ignoreBarrier: "Damage that ignores damage negating abilities and barriers is similar to 6* Law's special, but only for this character.", zombie: "The protection only works when attacked by one single enemy and will leave the team with at least 1 HP; " + - "the effect will not work when attacked by multiples enemies at once." + "the effect will not work when attacked by multiples enemies at once.", + colorAffinity: "'Color Affinity' boosts color type advantages. For example, a STR unit normally deals 2x to a DEX unit and .5x to QCK. With this Color Affinity boost, it will deal (2*#1)x to DEX and (0.5/#1)x to QCK.", + instantKill: "The chance for this character to instantly kill any enemy is #1. The kills can not be reset by exiting the game, but can change by passing the turn or killing an enemy on that stage.", + additionalDamage: "Every attacking character gains additional damage if they land a hit no less than Good.", + beneficial: "\"Beneficial\" orbs grant the same ATK boost as matching orbs and activate any Captain Abilities that are enabled by matching orbs.", }; /*********** @@ -76,6 +85,7 @@ filters.decorate = function() { .replace(/\[EMPTY\]/g,' EMPTY') .replace(/\[BLOCK\]/g,' BLOCK') .replace(/\[BOMB\]/g,' BOMB') + .replace(/\[RAINBOW\]/g,' RAINBOW') .replace(/\[G\]/g,'G'); }; }; diff --git a/common/js/dismissal.js b/common/js/dismissal.js index 331569952..1a7cb41fe 100644 --- a/common/js/dismissal.js +++ b/common/js/dismissal.js @@ -7,21 +7,18 @@ app.controller('DismissalCtrl', function(ngDialog, $templateCache) { var dismissalPopupShown = true; - try { dismissalPopupShown = JSON.parse(localStorage.getItem('dismissalShown')) || false; } - catch (e) { } +// try { dismissalPopupShown = JSON.parse(localStorage.getItem('dismissalShown')) || false; } +// catch (e) { } if (dismissalPopupShown) return; $templateCache.put('dismissal', '
    ' + - '

    Discontinuation Notice

    ' + + '

    Important Notice

    ' + '
    ' + - '
    The site will be no longer kept updated due to dwindling interest and lack of time. ' + - 'All past, present and future bugs will now become features.
    ' + - '
    Existing data will not be removed, you will still be able to browse it.
    ' + - '
    If someone is interested in picking up ' + - 'the torch, you are welcome to do so.
    ' + - '
    You won\'t be shown this popup again once you click on the button.
    ' + + '
    I\'m picking up this project for now.
    For the beggining you can at least expect updates for the DB part of the project. It will probably be a while before I understand the rest of the code.
    ' + + '
    That\'s it for now.
    ' + + '

    You won\'t be shown this popup again once you click on the button.
    ' + '
    ' + '
    ' + '
    ' + diff --git a/common/js/dragger.js b/common/js/dragger.js index 7091b9f42..8b6422436 100644 --- a/common/js/dragger.js +++ b/common/js/dragger.js @@ -43,15 +43,17 @@ var onMove = function(e) { var onEndMove = function(stopProp, removable) { return function(e) { - e.target.style.zIndex = 3; - e.target.style.webkitTransform = e.target.style.transform = ''; - if (removable) $('#removeZone').hide(); - if (stopProp && stopProp(dropped)) stopPropagation = true; - else stopPropagation = false; - coordinates = [ 0, 0 ]; - startObject.removeClass('ghoster'); - startObject = null; - $(e.target.parentNode).removeClass('dragging'); + setTimeout(function() { + e.target.style.zIndex = 3; + e.target.style.webkitTransform = e.target.style.transform = ''; + if (removable) $('#removeZone').hide(); + if (stopProp && stopProp(dropped)) stopPropagation = true; + else stopPropagation = false; + coordinates = [ 0, 0 ]; + startObject.removeClass('ghoster'); + startObject = null; + $(e.target.parentNode).removeClass('dragging'); + }, 100); }; }; diff --git a/common/js/error.js b/common/js/error.js index dd33cd141..6c4cc16d2 100644 --- a/common/js/error.js +++ b/common/js/error.js @@ -31,7 +31,7 @@ app.directive('errorReport', function($rootScope, $timeout) { replace: true, templateUrl: '../common/views/error-report.html', link: function(scope, element, attrs) { - scope.baseURL = 'https://docs.google.com/forms/d/1w40Pp8uAQm-gekiFfc8VkydmM_PFtM8qZcZokf7IzeE/viewform?entry.1585706216='; + scope.baseURL = 'https://discord.gg/MRhRrbF'; scope.clearError = function() { $timeout(function() { $rootScope.caughtException = null; diff --git a/common/js/nonSuspicious.js b/common/js/nonSuspicious.js new file mode 100644 index 000000000..c738d048e --- /dev/null +++ b/common/js/nonSuspicious.js @@ -0,0 +1,61 @@ +var pressed = [], konami = "38,38,40,40,37,39,37,39,66,65"; + +function hideChopper() { + $("#Chopper").remove(); + $("#hide").remove(); + $("#overlay").remove(); +} + +$(document).keydown(function(e) { + + pressed.push( e.keyCode ); + + if (pressed.toString().indexOf(konami)>=0) { + + $(document).unbind('keydown',arguments.callee); + + // Add a Spinning Chopperman to the index Page + var kon = document.createElement("img"); + //Chopperman + //kon.src = "http://i.imgur.com/gKxW9cm.png"; + //Fat Usoppp + kon.src = "http://i.imgur.com/zy5IoXu.png"; + kon.alt = "Chopperman"; + kon.id = "Chopper"; + + var overlay = document.createElement("div"); + overlay.className = "overlay"; + + var hide = document.createElement("div"); + hide.className = "hide"; + hide.id = "hide"; + + document.getElementById("empty").appendChild(overlay); + document.getElementById("empty").appendChild(hide); + document.getElementById("hide").appendChild(kon); + //Add an onCLick Event to disable him again + var chopper = document.getElementById("Chopper"); + chopper.addEventListener("click", hideChopper, false); + + } + +}); + +window.onload = function() { + + //Add new Units with Pics here so they show up in the Updates + //7 Units are about the Max you can add, otherwise you would need to implement another tr for them + var newUnits = [ 1619, 1610, 1621, 1623, 1624, 1606, 1605 ]; + + for (var i = 0, len = newUnits.length; i < len; i++) { + var unit = document.createElement("a"); + unit.href = "/characters/#/view/"+newUnits[i]; + unit.className = "slot small"; + unit.target = "_blank"; + unit.title = window.units[newUnits[i]-1][0]; + unit.style = "background-image: url("+Utils.getThumbnailUrl(newUnits[i])+");"; + //unit.style = "background-image: url("+Utils.getGlobalThumbnailUrl(newUnits[i])+"), url("+Utils.getThumbnailUrl(newUnits[i])+");"; + + document.getElementById("newUnits").appendChild(unit); + } +} \ No newline at end of file diff --git a/common/js/utils.js b/common/js/utils.js index a06b0b476..c56d0505c 100644 --- a/common/js/utils.js +++ b/common/js/utils.js @@ -1,193 +1,373 @@ -(function() { - -var FODDER_REGEX = new RegExp('(' + [ - 'Group', 'Ensign Navy HQ', 'Armed \\w+ Unit', '[BM]illions Baroque', 'Eneru\'s Elect', - 'Skypiea (Guard|Enforcer)', 'Shandian', - '(Seaman|Major|Corporal) Navy', 'Hoodlum.+Bounty Hunter', 'Black Cat Pirates', - 'Arlong crewmember', 'Gunner|Cannoneer|Assassin Master', 'Giant.*Pirates', - '(Soldier|General) Zombie.*Shadow', 'Wild Zombie' -].join(')|(') + ')','i'); - -var utils = { }; - -var fullNames = null, reverseEvoMap = null; - -/* * * * * Unit control * * * * */ - -var parseUnit = function(element,n) { - if (element.length === 0) return [ ]; - if (element[15] && element[15].constructor != Array) element[15] = [ element[15], element[15], element[15] ]; - var result = { - name : element[0] , type : element[1] , - class : element[2] , stars : element[3] , - cost : element[4] , combo : element[5] , - slots : element[6] , maxLevel : element[7] , - maxEXP : element[8] , minHP : element[9] , - minATK : element[10] , minRCV : element[11] , - maxHP : element[12] , maxATK : element[13] , - maxRCV : element[14] , growth : { - hp : element[15] ? element[15][0] : 0, - atk : element[15] ? element[15][1] : 0, - rcv : element[15] ? element[15][2] : 0 - }, - number: n - }; - if (element.indexOf(null) != -1) result.incomplete = true; - if (result.combo === null || result.combo === 0) result.preview = true; - return result; -}; - -utils.parseUnits = function(skipIncomplete) { - if (skipIncomplete) { - window.units = window.units.map(function(x,n) { - if (x.indexOf(null) == -1) return x; - var viable = x[9] && x[10] && x[11] && x[12] && x[13] && x[14]; - return viable ? x : [ ]; - - }); - } - window.units = window.units.map(parseUnit); -}; - -utils.getFullUnitName = function(id) { - if (fullNames === null) { - fullNames = units.map(function(x,n) { - if (!x.name) return null; - return x.name + (window.aliases[n + 1] ? ' ' + window.aliases[n + 1].join(', ') : ''); - }); - } - return fullNames[id - 1]; -}; - -/* * * * * Thumbnail control * * * * */ - -utils.getThumbnailUrl = function(n) { - if (n === null || n === undefined || (window.units && window.units[n-1].incomplete)) - return 'http://onepiece-treasurecruise.com/wp-content/themes/onepiece-treasurecruise/images/noimage.png'; - var id = ('0000' + n).slice(-4).replace(/(057[54])/,'0$1'); // missing aokiji image - return 'http://onepiece-treasurecruise.com/wp-content/uploads/f' + id + '.png'; -}; - -utils.getBigThumbnailUrl = function(n) { - if (window.units[n-1].incomplete) - return 'http://onepiece-treasurecruise.com/wp-content/themes/onepiece-treasurecruise/images/noimage.png'; - var id = ('0000' + n).slice(-4).replace(/(057[54])/,'0$1'); // missing aokiji image - return 'http://onepiece-treasurecruise.com/wp-content/uploads/c' + id + '.png'; -}; - -utils.getThumbnailTitle = function(arg) { - if (arg === null || arg === undefined) return null; - if (arg.constructor == Object) { - return [ arg.name, 'HP: ' + arg.hp, 'ATK: ' + arg.atk, 'RCV: ' + arg.rcv, 'CMB: ' + arg.cmb ].join('\n'); - } - var unit = (arg.constructor == Object ? arg : units[arg]); - return [ unit.name, 'HP: ' + unit.maxHP, 'ATK: ' + unit.maxATK, 'RCV: ' + unit.maxRCV, 'CMB: ' + unit.combo, 'Cost: ' + unit.cost ].join('\n'); -}; - -utils.isClickOnOrb = function(e,target) { - var x = e.offsetX, y = e.offsetY; - var distance = Math.sqrt(Math.pow(x-20,2)+Math.pow(y-21,2)); - return distance < 13; -}; - -/* * * * * Misc functions * * * * */ - -/* given an array of arrays, generates the cartesian product of - * all the arrays contained within the root array - * eg f([[1],[2,3],[4,5,6]]) -> [[1,2,4],[1,2,5],[1,2,6],[1,3,4],[1,3,5],[1,3,6]] */ -utils.arrayProduct = function(data) { - var result = data.reduce(function(prev,next) { - if (next.length === 0) return prev; - return next.map(function(n) { - return prev.map(function(p) { - return p.concat([ n ]); - }); - }).reduce(function(prev,next) { return prev.concat(next); },[ ]); - },[ [ ] ]); - return result.filter(function(r) { return r.length > 0; }); -}; - -utils.getOppositeType = function(type) { - if (!type) return null; - type = type.toUpperCase(); - if (type == 'STR') return 'QCK'; - if (type == 'QCK') return 'DEX'; - if (type == 'DEX') return 'STR'; - if (type == 'PSY') return 'INT'; - return 'PSY'; -}; - -/* * * * * Searching/filtering * * * * */ - -utils.getRegex = function(query) { - try { return new RegExp(query,'i'); } - catch (e) { return new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'), 'i'); } -}; - -utils.generateSearchParameters = function(query) { - if (!query || query.trim().length < 2) return null; - query = query.toLowerCase().trim(); - var result = { matchers: { }, ranges: { }, query: [ ] }; - var ranges = { }, params = [ 'hp', 'atk', 'stars', 'cost', 'growth', 'rcv', 'id', 'slots', 'combo', 'exp', 'minCD', 'maxCD' ]; - var regex = new RegExp('^((type|class):(\\w+)|(' + params.join('|') + ')(>|<|>=|<=|=)([\\d.]+))$', 'i'); - var tokens = query.replace(/\s+/g,' ').split(' ').filter(function(x) { return x.length > 0; }); - tokens.forEach(function(x) { - var temp = x.match(regex); - if (!temp) // if it couldn't be parsed, treat it as string - result.query.push(x); - else if (temp[4] !== undefined) { // numeric operator - var left = temp[4], op = temp[5], right = parseFloat(temp[6],10); - if (left == 'exp') left = 'maxEXP'; - if (!result.ranges.hasOwnProperty(left)) result.ranges[left] = [ 0, Infinity ]; - if (op == '=') { - result.ranges[left][0] = right; - result.ranges[left][1] = right; - } - else if (op == '<') result.ranges[left][1] = Math.min(result.ranges[left][1],right-1); - else if (op == '<=') result.ranges[left][1] = Math.min(result.ranges[left][1],right); - else if (op == '>') result.ranges[left][0] = Math.max(result.ranges[left][0],right+1); - else if (op == '>=') result.ranges[left][0] = Math.max(result.ranges[left][0],right); - } else // matcher - result.matchers[temp[2]] = new RegExp(temp[3],'i'); - }); - if (result.query.length > 0) result.query = utils.getRegex(result.query.join(' ')); - else result.query = null; - return result; -}; - -utils.isFodder = function(unit) { - return (unit.stars < 2 && !utils.isEvolverBooster(unit)) || FODDER_REGEX.test(unit.name); -}; - -utils.isEvolverBooster = function(unit) { - return /Evolver|Booster/i.test(unit.class); -}; - -utils.searchBaseForms = function(id) { - if (!reverseEvoMap) generateReverseEvoMap(); - if (!reverseEvoMap[id]) return null; - return reverseEvoMap[id]; -}; - -var updateEvoMap = function(from, to, via) { - if (!reverseEvoMap[to]) reverseEvoMap[to] = { }; - if (!reverseEvoMap[to][from]) reverseEvoMap[to][from] = [ ]; - reverseEvoMap[to][from].push(via); -}; - -var generateReverseEvoMap = function() { - reverseEvoMap = { }; - for (var evo in evolutions) { - var from = parseInt(evo, 10); - if (evolutions[evo].evolution.constructor != Array) - updateEvoMap(from, evolutions[evo].evolution, evolutions[evo].evolvers); - else for (var i=0;i [[1,2,4],[1,2,5],[1,2,6],[1,3,4],[1,3,5],[1,3,6]] */ + utils.arrayProduct = function (data) { + var result = data.reduce(function (prev, next) { + if (next.length === 0) + return prev; + return next.map(function (n) { + return prev.map(function (p) { + return p.concat([n]); + }); + }).reduce(function (prev, next) { + return prev.concat(next); + }, []); + }, [[]]); + return result.filter(function (r) { + return r.length > 0; + }); + }; + + utils.getOppositeType = function (type) { + if (!type) + return null; + type = type.toUpperCase(); + if (type == 'STR') + return 'QCK'; + if (type == 'QCK') + return 'DEX'; + if (type == 'DEX') + return 'STR'; + if (type == 'PSY') + return 'INT'; + return 'PSY'; + }; + + /* * * * * Searching/filtering * * * * */ + + utils.getRegex = function (query) { + try { + return new RegExp(query, 'i'); + } catch (e) { + return new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'), 'i'); + } + }; + + utils.generateSearchParameters = function (query) { + if (!query || query.trim().length < 2) + return null; + query = query.toLowerCase().trim(); + var result = {matchers: {}, ranges: {}, query: []}; + var ranges = {}, params = ['hp', 'atk', 'stars', 'cost', 'growth', 'rcv', 'id', 'slots', 'combo', 'exp', 'minCD', 'maxCD']; + var regex = new RegExp('^((type|class):(\\w+\\s{0,1}\\w+)|(' + params.join('|') + ')(>|<|>=|<=|=)([-?\\d.]+))$', 'i'); + var tokens = query.replace(/\s+/g, ' ').split(' ').filter(function (x) { + return x.length > 0; + }); + tokens.forEach(function (x) { + x = x.replace("_", ' '); + var temp = x.match(regex); + if (!temp) // if it couldn't be parsed, treat it as string + result.query.push(x); + else if (temp[4] !== undefined) { // numeric operator + var parameter = temp[4], + op = temp[5], + value = parseFloat(temp[6], 10); + if (parameter === 'exp') + parameter = 'maxEXP'; + if (!result.ranges.hasOwnProperty(parameter)) { + if (op === '>' || op === '>=') { + result.ranges[parameter] = [0, Number.POSITIVE_INFINITY]; + } else if (op === '<' || op === '<=') { + result.ranges[parameter] = [Number.NEGATIVE_INFINITY, 0]; + }else{ + result.ranges[parameter] = [Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY]; + } + } + if (op === '=') { + result.ranges[parameter][0] = value; + result.ranges[parameter][1] = value; + } else if (op === '<') { + result.ranges[parameter][1] = value - 1; + } else if (op === '<=') { + result.ranges[parameter][1] = value; + } else if (op === '>') { + result.ranges[parameter][0] = value + 1; + } else if (op === '>=') { + result.ranges[parameter][0] = value; + } + } else // matcher + result.matchers[temp[2]] = new RegExp(temp[3], 'i'); + }); + if (result.query.length > 0) + result.query = utils.getRegex(result.query.join(' ')); + else + result.query = null; + return result; + }; + + utils.isFodder = function (unit) { + return (unit.stars < 2 && !utils.isEvolverBooster(unit)) || FODDER_REGEX.test(unit.name); + }; + + utils.isEvolverBooster = function (unit) { + return /Evolver|Booster/i.test(unit.class); + }; + + utils.searchBaseForms = function (id) { + if (!reverseEvoMap) + generateReverseEvoMap(); + if (!reverseEvoMap[id]) + return null; + return reverseEvoMap[id]; + }; + + var updateEvoMap = function (from, to, via) { + if (!reverseEvoMap[to]) + reverseEvoMap[to] = {}; + if (!reverseEvoMap[to][from]) + reverseEvoMap[to][from] = []; + reverseEvoMap[to][from].push(via); + }; + + var generateReverseEvoMap = function () { + reverseEvoMap = {}; + for (var evo in evolutions) { + var from = parseInt(evo, 10); + if (evolutions[evo].evolution.constructor != Array) + updateEvoMap(from, evolutions[evo].evolution, evolutions[evo].evolvers); + else + for (var i = 0; i < evolutions[evo].evolution.length; ++i) + updateEvoMap(from, evolutions[evo].evolution[i], evolutions[evo].evolvers[i]); + } + }; + + /* * * * * Body * * * * */ + + window.Utils = utils; + +})(); diff --git a/common/libs/js/moment-timezone.js b/common/libs/js/moment-timezone.js new file mode 100644 index 000000000..1e17e2334 --- /dev/null +++ b/common/libs/js/moment-timezone.js @@ -0,0 +1,1173 @@ +//! moment-timezone.js +//! version : 0.5.0 +//! author : Tim Wood +//! license : MIT +//! github.com/moment/moment-timezone + +(function (root, factory) { + "use strict"; + + /*global define*/ + if (typeof define === 'function' && define.amd) { + define(['moment'], factory); // AMD + } else if (typeof module === 'object' && module.exports) { + module.exports = factory(require('moment')); // Node + } else { + factory(root.moment); // Browser + } +}(this, function (moment) { + "use strict"; + + // Do not load moment-timezone a second time. + if (moment.tz !== undefined) { + logError('Moment Timezone ' + moment.tz.version + ' was already loaded ' + (moment.tz.dataVersion ? 'with data from ' : 'without any data') + moment.tz.dataVersion); + return moment; + } + + var VERSION = "0.5.0", + zones = {}, + links = {}, + names = {}, + guesses = {}, + cachedGuess, + + momentVersion = moment.version.split('.'), + major = +momentVersion[0], + minor = +momentVersion[1]; + + // Moment.js version check + if (major < 2 || (major === 2 && minor < 6)) { + logError('Moment Timezone requires Moment.js >= 2.6.0. You are using Moment.js ' + moment.version + '. See momentjs.com'); + } + + /************************************ + Unpacking + ************************************/ + + function charCodeToInt(charCode) { + if (charCode > 96) { + return charCode - 87; + } else if (charCode > 64) { + return charCode - 29; + } + return charCode - 48; + } + + function unpackBase60(string) { + var i = 0, + parts = string.split('.'), + whole = parts[0], + fractional = parts[1] || '', + multiplier = 1, + num, + out = 0, + sign = 1; + + // handle negative numbers + if (string.charCodeAt(0) === 45) { + i = 1; + sign = -1; + } + + // handle digits before the decimal + for (i; i < whole.length; i++) { + num = charCodeToInt(whole.charCodeAt(i)); + out = 60 * out + num; + } + + // handle digits after the decimal + for (i = 0; i < fractional.length; i++) { + multiplier = multiplier / 60; + num = charCodeToInt(fractional.charCodeAt(i)); + out += num * multiplier; + } + + return out * sign; + } + + function arrayToInt (array) { + for (var i = 0; i < array.length; i++) { + array[i] = unpackBase60(array[i]); + } + } + + function intToUntil (array, length) { + for (var i = 0; i < length; i++) { + array[i] = Math.round((array[i - 1] || 0) + (array[i] * 60000)); // minutes to milliseconds + } + + array[length - 1] = Infinity; + } + + function mapIndices (source, indices) { + var out = [], i; + + for (i = 0; i < indices.length; i++) { + out[i] = source[indices[i]]; + } + + return out; + } + + function unpack (string) { + var data = string.split('|'), + offsets = data[2].split(' '), + indices = data[3].split(''), + untils = data[4].split(' '); + + arrayToInt(offsets); + arrayToInt(indices); + arrayToInt(untils); + + intToUntil(untils, indices.length); + + return { + name : data[0], + abbrs : mapIndices(data[1].split(' '), indices), + offsets : mapIndices(offsets, indices), + untils : untils, + population : data[5] | 0 + }; + } + + /************************************ + Zone object + ************************************/ + + function Zone (packedString) { + if (packedString) { + this._set(unpack(packedString)); + } + } + + Zone.prototype = { + _set : function (unpacked) { + this.name = unpacked.name; + this.abbrs = unpacked.abbrs; + this.untils = unpacked.untils; + this.offsets = unpacked.offsets; + this.population = unpacked.population; + }, + + _index : function (timestamp) { + var target = +timestamp, + untils = this.untils, + i; + + for (i = 0; i < untils.length; i++) { + if (target < untils[i]) { + return i; + } + } + }, + + parse : function (timestamp) { + var target = +timestamp, + offsets = this.offsets, + untils = this.untils, + max = untils.length - 1, + offset, offsetNext, offsetPrev, i; + + for (i = 0; i < max; i++) { + offset = offsets[i]; + offsetNext = offsets[i + 1]; + offsetPrev = offsets[i ? i - 1 : i]; + + if (offset < offsetNext && tz.moveAmbiguousForward) { + offset = offsetNext; + } else if (offset > offsetPrev && tz.moveInvalidForward) { + offset = offsetPrev; + } + + if (target < untils[i] - (offset * 60000)) { + return offsets[i]; + } + } + + return offsets[max]; + }, + + abbr : function (mom) { + return this.abbrs[this._index(mom)]; + }, + + offset : function (mom) { + return this.offsets[this._index(mom)]; + } + }; + + /************************************ + Current Timezone + ************************************/ + + function OffsetAt(at) { + var timeString = at.toTimeString(); + var abbr = timeString.match(/\(.+\)/); + if (abbr && abbr[0]) { + // 17:56:31 GMT-0600 (CST) + // 17:56:31 GMT-0600 (Central Standard Time) + abbr = abbr[0].match(/[A-Z]/g).join(''); + } else { + // 17:56:31 CST + abbr = timeString.match(/[A-Z]{3,5}/g)[0]; + } + + if (abbr === 'GMT') { + abbr = undefined; + } + + this.at = +at; + this.abbr = abbr; + this.offset = at.getTimezoneOffset(); + } + + function ZoneScore(zone) { + this.zone = zone; + this.offsetScore = 0; + this.abbrScore = 0; + } + + ZoneScore.prototype.scoreOffsetAt = function (offsetAt) { + this.offsetScore += Math.abs(this.zone.offset(offsetAt.at) - offsetAt.offset); + if (this.zone.abbr(offsetAt.at).match(/[A-Z]/g).join('') !== offsetAt.abbr) { + this.abbrScore++; + } + }; + + function findChange(low, high) { + var mid, diff; + + while ((diff = ((high.at - low.at) / 12e4 | 0) * 6e4)) { + mid = new OffsetAt(new Date(low.at + diff)); + if (mid.offset === low.offset) { + low = mid; + } else { + high = mid; + } + } + + return low; + } + + function userOffsets() { + var startYear = new Date().getFullYear() - 2, + last = new OffsetAt(new Date(startYear, 0, 1)), + offsets = [last], + change, next, i; + + for (i = 1; i < 48; i++) { + next = new OffsetAt(new Date(startYear, i, 1)); + if (next.offset !== last.offset) { + change = findChange(last, next); + offsets.push(change); + offsets.push(new OffsetAt(new Date(change.at + 6e4))); + } + last = next; + } + + for (i = 0; i < 4; i++) { + offsets.push(new OffsetAt(new Date(startYear + i, 0, 1))); + offsets.push(new OffsetAt(new Date(startYear + i, 6, 1))); + } + + return offsets; + } + + function sortZoneScores (a, b) { + if (a.offsetScore !== b.offsetScore) { + return a.offsetScore - b.offsetScore; + } + if (a.abbrScore !== b.abbrScore) { + return a.abbrScore - b.abbrScore; + } + return b.zone.population - a.zone.population; + } + + function addToGuesses (name, offsets) { + var i, offset; + arrayToInt(offsets); + for (i = 0; i < offsets.length; i++) { + offset = offsets[i]; + guesses[offset] = guesses[offset] || {}; + guesses[offset][name] = true; + } + } + + function guessesForUserOffsets (offsets) { + var offsetsLength = offsets.length, + filteredGuesses = {}, + out = [], + i, j, guessesOffset; + + for (i = 0; i < offsetsLength; i++) { + guessesOffset = guesses[offsets[i].offset] || {}; + for (j in guessesOffset) { + if (guessesOffset.hasOwnProperty(j)) { + filteredGuesses[j] = true; + } + } + } + + for (i in filteredGuesses) { + if (filteredGuesses.hasOwnProperty(i)) { + out.push(names[i]); + } + } + + return out; + } + + function rebuildGuess () { + var offsets = userOffsets(), + offsetsLength = offsets.length, + guesses = guessesForUserOffsets(offsets), + zoneScores = [], + zoneScore, i, j; + + for (i = 0; i < guesses.length; i++) { + zoneScore = new ZoneScore(getZone(guesses[i]), offsetsLength); + for (j = 0; j < offsetsLength; j++) { + zoneScore.scoreOffsetAt(offsets[j]); + } + zoneScores.push(zoneScore); + } + + zoneScores.sort(sortZoneScores); + + return zoneScores.length > 0 ? zoneScores[0].zone.name : undefined; + } + + function guess (ignoreCache) { + if (!cachedGuess || ignoreCache) { + cachedGuess = rebuildGuess(); + } + return cachedGuess; + } + + /************************************ + Global Methods + ************************************/ + + function normalizeName (name) { + return (name || '').toLowerCase().replace(/\//g, '_'); + } + + function addZone (packed) { + var i, name, split, normalized; + + if (typeof packed === "string") { + packed = [packed]; + } + + for (i = 0; i < packed.length; i++) { + split = packed[i].split('|'); + name = split[0]; + normalized = normalizeName(name); + zones[normalized] = packed[i]; + names[normalized] = name; + if (split[5]) { + addToGuesses(normalized, split[2].split(' ')); + } + } + } + + function getZone (name, caller) { + name = normalizeName(name); + + var zone = zones[name]; + var link; + + if (zone instanceof Zone) { + return zone; + } + + if (typeof zone === 'string') { + zone = new Zone(zone); + zones[name] = zone; + return zone; + } + + // Pass getZone to prevent recursion more than 1 level deep + if (links[name] && caller !== getZone && (link = getZone(links[name], getZone))) { + zone = zones[name] = new Zone(); + zone._set(link); + zone.name = names[name]; + return zone; + } + + return null; + } + + function getNames () { + var i, out = []; + + for (i in names) { + if (names.hasOwnProperty(i) && (zones[i] || zones[links[i]]) && names[i]) { + out.push(names[i]); + } + } + + return out.sort(); + } + + function addLink (aliases) { + var i, alias, normal0, normal1; + + if (typeof aliases === "string") { + aliases = [aliases]; + } + + for (i = 0; i < aliases.length; i++) { + alias = aliases[i].split('|'); + + normal0 = normalizeName(alias[0]); + normal1 = normalizeName(alias[1]); + + links[normal0] = normal1; + names[normal0] = alias[0]; + + links[normal1] = normal0; + names[normal1] = alias[1]; + } + } + + function loadData (data) { + addZone(data.zones); + addLink(data.links); + tz.dataVersion = data.version; + } + + function zoneExists (name) { + if (!zoneExists.didShowError) { + zoneExists.didShowError = true; + logError("moment.tz.zoneExists('" + name + "') has been deprecated in favor of !moment.tz.zone('" + name + "')"); + } + return !!getZone(name); + } + + function needsOffset (m) { + return !!(m._a && (m._tzm === undefined)); + } + + function logError (message) { + if (typeof console !== 'undefined' && typeof console.error === 'function') { + console.error(message); + } + } + + /************************************ + moment.tz namespace + ************************************/ + + function tz (input) { + var args = Array.prototype.slice.call(arguments, 0, -1), + name = arguments[arguments.length - 1], + zone = getZone(name), + out = moment.utc.apply(null, args); + + if (zone && !moment.isMoment(input) && needsOffset(out)) { + out.add(zone.parse(out), 'minutes'); + } + + out.tz(name); + + return out; + } + + tz.version = VERSION; + tz.dataVersion = ''; + tz._zones = zones; + tz._links = links; + tz._names = names; + tz.add = addZone; + tz.link = addLink; + tz.load = loadData; + tz.zone = getZone; + tz.zoneExists = zoneExists; // deprecated in 0.1.0 + tz.guess = guess; + tz.names = getNames; + tz.Zone = Zone; + tz.unpack = unpack; + tz.unpackBase60 = unpackBase60; + tz.needsOffset = needsOffset; + tz.moveInvalidForward = true; + tz.moveAmbiguousForward = false; + + /************************************ + Interface with Moment.js + ************************************/ + + var fn = moment.fn; + + moment.tz = tz; + + moment.defaultZone = null; + + moment.updateOffset = function (mom, keepTime) { + var zone = moment.defaultZone, + offset; + + if (mom._z === undefined) { + if (zone && needsOffset(mom) && !mom._isUTC) { + mom._d = moment.utc(mom._a)._d; + mom.utc().add(zone.parse(mom), 'minutes'); + } + mom._z = zone; + } + if (mom._z) { + offset = mom._z.offset(mom); + if (Math.abs(offset) < 16) { + offset = offset / 60; + } + if (mom.utcOffset !== undefined) { + mom.utcOffset(-offset, keepTime); + } else { + mom.zone(offset, keepTime); + } + } + }; + + fn.tz = function (name) { + if (name) { + this._z = getZone(name); + if (this._z) { + moment.updateOffset(this); + } else { + logError("Moment Timezone has no data for " + name + ". See http://momentjs.com/timezone/docs/#/data-loading/."); + } + return this; + } + if (this._z) { return this._z.name; } + }; + + function abbrWrap (old) { + return function () { + if (this._z) { return this._z.abbr(this); } + return old.call(this); + }; + } + + function resetZoneWrap (old) { + return function () { + this._z = null; + return old.apply(this, arguments); + }; + } + + fn.zoneName = abbrWrap(fn.zoneName); + fn.zoneAbbr = abbrWrap(fn.zoneAbbr); + fn.utc = resetZoneWrap(fn.utc); + + moment.tz.setDefault = function(name) { + if (major < 2 || (major === 2 && minor < 9)) { + logError('Moment Timezone setDefault() requires Moment.js >= 2.9.0. You are using Moment.js ' + moment.version + '.'); + } + moment.defaultZone = name ? getZone(name) : null; + return moment; + }; + + // Cloning a moment should include the _z property. + var momentProperties = moment.momentProperties; + if (Object.prototype.toString.call(momentProperties) === '[object Array]') { + // moment 2.8.1+ + momentProperties.push('_z'); + momentProperties.push('_a'); + } else if (momentProperties) { + // moment 2.7.0 + momentProperties._z = null; + } + + loadData({ + "version": "2015g", + "zones": [ + "Africa/Abidjan|LMT GMT|g.8 0|01|-2ldXH.Q|48e5", + "Africa/Accra|LMT GMT GHST|.Q 0 -k|012121212121212121212121212121212121212121212121|-26BbX.8 6tzX.8 MnE 1BAk MnE 1BAk MnE 1BAk MnE 1C0k MnE 1BAk MnE 1BAk MnE 1BAk MnE 1C0k MnE 1BAk MnE 1BAk MnE 1BAk MnE 1C0k MnE 1BAk MnE 1BAk MnE 1BAk MnE 1C0k MnE 1BAk MnE 1BAk MnE 1BAk MnE 1C0k MnE 1BAk MnE 1BAk MnE|41e5", + "Africa/Nairobi|LMT EAT BEAT BEAUT|-2r.g -30 -2u -2J|01231|-1F3Cr.g 3Dzr.g okMu MFXJ|47e5", + "Africa/Algiers|PMT WET WEST CET CEST|-9.l 0 -10 -10 -20|0121212121212121343431312123431213|-2nco9.l cNb9.l HA0 19A0 1iM0 11c0 1oo0 Wo0 1rc0 QM0 1EM0 UM0 DA0 Imo0 rd0 De0 9Xz0 1fb0 1ap0 16K0 2yo0 mEp0 hwL0 jxA0 11A0 dDd0 17b0 11B0 1cN0 2Dy0 1cN0 1fB0 1cL0|26e5", + "Africa/Lagos|LMT WAT|-d.A -10|01|-22y0d.A|17e6", + "Africa/Bissau|LMT WAT GMT|12.k 10 0|012|-2ldWV.E 2xonV.E|39e4", + "Africa/Maputo|LMT CAT|-2a.k -20|01|-2GJea.k|26e5", + "Africa/Cairo|EET EEST|-20 -30|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-1bIO0 vb0 1ip0 11z0 1iN0 1nz0 12p0 1pz0 10N0 1pz0 16p0 1jz0 s3d0 Vz0 1oN0 11b0 1oO0 10N0 1pz0 10N0 1pb0 10N0 1pb0 10N0 1pb0 10N0 1pz0 10N0 1pb0 10N0 1pb0 11d0 1oL0 11d0 1pb0 11d0 1oL0 11d0 1oL0 11d0 1oL0 11d0 1pb0 11d0 1oL0 11d0 1oL0 11d0 1oL0 11d0 1pb0 11d0 1oL0 11d0 1oL0 11d0 1oL0 11d0 1pb0 11d0 1oL0 11d0 1WL0 rd0 1Rz0 wp0 1pb0 11d0 1oL0 11d0 1oL0 11d0 1oL0 11d0 1pb0 11d0 1qL0 Xd0 1oL0 11d0 1oL0 11d0 1pb0 11d0 1oL0 11d0 1oL0 11d0 1ny0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 WL0 1qN0 Rb0 1wp0 On0 1zd0 Lz0 1EN0 Fb0 c10 8n0 8Nd0 gL0 e10 mn0|15e6", + "Africa/Casablanca|LMT WET WEST CET|u.k 0 -10 -10|0121212121212121213121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2gMnt.E 130Lt.E rb0 Dd0 dVb0 b6p0 TX0 EoB0 LL0 gnd0 rz0 43d0 AL0 1Nd0 XX0 1Cp0 pz0 dEp0 4mn0 SyN0 AL0 1Nd0 wn0 1FB0 Db0 1zd0 Lz0 1Nf0 wM0 co0 go0 1o00 s00 dA0 vc0 11A0 A00 e00 y00 11A0 uM0 e00 Dc0 11A0 s00 e00 IM0 WM0 mo0 gM0 LA0 WM0 jA0 e00 Rc0 11A0 e00 e00 U00 11A0 8o0 e00 11A0 11A0 5A0 e00 17c0 1fA0 1a00 1a00 1fA0 17c0 1io0 14o0 1lc0 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1lc0 14o0 1fA0|32e5", + "Africa/Ceuta|WET WEST CET CEST|0 -10 -10 -20|010101010101010101010232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-25KN0 11z0 drd0 18o0 3I00 17c0 1fA0 1a00 1io0 1a00 1y7p0 LL0 gnd0 rz0 43d0 AL0 1Nd0 XX0 1Cp0 pz0 dEp0 4VB0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|85e3", + "Africa/El_Aaiun|LMT WAT WET WEST|Q.M 10 0 -10|01232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-1rDz7.c 1GVA7.c 6L0 AL0 1Nd0 XX0 1Cp0 pz0 1cBB0 AL0 1Nd0 wn0 1FB0 Db0 1zd0 Lz0 1Nf0 wM0 co0 go0 1o00 s00 dA0 vc0 11A0 A00 e00 y00 11A0 uM0 e00 Dc0 11A0 s00 e00 IM0 WM0 mo0 gM0 LA0 WM0 jA0 e00 Rc0 11A0 e00 e00 U00 11A0 8o0 e00 11A0 11A0 5A0 e00 17c0 1fA0 1a00 1a00 1fA0 17c0 1io0 14o0 1lc0 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1lc0 14o0 1fA0|20e4", + "Africa/Johannesburg|SAST SAST SAST|-1u -20 -30|012121|-2GJdu 1Ajdu 1cL0 1cN0 1cL0|84e5", + "Africa/Khartoum|LMT CAT CAST EAT|-2a.8 -20 -30 -30|01212121212121212121212121212121213|-1yW2a.8 1zK0a.8 16L0 1iN0 17b0 1jd0 17b0 1ip0 17z0 1i10 17X0 1hB0 18n0 1hd0 19b0 1gp0 19z0 1iN0 17b0 1ip0 17z0 1i10 18n0 1hd0 18L0 1gN0 19b0 1gp0 19z0 1iN0 17z0 1i10 17X0 yGd0|51e5", + "Africa/Monrovia|MMT LRT GMT|H.8 I.u 0|012|-23Lzg.Q 29s01.m|11e5", + "Africa/Ndjamena|LMT WAT WAST|-10.c -10 -20|0121|-2le10.c 2J3c0.c Wn0|13e5", + "Africa/Tripoli|LMT CET CEST EET|-Q.I -10 -20 -20|012121213121212121212121213123123|-21JcQ.I 1hnBQ.I vx0 4iP0 xx0 4eN0 Bb0 7ip0 U0n0 A10 1db0 1cN0 1db0 1dd0 1db0 1eN0 1bb0 1e10 1cL0 1c10 1db0 1dd0 1db0 1cN0 1db0 1q10 fAn0 1ep0 1db0 AKq0 TA0 1o00|11e5", + "Africa/Tunis|PMT CET CEST|-9.l -10 -20|0121212121212121212121212121212121|-2nco9.l 18pa9.l 1qM0 DA0 3Tc0 11B0 1ze0 WM0 7z0 3d0 14L0 1cN0 1f90 1ar0 16J0 1gXB0 WM0 1rA0 11c0 nwo0 Ko0 1cM0 1cM0 1rA0 10M0 zuM0 10N0 1aN0 1qM0 WM0 1qM0 11A0 1o00|20e5", + "Africa/Windhoek|SWAT SAST SAST CAT WAT WAST|-1u -20 -30 -20 -10 -20|012134545454545454545454545454545454545454545454545454545454545454545454545454545454545454545|-2GJdu 1Ajdu 1cL0 1SqL0 9NA0 11D0 1nX0 11B0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 11B0 1nX0 11B0|32e4", + "America/Adak|NST NWT NPT BST BDT AHST HST HDT|b0 a0 a0 b0 a0 a0 a0 90|012034343434343434343434343434343456767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676|-17SX0 8wW0 iB0 Qlb0 52O0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 cm0 10q0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|326", + "America/Anchorage|CAT CAWT CAPT AHST AHDT YST AKST AKDT|a0 90 90 a0 90 90 90 80|012034343434343434343434343434343456767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676|-17T00 8wX0 iA0 Qlb0 52O0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 cm0 10q0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|30e4", + "America/Port_of_Spain|LMT AST|46.4 40|01|-2kNvR.U|43e3", + "America/Araguaina|LMT BRT BRST|3c.M 30 20|0121212121212121212121212121212121212121212121212121|-2glwL.c HdKL.c 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 1EN0 FX0 1HB0 Lz0 dMN0 Lz0 1zd0 Rb0 1wN0 Wn0 1tB0 Rb0 1tB0 WL0 1tB0 Rb0 1zd0 On0 1HB0 FX0 ny10 Lz0|14e4", + "America/Argentina/Buenos_Aires|CMT ART ARST ART ARST|4g.M 40 30 30 20|0121212121212121212121212121212121212121213434343434343234343|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1wp0 Rb0 1wp0 Rb0 1wp0 TX0 g0p0 10M0 j3c0 uL0 1qN0 WL0", + "America/Argentina/Catamarca|CMT ART ARST ART ARST WART|4g.M 40 30 30 20 40|0121212121212121212121212121212121212121213434343454343235343|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1wp0 Rb0 1wq0 Ra0 1wp0 TX0 g0p0 10M0 ako0 7B0 8zb0 uL0", + "America/Argentina/Cordoba|CMT ART ARST ART ARST WART|4g.M 40 30 30 20 40|0121212121212121212121212121212121212121213434343454343234343|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1wp0 Rb0 1wq0 Ra0 1wp0 TX0 g0p0 10M0 j3c0 uL0 1qN0 WL0", + "America/Argentina/Jujuy|CMT ART ARST ART ARST WART WARST|4g.M 40 30 30 20 40 30|01212121212121212121212121212121212121212134343456543432343|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1ze0 TX0 1ld0 WK0 1wp0 TX0 g0p0 10M0 j3c0 uL0", + "America/Argentina/La_Rioja|CMT ART ARST ART ARST WART|4g.M 40 30 30 20 40|01212121212121212121212121212121212121212134343434534343235343|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1wp0 Qn0 qO0 16n0 Rb0 1wp0 TX0 g0p0 10M0 ako0 7B0 8zb0 uL0", + "America/Argentina/Mendoza|CMT ART ARST ART ARST WART WARST|4g.M 40 30 30 20 40 30|0121212121212121212121212121212121212121213434345656543235343|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1u20 SL0 1vd0 Tb0 1wp0 TW0 g0p0 10M0 agM0 Op0 7TX0 uL0", + "America/Argentina/Rio_Gallegos|CMT ART ARST ART ARST WART|4g.M 40 30 30 20 40|0121212121212121212121212121212121212121213434343434343235343|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1wp0 Rb0 1wp0 Rb0 1wp0 TX0 g0p0 10M0 ako0 7B0 8zb0 uL0", + "America/Argentina/Salta|CMT ART ARST ART ARST WART|4g.M 40 30 30 20 40|01212121212121212121212121212121212121212134343434543432343|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1wp0 Rb0 1wq0 Ra0 1wp0 TX0 g0p0 10M0 j3c0 uL0", + "America/Argentina/San_Juan|CMT ART ARST ART ARST WART|4g.M 40 30 30 20 40|01212121212121212121212121212121212121212134343434534343235343|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1wp0 Qn0 qO0 16n0 Rb0 1wp0 TX0 g0p0 10M0 ak00 m10 8lb0 uL0", + "America/Argentina/San_Luis|CMT ART ARST ART ARST WART WARST|4g.M 40 30 30 20 40 30|01212121212121212121212121212121212121212134343456536353465653|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 XX0 1q20 SL0 AN0 kin0 10M0 ak00 m10 8lb0 8L0 jd0 1qN0 WL0 1qN0", + "America/Argentina/Tucuman|CMT ART ARST ART ARST WART|4g.M 40 30 30 20 40|012121212121212121212121212121212121212121343434345434323534343|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1wp0 Rb0 1wq0 Ra0 1wp0 TX0 g0p0 10M0 ako0 4N0 8BX0 uL0 1qN0 WL0", + "America/Argentina/Ushuaia|CMT ART ARST ART ARST WART|4g.M 40 30 30 20 40|0121212121212121212121212121212121212121213434343434343235343|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1wp0 Rb0 1wp0 Rb0 1wp0 TX0 g0p0 10M0 ajA0 8p0 8zb0 uL0", + "America/Curacao|LMT ANT AST|4z.L 4u 40|012|-2kV7o.d 28KLS.d|15e4", + "America/Asuncion|AMT PYT PYT PYST|3O.E 40 30 30|012131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313|-1x589.k 1DKM9.k 3CL0 3Dd0 10L0 1pB0 10n0 1pB0 10n0 1pB0 1cL0 1dd0 1db0 1dd0 1cL0 1dd0 1cL0 1dd0 1cL0 1dd0 1db0 1dd0 1cL0 1dd0 1cL0 1dd0 1cL0 1dd0 1db0 1dd0 1cL0 1lB0 14n0 1dd0 1cL0 1fd0 WL0 1rd0 1aL0 1dB0 Xz0 1qp0 Xb0 1qN0 10L0 1rB0 TX0 1tB0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1qN0 1cL0 WN0 1qL0 11B0 1nX0 1ip0 WL0 1qN0 WL0 1qN0 WL0 1tB0 TX0 1tB0 TX0 1tB0 19X0 1a10 1fz0 1a10 1fz0 1cN0 17b0 1ip0 17b0 1ip0 17b0 1ip0 19X0 1fB0 19X0 1fB0 19X0 1ip0 17b0 1ip0 17b0 1ip0 19X0 1fB0 19X0 1fB0 19X0 1fB0 19X0 1ip0 17b0 1ip0 17b0 1ip0 19X0 1fB0 19X0 1fB0 19X0 1ip0 17b0 1ip0 17b0 1ip0 19X0 1fB0 19X0 1fB0 19X0 1fB0 19X0 1ip0 17b0 1ip0 17b0 1ip0|28e5", + "America/Atikokan|CST CDT CWT CPT EST|60 50 50 50 50|0101234|-25TQ0 1in0 Rnb0 3je0 8x30 iw0|28e2", + "America/Bahia|LMT BRT BRST|2y.4 30 20|01212121212121212121212121212121212121212121212121212121212121|-2glxp.U HdLp.U 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 1EN0 FX0 1HB0 Lz0 1EN0 Lz0 1C10 IL0 1HB0 Db0 1HB0 On0 1zd0 On0 1zd0 Lz0 1zd0 Rb0 1wN0 Wn0 1tB0 Rb0 1tB0 WL0 1tB0 Rb0 1zd0 On0 1HB0 FX0 l5B0 Rb0|27e5", + "America/Bahia_Banderas|LMT MST CST PST MDT CDT|71 70 60 80 60 50|0121212131414141414141414141414141414152525252525252525252525252525252525252525252525252525252|-1UQF0 deL0 8lc0 17c0 10M0 1dd0 otX0 gmN0 P2N0 13Vd0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 1fB0 WL0 1fB0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nW0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0|84e3", + "America/Barbados|LMT BMT AST ADT|3W.t 3W.t 40 30|01232323232|-1Q0I1.v jsM0 1ODC1.v IL0 1ip0 17b0 1ip0 17b0 1ld0 13b0|28e4", + "America/Belem|LMT BRT BRST|3d.U 30 20|012121212121212121212121212121|-2glwK.4 HdKK.4 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0|20e5", + "America/Belize|LMT CST CHDT CDT|5Q.M 60 5u 50|01212121212121212121212121212121212121212121212121213131|-2kBu7.c fPA7.c Onu 1zcu Rbu 1wou Rbu 1wou Rbu 1zcu Onu 1zcu Onu 1zcu Rbu 1wou Rbu 1wou Rbu 1wou Rbu 1zcu Onu 1zcu Onu 1zcu Rbu 1wou Rbu 1wou Rbu 1zcu Onu 1zcu Onu 1zcu Onu 1zcu Rbu 1wou Rbu 1wou Rbu 1zcu Onu 1zcu Onu 1zcu Rbu 1wou Rbu 1f0Mu qn0 lxB0 mn0|57e3", + "America/Blanc-Sablon|AST ADT AWT APT|40 30 30 30|010230|-25TS0 1in0 UGp0 8x50 iu0|11e2", + "America/Boa_Vista|LMT AMT AMST|42.E 40 30|0121212121212121212121212121212121|-2glvV.k HdKV.k 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 smp0 WL0 1tB0 2L0|62e2", + "America/Bogota|BMT COT COST|4U.g 50 40|0121|-2eb73.I 38yo3.I 2en0|90e5", + "America/Boise|PST PDT MST MWT MPT MDT|80 70 70 60 60 60|0101023425252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252|-261q0 1nX0 11B0 1nX0 8C10 JCL0 8x20 ix0 QwN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 Dd0 1Kn0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|21e4", + "America/Cambridge_Bay|zzz MST MWT MPT MDDT MDT CST CDT EST|0 70 60 60 50 60 60 50 50|0123141515151515151515151515151515151515151515678651515151515151515151515151515151515151515151515151515151515151515151515151|-21Jc0 RO90 8x20 ix0 LCL0 1fA0 zgO0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11A0 1nX0 2K0 WQ0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|15e2", + "America/Campo_Grande|LMT AMT AMST|3C.s 40 30|012121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212|-2glwl.w HdLl.w 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 1EN0 FX0 1HB0 Lz0 1EN0 Lz0 1C10 IL0 1HB0 Db0 1HB0 On0 1zd0 On0 1zd0 Lz0 1zd0 Rb0 1wN0 Wn0 1tB0 Rb0 1tB0 WL0 1tB0 Rb0 1zd0 On0 1HB0 FX0 1C10 Lz0 1Ip0 HX0 1zd0 On0 1HB0 IL0 1wp0 On0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 Rb0 1zd0 Lz0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 On0 1zd0 On0 1C10 Lz0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 Rb0 1wp0 On0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 On0 1zd0 On0 1C10 Lz0 1C10 Lz0 1C10 Lz0 1C10 On0 1zd0 Rb0 1wp0 On0 1C10 Lz0 1C10 On0 1zd0|77e4", + "America/Cancun|LMT CST EST EDT CDT|5L.4 60 50 40 50|0123232341414141414141414141414141414141412|-1UQG0 2q2o0 yLB0 1lb0 14p0 1lb0 14p0 Lz0 xB0 14p0 1nX0 11B0 1nX0 1fB0 WL0 1fB0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 Dd0|63e4", + "America/Caracas|CMT VET VET|4r.E 4u 40|0121|-2kV7w.k 28KM2.k 1IwOu|29e5", + "America/Cayenne|LMT GFT GFT|3t.k 40 30|012|-2mrwu.E 2gWou.E|58e3", + "America/Cayman|KMT EST EDT|57.b 50 40|0121212121212121212121212121212121212121212121|-2l1uQ.N 4duNQ.N 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|58e3", + "America/Chicago|CST CDT EST CWT CPT|60 50 50 50 50|01010101010101010101010101010101010102010101010103401010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-261s0 1nX0 11B0 1nX0 1wp0 TX0 WN0 1qL0 1cN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 11B0 1Hz0 14p0 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 RB0 8x30 iw0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|92e5", + "America/Chihuahua|LMT MST CST CDT MDT|74.k 70 60 50 60|0121212323241414141414141414141414141414141414141414141414141414141414141414141414141414141|-1UQF0 deL0 8lc0 17c0 10M0 1dd0 2zQN0 1lb0 14p0 1lb0 14q0 1lb0 14p0 1nX0 11B0 1nX0 1fB0 WL0 1fB0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0|81e4", + "America/Costa_Rica|SJMT CST CDT|5A.d 60 50|0121212121|-1Xd6n.L 2lu0n.L Db0 1Kp0 Db0 pRB0 15b0 1kp0 mL0|12e5", + "America/Creston|MST PST|70 80|010|-29DR0 43B0|53e2", + "America/Cuiaba|LMT AMT AMST|3I.k 40 30|0121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212|-2glwf.E HdLf.E 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 1EN0 FX0 1HB0 Lz0 1EN0 Lz0 1C10 IL0 1HB0 Db0 1HB0 On0 1zd0 On0 1zd0 Lz0 1zd0 Rb0 1wN0 Wn0 1tB0 Rb0 1tB0 WL0 1tB0 Rb0 1zd0 On0 1HB0 FX0 4a10 HX0 1zd0 On0 1HB0 IL0 1wp0 On0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 Rb0 1zd0 Lz0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 On0 1zd0 On0 1C10 Lz0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 Rb0 1wp0 On0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 On0 1zd0 On0 1C10 Lz0 1C10 Lz0 1C10 Lz0 1C10 On0 1zd0 Rb0 1wp0 On0 1C10 Lz0 1C10 On0 1zd0|54e4", + "America/Danmarkshavn|LMT WGT WGST GMT|1e.E 30 20 0|01212121212121212121212121212121213|-2a5WJ.k 2z5fJ.k 19U0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 DC0|8", + "America/Dawson|YST YDT YWT YPT YDDT PST PDT|90 80 80 80 70 80 70|0101023040565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565|-25TN0 1in0 1o10 13V0 Ser0 8x00 iz0 LCL0 1fA0 jrA0 fNd0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|13e2", + "America/Dawson_Creek|PST PDT PWT PPT MST|80 70 70 70 70|0102301010101010101010101010101010101010101010101010101014|-25TO0 1in0 UGp0 8x10 iy0 3NB0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 ML0|12e3", + "America/Denver|MST MDT MWT MPT|70 60 60 60|01010101023010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-261r0 1nX0 11B0 1nX0 11B0 1qL0 WN0 mn0 Ord0 8x20 ix0 LCN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|26e5", + "America/Detroit|LMT CST EST EWT EPT EDT|5w.b 60 50 40 40 40|01234252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252|-2Cgir.N peqr.N 156L0 8x40 iv0 6fd0 11z0 Jy10 SL0 dnB0 1cL0 s10 1Vz0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|37e5", + "America/Edmonton|LMT MST MDT MWT MPT|7x.Q 70 60 60 60|01212121212121341212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2yd4q.8 shdq.8 1in0 17d0 hz0 2dB0 1fz0 1a10 11z0 1qN0 WL0 1qN0 11z0 IGN0 8x20 ix0 3NB0 11z0 LFB0 1cL0 3Cp0 1cL0 66N0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|10e5", + "America/Eirunepe|LMT ACT ACST AMT|4D.s 50 40 40|0121212121212121212121212121212131|-2glvk.w HdLk.w 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 dPB0 On0 yTd0 d5X0|31e3", + "America/El_Salvador|LMT CST CDT|5U.M 60 50|012121|-1XiG3.c 2Fvc3.c WL0 1qN0 WL0|11e5", + "America/Tijuana|LMT MST PST PDT PWT PPT|7M.4 70 80 70 70 70|012123245232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-1UQE0 4PX0 8mM0 8lc0 SN0 1cL0 pHB0 83r0 zI0 5O10 1Rz0 cOP0 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 BUp0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 U10 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|20e5", + "America/Fort_Nelson|PST PDT PWT PPT MST|80 70 70 70 70|01023010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010104|-25TO0 1in0 UGp0 8x10 iy0 3NB0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0|39e2", + "America/Fort_Wayne|CST CDT CWT CPT EST EDT|60 50 50 50 50 40|010101023010101010101010101040454545454545454545454545454545454545454545454545454545454545454545454|-261s0 1nX0 11B0 1nX0 QI10 Db0 RB0 8x30 iw0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 5Tz0 1o10 qLb0 1cL0 1cN0 1cL0 1qhd0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0", + "America/Fortaleza|LMT BRT BRST|2y 30 20|0121212121212121212121212121212121212121|-2glxq HdLq 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 1EN0 FX0 1HB0 Lz0 nsp0 WL0 1tB0 5z0 2mN0 On0|34e5", + "America/Glace_Bay|LMT AST ADT AWT APT|3X.M 40 30 30 30|012134121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2IsI0.c CwO0.c 1in0 UGp0 8x50 iu0 iq10 11z0 Jg10 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|19e3", + "America/Godthab|LMT WGT WGST|3q.U 30 20|0121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2a5Ux.4 2z5dx.4 19U0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|17e3", + "America/Goose_Bay|NST NDT NST NDT NWT NPT AST ADT ADDT|3u.Q 2u.Q 3u 2u 2u 2u 40 30 20|010232323232323245232323232323232323232323232323232323232326767676767676767676767676767676767676767676768676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676|-25TSt.8 1in0 DXb0 2HbX.8 WL0 1qN0 WL0 1qN0 WL0 1tB0 TX0 1tB0 WL0 1qN0 WL0 1qN0 7UHu itu 1tB0 WL0 1qN0 WL0 1qN0 WL0 1qN0 WL0 1tB0 WL0 1ld0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 S10 g0u 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14n1 1lb0 14p0 1nW0 11C0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zcX Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|76e2", + "America/Grand_Turk|KMT EST EDT AST|57.b 50 40 40|0121212121212121212121212121212121212121212121212121212121212121212121212123|-2l1uQ.N 2HHBQ.N 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|37e2", + "America/Guatemala|LMT CST CDT|62.4 60 50|0121212121|-24KhV.U 2efXV.U An0 mtd0 Nz0 ifB0 17b0 zDB0 11z0|13e5", + "America/Guayaquil|QMT ECT|5e 50|01|-1yVSK|27e5", + "America/Guyana|LMT GBGT GYT GYT GYT|3Q.E 3J 3J 30 40|01234|-2dvU7.k 24JzQ.k mlc0 Bxbf|80e4", + "America/Halifax|LMT AST ADT AWT APT|4e.o 40 30 30 30|0121212121212121212121212121212121212121212121212134121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2IsHJ.A xzzJ.A 1db0 3I30 1in0 3HX0 IL0 1E10 ML0 1yN0 Pb0 1Bd0 Mn0 1Bd0 Rz0 1w10 Xb0 1w10 LX0 1w10 Xb0 1w10 Lz0 1C10 Jz0 1E10 OL0 1yN0 Un0 1qp0 Xb0 1qp0 11X0 1w10 Lz0 1HB0 LX0 1C10 FX0 1w10 Xb0 1qp0 Xb0 1BB0 LX0 1td0 Xb0 1qp0 Xb0 Rf0 8x50 iu0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 3Qp0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 3Qp0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 6i10 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|39e4", + "America/Havana|HMT CST CDT|5t.A 50 40|012121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-1Meuu.o 72zu.o ML0 sld0 An0 1Nd0 Db0 1Nd0 An0 6Ep0 An0 1Nd0 An0 JDd0 Mn0 1Ap0 On0 1fd0 11X0 1qN0 WL0 1wp0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 14n0 1ld0 14L0 1kN0 15b0 1kp0 1cL0 1cN0 1fz0 1a10 1fz0 1fB0 11z0 14p0 1nX0 11B0 1nX0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 14n0 1ld0 14n0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 1a10 1in0 1a10 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 17c0 1o00 11A0 1qM0 11A0 1o00 11A0 1o00 14o0 1lc0 14o0 1lc0 11A0 6i00 Rc0 1wo0 U00 1tA0 Rc0 1wo0 U00 1wo0 U00 1zc0 U00 1qM0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0|21e5", + "America/Hermosillo|LMT MST CST PST MDT|7n.Q 70 60 80 60|0121212131414141|-1UQF0 deL0 8lc0 17c0 10M0 1dd0 otX0 gmN0 P2N0 13Vd0 1lb0 14p0 1lb0 14p0 1lb0|64e4", + "America/Indiana/Knox|CST CDT CWT CPT EST|60 50 50 50 50|0101023010101010101010101010101010101040101010101010101010101010101010101010101010101010141010101010101010101010101010101010101010101010101010101010101010|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 3NB0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 1fz0 1cN0 1cL0 1cN0 11z0 1o10 11z0 1o10 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 3Cn0 8wp0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 z8o0 1o00 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0", + "America/Indiana/Marengo|CST CDT CWT CPT EST EDT|60 50 50 50 50 40|0101023010101010101010104545454545414545454545454545454545454545454545454545454545454545454545454545454|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 dyN0 11z0 6fd0 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 jrz0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1VA0 LA0 1BX0 1e6p0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0", + "America/Indiana/Petersburg|CST CDT CWT CPT EST EDT|60 50 50 50 50 40|01010230101010101010101010104010101010101010101010141014545454545454545454545454545454545454545454545454545454545454|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 njX0 WN0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 3Fb0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 19co0 1o00 Rd0 1zb0 Oo0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0", + "America/Indiana/Tell_City|CST CDT CWT CPT EST EDT|60 50 50 50 50 40|01010230101010101010101010101010454541010101010101010101010101010101010101010101010101010101010101010|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 1o10 11z0 g0p0 11z0 1o10 11z0 1qL0 WN0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 1fz0 1cN0 WL0 1qN0 1cL0 1cN0 1cL0 1cN0 caL0 1cL0 1cN0 1cL0 1qhd0 1o00 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0", + "America/Indiana/Vevay|CST CDT CWT CPT EST EDT|60 50 50 50 50 40|010102304545454545454545454545454545454545454545454545454545454545454545454545454|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 kPB0 Awn0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1lnd0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0", + "America/Indiana/Vincennes|CST CDT CWT CPT EST EDT|60 50 50 50 50 40|01010230101010101010101010101010454541014545454545454545454545454545454545454545454545454545454545454|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 1o10 11z0 g0p0 11z0 1o10 11z0 1qL0 WN0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 1fz0 1cN0 WL0 1qN0 1cL0 1cN0 1cL0 1cN0 caL0 1cL0 1cN0 1cL0 1qhd0 1o00 Rd0 1zb0 Oo0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0", + "America/Indiana/Winamac|CST CDT CWT CPT EST EDT|60 50 50 50 50 40|01010230101010101010101010101010101010454541054545454545454545454545454545454545454545454545454545454545454|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 1fz0 1cN0 1cL0 1cN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 jrz0 1cL0 1cN0 1cL0 1qhd0 1o00 Rd0 1za0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0", + "America/Inuvik|zzz PST PDDT MST MDT|0 80 60 70 60|0121343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343|-FnA0 tWU0 1fA0 wPe0 2pz0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|35e2", + "America/Iqaluit|zzz EWT EPT EST EDDT EDT CST CDT|0 40 40 50 30 40 60 50|01234353535353535353535353535353535353535353567353535353535353535353535353535353535353535353535353535353535353535353535353|-16K00 7nX0 iv0 LCL0 1fA0 zgO0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11C0 1nX0 11A0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|67e2", + "America/Jamaica|KMT EST EDT|57.b 50 40|0121212121212121212121|-2l1uQ.N 2uM1Q.N 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0|94e4", + "America/Juneau|PST PWT PPT PDT YDT YST AKST AKDT|80 70 70 70 80 90 90 80|01203030303030303030303030403030356767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676|-17T20 8x10 iy0 Vo10 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cM0 1cM0 1cL0 1cN0 1fz0 1a10 1fz0 co0 10q0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|33e3", + "America/Kentucky/Louisville|CST CDT CWT CPT EST EDT|60 50 50 50 50 40|0101010102301010101010101010101010101454545454545414545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454|-261s0 1nX0 11B0 1nX0 3Fd0 Nb0 LPd0 11z0 RB0 8x30 iw0 Bb0 10N0 2bB0 8in0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 xz0 gso0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1VA0 LA0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0", + "America/Kentucky/Monticello|CST CDT CWT CPT EST EDT|60 50 50 50 50 40|0101023010101010101010101010101010101010101010101010101010101010101010101454545454545454545454545454545454545454545454545454545454545454545454545454|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 SWp0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11A0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0", + "America/La_Paz|CMT BOST BOT|4w.A 3w.A 40|012|-1x37r.o 13b0|19e5", + "America/Lima|LMT PET PEST|58.A 50 40|0121212121212121|-2tyGP.o 1bDzP.o zX0 1aN0 1cL0 1cN0 1cL0 1PrB0 zX0 1O10 zX0 6Gp0 zX0 98p0 zX0|11e6", + "America/Los_Angeles|PST PDT PWT PPT|80 70 70 70|010102301010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-261q0 1nX0 11B0 1nX0 SgN0 8x10 iy0 5Wp0 1Vb0 3dB0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|15e6", + "America/Maceio|LMT BRT BRST|2m.Q 30 20|012121212121212121212121212121212121212121|-2glxB.8 HdLB.8 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 1EN0 FX0 1HB0 Lz0 dMN0 Lz0 8Q10 WL0 1tB0 5z0 2mN0 On0|93e4", + "America/Managua|MMT CST EST CDT|5J.c 60 50 50|0121313121213131|-1quie.M 1yAMe.M 4mn0 9Up0 Dz0 1K10 Dz0 s3F0 1KH0 DB0 9In0 k8p0 19X0 1o30 11y0|22e5", + "America/Manaus|LMT AMT AMST|40.4 40 30|01212121212121212121212121212121|-2glvX.U HdKX.U 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 dPB0 On0|19e5", + "America/Martinique|FFMT AST ADT|44.k 40 30|0121|-2mPTT.E 2LPbT.E 19X0|39e4", + "America/Matamoros|LMT CST CDT|6E 60 50|0121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-1UQG0 2FjC0 1nX0 i6p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 1fB0 WL0 1fB0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 U10 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|45e4", + "America/Mazatlan|LMT MST CST PST MDT|75.E 70 60 80 60|0121212131414141414141414141414141414141414141414141414141414141414141414141414141414141414141|-1UQF0 deL0 8lc0 17c0 10M0 1dd0 otX0 gmN0 P2N0 13Vd0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 1fB0 WL0 1fB0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0|44e4", + "America/Menominee|CST CDT CWT CPT EST|60 50 50 50 50|01010230101041010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 1o10 11z0 LCN0 1fz0 6410 9Jb0 1cM0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|85e2", + "America/Merida|LMT CST EST CDT|5W.s 60 50 50|0121313131313131313131313131313131313131313131313131313131313131313131313131313131313131|-1UQG0 2q2o0 2hz0 wu30 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 1fB0 WL0 1fB0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0|11e5", + "America/Metlakatla|PST PWT PPT PDT|80 70 70 70|0120303030303030303030303030303030|-17T20 8x10 iy0 Vo10 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0|14e2", + "America/Mexico_City|LMT MST CST CDT CWT|6A.A 70 60 50 50|012121232324232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-1UQF0 deL0 8lc0 17c0 10M0 1dd0 gEn0 TX0 3xd0 Jb0 6zB0 SL0 e5d0 17b0 1Pff0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 1fB0 WL0 1fB0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0|20e6", + "America/Miquelon|LMT AST PMST PMDT|3I.E 40 30 20|012323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-2mKkf.k 2LTAf.k gQ10 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|61e2", + "America/Moncton|EST AST ADT AWT APT|50 40 30 30 30|012121212121212121212134121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2IsH0 CwN0 1in0 zAo0 An0 1Nd0 An0 1Nd0 An0 1Nd0 An0 1Nd0 An0 1Nd0 An0 1K10 Lz0 1zB0 NX0 1u10 Wn0 S20 8x50 iu0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 3Cp0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14n1 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 ReX 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|64e3", + "America/Monterrey|LMT CST CDT|6F.g 60 50|0121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-1UQG0 2FjC0 1nX0 i6p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 1fB0 WL0 1fB0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0|41e5", + "America/Montevideo|MMT UYT UYHST UYST UYT UYHST|3I.I 3u 30 20 30 2u|012121212121212121212121213434343434345454543453434343434343434343434343434343434343434|-20UIf.g 8jzJ.g 1cLu 1dcu 1cLu 1dcu 1cLu ircu 11zu 1o0u 11zu 1o0u 11zu 1qMu WLu 1qMu WLu 1qMu WLu 1qMu 11zu 1o0u 11zu NAu 11bu 2iMu zWu Dq10 19X0 pd0 jz0 cm10 19X0 1fB0 1on0 11d0 1oL0 1nB0 1fzu 1aou 1fzu 1aou 1fzu 3nAu Jb0 3MN0 1SLu 4jzu 2PB0 Lb0 3Dd0 1pb0 ixd0 An0 1MN0 An0 1wp0 On0 1wp0 Rb0 1zd0 On0 1wp0 Rb0 s8p0 1fB0 1ip0 11z0 1ld0 14n0 1o10 11z0 1o10 11z0 1o10 14n0 1ld0 14n0 1ld0 14n0 1o10 11z0 1o10 11z0 1o10 11z0|17e5", + "America/Toronto|EST EDT EWT EPT|50 40 40 40|01010101010101010101010101010101010101010101012301010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-25TR0 1in0 11Wu 1nzu 1fD0 WJ0 1wr0 Nb0 1Ap0 On0 1zd0 On0 1wp0 TX0 1tB0 TX0 1tB0 TX0 1tB0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 4kM0 8x40 iv0 1o10 11z0 1nX0 11z0 1o10 11z0 1o10 1qL0 11D0 1nX0 11B0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|65e5", + "America/Nassau|LMT EST EDT|59.u 50 40|012121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2kNuO.u 26XdO.u 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|24e4", + "America/New_York|EST EDT EWT EPT|50 40 40 40|01010101010101010101010101010101010101010101010102301010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-261t0 1nX0 11B0 1nX0 11B0 1qL0 1a10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 RB0 8x40 iv0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|21e6", + "America/Nipigon|EST EDT EWT EPT|50 40 40 40|010123010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-25TR0 1in0 Rnb0 3je0 8x40 iv0 19yN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|16e2", + "America/Nome|NST NWT NPT BST BDT YST AKST AKDT|b0 a0 a0 b0 a0 90 90 80|012034343434343434343434343434343456767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676|-17SX0 8wW0 iB0 Qlb0 52O0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 cl0 10q0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|38e2", + "America/Noronha|LMT FNT FNST|29.E 20 10|0121212121212121212121212121212121212121|-2glxO.k HdKO.k 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 1EN0 FX0 1HB0 Lz0 nsp0 WL0 1tB0 2L0 2pB0 On0|30e2", + "America/North_Dakota/Beulah|MST MDT MWT MPT CST CDT|70 60 60 60 60 50|010102301010101010101010101010101010101010101010101010101010101010101010101010101010101010101014545454545454545454545454545454545454545454545454545454|-261r0 1nX0 11B0 1nX0 SgN0 8x20 ix0 QwN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Oo0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0", + "America/North_Dakota/Center|MST MDT MWT MPT CST CDT|70 60 60 60 60 50|010102301010101010101010101010101010101010101010101010101014545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454|-261r0 1nX0 11B0 1nX0 SgN0 8x20 ix0 QwN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14o0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0", + "America/North_Dakota/New_Salem|MST MDT MWT MPT CST CDT|70 60 60 60 60 50|010102301010101010101010101010101010101010101010101010101010101010101010101010101454545454545454545454545454545454545454545454545454545454545454545454|-261r0 1nX0 11B0 1nX0 SgN0 8x20 ix0 QwN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14o0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0", + "America/Ojinaga|LMT MST CST CDT MDT|6V.E 70 60 50 60|0121212323241414141414141414141414141414141414141414141414141414141414141414141414141414141|-1UQF0 deL0 8lc0 17c0 10M0 1dd0 2zQN0 1lb0 14p0 1lb0 14q0 1lb0 14p0 1nX0 11B0 1nX0 1fB0 WL0 1fB0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 U10 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|23e3", + "America/Panama|CMT EST|5j.A 50|01|-2uduE.o|15e5", + "America/Pangnirtung|zzz AST AWT APT ADDT ADT EDT EST CST CDT|0 40 30 30 20 30 40 50 60 50|012314151515151515151515151515151515167676767689767676767676767676767676767676767676767676767676767676767676767676767676767|-1XiM0 PnG0 8x50 iu0 LCL0 1fA0 zgO0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1o00 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11C0 1nX0 11A0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|14e2", + "America/Paramaribo|LMT PMT PMT NEGT SRT SRT|3E.E 3E.Q 3E.A 3u 3u 30|012345|-2nDUj.k Wqo0.c qanX.I 1dmLN.o lzc0|24e4", + "America/Phoenix|MST MDT MWT|70 60 60|01010202010|-261r0 1nX0 11B0 1nX0 SgN0 4Al1 Ap0 1db0 SWqX 1cL0|42e5", + "America/Port-au-Prince|PPMT EST EDT|4N 50 40|0121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-28RHb 2FnMb 19X0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14q0 1o00 11A0 1o00 11A0 1o00 14o0 1lc0 14o0 1lc0 14o0 1o00 11A0 1o00 11A0 1o00 14o0 1lc0 14o0 1lc0 i6n0 1nX0 11B0 1nX0 d430 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|23e5", + "America/Rio_Branco|LMT ACT ACST AMT|4v.c 50 40 40|01212121212121212121212121212131|-2glvs.M HdLs.M 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 NBd0 d5X0|31e4", + "America/Porto_Velho|LMT AMT AMST|4f.A 40 30|012121212121212121212121212121|-2glvI.o HdKI.o 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0|37e4", + "America/Puerto_Rico|AST AWT APT|40 30 30|0120|-17lU0 7XT0 iu0|24e5", + "America/Rainy_River|CST CDT CWT CPT|60 50 50 50|010123010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-25TQ0 1in0 Rnb0 3je0 8x30 iw0 19yN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|842", + "America/Rankin_Inlet|zzz CST CDDT CDT EST|0 60 40 50 50|012131313131313131313131313131313131313131313431313131313131313131313131313131313131313131313131313131313131313131313131|-vDc0 keu0 1fA0 zgO0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|26e2", + "America/Recife|LMT BRT BRST|2j.A 30 20|0121212121212121212121212121212121212121|-2glxE.o HdLE.o 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 1EN0 FX0 1HB0 Lz0 nsp0 WL0 1tB0 2L0 2pB0 On0|33e5", + "America/Regina|LMT MST MDT MWT MPT CST|6W.A 70 60 60 60 60|012121212121212121212121341212121212121212121212121215|-2AD51.o uHe1.o 1in0 s2L0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 66N0 1cL0 1cN0 19X0 1fB0 1cL0 1fB0 1cL0 1cN0 1cL0 M30 8x20 ix0 1ip0 1cL0 1ip0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 3NB0 1cL0 1cN0|19e4", + "America/Resolute|zzz CST CDDT CDT EST|0 60 40 50 50|012131313131313131313131313131313131313131313431313131313431313131313131313131313131313131313131313131313131313131313131|-SnA0 GWS0 1fA0 zgO0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|229", + "America/Santa_Isabel|LMT MST PST PDT PWT PPT|7D.s 70 80 70 70 70|012123245232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-1UQE0 4PX0 8mM0 8lc0 SN0 1cL0 pHB0 83r0 zI0 5O10 1Rz0 cOP0 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 BUp0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0|23e3", + "America/Santarem|LMT AMT AMST BRT|3C.M 40 30 30|0121212121212121212121212121213|-2glwl.c HdLl.c 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 NBd0|21e4", + "America/Santiago|SMT CLT CLT CLST CLST CLT|4G.K 50 40 40 30 30|01020313131313121242124242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424245|-2q2jh.e fJAh.e 5knG.K 1Vzh.e jRAG.K 1pbh.e 11d0 1oL0 11d0 1oL0 11d0 1oL0 11d0 1pb0 11d0 nHX0 op0 9Bz0 jb0 1oN0 ko0 Qeo0 WL0 1zd0 On0 1ip0 11z0 1o10 11z0 1qN0 WL0 1ld0 14n0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 WL0 1qN0 1cL0 1cN0 11z0 1o10 11z0 1qN0 WL0 1fB0 19X0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 17b0 1ip0 11z0 1ip0 1fz0 1fB0 11z0 1qN0 WL0 1qN0 WL0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 17b0 1ip0 11z0 1o10 19X0 1fB0 1nX0 G10 1EL0 Op0 1zb0 Rd0 1wn0 Rd0 1wn0|62e5", + "America/Santo_Domingo|SDMT EST EDT EHDT AST|4E 50 40 4u 40|01213131313131414|-1ttjk 1lJMk Mn0 6sp0 Lbu 1Cou yLu 1RAu wLu 1QMu xzu 1Q0u xXu 1PAu 13jB0 e00|29e5", + "America/Sao_Paulo|LMT BRT BRST|36.s 30 20|012121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212|-2glwR.w HdKR.w 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 pTd0 PX0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 1EN0 FX0 1HB0 Lz0 1EN0 Lz0 1C10 IL0 1HB0 Db0 1HB0 On0 1zd0 On0 1zd0 Lz0 1zd0 Rb0 1wN0 Wn0 1tB0 Rb0 1tB0 WL0 1tB0 Rb0 1zd0 On0 1HB0 FX0 1C10 Lz0 1Ip0 HX0 1zd0 On0 1HB0 IL0 1wp0 On0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 Rb0 1zd0 Lz0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 On0 1zd0 On0 1C10 Lz0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 Rb0 1wp0 On0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 On0 1zd0 On0 1C10 Lz0 1C10 Lz0 1C10 Lz0 1C10 On0 1zd0 Rb0 1wp0 On0 1C10 Lz0 1C10 On0 1zd0|20e6", + "America/Scoresbysund|LMT CGT CGST EGST EGT|1r.Q 20 10 0 10|0121343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434|-2a5Ww.8 2z5ew.8 1a00 1cK0 1cL0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|452", + "America/Sitka|PST PWT PPT PDT YST AKST AKDT|80 70 70 70 90 90 80|01203030303030303030303030303030345656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565|-17T20 8x10 iy0 Vo10 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 co0 10q0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|90e2", + "America/St_Johns|NST NDT NST NDT NWT NPT NDDT|3u.Q 2u.Q 3u 2u 2u 2u 1u|01010101010101010101010101010101010102323232323232324523232323232323232323232323232323232323232323232323232323232323232323232323232323232326232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-28oit.8 14L0 1nB0 1in0 1gm0 Dz0 1JB0 1cL0 1cN0 1cL0 1fB0 19X0 1fB0 19X0 1fB0 19X0 1fB0 19X0 1fB0 1cL0 1cN0 1cL0 1fB0 19X0 1fB0 19X0 1fB0 19X0 1fB0 19X0 1fB0 1cL0 1fB0 19X0 1fB0 19X0 10O0 eKX.8 19X0 1iq0 WL0 1qN0 WL0 1qN0 WL0 1tB0 TX0 1tB0 WL0 1qN0 WL0 1qN0 7UHu itu 1tB0 WL0 1qN0 WL0 1qN0 WL0 1qN0 WL0 1tB0 WL0 1ld0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14n1 1lb0 14p0 1nW0 11C0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zcX Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|11e4", + "America/Swift_Current|LMT MST MDT MWT MPT CST|7b.k 70 60 60 60 60|012134121212121212121215|-2AD4M.E uHdM.E 1in0 UGp0 8x20 ix0 1o10 17b0 1ip0 11z0 1o10 11z0 1o10 11z0 isN0 1cL0 3Cp0 1cL0 1cN0 11z0 1qN0 WL0 pMp0|16e3", + "America/Tegucigalpa|LMT CST CDT|5M.Q 60 50|01212121|-1WGGb.8 2ETcb.8 WL0 1qN0 WL0 GRd0 AL0|11e5", + "America/Thule|LMT AST ADT|4z.8 40 30|012121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2a5To.Q 31NBo.Q 1cL0 1cN0 1cL0 1fB0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|656", + "America/Thunder_Bay|CST EST EWT EPT EDT|60 50 40 40 40|0123141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141|-2q5S0 1iaN0 8x40 iv0 XNB0 1cL0 1cN0 1fz0 1cN0 1cL0 3Cp0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|11e4", + "America/Vancouver|PST PDT PWT PPT|80 70 70 70|0102301010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-25TO0 1in0 UGp0 8x10 iy0 1o10 17b0 1ip0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|23e5", + "America/Whitehorse|YST YDT YWT YPT YDDT PST PDT|90 80 80 80 70 80 70|0101023040565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565|-25TN0 1in0 1o10 13V0 Ser0 8x00 iz0 LCL0 1fA0 3NA0 vrd0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|23e3", + "America/Winnipeg|CST CDT CWT CPT|60 50 50 50|010101023010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2aIi0 WL0 3ND0 1in0 Jap0 Rb0 aCN0 8x30 iw0 1tB0 11z0 1ip0 11z0 1o10 11z0 1o10 11z0 1rd0 10L0 1op0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 1cL0 1cN0 11z0 6i10 WL0 6i10 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1a00 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1a00 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 14o0 1lc0 14o0 1o00 11A0 1o00 11A0 1o00 14o0 1lc0 14o0 1lc0 14o0 1o00 11A0 1o00 11A0 1o00 14o0 1lc0 14o0 1lc0 14o0 1lc0 14o0 1o00 11A0 1o00 11A0 1o00 14o0 1lc0 14o0 1lc0 14o0 1o00 11A0 1o00 11A0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|66e4", + "America/Yakutat|YST YWT YPT YDT AKST AKDT|90 80 80 80 90 80|01203030303030303030303030303030304545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454|-17T10 8x00 iz0 Vo10 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 cn0 10q0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|642", + "America/Yellowknife|zzz MST MWT MPT MDDT MDT|0 70 60 60 50 60|012314151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151|-1pdA0 hix0 8x20 ix0 LCL0 1fA0 zgO0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|19e3", + "Antarctica/Casey|zzz AWST CAST|0 -80 -b0|012121|-2q00 1DjS0 T90 40P0 KL0|10", + "Antarctica/Davis|zzz DAVT DAVT|0 -70 -50|01012121|-vyo0 iXt0 alj0 1D7v0 VB0 3Wn0 KN0|70", + "Antarctica/DumontDUrville|zzz PMT DDUT|0 -a0 -a0|0102|-U0o0 cfq0 bFm0|80", + "Antarctica/Macquarie|AEST AEDT zzz MIST|-a0 -b0 0 -b0|0102010101010101010101010101010101010101010101010101010101010101010101010101010101010101013|-29E80 19X0 4SL0 1ayy0 Lvs0 1cM0 1o00 Rc0 1wo0 Rc0 1wo0 U00 1wo0 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 11A0 1qM0 WM0 1qM0 Oo0 1zc0 Oo0 1zc0 Oo0 1wo0 WM0 1tA0 WM0 1tA0 U00 1tA0 U00 1tA0 11A0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 11A0 1o00 1io0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1cM0 1a00 1io0 1cM0 1cM0 1cM0 1cM0 1cM0|1", + "Antarctica/Mawson|zzz MAWT MAWT|0 -60 -50|012|-CEo0 2fyk0|60", + "Pacific/Auckland|NZMT NZST NZST NZDT|-bu -cu -c0 -d0|01020202020202020202020202023232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323|-1GCVu Lz0 1tB0 11zu 1o0u 11zu 1o0u 11zu 1o0u 14nu 1lcu 14nu 1lcu 1lbu 11Au 1nXu 11Au 1nXu 11Au 1nXu 11Au 1nXu 11Au 1qLu WMu 1qLu 11Au 1n1bu IM0 1C00 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1qM0 14o0 1lc0 14o0 1lc0 14o0 1lc0 17c0 1io0 17c0 1io0 17c0 1io0 17c0 1lc0 14o0 1lc0 14o0 1lc0 17c0 1io0 17c0 1io0 17c0 1lc0 14o0 1lc0 14o0 1lc0 17c0 1io0 17c0 1io0 17c0 1io0 17c0 1io0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1io0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00|14e5", + "Antarctica/Palmer|zzz ARST ART ART ARST CLT CLST CLT|0 30 40 30 20 40 30 30|012121212123435656565656565656565656565656565656565656565656565656565656565656567|-cao0 nD0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 jsN0 14N0 11z0 1o10 11z0 1qN0 WL0 1qN0 WL0 1qN0 1cL0 1cN0 11z0 1o10 11z0 1qN0 WL0 1fB0 19X0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 17b0 1ip0 11z0 1ip0 1fz0 1fB0 11z0 1qN0 WL0 1qN0 WL0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 17b0 1ip0 11z0 1o10 19X0 1fB0 1nX0 G10 1EL0 Op0 1zb0 Rd0 1wn0 Rd0 1wn0|40", + "Antarctica/Rothera|zzz ROTT|0 30|01|gOo0|130", + "Antarctica/Syowa|zzz SYOT|0 -30|01|-vs00|20", + "Antarctica/Troll|zzz UTC CEST|0 0 -20|01212121212121212121212121212121212121212121212121212121212121212121|1puo0 hd0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|40", + "Antarctica/Vostok|zzz VOST|0 -60|01|-tjA0|25", + "Europe/Oslo|CET CEST|-10 -20|010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2awM0 Qm0 W6o0 5pf0 WM0 1fA0 1cM0 1cM0 1cM0 1cM0 wJc0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1qM0 WM0 zpc0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|62e4", + "Asia/Riyadh|LMT AST|-36.Q -30|01|-TvD6.Q|57e5", + "Asia/Almaty|LMT ALMT ALMT ALMST|-57.M -50 -60 -70|0123232323232323232323232323232323232323232323232|-1Pc57.M eUo7.M 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 3Cl0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0|15e5", + "Asia/Amman|LMT EET EEST|-2n.I -20 -30|0121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-1yW2n.I 1HiMn.I KL0 1oN0 11b0 1oN0 11b0 1pd0 1dz0 1cp0 11b0 1op0 11b0 fO10 1db0 1e10 1cL0 1cN0 1cL0 1cN0 1fz0 1pd0 10n0 1ld0 14n0 1hB0 15b0 1ip0 19X0 1cN0 1cL0 1cN0 17b0 1ld0 14o0 1lc0 17c0 1io0 17c0 1io0 17c0 1So0 y00 1fc0 1dc0 1co0 1dc0 1cM0 1cM0 1cM0 1o00 11A0 1lc0 17c0 1cM0 1cM0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 4bX0 Dd0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0|25e5", + "Asia/Anadyr|LMT ANAT ANAT ANAST ANAST ANAST ANAT|-bN.U -c0 -d0 -e0 -d0 -c0 -b0|01232414141414141414141561414141414141414141414141414141414141561|-1PcbN.U eUnN.U 23CL0 1db0 1cN0 1dc0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 IM0 rU0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qN0 WM0|13e3", + "Asia/Aqtau|LMT FORT FORT SHET SHET SHEST AQTT AQTST AQTST AQTT|-3l.4 -40 -50 -50 -60 -60 -50 -60 -50 -40|012345353535353535353536767676898989898989898989896|-1Pc3l.4 eUnl.4 1jcL0 JDc0 1cL0 1dc0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2UK0 Fz0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cN0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 RW0|15e4", + "Asia/Aqtobe|LMT AKTT AKTT AKTST AKTT AQTT AQTST|-3M.E -40 -50 -60 -60 -50 -60|01234323232323232323232565656565656565656565656565|-1Pc3M.E eUnM.E 23CL0 1db0 1cM0 1dc0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2UK0 Fz0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0|27e4", + "Asia/Ashgabat|LMT ASHT ASHT ASHST ASHST TMT TMT|-3R.w -40 -50 -60 -50 -40 -50|012323232323232323232324156|-1Pc3R.w eUnR.w 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 ba0 xC0|41e4", + "Asia/Baghdad|BMT AST ADT|-2V.A -30 -40|012121212121212121212121212121212121212121212121212121|-26BeV.A 2ACnV.A 11b0 1cp0 1dz0 1dd0 1db0 1cN0 1cp0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1de0 1dc0 1dc0 1dc0 1cM0 1dc0 1cM0 1dc0 1cM0 1dc0 1dc0 1dc0 1cM0 1dc0 1cM0 1dc0 1cM0 1dc0 1dc0 1dc0 1cM0 1dc0 1cM0 1dc0 1cM0 1dc0 1dc0 1dc0 1cM0 1dc0 1cM0 1dc0 1cM0 1dc0|66e5", + "Asia/Qatar|LMT GST AST|-3q.8 -40 -30|012|-21Jfq.8 27BXq.8|96e4", + "Asia/Baku|LMT BAKT BAKT BAKST BAKST AZST AZT AZT AZST|-3j.o -30 -40 -50 -40 -40 -30 -40 -50|0123232323232323232323245657878787878787878787878787878787878787878787878787878787878787878787878787878787878787|-1Pc3j.o 1jUoj.o WCL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 10K0 c30 1cJ0 1cL0 8wu0 1o00 11z0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|27e5", + "Asia/Bangkok|BMT ICT|-6G.4 -70|01|-218SG.4|15e6", + "Asia/Beirut|EET EEST|-20 -30|010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-21aq0 1on0 1410 1db0 19B0 1in0 1ip0 WL0 1lQp0 11b0 1oN0 11b0 1oN0 11b0 1pd0 11b0 1oN0 11b0 q6N0 En0 1oN0 11b0 1oN0 11b0 1oN0 11b0 1pd0 11b0 1oN0 11b0 1op0 11b0 dA10 17b0 1iN0 17b0 1iN0 17b0 1iN0 17b0 1vB0 SL0 1mp0 13z0 1iN0 17b0 1iN0 17b0 1jd0 12n0 1a10 1cL0 1cN0 1cL0 1cN0 1cL0 1fB0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0|22e5", + "Asia/Bishkek|LMT FRUT FRUT FRUST FRUST KGT KGST KGT|-4W.o -50 -60 -70 -60 -50 -60 -60|01232323232323232323232456565656565656565656565656567|-1Pc4W.o eUnW.o 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 11c0 1tX0 17b0 1ip0 17b0 1ip0 17b0 1ip0 17b0 1ip0 19X0 1cPu 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 T8u|87e4", + "Asia/Brunei|LMT BNT BNT|-7D.E -7u -80|012|-1KITD.E gDc9.E|42e4", + "Asia/Kolkata|HMT BURT IST IST|-5R.k -6u -5u -6u|01232|-18LFR.k 1unn.k HB0 7zX0|15e6", + "Asia/Chita|LMT YAKT YAKT YAKST YAKST YAKT IRKT|-7x.Q -80 -90 -a0 -90 -a0 -80|012323232323232323232324123232323232323232323232323232323232323256|-21Q7x.Q pAnx.Q 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 IM0 rU0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|33e4", + "Asia/Choibalsan|LMT ULAT ULAT CHOST CHOT CHOT CHOST|-7C -70 -80 -a0 -90 -80 -90|0123434343434343434343434343434343434343434343456565656565656565656565656565656565656565656565|-2APHC 2UkoC cKn0 1da0 1dd0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1fB0 1cL0 1cN0 1cL0 1cN0 1cL0 6hD0 11z0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 3Db0 h1f0 1cJ0 1cP0 1cJ0 1cP0 1fx0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1fx0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1fx0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1fx0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0|38e3", + "Asia/Shanghai|CST CDT|-80 -90|01010101010101010|-1c1I0 LX0 16p0 1jz0 1Myp0 Rb0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0|23e6", + "Asia/Colombo|MMT IST IHST IST LKT LKT|-5j.w -5u -60 -6u -6u -60|01231451|-2zOtj.w 1rFbN.w 1zzu 7Apu 23dz0 11zu n3cu|22e5", + "Asia/Dhaka|HMT BURT IST DACT BDT BDST|-5R.k -6u -5u -60 -60 -70|01213454|-18LFR.k 1unn.k HB0 m6n0 LqMu 1x6n0 1i00|16e6", + "Asia/Damascus|LMT EET EEST|-2p.c -20 -30|01212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-21Jep.c Hep.c 17b0 1ip0 17b0 1ip0 17b0 1ip0 19X0 1xRB0 11X0 1oN0 10L0 1pB0 11b0 1oN0 10L0 1mp0 13X0 1oN0 11b0 1pd0 11b0 1oN0 11b0 1oN0 11b0 1oN0 11b0 1pd0 11b0 1oN0 11b0 1oN0 11b0 1oN0 11b0 1pd0 11b0 1oN0 Nb0 1AN0 Nb0 bcp0 19X0 1gp0 19X0 3ld0 1xX0 Vd0 1Bz0 Sp0 1vX0 10p0 1dz0 1cN0 1cL0 1db0 1db0 1g10 1an0 1ap0 1db0 1fd0 1db0 1cN0 1db0 1dd0 1db0 1cp0 1dz0 1c10 1dX0 1cN0 1db0 1dd0 1db0 1cN0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1db0 1cN0 1db0 1cN0 19z0 1fB0 1qL0 11B0 1on0 Wp0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0|26e5", + "Asia/Dili|LMT TLT JST TLT WITA|-8m.k -80 -90 -90 -80|012343|-2le8m.k 1dnXm.k 8HA0 1ew00 Xld0|19e4", + "Asia/Dubai|LMT GST|-3F.c -40|01|-21JfF.c|39e5", + "Asia/Dushanbe|LMT DUST DUST DUSST DUSST TJT|-4z.c -50 -60 -70 -60 -50|0123232323232323232323245|-1Pc4z.c eUnz.c 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 14N0|76e4", + "Asia/Gaza|EET EET EEST IST IDT|-20 -30 -30 -20 -30|010101010102020202020202020202023434343434343434343434343430202020202020202020202020202020202020202020202020202020202020202020202020202020202020|-1c2q0 5Rb0 10r0 1px0 10N0 1pz0 16p0 1jB0 16p0 1jx0 pBd0 Vz0 1oN0 11b0 1oO0 10N0 1pz0 10N0 1pb0 10N0 1pb0 10N0 1pb0 10N0 1pz0 10N0 1pb0 10N0 1pb0 11d0 1oL0 dW0 hfB0 Db0 1fB0 Rb0 npB0 11z0 1C10 IL0 1s10 10n0 1o10 WL0 1zd0 On0 1ld0 11z0 1o10 14n0 1o10 14n0 1nd0 12n0 1nd0 Xz0 1q10 12n0 M10 C00 17c0 1io0 17c0 1io0 17c0 1o00 1cL0 1fB0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 17c0 1io0 18N0 1bz0 19z0 1gp0 1610 1iL0 11z0 1o10 14o0 1lA1 SKX 1xd1 MKX 1AN0 1a00 1fA0 1cL0 1cN0 1nX0 1210 1nz0 1210 1nz0 14N0 1nz0 1210 1nz0 1210 1nz0 1210 1nz0 1210 1nz0 1210 1nz0 14N0 1nz0 1210 1nz0 1210 1nz0 1210 1nz0 1210 1nz0 14N0 1nz0 1210 1nz0 1210 1nz0 1210 1nz0 1210 1nz0 1210 1nz0 14N0 1nz0 1210 1nz0 1210 1nz0 1210 1nz0|18e5", + "Asia/Hebron|EET EET EEST IST IDT|-20 -30 -30 -20 -30|01010101010202020202020202020202343434343434343434343434343020202020202020202020202020202020202020202020202020202020202020202020202020202020202020|-1c2q0 5Rb0 10r0 1px0 10N0 1pz0 16p0 1jB0 16p0 1jx0 pBd0 Vz0 1oN0 11b0 1oO0 10N0 1pz0 10N0 1pb0 10N0 1pb0 10N0 1pb0 10N0 1pz0 10N0 1pb0 10N0 1pb0 11d0 1oL0 dW0 hfB0 Db0 1fB0 Rb0 npB0 11z0 1C10 IL0 1s10 10n0 1o10 WL0 1zd0 On0 1ld0 11z0 1o10 14n0 1o10 14n0 1nd0 12n0 1nd0 Xz0 1q10 12n0 M10 C00 17c0 1io0 17c0 1io0 17c0 1o00 1cL0 1fB0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 17c0 1io0 18N0 1bz0 19z0 1gp0 1610 1iL0 12L0 1mN0 14o0 1lc0 Tb0 1xd1 MKX bB0 cn0 1cN0 1a00 1fA0 1cL0 1cN0 1nX0 1210 1nz0 1210 1nz0 14N0 1nz0 1210 1nz0 1210 1nz0 1210 1nz0 1210 1nz0 1210 1nz0 14N0 1nz0 1210 1nz0 1210 1nz0 1210 1nz0 1210 1nz0 14N0 1nz0 1210 1nz0 1210 1nz0 1210 1nz0 1210 1nz0 1210 1nz0 14N0 1nz0 1210 1nz0 1210 1nz0 1210 1nz0|25e4", + "Asia/Ho_Chi_Minh|LMT PLMT ICT IDT JST|-76.E -76.u -70 -80 -90|0123423232|-2yC76.E bK00.a 1h7b6.u 5lz0 18o0 3Oq0 k5b0 aW00 BAM0|90e5", + "Asia/Hong_Kong|LMT HKT HKST JST|-7A.G -80 -90 -90|0121312121212121212121212121212121212121212121212121212121212121212121|-2CFHA.G 1sEP6.G 1cL0 ylu 93X0 1qQu 1tX0 Rd0 1In0 NB0 1cL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1kL0 14N0 1nX0 U10 1tz0 U10 1wn0 Rd0 1wn0 U10 1tz0 U10 1tz0 U10 1tz0 U10 1wn0 Rd0 1wn0 Rd0 1wn0 U10 1tz0 U10 1tz0 17d0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 s10 1Vz0 1cN0 1cL0 1cN0 1cL0 6fd0 14n0|73e5", + "Asia/Hovd|LMT HOVT HOVT HOVST|-66.A -60 -70 -80|012323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-2APG6.A 2Uko6.A cKn0 1db0 1dd0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1fB0 1cL0 1cN0 1cL0 1cN0 1cL0 6hD0 11z0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 kEp0 1cJ0 1cP0 1cJ0 1cP0 1fx0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1fx0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1fx0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1fx0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0|81e3", + "Asia/Irkutsk|IMT IRKT IRKT IRKST IRKST IRKT|-6V.5 -70 -80 -90 -80 -90|012323232323232323232324123232323232323232323232323232323232323252|-21zGV.5 pjXV.5 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 IM0 rU0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|60e4", + "Europe/Istanbul|IMT EET EEST TRST TRT|-1U.U -20 -30 -40 -30|012121212121212121212121212121212121212121212121212121234343434342121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2ogNU.U dzzU.U 11b0 8tB0 1on0 1410 1db0 19B0 1in0 3Rd0 Un0 1oN0 11b0 zSp0 CL0 mN0 1Vz0 1gN0 1pz0 5Rd0 1fz0 1yp0 ML0 1kp0 17b0 1ip0 17b0 1fB0 19X0 1jB0 18L0 1ip0 17z0 qdd0 xX0 3S10 Tz0 dA10 11z0 1o10 11z0 1qN0 11z0 1ze0 11B0 WM0 1qO0 WI0 1nX0 1rB0 10L0 11B0 1in0 17d0 1in0 2pX0 19E0 1fU0 16Q0 1iI0 16Q0 1iI0 1Vd0 pb0 3Kp0 14o0 1df0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cL0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WO0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 Xc0 1qo0 WM0 1qM0 11A0 1o00 1200 1nA0 11A0 1tA0 U00 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|13e6", + "Asia/Jakarta|BMT JAVT WIB JST WIB WIB|-77.c -7k -7u -90 -80 -70|01232425|-1Q0Tk luM0 mPzO 8vWu 6kpu 4PXu xhcu|31e6", + "Asia/Jayapura|LMT WIT ACST|-9m.M -90 -9u|0121|-1uu9m.M sMMm.M L4nu|26e4", + "Asia/Jerusalem|JMT IST IDT IDDT|-2k.E -20 -30 -40|01212121212132121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-26Bek.E SyMk.E 5Rb0 10r0 1px0 10N0 1pz0 16p0 1jB0 16p0 1jx0 3LB0 Em0 or0 1cn0 1dB0 16n0 10O0 1ja0 1tC0 14o0 1cM0 1a00 11A0 1Na0 An0 1MP0 AJ0 1Kp0 LC0 1oo0 Wl0 EQN0 Db0 1fB0 Rb0 npB0 11z0 1C10 IL0 1s10 10n0 1o10 WL0 1zd0 On0 1ld0 11z0 1o10 14n0 1o10 14n0 1nd0 12n0 1nd0 Xz0 1q10 12n0 1hB0 1dX0 1ep0 1aL0 1eN0 17X0 1nf0 11z0 1tB0 19W0 1e10 17b0 1ep0 1gL0 18N0 1fz0 1eN0 17b0 1gq0 1gn0 19d0 1dz0 1c10 17X0 1hB0 1gn0 19d0 1dz0 1c10 17X0 1kp0 1dz0 1c10 1aL0 1eN0 1oL0 10N0 1oL0 10N0 1oL0 10N0 1rz0 W10 1rz0 W10 1rz0 10N0 1oL0 10N0 1oL0 10N0 1rz0 W10 1rz0 W10 1rz0 10N0 1oL0 10N0 1oL0 10N0 1oL0 10N0 1rz0 W10 1rz0 W10 1rz0 10N0 1oL0 10N0 1oL0 10N0 1rz0 W10 1rz0 W10 1rz0 W10 1rz0 10N0 1oL0 10N0 1oL0|81e4", + "Asia/Kabul|AFT AFT|-40 -4u|01|-10Qs0|46e5", + "Asia/Kamchatka|LMT PETT PETT PETST PETST|-ay.A -b0 -c0 -d0 -c0|01232323232323232323232412323232323232323232323232323232323232412|-1SLKy.A ivXy.A 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 IM0 rU0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qN0 WM0|18e4", + "Asia/Karachi|LMT IST IST KART PKT PKST|-4s.c -5u -6u -50 -50 -60|012134545454|-2xoss.c 1qOKW.c 7zX0 eup0 LqMu 1fy01 1cL0 dK0X 11b0 1610 1jX0|24e6", + "Asia/Urumqi|LMT XJT|-5O.k -60|01|-1GgtO.k|32e5", + "Asia/Kathmandu|LMT IST NPT|-5F.g -5u -5J|012|-21JhF.g 2EGMb.g|12e5", + "Asia/Khandyga|LMT YAKT YAKT YAKST YAKST VLAT VLAST VLAT YAKT|-92.d -80 -90 -a0 -90 -a0 -b0 -b0 -a0|01232323232323232323232412323232323232323232323232565656565656565782|-21Q92.d pAp2.d 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 IM0 rU0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 qK0 yN0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 17V0 7zD0|66e2", + "Asia/Krasnoyarsk|LMT KRAT KRAT KRAST KRAST KRAT|-6b.q -60 -70 -80 -70 -80|012323232323232323232324123232323232323232323232323232323232323252|-21Hib.q prAb.q 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 IM0 rU0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|10e5", + "Asia/Kuala_Lumpur|SMT MALT MALST MALT MALT JST MYT|-6T.p -70 -7k -7k -7u -90 -80|01234546|-2Bg6T.p 17anT.p 7hXE dM00 17bO 8Fyu 1so1u|71e5", + "Asia/Kuching|LMT BORT BORT BORTST JST MYT|-7l.k -7u -80 -8k -90 -80|01232323232323232425|-1KITl.k gDbP.k 6ynu AnE 1O0k AnE 1NAk AnE 1NAk AnE 1NAk AnE 1O0k AnE 1NAk AnE pAk 8Fz0 1so10|13e4", + "Asia/Macau|LMT MOT MOST CST|-7y.k -80 -90 -80|0121212121212121212121212121212121212121213|-2le7y.k 1XO34.k 1wn0 Rd0 1wn0 R9u 1wqu U10 1tz0 TVu 1tz0 17gu 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cJu 1cL0 1cN0 1fz0 1cN0 1cOu 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cJu 1cL0 1cN0 1fz0 1cN0 1cL0 KEp0|57e4", + "Asia/Magadan|LMT MAGT MAGT MAGST MAGST MAGT|-a3.c -a0 -b0 -c0 -b0 -c0|012323232323232323232324123232323232323232323232323232323232323251|-1Pca3.c eUo3.c 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 IM0 rU0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|95e3", + "Asia/Makassar|LMT MMT WITA JST|-7V.A -7V.A -80 -90|01232|-21JjV.A vfc0 myLV.A 8ML0|15e5", + "Asia/Manila|PHT PHST JST|-80 -90 -90|010201010|-1kJI0 AL0 cK10 65X0 mXB0 vX0 VK10 1db0|24e6", + "Asia/Nicosia|LMT EET EEST|-2d.s -20 -30|01212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-1Vc2d.s 2a3cd.s 1cL0 1qp0 Xz0 19B0 19X0 1fB0 1db0 1cp0 1cL0 1fB0 19X0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1fB0 1cL0 1cN0 1cL0 1cN0 1o30 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|32e4", + "Asia/Novokuznetsk|LMT KRAT KRAT KRAST KRAST NOVST NOVT NOVT|-5M.M -60 -70 -80 -70 -70 -60 -70|012323232323232323232324123232323232323232323232323232323232325672|-1PctM.M eULM.M 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 IM0 rU0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qN0 WM0 8Hz0|55e4", + "Asia/Novosibirsk|LMT NOVT NOVT NOVST NOVST|-5v.E -60 -70 -80 -70|0123232323232323232323241232341414141414141414141414141414141414121|-21Qnv.E pAFv.E 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 IM0 rU0 1cL0 1cQ0 ml0 Os0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|15e5", + "Asia/Omsk|LMT OMST OMST OMSST OMSST OMST|-4R.u -50 -60 -70 -60 -70|012323232323232323232324123232323232323232323232323232323232323252|-224sR.u pMLR.u 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 IM0 rU0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|12e5", + "Asia/Oral|LMT URAT URAT URAST URAT URAST ORAT ORAST ORAT|-3p.o -40 -50 -60 -60 -50 -40 -50 -50|012343232323232323251516767676767676767676767676768|-1Pc3p.o eUnp.o 23CL0 1db0 1cM0 1dc0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cN0 1cM0 1fA0 2UK0 Fz0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 RW0|27e4", + "Asia/Pontianak|LMT PMT WIB JST WIB WITA WIB|-7h.k -7h.k -7u -90 -80 -80 -70|012324256|-2ua7h.k XE00 munL.k 8Rau 6kpu 4PXu xhcu Wqnu|23e4", + "Asia/Pyongyang|LMT KST JCST JST KST|-8n -8u -90 -90 -90|012341|-2um8n 97XR 12FXu jdA0 2Onc0|29e5", + "Asia/Qyzylorda|LMT KIZT KIZT KIZST KIZT QYZT QYZT QYZST|-4l.Q -40 -50 -60 -60 -50 -60 -70|012343232323232323232325676767676767676767676767676|-1Pc4l.Q eUol.Q 23CL0 1db0 1cM0 1dc0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2UK0 dC0 rU0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0|73e4", + "Asia/Rangoon|RMT BURT JST MMT|-6o.E -6u -90 -6u|0123|-21Jio.E SmnS.E 7j9u|48e5", + "Asia/Sakhalin|LMT JCST JST SAKT SAKST SAKST SAKT|-9u.M -90 -90 -b0 -c0 -b0 -a0|0123434343434343434343435634343434343565656565656565656565656565636|-2AGVu.M 1iaMu.M je00 1qFa0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 IM0 rU0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o10 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|58e4", + "Asia/Samarkand|LMT SAMT SAMT SAMST TAST UZST UZT|-4r.R -40 -50 -60 -60 -60 -50|01234323232323232323232356|-1Pc4r.R eUor.R 23CL0 1db0 1cM0 1dc0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 11x0 bf0|36e4", + "Asia/Seoul|LMT KST JCST JST KST KDT KDT|-8r.Q -8u -90 -90 -90 -9u -a0|01234151515151515146464|-2um8r.Q 97XV.Q 12FXu jjA0 kKo0 2I0u OL0 1FB0 Rb0 1qN0 TX0 1tB0 TX0 1tB0 TX0 1tB0 TX0 2ap0 12FBu 11A0 1o00 11A0|23e6", + "Asia/Singapore|SMT MALT MALST MALT MALT JST SGT SGT|-6T.p -70 -7k -7k -7u -90 -7u -80|012345467|-2Bg6T.p 17anT.p 7hXE dM00 17bO 8Fyu Mspu DTA0|56e5", + "Asia/Srednekolymsk|LMT MAGT MAGT MAGST MAGST MAGT SRET|-ae.Q -a0 -b0 -c0 -b0 -c0 -b0|012323232323232323232324123232323232323232323232323232323232323256|-1Pcae.Q eUoe.Q 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 IM0 rU0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|35e2", + "Asia/Taipei|JWST JST CST CDT|-80 -90 -80 -90|01232323232323232323232323232323232323232|-1iw80 joM0 1yo0 Tz0 1ip0 1jX0 1cN0 11b0 1oN0 11b0 1oN0 11b0 1oN0 11b0 10N0 1BX0 10p0 1pz0 10p0 1pz0 10p0 1db0 1dd0 1db0 1cN0 1db0 1cN0 1db0 1cN0 1db0 1BB0 ML0 1Bd0 ML0 uq10 1db0 1cN0 1db0 97B0 AL0|74e5", + "Asia/Tashkent|LMT TAST TAST TASST TASST UZST UZT|-4B.b -50 -60 -70 -60 -60 -50|01232323232323232323232456|-1Pc4B.b eUnB.b 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 11y0 bf0|23e5", + "Asia/Tbilisi|TBMT TBIT TBIT TBIST TBIST GEST GET GET GEST|-2X.b -30 -40 -50 -40 -40 -30 -40 -50|0123232323232323232323245656565787878787878787878567|-1Pc2X.b 1jUnX.b WCL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 3y0 19f0 1cK0 1cL0 1cN0 1cL0 1cN0 1cL0 1cM0 1cL0 1fB0 3Nz0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 An0 Os0 WM0|11e5", + "Asia/Tehran|LMT TMT IRST IRST IRDT IRDT|-3p.I -3p.I -3u -40 -50 -4u|01234325252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252|-2btDp.I 1d3c0 1huLT.I TXu 1pz0 sN0 vAu 1cL0 1dB0 1en0 pNB0 UL0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 64p0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0|14e6", + "Asia/Thimphu|LMT IST BTT|-5W.A -5u -60|012|-Su5W.A 1BGMs.A|79e3", + "Asia/Tokyo|JCST JST JDT|-90 -90 -a0|0121212121|-1iw90 pKq0 QL0 1lB0 13X0 1zB0 NX0 1zB0 NX0|38e6", + "Asia/Ulaanbaatar|LMT ULAT ULAT ULAST|-77.w -70 -80 -90|012323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-2APH7.w 2Uko7.w cKn0 1db0 1dd0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1fB0 1cL0 1cN0 1cL0 1cN0 1cL0 6hD0 11z0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 kEp0 1cJ0 1cP0 1cJ0 1cP0 1fx0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1fx0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1fx0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1fx0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0|12e5", + "Asia/Ust-Nera|LMT YAKT YAKT MAGST MAGT MAGST MAGT MAGT VLAT VLAT|-9w.S -80 -90 -c0 -b0 -b0 -a0 -c0 -b0 -a0|0123434343434343434343456434343434343434343434343434343434343434789|-21Q9w.S pApw.S 23CL0 1d90 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 IM0 rU0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 17V0 7zD0|65e2", + "Asia/Vladivostok|LMT VLAT VLAT VLAST VLAST VLAT|-8L.v -90 -a0 -b0 -a0 -b0|012323232323232323232324123232323232323232323232323232323232323252|-1SJIL.v itXL.v 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 IM0 rU0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|60e4", + "Asia/Yakutsk|LMT YAKT YAKT YAKST YAKST YAKT|-8C.W -80 -90 -a0 -90 -a0|012323232323232323232324123232323232323232323232323232323232323252|-21Q8C.W pAoC.W 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 IM0 rU0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|28e4", + "Asia/Yekaterinburg|LMT PMT SVET SVET SVEST SVEST YEKT YEKST YEKT|-42.x -3J.5 -40 -50 -60 -50 -50 -60 -60|0123434343434343434343435267676767676767676767676767676767676767686|-2ag42.x 7mQh.s qBvJ.5 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 IM0 rU0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|14e5", + "Asia/Yerevan|LMT YERT YERT YERST YERST AMST AMT AMT AMST|-2W -30 -40 -50 -40 -40 -30 -40 -50|0123232323232323232323245656565657878787878787878787878787878787|-1Pc2W 1jUnW WCL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1am0 2r0 1cJ0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 3Fb0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0|13e5", + "Atlantic/Azores|HMT AZOT AZOST AZOMT AZOT AZOST WET|1S.w 20 10 0 10 0 0|01212121212121212121212121212121212121212121232123212321232121212121212121212121212121212121212121454545454545454545454545454545456545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454|-2ldW5.s aPX5.s Sp0 LX0 1vc0 Tc0 1uM0 SM0 1vc0 Tc0 1vc0 SM0 1vc0 6600 1co0 3E00 17c0 1fA0 1a00 1io0 1a00 1io0 17c0 3I00 17c0 1cM0 1cM0 3Fc0 1cM0 1a00 1fA0 1io0 17c0 1cM0 1cM0 1a00 1fA0 1io0 1qM0 Dc0 1tA0 1cM0 1dc0 1400 gL0 IM0 s10 U00 dX0 Rc0 pd0 Rc0 gL0 Oo0 pd0 Rc0 gL0 Oo0 pd0 14o0 1cM0 1cP0 1cM0 1cM0 1cM0 1cM0 1cM0 3Co0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 qIl0 1cM0 1fA0 1cM0 1cM0 1cN0 1cL0 1cN0 1cM0 1cM0 1cM0 1cM0 1cN0 1cL0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cL0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|25e4", + "Atlantic/Bermuda|LMT AST ADT|4j.i 40 30|0121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-1BnRE.G 1LTbE.G 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|65e3", + "Atlantic/Canary|LMT CANT WET WEST|11.A 10 0 -10|01232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-1UtaW.o XPAW.o 1lAK0 1a10 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|54e4", + "Atlantic/Cape_Verde|LMT CVT CVST CVT|1y.4 20 10 10|01213|-2xomp.U 1qOMp.U 7zX0 1djf0|50e4", + "Atlantic/Faroe|LMT WET WEST|r.4 0 -10|01212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2uSnw.U 2Wgow.U 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|49e3", + "Atlantic/Madeira|FMT MADT MADST MADMT WET WEST|17.A 10 0 -10 0 -10|01212121212121212121212121212121212121212121232123212321232121212121212121212121212121212121212121454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454|-2ldWQ.o aPWQ.o Sp0 LX0 1vc0 Tc0 1uM0 SM0 1vc0 Tc0 1vc0 SM0 1vc0 6600 1co0 3E00 17c0 1fA0 1a00 1io0 1a00 1io0 17c0 3I00 17c0 1cM0 1cM0 3Fc0 1cM0 1a00 1fA0 1io0 17c0 1cM0 1cM0 1a00 1fA0 1io0 1qM0 Dc0 1tA0 1cM0 1dc0 1400 gL0 IM0 s10 U00 dX0 Rc0 pd0 Rc0 gL0 Oo0 pd0 Rc0 gL0 Oo0 pd0 14o0 1cM0 1cP0 1cM0 1cM0 1cM0 1cM0 1cM0 3Co0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 qIl0 1cM0 1fA0 1cM0 1cM0 1cN0 1cL0 1cN0 1cM0 1cM0 1cM0 1cM0 1cN0 1cL0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|27e4", + "Atlantic/Reykjavik|LMT IST ISST GMT|1s 10 0 0|012121212121212121212121212121212121212121212121212121212121212121213|-2uWmw mfaw 1Bd0 ML0 1LB0 Cn0 1LB0 3fX0 C10 HrX0 1cO0 LB0 1EL0 LA0 1C00 Oo0 1wo0 Rc0 1wo0 Rc0 1wo0 Rc0 1zc0 Oo0 1zc0 14o0 1lc0 14o0 1lc0 14o0 1o00 11A0 1lc0 14o0 1o00 14o0 1lc0 14o0 1lc0 14o0 1lc0 14o0 1lc0 14o0 1o00 14o0 1lc0 14o0 1lc0 14o0 1lc0 14o0 1lc0 14o0 1lc0 14o0 1o00 14o0 1lc0 14o0 1lc0 14o0 1lc0 14o0 1lc0 14o0 1o00 14o0|12e4", + "Atlantic/South_Georgia|GST|20|0||30", + "Atlantic/Stanley|SMT FKT FKST FKT FKST|3P.o 40 30 30 20|0121212121212134343212121212121212121212121212121212121212121212121212|-2kJw8.A 12bA8.A 19X0 1fB0 19X0 1ip0 19X0 1fB0 19X0 1fB0 19X0 1fB0 Cn0 1Cc10 WL0 1qL0 U10 1tz0 U10 1qM0 WN0 1qL0 WN0 1qL0 WN0 1qL0 WN0 1tz0 U10 1tz0 WN0 1qL0 WN0 1qL0 WN0 1qL0 WN0 1qL0 WN0 1tz0 WN0 1qL0 WN0 1qL0 WN0 1qL0 WN0 1qL0 WN0 1qN0 U10 1wn0 Rd0 1wn0 U10 1tz0 U10 1tz0 U10 1tz0 U10 1tz0 U10 1wn0 U10 1tz0 U10 1tz0 U10|21e2", + "Australia/Sydney|AEST AEDT|-a0 -b0|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101|-293lX xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 14o0 1o00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 U00 1qM0 WM0 1tA0 WM0 1tA0 U00 1tA0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 11A0 1o00 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 WM0 1qM0 14o0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|40e5", + "Australia/Adelaide|ACST ACDT|-9u -au|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101|-293lt xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 U00 1qM0 WM0 1tA0 WM0 1tA0 U00 1tA0 U00 1tA0 Oo0 1zc0 WM0 1qM0 Rc0 1zc0 U00 1tA0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 WM0 1qM0 14o0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|11e5", + "Australia/Brisbane|AEST AEDT|-a0 -b0|01010101010101010|-293lX xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 H1A0 Oo0 1zc0 Oo0 1zc0 Oo0|20e5", + "Australia/Broken_Hill|ACST ACDT|-9u -au|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101|-293lt xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 14o0 1o00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 U00 1qM0 WM0 1tA0 WM0 1tA0 U00 1tA0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 WM0 1qM0 14o0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|18e3", + "Australia/Currie|AEST AEDT|-a0 -b0|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101|-29E80 19X0 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 11A0 1qM0 WM0 1qM0 Oo0 1zc0 Oo0 1zc0 Oo0 1wo0 WM0 1tA0 WM0 1tA0 U00 1tA0 U00 1tA0 11A0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 11A0 1o00 1io0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1cM0 1a00 1io0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|746", + "Australia/Darwin|ACST ACDT|-9u -au|010101010|-293lt xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0|12e4", + "Australia/Eucla|ACWST ACWDT|-8J -9J|0101010101010101010|-293kI xcX 10jd0 yL0 1cN0 1cL0 1gSp0 Oo0 l5A0 Oo0 iJA0 G00 zU00 IM0 1qM0 11A0 1o00 11A0|368", + "Australia/Hobart|AEST AEDT|-a0 -b0|010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101|-29E80 19X0 10jd0 yL0 1cN0 1cL0 1fB0 19X0 VfB0 1cM0 1o00 Rc0 1wo0 Rc0 1wo0 U00 1wo0 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 11A0 1qM0 WM0 1qM0 Oo0 1zc0 Oo0 1zc0 Oo0 1wo0 WM0 1tA0 WM0 1tA0 U00 1tA0 U00 1tA0 11A0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 11A0 1o00 1io0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1cM0 1a00 1io0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|21e4", + "Australia/Lord_Howe|AEST LHST LHDT LHDT|-a0 -au -bu -b0|0121212121313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313|raC0 1zdu Rb0 1zd0 On0 1zd0 On0 1zd0 On0 1zd0 TXu 1qMu WLu 1tAu WLu 1tAu TXu 1tAu Onu 1zcu Onu 1zcu Onu 1zcu Rbu 1zcu Onu 1zcu Onu 1zcu 11zu 1o0u 11zu 1o0u 11zu 1o0u 11zu 1qMu WLu 11Au 1nXu 1qMu 11zu 1o0u 11zu 1o0u 11zu 1qMu WLu 1qMu 11zu 1o0u WLu 1qMu 14nu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1fAu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1fAu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1fzu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1fAu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1fAu 1cLu 1cMu 1cLu 1cMu|347", + "Australia/Lindeman|AEST AEDT|-a0 -b0|010101010101010101010|-293lX xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 H1A0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0|10", + "Australia/Melbourne|AEST AEDT|-a0 -b0|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101|-293lX xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 U00 1qM0 WM0 1qM0 11A0 1tA0 U00 1tA0 U00 1tA0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 11A0 1o00 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 WM0 1qM0 14o0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|39e5", + "Australia/Perth|AWST AWDT|-80 -90|0101010101010101010|-293jX xcX 10jd0 yL0 1cN0 1cL0 1gSp0 Oo0 l5A0 Oo0 iJA0 G00 zU00 IM0 1qM0 11A0 1o00 11A0|18e5", + "CET|CET CEST|-10 -20|01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2aFe0 11d0 1iO0 11A0 1o00 11A0 Qrc0 6i00 WM0 1fA0 1cM0 1cM0 1cM0 16M0 1gMM0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00", + "CST6CDT|CST CDT CWT CPT|60 50 50 50|010102301010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 QwN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0", + "Pacific/Easter|EMT EAST EASST EAST EASST EAST|7h.s 70 60 60 50 50|012121212121212121212121212123434343434343434343434343434343434343434343434343434343434343434345|-1uSgG.w 1s4IG.w WL0 1zd0 On0 1ip0 11z0 1o10 11z0 1qN0 WL0 1ld0 14n0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 WL0 1qN0 1cL0 1cN0 11z0 1o10 11z0 1qN0 WL0 1fB0 19X0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 17b0 1ip0 11z0 1ip0 1fz0 1fB0 11z0 1qN0 WL0 1qN0 WL0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 17b0 1ip0 11z0 1o10 19X0 1fB0 1nX0 G10 1EL0 Op0 1zb0 Rd0 1wn0 Rd0 1wn0|30e2", + "EET|EET EEST|-20 -30|010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|hDB0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00", + "EST|EST|50|0|", + "EST5EDT|EST EDT EWT EPT|50 40 40 40|010102301010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-261t0 1nX0 11B0 1nX0 SgN0 8x40 iv0 QwN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0", + "Europe/Dublin|DMT IST GMT BST IST|p.l -y.D 0 -10 -10|01232323232324242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242|-2ax9y.D Rc0 1fzy.D 14M0 1fc0 1g00 1co0 1dc0 1co0 1oo0 1400 1dc0 19A0 1io0 1io0 WM0 1o00 14o0 1o00 17c0 1io0 17c0 1fA0 1a00 1lc0 17c0 1io0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1cM0 1io0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1a00 1io0 1qM0 Dc0 g5X0 14p0 1wn0 17d0 1io0 11A0 1o00 17c0 1fA0 1a00 1fA0 1cM0 1fA0 1a00 17c0 1fA0 1a00 1io0 17c0 1lc0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1a00 1a00 1qM0 WM0 1qM0 11A0 1o00 WM0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1tA0 IM0 90o0 U00 1tA0 U00 1tA0 U00 1tA0 U00 1tA0 WM0 1qM0 WM0 1qM0 WM0 1tA0 U00 1tA0 U00 1tA0 11z0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 14o0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|12e5", + "Etc/GMT+0|GMT|0|0|", + "Etc/GMT+1|GMT+1|10|0|", + "Etc/GMT+10|GMT+10|a0|0|", + "Etc/GMT+11|GMT+11|b0|0|", + "Etc/GMT+12|GMT+12|c0|0|", + "Etc/GMT+2|GMT+2|20|0|", + "Etc/GMT+3|GMT+3|30|0|", + "Etc/GMT+4|GMT+4|40|0|", + "Etc/GMT+5|GMT+5|50|0|", + "Etc/GMT+6|GMT+6|60|0|", + "Etc/GMT+7|GMT+7|70|0|", + "Etc/GMT+8|GMT+8|80|0|", + "Etc/GMT+9|GMT+9|90|0|", + "Etc/GMT-1|GMT-1|-10|0|", + "Etc/GMT-10|GMT-10|-a0|0|", + "Etc/GMT-11|GMT-11|-b0|0|", + "Etc/GMT-12|GMT-12|-c0|0|", + "Etc/GMT-13|GMT-13|-d0|0|", + "Etc/GMT-14|GMT-14|-e0|0|", + "Etc/GMT-2|GMT-2|-20|0|", + "Etc/GMT-3|GMT-3|-30|0|", + "Etc/GMT-4|GMT-4|-40|0|", + "Etc/GMT-5|GMT-5|-50|0|", + "Etc/GMT-6|GMT-6|-60|0|", + "Etc/GMT-7|GMT-7|-70|0|", + "Etc/GMT-8|GMT-8|-80|0|", + "Etc/GMT-9|GMT-9|-90|0|", + "Etc/UCT|UCT|0|0|", + "Etc/UTC|UTC|0|0|", + "Europe/Amsterdam|AMT NST NEST NET CEST CET|-j.w -1j.w -1k -k -20 -10|010101010101010101010101010101010101010101012323234545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545|-2aFcj.w 11b0 1iP0 11A0 1io0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1co0 1io0 1yo0 Pc0 1a00 1fA0 1Bc0 Mo0 1tc0 Uo0 1tA0 U00 1uo0 W00 1s00 VA0 1so0 Vc0 1sM0 UM0 1wo0 Rc0 1u00 Wo0 1rA0 W00 1s00 VA0 1sM0 UM0 1w00 fV0 BCX.w 1tA0 U00 1u00 Wo0 1sm0 601k WM0 1fA0 1cM0 1cM0 1cM0 16M0 1gMM0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|16e5", + "Europe/Andorra|WET CET CEST|0 -10 -20|012121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-UBA0 1xIN0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|79e3", + "Europe/Athens|AMT EET EEST CEST CET|-1y.Q -20 -30 -20 -10|012123434121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2a61x.Q CNbx.Q mn0 kU10 9b0 3Es0 Xa0 1fb0 1dd0 k3X0 Nz0 SCp0 1vc0 SO0 1cM0 1a00 1ao0 1fc0 1a10 1fG0 1cg0 1dX0 1bX0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|35e5", + "Europe/London|GMT BST BDST|0 -10 -20|0101010101010101010101010101010101010101010101010121212121210101210101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2axa0 Rc0 1fA0 14M0 1fc0 1g00 1co0 1dc0 1co0 1oo0 1400 1dc0 19A0 1io0 1io0 WM0 1o00 14o0 1o00 17c0 1io0 17c0 1fA0 1a00 1lc0 17c0 1io0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1cM0 1io0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1a00 1io0 1qM0 Dc0 2Rz0 Dc0 1zc0 Oo0 1zc0 Rc0 1wo0 17c0 1iM0 FA0 xB0 1fA0 1a00 14o0 bb0 LA0 xB0 Rc0 1wo0 11A0 1o00 17c0 1fA0 1a00 1fA0 1cM0 1fA0 1a00 17c0 1fA0 1a00 1io0 17c0 1lc0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1a00 1a00 1qM0 WM0 1qM0 11A0 1o00 WM0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1tA0 IM0 90o0 U00 1tA0 U00 1tA0 U00 1tA0 U00 1tA0 WM0 1qM0 WM0 1qM0 WM0 1tA0 U00 1tA0 U00 1tA0 11z0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 14o0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|10e6", + "Europe/Belgrade|CET CEST|-10 -20|01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-19RC0 3IP0 WM0 1fA0 1cM0 1cM0 1rc0 Qo0 1vmo0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|12e5", + "Europe/Berlin|CET CEST CEMT|-10 -20 -30|01010101010101210101210101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2aFe0 11d0 1iO0 11A0 1o00 11A0 Qrc0 6i00 WM0 1fA0 1cM0 1cM0 1cM0 kL0 Nc0 m10 WM0 1ao0 1cp0 dX0 jz0 Dd0 1io0 17c0 1fA0 1a00 1ehA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|41e5", + "Europe/Prague|CET CEST|-10 -20|010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2aFe0 11d0 1iO0 11A0 1o00 11A0 Qrc0 6i00 WM0 1fA0 1cM0 16M0 1lc0 1tA0 17A0 11c0 1io0 17c0 1io0 17c0 1fc0 1ao0 1bNc0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|13e5", + "Europe/Brussels|WET CET CEST WEST|0 -10 -20 -10|0121212103030303030303030303030303030303030303030303212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2ehc0 3zX0 11c0 1iO0 11A0 1o00 11A0 my0 Ic0 1qM0 Rc0 1EM0 UM0 1u00 10o0 1io0 1io0 17c0 1a00 1fA0 1cM0 1cM0 1io0 17c0 1fA0 1a00 1io0 1a30 1io0 17c0 1fA0 1a00 1io0 17c0 1cM0 1cM0 1a00 1io0 1cM0 1cM0 1a00 1fA0 1io0 17c0 1cM0 1cM0 1a00 1fA0 1io0 1qM0 Dc0 y00 5Wn0 WM0 1fA0 1cM0 16M0 1iM0 16M0 1C00 Uo0 1eeo0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|21e5", + "Europe/Bucharest|BMT EET EEST|-1I.o -20 -30|0121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-1xApI.o 20LI.o RA0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1Axc0 On0 1fA0 1a10 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cK0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cL0 1cN0 1cL0 1fB0 1nX0 11E0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|19e5", + "Europe/Budapest|CET CEST|-10 -20|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2aFe0 11d0 1iO0 11A0 1ip0 17b0 1op0 1tb0 Q2m0 3Ne0 WM0 1fA0 1cM0 1cM0 1oJ0 1dc0 1030 1fA0 1cM0 1cM0 1cM0 1cM0 1fA0 1a00 1iM0 1fA0 8Ha0 Rb0 1wN0 Rb0 1BB0 Lz0 1C20 LB0 SNX0 1a10 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|17e5", + "Europe/Zurich|CET CEST|-10 -20|01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-19Lc0 11A0 1o00 11A0 1xG10 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|38e4", + "Europe/Chisinau|CMT BMT EET EEST CEST CET MSK MSD|-1T -1I.o -20 -30 -20 -10 -30 -40|0123232323232323232345454676767676767676767623232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-26jdT wGMa.A 20LI.o RA0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 27A0 2en0 39g0 WM0 1fA0 1cM0 V90 1t7z0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1ty0 2bD0 1cM0 1cK0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1fB0 1nX0 11D0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|67e4", + "Europe/Copenhagen|CET CEST|-10 -20|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2azC0 Tz0 VuO0 60q0 WM0 1fA0 1cM0 1cM0 1cM0 S00 1HA0 Nc0 1C00 Dc0 1Nc0 Ao0 1h5A0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|12e5", + "Europe/Gibraltar|GMT BST BDST CET CEST|0 -10 -20 -10 -20|010101010101010101010101010101010101010101010101012121212121010121010101010101010101034343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343|-2axa0 Rc0 1fA0 14M0 1fc0 1g00 1co0 1dc0 1co0 1oo0 1400 1dc0 19A0 1io0 1io0 WM0 1o00 14o0 1o00 17c0 1io0 17c0 1fA0 1a00 1lc0 17c0 1io0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1cM0 1io0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1a00 1io0 1qM0 Dc0 2Rz0 Dc0 1zc0 Oo0 1zc0 Rc0 1wo0 17c0 1iM0 FA0 xB0 1fA0 1a00 14o0 bb0 LA0 xB0 Rc0 1wo0 11A0 1o00 17c0 1fA0 1a00 1fA0 1cM0 1fA0 1a00 17c0 1fA0 1a00 1io0 17c0 1lc0 17c0 1fA0 10Jz0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|30e3", + "Europe/Helsinki|HMT EET EEST|-1D.N -20 -30|0121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-1WuND.N OULD.N 1dA0 1xGq0 1cM0 1cM0 1cM0 1cN0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|12e5", + "Europe/Kaliningrad|CET CEST CET CEST MSK MSD EEST EET FET|-10 -20 -20 -30 -30 -40 -30 -20 -30|0101010101010232454545454545454545454676767676767676767676767676767676767676787|-2aFe0 11d0 1iO0 11A0 1o00 11A0 Qrc0 6i00 WM0 1fA0 1cM0 1cM0 Am0 Lb0 1en0 op0 1pNz0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 1cJ0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|44e4", + "Europe/Kiev|KMT EET MSK CEST CET MSD EEST|-22.4 -20 -30 -20 -10 -40 -30|0123434252525252525252525256161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161|-1Pc22.4 eUo2.4 rnz0 2Hg0 WM0 1fA0 da0 1v4m0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 Db0 3220 1cK0 1cL0 1cN0 1cL0 1cN0 1cL0 1cQ0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|34e5", + "Europe/Lisbon|LMT WET WEST WEMT CET CEST|A.J 0 -10 -20 -10 -20|012121212121212121212121212121212121212121212321232123212321212121212121212121212121212121212121214121212121212121212121212121212124545454212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2ldXn.f aPWn.f Sp0 LX0 1vc0 Tc0 1uM0 SM0 1vc0 Tc0 1vc0 SM0 1vc0 6600 1co0 3E00 17c0 1fA0 1a00 1io0 1a00 1io0 17c0 3I00 17c0 1cM0 1cM0 3Fc0 1cM0 1a00 1fA0 1io0 17c0 1cM0 1cM0 1a00 1fA0 1io0 1qM0 Dc0 1tA0 1cM0 1dc0 1400 gL0 IM0 s10 U00 dX0 Rc0 pd0 Rc0 gL0 Oo0 pd0 Rc0 gL0 Oo0 pd0 14o0 1cM0 1cP0 1cM0 1cM0 1cM0 1cM0 1cM0 3Co0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 pvy0 1cM0 1cM0 1fA0 1cM0 1cM0 1cN0 1cL0 1cN0 1cM0 1cM0 1cM0 1cM0 1cN0 1cL0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|27e5", + "Europe/Luxembourg|LMT CET CEST WET WEST WEST WET|-o.A -10 -20 0 -10 -20 -10|0121212134343434343434343434343434343434343434343434565651212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2DG0o.A t6mo.A TB0 1nX0 Up0 1o20 11A0 rW0 CM0 1qP0 R90 1EO0 UK0 1u20 10m0 1ip0 1in0 17e0 19W0 1fB0 1db0 1cp0 1in0 17d0 1fz0 1a10 1in0 1a10 1in0 17f0 1fA0 1a00 1io0 17c0 1cM0 1cM0 1a00 1io0 1cM0 1cM0 1a00 1fA0 1io0 17c0 1cM0 1cM0 1a00 1fA0 1io0 1qM0 Dc0 vA0 60L0 WM0 1fA0 1cM0 17c0 1io0 16M0 1C00 Uo0 1eeo0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|54e4", + "Europe/Madrid|WET WEST WEMT CET CEST|0 -10 -20 -10 -20|01010101010101010101010121212121234343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343|-28dd0 11A0 1go0 19A0 1co0 1dA0 b1A0 18o0 3I00 17c0 1fA0 1a00 1io0 1a00 1io0 17c0 iyo0 Rc0 18o0 1hc0 1io0 1a00 14o0 5aL0 MM0 1vc0 17A0 1i00 1bc0 1eo0 17d0 1in0 17A0 6hA0 10N0 XIL0 1a10 1in0 17d0 19X0 1cN0 1fz0 1a10 1fX0 1cp0 1cO0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|62e5", + "Europe/Malta|CET CEST|-10 -20|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2as10 M00 1cM0 1cM0 14o0 1o00 WM0 1qM0 17c0 1cM0 M3A0 5M20 WM0 1fA0 1cM0 1cM0 1cM0 16m0 1de0 1lc0 14m0 1lc0 WO0 1qM0 GTW0 On0 1C10 Lz0 1C10 Lz0 1EN0 Lz0 1C10 Lz0 1zd0 Oo0 1C00 On0 1cp0 1cM0 1lA0 Xc0 1qq0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1iN0 19z0 1fB0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|42e4", + "Europe/Minsk|MMT EET MSK CEST CET MSD EEST FET|-1O -20 -30 -20 -10 -40 -30 -30|012343432525252525252525252616161616161616161616161616161616161616172|-1Pc1O eUnO qNX0 3gQ0 WM0 1fA0 1cM0 Al0 1tsn0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 3Fc0 1cN0 1cK0 1cM0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hy0|19e5", + "Europe/Monaco|PMT WET WEST WEMT CET CEST|-9.l 0 -10 -20 -10 -20|01212121212121212121212121212121212121212121212121232323232345454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454|-2nco9.l cNb9.l HA0 19A0 1iM0 11c0 1oo0 Wo0 1rc0 QM0 1EM0 UM0 1u00 10o0 1io0 1wo0 Rc0 1a00 1fA0 1cM0 1cM0 1io0 17c0 1fA0 1a00 1io0 1a00 1io0 17c0 1fA0 1a00 1io0 17c0 1cM0 1cM0 1a00 1io0 1cM0 1cM0 1a00 1fA0 1io0 17c0 1cM0 1cM0 1a00 1fA0 1io0 1qM0 Df0 2RV0 11z0 11B0 1ze0 WM0 1fA0 1cM0 1fa0 1aq0 16M0 1ekn0 1cL0 1fC0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|38e3", + "Europe/Moscow|MMT MMT MST MDST MSD MSK MSM EET EEST MSK|-2u.h -2v.j -3v.j -4v.j -40 -30 -50 -20 -30 -40|012132345464575454545454545454545458754545454545454545454545454545454545454595|-2ag2u.h 2pyW.W 1bA0 11X0 GN0 1Hb0 c20 imv.j 3DA0 dz0 15A0 c10 2q10 iM10 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 IM0 rU0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|16e6", + "Europe/Paris|PMT WET WEST CEST CET WEMT|-9.l 0 -10 -20 -10 -20|0121212121212121212121212121212121212121212121212123434352543434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434|-2nco8.l cNb8.l HA0 19A0 1iM0 11c0 1oo0 Wo0 1rc0 QM0 1EM0 UM0 1u00 10o0 1io0 1wo0 Rc0 1a00 1fA0 1cM0 1cM0 1io0 17c0 1fA0 1a00 1io0 1a00 1io0 17c0 1fA0 1a00 1io0 17c0 1cM0 1cM0 1a00 1io0 1cM0 1cM0 1a00 1fA0 1io0 17c0 1cM0 1cM0 1a00 1fA0 1io0 1qM0 Df0 Ik0 5M30 WM0 1fA0 1cM0 Vx0 hB0 1aq0 16M0 1ekn0 1cL0 1fC0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|11e6", + "Europe/Riga|RMT LST EET MSK CEST CET MSD EEST|-1A.y -2A.y -20 -30 -20 -10 -40 -30|010102345454536363636363636363727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272|-25TzA.y 11A0 1iM0 ko0 gWm0 yDXA.y 2bX0 3fE0 WM0 1fA0 1cM0 1cM0 4m0 1sLy0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cN0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 1o00 11A0 1o00 11A0 1qM0 3oo0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|64e4", + "Europe/Rome|CET CEST|-10 -20|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2as10 M00 1cM0 1cM0 14o0 1o00 WM0 1qM0 17c0 1cM0 M3A0 5M20 WM0 1fA0 1cM0 16K0 1iO0 16m0 1de0 1lc0 14m0 1lc0 WO0 1qM0 GTW0 On0 1C10 Lz0 1C10 Lz0 1EN0 Lz0 1C10 Lz0 1zd0 Oo0 1C00 On0 1C10 Lz0 1zd0 On0 1C10 LA0 1C00 LA0 1zc0 Oo0 1C00 Oo0 1zc0 Oo0 1fC0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|39e5", + "Europe/Samara|LMT SAMT SAMT KUYT KUYST MSD MSK EEST KUYT SAMST SAMST|-3k.k -30 -40 -40 -50 -40 -30 -30 -30 -50 -40|012343434343434343435656782929292929292929292929292929292929292a12|-22WNk.k qHak.k bcn0 1Qqo0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cN0 1cM0 1fA0 1cM0 1cN0 8o0 14j0 1cL0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qN0 WM0|12e5", + "Europe/Simferopol|SMT EET MSK CEST CET MSD EEST MSK|-2g -20 -30 -20 -10 -40 -30 -40|012343432525252525252525252161616525252616161616161616161616161616161616172|-1Pc2g eUog rEn0 2qs0 WM0 1fA0 1cM0 3V0 1u0L0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1Q00 4eL0 1cL0 1cN0 1cL0 1cN0 dX0 WL0 1cN0 1cL0 1fB0 1o30 11B0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11z0 1nW0|33e4", + "Europe/Sofia|EET CET CEST EEST|-20 -10 -20 -30|01212103030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030|-168L0 WM0 1fA0 1cM0 1cM0 1cN0 1mKH0 1dd0 1fb0 1ap0 1fb0 1a20 1fy0 1a30 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cK0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1fB0 1nX0 11E0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|12e5", + "Europe/Stockholm|CET CEST|-10 -20|01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2azC0 TB0 2yDe0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|15e5", + "Europe/Tallinn|TMT CET CEST EET MSK MSD EEST|-1D -10 -20 -20 -30 -40 -30|012103421212454545454545454546363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363|-26oND teD 11A0 1Ta0 4rXl KSLD 2FX0 2Jg0 WM0 1fA0 1cM0 18J0 1sTX0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cN0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o10 11A0 1qM0 5QM0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|41e4", + "Europe/Tirane|LMT CET CEST|-1j.k -10 -20|01212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2glBj.k 14pcj.k 5LC0 WM0 4M0 1fCK0 10n0 1op0 11z0 1pd0 11z0 1qN0 WL0 1qp0 Xb0 1qp0 Xb0 1qp0 11z0 1lB0 11z0 1qN0 11z0 1iN0 16n0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|42e4", + "Europe/Uzhgorod|CET CEST MSK MSD EET EEST|-10 -20 -30 -40 -20 -30|010101023232323232323232320454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454|-1cqL0 6i00 WM0 1fA0 1cM0 1ml0 1Cp0 1r3W0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1Q00 1Nf0 2pw0 1cL0 1cN0 1cL0 1cN0 1cL0 1cQ0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|11e4", + "Europe/Vienna|CET CEST|-10 -20|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2aFe0 11d0 1iO0 11A0 1o00 11A0 3KM0 14o0 LA00 6i00 WM0 1fA0 1cM0 1cM0 1cM0 400 2qM0 1a00 1cM0 1cM0 1io0 17c0 1gHa0 19X0 1cP0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|18e5", + "Europe/Vilnius|WMT KMT CET EET MSK CEST MSD EEST|-1o -1z.A -10 -20 -30 -20 -40 -30|012324525254646464646464646464647373737373737352537373737373737373737373737373737373737373737373737373737373737373737373|-293do 6ILM.o 1Ooz.A zz0 Mfd0 29W0 3is0 WM0 1fA0 1cM0 LV0 1tgL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11B0 1o00 11A0 1qM0 8io0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|54e4", + "Europe/Volgograd|LMT TSAT STAT STAT VOLT VOLST VOLST VOLT MSD MSK MSK|-2V.E -30 -30 -40 -40 -50 -40 -30 -40 -30 -40|0123454545454545454546767489898989898989898989898989898989898989a9|-21IqV.E cLXV.E cEM0 1gqn0 Lco0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cN0 1cM0 1fA0 1cM0 2pz0 1cJ0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|10e5", + "Europe/Warsaw|WMT CET CEST EET EEST|-1o -10 -20 -20 -30|012121234312121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2ctdo 1LXo 11d0 1iO0 11A0 1o00 11A0 1on0 11A0 6zy0 HWP0 5IM0 WM0 1fA0 1cM0 1dz0 1mL0 1en0 15B0 1aq0 1nA0 11A0 1io0 17c0 1fA0 1a00 iDX0 LA0 1cM0 1cM0 1C00 Oo0 1cM0 1cM0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1C00 LA0 uso0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cN0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|17e5", + "Europe/Zaporozhye|CUT EET MSK CEST CET MSD EEST|-2k -20 -30 -20 -10 -40 -30|01234342525252525252525252526161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161|-1Pc2k eUok rdb0 2RE0 WM0 1fA0 8m0 1v9a0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cK0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cQ0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|77e4", + "HST|HST|a0|0|", + "Indian/Chagos|LMT IOT IOT|-4N.E -50 -60|012|-2xosN.E 3AGLN.E|30e2", + "Indian/Christmas|CXT|-70|0||21e2", + "Indian/Cocos|CCT|-6u|0||596", + "Indian/Kerguelen|zzz TFT|0 -50|01|-MG00|130", + "Indian/Mahe|LMT SCT|-3F.M -40|01|-2yO3F.M|79e3", + "Indian/Maldives|MMT MVT|-4S -50|01|-olgS|35e4", + "Indian/Mauritius|LMT MUT MUST|-3O -40 -50|012121|-2xorO 34unO 14L0 12kr0 11z0|15e4", + "Indian/Reunion|LMT RET|-3F.Q -40|01|-2mDDF.Q|84e4", + "Pacific/Kwajalein|MHT KWAT MHT|-b0 c0 -c0|012|-AX0 W9X0|14e3", + "MET|MET MEST|-10 -20|01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2aFe0 11d0 1iO0 11A0 1o00 11A0 Qrc0 6i00 WM0 1fA0 1cM0 1cM0 1cM0 16M0 1gMM0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00", + "MST|MST|70|0|", + "MST7MDT|MST MDT MWT MPT|70 60 60 60|010102301010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-261r0 1nX0 11B0 1nX0 SgN0 8x20 ix0 QwN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0", + "Pacific/Chatham|CHAST CHAST CHADT|-cf -cJ -dJ|012121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212|-WqAf 1adef IM0 1C00 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1qM0 14o0 1lc0 14o0 1lc0 14o0 1lc0 17c0 1io0 17c0 1io0 17c0 1io0 17c0 1lc0 14o0 1lc0 14o0 1lc0 17c0 1io0 17c0 1io0 17c0 1lc0 14o0 1lc0 14o0 1lc0 17c0 1io0 17c0 1io0 17c0 1io0 17c0 1io0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1io0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00|600", + "PST8PDT|PST PDT PWT PPT|80 70 70 70|010102301010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-261q0 1nX0 11B0 1nX0 SgN0 8x10 iy0 QwN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0", + "Pacific/Apia|LMT WSST SST SDT WSDT WSST|bq.U bu b0 a0 -e0 -d0|01232345454545454545454545454545454545454545454545454545454|-2nDMx.4 1yW03.4 2rRbu 1ff0 1a00 CI0 AQ0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1io0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00|37e3", + "Pacific/Bougainville|PGT JST BST|-a0 -90 -b0|0102|-16Wy0 7CN0 2MQp0|18e4", + "Pacific/Chuuk|CHUT|-a0|0||49e3", + "Pacific/Efate|LMT VUT VUST|-bd.g -b0 -c0|0121212121212121212121|-2l9nd.g 2Szcd.g 1cL0 1oN0 10L0 1fB0 19X0 1fB0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1fB0 Lz0 1Nd0 An0|66e3", + "Pacific/Enderbury|PHOT PHOT PHOT|c0 b0 -d0|012|nIc0 B8n0|1", + "Pacific/Fakaofo|TKT TKT|b0 -d0|01|1Gfn0|483", + "Pacific/Fiji|LMT FJT FJST|-bT.I -c0 -d0|0121212121212121212121212121212121212121212121212121212121212121|-2bUzT.I 3m8NT.I LA0 1EM0 IM0 nJc0 LA0 1o00 Rc0 1wo0 Ao0 1Nc0 Ao0 1Q00 xz0 1SN0 uM0 1SM0 uM0 1VA0 s00 1VA0 uM0 1SM0 uM0 1SM0 uM0 1SM0 uM0 1VA0 s00 1VA0 s00 1VA0 uM0 1SM0 uM0 1SM0 uM0 1SM0 uM0 1VA0 s00 1VA0 uM0 1SM0 uM0 1SM0 uM0 1SM0 uM0 1VA0 s00 1VA0 s00 1VA0 uM0 1SM0 uM0 1SM0 uM0 1SM0 uM0|88e4", + "Pacific/Funafuti|TVT|-c0|0||45e2", + "Pacific/Galapagos|LMT ECT GALT|5W.o 50 60|012|-1yVS1.A 2dTz1.A|25e3", + "Pacific/Gambier|LMT GAMT|8X.M 90|01|-2jof0.c|125", + "Pacific/Guadalcanal|LMT SBT|-aD.M -b0|01|-2joyD.M|11e4", + "Pacific/Guam|GST ChST|-a0 -a0|01|1fpq0|17e4", + "Pacific/Honolulu|HST HDT HST|au 9u a0|010102|-1thLu 8x0 lef0 8Pz0 46p0|37e4", + "Pacific/Kiritimati|LINT LINT LINT|aE a0 -e0|012|nIaE B8nk|51e2", + "Pacific/Kosrae|KOST KOST|-b0 -c0|010|-AX0 1bdz0|66e2", + "Pacific/Majuro|MHT MHT|-b0 -c0|01|-AX0|28e3", + "Pacific/Marquesas|LMT MART|9i 9u|01|-2joeG|86e2", + "Pacific/Pago_Pago|LMT NST BST SST|bm.M b0 b0 b0|0123|-2nDMB.c 2gVzB.c EyM0|37e2", + "Pacific/Nauru|LMT NRT JST NRT|-b7.E -bu -90 -c0|01213|-1Xdn7.E PvzB.E 5RCu 1ouJu|10e3", + "Pacific/Niue|NUT NUT NUT|bk bu b0|012|-KfME 17y0a|12e2", + "Pacific/Norfolk|NMT NFT NFST NFT|-bc -bu -cu -b0|01213|-Kgbc W01G On0 1COp0|25e4", + "Pacific/Noumea|LMT NCT NCST|-b5.M -b0 -c0|01212121|-2l9n5.M 2EqM5.M xX0 1PB0 yn0 HeP0 Ao0|98e3", + "Pacific/Palau|PWT|-90|0||21e3", + "Pacific/Pitcairn|PNT PST|8u 80|01|18Vku|56", + "Pacific/Pohnpei|PONT|-b0|0||34e3", + "Pacific/Port_Moresby|PGT|-a0|0||25e4", + "Pacific/Rarotonga|CKT CKHST CKT|au 9u a0|012121212121212121212121212|lyWu IL0 1zcu Onu 1zcu Onu 1zcu Rbu 1zcu Onu 1zcu Onu 1zcu Onu 1zcu Onu 1zcu Onu 1zcu Rbu 1zcu Onu 1zcu Onu 1zcu Onu|13e3", + "Pacific/Tahiti|LMT TAHT|9W.g a0|01|-2joe1.I|18e4", + "Pacific/Tarawa|GILT|-c0|0||29e3", + "Pacific/Tongatapu|TOT TOT TOST|-ck -d0 -e0|01212121|-1aB0k 2n5dk 15A0 1wo0 xz0 1Q10 xz0|75e3", + "Pacific/Wake|WAKT|-c0|0||16e3", + "Pacific/Wallis|WFT|-c0|0||94", + "WET|WET WEST|0 -10|010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|hDB0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00" + ], + "links": [ + "Africa/Abidjan|Africa/Bamako", + "Africa/Abidjan|Africa/Banjul", + "Africa/Abidjan|Africa/Conakry", + "Africa/Abidjan|Africa/Dakar", + "Africa/Abidjan|Africa/Freetown", + "Africa/Abidjan|Africa/Lome", + "Africa/Abidjan|Africa/Nouakchott", + "Africa/Abidjan|Africa/Ouagadougou", + "Africa/Abidjan|Africa/Sao_Tome", + "Africa/Abidjan|Africa/Timbuktu", + "Africa/Abidjan|Atlantic/St_Helena", + "Africa/Cairo|Egypt", + "Africa/Johannesburg|Africa/Maseru", + "Africa/Johannesburg|Africa/Mbabane", + "Africa/Khartoum|Africa/Juba", + "Africa/Lagos|Africa/Bangui", + "Africa/Lagos|Africa/Brazzaville", + "Africa/Lagos|Africa/Douala", + "Africa/Lagos|Africa/Kinshasa", + "Africa/Lagos|Africa/Libreville", + "Africa/Lagos|Africa/Luanda", + "Africa/Lagos|Africa/Malabo", + "Africa/Lagos|Africa/Niamey", + "Africa/Lagos|Africa/Porto-Novo", + "Africa/Maputo|Africa/Blantyre", + "Africa/Maputo|Africa/Bujumbura", + "Africa/Maputo|Africa/Gaborone", + "Africa/Maputo|Africa/Harare", + "Africa/Maputo|Africa/Kigali", + "Africa/Maputo|Africa/Lubumbashi", + "Africa/Maputo|Africa/Lusaka", + "Africa/Nairobi|Africa/Addis_Ababa", + "Africa/Nairobi|Africa/Asmara", + "Africa/Nairobi|Africa/Asmera", + "Africa/Nairobi|Africa/Dar_es_Salaam", + "Africa/Nairobi|Africa/Djibouti", + "Africa/Nairobi|Africa/Kampala", + "Africa/Nairobi|Africa/Mogadishu", + "Africa/Nairobi|Indian/Antananarivo", + "Africa/Nairobi|Indian/Comoro", + "Africa/Nairobi|Indian/Mayotte", + "Africa/Tripoli|Libya", + "America/Adak|America/Atka", + "America/Adak|US/Aleutian", + "America/Anchorage|US/Alaska", + "America/Argentina/Buenos_Aires|America/Buenos_Aires", + "America/Argentina/Catamarca|America/Argentina/ComodRivadavia", + "America/Argentina/Catamarca|America/Catamarca", + "America/Argentina/Cordoba|America/Cordoba", + "America/Argentina/Cordoba|America/Rosario", + "America/Argentina/Jujuy|America/Jujuy", + "America/Argentina/Mendoza|America/Mendoza", + "America/Atikokan|America/Coral_Harbour", + "America/Chicago|US/Central", + "America/Curacao|America/Aruba", + "America/Curacao|America/Kralendijk", + "America/Curacao|America/Lower_Princes", + "America/Denver|America/Shiprock", + "America/Denver|Navajo", + "America/Denver|US/Mountain", + "America/Detroit|US/Michigan", + "America/Edmonton|Canada/Mountain", + "America/Fort_Wayne|America/Indiana/Indianapolis", + "America/Fort_Wayne|America/Indianapolis", + "America/Fort_Wayne|US/East-Indiana", + "America/Halifax|Canada/Atlantic", + "America/Havana|Cuba", + "America/Indiana/Knox|America/Knox_IN", + "America/Indiana/Knox|US/Indiana-Starke", + "America/Jamaica|Jamaica", + "America/Kentucky/Louisville|America/Louisville", + "America/Los_Angeles|US/Pacific", + "America/Los_Angeles|US/Pacific-New", + "America/Manaus|Brazil/West", + "America/Mazatlan|Mexico/BajaSur", + "America/Mexico_City|Mexico/General", + "America/New_York|US/Eastern", + "America/Noronha|Brazil/DeNoronha", + "America/Phoenix|US/Arizona", + "America/Port_of_Spain|America/Anguilla", + "America/Port_of_Spain|America/Antigua", + "America/Port_of_Spain|America/Dominica", + "America/Port_of_Spain|America/Grenada", + "America/Port_of_Spain|America/Guadeloupe", + "America/Port_of_Spain|America/Marigot", + "America/Port_of_Spain|America/Montserrat", + "America/Port_of_Spain|America/St_Barthelemy", + "America/Port_of_Spain|America/St_Kitts", + "America/Port_of_Spain|America/St_Lucia", + "America/Port_of_Spain|America/St_Thomas", + "America/Port_of_Spain|America/St_Vincent", + "America/Port_of_Spain|America/Tortola", + "America/Port_of_Spain|America/Virgin", + "America/Regina|Canada/East-Saskatchewan", + "America/Regina|Canada/Saskatchewan", + "America/Rio_Branco|America/Porto_Acre", + "America/Rio_Branco|Brazil/Acre", + "America/Santiago|Chile/Continental", + "America/Sao_Paulo|Brazil/East", + "America/St_Johns|Canada/Newfoundland", + "America/Tijuana|America/Ensenada", + "America/Tijuana|Mexico/BajaNorte", + "America/Toronto|America/Montreal", + "America/Toronto|Canada/Eastern", + "America/Vancouver|Canada/Pacific", + "America/Whitehorse|Canada/Yukon", + "America/Winnipeg|Canada/Central", + "Asia/Ashgabat|Asia/Ashkhabad", + "Asia/Bangkok|Asia/Phnom_Penh", + "Asia/Bangkok|Asia/Vientiane", + "Asia/Dhaka|Asia/Dacca", + "Asia/Dubai|Asia/Muscat", + "Asia/Ho_Chi_Minh|Asia/Saigon", + "Asia/Hong_Kong|Hongkong", + "Asia/Jerusalem|Asia/Tel_Aviv", + "Asia/Jerusalem|Israel", + "Asia/Kathmandu|Asia/Katmandu", + "Asia/Kolkata|Asia/Calcutta", + "Asia/Macau|Asia/Macao", + "Asia/Makassar|Asia/Ujung_Pandang", + "Asia/Nicosia|Europe/Nicosia", + "Asia/Qatar|Asia/Bahrain", + "Asia/Riyadh|Asia/Aden", + "Asia/Riyadh|Asia/Kuwait", + "Asia/Seoul|ROK", + "Asia/Shanghai|Asia/Chongqing", + "Asia/Shanghai|Asia/Chungking", + "Asia/Shanghai|Asia/Harbin", + "Asia/Shanghai|PRC", + "Asia/Singapore|Singapore", + "Asia/Taipei|ROC", + "Asia/Tehran|Iran", + "Asia/Thimphu|Asia/Thimbu", + "Asia/Tokyo|Japan", + "Asia/Ulaanbaatar|Asia/Ulan_Bator", + "Asia/Urumqi|Asia/Kashgar", + "Atlantic/Faroe|Atlantic/Faeroe", + "Atlantic/Reykjavik|Iceland", + "Australia/Adelaide|Australia/South", + "Australia/Brisbane|Australia/Queensland", + "Australia/Broken_Hill|Australia/Yancowinna", + "Australia/Darwin|Australia/North", + "Australia/Hobart|Australia/Tasmania", + "Australia/Lord_Howe|Australia/LHI", + "Australia/Melbourne|Australia/Victoria", + "Australia/Perth|Australia/West", + "Australia/Sydney|Australia/ACT", + "Australia/Sydney|Australia/Canberra", + "Australia/Sydney|Australia/NSW", + "Etc/GMT+0|Etc/GMT", + "Etc/GMT+0|Etc/GMT-0", + "Etc/GMT+0|Etc/GMT0", + "Etc/GMT+0|Etc/Greenwich", + "Etc/GMT+0|GMT", + "Etc/GMT+0|GMT+0", + "Etc/GMT+0|GMT-0", + "Etc/GMT+0|GMT0", + "Etc/GMT+0|Greenwich", + "Etc/UCT|UCT", + "Etc/UTC|Etc/Universal", + "Etc/UTC|Etc/Zulu", + "Etc/UTC|UTC", + "Etc/UTC|Universal", + "Etc/UTC|Zulu", + "Europe/Belgrade|Europe/Ljubljana", + "Europe/Belgrade|Europe/Podgorica", + "Europe/Belgrade|Europe/Sarajevo", + "Europe/Belgrade|Europe/Skopje", + "Europe/Belgrade|Europe/Zagreb", + "Europe/Chisinau|Europe/Tiraspol", + "Europe/Dublin|Eire", + "Europe/Helsinki|Europe/Mariehamn", + "Europe/Istanbul|Asia/Istanbul", + "Europe/Istanbul|Turkey", + "Europe/Lisbon|Portugal", + "Europe/London|Europe/Belfast", + "Europe/London|Europe/Guernsey", + "Europe/London|Europe/Isle_of_Man", + "Europe/London|Europe/Jersey", + "Europe/London|GB", + "Europe/London|GB-Eire", + "Europe/Moscow|W-SU", + "Europe/Oslo|Arctic/Longyearbyen", + "Europe/Oslo|Atlantic/Jan_Mayen", + "Europe/Prague|Europe/Bratislava", + "Europe/Rome|Europe/San_Marino", + "Europe/Rome|Europe/Vatican", + "Europe/Warsaw|Poland", + "Europe/Zurich|Europe/Busingen", + "Europe/Zurich|Europe/Vaduz", + "Pacific/Auckland|Antarctica/McMurdo", + "Pacific/Auckland|Antarctica/South_Pole", + "Pacific/Auckland|NZ", + "Pacific/Chatham|NZ-CHAT", + "Pacific/Chuuk|Pacific/Truk", + "Pacific/Chuuk|Pacific/Yap", + "Pacific/Easter|Chile/EasterIsland", + "Pacific/Guam|Pacific/Saipan", + "Pacific/Honolulu|Pacific/Johnston", + "Pacific/Honolulu|US/Hawaii", + "Pacific/Kwajalein|Kwajalein", + "Pacific/Pago_Pago|Pacific/Midway", + "Pacific/Pago_Pago|Pacific/Samoa", + "Pacific/Pago_Pago|US/Samoa", + "Pacific/Pohnpei|Pacific/Ponape" + ] + }); + + + return moment; +})); \ No newline at end of file diff --git a/common/libs/js/moment.js b/common/libs/js/moment.js new file mode 100644 index 000000000..7299fa45c --- /dev/null +++ b/common/libs/js/moment.js @@ -0,0 +1,3606 @@ +//! moment.js +//! version : 2.11.2 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + global.moment = factory() +}(this, function () { 'use strict'; + + var hookCallback; + + function utils_hooks__hooks () { + return hookCallback.apply(null, arguments); + } + + // This is done to register the method called with moment() + // without creating circular dependencies. + function setHookCallback (callback) { + hookCallback = callback; + } + + function isArray(input) { + return Object.prototype.toString.call(input) === '[object Array]'; + } + + function isDate(input) { + return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]'; + } + + function map(arr, fn) { + var res = [], i; + for (i = 0; i < arr.length; ++i) { + res.push(fn(arr[i], i)); + } + return res; + } + + function hasOwnProp(a, b) { + return Object.prototype.hasOwnProperty.call(a, b); + } + + function extend(a, b) { + for (var i in b) { + if (hasOwnProp(b, i)) { + a[i] = b[i]; + } + } + + if (hasOwnProp(b, 'toString')) { + a.toString = b.toString; + } + + if (hasOwnProp(b, 'valueOf')) { + a.valueOf = b.valueOf; + } + + return a; + } + + function create_utc__createUTC (input, format, locale, strict) { + return createLocalOrUTC(input, format, locale, strict, true).utc(); + } + + function defaultParsingFlags() { + // We need to deep clone this object. + return { + empty : false, + unusedTokens : [], + unusedInput : [], + overflow : -2, + charsLeftOver : 0, + nullInput : false, + invalidMonth : null, + invalidFormat : false, + userInvalidated : false, + iso : false + }; + } + + function getParsingFlags(m) { + if (m._pf == null) { + m._pf = defaultParsingFlags(); + } + return m._pf; + } + + function valid__isValid(m) { + if (m._isValid == null) { + var flags = getParsingFlags(m); + m._isValid = !isNaN(m._d.getTime()) && + flags.overflow < 0 && + !flags.empty && + !flags.invalidMonth && + !flags.invalidWeekday && + !flags.nullInput && + !flags.invalidFormat && + !flags.userInvalidated; + + if (m._strict) { + m._isValid = m._isValid && + flags.charsLeftOver === 0 && + flags.unusedTokens.length === 0 && + flags.bigHour === undefined; + } + } + return m._isValid; + } + + function valid__createInvalid (flags) { + var m = create_utc__createUTC(NaN); + if (flags != null) { + extend(getParsingFlags(m), flags); + } + else { + getParsingFlags(m).userInvalidated = true; + } + + return m; + } + + function isUndefined(input) { + return input === void 0; + } + + // Plugins that add properties should also add the key here (null value), + // so we can properly clone ourselves. + var momentProperties = utils_hooks__hooks.momentProperties = []; + + function copyConfig(to, from) { + var i, prop, val; + + if (!isUndefined(from._isAMomentObject)) { + to._isAMomentObject = from._isAMomentObject; + } + if (!isUndefined(from._i)) { + to._i = from._i; + } + if (!isUndefined(from._f)) { + to._f = from._f; + } + if (!isUndefined(from._l)) { + to._l = from._l; + } + if (!isUndefined(from._strict)) { + to._strict = from._strict; + } + if (!isUndefined(from._tzm)) { + to._tzm = from._tzm; + } + if (!isUndefined(from._isUTC)) { + to._isUTC = from._isUTC; + } + if (!isUndefined(from._offset)) { + to._offset = from._offset; + } + if (!isUndefined(from._pf)) { + to._pf = getParsingFlags(from); + } + if (!isUndefined(from._locale)) { + to._locale = from._locale; + } + + if (momentProperties.length > 0) { + for (i in momentProperties) { + prop = momentProperties[i]; + val = from[prop]; + if (!isUndefined(val)) { + to[prop] = val; + } + } + } + + return to; + } + + var updateInProgress = false; + + // Moment prototype object + function Moment(config) { + copyConfig(this, config); + this._d = new Date(config._d != null ? config._d.getTime() : NaN); + // Prevent infinite loop in case updateOffset creates new moment + // objects. + if (updateInProgress === false) { + updateInProgress = true; + utils_hooks__hooks.updateOffset(this); + updateInProgress = false; + } + } + + function isMoment (obj) { + return obj instanceof Moment || (obj != null && obj._isAMomentObject != null); + } + + function absFloor (number) { + if (number < 0) { + return Math.ceil(number); + } else { + return Math.floor(number); + } + } + + function toInt(argumentForCoercion) { + var coercedNumber = +argumentForCoercion, + value = 0; + + if (coercedNumber !== 0 && isFinite(coercedNumber)) { + value = absFloor(coercedNumber); + } + + return value; + } + + // compare two arrays, return the number of differences + function compareArrays(array1, array2, dontConvert) { + var len = Math.min(array1.length, array2.length), + lengthDiff = Math.abs(array1.length - array2.length), + diffs = 0, + i; + for (i = 0; i < len; i++) { + if ((dontConvert && array1[i] !== array2[i]) || + (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { + diffs++; + } + } + return diffs + lengthDiff; + } + + function Locale() { + } + + // internal storage for locale config files + var locales = {}; + var globalLocale; + + function normalizeLocale(key) { + return key ? key.toLowerCase().replace('_', '-') : key; + } + + // pick the locale from the array + // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each + // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root + function chooseLocale(names) { + var i = 0, j, next, locale, split; + + while (i < names.length) { + split = normalizeLocale(names[i]).split('-'); + j = split.length; + next = normalizeLocale(names[i + 1]); + next = next ? next.split('-') : null; + while (j > 0) { + locale = loadLocale(split.slice(0, j).join('-')); + if (locale) { + return locale; + } + if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { + //the next array item is better than a shallower substring of this one + break; + } + j--; + } + i++; + } + return null; + } + + function loadLocale(name) { + var oldLocale = null; + // TODO: Find a better way to register and load all the locales in Node + if (!locales[name] && (typeof module !== 'undefined') && + module && module.exports) { + try { + oldLocale = globalLocale._abbr; + require('./locale/' + name); + // because defineLocale currently also sets the global locale, we + // want to undo that for lazy loaded locales + locale_locales__getSetGlobalLocale(oldLocale); + } catch (e) { } + } + return locales[name]; + } + + // This function will load locale and then set the global locale. If + // no arguments are passed in, it will simply return the current global + // locale key. + function locale_locales__getSetGlobalLocale (key, values) { + var data; + if (key) { + if (isUndefined(values)) { + data = locale_locales__getLocale(key); + } + else { + data = defineLocale(key, values); + } + + if (data) { + // moment.duration._locale = moment._locale = data; + globalLocale = data; + } + } + + return globalLocale._abbr; + } + + function defineLocale (name, values) { + if (values !== null) { + values.abbr = name; + locales[name] = locales[name] || new Locale(); + locales[name].set(values); + + // backwards compat for now: also set the locale + locale_locales__getSetGlobalLocale(name); + + return locales[name]; + } else { + // useful for testing + delete locales[name]; + return null; + } + } + + // returns locale data + function locale_locales__getLocale (key) { + var locale; + + if (key && key._locale && key._locale._abbr) { + key = key._locale._abbr; + } + + if (!key) { + return globalLocale; + } + + if (!isArray(key)) { + //short-circuit everything else + locale = loadLocale(key); + if (locale) { + return locale; + } + key = [key]; + } + + return chooseLocale(key); + } + + var aliases = {}; + + function addUnitAlias (unit, shorthand) { + var lowerCase = unit.toLowerCase(); + aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit; + } + + function normalizeUnits(units) { + return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined; + } + + function normalizeObjectUnits(inputObject) { + var normalizedInput = {}, + normalizedProp, + prop; + + for (prop in inputObject) { + if (hasOwnProp(inputObject, prop)) { + normalizedProp = normalizeUnits(prop); + if (normalizedProp) { + normalizedInput[normalizedProp] = inputObject[prop]; + } + } + } + + return normalizedInput; + } + + function isFunction(input) { + return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]'; + } + + function makeGetSet (unit, keepTime) { + return function (value) { + if (value != null) { + get_set__set(this, unit, value); + utils_hooks__hooks.updateOffset(this, keepTime); + return this; + } else { + return get_set__get(this, unit); + } + }; + } + + function get_set__get (mom, unit) { + return mom.isValid() ? + mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN; + } + + function get_set__set (mom, unit, value) { + if (mom.isValid()) { + mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); + } + } + + // MOMENTS + + function getSet (units, value) { + var unit; + if (typeof units === 'object') { + for (unit in units) { + this.set(unit, units[unit]); + } + } else { + units = normalizeUnits(units); + if (isFunction(this[units])) { + return this[units](value); + } + } + return this; + } + + function zeroFill(number, targetLength, forceSign) { + var absNumber = '' + Math.abs(number), + zerosToFill = targetLength - absNumber.length, + sign = number >= 0; + return (sign ? (forceSign ? '+' : '') : '-') + + Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber; + } + + var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g; + + var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g; + + var formatFunctions = {}; + + var formatTokenFunctions = {}; + + // token: 'M' + // padded: ['MM', 2] + // ordinal: 'Mo' + // callback: function () { this.month() + 1 } + function addFormatToken (token, padded, ordinal, callback) { + var func = callback; + if (typeof callback === 'string') { + func = function () { + return this[callback](); + }; + } + if (token) { + formatTokenFunctions[token] = func; + } + if (padded) { + formatTokenFunctions[padded[0]] = function () { + return zeroFill(func.apply(this, arguments), padded[1], padded[2]); + }; + } + if (ordinal) { + formatTokenFunctions[ordinal] = function () { + return this.localeData().ordinal(func.apply(this, arguments), token); + }; + } + } + + function removeFormattingTokens(input) { + if (input.match(/\[[\s\S]/)) { + return input.replace(/^\[|\]$/g, ''); + } + return input.replace(/\\/g, ''); + } + + function makeFormatFunction(format) { + var array = format.match(formattingTokens), i, length; + + for (i = 0, length = array.length; i < length; i++) { + if (formatTokenFunctions[array[i]]) { + array[i] = formatTokenFunctions[array[i]]; + } else { + array[i] = removeFormattingTokens(array[i]); + } + } + + return function (mom) { + var output = ''; + for (i = 0; i < length; i++) { + output += array[i] instanceof Function ? array[i].call(mom, format) : array[i]; + } + return output; + }; + } + + // format date using native date object + function formatMoment(m, format) { + if (!m.isValid()) { + return m.localeData().invalidDate(); + } + + format = expandFormat(format, m.localeData()); + formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format); + + return formatFunctions[format](m); + } + + function expandFormat(format, locale) { + var i = 5; + + function replaceLongDateFormatTokens(input) { + return locale.longDateFormat(input) || input; + } + + localFormattingTokens.lastIndex = 0; + while (i >= 0 && localFormattingTokens.test(format)) { + format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); + localFormattingTokens.lastIndex = 0; + i -= 1; + } + + return format; + } + + var match1 = /\d/; // 0 - 9 + var match2 = /\d\d/; // 00 - 99 + var match3 = /\d{3}/; // 000 - 999 + var match4 = /\d{4}/; // 0000 - 9999 + var match6 = /[+-]?\d{6}/; // -999999 - 999999 + var match1to2 = /\d\d?/; // 0 - 99 + var match3to4 = /\d\d\d\d?/; // 999 - 9999 + var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999 + var match1to3 = /\d{1,3}/; // 0 - 999 + var match1to4 = /\d{1,4}/; // 0 - 9999 + var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999 + + var matchUnsigned = /\d+/; // 0 - inf + var matchSigned = /[+-]?\d+/; // -inf - inf + + var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z + var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z + + var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123 + + // any word (or two) characters or numbers including two/three word month in arabic. + // includes scottish gaelic two word and hyphenated months + var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i; + + + var regexes = {}; + + function addRegexToken (token, regex, strictRegex) { + regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) { + return (isStrict && strictRegex) ? strictRegex : regex; + }; + } + + function getParseRegexForToken (token, config) { + if (!hasOwnProp(regexes, token)) { + return new RegExp(unescapeFormat(token)); + } + + return regexes[token](config._strict, config._locale); + } + + // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript + function unescapeFormat(s) { + return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { + return p1 || p2 || p3 || p4; + })); + } + + function regexEscape(s) { + return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); + } + + var tokens = {}; + + function addParseToken (token, callback) { + var i, func = callback; + if (typeof token === 'string') { + token = [token]; + } + if (typeof callback === 'number') { + func = function (input, array) { + array[callback] = toInt(input); + }; + } + for (i = 0; i < token.length; i++) { + tokens[token[i]] = func; + } + } + + function addWeekParseToken (token, callback) { + addParseToken(token, function (input, array, config, token) { + config._w = config._w || {}; + callback(input, config._w, config, token); + }); + } + + function addTimeToArrayFromToken(token, input, config) { + if (input != null && hasOwnProp(tokens, token)) { + tokens[token](input, config._a, config, token); + } + } + + var YEAR = 0; + var MONTH = 1; + var DATE = 2; + var HOUR = 3; + var MINUTE = 4; + var SECOND = 5; + var MILLISECOND = 6; + var WEEK = 7; + var WEEKDAY = 8; + + function daysInMonth(year, month) { + return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); + } + + // FORMATTING + + addFormatToken('M', ['MM', 2], 'Mo', function () { + return this.month() + 1; + }); + + addFormatToken('MMM', 0, 0, function (format) { + return this.localeData().monthsShort(this, format); + }); + + addFormatToken('MMMM', 0, 0, function (format) { + return this.localeData().months(this, format); + }); + + // ALIASES + + addUnitAlias('month', 'M'); + + // PARSING + + addRegexToken('M', match1to2); + addRegexToken('MM', match1to2, match2); + addRegexToken('MMM', function (isStrict, locale) { + return locale.monthsShortRegex(isStrict); + }); + addRegexToken('MMMM', function (isStrict, locale) { + return locale.monthsRegex(isStrict); + }); + + addParseToken(['M', 'MM'], function (input, array) { + array[MONTH] = toInt(input) - 1; + }); + + addParseToken(['MMM', 'MMMM'], function (input, array, config, token) { + var month = config._locale.monthsParse(input, token, config._strict); + // if we didn't find a month name, mark the date as invalid. + if (month != null) { + array[MONTH] = month; + } else { + getParsingFlags(config).invalidMonth = input; + } + }); + + // LOCALES + + var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/; + var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'); + function localeMonths (m, format) { + return isArray(this._months) ? this._months[m.month()] : + this._months[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()]; + } + + var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'); + function localeMonthsShort (m, format) { + return isArray(this._monthsShort) ? this._monthsShort[m.month()] : + this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()]; + } + + function localeMonthsParse (monthName, format, strict) { + var i, mom, regex; + + if (!this._monthsParse) { + this._monthsParse = []; + this._longMonthsParse = []; + this._shortMonthsParse = []; + } + + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + mom = create_utc__createUTC([2000, i]); + if (strict && !this._longMonthsParse[i]) { + this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i'); + this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i'); + } + if (!strict && !this._monthsParse[i]) { + regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); + this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) { + return i; + } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) { + return i; + } else if (!strict && this._monthsParse[i].test(monthName)) { + return i; + } + } + } + + // MOMENTS + + function setMonth (mom, value) { + var dayOfMonth; + + if (!mom.isValid()) { + // No op + return mom; + } + + // TODO: Move this out of here! + if (typeof value === 'string') { + value = mom.localeData().monthsParse(value); + // TODO: Another silent failure? + if (typeof value !== 'number') { + return mom; + } + } + + dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value)); + mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); + return mom; + } + + function getSetMonth (value) { + if (value != null) { + setMonth(this, value); + utils_hooks__hooks.updateOffset(this, true); + return this; + } else { + return get_set__get(this, 'Month'); + } + } + + function getDaysInMonth () { + return daysInMonth(this.year(), this.month()); + } + + var defaultMonthsShortRegex = matchWord; + function monthsShortRegex (isStrict) { + if (this._monthsParseExact) { + if (!hasOwnProp(this, '_monthsRegex')) { + computeMonthsParse.call(this); + } + if (isStrict) { + return this._monthsShortStrictRegex; + } else { + return this._monthsShortRegex; + } + } else { + return this._monthsShortStrictRegex && isStrict ? + this._monthsShortStrictRegex : this._monthsShortRegex; + } + } + + var defaultMonthsRegex = matchWord; + function monthsRegex (isStrict) { + if (this._monthsParseExact) { + if (!hasOwnProp(this, '_monthsRegex')) { + computeMonthsParse.call(this); + } + if (isStrict) { + return this._monthsStrictRegex; + } else { + return this._monthsRegex; + } + } else { + return this._monthsStrictRegex && isStrict ? + this._monthsStrictRegex : this._monthsRegex; + } + } + + function computeMonthsParse () { + function cmpLenRev(a, b) { + return b.length - a.length; + } + + var shortPieces = [], longPieces = [], mixedPieces = [], + i, mom; + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + mom = create_utc__createUTC([2000, i]); + shortPieces.push(this.monthsShort(mom, '')); + longPieces.push(this.months(mom, '')); + mixedPieces.push(this.months(mom, '')); + mixedPieces.push(this.monthsShort(mom, '')); + } + // Sorting makes sure if one month (or abbr) is a prefix of another it + // will match the longer piece. + shortPieces.sort(cmpLenRev); + longPieces.sort(cmpLenRev); + mixedPieces.sort(cmpLenRev); + for (i = 0; i < 12; i++) { + shortPieces[i] = regexEscape(shortPieces[i]); + longPieces[i] = regexEscape(longPieces[i]); + mixedPieces[i] = regexEscape(mixedPieces[i]); + } + + this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); + this._monthsShortRegex = this._monthsRegex; + this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')$', 'i'); + this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')$', 'i'); + } + + function checkOverflow (m) { + var overflow; + var a = m._a; + + if (a && getParsingFlags(m).overflow === -2) { + overflow = + a[MONTH] < 0 || a[MONTH] > 11 ? MONTH : + a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE : + a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR : + a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE : + a[SECOND] < 0 || a[SECOND] > 59 ? SECOND : + a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND : + -1; + + if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { + overflow = DATE; + } + if (getParsingFlags(m)._overflowWeeks && overflow === -1) { + overflow = WEEK; + } + if (getParsingFlags(m)._overflowWeekday && overflow === -1) { + overflow = WEEKDAY; + } + + getParsingFlags(m).overflow = overflow; + } + + return m; + } + + function warn(msg) { + if (utils_hooks__hooks.suppressDeprecationWarnings === false && + (typeof console !== 'undefined') && console.warn) { + console.warn('Deprecation warning: ' + msg); + } + } + + function deprecate(msg, fn) { + var firstTime = true; + + return extend(function () { + if (firstTime) { + warn(msg + '\nArguments: ' + Array.prototype.slice.call(arguments).join(', ') + '\n' + (new Error()).stack); + firstTime = false; + } + return fn.apply(this, arguments); + }, fn); + } + + var deprecations = {}; + + function deprecateSimple(name, msg) { + if (!deprecations[name]) { + warn(msg); + deprecations[name] = true; + } + } + + utils_hooks__hooks.suppressDeprecationWarnings = false; + + // iso 8601 regex + // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00) + var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/; + var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/; + + var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/; + + var isoDates = [ + ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/], + ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/], + ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/], + ['GGGG-[W]WW', /\d{4}-W\d\d/, false], + ['YYYY-DDD', /\d{4}-\d{3}/], + ['YYYY-MM', /\d{4}-\d\d/, false], + ['YYYYYYMMDD', /[+-]\d{10}/], + ['YYYYMMDD', /\d{8}/], + // YYYYMM is NOT allowed by the standard + ['GGGG[W]WWE', /\d{4}W\d{3}/], + ['GGGG[W]WW', /\d{4}W\d{2}/, false], + ['YYYYDDD', /\d{7}/] + ]; + + // iso time formats and regexes + var isoTimes = [ + ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/], + ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/], + ['HH:mm:ss', /\d\d:\d\d:\d\d/], + ['HH:mm', /\d\d:\d\d/], + ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/], + ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/], + ['HHmmss', /\d\d\d\d\d\d/], + ['HHmm', /\d\d\d\d/], + ['HH', /\d\d/] + ]; + + var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i; + + // date from iso format + function configFromISO(config) { + var i, l, + string = config._i, + match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string), + allowTime, dateFormat, timeFormat, tzFormat; + + if (match) { + getParsingFlags(config).iso = true; + + for (i = 0, l = isoDates.length; i < l; i++) { + if (isoDates[i][1].exec(match[1])) { + dateFormat = isoDates[i][0]; + allowTime = isoDates[i][2] !== false; + break; + } + } + if (dateFormat == null) { + config._isValid = false; + return; + } + if (match[3]) { + for (i = 0, l = isoTimes.length; i < l; i++) { + if (isoTimes[i][1].exec(match[3])) { + // match[2] should be 'T' or space + timeFormat = (match[2] || ' ') + isoTimes[i][0]; + break; + } + } + if (timeFormat == null) { + config._isValid = false; + return; + } + } + if (!allowTime && timeFormat != null) { + config._isValid = false; + return; + } + if (match[4]) { + if (tzRegex.exec(match[4])) { + tzFormat = 'Z'; + } else { + config._isValid = false; + return; + } + } + config._f = dateFormat + (timeFormat || '') + (tzFormat || ''); + configFromStringAndFormat(config); + } else { + config._isValid = false; + } + } + + // date from iso format or fallback + function configFromString(config) { + var matched = aspNetJsonRegex.exec(config._i); + + if (matched !== null) { + config._d = new Date(+matched[1]); + return; + } + + configFromISO(config); + if (config._isValid === false) { + delete config._isValid; + utils_hooks__hooks.createFromInputFallback(config); + } + } + + utils_hooks__hooks.createFromInputFallback = deprecate( + 'moment construction falls back to js Date. This is ' + + 'discouraged and will be removed in upcoming major ' + + 'release. Please refer to ' + + 'https://github.com/moment/moment/issues/1407 for more info.', + function (config) { + config._d = new Date(config._i + (config._useUTC ? ' UTC' : '')); + } + ); + + function createDate (y, m, d, h, M, s, ms) { + //can't just apply() to create a date: + //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply + var date = new Date(y, m, d, h, M, s, ms); + + //the date constructor remaps years 0-99 to 1900-1999 + if (y < 100 && y >= 0 && isFinite(date.getFullYear())) { + date.setFullYear(y); + } + return date; + } + + function createUTCDate (y) { + var date = new Date(Date.UTC.apply(null, arguments)); + + //the Date.UTC function remaps years 0-99 to 1900-1999 + if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) { + date.setUTCFullYear(y); + } + return date; + } + + // FORMATTING + + addFormatToken('Y', 0, 0, function () { + var y = this.year(); + return y <= 9999 ? '' + y : '+' + y; + }); + + addFormatToken(0, ['YY', 2], 0, function () { + return this.year() % 100; + }); + + addFormatToken(0, ['YYYY', 4], 0, 'year'); + addFormatToken(0, ['YYYYY', 5], 0, 'year'); + addFormatToken(0, ['YYYYYY', 6, true], 0, 'year'); + + // ALIASES + + addUnitAlias('year', 'y'); + + // PARSING + + addRegexToken('Y', matchSigned); + addRegexToken('YY', match1to2, match2); + addRegexToken('YYYY', match1to4, match4); + addRegexToken('YYYYY', match1to6, match6); + addRegexToken('YYYYYY', match1to6, match6); + + addParseToken(['YYYYY', 'YYYYYY'], YEAR); + addParseToken('YYYY', function (input, array) { + array[YEAR] = input.length === 2 ? utils_hooks__hooks.parseTwoDigitYear(input) : toInt(input); + }); + addParseToken('YY', function (input, array) { + array[YEAR] = utils_hooks__hooks.parseTwoDigitYear(input); + }); + addParseToken('Y', function (input, array) { + array[YEAR] = parseInt(input, 10); + }); + + // HELPERS + + function daysInYear(year) { + return isLeapYear(year) ? 366 : 365; + } + + function isLeapYear(year) { + return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; + } + + // HOOKS + + utils_hooks__hooks.parseTwoDigitYear = function (input) { + return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); + }; + + // MOMENTS + + var getSetYear = makeGetSet('FullYear', false); + + function getIsLeapYear () { + return isLeapYear(this.year()); + } + + // start-of-first-week - start-of-year + function firstWeekOffset(year, dow, doy) { + var // first-week day -- which january is always in the first week (4 for iso, 1 for other) + fwd = 7 + dow - doy, + // first-week day local weekday -- which local weekday is fwd + fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7; + + return -fwdlw + fwd - 1; + } + + //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday + function dayOfYearFromWeeks(year, week, weekday, dow, doy) { + var localWeekday = (7 + weekday - dow) % 7, + weekOffset = firstWeekOffset(year, dow, doy), + dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset, + resYear, resDayOfYear; + + if (dayOfYear <= 0) { + resYear = year - 1; + resDayOfYear = daysInYear(resYear) + dayOfYear; + } else if (dayOfYear > daysInYear(year)) { + resYear = year + 1; + resDayOfYear = dayOfYear - daysInYear(year); + } else { + resYear = year; + resDayOfYear = dayOfYear; + } + + return { + year: resYear, + dayOfYear: resDayOfYear + }; + } + + function weekOfYear(mom, dow, doy) { + var weekOffset = firstWeekOffset(mom.year(), dow, doy), + week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1, + resWeek, resYear; + + if (week < 1) { + resYear = mom.year() - 1; + resWeek = week + weeksInYear(resYear, dow, doy); + } else if (week > weeksInYear(mom.year(), dow, doy)) { + resWeek = week - weeksInYear(mom.year(), dow, doy); + resYear = mom.year() + 1; + } else { + resYear = mom.year(); + resWeek = week; + } + + return { + week: resWeek, + year: resYear + }; + } + + function weeksInYear(year, dow, doy) { + var weekOffset = firstWeekOffset(year, dow, doy), + weekOffsetNext = firstWeekOffset(year + 1, dow, doy); + return (daysInYear(year) - weekOffset + weekOffsetNext) / 7; + } + + // Pick the first defined of two or three arguments. + function defaults(a, b, c) { + if (a != null) { + return a; + } + if (b != null) { + return b; + } + return c; + } + + function currentDateArray(config) { + // hooks is actually the exported moment object + var nowValue = new Date(utils_hooks__hooks.now()); + if (config._useUTC) { + return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()]; + } + return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()]; + } + + // convert an array to a date. + // the array should mirror the parameters below + // note: all values past the year are optional and will default to the lowest possible value. + // [year, month, day , hour, minute, second, millisecond] + function configFromArray (config) { + var i, date, input = [], currentDate, yearToUse; + + if (config._d) { + return; + } + + currentDate = currentDateArray(config); + + //compute day of the year from weeks and weekdays + if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { + dayOfYearFromWeekInfo(config); + } + + //if the day of the year is set, figure out what it is + if (config._dayOfYear) { + yearToUse = defaults(config._a[YEAR], currentDate[YEAR]); + + if (config._dayOfYear > daysInYear(yearToUse)) { + getParsingFlags(config)._overflowDayOfYear = true; + } + + date = createUTCDate(yearToUse, 0, config._dayOfYear); + config._a[MONTH] = date.getUTCMonth(); + config._a[DATE] = date.getUTCDate(); + } + + // Default to current date. + // * if no year, month, day of month are given, default to today + // * if day of month is given, default month and year + // * if month is given, default only year + // * if year is given, don't default anything + for (i = 0; i < 3 && config._a[i] == null; ++i) { + config._a[i] = input[i] = currentDate[i]; + } + + // Zero out whatever was not defaulted, including time + for (; i < 7; i++) { + config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; + } + + // Check for 24:00:00.000 + if (config._a[HOUR] === 24 && + config._a[MINUTE] === 0 && + config._a[SECOND] === 0 && + config._a[MILLISECOND] === 0) { + config._nextDay = true; + config._a[HOUR] = 0; + } + + config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input); + // Apply timezone offset from input. The actual utcOffset can be changed + // with parseZone. + if (config._tzm != null) { + config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); + } + + if (config._nextDay) { + config._a[HOUR] = 24; + } + } + + function dayOfYearFromWeekInfo(config) { + var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow; + + w = config._w; + if (w.GG != null || w.W != null || w.E != null) { + dow = 1; + doy = 4; + + // TODO: We need to take the current isoWeekYear, but that depends on + // how we interpret now (local, utc, fixed offset). So create + // a now version of current config (take local/utc/offset flags, and + // create now). + weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__createLocal(), 1, 4).year); + week = defaults(w.W, 1); + weekday = defaults(w.E, 1); + if (weekday < 1 || weekday > 7) { + weekdayOverflow = true; + } + } else { + dow = config._locale._week.dow; + doy = config._locale._week.doy; + + weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year); + week = defaults(w.w, 1); + + if (w.d != null) { + // weekday -- low day numbers are considered next week + weekday = w.d; + if (weekday < 0 || weekday > 6) { + weekdayOverflow = true; + } + } else if (w.e != null) { + // local weekday -- counting starts from begining of week + weekday = w.e + dow; + if (w.e < 0 || w.e > 6) { + weekdayOverflow = true; + } + } else { + // default to begining of week + weekday = dow; + } + } + if (week < 1 || week > weeksInYear(weekYear, dow, doy)) { + getParsingFlags(config)._overflowWeeks = true; + } else if (weekdayOverflow != null) { + getParsingFlags(config)._overflowWeekday = true; + } else { + temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy); + config._a[YEAR] = temp.year; + config._dayOfYear = temp.dayOfYear; + } + } + + // constant that refers to the ISO standard + utils_hooks__hooks.ISO_8601 = function () {}; + + // date from string and format string + function configFromStringAndFormat(config) { + // TODO: Move this to another part of the creation flow to prevent circular deps + if (config._f === utils_hooks__hooks.ISO_8601) { + configFromISO(config); + return; + } + + config._a = []; + getParsingFlags(config).empty = true; + + // This array is used to make a Date, either with `new Date` or `Date.UTC` + var string = '' + config._i, + i, parsedInput, tokens, token, skipped, + stringLength = string.length, + totalParsedInputLength = 0; + + tokens = expandFormat(config._f, config._locale).match(formattingTokens) || []; + + for (i = 0; i < tokens.length; i++) { + token = tokens[i]; + parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; + // console.log('token', token, 'parsedInput', parsedInput, + // 'regex', getParseRegexForToken(token, config)); + if (parsedInput) { + skipped = string.substr(0, string.indexOf(parsedInput)); + if (skipped.length > 0) { + getParsingFlags(config).unusedInput.push(skipped); + } + string = string.slice(string.indexOf(parsedInput) + parsedInput.length); + totalParsedInputLength += parsedInput.length; + } + // don't parse if it's not a known token + if (formatTokenFunctions[token]) { + if (parsedInput) { + getParsingFlags(config).empty = false; + } + else { + getParsingFlags(config).unusedTokens.push(token); + } + addTimeToArrayFromToken(token, parsedInput, config); + } + else if (config._strict && !parsedInput) { + getParsingFlags(config).unusedTokens.push(token); + } + } + + // add remaining unparsed input length to the string + getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength; + if (string.length > 0) { + getParsingFlags(config).unusedInput.push(string); + } + + // clear _12h flag if hour is <= 12 + if (getParsingFlags(config).bigHour === true && + config._a[HOUR] <= 12 && + config._a[HOUR] > 0) { + getParsingFlags(config).bigHour = undefined; + } + // handle meridiem + config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem); + + configFromArray(config); + checkOverflow(config); + } + + + function meridiemFixWrap (locale, hour, meridiem) { + var isPm; + + if (meridiem == null) { + // nothing to do + return hour; + } + if (locale.meridiemHour != null) { + return locale.meridiemHour(hour, meridiem); + } else if (locale.isPM != null) { + // Fallback + isPm = locale.isPM(meridiem); + if (isPm && hour < 12) { + hour += 12; + } + if (!isPm && hour === 12) { + hour = 0; + } + return hour; + } else { + // this is not supposed to happen + return hour; + } + } + + // date from string and array of format strings + function configFromStringAndArray(config) { + var tempConfig, + bestMoment, + + scoreToBeat, + i, + currentScore; + + if (config._f.length === 0) { + getParsingFlags(config).invalidFormat = true; + config._d = new Date(NaN); + return; + } + + for (i = 0; i < config._f.length; i++) { + currentScore = 0; + tempConfig = copyConfig({}, config); + if (config._useUTC != null) { + tempConfig._useUTC = config._useUTC; + } + tempConfig._f = config._f[i]; + configFromStringAndFormat(tempConfig); + + if (!valid__isValid(tempConfig)) { + continue; + } + + // if there is any input that was not parsed add a penalty for that format + currentScore += getParsingFlags(tempConfig).charsLeftOver; + + //or tokens + currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10; + + getParsingFlags(tempConfig).score = currentScore; + + if (scoreToBeat == null || currentScore < scoreToBeat) { + scoreToBeat = currentScore; + bestMoment = tempConfig; + } + } + + extend(config, bestMoment || tempConfig); + } + + function configFromObject(config) { + if (config._d) { + return; + } + + var i = normalizeObjectUnits(config._i); + config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) { + return obj && parseInt(obj, 10); + }); + + configFromArray(config); + } + + function createFromConfig (config) { + var res = new Moment(checkOverflow(prepareConfig(config))); + if (res._nextDay) { + // Adding is smart enough around DST + res.add(1, 'd'); + res._nextDay = undefined; + } + + return res; + } + + function prepareConfig (config) { + var input = config._i, + format = config._f; + + config._locale = config._locale || locale_locales__getLocale(config._l); + + if (input === null || (format === undefined && input === '')) { + return valid__createInvalid({nullInput: true}); + } + + if (typeof input === 'string') { + config._i = input = config._locale.preparse(input); + } + + if (isMoment(input)) { + return new Moment(checkOverflow(input)); + } else if (isArray(format)) { + configFromStringAndArray(config); + } else if (format) { + configFromStringAndFormat(config); + } else if (isDate(input)) { + config._d = input; + } else { + configFromInput(config); + } + + if (!valid__isValid(config)) { + config._d = null; + } + + return config; + } + + function configFromInput(config) { + var input = config._i; + if (input === undefined) { + config._d = new Date(utils_hooks__hooks.now()); + } else if (isDate(input)) { + config._d = new Date(+input); + } else if (typeof input === 'string') { + configFromString(config); + } else if (isArray(input)) { + config._a = map(input.slice(0), function (obj) { + return parseInt(obj, 10); + }); + configFromArray(config); + } else if (typeof(input) === 'object') { + configFromObject(config); + } else if (typeof(input) === 'number') { + // from milliseconds + config._d = new Date(input); + } else { + utils_hooks__hooks.createFromInputFallback(config); + } + } + + function createLocalOrUTC (input, format, locale, strict, isUTC) { + var c = {}; + + if (typeof(locale) === 'boolean') { + strict = locale; + locale = undefined; + } + // object construction must be done this way. + // https://github.com/moment/moment/issues/1423 + c._isAMomentObject = true; + c._useUTC = c._isUTC = isUTC; + c._l = locale; + c._i = input; + c._f = format; + c._strict = strict; + + return createFromConfig(c); + } + + function local__createLocal (input, format, locale, strict) { + return createLocalOrUTC(input, format, locale, strict, false); + } + + var prototypeMin = deprecate( + 'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548', + function () { + var other = local__createLocal.apply(null, arguments); + if (this.isValid() && other.isValid()) { + return other < this ? this : other; + } else { + return valid__createInvalid(); + } + } + ); + + var prototypeMax = deprecate( + 'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548', + function () { + var other = local__createLocal.apply(null, arguments); + if (this.isValid() && other.isValid()) { + return other > this ? this : other; + } else { + return valid__createInvalid(); + } + } + ); + + // Pick a moment m from moments so that m[fn](other) is true for all + // other. This relies on the function fn to be transitive. + // + // moments should either be an array of moment objects or an array, whose + // first element is an array of moment objects. + function pickBy(fn, moments) { + var res, i; + if (moments.length === 1 && isArray(moments[0])) { + moments = moments[0]; + } + if (!moments.length) { + return local__createLocal(); + } + res = moments[0]; + for (i = 1; i < moments.length; ++i) { + if (!moments[i].isValid() || moments[i][fn](res)) { + res = moments[i]; + } + } + return res; + } + + // TODO: Use [].sort instead? + function min () { + var args = [].slice.call(arguments, 0); + + return pickBy('isBefore', args); + } + + function max () { + var args = [].slice.call(arguments, 0); + + return pickBy('isAfter', args); + } + + var now = function () { + return Date.now ? Date.now() : +(new Date()); + }; + + function Duration (duration) { + var normalizedInput = normalizeObjectUnits(duration), + years = normalizedInput.year || 0, + quarters = normalizedInput.quarter || 0, + months = normalizedInput.month || 0, + weeks = normalizedInput.week || 0, + days = normalizedInput.day || 0, + hours = normalizedInput.hour || 0, + minutes = normalizedInput.minute || 0, + seconds = normalizedInput.second || 0, + milliseconds = normalizedInput.millisecond || 0; + + // representation for dateAddRemove + this._milliseconds = +milliseconds + + seconds * 1e3 + // 1000 + minutes * 6e4 + // 1000 * 60 + hours * 36e5; // 1000 * 60 * 60 + // Because of dateAddRemove treats 24 hours as different from a + // day when working around DST, we need to store them separately + this._days = +days + + weeks * 7; + // It is impossible translate months into days without knowing + // which months you are are talking about, so we have to store + // it separately. + this._months = +months + + quarters * 3 + + years * 12; + + this._data = {}; + + this._locale = locale_locales__getLocale(); + + this._bubble(); + } + + function isDuration (obj) { + return obj instanceof Duration; + } + + // FORMATTING + + function offset (token, separator) { + addFormatToken(token, 0, 0, function () { + var offset = this.utcOffset(); + var sign = '+'; + if (offset < 0) { + offset = -offset; + sign = '-'; + } + return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2); + }); + } + + offset('Z', ':'); + offset('ZZ', ''); + + // PARSING + + addRegexToken('Z', matchShortOffset); + addRegexToken('ZZ', matchShortOffset); + addParseToken(['Z', 'ZZ'], function (input, array, config) { + config._useUTC = true; + config._tzm = offsetFromString(matchShortOffset, input); + }); + + // HELPERS + + // timezone chunker + // '+10:00' > ['10', '00'] + // '-1530' > ['-15', '30'] + var chunkOffset = /([\+\-]|\d\d)/gi; + + function offsetFromString(matcher, string) { + var matches = ((string || '').match(matcher) || []); + var chunk = matches[matches.length - 1] || []; + var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0]; + var minutes = +(parts[1] * 60) + toInt(parts[2]); + + return parts[0] === '+' ? minutes : -minutes; + } + + // Return a moment from input, that is local/utc/zone equivalent to model. + function cloneWithOffset(input, model) { + var res, diff; + if (model._isUTC) { + res = model.clone(); + diff = (isMoment(input) || isDate(input) ? +input : +local__createLocal(input)) - (+res); + // Use low-level api, because this fn is low-level api. + res._d.setTime(+res._d + diff); + utils_hooks__hooks.updateOffset(res, false); + return res; + } else { + return local__createLocal(input).local(); + } + } + + function getDateOffset (m) { + // On Firefox.24 Date#getTimezoneOffset returns a floating point. + // https://github.com/moment/moment/pull/1871 + return -Math.round(m._d.getTimezoneOffset() / 15) * 15; + } + + // HOOKS + + // This function will be called whenever a moment is mutated. + // It is intended to keep the offset in sync with the timezone. + utils_hooks__hooks.updateOffset = function () {}; + + // MOMENTS + + // keepLocalTime = true means only change the timezone, without + // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]--> + // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset + // +0200, so we adjust the time as needed, to be valid. + // + // Keeping the time actually adds/subtracts (one hour) + // from the actual represented time. That is why we call updateOffset + // a second time. In case it wants us to change the offset again + // _changeInProgress == true case, then we have to adjust, because + // there is no such time in the given timezone. + function getSetOffset (input, keepLocalTime) { + var offset = this._offset || 0, + localAdjust; + if (!this.isValid()) { + return input != null ? this : NaN; + } + if (input != null) { + if (typeof input === 'string') { + input = offsetFromString(matchShortOffset, input); + } else if (Math.abs(input) < 16) { + input = input * 60; + } + if (!this._isUTC && keepLocalTime) { + localAdjust = getDateOffset(this); + } + this._offset = input; + this._isUTC = true; + if (localAdjust != null) { + this.add(localAdjust, 'm'); + } + if (offset !== input) { + if (!keepLocalTime || this._changeInProgress) { + add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false); + } else if (!this._changeInProgress) { + this._changeInProgress = true; + utils_hooks__hooks.updateOffset(this, true); + this._changeInProgress = null; + } + } + return this; + } else { + return this._isUTC ? offset : getDateOffset(this); + } + } + + function getSetZone (input, keepLocalTime) { + if (input != null) { + if (typeof input !== 'string') { + input = -input; + } + + this.utcOffset(input, keepLocalTime); + + return this; + } else { + return -this.utcOffset(); + } + } + + function setOffsetToUTC (keepLocalTime) { + return this.utcOffset(0, keepLocalTime); + } + + function setOffsetToLocal (keepLocalTime) { + if (this._isUTC) { + this.utcOffset(0, keepLocalTime); + this._isUTC = false; + + if (keepLocalTime) { + this.subtract(getDateOffset(this), 'm'); + } + } + return this; + } + + function setOffsetToParsedOffset () { + if (this._tzm) { + this.utcOffset(this._tzm); + } else if (typeof this._i === 'string') { + this.utcOffset(offsetFromString(matchOffset, this._i)); + } + return this; + } + + function hasAlignedHourOffset (input) { + if (!this.isValid()) { + return false; + } + input = input ? local__createLocal(input).utcOffset() : 0; + + return (this.utcOffset() - input) % 60 === 0; + } + + function isDaylightSavingTime () { + return ( + this.utcOffset() > this.clone().month(0).utcOffset() || + this.utcOffset() > this.clone().month(5).utcOffset() + ); + } + + function isDaylightSavingTimeShifted () { + if (!isUndefined(this._isDSTShifted)) { + return this._isDSTShifted; + } + + var c = {}; + + copyConfig(c, this); + c = prepareConfig(c); + + if (c._a) { + var other = c._isUTC ? create_utc__createUTC(c._a) : local__createLocal(c._a); + this._isDSTShifted = this.isValid() && + compareArrays(c._a, other.toArray()) > 0; + } else { + this._isDSTShifted = false; + } + + return this._isDSTShifted; + } + + function isLocal () { + return this.isValid() ? !this._isUTC : false; + } + + function isUtcOffset () { + return this.isValid() ? this._isUTC : false; + } + + function isUtc () { + return this.isValid() ? this._isUTC && this._offset === 0 : false; + } + + // ASP.NET json date format regex + var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/; + + // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html + // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere + var isoRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/; + + function create__createDuration (input, key) { + var duration = input, + // matching against regexp is expensive, do it on demand + match = null, + sign, + ret, + diffRes; + + if (isDuration(input)) { + duration = { + ms : input._milliseconds, + d : input._days, + M : input._months + }; + } else if (typeof input === 'number') { + duration = {}; + if (key) { + duration[key] = input; + } else { + duration.milliseconds = input; + } + } else if (!!(match = aspNetRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y : 0, + d : toInt(match[DATE]) * sign, + h : toInt(match[HOUR]) * sign, + m : toInt(match[MINUTE]) * sign, + s : toInt(match[SECOND]) * sign, + ms : toInt(match[MILLISECOND]) * sign + }; + } else if (!!(match = isoRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y : parseIso(match[2], sign), + M : parseIso(match[3], sign), + d : parseIso(match[4], sign), + h : parseIso(match[5], sign), + m : parseIso(match[6], sign), + s : parseIso(match[7], sign), + w : parseIso(match[8], sign) + }; + } else if (duration == null) {// checks for null or undefined + duration = {}; + } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) { + diffRes = momentsDifference(local__createLocal(duration.from), local__createLocal(duration.to)); + + duration = {}; + duration.ms = diffRes.milliseconds; + duration.M = diffRes.months; + } + + ret = new Duration(duration); + + if (isDuration(input) && hasOwnProp(input, '_locale')) { + ret._locale = input._locale; + } + + return ret; + } + + create__createDuration.fn = Duration.prototype; + + function parseIso (inp, sign) { + // We'd normally use ~~inp for this, but unfortunately it also + // converts floats to ints. + // inp may be undefined, so careful calling replace on it. + var res = inp && parseFloat(inp.replace(',', '.')); + // apply sign while we're at it + return (isNaN(res) ? 0 : res) * sign; + } + + function positiveMomentsDifference(base, other) { + var res = {milliseconds: 0, months: 0}; + + res.months = other.month() - base.month() + + (other.year() - base.year()) * 12; + if (base.clone().add(res.months, 'M').isAfter(other)) { + --res.months; + } + + res.milliseconds = +other - +(base.clone().add(res.months, 'M')); + + return res; + } + + function momentsDifference(base, other) { + var res; + if (!(base.isValid() && other.isValid())) { + return {milliseconds: 0, months: 0}; + } + + other = cloneWithOffset(other, base); + if (base.isBefore(other)) { + res = positiveMomentsDifference(base, other); + } else { + res = positiveMomentsDifference(other, base); + res.milliseconds = -res.milliseconds; + res.months = -res.months; + } + + return res; + } + + // TODO: remove 'name' arg after deprecation is removed + function createAdder(direction, name) { + return function (val, period) { + var dur, tmp; + //invert the arguments, but complain about it + if (period !== null && !isNaN(+period)) { + deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).'); + tmp = val; val = period; period = tmp; + } + + val = typeof val === 'string' ? +val : val; + dur = create__createDuration(val, period); + add_subtract__addSubtract(this, dur, direction); + return this; + }; + } + + function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) { + var milliseconds = duration._milliseconds, + days = duration._days, + months = duration._months; + + if (!mom.isValid()) { + // No op + return; + } + + updateOffset = updateOffset == null ? true : updateOffset; + + if (milliseconds) { + mom._d.setTime(+mom._d + milliseconds * isAdding); + } + if (days) { + get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding); + } + if (months) { + setMonth(mom, get_set__get(mom, 'Month') + months * isAdding); + } + if (updateOffset) { + utils_hooks__hooks.updateOffset(mom, days || months); + } + } + + var add_subtract__add = createAdder(1, 'add'); + var add_subtract__subtract = createAdder(-1, 'subtract'); + + function moment_calendar__calendar (time, formats) { + // We want to compare the start of today, vs this. + // Getting start-of-today depends on whether we're local/utc/offset or not. + var now = time || local__createLocal(), + sod = cloneWithOffset(now, this).startOf('day'), + diff = this.diff(sod, 'days', true), + format = diff < -6 ? 'sameElse' : + diff < -1 ? 'lastWeek' : + diff < 0 ? 'lastDay' : + diff < 1 ? 'sameDay' : + diff < 2 ? 'nextDay' : + diff < 7 ? 'nextWeek' : 'sameElse'; + + var output = formats && (isFunction(formats[format]) ? formats[format]() : formats[format]); + + return this.format(output || this.localeData().calendar(format, this, local__createLocal(now))); + } + + function clone () { + return new Moment(this); + } + + function isAfter (input, units) { + var localInput = isMoment(input) ? input : local__createLocal(input); + if (!(this.isValid() && localInput.isValid())) { + return false; + } + units = normalizeUnits(!isUndefined(units) ? units : 'millisecond'); + if (units === 'millisecond') { + return +this > +localInput; + } else { + return +localInput < +this.clone().startOf(units); + } + } + + function isBefore (input, units) { + var localInput = isMoment(input) ? input : local__createLocal(input); + if (!(this.isValid() && localInput.isValid())) { + return false; + } + units = normalizeUnits(!isUndefined(units) ? units : 'millisecond'); + if (units === 'millisecond') { + return +this < +localInput; + } else { + return +this.clone().endOf(units) < +localInput; + } + } + + function isBetween (from, to, units) { + return this.isAfter(from, units) && this.isBefore(to, units); + } + + function isSame (input, units) { + var localInput = isMoment(input) ? input : local__createLocal(input), + inputMs; + if (!(this.isValid() && localInput.isValid())) { + return false; + } + units = normalizeUnits(units || 'millisecond'); + if (units === 'millisecond') { + return +this === +localInput; + } else { + inputMs = +localInput; + return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units)); + } + } + + function isSameOrAfter (input, units) { + return this.isSame(input, units) || this.isAfter(input,units); + } + + function isSameOrBefore (input, units) { + return this.isSame(input, units) || this.isBefore(input,units); + } + + function diff (input, units, asFloat) { + var that, + zoneDelta, + delta, output; + + if (!this.isValid()) { + return NaN; + } + + that = cloneWithOffset(input, this); + + if (!that.isValid()) { + return NaN; + } + + zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4; + + units = normalizeUnits(units); + + if (units === 'year' || units === 'month' || units === 'quarter') { + output = monthDiff(this, that); + if (units === 'quarter') { + output = output / 3; + } else if (units === 'year') { + output = output / 12; + } + } else { + delta = this - that; + output = units === 'second' ? delta / 1e3 : // 1000 + units === 'minute' ? delta / 6e4 : // 1000 * 60 + units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60 + units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst + units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst + delta; + } + return asFloat ? output : absFloor(output); + } + + function monthDiff (a, b) { + // difference in months + var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()), + // b is in (anchor - 1 month, anchor + 1 month) + anchor = a.clone().add(wholeMonthDiff, 'months'), + anchor2, adjust; + + if (b - anchor < 0) { + anchor2 = a.clone().add(wholeMonthDiff - 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor - anchor2); + } else { + anchor2 = a.clone().add(wholeMonthDiff + 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor2 - anchor); + } + + return -(wholeMonthDiff + adjust); + } + + utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ'; + + function toString () { + return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); + } + + function moment_format__toISOString () { + var m = this.clone().utc(); + if (0 < m.year() && m.year() <= 9999) { + if (isFunction(Date.prototype.toISOString)) { + // native implementation is ~50x faster, use it when we can + return this.toDate().toISOString(); + } else { + return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } + } else { + return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } + } + + function format (inputString) { + var output = formatMoment(this, inputString || utils_hooks__hooks.defaultFormat); + return this.localeData().postformat(output); + } + + function from (time, withoutSuffix) { + if (this.isValid() && + ((isMoment(time) && time.isValid()) || + local__createLocal(time).isValid())) { + return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix); + } else { + return this.localeData().invalidDate(); + } + } + + function fromNow (withoutSuffix) { + return this.from(local__createLocal(), withoutSuffix); + } + + function to (time, withoutSuffix) { + if (this.isValid() && + ((isMoment(time) && time.isValid()) || + local__createLocal(time).isValid())) { + return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix); + } else { + return this.localeData().invalidDate(); + } + } + + function toNow (withoutSuffix) { + return this.to(local__createLocal(), withoutSuffix); + } + + // If passed a locale key, it will set the locale for this + // instance. Otherwise, it will return the locale configuration + // variables for this instance. + function locale (key) { + var newLocaleData; + + if (key === undefined) { + return this._locale._abbr; + } else { + newLocaleData = locale_locales__getLocale(key); + if (newLocaleData != null) { + this._locale = newLocaleData; + } + return this; + } + } + + var lang = deprecate( + 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', + function (key) { + if (key === undefined) { + return this.localeData(); + } else { + return this.locale(key); + } + } + ); + + function localeData () { + return this._locale; + } + + function startOf (units) { + units = normalizeUnits(units); + // the following switch intentionally omits break keywords + // to utilize falling through the cases. + switch (units) { + case 'year': + this.month(0); + /* falls through */ + case 'quarter': + case 'month': + this.date(1); + /* falls through */ + case 'week': + case 'isoWeek': + case 'day': + this.hours(0); + /* falls through */ + case 'hour': + this.minutes(0); + /* falls through */ + case 'minute': + this.seconds(0); + /* falls through */ + case 'second': + this.milliseconds(0); + } + + // weeks are a special case + if (units === 'week') { + this.weekday(0); + } + if (units === 'isoWeek') { + this.isoWeekday(1); + } + + // quarters are also special + if (units === 'quarter') { + this.month(Math.floor(this.month() / 3) * 3); + } + + return this; + } + + function endOf (units) { + units = normalizeUnits(units); + if (units === undefined || units === 'millisecond') { + return this; + } + return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms'); + } + + function to_type__valueOf () { + return +this._d - ((this._offset || 0) * 60000); + } + + function unix () { + return Math.floor(+this / 1000); + } + + function toDate () { + return this._offset ? new Date(+this) : this._d; + } + + function toArray () { + var m = this; + return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()]; + } + + function toObject () { + var m = this; + return { + years: m.year(), + months: m.month(), + date: m.date(), + hours: m.hours(), + minutes: m.minutes(), + seconds: m.seconds(), + milliseconds: m.milliseconds() + }; + } + + function toJSON () { + // JSON.stringify(new Date(NaN)) === 'null' + return this.isValid() ? this.toISOString() : 'null'; + } + + function moment_valid__isValid () { + return valid__isValid(this); + } + + function parsingFlags () { + return extend({}, getParsingFlags(this)); + } + + function invalidAt () { + return getParsingFlags(this).overflow; + } + + function creationData() { + return { + input: this._i, + format: this._f, + locale: this._locale, + isUTC: this._isUTC, + strict: this._strict + }; + } + + // FORMATTING + + addFormatToken(0, ['gg', 2], 0, function () { + return this.weekYear() % 100; + }); + + addFormatToken(0, ['GG', 2], 0, function () { + return this.isoWeekYear() % 100; + }); + + function addWeekYearFormatToken (token, getter) { + addFormatToken(0, [token, token.length], 0, getter); + } + + addWeekYearFormatToken('gggg', 'weekYear'); + addWeekYearFormatToken('ggggg', 'weekYear'); + addWeekYearFormatToken('GGGG', 'isoWeekYear'); + addWeekYearFormatToken('GGGGG', 'isoWeekYear'); + + // ALIASES + + addUnitAlias('weekYear', 'gg'); + addUnitAlias('isoWeekYear', 'GG'); + + // PARSING + + addRegexToken('G', matchSigned); + addRegexToken('g', matchSigned); + addRegexToken('GG', match1to2, match2); + addRegexToken('gg', match1to2, match2); + addRegexToken('GGGG', match1to4, match4); + addRegexToken('gggg', match1to4, match4); + addRegexToken('GGGGG', match1to6, match6); + addRegexToken('ggggg', match1to6, match6); + + addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) { + week[token.substr(0, 2)] = toInt(input); + }); + + addWeekParseToken(['gg', 'GG'], function (input, week, config, token) { + week[token] = utils_hooks__hooks.parseTwoDigitYear(input); + }); + + // MOMENTS + + function getSetWeekYear (input) { + return getSetWeekYearHelper.call(this, + input, + this.week(), + this.weekday(), + this.localeData()._week.dow, + this.localeData()._week.doy); + } + + function getSetISOWeekYear (input) { + return getSetWeekYearHelper.call(this, + input, this.isoWeek(), this.isoWeekday(), 1, 4); + } + + function getISOWeeksInYear () { + return weeksInYear(this.year(), 1, 4); + } + + function getWeeksInYear () { + var weekInfo = this.localeData()._week; + return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); + } + + function getSetWeekYearHelper(input, week, weekday, dow, doy) { + var weeksTarget; + if (input == null) { + return weekOfYear(this, dow, doy).year; + } else { + weeksTarget = weeksInYear(input, dow, doy); + if (week > weeksTarget) { + week = weeksTarget; + } + return setWeekAll.call(this, input, week, weekday, dow, doy); + } + } + + function setWeekAll(weekYear, week, weekday, dow, doy) { + var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy), + date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear); + + // console.log("got", weekYear, week, weekday, "set", date.toISOString()); + this.year(date.getUTCFullYear()); + this.month(date.getUTCMonth()); + this.date(date.getUTCDate()); + return this; + } + + // FORMATTING + + addFormatToken('Q', 0, 'Qo', 'quarter'); + + // ALIASES + + addUnitAlias('quarter', 'Q'); + + // PARSING + + addRegexToken('Q', match1); + addParseToken('Q', function (input, array) { + array[MONTH] = (toInt(input) - 1) * 3; + }); + + // MOMENTS + + function getSetQuarter (input) { + return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); + } + + // FORMATTING + + addFormatToken('w', ['ww', 2], 'wo', 'week'); + addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek'); + + // ALIASES + + addUnitAlias('week', 'w'); + addUnitAlias('isoWeek', 'W'); + + // PARSING + + addRegexToken('w', match1to2); + addRegexToken('ww', match1to2, match2); + addRegexToken('W', match1to2); + addRegexToken('WW', match1to2, match2); + + addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) { + week[token.substr(0, 1)] = toInt(input); + }); + + // HELPERS + + // LOCALES + + function localeWeek (mom) { + return weekOfYear(mom, this._week.dow, this._week.doy).week; + } + + var defaultLocaleWeek = { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + }; + + function localeFirstDayOfWeek () { + return this._week.dow; + } + + function localeFirstDayOfYear () { + return this._week.doy; + } + + // MOMENTS + + function getSetWeek (input) { + var week = this.localeData().week(this); + return input == null ? week : this.add((input - week) * 7, 'd'); + } + + function getSetISOWeek (input) { + var week = weekOfYear(this, 1, 4).week; + return input == null ? week : this.add((input - week) * 7, 'd'); + } + + // FORMATTING + + addFormatToken('D', ['DD', 2], 'Do', 'date'); + + // ALIASES + + addUnitAlias('date', 'D'); + + // PARSING + + addRegexToken('D', match1to2); + addRegexToken('DD', match1to2, match2); + addRegexToken('Do', function (isStrict, locale) { + return isStrict ? locale._ordinalParse : locale._ordinalParseLenient; + }); + + addParseToken(['D', 'DD'], DATE); + addParseToken('Do', function (input, array) { + array[DATE] = toInt(input.match(match1to2)[0], 10); + }); + + // MOMENTS + + var getSetDayOfMonth = makeGetSet('Date', true); + + // FORMATTING + + addFormatToken('d', 0, 'do', 'day'); + + addFormatToken('dd', 0, 0, function (format) { + return this.localeData().weekdaysMin(this, format); + }); + + addFormatToken('ddd', 0, 0, function (format) { + return this.localeData().weekdaysShort(this, format); + }); + + addFormatToken('dddd', 0, 0, function (format) { + return this.localeData().weekdays(this, format); + }); + + addFormatToken('e', 0, 0, 'weekday'); + addFormatToken('E', 0, 0, 'isoWeekday'); + + // ALIASES + + addUnitAlias('day', 'd'); + addUnitAlias('weekday', 'e'); + addUnitAlias('isoWeekday', 'E'); + + // PARSING + + addRegexToken('d', match1to2); + addRegexToken('e', match1to2); + addRegexToken('E', match1to2); + addRegexToken('dd', matchWord); + addRegexToken('ddd', matchWord); + addRegexToken('dddd', matchWord); + + addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) { + var weekday = config._locale.weekdaysParse(input, token, config._strict); + // if we didn't get a weekday name, mark the date as invalid + if (weekday != null) { + week.d = weekday; + } else { + getParsingFlags(config).invalidWeekday = input; + } + }); + + addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) { + week[token] = toInt(input); + }); + + // HELPERS + + function parseWeekday(input, locale) { + if (typeof input !== 'string') { + return input; + } + + if (!isNaN(input)) { + return parseInt(input, 10); + } + + input = locale.weekdaysParse(input); + if (typeof input === 'number') { + return input; + } + + return null; + } + + // LOCALES + + var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'); + function localeWeekdays (m, format) { + return isArray(this._weekdays) ? this._weekdays[m.day()] : + this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()]; + } + + var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'); + function localeWeekdaysShort (m) { + return this._weekdaysShort[m.day()]; + } + + var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'); + function localeWeekdaysMin (m) { + return this._weekdaysMin[m.day()]; + } + + function localeWeekdaysParse (weekdayName, format, strict) { + var i, mom, regex; + + if (!this._weekdaysParse) { + this._weekdaysParse = []; + this._minWeekdaysParse = []; + this._shortWeekdaysParse = []; + this._fullWeekdaysParse = []; + } + + for (i = 0; i < 7; i++) { + // make the regex if we don't have it already + + mom = local__createLocal([2000, 1]).day(i); + if (strict && !this._fullWeekdaysParse[i]) { + this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i'); + this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i'); + this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i'); + } + if (!this._weekdaysParse[i]) { + regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); + this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) { + return i; + } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) { + return i; + } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) { + return i; + } else if (!strict && this._weekdaysParse[i].test(weekdayName)) { + return i; + } + } + } + + // MOMENTS + + function getSetDayOfWeek (input) { + if (!this.isValid()) { + return input != null ? this : NaN; + } + var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); + if (input != null) { + input = parseWeekday(input, this.localeData()); + return this.add(input - day, 'd'); + } else { + return day; + } + } + + function getSetLocaleDayOfWeek (input) { + if (!this.isValid()) { + return input != null ? this : NaN; + } + var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7; + return input == null ? weekday : this.add(input - weekday, 'd'); + } + + function getSetISODayOfWeek (input) { + if (!this.isValid()) { + return input != null ? this : NaN; + } + // behaves the same as moment#day except + // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) + // as a setter, sunday should belong to the previous week. + return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7); + } + + // FORMATTING + + addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear'); + + // ALIASES + + addUnitAlias('dayOfYear', 'DDD'); + + // PARSING + + addRegexToken('DDD', match1to3); + addRegexToken('DDDD', match3); + addParseToken(['DDD', 'DDDD'], function (input, array, config) { + config._dayOfYear = toInt(input); + }); + + // HELPERS + + // MOMENTS + + function getSetDayOfYear (input) { + var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1; + return input == null ? dayOfYear : this.add((input - dayOfYear), 'd'); + } + + // FORMATTING + + function hFormat() { + return this.hours() % 12 || 12; + } + + addFormatToken('H', ['HH', 2], 0, 'hour'); + addFormatToken('h', ['hh', 2], 0, hFormat); + + addFormatToken('hmm', 0, 0, function () { + return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2); + }); + + addFormatToken('hmmss', 0, 0, function () { + return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) + + zeroFill(this.seconds(), 2); + }); + + addFormatToken('Hmm', 0, 0, function () { + return '' + this.hours() + zeroFill(this.minutes(), 2); + }); + + addFormatToken('Hmmss', 0, 0, function () { + return '' + this.hours() + zeroFill(this.minutes(), 2) + + zeroFill(this.seconds(), 2); + }); + + function meridiem (token, lowercase) { + addFormatToken(token, 0, 0, function () { + return this.localeData().meridiem(this.hours(), this.minutes(), lowercase); + }); + } + + meridiem('a', true); + meridiem('A', false); + + // ALIASES + + addUnitAlias('hour', 'h'); + + // PARSING + + function matchMeridiem (isStrict, locale) { + return locale._meridiemParse; + } + + addRegexToken('a', matchMeridiem); + addRegexToken('A', matchMeridiem); + addRegexToken('H', match1to2); + addRegexToken('h', match1to2); + addRegexToken('HH', match1to2, match2); + addRegexToken('hh', match1to2, match2); + + addRegexToken('hmm', match3to4); + addRegexToken('hmmss', match5to6); + addRegexToken('Hmm', match3to4); + addRegexToken('Hmmss', match5to6); + + addParseToken(['H', 'HH'], HOUR); + addParseToken(['a', 'A'], function (input, array, config) { + config._isPm = config._locale.isPM(input); + config._meridiem = input; + }); + addParseToken(['h', 'hh'], function (input, array, config) { + array[HOUR] = toInt(input); + getParsingFlags(config).bigHour = true; + }); + addParseToken('hmm', function (input, array, config) { + var pos = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos)); + array[MINUTE] = toInt(input.substr(pos)); + getParsingFlags(config).bigHour = true; + }); + addParseToken('hmmss', function (input, array, config) { + var pos1 = input.length - 4; + var pos2 = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos1)); + array[MINUTE] = toInt(input.substr(pos1, 2)); + array[SECOND] = toInt(input.substr(pos2)); + getParsingFlags(config).bigHour = true; + }); + addParseToken('Hmm', function (input, array, config) { + var pos = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos)); + array[MINUTE] = toInt(input.substr(pos)); + }); + addParseToken('Hmmss', function (input, array, config) { + var pos1 = input.length - 4; + var pos2 = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos1)); + array[MINUTE] = toInt(input.substr(pos1, 2)); + array[SECOND] = toInt(input.substr(pos2)); + }); + + // LOCALES + + function localeIsPM (input) { + // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays + // Using charAt should be more compatible. + return ((input + '').toLowerCase().charAt(0) === 'p'); + } + + var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i; + function localeMeridiem (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'pm' : 'PM'; + } else { + return isLower ? 'am' : 'AM'; + } + } + + + // MOMENTS + + // Setting the hour should keep the time, because the user explicitly + // specified which hour he wants. So trying to maintain the same hour (in + // a new timezone) makes sense. Adding/subtracting hours does not follow + // this rule. + var getSetHour = makeGetSet('Hours', true); + + // FORMATTING + + addFormatToken('m', ['mm', 2], 0, 'minute'); + + // ALIASES + + addUnitAlias('minute', 'm'); + + // PARSING + + addRegexToken('m', match1to2); + addRegexToken('mm', match1to2, match2); + addParseToken(['m', 'mm'], MINUTE); + + // MOMENTS + + var getSetMinute = makeGetSet('Minutes', false); + + // FORMATTING + + addFormatToken('s', ['ss', 2], 0, 'second'); + + // ALIASES + + addUnitAlias('second', 's'); + + // PARSING + + addRegexToken('s', match1to2); + addRegexToken('ss', match1to2, match2); + addParseToken(['s', 'ss'], SECOND); + + // MOMENTS + + var getSetSecond = makeGetSet('Seconds', false); + + // FORMATTING + + addFormatToken('S', 0, 0, function () { + return ~~(this.millisecond() / 100); + }); + + addFormatToken(0, ['SS', 2], 0, function () { + return ~~(this.millisecond() / 10); + }); + + addFormatToken(0, ['SSS', 3], 0, 'millisecond'); + addFormatToken(0, ['SSSS', 4], 0, function () { + return this.millisecond() * 10; + }); + addFormatToken(0, ['SSSSS', 5], 0, function () { + return this.millisecond() * 100; + }); + addFormatToken(0, ['SSSSSS', 6], 0, function () { + return this.millisecond() * 1000; + }); + addFormatToken(0, ['SSSSSSS', 7], 0, function () { + return this.millisecond() * 10000; + }); + addFormatToken(0, ['SSSSSSSS', 8], 0, function () { + return this.millisecond() * 100000; + }); + addFormatToken(0, ['SSSSSSSSS', 9], 0, function () { + return this.millisecond() * 1000000; + }); + + + // ALIASES + + addUnitAlias('millisecond', 'ms'); + + // PARSING + + addRegexToken('S', match1to3, match1); + addRegexToken('SS', match1to3, match2); + addRegexToken('SSS', match1to3, match3); + + var token; + for (token = 'SSSS'; token.length <= 9; token += 'S') { + addRegexToken(token, matchUnsigned); + } + + function parseMs(input, array) { + array[MILLISECOND] = toInt(('0.' + input) * 1000); + } + + for (token = 'S'; token.length <= 9; token += 'S') { + addParseToken(token, parseMs); + } + // MOMENTS + + var getSetMillisecond = makeGetSet('Milliseconds', false); + + // FORMATTING + + addFormatToken('z', 0, 0, 'zoneAbbr'); + addFormatToken('zz', 0, 0, 'zoneName'); + + // MOMENTS + + function getZoneAbbr () { + return this._isUTC ? 'UTC' : ''; + } + + function getZoneName () { + return this._isUTC ? 'Coordinated Universal Time' : ''; + } + + var momentPrototype__proto = Moment.prototype; + + momentPrototype__proto.add = add_subtract__add; + momentPrototype__proto.calendar = moment_calendar__calendar; + momentPrototype__proto.clone = clone; + momentPrototype__proto.diff = diff; + momentPrototype__proto.endOf = endOf; + momentPrototype__proto.format = format; + momentPrototype__proto.from = from; + momentPrototype__proto.fromNow = fromNow; + momentPrototype__proto.to = to; + momentPrototype__proto.toNow = toNow; + momentPrototype__proto.get = getSet; + momentPrototype__proto.invalidAt = invalidAt; + momentPrototype__proto.isAfter = isAfter; + momentPrototype__proto.isBefore = isBefore; + momentPrototype__proto.isBetween = isBetween; + momentPrototype__proto.isSame = isSame; + momentPrototype__proto.isSameOrAfter = isSameOrAfter; + momentPrototype__proto.isSameOrBefore = isSameOrBefore; + momentPrototype__proto.isValid = moment_valid__isValid; + momentPrototype__proto.lang = lang; + momentPrototype__proto.locale = locale; + momentPrototype__proto.localeData = localeData; + momentPrototype__proto.max = prototypeMax; + momentPrototype__proto.min = prototypeMin; + momentPrototype__proto.parsingFlags = parsingFlags; + momentPrototype__proto.set = getSet; + momentPrototype__proto.startOf = startOf; + momentPrototype__proto.subtract = add_subtract__subtract; + momentPrototype__proto.toArray = toArray; + momentPrototype__proto.toObject = toObject; + momentPrototype__proto.toDate = toDate; + momentPrototype__proto.toISOString = moment_format__toISOString; + momentPrototype__proto.toJSON = toJSON; + momentPrototype__proto.toString = toString; + momentPrototype__proto.unix = unix; + momentPrototype__proto.valueOf = to_type__valueOf; + momentPrototype__proto.creationData = creationData; + + // Year + momentPrototype__proto.year = getSetYear; + momentPrototype__proto.isLeapYear = getIsLeapYear; + + // Week Year + momentPrototype__proto.weekYear = getSetWeekYear; + momentPrototype__proto.isoWeekYear = getSetISOWeekYear; + + // Quarter + momentPrototype__proto.quarter = momentPrototype__proto.quarters = getSetQuarter; + + // Month + momentPrototype__proto.month = getSetMonth; + momentPrototype__proto.daysInMonth = getDaysInMonth; + + // Week + momentPrototype__proto.week = momentPrototype__proto.weeks = getSetWeek; + momentPrototype__proto.isoWeek = momentPrototype__proto.isoWeeks = getSetISOWeek; + momentPrototype__proto.weeksInYear = getWeeksInYear; + momentPrototype__proto.isoWeeksInYear = getISOWeeksInYear; + + // Day + momentPrototype__proto.date = getSetDayOfMonth; + momentPrototype__proto.day = momentPrototype__proto.days = getSetDayOfWeek; + momentPrototype__proto.weekday = getSetLocaleDayOfWeek; + momentPrototype__proto.isoWeekday = getSetISODayOfWeek; + momentPrototype__proto.dayOfYear = getSetDayOfYear; + + // Hour + momentPrototype__proto.hour = momentPrototype__proto.hours = getSetHour; + + // Minute + momentPrototype__proto.minute = momentPrototype__proto.minutes = getSetMinute; + + // Second + momentPrototype__proto.second = momentPrototype__proto.seconds = getSetSecond; + + // Millisecond + momentPrototype__proto.millisecond = momentPrototype__proto.milliseconds = getSetMillisecond; + + // Offset + momentPrototype__proto.utcOffset = getSetOffset; + momentPrototype__proto.utc = setOffsetToUTC; + momentPrototype__proto.local = setOffsetToLocal; + momentPrototype__proto.parseZone = setOffsetToParsedOffset; + momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset; + momentPrototype__proto.isDST = isDaylightSavingTime; + momentPrototype__proto.isDSTShifted = isDaylightSavingTimeShifted; + momentPrototype__proto.isLocal = isLocal; + momentPrototype__proto.isUtcOffset = isUtcOffset; + momentPrototype__proto.isUtc = isUtc; + momentPrototype__proto.isUTC = isUtc; + + // Timezone + momentPrototype__proto.zoneAbbr = getZoneAbbr; + momentPrototype__proto.zoneName = getZoneName; + + // Deprecations + momentPrototype__proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth); + momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth); + momentPrototype__proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear); + momentPrototype__proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779', getSetZone); + + var momentPrototype = momentPrototype__proto; + + function moment__createUnix (input) { + return local__createLocal(input * 1000); + } + + function moment__createInZone () { + return local__createLocal.apply(null, arguments).parseZone(); + } + + var defaultCalendar = { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }; + + function locale_calendar__calendar (key, mom, now) { + var output = this._calendar[key]; + return isFunction(output) ? output.call(mom, now) : output; + } + + var defaultLongDateFormat = { + LTS : 'h:mm:ss A', + LT : 'h:mm A', + L : 'MM/DD/YYYY', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY h:mm A', + LLLL : 'dddd, MMMM D, YYYY h:mm A' + }; + + function longDateFormat (key) { + var format = this._longDateFormat[key], + formatUpper = this._longDateFormat[key.toUpperCase()]; + + if (format || !formatUpper) { + return format; + } + + this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) { + return val.slice(1); + }); + + return this._longDateFormat[key]; + } + + var defaultInvalidDate = 'Invalid date'; + + function invalidDate () { + return this._invalidDate; + } + + var defaultOrdinal = '%d'; + var defaultOrdinalParse = /\d{1,2}/; + + function ordinal (number) { + return this._ordinal.replace('%d', number); + } + + function preParsePostFormat (string) { + return string; + } + + var defaultRelativeTime = { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }; + + function relative__relativeTime (number, withoutSuffix, string, isFuture) { + var output = this._relativeTime[string]; + return (isFunction(output)) ? + output(number, withoutSuffix, string, isFuture) : + output.replace(/%d/i, number); + } + + function pastFuture (diff, output) { + var format = this._relativeTime[diff > 0 ? 'future' : 'past']; + return isFunction(format) ? format(output) : format.replace(/%s/i, output); + } + + function locale_set__set (config) { + var prop, i; + for (i in config) { + prop = config[i]; + if (isFunction(prop)) { + this[i] = prop; + } else { + this['_' + i] = prop; + } + } + // Lenient ordinal parsing accepts just a number in addition to + // number + (possibly) stuff coming from _ordinalParseLenient. + this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\d{1,2}/).source); + } + + var prototype__proto = Locale.prototype; + + prototype__proto._calendar = defaultCalendar; + prototype__proto.calendar = locale_calendar__calendar; + prototype__proto._longDateFormat = defaultLongDateFormat; + prototype__proto.longDateFormat = longDateFormat; + prototype__proto._invalidDate = defaultInvalidDate; + prototype__proto.invalidDate = invalidDate; + prototype__proto._ordinal = defaultOrdinal; + prototype__proto.ordinal = ordinal; + prototype__proto._ordinalParse = defaultOrdinalParse; + prototype__proto.preparse = preParsePostFormat; + prototype__proto.postformat = preParsePostFormat; + prototype__proto._relativeTime = defaultRelativeTime; + prototype__proto.relativeTime = relative__relativeTime; + prototype__proto.pastFuture = pastFuture; + prototype__proto.set = locale_set__set; + + // Month + prototype__proto.months = localeMonths; + prototype__proto._months = defaultLocaleMonths; + prototype__proto.monthsShort = localeMonthsShort; + prototype__proto._monthsShort = defaultLocaleMonthsShort; + prototype__proto.monthsParse = localeMonthsParse; + prototype__proto._monthsRegex = defaultMonthsRegex; + prototype__proto.monthsRegex = monthsRegex; + prototype__proto._monthsShortRegex = defaultMonthsShortRegex; + prototype__proto.monthsShortRegex = monthsShortRegex; + + // Week + prototype__proto.week = localeWeek; + prototype__proto._week = defaultLocaleWeek; + prototype__proto.firstDayOfYear = localeFirstDayOfYear; + prototype__proto.firstDayOfWeek = localeFirstDayOfWeek; + + // Day of Week + prototype__proto.weekdays = localeWeekdays; + prototype__proto._weekdays = defaultLocaleWeekdays; + prototype__proto.weekdaysMin = localeWeekdaysMin; + prototype__proto._weekdaysMin = defaultLocaleWeekdaysMin; + prototype__proto.weekdaysShort = localeWeekdaysShort; + prototype__proto._weekdaysShort = defaultLocaleWeekdaysShort; + prototype__proto.weekdaysParse = localeWeekdaysParse; + + // Hours + prototype__proto.isPM = localeIsPM; + prototype__proto._meridiemParse = defaultLocaleMeridiemParse; + prototype__proto.meridiem = localeMeridiem; + + function lists__get (format, index, field, setter) { + var locale = locale_locales__getLocale(); + var utc = create_utc__createUTC().set(setter, index); + return locale[field](utc, format); + } + + function list (format, index, field, count, setter) { + if (typeof format === 'number') { + index = format; + format = undefined; + } + + format = format || ''; + + if (index != null) { + return lists__get(format, index, field, setter); + } + + var i; + var out = []; + for (i = 0; i < count; i++) { + out[i] = lists__get(format, i, field, setter); + } + return out; + } + + function lists__listMonths (format, index) { + return list(format, index, 'months', 12, 'month'); + } + + function lists__listMonthsShort (format, index) { + return list(format, index, 'monthsShort', 12, 'month'); + } + + function lists__listWeekdays (format, index) { + return list(format, index, 'weekdays', 7, 'day'); + } + + function lists__listWeekdaysShort (format, index) { + return list(format, index, 'weekdaysShort', 7, 'day'); + } + + function lists__listWeekdaysMin (format, index) { + return list(format, index, 'weekdaysMin', 7, 'day'); + } + + locale_locales__getSetGlobalLocale('en', { + ordinalParse: /\d{1,2}(th|st|nd|rd)/, + ordinal : function (number) { + var b = number % 10, + output = (toInt(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } + }); + + // Side effect imports + utils_hooks__hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', locale_locales__getSetGlobalLocale); + utils_hooks__hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', locale_locales__getLocale); + + var mathAbs = Math.abs; + + function duration_abs__abs () { + var data = this._data; + + this._milliseconds = mathAbs(this._milliseconds); + this._days = mathAbs(this._days); + this._months = mathAbs(this._months); + + data.milliseconds = mathAbs(data.milliseconds); + data.seconds = mathAbs(data.seconds); + data.minutes = mathAbs(data.minutes); + data.hours = mathAbs(data.hours); + data.months = mathAbs(data.months); + data.years = mathAbs(data.years); + + return this; + } + + function duration_add_subtract__addSubtract (duration, input, value, direction) { + var other = create__createDuration(input, value); + + duration._milliseconds += direction * other._milliseconds; + duration._days += direction * other._days; + duration._months += direction * other._months; + + return duration._bubble(); + } + + // supports only 2.0-style add(1, 's') or add(duration) + function duration_add_subtract__add (input, value) { + return duration_add_subtract__addSubtract(this, input, value, 1); + } + + // supports only 2.0-style subtract(1, 's') or subtract(duration) + function duration_add_subtract__subtract (input, value) { + return duration_add_subtract__addSubtract(this, input, value, -1); + } + + function absCeil (number) { + if (number < 0) { + return Math.floor(number); + } else { + return Math.ceil(number); + } + } + + function bubble () { + var milliseconds = this._milliseconds; + var days = this._days; + var months = this._months; + var data = this._data; + var seconds, minutes, hours, years, monthsFromDays; + + // if we have a mix of positive and negative values, bubble down first + // check: https://github.com/moment/moment/issues/2166 + if (!((milliseconds >= 0 && days >= 0 && months >= 0) || + (milliseconds <= 0 && days <= 0 && months <= 0))) { + milliseconds += absCeil(monthsToDays(months) + days) * 864e5; + days = 0; + months = 0; + } + + // The following code bubbles up values, see the tests for + // examples of what that means. + data.milliseconds = milliseconds % 1000; + + seconds = absFloor(milliseconds / 1000); + data.seconds = seconds % 60; + + minutes = absFloor(seconds / 60); + data.minutes = minutes % 60; + + hours = absFloor(minutes / 60); + data.hours = hours % 24; + + days += absFloor(hours / 24); + + // convert days to months + monthsFromDays = absFloor(daysToMonths(days)); + months += monthsFromDays; + days -= absCeil(monthsToDays(monthsFromDays)); + + // 12 months -> 1 year + years = absFloor(months / 12); + months %= 12; + + data.days = days; + data.months = months; + data.years = years; + + return this; + } + + function daysToMonths (days) { + // 400 years have 146097 days (taking into account leap year rules) + // 400 years have 12 months === 4800 + return days * 4800 / 146097; + } + + function monthsToDays (months) { + // the reverse of daysToMonths + return months * 146097 / 4800; + } + + function as (units) { + var days; + var months; + var milliseconds = this._milliseconds; + + units = normalizeUnits(units); + + if (units === 'month' || units === 'year') { + days = this._days + milliseconds / 864e5; + months = this._months + daysToMonths(days); + return units === 'month' ? months : months / 12; + } else { + // handle milliseconds separately because of floating point math errors (issue #1867) + days = this._days + Math.round(monthsToDays(this._months)); + switch (units) { + case 'week' : return days / 7 + milliseconds / 6048e5; + case 'day' : return days + milliseconds / 864e5; + case 'hour' : return days * 24 + milliseconds / 36e5; + case 'minute' : return days * 1440 + milliseconds / 6e4; + case 'second' : return days * 86400 + milliseconds / 1000; + // Math.floor prevents floating point math errors here + case 'millisecond': return Math.floor(days * 864e5) + milliseconds; + default: throw new Error('Unknown unit ' + units); + } + } + } + + // TODO: Use this.as('ms')? + function duration_as__valueOf () { + return ( + this._milliseconds + + this._days * 864e5 + + (this._months % 12) * 2592e6 + + toInt(this._months / 12) * 31536e6 + ); + } + + function makeAs (alias) { + return function () { + return this.as(alias); + }; + } + + var asMilliseconds = makeAs('ms'); + var asSeconds = makeAs('s'); + var asMinutes = makeAs('m'); + var asHours = makeAs('h'); + var asDays = makeAs('d'); + var asWeeks = makeAs('w'); + var asMonths = makeAs('M'); + var asYears = makeAs('y'); + + function duration_get__get (units) { + units = normalizeUnits(units); + return this[units + 's'](); + } + + function makeGetter(name) { + return function () { + return this._data[name]; + }; + } + + var milliseconds = makeGetter('milliseconds'); + var seconds = makeGetter('seconds'); + var minutes = makeGetter('minutes'); + var hours = makeGetter('hours'); + var days = makeGetter('days'); + var months = makeGetter('months'); + var years = makeGetter('years'); + + function weeks () { + return absFloor(this.days() / 7); + } + + var round = Math.round; + var thresholds = { + s: 45, // seconds to minute + m: 45, // minutes to hour + h: 22, // hours to day + d: 26, // days to month + M: 11 // months to year + }; + + // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize + function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) { + return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture); + } + + function duration_humanize__relativeTime (posNegDuration, withoutSuffix, locale) { + var duration = create__createDuration(posNegDuration).abs(); + var seconds = round(duration.as('s')); + var minutes = round(duration.as('m')); + var hours = round(duration.as('h')); + var days = round(duration.as('d')); + var months = round(duration.as('M')); + var years = round(duration.as('y')); + + var a = seconds < thresholds.s && ['s', seconds] || + minutes <= 1 && ['m'] || + minutes < thresholds.m && ['mm', minutes] || + hours <= 1 && ['h'] || + hours < thresholds.h && ['hh', hours] || + days <= 1 && ['d'] || + days < thresholds.d && ['dd', days] || + months <= 1 && ['M'] || + months < thresholds.M && ['MM', months] || + years <= 1 && ['y'] || ['yy', years]; + + a[2] = withoutSuffix; + a[3] = +posNegDuration > 0; + a[4] = locale; + return substituteTimeAgo.apply(null, a); + } + + // This function allows you to set a threshold for relative time strings + function duration_humanize__getSetRelativeTimeThreshold (threshold, limit) { + if (thresholds[threshold] === undefined) { + return false; + } + if (limit === undefined) { + return thresholds[threshold]; + } + thresholds[threshold] = limit; + return true; + } + + function humanize (withSuffix) { + var locale = this.localeData(); + var output = duration_humanize__relativeTime(this, !withSuffix, locale); + + if (withSuffix) { + output = locale.pastFuture(+this, output); + } + + return locale.postformat(output); + } + + var iso_string__abs = Math.abs; + + function iso_string__toISOString() { + // for ISO strings we do not use the normal bubbling rules: + // * milliseconds bubble up until they become hours + // * days do not bubble at all + // * months bubble up until they become years + // This is because there is no context-free conversion between hours and days + // (think of clock changes) + // and also not between days and months (28-31 days per month) + var seconds = iso_string__abs(this._milliseconds) / 1000; + var days = iso_string__abs(this._days); + var months = iso_string__abs(this._months); + var minutes, hours, years; + + // 3600 seconds -> 60 minutes -> 1 hour + minutes = absFloor(seconds / 60); + hours = absFloor(minutes / 60); + seconds %= 60; + minutes %= 60; + + // 12 months -> 1 year + years = absFloor(months / 12); + months %= 12; + + + // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js + var Y = years; + var M = months; + var D = days; + var h = hours; + var m = minutes; + var s = seconds; + var total = this.asSeconds(); + + if (!total) { + // this is the same as C#'s (Noda) and python (isodate)... + // but not other JS (goog.date) + return 'P0D'; + } + + return (total < 0 ? '-' : '') + + 'P' + + (Y ? Y + 'Y' : '') + + (M ? M + 'M' : '') + + (D ? D + 'D' : '') + + ((h || m || s) ? 'T' : '') + + (h ? h + 'H' : '') + + (m ? m + 'M' : '') + + (s ? s + 'S' : ''); + } + + var duration_prototype__proto = Duration.prototype; + + duration_prototype__proto.abs = duration_abs__abs; + duration_prototype__proto.add = duration_add_subtract__add; + duration_prototype__proto.subtract = duration_add_subtract__subtract; + duration_prototype__proto.as = as; + duration_prototype__proto.asMilliseconds = asMilliseconds; + duration_prototype__proto.asSeconds = asSeconds; + duration_prototype__proto.asMinutes = asMinutes; + duration_prototype__proto.asHours = asHours; + duration_prototype__proto.asDays = asDays; + duration_prototype__proto.asWeeks = asWeeks; + duration_prototype__proto.asMonths = asMonths; + duration_prototype__proto.asYears = asYears; + duration_prototype__proto.valueOf = duration_as__valueOf; + duration_prototype__proto._bubble = bubble; + duration_prototype__proto.get = duration_get__get; + duration_prototype__proto.milliseconds = milliseconds; + duration_prototype__proto.seconds = seconds; + duration_prototype__proto.minutes = minutes; + duration_prototype__proto.hours = hours; + duration_prototype__proto.days = days; + duration_prototype__proto.weeks = weeks; + duration_prototype__proto.months = months; + duration_prototype__proto.years = years; + duration_prototype__proto.humanize = humanize; + duration_prototype__proto.toISOString = iso_string__toISOString; + duration_prototype__proto.toString = iso_string__toISOString; + duration_prototype__proto.toJSON = iso_string__toISOString; + duration_prototype__proto.locale = locale; + duration_prototype__proto.localeData = localeData; + + // Deprecations + duration_prototype__proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', iso_string__toISOString); + duration_prototype__proto.lang = lang; + + // Side effect imports + + // FORMATTING + + addFormatToken('X', 0, 0, 'unix'); + addFormatToken('x', 0, 0, 'valueOf'); + + // PARSING + + addRegexToken('x', matchSigned); + addRegexToken('X', matchTimestamp); + addParseToken('X', function (input, array, config) { + config._d = new Date(parseFloat(input, 10) * 1000); + }); + addParseToken('x', function (input, array, config) { + config._d = new Date(toInt(input)); + }); + + // Side effect imports + + + utils_hooks__hooks.version = '2.11.2'; + + setHookCallback(local__createLocal); + + utils_hooks__hooks.fn = momentPrototype; + utils_hooks__hooks.min = min; + utils_hooks__hooks.max = max; + utils_hooks__hooks.now = now; + utils_hooks__hooks.utc = create_utc__createUTC; + utils_hooks__hooks.unix = moment__createUnix; + utils_hooks__hooks.months = lists__listMonths; + utils_hooks__hooks.isDate = isDate; + utils_hooks__hooks.locale = locale_locales__getSetGlobalLocale; + utils_hooks__hooks.invalid = valid__createInvalid; + utils_hooks__hooks.duration = create__createDuration; + utils_hooks__hooks.isMoment = isMoment; + utils_hooks__hooks.weekdays = lists__listWeekdays; + utils_hooks__hooks.parseZone = moment__createInZone; + utils_hooks__hooks.localeData = locale_locales__getLocale; + utils_hooks__hooks.isDuration = isDuration; + utils_hooks__hooks.monthsShort = lists__listMonthsShort; + utils_hooks__hooks.weekdaysMin = lists__listWeekdaysMin; + utils_hooks__hooks.defineLocale = defineLocale; + utils_hooks__hooks.weekdaysShort = lists__listWeekdaysShort; + utils_hooks__hooks.normalizeUnits = normalizeUnits; + utils_hooks__hooks.relativeTimeThreshold = duration_humanize__getSetRelativeTimeThreshold; + utils_hooks__hooks.prototype = momentPrototype; + + var _moment = utils_hooks__hooks; + + return _moment; + +})); \ No newline at end of file diff --git a/common/views/links.html b/common/views/links.html index c74e3c0ee..68404601e 100644 --- a/common/views/links.html +++ b/common/views/links.html @@ -5,14 +5,28 @@
    diff --git a/damage/css/edgy.css b/damage/css/edgy.css index 795515977..8dd648bcb 100644 --- a/damage/css/edgy.css +++ b/damage/css/edgy.css @@ -2,7 +2,7 @@ html, body { background-color: #2b303b; } -#hp-rcv, .tip { +#hp-rcv, .tip, #turnLabel, #healLabel { color: white; } diff --git a/damage/css/main.css b/damage/css/main.css index e2fac298f..2b81656c1 100644 --- a/damage/css/main.css +++ b/damage/css/main.css @@ -1,12 +1,12 @@ @font-face { - font-family: 'icomoon'; - src:url('../../res/icomoon.eot?xewvs9'); - src:url('../../res/icomoon.eot?xewvs9#iefix') format('embedded-opentype'), - url('../../res/icomoon.ttf?xewvs9') format('truetype'), - url('../../res/icomoon.woff?xewvs9') format('woff'), - url('../../res/icomoon.svg?xewvs9#icomoon') format('svg'); - font-weight: normal; - font-style: normal; + font-family: 'icomoon'; + src:url('../../res/icomoon.eot?xewvs9'); + src:url('../../res/icomoon.eot?xewvs9#iefix') format('embedded-opentype'), + url('../../res/icomoon.ttf?xewvs9') format('truetype'), + url('../../res/icomoon.woff?xewvs9') format('woff'), + url('../../res/icomoon.svg?xewvs9#icomoon') format('svg'); + font-weight: normal; + font-style: normal; } /*************** @@ -101,6 +101,16 @@ body, html { -webkit-animation-duration: 0.5s !important; } +#instructions { + padding-left:10px +} + +#instructions > ul { + list-style-type: none; + margin-left: 15px; +} + + /****************** * MAIN UNIT PANE * ******************/ @@ -321,13 +331,13 @@ body, html { * BUTTONS & HP BAR * ********************/ -#hpSlider, #turnSlider { +#hpSlider, #turnSlider, #healSlider { width: 350px; height: 12px; display: inline-block; } -#turnSlider { +#turnSlider, #healSlider { width: 300px; } @@ -335,6 +345,10 @@ body, html { background: orchid; } +#heals > .noUi-connect { + background: green; +} + .noUi-handle { width: 24px !important; height: 18px !important; @@ -458,11 +472,13 @@ body, html { #menu { position: fixed; top: 0px; - left: -17.9em; - width: 17.9em; + left: -20.9em; + width: 20.9em; height: 100%; transition: left .1s linear; margin-bottom: 0; + overflow-y: scroll; + overflow-x: hidden; } #menu.open { @@ -550,7 +566,7 @@ li.disabled { } .special > div, #profileContainer { - width: 249px; + width: 270px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -928,8 +944,8 @@ nav > li > div { .unitCandies { position: absolute; - bottom: 2px; - left: 7px; + top: 5px; + right: 40px; z-index: 4; font-weight: bold; color: gold; @@ -938,6 +954,23 @@ nav > li > div { 0 0 black, 0 1px black, 1px 0 black, 1px 1px black, 0 -1px black, -1px 0 black, -1px -1px black; } +.unitSailor { + position: absolute; + width: 19px; + height: 21px; + bottom: -1px; + z-index: 4; + font-size: 9pt; + color: powderblue; + border: 2px solid gold; + border-left: 1px solid black; + border-radius: 4px; + background-color: SteelBlue; + pointer-events: none; + text-shadow: 2px 0 0 #003366, -2px 0 0 #003366, 0 2px 0 #003366, 0 -2px 0 #003366, 1px 1px #003366, -1px -1px 0 #003366, 1px -1px 0 #003366, -1px 1px 0 #003366; + box-shadow: inset 0px 0px 1px blue, 0px 0px 1px blue; +} + .unitAbilities { width: 20px; height: 20px; @@ -1030,10 +1063,11 @@ body > .popover .popover-content { .popover-data .DEX { background: lightgreen; } .popover-data .PSY { background: gold; } .popover-data .INT { background: orchid; } -.popover-data .RCV { background: sandybrown; } +.popover-data .RCV { background: darkgoldenrod; } .popover-data .TND { background: peru; } .popover-data .BLOCK { background: darkslateblue; } .popover-data .BOMB { background: maroon; } +.popover-data .RAINBOW { background: magenta; } .popover-data .G { background: orange; } .block-icon:before, .tnd-icon:before { @@ -1143,3 +1177,4 @@ body > .popover .popover-content { } } + diff --git a/damage/css/orbs.css b/damage/css/orbs.css index 3bd28ef72..2a6d25524 100644 --- a/damage/css/orbs.css +++ b/damage/css/orbs.css @@ -50,6 +50,24 @@ background-image: radial-gradient(9px 3px, circle cover, oldlace, orange, orangered); } +.unitOrb.S { + background-image: -webkit-radial-gradient(9px 3px, circle cover, oldlace, orangered, rgb(50,50,50)); + background-image: -moz-radial-gradient(9px 3px, circle cover, oldlace, orangered, rgb(50,50,50)); + background-image: radial-gradient(9px 3px, circle cover, oldlace, orangered, rgb(50,50,50)); +} + +.unitOrb.R { + background-image: -webkit-radial-gradient(9px 3px, circle cover, oldlace, pink, magenta); + background-image: -moz-radial-gradient(9px 3px, circle cover, oldlace, pink, magenta); + background-image: radial-gradient(9px 3px, circle cover, oldlace, pink, magenta); +} + +.unitOrb.M { + background-image: -webkit-radial-gradient(9px 3px, circle cover, oldlace, darkgoldenrod, saddlebrown); + background-image: -moz-radial-gradient(9px 3px, circle cover, oldlace, darkgoldenrod, saddlebrown); + background-image: radial-gradient(9px 3px, circle cover, oldlace, darkgoldenrod, saddlebrown); +} + .unitOrb .fa { position: relative; font-size: 2em; @@ -70,6 +88,39 @@ top: 1px; } +.str-orb { + color: white; + font-weight: bold; + font-style: normal; + font-size: 18px; + margin-right: 2px; + text-shadow: 0 0 5px black; + position: relative; + top: 1px; +} + +.rainbow-orb { + color: white; + font-weight: bold; + font-style: normal; + font-size: 18px; + margin-right: 2px; + text-shadow: 0 0 5px black; + position: relative; + top: 1px; +} + +.meat-orb { + color: white; + font-weight: bold; + font-style: normal; + font-size: 18px; + margin-right: 2px; + text-shadow: 0 0 5px black; + position: relative; + top: 1px; +} + /*********************** * ORB GLOWING * ***********************/ @@ -80,6 +131,8 @@ .unitOrb.PSY { animation: glowOrange .5s linear infinite alternate; } .unitOrb.INT { animation: glowPurple .5s linear infinite alternate; } .unitOrb.G { animation: glowG .5s linear infinite alternate; } +.unitOrb.S { animation: glowS .5s linear infinite alternate; } +.unitOrb.R { animation: glowR .5s linear infinite alternate; } .unitOrb.opposite { animation: glowBlack .5s linear infinite alternate; } @keyframes glowRed { @@ -116,3 +169,13 @@ from { box-shadow 0 0 10px white, 0 0 20px white, 0 0 30px white, 0 0 40px orangered, 0 0 70px orangered, 0 0 80px orangered, 0 0 100px orangered, 0 0 150px orangered; } to { box-shadow: 0 0 5px white, 0 0 10px white, 0 0 15px white, 0 0 20px orangered, 0 0 35px orangered, 0 0 40px orangered, 0 0 50px orangered, 0 0 75px orangered; } } + +@keyframes glowS { + from { box-shadow 0 0 10px white, 0 0 20px white, 0 0 30px white, 0 0 40px red, 0 0 70px red, 0 0 80px red, 0 0 100px red, 0 0 150px red; } + to { box-shadow: 0 0 5px white, 0 0 10px white, 0 0 15px white, 0 0 20px red, 0 0 35px red, 0 0 40px red, 0 0 50px red, 0 0 75px red; } +} + +@keyframes glowR { + from { box-shadow 0 0 10px white, 0 0 20px white, 0 0 30px white, 0 0 40px magenta, 0 0 70px magenta, 0 0 80px magenta, 0 0 100px magenta, 0 0 150px magenta; } + to { box-shadow: 0 0 5px white, 0 0 10px white, 0 0 15px white, 0 0 20px magenta, 0 0 35px magenta, 0 0 40px magenta, 0 0 50px magenta, 0 0 75px magenta; } +} diff --git a/damage/index.html b/damage/index.html index 2bfdfa7ed..c224e8f23 100644 --- a/damage/index.html +++ b/damage/index.html @@ -5,7 +5,9 @@ - + + + One Piece Treasure Cruise Damage Calculator @@ -32,6 +34,7 @@ + @@ -83,8 +86,9 @@ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); - ga('create', 'UA-64769042-1', 'auto'); + }) + (window,document,'script','//www.google-analytics.com/analytics.js','ga'); + ga('create', 'UA-73715806-1', 'auto'); ga('send', 'pageview', '/damage'); @@ -95,7 +99,8 @@
    - + + diff --git a/damage/js/app.js b/damage/js/app.js index 1c26c4e88..43800f26c 100644 --- a/damage/js/app.js +++ b/damage/js/app.js @@ -9,7 +9,7 @@ var app = angular.module('optc', [ 'ui.router', 'ui.bootstrap', 'ngSanitize', 'n var SharedRootCtrl = function($scope, $rootScope, $timeout) { $rootScope.data = { - + //setting default values team: [ { unit: null, level: -1, candies: { hp: 0, atk: 0, rcv: 0 } }, { unit: null, level: -1, candies: { hp: 0, atk: 0, rcv: 0 } }, @@ -20,8 +20,8 @@ var SharedRootCtrl = function($scope, $rootScope, $timeout) { ], percHP: 100.0, - - ship: [ 1, 5 ], + + ship: [ 1, 10 ], defense: 0, @@ -50,7 +50,12 @@ var SharedRootCtrl = function($scope, $rootScope, $timeout) { turnCounter: { enabled: false, value: 0 - } + }, + + healCounter: { + enabled: false, + value: 0 + }, }; @@ -61,6 +66,9 @@ var SharedRootCtrl = function($scope, $rootScope, $timeout) { $rootScope.options = { gOrbsEnabled: 0, + strOrbsEnabled: 0, + rainbowOrbsEnabled: 0, + meatOrbsEnabled: 0, slidersEnabled: true, sidebarVisible: false, transientMode: false, @@ -80,7 +88,7 @@ var SharedRootCtrl = function($scope, $rootScope, $timeout) { // reset slot if (!onlyTransitional) $scope.data.team[n] = { unit: null, level: -1, candies: { hp: 0, atk: 0, rcv: 0 } }; - $scope.tdata.team[n] = { orb: 1, g: false, special: false, lock: 0, silence: 0, removed: 0 }; + $scope.tdata.team[n] = { orb: 1, g: false, str: false, rainbow: false, special: false, lock: 0, silence: 0, removed: 0 }; }; // to be invoked every time a new unit is set in a slot so the insertion events can be triggered @@ -120,6 +128,93 @@ var SharedRootCtrl = function($scope, $rootScope, $timeout) { return false; }; + /* * * * * [STR] orb control * * * * */ + + var resetSTROrbs = function() { + for (var i=0;i<6;++i) { + if ($scope.tdata.team[i].orb == 'str') + $scope.tdata.team[i].orb = 1; + } + }; + + // reset STR slots automatically + $scope.$watch('options.strOrbsEnabled',function() { + if (!$rootScope.areSTROrbsEnabled()) + resetSTROrbs(); + }); + + $scope.$watch('data.effect',function() { + if (!$rootScope.areSTROrbsEnabled()) + resetSTROrbs(); + }); + + $rootScope.areSTROrbsEnabled = function() { + if ($rootScope.options.strOrbsEnabled > 0) return true; + if ($rootScope.data.effect) { + var effect = window.effects[$rootScope.data.effect]; + if (effect && effect.strOrbsEnabled) return true; + } + return false; + }; + + /* * * * * [RAINBOW] orb control * * * * */ + + var resetRainbowOrbs = function() { + for (var i=0;i<6;++i) { + if ($scope.tdata.team[i].orb == 'rainbow') + $scope.tdata.team[i].orb = 1; + } + }; + + // reset rainbow slots automatically + $scope.$watch('options.rainbowOrbsEnabled',function() { + if (!$rootScope.areRainbowOrbsEnabled()) + resetRainbowOrbs(); + }); + + $scope.$watch('data.effect',function() { + if (!$rootScope.areRainbowOrbsEnabled()) + resetRainbowOrbs(); + }); + + $rootScope.areRainbowOrbsEnabled = function() { + if ($rootScope.options.rainbowOrbsEnabled > 0) return true; + if ($rootScope.data.effect) { + var effect = window.effects[$rootScope.data.effect]; + if (effect && effect.rainbowOrbsEnabled) return true; + } + return false; + }; + + /* * * * * [MEAT] orb control * * * * */ + + var resetMeatOrbs = function() { + for (var i=0;i<6;++i) { + if ($scope.tdata.team[i].orb == 'meat') + $scope.tdata.team[i].orb = 1; + } + }; + + // reset meat slots automatically + $scope.$watch('options.meatOrbsEnabled',function() { + if (!$rootScope.areMeatOrbsEnabled()) + resetMeatOrbs(); + }); + + $scope.$watch('data.effect',function() { + if (!$rootScope.areMeatOrbsEnabled()) + resetMeatOrbs(); + }); + + $rootScope.areMeatOrbsEnabled = function() { + if ($rootScope.options.meatOrbsEnabled > 0) return true; + if ($rootScope.data.effect) { + var effect = window.effects[$rootScope.data.effect]; + if (effect && effect.meatOrbsEnabled) return true; + } + return false; + }; + /* * * * * Custom hit modifiers resetting * * * * */ var resetTransitional = function() { diff --git a/damage/js/controllers.js b/damage/js/controllers.js index 63826d2b3..2cfe7c267 100644 --- a/damage/js/controllers.js +++ b/damage/js/controllers.js @@ -44,7 +44,7 @@ controllers.PickerCtrl = function($scope, $state, $stateParams, $storage) { $scope.pickUnit = function(unitNumber) { $scope.resetSlot($stateParams.slot); $scope.data.team[$stateParams.slot].unit = units[unitNumber]; - $scope.data.team[$stateParams.slot].level = 1; + $scope.data.team[$stateParams.slot].level = $scope.data.team[$stateParams.slot].unit.maxLevel; $scope.slotChanged($stateParams.slot); updateRecent(unitNumber); // captain warning @@ -199,7 +199,7 @@ controllers.ShipCtrl = function($scope, $state) { $scope.getThumbnail = function(ship) { if (!ship.thumb) return 'background-image: url(' + Utils.getThumbnailUrl(null) + ')'; - return 'background-image: url(http://onepiece-treasurecruise.com/wp-content/uploads/' + ship.thumb + ')'; + return 'background-image: url(https://onepiece-treasurecruise.com/wp-content/uploads/' + ship.thumb + ')'; }; $scope.pickShip = function(name) { @@ -224,6 +224,14 @@ controllers.ResetCtrl = function($scope, $state, $storage) { $state.go('^'); }; }; + +/******************* + * InstructionCtrl * + ******************/ + +controllers.InstructionCtrl = function() { + //Do nothing +}; /************* * CandyCtrl * diff --git a/damage/js/cruncher.js b/damage/js/cruncher.js index 257780ff3..e41cf27f0 100644 --- a/damage/js/cruncher.js +++ b/damage/js/cruncher.js @@ -58,6 +58,7 @@ var CruncherCtrl = function($scope, $rootScope, $timeout) { var cptsWith = { }; var currentDefense = 0; var isDefenseDown = false; + var isDelayed = false; var specialsCombinations = [ ], chainSpecials = [ ]; var hitModifiers = [ ]; @@ -102,14 +103,15 @@ var CruncherCtrl = function($scope, $rootScope, $timeout) { result[type] = crunchForType(type); }); result.team = getTeamDetails(); - var hpMax = 0, rcvTotal = 0; + var hpMax = 0, rcvTotal = 0, bonusrcv = 0; team.forEach(function(x,n) { if (n > 5 || x.unit === null) return; // hp var hp = getStatOfUnit(x,'hp'); hp += getShipBonus('hp',true,x.unit,n); - hp *= getShipBonus('hp',false,x.unit,n); + hp = applyStaticEffectsToHP(n,hp); hp *= getEffectBonus('hp',x.unit); + hp *= getShipBonus('hp',false,x.unit,n); hpMax += Math.floor(applyCaptainEffectsToHP(n,hp)); // rcv var rcv = getStatOfUnit(x,'rcv'); @@ -117,8 +119,13 @@ var CruncherCtrl = function($scope, $rootScope, $timeout) { rcv *= getShipBonus('rcv',false,x.unit,n); rcv *= getEffectBonus('rcv',x.unit); rcvTotal += Math.floor(applyCaptainEffectsAndSpecialsToRCV(n,rcv)); + + bonusrcv = applyAddRCVSpecialsToRCV(n,0); + }); + result.rcv = Math.max(0,rcvTotal); + result.rcv += bonusrcv var cost = team.slice(1,6).reduce(function(prev,next) { return prev + (!next.unit ? 0 : next.unit.cost); },0); result.cost = { cost: cost, level: Math.max(1,Math.floor(cost / 2) * 2 - 18) }; $scope.numbers = jQuery.extend($scope.numbers, result); @@ -173,14 +180,45 @@ var CruncherCtrl = function($scope, $rootScope, $timeout) { // populate array with the damage of each unit in the team team.forEach(function(x,n) { if (n > 5 || x.unit === null || $scope.tdata.team[n].lock > 0) return; + var friendCaptain = $scope.tdata.team[0]; + var captain = $scope.tdata.team[1]; var orb = $scope.tdata.team[n].orb; var atk = getStatOfUnit(x,'atk'); // basic attack (scales with level); var ship = getShipBonus('atk',false,x.unit,n), againstType = type; var multipliers = [ ]; if (orb == 'g') orb = 1.5; + if (orb == 0.5 && x.unit.type == 'DEX') orb = (window.specials[1221].turnedOn || window.specials[1222].turnedOn) ? 2 : 0.5; + if (orb == 0.5 && x.unit.type == 'DEX' && x.unit.class.has("Driven")) orb = (window.specials[1259].turnedOn || window.specials[1260].turnedOn || window.specials[1323].turnedOn || window.specials[1324].turnedOn) ? 2 : 0.5; + if (orb == 0.5 && x.unit.type == 'DEX' && x.unit.class.has("Slasher")) orb = (window.specials[1323].turnedOn || window.specials[1324].turnedOn) ? 2 : 0.5; + if (orb == 0.5 && x.unit.type == 'DEX' && x.unit.class.has("Fighter")) orb = (window.specials[1593].turnedOn || window.specials[1463]. turnedOn || window.specials[1462]. turnedOn) ? 2 : 0.5; + if (orb == 0.5 && x.unit.type == 'DEX' && x.unit.class.has("Powerhouse")) orb = (window.specials[1528].turnedOn) ? 2 : 0.5; + if (orb == 0.5 && x.unit.type == 'DEX' && x.unit.class.has("Free Spirit")) orb = (window.specials[1593].turnedOn) ? 2 : 0.5; + if (orb == 0.5 && x.unit.type == 'DEX' && x.unit.class.has("Shooter")) orb = (window.specials[1640].turnedOn || window.specials[1746].turnedOn || window.specials[1747].turnedOn) ? 2 : 0.5; + if (orb == 0.5 && x.unit.type == 'DEX' && x.unit.class.has("Striker")) orb = (window.specials[1651].turnedOn || window.specials[1652].turnedOn) ? 2 : 0.5; + if (orb == 'str') orb = (window.specials[1221].turnedOn || window.specials[1222].turnedOn + || (window.specials[1259].turnedOn && x.unit.class.has("Driven")) || (window.specials[1260].turnedOn && x.unit.class.has("Driven")) + || (window.specials[1323].turnedOn && (x.unit.class.has("Driven") || x.unit.class.has("Slasher"))) || (window.specials[1324].turnedOn && (x.unit.class.has("Driven") || x.unit.class.has("Slasher"))) || (window.specials[1528].turnedOn && x.unit.class.has("Powerhouse")) || (window.specials[1593].turnedOn && (x.unit.class.has("Fighter") || x.unit.class.has("Free Spirit"))) || (window.specials[1640].turnedOn && x.unit.class.has("Shooter")) || ((window.specials[1651].turnedOn || window.specials[1652].turnedOn) && x.unit.class.has("Striker")) || ((window.specials[1746].turnedOn || window.specials[1747].turnedOn) && x.unit.class.has("Shooter"))) ? 2 : 1; + + if (orb == 0.5) orb = (window.specials[1269].turnedOn || window.specials[1270].turnedOn || window.specials[1330].turnedOn || window.specials[1546].turnedOn || window.specials[1547].turnedOn || window.specials[1557].turnedOn) ? 1 : .5; + + //Captain Meat orbs because Nekomamushi + if (orb =='meat'){ + for (temp = 0; temp < 2; temp++){ + if (team[temp].unit != null){ + /*if (team[temp].unit.name.includes("Kami Enel") || team[temp].unit.name.includes("God Usopp") || team[temp].unit.name.includes("Usoland")){ + orb = 2; + }*/ + if (team[temp].unit.number == 1610 || team[temp].unit.number == 1609 || team[temp].unit.number == 1532 || team[temp].unit.number == 1531){ + orb = 2; + } + } + } + } + if (orb == 'meat') orb = (window.specials[1515].turnedOn || window.specials[1516].turnedOn || (window.specials[1593].turnedOn && x.unit.class.has("Fighter")) || ((window.specials[1181].turnedOn || window.specials[1182].turnedOn) && x.unit.class.has("Slasher")) || ((window.specials[1380].turnedOn || window.specials[1379].turnedOn) && (x.unit.class.has("Cerebral") || x.unit.class.has("Free Spirit")))) ? 2 : 1; + if (orb == 'rainbow') orb = 2; atk += getShipBonus('atk',true,x.unit,n); multipliers.push([ orb, 'orb' ]); // orb multiplier (fixed) - multipliers.push([ getTypeMultiplierOfUnit(x.unit.type,type), 'type' ]); // type multiplier + multipliers.push([ getTypeMultiplierOfUnit(x.unit.type,type, x), 'type' ]); // type multiplier multipliers.push([ getEffectBonus('atk',x.unit), 'map effect' ]); // effect bonus (fixed) multipliers.push([ ship, 'ship' ]); // ship bonus (fixed) result.push({ unit: x, orb: orb, base: Math.floor(atk), multipliers: multipliers, position: n }); @@ -188,10 +226,11 @@ var CruncherCtrl = function($scope, $rootScope, $timeout) { // apply static multipliers and static bonuses for (var i=0;i currentResult.overall) currentResult = newResult; } + return currentResult; }; @@ -308,24 +351,41 @@ var CruncherCtrl = function($scope, $rootScope, $timeout) { // apply hits for (var i=0;i 0) { - --mapEffect.shieldLeft; - continue; - } lastAtk = unitAtk; // apply hit-based captain effects if any cptsWith.hitMultipliers.forEach(function(x) { lastAtk *= x.hit(result.hits); }); // apply defense lastHit = lastAtk / unit.combo; - lastHit = Math.floor(Math.max(1, lastHit - currentDefense)); + lastHit = Math.ceil(Math.max(1, lastHit - currentDefense)); + // apply combo shield if active + if (mapEffect.shieldLeft > 0) { + if (!mapEffect.comboType) { + --mapEffect.shieldLeft; + } + continue; + } // add hit to current total result.result += lastHit; } + if (mapEffect.comboType == hitModifier && mapEffect.shieldLeft > 0) { + --mapEffect.shieldLeft; + } // apply hit bonus - if (bonusDamageBase > 0) { - if (lastHit > 1) result.result += Math.floor(lastAtk * 0.9 * bonusDamageBase); - else result.result += Math.max(0,Math.floor(lastAtk * (0.9 * bonusDamageBase + 1 / unit.combo)) - currentDefense); + if (bonusDamageBase > 0 && mapEffect.shieldLeft == 0) { + if (lastHit > 1) result.result += Math.ceil(lastAtk * 0.9 * bonusDamageBase); + else result.result += Math.max(0,Math.ceil(lastAtk * (0.9 * bonusDamageBase + 1 / unit.combo)) - currentDefense); + } + + //Apply Static Bonus Damage From Specials + var staticBonusDamage = computeFlatBonusDamage(hitModifier); + if ((staticBonusDamage > 0) && ((staticBonusDamage - currentDefense)>0) && (result.result > 0)) { + result.result += (staticBonusDamage - currentDefense); + } + + // apply fixed threshold barrier if active + if (mapEffect.barrierThreshold && result.result > mapEffect.barrierThreshold) { + result.result = mapEffect.barrierThreshold + + Math.floor((result.result - mapEffect.barrierThreshold) * (1 - mapEffect.barrierReduction)); } return result; }; @@ -333,13 +393,17 @@ var CruncherCtrl = function($scope, $rootScope, $timeout) { /* Computes the actual defense threshold of the enemy after the specials are factored in. * Defense-reducing specials do not stack with each other, so we just use the one that grants the lowest defense. */ - var computeActualDefense = function() { + var computeActualDefense = function(shipName) { var baseDefense = parseInt($scope.data.defense, 10) || 0; currentDefense = baseDefense; enabledSpecials.forEach(function(x) { if (x === null || !x.hasOwnProperty('def')) return; currentDefense = Math.min(currentDefense,baseDefense * x.def()); }); + if(shipName=="Flying Dutchman - Special ACTIVATED"){ + currentDefense = Math.min(currentDefense,baseDefense * .75); + } + }; var getShipBonus = function(type,static,unit,slot) { @@ -348,8 +412,8 @@ var CruncherCtrl = function($scope, $rootScope, $timeout) { if (key.indexOf(type) !== 0) continue; var isStatic = (key.indexOf('Static') !== -1); if (isStatic != static) continue; - if (static) result += shipBonus.bonus[key]({ boatLevel: shipBonus.level, unit: unit, slot: slot }); - else result *= shipBonus.bonus[key]({ boatLevel: shipBonus.level, unit: unit, slot: slot }); + if (static) result += shipBonus.bonus[key]({ boatLevel: shipBonus.level, unit: unit, slot: slot, classCount: classCounter(), colorCount: colorCounter() }); + else result *= shipBonus.bonus[key]({ boatLevel: shipBonus.level, unit: unit, slot: slot, classCount: classCounter(), colorCount: colorCounter() }); } return result; }; @@ -359,16 +423,31 @@ var CruncherCtrl = function($scope, $rootScope, $timeout) { return effects[$scope.data.effect][type](unit.unit || unit); }; - var getTypeMultiplierOfUnit = function(attackerType,attackedType) { - if (attackerType == 'STR' && attackedType == 'DEX') return 2; - if (attackerType == 'QCK' && attackedType == 'STR') return 2; - if (attackerType == 'DEX' && attackedType == 'QCK') return 2; - if (attackerType == 'INT' && attackedType == 'PSY') return 2; - if (attackerType == 'PSY' && attackedType == 'INT') return 2; - if (attackerType == 'STR' && attackedType == 'QCK') return 0.5; - if (attackerType == 'QCK' && attackedType == 'DEX') return 0.5; - if (attackerType == 'DEX' && attackedType == 'STR') return 0.5; - return 1; + var getTypeMultiplierOfUnit = function(attackerType,attackedType, unit) { + var typeMult = 1, affinityMult = 1; + + if (attackerType == 'STR' && attackedType == 'DEX') typeMult = 2; + if (attackerType == 'QCK' && attackedType == 'STR') typeMult = 2; + if (attackerType == 'DEX' && attackedType == 'QCK') typeMult = 2; + if (attackerType == 'INT' && attackedType == 'PSY') typeMult = 2; + if (attackerType == 'PSY' && attackedType == 'INT') typeMult = 2; + if (attackerType == 'STR' && attackedType == 'QCK') typeMult = 0.5; + if (attackerType == 'QCK' && attackedType == 'DEX') typeMult = 0.5; + if (attackerType == 'DEX' && attackedType == 'STR') typeMult = 0.5; + + //Get the strongest Color affinity Mult if it exists and apply it + affinityMultiplier.forEach(function(special){ + if(affinityMult0){ + chainModifier = Math.min(mapEffect.chainModifier(params[n])*chainModifier, chainModifier); + }else{ + //chain modifier without chain boosting captain + chainModifier = Math.min(mapEffect.chainModifier(params[n]), chainModifier); + } var chainMultiplier = getChainMultiplier(special.chain(params[n]), modifiers.slice(0,n), chainModifier); + //Add flat Multiplier Bonuses if they exist + if(addition>0.0 && chainMultiplier != 1.0) + chainMultiplier = chainMultiplier + addition; if (mapEffect.hasOwnProperty('chainLimiter')) chainMultiplier = Math.min(mapEffect.chainLimiter(params[n]), chainMultiplier); else if (special.hasOwnProperty('chainLimiter')) @@ -527,6 +665,18 @@ var CruncherCtrl = function($scope, $rootScope, $timeout) { result.push(JSON.parse(JSON.stringify(captains[i].hitModifiers))); } } + // Auto sorting for Hit Barriers + if (mapEffect.comboType){ + var mapComboArray = [] + for(var cmb=0;cmbconditionalMultiplier){ + conditionalMultiplier = thisMult; + } + } + } + //Add the static extra Damage to each attacking member + for (var y=0;y 1 || chainSpecials.length > 1); - // get ship bonus - shipBonus = jQuery.extend({ bonus: window.ships[$scope.data.ship[0]] },{ level: $scope.data.ship[1] }); + $scope.conflictingSpecials = (specialsCombinations.length > 1 || chainSpecials.length > 1 || chainAddition.length > 1 || affinityMultiplier.length > 1); + $scope.conflictingMultipliers = ( staticMultiplier.length > 1 ) }; - - + + //Returns an Object with a counter of classes in the current Team + //Used for Bartolomeos Captain ability so far + var classCounter = function() { + var classes = {}; + var classArray = ['Fighter', 'Slasher', 'FreeSpirit', 'Powerhouse', 'Shooter', 'Striker', 'Cerebral', 'Driven']; + for (var i = 0, j = classArray.length; i < j; i++) { + classes[classArray[i]] = 0; + } + for(var z=0;z 0) numbers.healPerTurn = healAmount; else return; // nothing to do if there's no healer diff --git a/damage/js/directives.js b/damage/js/directives.js index e079ab744..4ea738f29 100644 --- a/damage/js/directives.js +++ b/damage/js/directives.js @@ -10,12 +10,12 @@ var directives = { }; *****************/ directives.autoFocus = function($timeout) { - return { - restrict: 'A', - link: function(scope, element, attrs) { - $timeout(function(){ element[0].focus(); }); - } - }; + return { + restrict: 'A', + link: function(scope, element, attrs) { + $timeout(function(){ element[0].focus(); }); + } + }; }; directives.decorateSlot = function($rootScope) { @@ -31,6 +31,7 @@ directives.decorateSlot = function($rootScope) { } else { if (scope.uid != 1 || scope.flag || (scope.udata && scope.udata.name == 'Monkey D. Luffy')) target.style.backgroundImage = 'url(' + Utils.getThumbnailUrl(scope.uid) + ')'; + //target.style.backgroundImage = 'url(' + Utils.getGlobalThumbnailUrl(scope.uid) + '), url(' + Utils.getThumbnailUrl(scope.uid) + ')'; else target.style.backgroundImage = null; if (attrs.decorateSlot.indexOf('notitle') == -1) @@ -255,8 +256,8 @@ directives.floatingHeader = function($timeout) { }; directives.goBack = function($state) { - return { - restrict: 'A', + return { + restrict: 'A', link: function(scope, element, attrs) { element.click(function(e) { if (!e.target || e.target.className.indexOf('inner-container') == -1) return; @@ -267,8 +268,8 @@ directives.goBack = function($state) { }; directives.quickPick = function() { - return { - restrict: 'A', + return { + restrict: 'A', link: function(scope, element, attrs) { var fuse = new Fuse(window.units, { keys: [ 'name' ], id: 'number', threshold: 0.3, distance: 200 }); element.textcomplete([{ @@ -283,6 +284,8 @@ directives.quickPick = function() { template: function (value) { var thumb = Utils.getThumbnailUrl(value + 1); return ' ' + window.units[value].name + ''; + //var thumb2 = Utils.getGlobalThumbnailUrl(value + 1); + //return ' ' + window.units[value].name + ''; }, replace: function(value) { return window.units[value].name; @@ -346,6 +349,8 @@ directives.slot = function() { scope: true, link: function(scope, element, attrs) { scope.slot = element.index(); + var id = scope.data.team[scope.slot].unit.number + 1; + scope.sailors = window.sailors[id] ? JSON.parse(JSON.stringify(window.sailors[id])) : null; scope.onDrop = function(i, j) { var temp = scope.data.team[i]; scope.data.team[i] = scope.data.team[j]; @@ -434,6 +439,7 @@ directives.hpBar = function() { if (!hp) return; hp = hp.trim(); if (/%$/.test(hp)) perc = true; + if(!perc) hp = eval(hp); //Enable User Input to be calculated hp = parseFloat(hp, 10); if (!perc) hp = Math.floor(hp); if (isNaN(hp)) return; @@ -483,7 +489,44 @@ directives.turnCounter = function() { } }; }; + +directives.healCounter = function() { + return { + retrict: 'E', + replace: true, + template: '
    ' + + '
    {{currentHeals}} {{currentHeals == 1 ? "Health Point" : "Health Points"}} recovered in the last turn
    ', + link: function(scope, element, attrs) { + + scope.currentHeals = 0; + + var slider = element.find('#healSlider')[0]; + var sliderSettings = { + start: [ scope.currentTurns ], + range: { min: [ 0 ], max: [ 10000 ] }, + step: 10, + connect: 'lower' + }; + + var createSlider = function() { + if (slider.noUiSlider) slider.noUiSlider.destroy(); + noUiSlider.create(slider, sliderSettings); + slider.noUiSlider.on('change', function(_,__,value) { update('change', value); }); + slider.noUiSlider.on('slide', function(_,__,value) { update('slide', value); }); + }; + + var update = function(event,value) { + scope.currentHeals = parseInt(value, 10); + if (event == 'change') scope.tdata.healCounter.value = scope.currentHeals; + scope.$apply(); + }; + createSlider(); + + } + }; +}; + directives.levelLabel = function($timeout) { return { restrict: 'E', @@ -571,7 +614,7 @@ directives.levelSlider = function($timeout) { }; directives.unitOrb = function($rootScope) { - var ORBS = [ 0.5, 1, 2, 'g' ]; + var ORBS = [ 0.5, 1, 2 ]; return { restrict: 'E', replace: true, @@ -583,6 +626,9 @@ directives.unitOrb = function($rootScope) { if (unit.orb == 1) return 'none'; if (unit.orb == 2) return scope.data.team[scope.slot].unit.type; if (unit.orb == 'g') return 'G'; + if (unit.orb == 'str') return 'S'; + if (unit.orb == 'rainbow') return 'R'; + if (unit.orb == 'meat') return 'M'; return Utils.getOppositeType(scope.data.team[scope.slot].unit.type) + ' opposite'; }; var onShortPress = function(e) { @@ -590,23 +636,66 @@ directives.unitOrb = function($rootScope) { if (!$(e.target).hasClass('unitPortrait')) return; if (unit.unit === null || /unitLevel/.test(e.target.className) || e.altKey || e.shiftKey) return; if (e.which == 2 || (e.which == 1 && (e.ctrlKey || e.metaKey || Utils.isClickOnOrb(e,e.target.parentNode)))) { + if($rootScope.areGOrbsEnabled()){ + ORBS.push('g'); + } + if($rootScope.areRainbowOrbsEnabled()){ + ORBS.push('rainbow'); + } + if($rootScope.areMeatOrbsEnabled()){ + ORBS.push('meat'); + } + if($rootScope.areSTROrbsEnabled()){ + ORBS.push('str'); + } + var ORBSlength = ORBS.length; + if($rootScope.areSTROrbsEnabled() && (unit.unit.type == "STR" || unit.unit.type == "DEX")){ + ORBSlength--; + } var n = ORBS.indexOf(tunit.orb); - tunit.orb = ORBS[(n + 1) % ($rootScope.areGOrbsEnabled() ? ORBS.length : ORBS.length - 1)]; + /*if(unit.unit.type == "STR" || unit.unit.type == "DEX") + tunit.orb = ORBS[(n + 1) % ($rootScope.areGOrbsEnabled() ? ORBS.length - 1 : ORBS.length - 2)]; + else + tunit.orb = ORBS[(n + ((!$rootScope.areGOrbsEnabled() && $rootScope.areSTROrbsEnabled() && n == ORBS.length - 3) ? 2 : 1)) % ($rootScope.areGOrbsEnabled() ? ($rootScope.areSTROrbsEnabled() ? ORBS.length : ORBS.length - 1) : ($rootScope.areSTROrbsEnabled() ? ORBS.length : ORBS.length - 2))];*/ + tunit.orb = ORBS[(n + 1) % (ORBSlength)]; scope.glow(); scope.$apply(); e.preventDefault(); e.stopPropagation(); + ORBS = [ 0.5, 1, 2 ]; return false; } + }; var onLongPress = function(e) { + if($rootScope.areGOrbsEnabled()){ + ORBS.push('g'); + } + if($rootScope.areRainbowOrbsEnabled()){ + ORBS.push('rainbow'); + } + if($rootScope.areMeatOrbsEnabled()){ + ORBS.push('meat'); + } + if($rootScope.areSTROrbsEnabled()){ + ORBS.push('str'); + } var unit = scope.data.team[scope.slot], tunit = scope.tdata.team[scope.slot]; - var n = ORBS.indexOf(tunit.orb); - tunit.orb = ORBS[(n + 1) % ($rootScope.areGOrbsEnabled() ? ORBS.length : ORBS.length - 1)]; + var ORBSlength = ORBS.length; + if($rootScope.areSTROrbsEnabled() && (unit.unit.type == "STR" || unit.unit.type == "DEX")){ + ORBSlength--; + } + var n = ORBS.indexOf(tunit.orb); + /*if(unit.unit.type == "STR" || unit.unit.type == "DEX") + tunit.orb = ORBS[(n + 1) % ($rootScope.areGOrbsEnabled() ? ORBS.length - 1 : ORBS.length - 2)]; + else + tunit.orb = ORBS[(n + ((!$rootScope.areGOrbsEnabled() && $rootScope.areSTROrbsEnabled() && n == ORBS.length - 3) ? 2 : 1)) % ($rootScope.areGOrbsEnabled() ? ($rootScope.areSTROrbsEnabled() ? ORBS.length : ORBS.length - 1) : ($rootScope.areSTROrbsEnabled() ? ORBS.length : ORBS.length - 2))];*/ + tunit.orb = ORBS[(n + 1) % (ORBSlength)]; scope.glow(); scope.$apply(); e.preventDefault(); e.stopPropagation(); + ORBS = [ 0.5, 1, 2 ]; return false; }; element.parent().longpress(onLongPress,onShortPress); @@ -719,6 +808,21 @@ directives.unitCandies = function() { }; }; +directives.unitSailor = function() { + return { + restrict: 'E', + replace: true, + scope: true, + template: '
    ', + link: function(scope, element, attrs) { + scope.hasSailor = false; + scope.$watch('data.team[slot].unit',function(unit) { + scope.hasSailor = unit && window.sailors.hasOwnProperty(unit.number+1); + }); + } + }; +}; + directives.special = function($rootScope) { return { restrict: 'E', @@ -778,7 +882,7 @@ directives.candySlider = function($compile, $timeout) { }; var updateMax = function(data) { var used = Object.keys(data).reduce(function(prev,next) { return prev + (next == scope.type ? 0 : data[next]); },0); - input.trigger('configure',{ max: Math.min(100,200 - used) }); + input.trigger('configure',{ max: Math.min(500,2000 - used) }); currentValue = data[scope.type]; input.val(currentValue).trigger('change'); scope.actualBonus = currentValue * { hp: 5, atk: 2, rcv: 1 }[scope.type]; diff --git a/damage/js/images.js b/damage/js/images.js index f7afc55e6..5e2b0c1f5 100644 --- a/damage/js/images.js +++ b/damage/js/images.js @@ -3,7 +3,7 @@ var app = angular.module('optc'); var BOX_COLORS = { STR: 'salmon', QCK: 'lightskyblue', DEX: 'lightgreen', PSY: 'gold', INT: 'orchid' }; -var ORB_COLORS = { STR: 'orangered', QCK: 'dodgerblue', DEX: 'lightgreen', PSY: 'gold', INT: 'orchid', G: 'orange' }; +var ORB_COLORS = { STR: 'orangered', QCK: 'dodgerblue', DEX: 'lightgreen', PSY: 'gold', INT: 'orchid', G: 'orange', S: 'orangered', RAINBOW: 'pink', MEAT: 'darkgoldenrod'}; var lock = new Image(), silence = new Image(); lock.src = 'res/chain.png'; @@ -39,12 +39,21 @@ app.controller('ImageGeneratorCtrl', function($scope, $filter, $timeout) { var percHP = $filter('number')(Math.round($scope.data.percHP * 100) / 100); var rcv = $filter('number')($scope.numbers.rcv); var cost = $filter('number')($scope.numbers.cost.cost); + var healPerTurn = $filter('number')($scope.numbers.healPerTurn); + //HP awesome(context, { text: 'f21e', x: baseX + 8, y: baseY, align: 'center' }); type(context, { text: currentHP + ' HP (' + percHP + '%)', x: baseX + 25, y: baseY }); - awesome(context, { text: 'f0f5', x: baseX + 8, y: baseY + 25, align: 'center' }); + //RCV + awesome(context, { text: 'f0f5', x: baseX + 8, y: baseY + 25, align: 'center' }); type(context, { text: rcv + ' RCV', x: baseX + 25, y: baseY + 25 }); - awesome(context, { text: 'f039', x: baseX + 8, y: baseY + 50, align: 'center' }); + //Cost + awesome(context, { text: 'f039', x: baseX + 8, y: baseY + 50, align: 'center' }); type(context, { text: cost + ' cost', x: baseX + 25, y: baseY + 50 }); + //Heal per Turn + if(healPerTurn){ + awesome(context, { text: 'f0fa', x: baseX + 8, y: baseY + 75, align: 'center' }); + type(context, { text: healPerTurn + ' Heal per turn', x: baseX + 25, y: baseY + 75 }); + } } },true); @@ -74,7 +83,7 @@ app.controller('ImageGeneratorCtrl', function($scope, $filter, $timeout) { if (orb != 1.0) { var gradient = context.createRadialGradient(baseX + 20, baseY + 21, 13, baseX + 22, baseY + 22, 35); if (orb < 1) gradient.addColorStop(0.1, ORB_COLORS[Utils.getOppositeType(unit.type)]); - else gradient.addColorStop(0.1, ORB_COLORS[orb == 'g' ? 'G' : unit.type]); + else gradient.addColorStop(0.1, ORB_COLORS[orb == 'g' ? 'G' : orb == 'str' ? 'STR' : orb == 'rainbow' ? 'RAINBOW' : orb == 'meat' ? 'MEAT' : unit.type]); if (orb < 1) gradient.addColorStop(0.2, 'black'); else { gradient.addColorStop(0.2, 'white'); @@ -84,13 +93,22 @@ app.controller('ImageGeneratorCtrl', function($scope, $filter, $timeout) { gradient.addColorStop(1.0, 'transparent'); context.fillStyle = gradient; context.fillRect(0, 0, canvas.width, canvas.height); - if (orb != 'g') { + if (orb != 'g' && orb != 'str' && orb != 'rainbow' && orb != 'meat') { var temp = (orb < 1 ? [ 'f0d7', baseX + 13, baseY + 31 ] : [ 'f0d8', baseX + 13, baseY + 28 ]); awesome(context, { text: temp[0], style: '28px', color: 'white', x: temp[1], y: temp[2], stroke: 'gray' }); - } else { + } else if (orb == 'g') { type(context, { text: 'G', style: 'bold 20px "Open Sans"', x: baseX + 13, y: baseY + 28, color: 'white', stroke: 'black', strokeWidth: 2 }); + } else if (orb == 'str'){ + type(context, { text: 'S', style: 'bold 20px "Open Sans"', + x: baseX + 13, y: baseY + 28, color: 'white', stroke: 'black', strokeWidth: 2 }); + } else if (orb == 'rainbow'){ + type(context, { text: 'R', style: 'bold 20px "Open Sans"', + x: baseX + 13, y: baseY + 28, color: 'white', stroke: 'black', strokeWidth: 2 }); + } else{ + type(context, { text: 'M', style: 'bold 20px "Open Sans"', + x: baseX + 13, y: baseY + 28, color: 'white', stroke: 'black', strokeWidth: 2 }); } } // level label @@ -106,15 +124,26 @@ app.controller('ImageGeneratorCtrl', function($scope, $filter, $timeout) { var total = data.candies.hp + data.candies.atk + data.candies.rcv; if (total > 0) { type(context, { text: '+' + total, style: 'bold 14px "Open Sans"', - x: baseX + 7, y: baseY + 103, color: 'gold', stroke: 'black', strokeWidth: 3 }); + x: baseX + 40, y: baseY + 18, color: 'gold', stroke: 'black', strokeWidth: 3 }); + } + + if (n >= 2 && window.sailors.hasOwnProperty(unit.number +1)) { + awesome(context, { text: 'f13d', + x: baseX + 3, y: baseY + 105, color: 'gold', stroke: 'black', strokeWidth: 3 }); } }; image.src = Utils.getThumbnailUrl(unit.number + 1); + //image.src = Utils.getGlobalThumbnailUrl(unit.number + 1); + //image.onerror = function(){ + // image.src = Utils.getThumbnailUrl(unit.number + 1); + //} }); },true); baseX = 10; baseY = 85; + if($scope.numbers.healPerTurn) baseY +=25; + if ($scope.data.effect) { awesome(context, { text: 'f02d', x: baseX + 8, y: baseY + 20, align: 'center', color: 'darkorchid' }); type(context, { text: $scope.data.effect, x: baseX + 25, y: baseY + 20, maxWidth: 155, truncate: true, color: 'darkorchid' }); @@ -140,6 +169,14 @@ app.controller('ImageGeneratorCtrl', function($scope, $filter, $timeout) { baseY += 25; } + // heal counter + if ($scope.tdata.healCounter.enabled) { + awesome(context, { text: 'f162', x: baseX + 8, y: baseY + 20, align: 'center' }); + var turns = $scope.tdata.healCounter.value; + type(context, { text: turns + (turns == 1 ? ' Health Point' : ' Health Points') + ' recovered in the last turn', x: baseX + 25, y: baseY + 20 }); + baseY += 25; + } + // specials awesome(context, { text: 'f0e7', x: baseX + 8, y: baseY + 20, align: 'center' }); type(context, { text: 'Active specials:', x: baseX + 25, y: baseY + 20 }); diff --git a/damage/js/main.js b/damage/js/main.js index f0c94ca03..fd76e600c 100644 --- a/damage/js/main.js +++ b/damage/js/main.js @@ -36,6 +36,16 @@ var MainCtrl = function($scope, $rootScope, $controller, $filter, $storage) { }); } }); + + $scope.$watch('conflictingMultipliers',function(value) { + if (value) { + $scope.notify({ + text: 'Only one Static Attack Multiplier may be active at a time,'+ + 'please check yourself which combination is better.', + type: 'error' + }); + } + }); var zombieNoty = null; $scope.$watch('numbers.zombie',function(zombie) { diff --git a/damage/js/states.js b/damage/js/states.js index d5046de18..3074bba4e 100644 --- a/damage/js/states.js +++ b/damage/js/states.js @@ -72,6 +72,16 @@ angular.module('optc').config(function($stateProvider, $urlRouterProvider) { } } }) + + .state('main.instruction',{ + url: 'instruction', + views: { + popup: { + templateUrl: 'views/popup/instruction.html', + controller: 'InstructionCtrl' + } + } + }) .state('main.effects',{ url: 'effects', diff --git a/damage/js/transfer.js b/damage/js/transfer.js index 656782e0f..a0acffbaa 100644 --- a/damage/js/transfer.js +++ b/damage/js/transfer.js @@ -7,6 +7,7 @@ **************/ var ImportCtrl = function($scope, $rootScope, $state, $stateParams) { + history.replaceState(null, null, '#/'); var checkInt = function(n, min, max) { var temp = parseInt(n, 10); @@ -41,7 +42,7 @@ var ImportCtrl = function($scope, $rootScope, $state, $stateParams) { rcv = parseInt(matches[5],10) || 0; if (id < 1 || id > window.units.length || window.units[id - 1].length === 0) break; if (level < 1 || level > window.units[id - 1].maxLevel) break; - if (atk > 100 || hp > 100 || rcv > 100 || (atk + hp + rcv) > 200) break; + if (atk > 200 || hp > 200 || rcv > 200 || (atk + hp + rcv) > 500) break; team.push({ id: id, level: level, candies: { atk: atk, hp: hp, rcv: rcv }}); } } @@ -115,7 +116,7 @@ var ImportCtrl = function($scope, $rootScope, $state, $stateParams) { .slice(-6).split('').map(function(x) { return parseInt(x, 10); }); temp.forEach(function(x,n) { var unit = $scope.tdata.team[n]; - if (type == 'O') unit.orb = (x == 1 ? 2 : (x == 2 ? 0.5 : (x == 3 ? 'g' : 1))); + if (type == 'O') unit.orb = (x == 1 ? 2 : (x == 2 ? 0.5 : (x == 3 ? 'g' : (x == 4 ? 'str' : (x == 5 ? 'rainbow' : 1))))); else if (type == 'L') unit.lock = x; else if (type == 'G') unit.silence = x; else if (type == 'R') unit.removed = x; @@ -125,7 +126,7 @@ var ImportCtrl = function($scope, $rootScope, $state, $stateParams) { .slice(-6).split('').map(function(x) { return parseInt(x, 10); }); temp.forEach(function(x,n) { var unit = $scope.tdata.team[n]; - unit.orb = (x == 1 ? 2 : (x == 2 ? 0.5 : (x == 3 ? 'g' : 1))); + unit.orb = (x == 1 ? 2 : (x == 2 ? 0.5 : (x == 3 ? 'g' : (x == 4 ? 'str' : (x == 5 ? 'rainbow' : 1))))); if (unit.orb == 'g' && !$rootScope.areGOrbsEnabled()) unit.orb = 1; }); } else if (type == 'S') { @@ -186,11 +187,11 @@ var ExportCtrl = function($scope) { result = '#/transfer/D' + tokens.join(',') + 'C'; // others - result += data.ship[0] + ',' + data.ship[1] + 'B'; - result += (data.defense && data.defense.constructor == Number ? data.defense : 0) + 'D'; + result += (data.defense && data.defense.constructor == Number ? data.defense : parseInt(data.defense)) + 'D'; + //result += (data.defense != 0 ) + 'D'; result += ($scope.data.effect ? window.effects[$scope.data.effect].id : 0) + 'E'; - result += parseInt(team.map(function(x) { return ({ '2': 1, '0.5': 2, 'g': 3, '1': 0 }['' + x.orb] || 0); }).join(''),4) + 'Q'; + result += parseInt(team.map(function(x) { return ({ '2': 1, '0.5': 2, 'g': 3, 'str': 4, 'rainbow': 5, '1': 0 }['' + x.orb] || 0); }).join(''),4) + 'Q'; result += parseInt(team.map(function(x) { return x.lock; }).join(''),3) + 'L'; result += parseInt(team.map(function(x) { return x.silence; }).join(''),3) + 'G'; result += parseInt(team.map(function(x) { return x.removed; }).join(''),3) + 'R'; diff --git a/damage/js/utils.js b/damage/js/utils.js index ac8a53866..f95026d34 100644 --- a/damage/js/utils.js +++ b/damage/js/utils.js @@ -31,30 +31,183 @@ window.CrunchUtils.okamaSort = function(array, data) { if (temp.length != data.length) return null; else return [ temp.concat(that) ]; }; - -window.CrunchUtils.mihawkSort = function(array) { + +/* Sorts by class (units not belonging to the specified class(es) at the + * beginning), then by ATK. classMultiplier is the multiplier units belonging + * to the specified class(es) receive. */ +window.CrunchUtils.classSort = function(array, classMultiplier, classes) { + var result = [ ]; + function isUnitAMatch(unit) { + for (var n = 0;n + +
    @@ -33,6 +35,10 @@ uib-tooltip="Export Image" tooltip-append-to-body="true"> +
    diff --git a/damage/views/fragments/orb.html b/damage/views/fragments/orb.html index 5f300b323..e4df8492f 100644 --- a/damage/views/fragments/orb.html +++ b/damage/views/fragments/orb.html @@ -1,7 +1,7 @@
    @@ -9,4 +9,16 @@ G + + S + + + + R + + + + M + +
    diff --git a/damage/views/fragments/popover.html b/damage/views/fragments/popover.html index d60ab091e..c4783f7df 100644 --- a/damage/views/fragments/popover.html +++ b/damage/views/fragments/popover.html @@ -53,6 +53,15 @@ + + Sailor Ability + + + +
    + + + Special diff --git a/damage/views/fragments/slot.html b/damage/views/fragments/slot.html index 82bb2032a..ff242dd61 100644 --- a/damage/views/fragments/slot.html +++ b/damage/views/fragments/slot.html @@ -19,9 +19,11 @@ +
    +
    Friend
    diff --git a/damage/views/popup/gather.html b/damage/views/popup/gather.html index dce18a46d..26c3e16e9 100644 --- a/damage/views/popup/gather.html +++ b/damage/views/popup/gather.html @@ -18,7 +18,7 @@
  • They're NOT at max level
  • - please head over here and complete the form (it takes like 20 seconds), any help is appreciated. + please head over here and complete the form (it takes like 20 seconds), any help is appreciated.

    + +
  • +
    + + Heal Socket Level: +
    +
  • - Enemy defense: + Enemy Defense: +
    +
  • + +
  • +
    + + Barrier: +
  • +
  • + +
  • +
    + + Captain Actions:
    Friend/Guest Captain
    Captain
  • @@ -43,7 +70,7 @@
  • - Data gathering + Data Gathering
  • diff --git a/drops/index.css b/drops/index.css index bc329b48e..4cd34e6ec 100644 --- a/drops/index.css +++ b/drops/index.css @@ -188,3 +188,10 @@ h1 > label > input { .bonus.JP:before { content: "JP: "; } +#times { + text-align: center; +} + +#timesNote { + text-align: center; +} diff --git a/drops/index.html b/drops/index.html index d26173536..fe6f40cb0 100644 --- a/drops/index.html +++ b/drops/index.html @@ -5,7 +5,9 @@ - + + + One Piece Treasure Cruise Drop Table @@ -42,10 +44,13 @@ + + + - + diff --git a/drops/index.js b/drops/index.js index 5906b328e..791792593 100644 --- a/drops/index.js +++ b/drops/index.js @@ -18,6 +18,8 @@ app.controller('MainCtrl',function($scope, $rootScope, $timeout, $controller) { $rootScope.query = ''; $scope.data = drops; $scope.hiddenUnits = [ ]; + var searchQuery = location.search.replace('?',''); + // units $scope.reverse = function(x) { return -x; }; @@ -33,6 +35,11 @@ app.controller('MainCtrl',function($scope, $rootScope, $timeout, $controller) { if (!$scope.$$phase) $scope.$apply(); }; + //Use URI for one time search + if(searchQuery!=""){ + $scope.query = Utils.getRegex(decodeURI(searchQuery.replace(/%20Fortnight|%20Raid/g,"").replace(/\?/,"\\?"))); + } + $controller('DismissalCtrl'); }); @@ -43,8 +50,10 @@ app.directive('decorateSlot',function() { scope: { uid: '=', big: '@', delay: '@' }, link: function(scope, element, attrs) { var url = scope.big ? Utils.getBigThumbnailUrl(scope.uid) : Utils.getThumbnailUrl(scope.uid); + //var url2 = scope.big ? Utils.getBigThumbnailUrl(scope.uid) : Utils.getGlobalThumbnailUrl(scope.uid); if (scope.delay) element[0].setAttribute('data',url); else element[0].style.backgroundImage = 'url(' + url + ')'; + //else element[0].style.backgroundImage = 'url(' + url2 + '), url(' + url + ')'; } }; }); @@ -61,7 +70,7 @@ app.directive('type',function() { app.directive('island',function() { return { restrict: 'E', - scope: { island: '=', data: '=', type: '=', hiddenUnits: '=' }, + scope: { island: '=', data: '=', type: '=', hiddenUnits: '=', condition: '=', challenge: '=', completion: '=', showManual: '=' }, replace: true, templateUrl: 'island.html', link: function(scope, element, attrs) { @@ -224,3 +233,24 @@ app.filter('smartSort',function($rootScope) { }); })(); + +function refreshTimer(){ +var refresh=1000; // Refresh rate in milli seconds +mytime=setTimeout('updateTimes()',refresh) +} + +function updateTimes(){ + //Japan can also be Etc/GMT-9 + document.getElementById("times").innerHTML = "Global: "+moment().tz('Etc/GMT+8').format('H:mm:ss')+" | Japan: "+moment().tz('Asia/Tokyo').format('H:mm:ss')+""; + + if(moment().tz('Asia/Tokyo').format('H')>12 && moment().tz('Asia/Tokyo').format('H')<23){ + document.getElementById("timesNote").innerHTML = "The Bonuses in the Japanese Version only last from 12:00 till 23:00
    Japan Bonuses are currently active"; + }else{ + document.getElementById("timesNote").innerHTML = "The Bonuses in the Japanese Version only last from 12:00 till 23:00
    Japan Bonuses are currently not active"; + } + tt=refreshTimer(); +} +window.onload = function() { + //Also add the URI Search into the Search Bar + document.getElementById("search").value = decodeURI(location.search.replace('?','').replace(/%20Fortnight|%20Raid/g,"").replace(/\?/,"\\?")); +} \ No newline at end of file diff --git a/favicon.ico b/favicon.ico index 03e93cb4b..3ea387b4e 100644 Binary files a/favicon.ico and b/favicon.ico differ diff --git a/index.css b/index.css index a213959d3..147b5c1a7 100644 --- a/index.css +++ b/index.css @@ -1,4 +1,15 @@ +@font-face { + font-family: 'icomoon'; + src:url('../../res/icomoon.eot?xewvs9'); + src:url('../../res/icomoon.eot?xewvs9#iefix') format('embedded-opentype'), + url('../../res/icomoon.ttf?xewvs9') format('truetype'), + url('../../res/icomoon.woff?xewvs9') format('woff'), + url('../../res/icomoon.svg?xewvs9#icomoon') format('svg'); + font-weight: normal; + font-style: normal; +} + * { -moz-box-sizing: border-box; -o-box-sizing: border-box; @@ -23,6 +34,39 @@ body { transform: translate3d(0,-50%,0); } +#changelog { + position: fixed; + padding: 35px; + float: right; + bottom: 10; + right: 10; +/* z-index: -1;*/ +} + +#changelog > p { + width: 100%; + margin: auto; + text-align: center; + +} + +#changelog > ul { + list-style-type: none; + text-align: left; + margin: auto; + padding-left: 0; +} + +#update { + font-size: 20; +} + +@media only screen and (max-width: 1000px) { + #changelog { + display: none; + } +} + .button { display: block; width: 250px; @@ -48,9 +92,77 @@ body { .red { background-color: #E96D63; } .purple { background-color: #DA70D6; } .yellow { background-color: #F4BA70; } +.pink { background-color: #DEA5A4; } +.brown { background-color: #993300; } .green:hover { background-color: #6EB98E; } .blue:hover { background-color: #74B0E4; } .red:hover { background-color: #D85C52; } .purple:hover { background-color: #C96995; } .yellow:hover { background-color: #E3A969; } +.pink:hover { background-color: #A57777; } +.brown:hover { background-color: #662200; } + +.overlay { + position: absolute; + height: 100%; + width: 100%; + display: table; + z-index: 100; +} + +.hide { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0,0,0,0.65); + z-index: 100; +} + +#hide > img { + margin-top: 15%; + animation: fa-spin 3s infinite linear; +} + +.slot { + display: inline-block; +} + +.slot:hover { + outline: 1px solid red; +} + +.slot.small { + width: 40px; + height: 40px; + background-size: 40px 40px; + margin: 1px; +} + +.STR { background: salmon; } +.QCK { background: lightskyblue; } +.DEX { background: lightgreen; } +.PSY { background: gold; } +.INT { background: orchid; } +.RCV { background: darkgoldenrod; } +.TND { background: peru; } +.BLOCK { background: darkslateblue; } +.BOMB { background: maroon; } +.RAINBOW { background: magenta; } +.G { background: orange; } +.EMPTY { background: #777; } + +.block-icon:before { + font-style: normal; + font-weight: normal; + font-family: icomoon; + font-size: 11px; + position: relative; + top: 1px; +} + +.block-icon:before { + content: "\e902"; +} \ No newline at end of file diff --git a/index.html b/index.html index 3744ff03f..f2ca4c746 100644 --- a/index.html +++ b/index.html @@ -1,24 +1,89 @@ + - OPTC Stuff + OPTC Database + + + + + + + + + + + + +
    +
    +
    +

    Updates

    + +

    15/6/2017

    +
    +
      +
    • New Coliseum Units Added to Calculator
    • +
      +
    • We Changed Stuff
    • +
      +
    • Love, Solaris, Zeenigami, Mondfischer & Team
    • +
      +
    + +

    Recently Added:

    + + + + + +
    +
    +
    diff --git a/mats/index.html b/mats/index.html index 5ad5a60c5..f3bbe9695 100644 --- a/mats/index.html +++ b/mats/index.html @@ -5,7 +5,9 @@ - + + + One Piece Treasure Cruise Evolution Helper @@ -56,8 +58,9 @@ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); - ga('create', 'UA-64769042-1', 'auto'); + }) + (window,document,'script','//www.google-analytics.com/analytics.js','ga'); + ga('create', 'UA-73715806-1', 'auto'); ga('send', 'pageview', '/mats'); diff --git a/mats/index.js b/mats/index.js index af85336b6..a46efccd2 100644 --- a/mats/index.js +++ b/mats/index.js @@ -321,8 +321,10 @@ app.directive('decorateSlot',function() { if (scope.uid && attrs.hasOwnProperty('addHref')) element.attr('href','../characters/#/view/' + parseInt(scope.uid, 10)); var url = Utils.getThumbnailUrl(scope.uid); + //var url2 = Utils.getGlobalThumbnailUrl(scope.uid); var div = $('
    '); element[0].style.backgroundImage = 'url(' + url + ')'; + //element[0].style.backgroundImage = 'url(' + url2 + '), url(' + url + ')'; element.append(div); // updating var update = function() { diff --git a/mats/views/popover.html b/mats/views/popover.html index e82d63999..cdd9a36fe 100644 --- a/mats/views/popover.html +++ b/mats/views/popover.html @@ -20,6 +20,9 @@
    + +
    + diff --git a/probability/index.css b/probability/index.css new file mode 100644 index 000000000..93d7642b9 --- /dev/null +++ b/probability/index.css @@ -0,0 +1,748 @@ +/******** + * MAIN * + ********/ + +html, body, body > [ui-view] { + height: 100%; + cursor: default !important; +} + +[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { + display: none !important; +} + +#outer-container, #container { + width: 100%; + height: 100%; +} + +#outer-container { + display: table; +} + +#container { + vertical-align: middle; + text-align: center; +} + +#content { + display: inline-block; +} + +#calculation-area { + padding-bottom: 10px; +} + +#settings > label > input { + position: relative; + right: 1px; + top: 2px; +} + +#special-sheet { + margin-left: auto; + margin-right: auto; + left: 0; + right: 0; +} + +p { + margin: 0px; +} + +.small-container { + padding-top: 10px; + padding-bottom: 10px; + border-bottom: 1px solid #eee; + width: 408px; + margin: 0 auto; +} + +.loose-container { + padding-top: 10px; + padding-bottom: 10px; + border-bottom: 1px solid #eee; +} + + +.page-header { + width: 408px; + margin-left: auto; + margin-right: auto; + margin-bottom: 10px; +} + +.result { + font-weight: 30; + font-size: 30px; +} + +.slots { + display: inline-block; +} + +.unit { + width: 100px; + height: 100px; + border: 1px solid black; + cursor: pointer; + background-size: 100px 100px; + background-position: -1px -1px; + margin: 0 auto; +} + +.unit:hover { + border-color: red; +} + +.unit.empty { + border-style: dashed !important; + opacity: 0.5; +} + +.slot { + display: inline-block; + cursor: pointer; + position: relative; +} + +.slot:not(#add):hover { + outline: 1px solid red; +} + +.slot.medium { + width: 80px; + height: 80px; + background-size: 80px 80px; + margin: 2px; +} + +.slot.small { + width: 40px; + height: 40px; + background-size: 40px 40px; + margin: 1px; +} + +.number-field { + width: 60px; +} + +.unitContainer, .ghostContainer { + width: 100%; + top: 27px; + left: -1px; + padding-bottom: 10px; +} + +.ghoster .unitContainer { + z-index: 201 !important; +} + +.ghosted .unitContainer { + display: none; +} + +slot-wheel { + position: relative; + display: inline-block; + padding-left: 1px; + padding-right: 1px; +} + +slot-wheel > .ghoster { + z-index: 300; +} + +#removeZone { + position: fixed; + right: 5px; + top: 5px; + border-color: red; + opacity: 1; + background-position: 10px 10px; + font-size: 3em; + line-height: 1.5em; + color: salmon; + text-align: center; +} + +#urlContainer { + margin-top: 10px; +} + +#urlContainer { + position: relative; + top: 1px; + height: 0; + white-space: nowrap; + overflow: hidden; + transition: height 0.1s linear; + -moz-transition: height 0.1s linear; +} + +#urlContainer.visible { + height: 37px; +} + +#urlContainer > button { + width: 10%; + margin-right: 5px; + padding: 3px 6px; +} + +#urlContainer > input { + width: 100%; +} + +#transient { + padding: 5px; + margin: 15px auto 0 auto; + cursor: pointer; +} + +#transient:hover { + background-color: #FF9E9E; + border-color: #EC92A0; +} + +#transient > span { + text-decoration: underline; + cursor: help; +} + +#transient-explanation { + padding: 10px; +} + +.quick-fill { + width: 62px; + height: 21px; + margin: 2px 0 2px 0; + outline: 1px solid #777; + text-align: center; + cursor: pointer; + visibility: hidden; +} + +.quick-fill.visible { + visibility: visible; +} + +.quick-fill:hover { + background: #ddd; +} + +.quick-fill-slots { + margin: 2px auto; +} + +.quick-fill-skillups { + display: inline-block; +} + +.label.label-danger { + display: inline-block; + white-space: nowrap; +} + +#canvasContainer { + text-align: center; +} + +canvas { + border: 1px solid black; +} + +/********** + * COLORS * + **********/ + +.color0 { background: #ff6666; } +.color1 { background: #ff9966; } +.color2 { background: #ffcc33; } +.color3 { background: #ffff99; } +.color4 { background: #ccff99; } +.color5 { background: #99cc66; } +.color6 { background: #99cccc; } +.color7 { background: #0099ff; } +.color8 { background: #cc99ff; } +.color9 { background: #cc55cc; } + +/************* + * ABILITIES * + *************/ + +#slotContainer td:nth-child(3) { + width: 100%; +} + +#slotContainer input { + width: 50px; +} + +.ability-button { + width: 62px; + height: 43px; + margin: 2px 0 2px 0; + position: relative; + vertical-align: top; +} + +.inner-backdrop { + position: absolute; + top: -1px; + left: 0; + width: 100%; + height: 100%; + z-index: 99; + background: rgba(255,255,255,0.85); +} + +.busy .ability-button:not(.active) { + pointer-events: none; + z-index: 1; +} + +.ability-button.active { + z-index: 101; +} + +.ability-button:not(.active) .abilitySlot { + display: none; +} + +.ability-button .btn, .abilitySlot { + width: 32px; + height: 32px; + border-radius: 50%; + padding: 0; +} + +.slot-container { + position: relative; +} + +.slot-frame { + position: absolute; + left: 10px; + width: 43px; + height: 43px; + background-position: -320px 0px; + background-size: 363px 43px; + background-image: url('../res/abilities.png') !important; +} + +.ability-button .trigger { + z-index: 100; + cursor: pointer; + position: relative; + top: 5px; +} + +.active:not(#links-button) .trigger { + background: salmon !important; + z-index: 102; +} + +.abilitySlot { + position: absolute; + top: 3px; + left: 16px; + z-index: 1; +} + +.ability { + width: 32px; + height: 32px; + border-radius: 50%; + cursor: pointer; + box-shadow: inset 0 0 1pt 1pt black, 0 0 1pt 1pt white; + -webkit-box-shadow: inset 0 0 1pt 1pt black, 0 0 1pt 1pt white; + -moz-box-shadow: inset 0 0 1pt 1pt black, 0 0 1pt 1pt white; +} + +.ability:hover { + box-shadow: inset 0 0 1pt 1pt black, 0 0 1pt 1pt red; + -webkit-box-shadow: inset 0 0 1pt 1pt black, 0 0 1pt 1pt red; + -moz-box-shadow: inset 0 0 1pt 1pt black, 0 0 1pt 1pt red; +} + +#ability-table td { + vertical-align: middle; +} + +#ability-table td:first-child { + width: 0%; +} + +#ability-table td:last-child { + width: 100%; +} + +#ability-table .next { + color: rgb(100,100,100); +} + +#ability-table .inactive { + color: red; + font-weight: bold; +} + +.abilityLevel { + position: absolute; + bottom: 1px; + right: 3px; + font-size: 11px; + font-weight: bold; + color: white; + text-shadow: 0 0 1px black, -1px 0 1px black, 1px 0 1px black, 0 1px 1px black, 0 -1px 1px black; + cursor: pointer; +} + +/*************** + * POSITIONING * + ***************/ + +.abilitySlot:nth-child(1) { + -webkit-transform: rotate(0); + transform: rotate(0); +} + +.abilitySlot:nth-child(1) > .ability { + transform: translateY(-4em); + -webkit-transform: translateY(-4em); +} + +.abilitySlot:nth-child(1) > .ability, tr:nth-child(1) td > .ability { + background-position: 0 -7px; + background-size: 363px 43px; +} + +.abilitySlot:nth-child(2) { + -webkit-transform: rotate(36deg); + transform: rotate(36deg); +} + +.abilitySlot:nth-child(2) > .ability { + -webkit-transform: translateY(-4em) rotate(-36deg); + transform: translateY(-4em) rotate(-36deg); +} + +.abilitySlot:nth-child(2) > .ability, tr:nth-child(2) td > .ability { + background-position: -32px -7px; + background-size: 363px 43px; +} + +.abilitySlot:nth-child(3) { + -webkit-transform: rotate(72deg); + transform: rotate(72deg); +} + +.abilitySlot:nth-child(3) > .ability { + -webkit-transform: translateY(-4em) rotate(-72deg); + transform: translateY(-4em) rotate(-72deg); +} + +.abilitySlot:nth-child(3) > .ability, tr:nth-child(3) td > .ability { + background-position: -64px -7px; + background-size: 363px 43px; +} + +.abilitySlot:nth-child(4) { + -webkit-transform: rotate(108deg); + transform: rotate(108deg); +} + +.abilitySlot:nth-child(4) > .ability { + -webkit-transform: translateY(-4em) rotate(-108deg); + transform: translateY(-4em) rotate(-108deg); +} + +.abilitySlot:nth-child(4) > .ability, tr:nth-child(4) td > .ability { + background-position: -96px -7px; + background-size: 363px 43px; +} + +.abilitySlot:nth-child(5) { + -webkit-transform: rotate(144deg); + transform: rotate(144deg); +} + +.abilitySlot:nth-child(5) > .ability { + -webkit-transform: translateY(-4em) rotate(-144deg); + transform: translateY(-4em) rotate(-144deg); +} + +.abilitySlot:nth-child(5) > .ability, tr:nth-child(5) td > .ability { + background-position: -128px -7px; + background-size: 363px 43px; +} + +.abilitySlot:nth-child(6) { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); +} + +.abilitySlot:nth-child(6) > .ability { + -webkit-transform: translateY(-4em) rotate(-180deg); + transform: translateY(-4em) rotate(-180deg); +} + +.abilitySlot:nth-child(6) > .ability, tr:nth-child(6) td > .ability { + background-position: -160px -7px; + background-size: 363px 43px; +} + +.abilitySlot:nth-child(7) { + -webkit-transform: rotate(216deg); + transform: rotate(216deg); +} + +.abilitySlot:nth-child(7) > .ability { + -webkit-transform: translateY(-4em) rotate(-216deg); + transform: translateY(-4em) rotate(-216deg); +} + +.abilitySlot:nth-child(7) > .ability, tr:nth-child(7) td > .ability { + background-position: -192px -7px; + background-size: 363px 43px; +} + +.abilitySlot:nth-child(8) { + -webkit-transform: rotate(252deg); + transform: rotate(252deg); +} + +.abilitySlot:nth-child(8) > .ability { + -webkit-transform: translateY(-4em) rotate(-252deg); + transform: translateY(-4em) rotate(-252deg); +} + +.abilitySlot:nth-child(8) > .ability, tr:nth-child(8) td > .ability { + background-position: -224px -7px; + background-size: 363px 43px; +} + +.abilitySlot:nth-child(9) { + -webkit-transform: rotate(288deg); + transform: rotate(288deg); +} + +.abilitySlot:nth-child(9) > .ability { + -webkit-transform: translateY(-4em) rotate(-288deg); + transform: translateY(-4em) rotate(-288deg); +} + +.abilitySlot:nth-child(9) > .ability, tr:nth-child(9) td > .ability { + background-position: -256px -7px; + background-size: 363px 43px; +} + +.abilitySlot:nth-child(10) { + -webkit-transform: rotate(324deg); + transform: rotate(324deg); +} + +.abilitySlot:nth-child(10) > .ability { + -webkit-transform: translateY(-4em) rotate(-324deg); + transform: translateY(-4em) rotate(-324deg); +} + +.abilitySlot:nth-child(10) > .ability, tr:nth-child(10) td > .ability { + background-position: -288px -7px; + background-size: 363px 43px; +} + +.ability-button:not(.active) .abilityBackground { + display: none; +} + +/********** + * POPUPS * + **********/ + +.popup { + position: absolute; + height: 100%; + width: 100%; + display: table; + z-index: 300; + top: 0; + left: 0; +} + +.popup:not(.visible) { + display: none; +} + +.backdrop { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0,0,0,0.65); + z-index: 300; +} + +.inner-container { + position: relative; + display: table-cell; + width: 100%; + height: 100%; + vertical-align: middle; + z-index: 301; +} + +.custom-modal { + position: relative; + z-index: 301; + width: 705px; + margin: auto; +} + +.modal-dialog { + width: 705px; +} + +.modal-content { + border-radius: 0; +} + +.modal-header { + background-color: #428bca; + color: white; +} + +.modal-header a { + color: white; +} + +.modal-footer { + background-color: rgb(235,235,235); +} + +.animated { + animation-duration: 0.2s; + -webkit-animation-duration: 0.2s; +} + +.modal-filter { + width: 100%; +} + +.modal-div:not(.slim) { + height: 340px; + overflow: auto; +} + +.modal-div.tiny { + height: 42px; +}; + +.modal-div td { + padding-left: 5px; +} + +.modal-div table { + width: 100%; +} + +.modal-div th { + padding: 10px 0 10px 0; +} + +.modal-div .to-the-right { + text-align: right; +} + +.modal-div.padded { + padding: 10px; +} + +#recent > span { + border-bottom: 1px solid black; + display: block; +} + +#recentUnits { + height: 42px; + margin-top: 5px; +} + +#saveSlot .alert-danger { + margin-bottom: 0; +} + +#saveSlot .padded { + padding-bottom: 0; +} + +#loadSlot .modal-div { + padding-top: 10px; +} + +#loadSlot tr:hover { + background: #ddd; + cursor: pointer; +} + +#loadSlot td > div { + vertical-align: middle; +} + +#loadSlot td:first-child { + padding-left: 5px; +} + +#summary .label { + font-size: 85%; +} + +/*********** + * POPOVER * + ***********/ + +.popover { + width: 400px; +} + +.popover-content { + color: black; + font-size: 90%; + padding: 0; +} + +.popover-data { + font-size: 90%; +} + +.popover-data table { + margin: 0; +} + +.popover-data td { + width: 25%; + padding: 4px !important; +} + +.popover-data .header > td { + font-weight: bold; +} + +/*************** + * BACKGROUNDS * + ***************/ + +.abilityBackground { + width: 160px; + height: 165px; + -webkit-transform: translate(-48px, -95px); + transform: translate(-48px, -95px); + background-image: url('../res/wheel.png'); +} + +.ability, .slotsBackground { + background-image: url('../res/abilities.png') !important; +} diff --git a/probability/index.html b/probability/index.html new file mode 100644 index 000000000..7a4e90656 --- /dev/null +++ b/probability/index.html @@ -0,0 +1,81 @@ + + + + + + + + + + + + One Piece Treasure Cruise Probability Calculator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + diff --git a/probability/js/app.js b/probability/js/app.js new file mode 100644 index 000000000..dd1f9e07a --- /dev/null +++ b/probability/js/app.js @@ -0,0 +1,64 @@ +(function() { + +var app = angular.module('optc', [ 'ui.router', 'ui.bootstrap', 'ngDialog' ]); + +Utils.parseUnits(false); + +/****************** + * STATE HANDLING * + ******************/ + +app.run(function($rootScope, $state) { + $rootScope.$on('$stateChangeSuccess',function(e) { + var state = $state.current.name; + $rootScope.isPopupVisible = (state != 'main'); + }); + }); + +app.factory("SpecialProbability",['$q',function($q){ + + return { + compute : function(data){ + var worker = new Worker('js/specialprobability.js'); + var defer = $q.defer(); + worker.addEventListener('message', function(e) { + //console.log('Worker said: ', e.data); + defer.notify(e.data); + if (e.data.finished == true) { + defer.resolve(e.data); + worker.terminate(); + } + }, false); + + worker.postMessage(data); // Send data to our worker. + return defer.promise; + } + }; + +}]); + + +app.factory("SocketProbability",['$q',function($q){ + + return { + compute : function(data){ + var worker = new Worker('js/socketprobability.js'); + var defer = $q.defer(); + worker.addEventListener('message', function(e) { + //console.log('Worker said: ', e.data); + defer.notify(e.data); + if (e.data.finished == true) { + defer.resolve(e.data); + worker.terminate(); + } + }, false); + + worker.postMessage(data); // Send data to our worker. + return defer.promise; + } + }; + +}]); + +})(); + diff --git a/probability/js/controllers.js b/probability/js/controllers.js new file mode 100644 index 000000000..aa93fdf70 --- /dev/null +++ b/probability/js/controllers.js @@ -0,0 +1,300 @@ +/* jshint loopfunc: true */ + +(function() { + +var controllers = { }; + +/************ + * MainCtrl * + ************/ + +controllers.MainCtrl = ['$scope', '$rootScope', '$state', '$stateParams', '$controller', '$timeout', '$window', 'SpecialProbability', 'SocketProbability', function($scope, $rootScope, $state, $stateParams, $controller, $timeout, $window, SpecialProbability, SocketProbability) { + + $rootScope.character = null; + $rootScope.options = { transient: false }; + + $scope.skillups = null; + $scope.copies = null; + $scope.slots = null; + $scope.specialEvent = false; + $scope.special3Event = false; + $scope.jpnVersion = false; + + $scope.specialProbabilityProgress = 0; + $scope.specialProbabilityProgressBar = null; + $scope.specialProbabilityResult = 0; + $scope.specialProbabilityColor = null; + $scope.isSpecialReady = true; + // calculate Special Up + $scope.calculateSpecialUp = function() { + if ($scope.copies == null || $scope.skillups == null) { + window.alert("Please enter your amount of copies and the amount of skillups needed"); + return; + } + $scope.isSpecialReady = false; + var data = {copies: $scope.copies, skillups: $scope.skillups, special_event: $scope.specialEvent, special_3event: $scope.special3Event, jpn_server: $scope.jpnVersion}; + SpecialProbability.compute(data).then( + function(data) { + if (data.finished == true) { + if (data.result >= 0.6) { + $scope.specialProbabilityColor = "green"; + } else if (data.result >= 0.3) { + $scope.specialProbabilityColor = "orange"; + } else { + $scope.specialProbabilityColor = "red"; + } + $scope.specialProbabilityResult = Math.min((data.result * 100),99.9).toFixed(1); + $scope.specialProbabilityProgressBar = "Complete"; + $scope.isSpecialReady = true; + } + }, + null, + function(data) { + $scope.specialProbabilityProgress = data.progress; + $scope.specialProbabilityProgressBar = data.progress + "%"; + } + ); + }; + + $scope.socketProbabilityProgress = 0; + $scope.socketProbabilityProgressBar = null; + $scope.socketProbabilityResult = 0; + $scope.socketProbabilityColor = null; + $scope.isSocketReady = true; + // calculate Socket Up + $scope.calculateSocketUp = function() { + if ($scope.copies == null || $scope.character == null) { + window.alert("Please enter your amount of copies and pick the character you want to socket"); + return; + } + $scope.isSocketReady = false; + // create slot array + var slots = Array.apply(null, Array($scope.slots)).map(function (x) { return 0; });; + for (i = 0; i < $scope.character.slots.length; ++i) { + //console.log($scope.character.slots[i]); + var obj = $scope.character.slots[i]; + if (obj != null) { + slots[i] = obj.level; + } else { + slots[i] = 0; + } + } + var data = {copies: $scope.copies, slots: slots}; + SocketProbability.compute(data).then( + function(data) { + if (data.finished == true) { + if (data.result >= 0.6) { + $scope.socketProbabilityColor = "green"; + } else if (data.result >= 0.3) { + $scope.socketProbabilityColor = "orange"; + } else { + $scope.socketProbabilityColor = "red"; + } + $scope.socketProbabilityResult = Math.min((data.result * 100),99.9).toFixed(1); + //console.log($scope.socketProbabilityResult); + $scope.socketProbabilityProgressBar = "Complete"; + $scope.isSocketReady = true; + } + }, + null, + function(data) { + $scope.socketProbabilityProgress = data.progress; + $scope.socketProbabilityProgressBar = data.progress + "%"; + } + ); + }; + + $rootScope.changeUnit = function(unit, uid) { + $scope.character = { uid: uid, slots: [ ], name: $scope.returnName(uid) }; + $scope.slots = $scope.slotCount(uid); + }; + + $scope.range = function(min, max) { + var result = new Array(max - min); + for (var i=0;i input').select(); + }); + + }; + + var notifications = { }; + + $rootScope.notify = function(data) { + data = jQuery.extend({ type: 'information' },data); + if (data.name && notifications[data[name]]) notifications[data[name]].close(); + var notification = noty(jQuery.extend({ timeout: 2500, layout: 'topRight', theme: 'relax' }, data)); + if (data.name) notifications[data[name]] = notification; + return notification; + + }; + + $controller('StorageCtrl', { $scope: $scope }); + $controller('DismissalCtrl'); + +}]; + +/************** + * PickerCtrl * + **************/ + +controllers.PickerCtrl = function($scope, $state, $stateParams, $storage) { + + /* * * * * Scope variables * * * * */ + + $scope.units = [ ]; + $scope.query = ''; + $scope.recents = $storage.get('slotRecentUnits', [ ]); + + $scope.isMats = $stateParams.mats; + + $scope.$watch('query',function() { populateList(); },true); + + /* * * * * Scope functions * * * * */ + + $scope.pickUnit = function(unitNumber) { + $scope.changeUnit($stateParams.unit, unitNumber + 1); + updateRecent(unitNumber); + $state.go('^'); + }; + + /* * * * * List generation * * * * */ + + var populateList = function() { + $scope.units = [ ]; + var result, parameters = Utils.generateSearchParameters($scope.query); + if (parameters === null) return; + result = window.units.filter(function(x) { return x !== null && x !== undefined && x.hasOwnProperty('number'); }); + // filter by query + if (parameters.query) { + result = result.filter(function(unit) { + return parameters.query.test(Utils.getFullUnitName(unit.number + 1)); + }); + } + $scope.units = result; + }; + + var updateRecent = function(unitNumber) { + var recentUnits = JSON.parse(JSON.stringify($scope.recents)); + var n = recentUnits.indexOf(unitNumber); + if (n < 0) recentUnits.unshift(unitNumber); + else recentUnits = recentUnits.splice(n,1).concat(recentUnits); + recentUnits = recentUnits.slice(0,16); + $storage.set('slotRecentUnits', recentUnits); + }; + +}; + +/*************** + * StorageCtrl * + ***************/ + +controllers.StorageCtrl = function($scope, $rootScope, $storage) { + var character = $storage.get('slotCharacter', null); + if (character === null) { + character = $rootScope.character; + } else { + $rootScope.character = character; + } +}; + + +/************* + * ResetCtrl * + *************/ + +controllers.ResetCtrl = function($scope, $rootScope, $state) { + $scope.resetStorage = function() { + $rootScope.character = null; + $state.go('^'); + }; +}; + +/******************* + * InstructionCtrl * + ******************/ + +controllers.InstructionCtrl = function() { + //Do nothing +}; + +/*************** + * PopoverCtrl * + ***************/ + +controllers.PopoverCtrl = function($scope) { + if (!$scope.character) return; + var id = $scope.character.uid; + $scope.details = window.details[id] ? JSON.parse(JSON.stringify(window.details[id])) : null; + $scope.cooldown = window.cooldowns[id - 1]; + if (!$scope.details || !$scope.details.special) return; + if ($scope.details.special.japan) + $scope.details.special = $scope.details.special.japan; + if ($scope.details.special.constructor == Array) { + var lastStage = $scope.details.special.slice(-1)[0]; + $scope.cooldown = lastStage.cooldown; + $scope.details.special = lastStage.description; + } +}; + +/****************** + * Initialization * + ******************/ + +for (var controller in controllers) + angular.module('optc') + .controller(controller, controllers[controller]); + +})(); diff --git a/probability/js/directives.js b/probability/js/directives.js new file mode 100644 index 000000000..de8121ce0 --- /dev/null +++ b/probability/js/directives.js @@ -0,0 +1,138 @@ +/* jshint eqnull: true */ + +(function() { + +var app = angular.module('optc'); + +var directives = { }; + +/********************** + * Element directives * + **********************/ + +directives.slotWheel = function() { + return { + restrict: 'E', + templateUrl: 'views/wheel.html', + link: function(scope, element, attrs) { + + element.find('.trigger').click(function() { + var isActive = element.hasClass('active'); + if (isActive) { + scope.character.slots[scope.slotNumber] = null; + } + element.find('.ability-button').toggleClass('active'); + element.toggleClass('active'); + if (!scope.$$phase) { + scope.$apply(); + } + }); + + scope.isUsed = function(id) { + return scope.character.slots.some(function(x,p) { + return x && p != scope.slotNumber && x.id == id; + }); + }; + + scope.pickAbility = function(e,id) { + var slots = scope.character.slots; + if (!slots[scope.slotNumber] || slots[scope.slotNumber].id != id) { + slots[scope.slotNumber] = { id: id, level: 1 }; + } + element.find('.ability-button').toggleClass('active'); + element.toggleClass('active'); + if (!scope.$$phase) scope.$apply(); + }; + + scope.pickLevel = function(e) { + var n; + if (e.which == 2 || e.ctrlKey || e.metaKey) { + n = 5; + } else { + n = parseInt(prompt('Ability level:'), 10); + } + if (isNaN(n) || n < 0 || n > 5) { + return; + } + scope.character.slots[scope.slotNumber].level = n; + }; + + } + }; +}; + +/************************ + * Attribute directives * + ************************/ + +directives.decorateSlot = function() { + return { + restrict: 'A', + scope: { uid: '=' }, + link: function(scope, element, attrs) { + var update = function(uid) { + if (!uid) element[0].style.backgroundImage = null; + else { + var url = Utils.getThumbnailUrl(scope.uid); + element[0].style.backgroundImage = 'url(' + url + ')'; + //var url2 = Utils.getGlobalThumbnailUrl(scope.uid); + //element[0].style.backgroundImage = 'url(' + url2 + '), url(' + url + ')'; + } + }; + scope.$watch('uid', update); + } + }; +}; + +directives.attachPicker = function() { + return { + restrict: 'A', + scope: true, + controller: function($scope, $state) { $scope.$state = $state; }, + link: function(scope, element, attrs) { + element.longpress(function() { },function(e) { + if (e.which != 1 || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey) return; + if (!$(e.target).hasClass('unit')) return; + if ($(this).hasClass('slide') || $(this).hasClass('dragging')) return; + scope.$state.go('.pick',{ unit: scope.unitNumber }); + }); + } + }; +}; + +directives.autoFocus = function($timeout) { + return { + restrict: 'A', + link: function(scope, element, attrs) { + $timeout(function(){ element[0].focus(); }); + } + }; +}; + +directives.addAbility = function() { + return { + restrict: 'A', + link: function(scope, element, attrs) { + + scope.$watch('character.slots[slotNumber]',function(slot) { + element.removeClass('slotsBackground'); + element.parent().parent().removeClass('color0 color1 color2 color3 color4 color5 color6 color7 color8 color9'); + if (!slot || slot.id === undefined) return; + element.addClass('slotsBackground'); + element.css('background-position', (-32*slot.id-1) + 'px -7px'); + element.css('background-size', '363px 43px'); + element.parent().parent().addClass('color' + slot.id); + },true); + + } + }; +}; + +/****************** + * Initialization * + ******************/ + +for (var directive in directives) + app.directive(directive, directives[directive]); + +})(); diff --git a/probability/js/socketprobability.js b/probability/js/socketprobability.js new file mode 100644 index 000000000..0eabb105f --- /dev/null +++ b/probability/js/socketprobability.js @@ -0,0 +1,84 @@ +onmessage = function(e) { + + var copies = parseInt(e.data.copies); + var slots = e.data.slots; + var temp = slots.slice(0); + + + var approximationLimit = 500000; + var domain = 10; + var max_sockets = 5; + //Array.apply(null, Array(slots)).map(function (x) { return 0; }); // intialize [0, ... , 0] length = #slots + var successful = 0; + var draw_result = 0; + var maxed = true; + + var socketProgress = 0; + var data = null; + + for (var i = 0; i < approximationLimit; i++) { + for (var j = 0; j < copies; j++) { + do { + draw_result = draw(0, domain - 1); + + // if socket is a socket we don't need + if (draw_result >= slots.length) { + break; + } + + // check if pulled socket is already maxed + if (slots[draw_result] < max_sockets) { + slots[draw_result]++; + break; + } + + // we get here if socket pulled is already maxed and we pull again without subtracting the copy count (lazy solution) + } while (true); + + } + // check if all slots were maxed + for (var k = 0; k < slots.length; k++) { + if (slots[k] < max_sockets) { + maxed = false; + break; + } + } + + if (maxed == true) { + successful++; + } + // reset all variables + slots = temp.slice(0); + maxed = true; + drawResult = 0; + + if (i % 5000 == 0) { + //console.log(i); + + socketProgress = Math.round(i / approximationLimit * 100); + data = + { + finished: false, + progress: socketProgress + + }; + postMessage(data); + + } + } + //console.log("successful: " + successful); + //console.log(approximationLimit); + var prob = successful / approximationLimit; + data = + { + finished: true, + result: prob, + progress: 100 + }; + postMessage(data); + +} + +function draw(min, max) { + return Math.floor(Math.random() * (max - min + 1) + min); +} \ No newline at end of file diff --git a/probability/js/specialprobability.js b/probability/js/specialprobability.js new file mode 100644 index 000000000..c2d6649d9 --- /dev/null +++ b/probability/js/specialprobability.js @@ -0,0 +1,77 @@ +onmessage = function(e) { + + var copies = parseInt(e.data.copies); + var skillups = parseInt(e.data.skillups); + + var probability = 0.125; + if (e.data.jpn_server == true) { + probability = .2; + } + // if special event selected probability is doubled + if (e.data.special_event == true) { + probability *= 2; + } + // if special event selected probability is trippled + else if (e.data.special_3event == true) { + probability *= 3; + } + + + var prob = 0; + var result = 0; + + var socketProgress = 0; + var data = null; + + for (var i = skillups; i <= copies; i++) { + result = binomial(copies, i, probability); + prob += result; + + socketProgress = Math.round(i / copies * 100); + + data = + { + finished: false, + progress: socketProgress + + }; + postMessage(data); + + } + + if (isNaN(prob) || !isFinite(prob)) + prob = 0.999; + data = + { + finished: true, + result: prob, + progress: 100 + }; + postMessage(data); +} + +function binomial(copies, skillups, probability) { + return coefficient(copies, skillups) * Math.pow(probability, skillups) + * Math.pow((1 - probability), copies - skillups); +} + +function coefficient(n, k) { + if (k == 0) { + return 1; + } else if (k > n || k < 0 || n < 0) { + return 0; + } else { + var denominator = facculty(n, n - k + 1); + var counter = facculty(k, 1); + + return denominator / counter; + } +} + +function facculty(start, end) { + if (start > end) { + return start * facculty(start - 1, end); + } else { + return end; + } +} diff --git a/probability/js/states.js b/probability/js/states.js new file mode 100644 index 000000000..271ff4137 --- /dev/null +++ b/probability/js/states.js @@ -0,0 +1,53 @@ +(function() { + +angular.module('optc').config(function($stateProvider, $urlRouterProvider) { + + $urlRouterProvider.otherwise('/'); + + $stateProvider + + .state('main',{ + url: '^/', + views: { + '': { + templateUrl: 'views/main.html', + controller: 'MainCtrl', + } + } + }) + + .state('main.pick',{ + views: { + 'popup@': { + templateUrl: 'views/picker.html', + controller: 'PickerCtrl' + } + }, + params: { unit: 0 } + }) + + + .state('main.reset',{ + views: { + 'popup@': { + templateUrl: 'views/popup/reset.html', + controller: 'ResetCtrl' + } + } + }) + + .state('main.instruction',{ + url: 'instruction', + views: { + 'popup@': { + templateUrl: 'views/popup/instruction.html', + controller: 'InstructionCtrl' + } + } + }) + + + +}); + +})(); diff --git a/probability/views/fragments/popover.html b/probability/views/fragments/popover.html new file mode 100644 index 000000000..5bd1c9b77 --- /dev/null +++ b/probability/views/fragments/popover.html @@ -0,0 +1,22 @@ +
    + + + + + + + + + + +
    Special
    +
    + {{details.special}} +
    +
    + {{cooldown.length ? cooldown[0] : cooldown}} turns + {{cooldown.length ? ' (maxed: ' + cooldown[1] + ' turns)' : ''}} +
    +
    + +
    diff --git a/probability/views/main.html b/probability/views/main.html new file mode 100644 index 000000000..1470facb9 --- /dev/null +++ b/probability/views/main.html @@ -0,0 +1,108 @@ +
    +
    +
    +

    + Probability Calculator +

    +
    +
    + +
    + +
    + +
    +

    Select which Sockets your Unit already has.

    +

    This Unit has no Sockets.

    +
    + Quick fill +
    +
    + + + + +
    + +
    +
    + +
    + +
    +
    + Special x2 Event + Special x3 Event +
    +     + +

    + Copies/Books: +

    + Number of Skill-Ups You Need: +
    + Quick fill +
    + +
    + +
    +

    + Probability to get {{skillups}} skillups with {{copies}} copies/books:
    + +

    + {{specialProbabilityProgressBar}} + +
    + +
    +

    + Probability to max above Powers with {{copies}} copies:
    + Note: Slots chosen above are how many you CURRENTLY have
    + To change how many of a type you have, click on the number
    + +

    + {{socketProbabilityProgressBar}} + +
    + + + +
    + +
    + +
    + +
    + + + + + + + +
    + +
    + + Transient mode enabled. Click to disable. +
    + +
    +
    +
    diff --git a/probability/views/picker.html b/probability/views/picker.html new file mode 100644 index 000000000..4ed7ce275 --- /dev/null +++ b/probability/views/picker.html @@ -0,0 +1,38 @@ +
    + +
    + +
    + + +
    + +
    diff --git a/probability/views/popup/instruction.html b/probability/views/popup/instruction.html new file mode 100644 index 000000000..691dd8a3a --- /dev/null +++ b/probability/views/popup/instruction.html @@ -0,0 +1,39 @@ +
    + +
    + +
    + +
    + +
    diff --git a/probability/views/popup/reset.html b/probability/views/popup/reset.html new file mode 100644 index 000000000..194dd7de7 --- /dev/null +++ b/probability/views/popup/reset.html @@ -0,0 +1,20 @@ +
    + +
    + +
    + +
    + +
    diff --git a/probability/views/wheel.html b/probability/views/wheel.html new file mode 100644 index 000000000..2b81018a9 --- /dev/null +++ b/probability/views/wheel.html @@ -0,0 +1,22 @@ + diff --git a/res/blank_dex.png b/res/blank_dex.png new file mode 100644 index 000000000..7533ba0d0 Binary files /dev/null and b/res/blank_dex.png differ diff --git a/res/blank_int.png b/res/blank_int.png new file mode 100644 index 000000000..347357436 Binary files /dev/null and b/res/blank_int.png differ diff --git a/res/blank_psy.png b/res/blank_psy.png new file mode 100644 index 000000000..6361e1026 Binary files /dev/null and b/res/blank_psy.png differ diff --git a/res/blank_qck.png b/res/blank_qck.png new file mode 100644 index 000000000..bc1c85599 Binary files /dev/null and b/res/blank_qck.png differ diff --git a/res/blank_str.png b/res/blank_str.png new file mode 100644 index 000000000..b2d517bf7 Binary files /dev/null and b/res/blank_str.png differ diff --git a/slots/index.html b/slots/index.html index 9400b58bb..c4c8e954b 100644 --- a/slots/index.html +++ b/slots/index.html @@ -5,7 +5,9 @@ - + + + One Piece Treasure Cruise Slot Planner @@ -27,6 +29,7 @@ + @@ -55,8 +58,9 @@ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); - ga('create', 'UA-64769042-1', 'auto'); + }) + (window,document,'script','//www.google-analytics.com/analytics.js','ga'); + ga('create', 'UA-73715806-1', 'auto'); ga('send', 'pageview', '/slots'); diff --git a/slots/js/controllers.js b/slots/js/controllers.js index 83b565be5..a76e7f7eb 100644 --- a/slots/js/controllers.js +++ b/slots/js/controllers.js @@ -76,7 +76,17 @@ controllers.MainCtrl = function($scope, $rootScope, $state, $stateParams, $contr for (var i=0;i - + + - - - -
    -
    +
    Transient mode enabled. Click to disable.
    diff --git a/slots/views/popup/copy.html b/slots/views/popup/copy.html new file mode 100644 index 000000000..83ec50656 --- /dev/null +++ b/slots/views/popup/copy.html @@ -0,0 +1,20 @@ +
    + +
    + +
    + +
    + +
    diff --git a/turtles/.gitignore b/turtles/.gitignore new file mode 100644 index 000000000..c30dae854 --- /dev/null +++ b/turtles/.gitignore @@ -0,0 +1,9 @@ +css/.sass-cache/ +css/bootstrap.css.map +css/main.css.map +/vendor/ +process.php +composer.json +composer.lock +.DS_Store +.sass-cache/ diff --git a/turtles/README.md b/turtles/README.md new file mode 100644 index 000000000..f3758b7a1 --- /dev/null +++ b/turtles/README.md @@ -0,0 +1,6 @@ +# OPTC Calculator +This is a calculator for the mobile game One Piece Treasure Cruise. More features will be added as they are requested. Shoot me a message on reddit if you want something else added. + +Changelog can be viewed [here](https://github.com/cyung/optc/commits/gh-pages). + +This is my first project done using AngularJS and I'm learning along the way, but I've made sure to follow the [Angular Style Guide](https://github.com/johnpapa/angular-styleguide) to make for easy reading. diff --git a/turtles/app/app.js b/turtles/app/app.js new file mode 100644 index 000000000..380634d24 --- /dev/null +++ b/turtles/app/app.js @@ -0,0 +1,9 @@ +angular.module('app', ['LocalStorageModule', 'timer', 'ngTable', 'pascalprecht.translate', 'ui.bootstrap', 'ngAnimate', 'polyglotLanguageSwitcher']) +.config( [ + '$compileProvider', + function( $compileProvider ) + { + $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrome-extension|data):/); + // Angular before v1.2 uses $compileProvider.urlSanitizationWhitelist(...) + } +]); \ No newline at end of file diff --git a/turtles/app/app2.js b/turtles/app/app2.js new file mode 100644 index 000000000..ad07bc165 --- /dev/null +++ b/turtles/app/app2.js @@ -0,0 +1 @@ +angular.module('app', ['ajoslin.promise-tracker']); \ No newline at end of file diff --git a/turtles/app/config/localizeConfig.js b/turtles/app/config/localizeConfig.js new file mode 100644 index 000000000..f0e2ec296 --- /dev/null +++ b/turtles/app/config/localizeConfig.js @@ -0,0 +1,101 @@ +angular.module('app') + .config(function ($translateProvider) { + $translateProvider.translations('en', { + NAV_TURTLE: 'Turtle Time', + NAV_BARREL: 'Barrel Breaking', + NAV_EVENT: 'Event', + NAV_CONTACT: 'Contact Me', + NAV_SETTINGS: 'Settings', + TT_TITLE: 'Turtle Time Calculator', + TT_DIGIT: '6th ID digit:', + TT_FORMAT: '24hr format', + TT_TIMEZONE: 'Time Zone:', + TT_SEEMORE: 'See More', + TT_ADD_CALENDAR: 'Add to Calendar', + TT_NOTIFICATION: 'Notification Settings', + TT_NOTIF_MINUTES: 'Minutes before event', + TT_NOTIF_SOUND: 'Play sound', + TT_NOTIF_EXAMPLE: 'Example', + BB_TITLE: 'Barrel Breaking', + BB_TIME: 'Time till next rotation:', + BB_ALT: 'Show Hours', + BB_DATE: 'Date', + BB_WOODEN: 'Wooden', + BB_SILVER: 'Silver', + BB_GOLD: 'Gold' + }) + .translations('de', { + NAV_TURTLE: 'Turtle Zeiten', + NAV_BARREL: 'Friend Game', + NAV_EVENT: 'Ereignis', + NAV_CONTACT: 'Kontaktiere Mich', + NAV_SETTINGS: 'Einstellungen', + TT_TITLE: 'Turtle Zeiten Rechner', + TT_DIGIT: '6te Ziffer der ID:', + TT_FORMAT: '24-Stunden Format', + TT_TIMEZONE: 'Zeitzone:', + TT_SEEMORE: 'siehe mehr', + TT_ADD_CALENDAR: 'Zum Kalender hinzufügen', + TT_NOTIFICATION: 'Mitteilungeinstellungen', + TT_NOTIF_MINUTES: 'Minuten bis zur Veranstaltung', + TT_NOTIF_SOUND: 'Ton abspielen', + TT_NOTIF_EXAMPLE: 'Beispiel', + BB_TITLE: 'Barrel Breaking', + BB_TIME: 'Zeit bis zum nächsten Wechsel:', + BB_ALT: 'Anzeige Stunden', + BB_DATE: 'Datum', + BB_WOODEN: 'Holz', + BB_SILVER: 'Silber', + BB_GOLD: 'Gold' + }) + .translations('es', { + NAV_TURTLE: 'Horario Tortugas', + NAV_BARREL: 'Friend Game', + NAV_EVENT: 'Evento', + NAV_CONTACT: 'Contáctame', + NAV_SETTINGS: 'Configuración', + TT_TITLE: 'Horario Tortugas Calculadora', + TT_DIGIT: '6th dígito de ID:', + TT_FORMAT: '24 horas', + TT_TIMEZONE: 'Zona Horaria:', + TT_SEEMORE: 'ver más', + TT_ADD_CALENDAR: 'Añadir al calendario', + TT_NOTIFICATION: 'Configuración De Las Notificaciones', + TT_NOTIF_MINUTES: 'Minutos antes de evento', + TT_NOTIF_SOUND: 'Reproducir sonido', + TT_NOTIF_EXAMPLE: 'Ejemplo', + BB_TITLE: 'Friend Game', + BB_TIME: 'Tiempo hasta la próxima rotación:', + BB_ALT: 'Mostrar las horas', + BB_DATE: 'Fecha', + BB_WOODEN: 'Madera', + BB_SILVER: 'Plata', + BB_GOLD: 'Oro' + }) + .translations('fr', { + NAV_TURTLE: 'Horaires des Tortues', + NAV_BARREL: 'Partie d\'amis', + NAV_EVENT: 'Event', + NAV_CONTACT: 'Me Contacter', + NAV_SETTINGS: 'Réglages', + TT_TITLE: 'Calculateur de l\'Horaire des Tortues', + TT_DIGIT: '6eme chiffre ID:', + TT_FORMAT: 'Format 24h', + TT_TIMEZONE: 'Fuseau Horaire:', + TT_SEEMORE: 'Lire la suite', + TT_ADD_CALENDAR: 'Ajouter au Calendrier', + TT_NOTIFICATION: 'Réglages des Notifications', + TT_NOTIF_MINUTES: 'Temps Restant avant Event', + TT_NOTIF_SOUND: 'Jouer le son', + TT_NOTIF_EXAMPLE: 'Exemple', + BB_TITLE: 'Éclatement du Tonneau', + BB_TIME: 'Temps jusqu\'à la Prochaine Rotation:', + BB_ALT: 'Afficher les Heures', + BB_DATE: 'Date', + BB_WOODEN: 'Bois', + BB_SILVER: 'Argent', + BB_GOLD: 'Or', + }); + $translateProvider.preferredLanguage('en'); + $translateProvider.useSanitizeValueStrategy('escaped'); + }); diff --git a/turtles/app/controllers/barrelCtrl.js b/turtles/app/controllers/barrelCtrl.js new file mode 100644 index 000000000..43e66b208 --- /dev/null +++ b/turtles/app/controllers/barrelCtrl.js @@ -0,0 +1,82 @@ +angular.module('app') + .controller('BarrelCtrl', function($scope, localStorageService){ + var self = this; + self.see_more = false; + + var day = moment().utc().startOf('day').add(12,'hours'); + var local = day.clone().local(); + var hour_start = local.format('HH:mm'); + var hour_end = local.clone().add(23,'hours').add(59, 'minutes').format('HH:mm'); + var hour_string = ' ' + hour_start + '-' + hour_end; + var now = moment(); + if (day.isAfter(now)) + day.subtract(1, 'days'); + + self.day_num = day.dayOfYear(); + self.day = day.clone().add(1, 'days').format('x'); + self.times = []; + self.show_hours = JSON.parse(localStorageService.get('show_hours')); + if (self.show_hours === null) + self.show_hours = false; + + set_time(); + + + $scope.$watch(function() { + return self.show_hours; + }, function(newVal) { + localStorageService.set('show_hours', self.show_hours); + set_time(); + }); + + function set_time() { + self.times = []; + for (var i=0; i<5; i++) + self.times.push(calc_day(i)); + } + + function calc_day(day_offset) { + var wooden = [0,5,4,9,3,8,4,9,2,7,3,8,1,6,2,7,0,5,1,6]; + var silver = [1,6,2,7,0,5,1,6,0,5,4,9,3,8,4,9,2,7,3,8]; + var gold = [3,8,2,7,1,6,0,5,4,9]; + + var offset = self.day_num + day_offset + 4; + offset = offset % 5; + + var start1 = (offset*4) % 20; + var start2 = (offset*2) % 10; + + var chest_wooden = wooden.slice(start1, start1+4); + var chest_silver = silver.slice(start1, start1+4); + var chest_gold = gold .slice(start2, start2+2); + + var now = moment(); + now.add(day_offset,'day'); + + var date = now.format('YYYY/MM/DD'); + + // Show Hours display + var day_end = day.clone().local().add(day_offset, 'day') + .add(23, 'hours').add(59, 'minutes'); + var current_day = moment(date, "YYYY/MM/DD").endOf('day'); + if (self.show_hours){ + if (current_day.isAfter(day_end)) + date = current_day.subtract(1,'day').format('YYYY/MM/DD'); + date += hour_string; + } + + + var chest_day = {}; + chest_day.date = date; + chest_day.wooden = chest_wooden; + chest_day.silver = chest_silver; + chest_day.gold = chest_gold; + + return chest_day; + } + + self.range = function(num) { + return new Array(num); + }; + + }); \ No newline at end of file diff --git a/turtles/app/controllers/contactCtrl.js b/turtles/app/controllers/contactCtrl.js new file mode 100644 index 000000000..8e3efc69f --- /dev/null +++ b/turtles/app/controllers/contactCtrl.js @@ -0,0 +1,73 @@ +angular.module('app') + .controller('ContactCtrl', function ($scope, $http, $log, promiseTracker, $timeout) { + $scope.subjectListOptions = [ + 'Report a bug', + 'Make a suggestion', + 'Other' + ]; + + $scope.subjectList = $scope.subjectListOptions[0]; + + // Inititate the promise tracker to track form submissions. + $scope.progress = promiseTracker(); + + // Form submit handler. + $scope.submit = function(form) { + // Trigger validation flag. + $scope.submitted = true; + + // If form is invalid, return and let AngularJS show validation errors. + if (form.$invalid) { + return; + } + + var formData = { + 'From': $scope.name, + 'Email': $scope.email, + 'Subject': $scope.subjectList, + 'Comments': $scope.comments + }; + console.log('formData = ', formData); + // var $promise = $http.post('process.php', formData) + var $promise = $http({ + url: 'process.php', + method: 'POST', + data: $.param(formData), + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + } + }) + .success(function(data, status, headers, config) { + console.log('data', data); + console.log('status', status); + console.log('headers', headers); + console.log('config', config); + if (data == 'OK') { + $scope.name = null; + $scope.email = null; + $scope.subjectList = null; + $scope.url = null; + $scope.comments = null; + $scope.messages = 'Your form has been sent!'; + $scope.submitted = false; + } else { + $scope.messages = 'Oops. We received your request, but there was an error processing it.'; + $log.error(data); + } + }) + .error(function(data, status, headers, config) { + $scope.progress = data; + $scope.messages = 'There was a network error. Try again later.'; + $log.error(data); + }) + .finally(function() { + // Hide status messages after three seconds. + $timeout(function() { + $scope.messages = null; + }, 3000); + }); + + // Track the request and show its progress to the user. + $scope.progress.addPromise($promise); + }; + }); \ No newline at end of file diff --git a/turtles/app/controllers/eventCtrl.js b/turtles/app/controllers/eventCtrl.js new file mode 100644 index 000000000..8fb6a33ce --- /dev/null +++ b/turtles/app/controllers/eventCtrl.js @@ -0,0 +1,160 @@ +angular.module('app') + .controller('EventCtrl', function($scope, localStorageService){ + var self = this; + + /*====================================== + = One-time event = + ======================================*/ + + // self.timezone = jstz.determine().name(); + + // self.my_time = moment.utc("2015-07-08 13:00").local(); + // self.id = localStorageService.get('id'); + // self.military = JSON.parse(localStorageService.get('military')); + + /*----- End of One-time event ------*/ + + /*================================== + = COUNTDOWNS = + ==================================*/ + + // var sugofest = moment.utc("2015-07-15 03:00"); + // console.log(sugofest.format("x")); + + /*----- End of COUNTDOWNS ------*/ + + + + var day = moment().utc().startOf('day').add(8,'hours'); + var day_jpn = moment().utc().startOf('day').add(2, 'hours'); + + var now = moment(); + if (day.isAfter(now)) + day.subtract(1, 'days'); + if (day_jpn.isAfter(now)) + day_jpn.subtract(1, 'days'); + + var day_num = day.dayOfYear(); + var day_num_jpn = day_jpn.dayOfYear(); + self.next_day = day.clone().add(1, 'days').format('x'); + self.next_day_jpn = day_jpn.clone().add(1, 'days').format('x'); + self.times = []; + + self.global = localStorageService.get('version'); + if (self.global === null) + self.global = 'global'; + self.show_hours = JSON.parse(localStorageService.get('show_hours')); + if (self.show_hours === null) + self.show_hours = false; + + calc_hour_string(); + + var drop = ['Loguetown, Jaya', 'Arlong Park, Alubarna', 'Baratie, Nanohana Rainbase', 'Syrup Village, Drum Island', 'Orange Town, Little Garden', 'Shell Town, Whiskey Peak, Ark Maxim', "Alvida's Hideout, Twin Cape"]; + var stamina = ['Orange Town, Drum Island', 'Shell Town, Little Garden', "Alvida's Hideout, Whiskey Peak", 'Fuschia Village, Twin Cape, Skypia', 'Loguetown, Jaya', 'Arlong Park, Alubarna', 'Baratie, Nanohana Rainbase']; + var beli = ['Baratie, Whiskey Peak, Ark Maxim', 'Syrup Village, Twin Cape, Skypia', 'Loguetown, Jaya', 'Arlong Park, Alubarna', 'Baratie, Nanohana Rainbase', 'Syrup Village, Drum Island', 'Little Garden']; + var drop_jpn = ['Loguetown, Jaya', 'Arlong Park, Alubarna', 'Baratie, Nanohana Rainbase', 'Syrup Village, Drum Island', 'Orange Town, Little Garden', 'Shell Town, Whiskey Peak, Ark Maxim', "Alvida's Hideout, Twin Cape"]; + var stamina_jpn = ['Orange Town, Drum Island', 'Shell Town, Little Garden', "Alvida's Hideout, Whiskey Peak", 'Fuschia Village, Twin Cape, Skypia', 'Loguetown, Jaya', 'Arlong Park, Alubarna', 'Baratie, Nanohana Rainbase']; + var beli_jpn = ['Baratie, Whiskey Peak, Ark Maxim', 'Syrup Village, Twin Cape, Skypia', 'Loguetown, Jaya', 'Arlong Park, Alubarna', 'Baratie, Nanohana Rainbase', 'Syrup Village, Drum Island', 'Little Garden']; + + self.version = function() { + return (self.global === 'global'); + }; + + set_time(); + + $scope.$watch(function() { + return self.show_hours; + }, function(newVal) { + localStorageService.set('bb_alt'); + set_time(); + }); + + $scope.$watch(function() { + return self.global; + }, function(newVal) { + set_time(); + localStorageService.set('version'); + }); + + + function set_time() { + self.times = []; + for (var i=0; i<7; i++) + self.times.push(calc_day(i)); + } + + function calc_day(day_offset) { + var offset, day_drop, day_stamina, day_beli; + if (self.version()) { + offset = (day_num + day_offset + 2) % 7; + day_drop = drop[offset]; + day_stamina = stamina[offset]; + day_beli = beli[offset]; + } else { + offset = (day_num_jpn + day_offset + 2) % 7; + day_drop = drop_jpn[offset]; + day_stamina = stamina_jpn[offset]; + day_beli = beli_jpn[offset]; + } + + offset = offset % 7; + + var now = moment(); + for (var i=0; i

    {{date}}

    Wooden {{chest_wooden}}

    Silver {{chest_silver}}

    Gold {{chest_gold}}

    ', + link: function (scope, elem, attrs) { + var wooden = [0,5,4,9,3,8,4,9,2,7,3,8,1,6,2,7,0,5,1,6]; + var silver = [1,6,2,7,0,5,1,6,0,5,4,9,3,8,4,9,2,7,3,8]; + var gold = [3,8,2,7,1,6,0,5,4,9]; + + var offset = parseInt(scope.index) + scope.dayNum; + offset += 4; + + var start1 = (offset*4) % 20; + var start2 = (offset*2) % 10; + + scope.chest_wooden = wooden.slice(start1, start1+4); + scope.chest_silver = silver.slice(start1, start1+4); + scope.chest_gold = gold .slice(start2, start2+2); + + var date = moment(); + for (var i=0; i{{hhours}}:{{mminutes}}:{{sseconds}}'; + return html; + }, + compile: function(elem, attrs) { + } + }; + }); \ No newline at end of file diff --git a/turtles/app/directives/collapseDirective.js b/turtles/app/directives/collapseDirective.js new file mode 100644 index 000000000..aba284596 --- /dev/null +++ b/turtles/app/directives/collapseDirective.js @@ -0,0 +1,65 @@ +angular.module('ui.bootstrap.collapse', []) + + .directive('collapse', ['$animate', '$animateCss', '$timeout', function ($animate, $animateCss, $timeout) { + + return { + link: function (scope, element, attrs) { + function expand() { + element.removeClass('collapse').addClass('collapsing'); + + var animation = $animateCss(element, { + addClass: 'in', + to: { height: element[0].scrollHeight + 'px' } + }); + + animation.start().done(expandDone); + } + + function expandDone() { + element.removeClass('in collapsing'); + element.css({height: 'auto'}); + } + + function collapse() { + // if(! element.hasClass('collapse') && ! element.hasClass('in')) { + // return collapseDone(); + // } + if (element.hasClass('init')){ + element.removeClass('init'); + return collapseDone(); + } + element + // IMPORTANT: The height must be set before adding "collapsing" class. + // Otherwise, the browser attempts to animate from height 0 (in + // collapsing class) to the given height here. + .css({height: element[0].scrollHeight + 'px'}) + // initially all panel collapse have the collapse class, this removal + // prevents the animation from jumping to collapsed state + .removeClass('collapse') + .addClass('collapsing'); + + + var animation = $animateCss(element, { + addClass: 'in', + to: { height: '0' } + }); + + animation.start().done(collapseDone); + } + + function collapseDone() { + element.css({height: '0'}); // Required so that collapse works when animation is disabled + element.removeClass('in collapsing'); + element.addClass('collapse'); + } + + scope.$watch(attrs.collapse, function (shouldCollapse) { + if (shouldCollapse) { + collapse(); + } else { + expand(); + } + }); + } + }; + }]); \ No newline at end of file diff --git a/turtles/app/directives/eventDirective.js b/turtles/app/directives/eventDirective.js new file mode 100644 index 000000000..314f5b172 --- /dev/null +++ b/turtles/app/directives/eventDirective.js @@ -0,0 +1,190 @@ +angular.module('app') + .directive('eventDay', function (localStorageService) { + return { + restrict: 'AE', + scope: { + military: '=', + index: '=', + my_id: '=myId', + my_time: '=myTime', + locale: '=' + }, + template: '

    {{date1}}{{ttime1_format}}

    {{date2}}{{ttime2_format}}

    4) + id -=5; + + ttime.add(weekly_order[id]*2, 'hours'); + if (second_time) + ttime.add(10,'hours'); + return ttime; + } + + function print_time(date, military) { + if (military) + return date.format('HH:mm'); + return date.format('h:mm a'); + } + } + }; + }) + .directive('eventDayJpn', function (localStorageService) { + return { + restrict: 'AE', + scope: { + military: '=', + index: '=', + my_id: '=myId', + my_time: '=myTime', + locale: '=' + }, + template: '

    {{date1}}{{ttime1_format}}

    {{hhours}}:{{mminutes}}:{{sseconds}}'; + return html; + } + }; + }); \ No newline at end of file diff --git a/turtles/app/directives/turtleBetaDirective.js b/turtles/app/directives/turtleBetaDirective.js new file mode 100644 index 000000000..d160b44e7 --- /dev/null +++ b/turtles/app/directives/turtleBetaDirective.js @@ -0,0 +1,62 @@ +(function() { + 'use strict'; + + angular.module('app') + .directive('turtleBeta', + turtle_beta); + + function turtle_beta(turtleFact) { + return { + restrict: 'E', + scope: { + military: '=', + locale: '=', + index: '=', + numid: '=', + version: '=' + }, + template: '

    {{date}}{{ttime_format}}

    ', + link: linker + } + + function linker(scope, elem, attrs) { + function update_times() { + var ttime = turtleFact.get_ttimes()[scope.index].local(); + if (scope.locale !== null) + ttime.locale(scope.locale); + else + ttime.locale('en'); + + scope.date = ttime.format('LL'); + scope.ttime_format = print_time(ttime); + } + + function print_time (date) { + if (scope.military) + return date.format('HH:mm'); + return date.format('h:mm a'); + } + + + scope.$watch('numid', function(newVal, oldVal) { + update_times(); + }); + + scope.$watch('military', function(newVal, oldVal) { + update_times(); + }); + + scope.$watch('ttime', function(newVal, oldVal) { + update_times(); + }); + + scope.$watch('locale', function(newVal, oldVal) { + update_times(); + }); + + scope.$watch('version', function(newVal, oldVal) { + update_times(); + }); + } + } +})() \ No newline at end of file diff --git a/turtles/app/directives/turtleDirective.js b/turtles/app/directives/turtleDirective.js new file mode 100644 index 000000000..554b01a06 --- /dev/null +++ b/turtles/app/directives/turtleDirective.js @@ -0,0 +1,194 @@ +angular.module('app') + .directive('turtleDay', function (localStorageService) { + return { + restrict: 'AE', + scope: { + military: '=', + index: '=', + my_id: '=myId', + my_time: '=myTime', + locale: '=' + }, + template: '

    {{date1}}{{ttime1_format}}

    {{date2}}{{ttime2_format}}

    ', + link: function (scope, elem, attrs) { + var my_time = scope.my_time; + var week_num = scope.index; + + scope.$watch('military', function(value) { + update_times(); + if (scope.military !== null) + localStorageService.set('military', scope.military); + }); + + scope.$watch('my_id', function(value) { + update_times(); + if (scope.my_id !== null && scope.my_id !== undefined) + localStorageService.set('id', scope.my_id); + }); + + scope.$watch('locale', function(value) { + update_times(); + }); + + function update_times() { + var ttime1 = calc_time(scope.my_id, false); + var ttime2 = calc_time(scope.my_id, true); + + if (scope.locale !== null){ + ttime1.locale(scope.locale); + ttime2.locale(scope.locale); + } + scope.date1 = ttime1.format('LL'); + scope.date2 = ttime2.format('LL'); + scope.ttime1_format = print_time(ttime1, scope.military); + scope.ttime2_format = print_time(ttime2, scope.military); + } + + function calc_time(id, second_time) { + var weekly_order = [0,1,2,3,4]; + var ttime = my_time.clone(); + var offset = week_num + my_time.isoWeek() + 3; + + offset = offset % 5; + + for (var i=0; i < offset; i++) + weekly_order.unshift(weekly_order.pop()); + + for (i=0; i < week_num; i++) + ttime.add(1, 'week'); + + if (id>4) + id -=5; + + ttime.add(weekly_order[id]*2, 'hours'); + if (second_time) + ttime.add(10,'hours'); + + return ttime; + } + + function print_time(date, military) { + if (military) + return date.format('HH:mm'); + return date.format('h:mm a'); + } + } + }; + }) + .directive('turtleDayJpn', function (localStorageService) { + return { + restrict: 'AE', + scope: { + military: '=', + index: '=', + my_id: '=myId', + my_time: '=myTime', + locale: '=', + jpn_monday: '=jpnMonday' + }, + template: '

    {{date1}}{{ttime1_format}}

    1 ? end : this.data.length) + , type + , this.encoding + ); + }; + FB_proto.toString = function() { + return "[object Blob]"; + }; + FB_proto.close = function() { + this.size = 0; + delete this.data; + }; + return FakeBlobBuilder; + }(view)); + + view.Blob = function(blobParts, options) { + var type = options ? (options.type || "") : ""; + var builder = new BlobBuilder(); + if (blobParts) { + for (var i = 0, len = blobParts.length; i < len; i++) { + if (Uint8Array && blobParts[i] instanceof Uint8Array) { + builder.append(blobParts[i].buffer); + } + else { + builder.append(blobParts[i]); + } + } + } + var blob = builder.getBlob(type); + if (!blob.slice && blob.webkitSlice) { + blob.slice = blob.webkitSlice; + } + return blob; + }; + + var getPrototypeOf = Object.getPrototypeOf || function(object) { + return object.__proto__; + }; + view.Blob.prototype = getPrototypeOf(new view.Blob()); +}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this)); \ No newline at end of file diff --git a/turtles/app/lib/FileSaver.js b/turtles/app/lib/FileSaver.js new file mode 100644 index 000000000..11081a897 --- /dev/null +++ b/turtles/app/lib/FileSaver.js @@ -0,0 +1,253 @@ +/* FileSaver.js + * A saveAs() FileSaver implementation. + * 2015-05-07.2 + * + * By Eli Grey, http://eligrey.com + * License: X11/MIT + * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md + */ + +/*global self */ +/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ + +/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ + +var saveAs = saveAs || (function(view) { + "use strict"; + // IE <10 is explicitly unsupported + if (typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { + return; + } + var + doc = view.document + // only get URL when necessary in case Blob.js hasn't overridden it yet + , get_URL = function() { + return view.URL || view.webkitURL || view; + } + , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a") + , can_use_save_link = "download" in save_link + , click = function(node) { + var event = doc.createEvent("MouseEvents"); + event.initMouseEvent( + "click", true, false, view, 0, 0, 0, 0, 0 + , false, false, false, false, 0, null + ); + node.dispatchEvent(event); + } + , webkit_req_fs = view.webkitRequestFileSystem + , req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem + , throw_outside = function(ex) { + (view.setImmediate || view.setTimeout)(function() { + throw ex; + }, 0); + } + , force_saveable_type = "application/octet-stream" + , fs_min_size = 0 + // See https://code.google.com/p/chromium/issues/detail?id=375297#c7 and + // https://github.com/eligrey/FileSaver.js/commit/485930a#commitcomment-8768047 + // for the reasoning behind the timeout and revocation flow + , arbitrary_revoke_timeout = 500 // in ms + , revoke = function(file) { + var revoker = function() { + if (typeof file === "string") { // file is an object URL + get_URL().revokeObjectURL(file); + } else { // file is a File + file.remove(); + } + }; + if (view.chrome) { + revoker(); + } else { + setTimeout(revoker, arbitrary_revoke_timeout); + } + } + , dispatch = function(filesaver, event_types, event) { + event_types = [].concat(event_types); + var i = event_types.length; + while (i--) { + var listener = filesaver["on" + event_types[i]]; + if (typeof listener === "function") { + try { + listener.call(filesaver, event || filesaver); + } catch (ex) { + throw_outside(ex); + } + } + } + } + , auto_bom = function(blob) { + // prepend BOM for UTF-8 XML and text/* types (including HTML) + if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { + return new Blob(["\ufeff", blob], {type: blob.type}); + } + return blob; + } + , FileSaver = function(blob, name) { + blob = auto_bom(blob); + // First try a.download, then web filesystem, then object URLs + var + filesaver = this + , type = blob.type + , blob_changed = false + , object_url + , target_view + , dispatch_all = function() { + dispatch(filesaver, "writestart progress write writeend".split(" ")); + } + // on any filesys errors revert to saving with object URLs + , fs_error = function() { + // don't create more object URLs than needed + if (blob_changed || !object_url) { + object_url = get_URL().createObjectURL(blob); + } + if (target_view) { + target_view.location.href = object_url; + } else { + var new_tab = view.open(object_url, "_blank"); + if (new_tab == undefined && typeof safari !== "undefined") { + //Apple do not allow window.open, see http://bit.ly/1kZffRI + view.location.href = object_url + } + } + filesaver.readyState = filesaver.DONE; + dispatch_all(); + revoke(object_url); + } + , abortable = function(func) { + return function() { + if (filesaver.readyState !== filesaver.DONE) { + return func.apply(this, arguments); + } + }; + } + , create_if_not_found = {create: true, exclusive: false} + , slice + ; + filesaver.readyState = filesaver.INIT; + if (!name) { + name = "download"; + } + if (can_use_save_link) { + object_url = get_URL().createObjectURL(blob); + save_link.href = object_url; + save_link.download = name; + click(save_link); + filesaver.readyState = filesaver.DONE; + dispatch_all(); + revoke(object_url); + return; + } + // Object and web filesystem URLs have a problem saving in Google Chrome when + // viewed in a tab, so I force save with application/octet-stream + // http://code.google.com/p/chromium/issues/detail?id=91158 + // Update: Google errantly closed 91158, I submitted it again: + // https://code.google.com/p/chromium/issues/detail?id=389642 + if (view.chrome && type && type !== force_saveable_type) { + slice = blob.slice || blob.webkitSlice; + blob = slice.call(blob, 0, blob.size, force_saveable_type); + blob_changed = true; + } + // Since I can't be sure that the guessed media type will trigger a download + // in WebKit, I append .download to the filename. + // https://bugs.webkit.org/show_bug.cgi?id=65440 + if (webkit_req_fs && name !== "download") { + name += ".download"; + } + if (type === force_saveable_type || webkit_req_fs) { + target_view = view; + } + if (!req_fs) { + fs_error(); + return; + } + fs_min_size += blob.size; + req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) { + fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) { + var save = function() { + dir.getFile(name, create_if_not_found, abortable(function(file) { + file.createWriter(abortable(function(writer) { + writer.onwriteend = function(event) { + target_view.location.href = file.toURL(); + filesaver.readyState = filesaver.DONE; + dispatch(filesaver, "writeend", event); + revoke(file); + }; + writer.onerror = function() { + var error = writer.error; + if (error.code !== error.ABORT_ERR) { + fs_error(); + } + }; + "writestart progress write abort".split(" ").forEach(function(event) { + writer["on" + event] = filesaver["on" + event]; + }); + writer.write(blob); + filesaver.abort = function() { + writer.abort(); + filesaver.readyState = filesaver.DONE; + }; + filesaver.readyState = filesaver.WRITING; + }), fs_error); + }), fs_error); + }; + dir.getFile(name, {create: false}, abortable(function(file) { + // delete file if it already exists + file.remove(); + save(); + }), abortable(function(ex) { + if (ex.code === ex.NOT_FOUND_ERR) { + save(); + } else { + fs_error(); + } + })); + }), fs_error); + }), fs_error); + } + , FS_proto = FileSaver.prototype + , saveAs = function(blob, name) { + return new FileSaver(blob, name); + } + ; + // IE 10+ (native saveAs) + if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) { + return function(blob, name) { + return navigator.msSaveOrOpenBlob(auto_bom(blob), name); + }; + } + + FS_proto.abort = function() { + var filesaver = this; + filesaver.readyState = filesaver.DONE; + dispatch(filesaver, "abort"); + }; + FS_proto.readyState = FS_proto.INIT = 0; + FS_proto.WRITING = 1; + FS_proto.DONE = 2; + + FS_proto.error = + FS_proto.onwritestart = + FS_proto.onprogress = + FS_proto.onwrite = + FS_proto.onabort = + FS_proto.onerror = + FS_proto.onwriteend = + null; + + return saveAs; +}( + typeof self !== "undefined" && self + || typeof window !== "undefined" && window + || this.content +)); +// `self` is undefined in Firefox for Android content script context +// while `this` is nsIContentFrameMessageManager +// with an attribute `content` that corresponds to the window + +if (typeof module !== "undefined" && module.exports) { + module.exports.saveAs = saveAs; +} else if ((typeof define !== "undefined" && define !== null) && (define.amd != null)) { + define([], function() { + return saveAs; + }); +} \ No newline at end of file diff --git a/turtles/app/lib/angular-local-storage.min.js b/turtles/app/lib/angular-local-storage.min.js new file mode 100644 index 000000000..462dd62bd --- /dev/null +++ b/turtles/app/lib/angular-local-storage.min.js @@ -0,0 +1,7 @@ +/** + * An Angular module that gives you access to the browsers local storage + * @version v0.2.0 - 2015-05-10 + * @link https://github.com/grevory/angular-local-storage + * @author grevory + * @license MIT License, http://www.opensource.org/licenses/MIT + */!function(a,b,c){"use strict";function d(a){return/^-?\d+\.?\d*$/.test(a.replace(/["']/g,""))}var e=b.isDefined,f=b.isUndefined,g=b.isNumber,h=b.isObject,i=b.isArray,j=b.extend,k=b.toJson,l=b.module("LocalStorageModule",[]);l.provider("localStorageService",function(){this.prefix="ls",this.storageType="localStorage",this.cookie={expiry:30,path:"/"},this.notify={setItem:!0,removeItem:!1},this.setPrefix=function(a){return this.prefix=a,this},this.setStorageType=function(a){return this.storageType=a,this},this.setStorageCookie=function(a,b){return this.cookie.expiry=a,this.cookie.path=b,this},this.setStorageCookieDomain=function(a){return this.cookie.domain=a,this},this.setNotify=function(a,b){return this.notify={setItem:a,removeItem:b},this},this.$get=["$rootScope","$window","$document","$parse",function(a,b,c,l){function m(a,b){return"true"===b||"false"===b?"true"===b:b}var n,o=this,p=o.prefix,q=o.cookie,r=o.notify,s=o.storageType;c?c[0]&&(c=c[0]):c=document,"."!==p.substr(-1)&&(p=p?p+".":"");var t=function(a){return p+a},u=function(){try{var c=s in b&&null!==b[s],d=t("__"+Math.round(1e7*Math.random()));return c&&(n=b[s],n.setItem(d,""),n.removeItem(d)),c}catch(e){return s="cookie",a.$broadcast("LocalStorageModule.notification.error",e.message),!1}}(),v=function(b,c){if(f(c)?c=null:(h(c)||i(c)||g(+c||c))&&(c=k(c)),!u||"cookie"===o.storageType)return u||a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),r.setItem&&a.$broadcast("LocalStorageModule.notification.setitem",{key:b,newvalue:c,storageType:"cookie"}),B(b,c);try{n&&n.setItem(t(b),c),r.setItem&&a.$broadcast("LocalStorageModule.notification.setitem",{key:b,newvalue:c,storageType:o.storageType})}catch(d){return a.$broadcast("LocalStorageModule.notification.error",d.message),B(b,c)}return!0},w=function(b){if(!u||"cookie"===o.storageType)return u||a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),C(b);var c=n?n.getItem(t(b)):null;return c&&"null"!==c?"{"===c.charAt(0)||"["===c.charAt(0)||d(c)?JSON.parse(c,m):c:null},x=function(){var b,c;for(b=0;b0||(c.cookie="test").indexOf.call(c.cookie,"test")>-1)}catch(d){return a.$broadcast("LocalStorageModule.notification.error",d.message),!1}}(),B=function(b,d,e){if(f(d))return!1;if((i(d)||h(d))&&(d=k(d)),!A)return a.$broadcast("LocalStorageModule.notification.error","COOKIES_NOT_SUPPORTED"),!1;try{var j="",l=new Date,m="";if(null===d?(l.setTime(l.getTime()+-864e5),j="; expires="+l.toGMTString(),d=""):g(e)&&0!==e?(l.setTime(l.getTime()+24*e*60*60*1e3),j="; expires="+l.toGMTString()):0!==q.expiry&&(l.setTime(l.getTime()+24*q.expiry*60*60*1e3),j="; expires="+l.toGMTString()),b){var n="; path="+q.path;q.domain&&(m="; domain="+q.domain),c.cookie=t(b)+"="+encodeURIComponent(d)+j+n+m}}catch(o){return a.$broadcast("LocalStorageModule.notification.error",o.message),!1}return!0},C=function(b){if(!A)return a.$broadcast("LocalStorageModule.notification.error","COOKIES_NOT_SUPPORTED"),!1;for(var d=c.cookie&&c.cookie.split(";")||[],e=0;e 0) { + $scope.model.columns.push(column); + column = null; + } + if (!$scope.model.selectedLang) { + $scope.model.selectedLang = $scope.items[0]; + $scope.items[0].selected = true; + } + }; + + var openPopup = function () { + if (!$scope.model.opened) { + $scope.$emit('pls.popupOpening', {id: $scope.id}); + $scope.model.opened = true; + $document.on('click', documentClickHandler); + $document.on('keydown', documentKeyHandler); + $scope.$emit('pls.popupOpened', {id: $scope.id}); + } + return false; + }; + + var closePopup = function () { + if ($scope.model.opened) { + $scope.$emit('pls.popupClosing', {id: $scope.id}); + $document.off('click', documentClickHandler); + $document.off('keydown', documentKeyHandler); + $scope.model.opened = false; + $scope.$emit('pls.popupClosed', {id: $scope.id}); + } + return false; + }; + + $scope.onMouseEnterOrLeave = function (mouseEnter) { + if (mouseEnter) { + if (hoverTimeoutPromise) { + $timeout.cancel(hoverTimeoutPromise); + hoverTimeoutPromise = null; + } + openPopup(); + } else { + if (!hoverTimeoutPromise) { + hoverTimeoutPromise = $timeout(function () { + closePopup(); + }, hoverTimeout); + } + } + return false; + }; + + $scope.onClick = function (evt) { + evt.stopPropagation(); + if (!$scope.model.opened) { + openPopup(); + } else { + closePopup(); + } + return false; + }; + + $scope.onLanguageChanged = function (evt, selectedLang) { + evt.stopPropagation(); + closePopup(); + angular.forEach($scope.items, function (item) { + item.selected = false; + }); + selectedLang.selected = true; + $scope.model.selectedLang = selectedLang; + $scope.$emit('pls.onLanguageChanged', { + id: $scope.id, + lang: angular.copy(selectedLang) + }); + return false; + }; + + prepareModel(); + }], + template: function (context, $scope) { + var template = '
    '; + if ($scope.openMode === 'hover') { + template += '{{model.selectedLang.flagTitle}} {{model.selectedLang.name}}' + + '
    '; + } else if ($scope.openMode === 'click') { + template += '{{model.selectedLang.flagTitle}} {{model.selectedLang.name}}' + + '
    '; + } + template += '' + + '' + + '
    ' + + '
    ' + + '
    '; + return template; + } + }; + }]); \ No newline at end of file diff --git a/turtles/app/lib/angular-timer.min.js b/turtles/app/lib/angular-timer.min.js new file mode 100644 index 000000000..f1d9b2af0 --- /dev/null +++ b/turtles/app/lib/angular-timer.min.js @@ -0,0 +1,8 @@ +/** + * angular-timer - v1.3.1 - 2015-03-30 1:00 PM + * https://github.com/siddii/angular-timer + * + * Copyright (c) 2015 Siddique Hameed + * Licensed MIT + */ +var timerModule=angular.module("timer",[]).directive("timer",["$compile",function(a){return{restrict:"EA",replace:!1,scope:{interval:"=interval",startTimeAttr:"=startTime",endTimeAttr:"=endTime",countdownattr:"=countdown",finishCallback:"&finishCallback",autoStart:"&autoStart",language:"@?",maxTimeUnit:"="},controller:["$scope","$element","$attrs","$timeout","I18nService","$interpolate","progressBarService",function(b,c,d,e,f,g,h){function i(){b.timeoutId&&clearTimeout(b.timeoutId)}function j(){var a={};void 0!==d.startTime&&(b.millis=moment().diff(moment(b.startTimeAttr))),a=k.getTimeUnits(b.millis),b.maxTimeUnit&&"day"!==b.maxTimeUnit?"second"===b.maxTimeUnit?(b.seconds=Math.floor(b.millis/1e3),b.minutes=0,b.hours=0,b.days=0,b.months=0,b.years=0):"minute"===b.maxTimeUnit?(b.seconds=Math.floor(b.millis/1e3%60),b.minutes=Math.floor(b.millis/6e4),b.hours=0,b.days=0,b.months=0,b.years=0):"hour"===b.maxTimeUnit?(b.seconds=Math.floor(b.millis/1e3%60),b.minutes=Math.floor(b.millis/6e4%60),b.hours=Math.floor(b.millis/36e5),b.days=0,b.months=0,b.years=0):"month"===b.maxTimeUnit?(b.seconds=Math.floor(b.millis/1e3%60),b.minutes=Math.floor(b.millis/6e4%60),b.hours=Math.floor(b.millis/36e5%24),b.days=Math.floor(b.millis/36e5/24%30),b.months=Math.floor(b.millis/36e5/24/30),b.years=0):"year"===b.maxTimeUnit&&(b.seconds=Math.floor(b.millis/1e3%60),b.minutes=Math.floor(b.millis/6e4%60),b.hours=Math.floor(b.millis/36e5%24),b.days=Math.floor(b.millis/36e5/24%30),b.months=Math.floor(b.millis/36e5/24/30%12),b.years=Math.floor(b.millis/36e5/24/365)):(b.seconds=Math.floor(b.millis/1e3%60),b.minutes=Math.floor(b.millis/6e4%60),b.hours=Math.floor(b.millis/36e5%24),b.days=Math.floor(b.millis/36e5/24),b.months=0,b.years=0),b.secondsS=1===b.seconds?"":"s",b.minutesS=1===b.minutes?"":"s",b.hoursS=1===b.hours?"":"s",b.daysS=1===b.days?"":"s",b.monthsS=1===b.months?"":"s",b.yearsS=1===b.years?"":"s",b.secondUnit=a.seconds,b.minuteUnit=a.minutes,b.hourUnit=a.hours,b.dayUnit=a.days,b.monthUnit=a.months,b.yearUnit=a.years,b.sseconds=b.seconds<10?"0"+b.seconds:b.seconds,b.mminutes=b.minutes<10?"0"+b.minutes:b.minutes,b.hhours=b.hours<10?"0"+b.hours:b.hours,b.ddays=b.days<10?"0"+b.days:b.days,b.mmonths=b.months<10?"0"+b.months:b.months,b.yyears=b.years<10?"0"+b.years:b.years}"function"!=typeof String.prototype.trim&&(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),b.autoStart=d.autoStart||d.autostart,b.language=b.language||"en",b.$watch("language",function(){k.init(b.language)});var k=new f;k.init(b.language),b.displayProgressBar=0,b.displayProgressActive="active",c.append(0===c.html().trim().length?a(""+g.startSymbol()+"millis"+g.endSymbol()+"")(b):a(c.contents())(b)),b.startTime=null,b.endTime=null,b.timeoutId=null,b.countdown=b.countdownattr&&parseInt(b.countdownattr,10)>=0?parseInt(b.countdownattr,10):void 0,b.isRunning=!1,b.$on("timer-start",function(){b.start()}),b.$on("timer-resume",function(){b.resume()}),b.$on("timer-stop",function(){b.stop()}),b.$on("timer-clear",function(){b.clear()}),b.$on("timer-reset",function(){b.reset()}),b.$on("timer-set-countdown",function(a,c){b.countdown=c}),b.$watch("startTimeAttr",function(a,c){a!==c&&b.isRunning&&b.start()}),b.start=c[0].start=function(){b.startTime=b.startTimeAttr?moment(b.startTimeAttr):moment(),b.endTime=b.endTimeAttr?moment(b.endTimeAttr):null,b.countdown||(b.countdown=b.countdownattr&&parseInt(b.countdownattr,10)>0?parseInt(b.countdownattr,10):void 0),i(),l(),b.isRunning=!0},b.resume=c[0].resume=function(){i(),b.countdownattr&&(b.countdown+=1),b.startTime=moment().diff(moment(b.stoppedTime).diff(moment(b.startTime))),l(),b.isRunning=!0},b.stop=b.pause=c[0].stop=c[0].pause=function(){var a=b.timeoutId;b.clear(),b.$emit("timer-stopped",{timeoutId:a,millis:b.millis,seconds:b.seconds,minutes:b.minutes,hours:b.hours,days:b.days})},b.clear=c[0].clear=function(){b.stoppedTime=moment(),i(),b.timeoutId=null,b.isRunning=!1},b.reset=c[0].reset=function(){b.startTime=b.startTimeAttr?moment(b.startTimeAttr):moment(),b.endTime=b.endTimeAttr?moment(b.endTimeAttr):null,b.countdown=b.countdownattr&&parseInt(b.countdownattr,10)>0?parseInt(b.countdownattr,10):void 0,i(),l(),b.isRunning=!1,b.clear()},c.bind("$destroy",function(){i(),b.isRunning=!1}),b.countdownattr?(b.millis=1e3*b.countdownattr,b.addCDSeconds=c[0].addCDSeconds=function(a){b.countdown+=a,b.$digest(),b.isRunning||b.start()},b.$on("timer-add-cd-seconds",function(a,c){e(function(){b.addCDSeconds(c)})}),b.$on("timer-set-countdown-seconds",function(a,c){b.isRunning||b.clear(),b.countdown=c,b.millis=1e3*c,j()})):b.millis=0,j();var l=function m(){var a=null;b.millis=moment().diff(b.startTime);var c=b.millis%1e3;return b.endTimeAttr&&(a=b.endTimeAttr,b.millis=moment(b.endTime).diff(moment()),c=b.interval-b.millis%1e3),b.countdownattr&&(a=b.countdownattr,b.millis=1e3*b.countdown),b.millis<0?(b.stop(),b.millis=0,j(),void(b.finishCallback&&b.$eval(b.finishCallback))):(j(),b.timeoutId=setTimeout(function(){m(),b.$digest()},b.interval-c),b.$emit("timer-tick",{timeoutId:b.timeoutId,millis:b.millis}),b.countdown>0?b.countdown--:b.countdown<=0&&(b.stop(),b.finishCallback&&b.$eval(b.finishCallback)),void(null!==a&&(b.progressBar=h.calculateProgressBar(b.startTime,b.millis,b.endTime,b.countdownattr),100===b.progressBar&&(b.displayProgressActive=""))))};(void 0===b.autoStart||b.autoStart===!0)&&b.start()}]}}]);"undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports=timerModule);var app=angular.module("timer");app.factory("I18nService",function(){var a=function(){};return a.prototype.language="en",a.prototype.timeHumanizer={},a.prototype.init=function(a){this.language=a,moment.locale(this.language),this.timeHumanizer=humanizeDuration.humanizer({language:this.language,halfUnit:!1})},a.prototype.getTimeUnits=function(a){var b=1e3*Math.round(a/1e3),c={};return"undefined"!=typeof this.timeHumanizer?c={millis:this.timeHumanizer(b,{units:["milliseconds"]}),seconds:this.timeHumanizer(b,{units:["seconds"]}),minutes:this.timeHumanizer(b,{units:["minutes","seconds"]}),hours:this.timeHumanizer(b,{units:["hours","minutes","seconds"]}),days:this.timeHumanizer(b,{units:["days","hours","minutes","seconds"]}),months:this.timeHumanizer(b,{units:["months","days","hours","minutes","seconds"]}),years:this.timeHumanizer(b,{units:["years","months","days","hours","minutes","seconds"]})}:console.error('i18nService has not been initialized. You must call i18nService.init("en") for example'),c},a});var app=angular.module("timer");app.factory("progressBarService",function(){var a=function(){};return a.prototype.calculateProgressBar=function(a,b,c,d){var e,f,g=0;return b/=1e3,null!==c?(e=moment(c),f=e.diff(a,"seconds"),g=100*b/f):g=100*b/d,g=100-g,g=Math.round(10*g)/10,g>100&&(g=100),g},new a}); \ No newline at end of file diff --git a/turtles/app/lib/angular-translate.min.js b/turtles/app/lib/angular-translate.min.js new file mode 100644 index 000000000..f1104f5e2 --- /dev/null +++ b/turtles/app/lib/angular-translate.min.js @@ -0,0 +1,6 @@ +/*! + * angular-translate - v2.7.0 - 2015-05-02 + * http://github.com/angular-translate/angular-translate + * Copyright (c) 2015 ; Licensed MIT + */ +!function(a,b){"function"==typeof define&&define.amd?define([],function(){return b()}):"object"==typeof exports?module.exports=b():b()}(this,function(){function a(a){"use strict";var b=a.storageKey(),c=a.storage(),d=function(){var d=a.preferredLanguage();angular.isString(d)?a.use(d):c.put(b,a.use())};d.displayName="fallbackFromIncorrectStorageValue",c?c.get(b)?a.use(c.get(b))["catch"](d):d():angular.isString(a.preferredLanguage())&&a.use(a.preferredLanguage())}function b(){"use strict";var a,b,c=null,d=!1,e=!1;b={sanitize:function(a,b){return"text"===b&&(a=g(a)),a},escape:function(a,b){return"text"===b&&(a=f(a)),a},sanitizeParameters:function(a,b){return"params"===b&&(a=h(a,g)),a},escapeParameters:function(a,b){return"params"===b&&(a=h(a,f)),a}},b.escaped=b.escapeParameters,this.addStrategy=function(a,c){return b[a]=c,this},this.removeStrategy=function(a){return delete b[a],this},this.useStrategy=function(a){return d=!0,c=a,this},this.$get=["$injector","$log",function(f,g){var h=function(a,c,d){return angular.forEach(d,function(d){if(angular.isFunction(d))a=d(a,c);else{if(!angular.isFunction(b[d]))throw new Error("pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: '"+d+"'");a=b[d](a,c)}}),a},i=function(){d||e||(g.warn("pascalprecht.translate.$translateSanitization: No sanitization strategy has been configured. This can have serious security implications. See http://angular-translate.github.io/docs/#/guide/19_security for details."),e=!0)};return f.has("$sanitize")&&(a=f.get("$sanitize")),{useStrategy:function(a){return function(b){a.useStrategy(b)}}(this),sanitize:function(a,b,d){if(c||i(),arguments.length<3&&(d=c),!d)return a;var e=angular.isArray(d)?d:[d];return h(a,b,e)}}}];var f=function(a){return angular.element("
    ").text(a).html()},g=function(b){if(!a)throw new Error("pascalprecht.translate.$translateSanitization: Error cannot find $sanitize service. Either include the ngSanitize module (https://docs.angularjs.org/api/ngSanitize) or use a sanitization strategy which does not depend on $sanitize, such as 'escape'.");return a(b)},h=function(a,b){if(angular.isObject(a)){var c=angular.isArray(a)?[]:{};return angular.forEach(a,function(a,d){c[d]=h(a,b)}),c}return angular.isNumber(a)?a:b(a)}}function c(a,b,c,d){"use strict";var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t={},u=[],v=a,w=[],x="translate-cloak",y=!1,z=".",A=0,B=!0,C="default",D={"default":function(a){return(a||"").split("-").join("_")},java:function(a){var b=(a||"").split("-").join("_"),c=b.split("_");return c.length>1?c[0].toLowerCase()+"_"+c[1].toUpperCase():b},bcp47:function(a){var b=(a||"").split("_").join("-"),c=b.split("-");return c.length>1?c[0].toLowerCase()+"-"+c[1].toUpperCase():b}},E="2.7.0",F=function(){if(angular.isFunction(d.getLocale))return d.getLocale();var a,c,e=b.$get().navigator,f=["language","browserLanguage","systemLanguage","userLanguage"];if(angular.isArray(e.languages))for(a=0;ac;c++)if(a[c]===b)return c;return-1},I=function(){return this.replace(/^\s+|\s+$/g,"")},J=function(a){for(var b=[],c=angular.lowercase(a),d=0,e=u.length;e>d;d++)b.push(angular.lowercase(u[d]));if(H(b,c)>-1)return a;if(f){var g;for(var h in f){var i=!1,j=Object.prototype.hasOwnProperty.call(f,h)&&angular.lowercase(h)===angular.lowercase(a);if("*"===h.slice(-1)&&(i=h.slice(0,-1)===a.slice(0,h.length-1)),(j||i)&&(g=f[h],H(b,angular.lowercase(g))>-1))return g}}if(a){var k=a.split("_");if(k.length>1&&H(b,angular.lowercase(k[0]))>-1)return k[0]}return a},K=function(a,b){if(!a&&!b)return t;if(a&&!b){if(angular.isString(a))return t[a]}else angular.isObject(t[a])||(t[a]={}),angular.extend(t[a],L(b));return this};this.translations=K,this.cloakClassName=function(a){return a?(x=a,this):x};var L=function(a,b,c,d){var e,f,g,h;b||(b=[]),c||(c={});for(e in a)Object.prototype.hasOwnProperty.call(a,e)&&(h=a[e],angular.isObject(h)?L(h,b.concat(e),c,e):(f=b.length?""+b.join(z)+z+e:e,b.length&&e===d&&(g=""+b.join(z),c[g]="@:"+f),c[f]=h));return c};L.displayName="flatObject",this.addInterpolation=function(a){return w.push(a),this},this.useMessageFormatInterpolation=function(){return this.useInterpolation("$translateMessageFormatInterpolation")},this.useInterpolation=function(a){return n=a,this},this.useSanitizeValueStrategy=function(a){return c.useStrategy(a),this},this.preferredLanguage=function(a){return M(a),this};var M=function(a){return a&&(e=a),e};this.translationNotFoundIndicator=function(a){return this.translationNotFoundIndicatorLeft(a),this.translationNotFoundIndicatorRight(a),this},this.translationNotFoundIndicatorLeft=function(a){return a?(q=a,this):q},this.translationNotFoundIndicatorRight=function(a){return a?(r=a,this):r},this.fallbackLanguage=function(a){return N(a),this};var N=function(a){return a?(angular.isString(a)?(h=!0,g=[a]):angular.isArray(a)&&(h=!1,g=a),angular.isString(e)&&H(g,e)<0&&g.push(e),this):h?g[0]:g};this.use=function(a){if(a){if(!t[a]&&!o)throw new Error("$translateProvider couldn't find translationTable for langKey: '"+a+"'");return i=a,this}return i};var O=function(a){return a?void(v=a):l?l+v:v};this.storageKey=O,this.useUrlLoader=function(a,b){return this.useLoader("$translateUrlLoader",angular.extend({url:a},b))},this.useStaticFilesLoader=function(a){return this.useLoader("$translateStaticFilesLoader",a)},this.useLoader=function(a,b){return o=a,p=b||{},this},this.useLocalStorage=function(){return this.useStorage("$translateLocalStorage")},this.useCookieStorage=function(){return this.useStorage("$translateCookieStorage")},this.useStorage=function(a){return k=a,this},this.storagePrefix=function(a){return a?(l=a,this):a},this.useMissingTranslationHandlerLog=function(){return this.useMissingTranslationHandler("$translateMissingTranslationHandlerLog")},this.useMissingTranslationHandler=function(a){return m=a,this},this.usePostCompiling=function(a){return y=!!a,this},this.uniformLanguageTag=function(a){return a?angular.isString(a)&&(a={standard:a}):a={},C=a.standard,this},this.determinePreferredLanguage=function(a){var b=a&&angular.isFunction(a)?a():G();return e=u.length?J(b):b,this},this.registerAvailableLanguageKeys=function(a,b){return a?(u=a,b&&(f=b),this):u},this.useLoaderCache=function(a){return a===!1?s=void 0:a===!0?s=!0:"undefined"==typeof a?s="$translationCache":a&&(s=a),this},this.directivePriority=function(a){return void 0===a?A:(A=a,this)},this.statefulFilter=function(a){return void 0===a?B:(B=a,this)},this.$get=["$log","$injector","$rootScope","$q",function(a,b,c,d){var f,l,u,z=b.get(n||"$translateDefaultInterpolation"),C=!1,D={},F={},G=function(a,b,c,h){if(angular.isArray(a)){var j=function(a){for(var e={},f=[],g=function(a){var f=d.defer(),g=function(b){e[a]=b,f.resolve([a,b])};return G(a,b,c,h).then(g,g),f.promise},i=0,j=a.length;j>i;i++)f.push(g(a[i]));return d.all(f).then(function(){return e})};return j(a)}var m=d.defer();a&&(a=I.apply(a));var n=function(){var a=e?F[e]:F[i];if(l=0,k&&!a){var b=f.get(v);if(a=F[b],g&&g.length){var c=H(g,b);l=0===c?1:0,H(g,e)<0&&g.push(e)}}return a}();if(n){var o=function(){_(a,b,c,h).then(m.resolve,m.reject)};o.displayName="promiseResolved",n["finally"](o,m.reject)}else _(a,b,c,h).then(m.resolve,m.reject);return m.promise},P=function(a){return q&&(a=[q,a].join(" ")),r&&(a=[a,r].join(" ")),a},Q=function(a){i=a,c.$emit("$translateChangeSuccess",{language:a}),k&&f.put(G.storageKey(),i),z.setLocale(i);var b=function(a,b){D[b].setLocale(i)};b.displayName="eachInterpolatorLocaleSetter",angular.forEach(D,b),c.$emit("$translateChangeEnd",{language:a})},R=function(a){if(!a)throw"No language key specified for loading.";var e=d.defer();c.$emit("$translateLoadingStart",{language:a}),C=!0;var f=s;"string"==typeof f&&(f=b.get(f));var g=angular.extend({},p,{key:a,$http:angular.extend({},{cache:f},p.$http)}),h=function(b){var d={};c.$emit("$translateLoadingSuccess",{language:a}),angular.isArray(b)?angular.forEach(b,function(a){angular.extend(d,L(a))}):angular.extend(d,L(b)),C=!1,e.resolve({key:a,table:d}),c.$emit("$translateLoadingEnd",{language:a})};h.displayName="onLoaderSuccess";var i=function(a){c.$emit("$translateLoadingError",{language:a}),e.reject(a),c.$emit("$translateLoadingEnd",{language:a})};return i.displayName="onLoaderError",b.get(o)(g).then(h,i),e.promise};if(k&&(f=b.get(k),!f.get||!f.put))throw new Error("Couldn't use storage '"+k+"', missing get() or put() method!");if(w.length){var S=function(a){var c=b.get(a);c.setLocale(e||i),D[c.getInterpolationIdentifier()]=c};S.displayName="interpolationFactoryAdder",angular.forEach(w,S)}var T=function(a){var b=d.defer();if(Object.prototype.hasOwnProperty.call(t,a))b.resolve(t[a]);else if(F[a]){var c=function(a){K(a.key,a.table),b.resolve(a.table)};c.displayName="translationTableResolver",F[a].then(c,b.reject)}else b.reject();return b.promise},U=function(a,b,c,e){var f=d.defer(),g=function(d){if(Object.prototype.hasOwnProperty.call(d,b)){e.setLocale(a);var g=d[b];"@:"===g.substr(0,2)?U(a,g.substr(2),c,e).then(f.resolve,f.reject):f.resolve(e.interpolate(d[b],c)),e.setLocale(i)}else f.reject()};return g.displayName="fallbackTranslationResolver",T(a).then(g,f.reject),f.promise},V=function(a,b,c,d){var e,f=t[a];if(f&&Object.prototype.hasOwnProperty.call(f,b)){if(d.setLocale(a),e=d.interpolate(f[b],c),"@:"===e.substr(0,2))return V(a,e.substr(2),c,d);d.setLocale(i)}return e},W=function(a,c){if(m){var d=b.get(m)(a,i,c);return void 0!==d?d:a}return a},X=function(a,b,c,e,f){var h=d.defer();if(a0?u:l,a,b,c,d)},$=function(a,b,c){return Y(u>0?u:l,a,b,c)},_=function(a,b,c,e){var f=d.defer(),h=i?t[i]:t,j=c?D[c]:z;if(h&&Object.prototype.hasOwnProperty.call(h,a)){var k=h[a];"@:"===k.substr(0,2)?G(k.substr(2),b,c,e).then(f.resolve,f.reject):f.resolve(j.interpolate(k,b))}else{var l;m&&!C&&(l=W(a,b)),i&&g&&g.length?Z(a,b,j,e).then(function(a){f.resolve(a)},function(a){f.reject(P(a))}):m&&!C&&l?f.resolve(e?e:l):e?f.resolve(e):f.reject(P(a))}return f.promise},ab=function(a,b,c){var d,e=i?t[i]:t,f=z;if(D&&Object.prototype.hasOwnProperty.call(D,c)&&(f=D[c]),e&&Object.prototype.hasOwnProperty.call(e,a)){var h=e[a];d="@:"===h.substr(0,2)?ab(h.substr(2),b,c):f.interpolate(h,b)}else{var j;m&&!C&&(j=W(a,b)),i&&g&&g.length?(l=0,d=$(a,b,f)):d=m&&!C&&j?j:P(a)}return d},bb=function(a){j===a&&(j=void 0),F[a]=void 0};if(G.preferredLanguage=function(a){return a&&M(a),e},G.cloakClassName=function(){return x},G.fallbackLanguage=function(a){if(void 0!==a&&null!==a){if(N(a),o&&g&&g.length)for(var b=0,c=g.length;c>b;b++)F[g[b]]||(F[g[b]]=R(g[b]));G.use(G.use())}return h?g[0]:g},G.useFallbackLanguage=function(a){if(void 0!==a&&null!==a)if(a){var b=H(g,a);b>-1&&(u=b)}else u=0},G.proposedLanguage=function(){return j},G.storage=function(){return f},G.use=function(a){if(!a)return i;var b=d.defer();c.$emit("$translateChangeStart",{language:a});var e=J(a);return e&&(a=e),t[a]||!o||F[a]?j===a&&F[a]?F[a].then(function(a){return b.resolve(a.key),a},function(a){return b.reject(a),d.reject(a)}):(b.resolve(a),Q(a)):(j=a,F[a]=R(a).then(function(a){return K(a.key,a.table),b.resolve(a.key),Q(a.key),a},function(a){return c.$emit("$translateChangeError",{language:a}),b.reject(a),c.$emit("$translateChangeEnd",{language:a}),d.reject(a)}),F[a]["finally"](function(){bb(a)})),b.promise},G.storageKey=function(){return O()},G.isPostCompilingEnabled=function(){return y},G.refresh=function(a){function b(){f.resolve(),c.$emit("$translateRefreshEnd",{language:a})}function e(){f.reject(),c.$emit("$translateRefreshEnd",{language:a})}if(!o)throw new Error("Couldn't refresh translation table, no loader registered!");var f=d.defer();if(c.$emit("$translateRefreshStart",{language:a}),a)if(t[a]){var h=function(c){K(c.key,c.table),a===i&&Q(i),b()};h.displayName="refreshPostProcessor",R(a).then(h,e)}else e();else{var j=[],k={};if(g&&g.length)for(var l=0,m=g.length;m>l;l++)j.push(R(g[l])),k[g[l]]=!0;i&&!k[i]&&j.push(R(i));var n=function(a){t={},angular.forEach(a,function(a){K(a.key,a.table)}),i&&Q(i),b()};n.displayName="refreshPostProcessor",d.all(j).then(n)}return f.promise},G.instant=function(a,b,c){if(null===a||angular.isUndefined(a))return a;if(angular.isArray(a)){for(var d={},f=0,h=a.length;h>f;f++)d[a[f]]=G.instant(a[f],b,c);return d}if(angular.isString(a)&&a.length<1)return a;a&&(a=I.apply(a));var j,k=[];e&&k.push(e),i&&k.push(i),g&&g.length&&(k=k.concat(g));for(var l=0,n=k.length;n>l;l++){var o=k[l];if(t[o]&&("undefined"!=typeof t[o][a]?j=ab(a,b,c):(q||r)&&(j=P(a))),"undefined"!=typeof j)break}return j||""===j||(j=z.interpolate(a,b),m&&!C&&(j=W(a,b))),j},G.versionInfo=function(){return E},G.loaderCache=function(){return s},G.directivePriority=function(){return A},G.statefulFilter=function(){return B},o&&(angular.equals(t,{})&&G.use(G.use()),g&&g.length))for(var cb=function(a){return K(a.key,a.table),c.$emit("$translateChangeEnd",{language:a.key}),a},db=0,eb=g.length;eb>db;db++){var fb=g[db];t[fb]||(F[fb]=R(fb).then(cb))}return G}]}function d(a,b){"use strict";var c,d={},e="default";return d.setLocale=function(a){c=a},d.getInterpolationIdentifier=function(){return e},d.useSanitizeValueStrategy=function(a){return b.useStrategy(a),this},d.interpolate=function(c,d){d=d||{},d=b.sanitize(d,"params");var e=a(c)(d);return e=b.sanitize(e,"text")},d}function e(a,b,c,d,e,f){"use strict";var g=function(){return this.replace(/^\s+|\s+$/g,"")};return{restrict:"AE",scope:!0,priority:a.directivePriority(),compile:function(b,h){var i=h.translateValues?h.translateValues:void 0,j=h.translateInterpolation?h.translateInterpolation:void 0,k=b[0].outerHTML.match(/translate-value-+/i),l="^(.*)("+c.startSymbol()+".*"+c.endSymbol()+")(.*)",m="^(.*)"+c.startSymbol()+"(.*)"+c.endSymbol()+"(.*)";return function(b,n,o){b.interpolateParams={},b.preText="",b.postText="";var p={},q=function(a,c,d){if(c.translateValues&&angular.extend(a,e(c.translateValues)(b.$parent)),k)for(var f in d)if(Object.prototype.hasOwnProperty.call(c,f)&&"translateValue"===f.substr(0,14)&&"translateValues"!==f){var g=angular.lowercase(f.substr(14,1))+f.substr(15);a[g]=d[f]}},r=function(a){if(angular.isFunction(r._unwatchOld)&&(r._unwatchOld(),r._unwatchOld=void 0),angular.equals(a,"")||!angular.isDefined(a)){var d=g.apply(n.text()).match(l);if(angular.isArray(d)){b.preText=d[1],b.postText=d[3],p.translate=c(d[2])(b.$parent);var e=n.text().match(m);angular.isArray(e)&&e[2]&&e[2].length&&(r._unwatchOld=b.$watch(e[2],function(a){p.translate=a,x()}))}else p.translate=n.text().replace(/^\s+|\s+$/g,"")}else p.translate=a;x()},s=function(a){o.$observe(a,function(b){p[a]=b,x()})};q(b.interpolateParams,o,h);var t=!0;o.$observe("translate",function(a){"undefined"==typeof a?r(""):""===a&&t||(p.translate=a,x()),t=!1});for(var u in o)o.hasOwnProperty(u)&&"translateAttr"===u.substr(0,13)&&s(u);if(o.$observe("translateDefault",function(a){b.defaultText=a}),i&&o.$observe("translateValues",function(a){a&&b.$parent.$watch(function(){angular.extend(b.interpolateParams,e(a)(b.$parent))})}),k){var v=function(a){o.$observe(a,function(c){var d=angular.lowercase(a.substr(14,1))+a.substr(15);b.interpolateParams[d]=c})};for(var w in o)Object.prototype.hasOwnProperty.call(o,w)&&"translateValue"===w.substr(0,14)&&"translateValues"!==w&&v(w)}var x=function(){for(var a in p)p.hasOwnProperty(a)&&void 0!==p[a]&&y(a,p[a],b,b.interpolateParams,b.defaultText)},y=function(b,c,d,e,f){c?a(c,e,j,f).then(function(a){z(a,d,!0,b)},function(a){z(a,d,!1,b)}):z(c,d,!1,b)},z=function(b,c,e,f){if("translate"===f){e||"undefined"==typeof c.defaultText||(b=c.defaultText),n.html(c.preText+b+c.postText);var g=a.isPostCompilingEnabled(),i="undefined"!=typeof h.translateCompile,j=i&&"false"!==h.translateCompile;(g&&!i||j)&&d(n.contents())(c)}else{e||"undefined"==typeof c.defaultText||(b=c.defaultText);var k=o.$attr[f];"data-"===k.substr(0,5)&&(k=k.substr(5)),k=k.substr(15),n.attr(k,b)}};(i||k||o.translateDefault)&&b.$watch("interpolateParams",x,!0);var A=f.$on("$translateChangeSuccess",x);n.text().length&&r(o.translate?o.translate:""),x(),b.$on("$destroy",A)}}}}function f(a,b){"use strict";return{compile:function(c){var d=function(){c.addClass(b.cloakClassName())},e=function(){c.removeClass(b.cloakClassName())},f=a.$on("$translateChangeEnd",function(){e(),f(),f=null});return d(),function(a,c,f){f.translateCloak&&f.translateCloak.length&&f.$observe("translateCloak",function(a){b(a).then(e,d)})}}}}function g(a,b){"use strict";var c=function(c,d,e){return angular.isObject(d)||(d=a(d)(this)),b.instant(c,d,e)};return b.statefulFilter()&&(c.$stateful=!0),c}return angular.module("pascalprecht.translate",["ng"]).run(a),a.$inject=["$translate"],a.displayName="runTranslate",angular.module("pascalprecht.translate").provider("$translateSanitization",b),angular.module("pascalprecht.translate").constant("pascalprechtTranslateOverrider",{}).provider("$translate",c),c.$inject=["$STORAGE_KEY","$windowProvider","$translateSanitizationProvider","pascalprechtTranslateOverrider"],c.displayName="displayName",angular.module("pascalprecht.translate").factory("$translateDefaultInterpolation",d),d.$inject=["$interpolate","$translateSanitization"],d.displayName="$translateDefaultInterpolation",angular.module("pascalprecht.translate").constant("$STORAGE_KEY","NG_TRANSLATE_LANG_KEY"),angular.module("pascalprecht.translate").directive("translate",e),e.$inject=["$translate","$q","$interpolate","$compile","$parse","$rootScope"],e.displayName="translateDirective",angular.module("pascalprecht.translate").directive("translateCloak",f),f.$inject=["$rootScope","$translate"],f.displayName="translateCloakDirective",angular.module("pascalprecht.translate").filter("translate",g),g.$inject=["$parse","$translate"],g.displayName="translateFilterFactory","pascalprecht.translate"}); \ No newline at end of file diff --git a/turtles/app/lib/bower_components/angular-animate/.bower.json b/turtles/app/lib/bower_components/angular-animate/.bower.json new file mode 100644 index 000000000..49917407c --- /dev/null +++ b/turtles/app/lib/bower_components/angular-animate/.bower.json @@ -0,0 +1,20 @@ +{ + "name": "angular-animate", + "version": "1.4.0", + "main": "./angular-animate.js", + "ignore": [], + "dependencies": { + "angular": "1.4.0" + }, + "homepage": "https://github.com/angular/bower-angular-animate", + "_release": "1.4.0", + "_resolution": { + "type": "version", + "tag": "v1.4.0", + "commit": "708368e2865fcbee7c6f0f6107aa4eb9c6a9b780" + }, + "_source": "git://github.com/angular/bower-angular-animate.git", + "_target": "~1.4.0", + "_originalSource": "angular-animate", + "_direct": true +} \ No newline at end of file diff --git a/turtles/app/lib/bower_components/angular-animate/README.md b/turtles/app/lib/bower_components/angular-animate/README.md new file mode 100644 index 000000000..8313da67c --- /dev/null +++ b/turtles/app/lib/bower_components/angular-animate/README.md @@ -0,0 +1,68 @@ +# packaged angular-animate + +This repo is for distribution on `npm` and `bower`. The source for this module is in the +[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngAnimate). +Please file issues and pull requests against that repo. + +## Install + +You can install this package either with `npm` or with `bower`. + +### npm + +```shell +npm install angular-animate +``` + +Then add `ngAnimate` as a dependency for your app: + +```javascript +angular.module('myApp', [require('angular-animate')]); +``` + +### bower + +```shell +bower install angular-animate +``` + +Then add a ` +``` + +Then add `ngAnimate` as a dependency for your app: + +```javascript +angular.module('myApp', ['ngAnimate']); +``` + +## Documentation + +Documentation is available on the +[AngularJS docs site](http://docs.angularjs.org/api/ngAnimate). + +## License + +The MIT License + +Copyright (c) 2010-2015 Google, Inc. http://angularjs.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/turtles/app/lib/bower_components/angular-animate/angular-animate.js b/turtles/app/lib/bower_components/angular-animate/angular-animate.js new file mode 100644 index 000000000..42b03e0b5 --- /dev/null +++ b/turtles/app/lib/bower_components/angular-animate/angular-animate.js @@ -0,0 +1,3708 @@ +/** + * @license AngularJS v1.4.0 + * (c) 2010-2015 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular, undefined) {'use strict'; + +/* jshint ignore:start */ +var noop = angular.noop; +var extend = angular.extend; +var jqLite = angular.element; +var forEach = angular.forEach; +var isArray = angular.isArray; +var isString = angular.isString; +var isObject = angular.isObject; +var isUndefined = angular.isUndefined; +var isDefined = angular.isDefined; +var isFunction = angular.isFunction; +var isElement = angular.isElement; + +var ELEMENT_NODE = 1; +var COMMENT_NODE = 8; + +var NG_ANIMATE_CLASSNAME = 'ng-animate'; +var NG_ANIMATE_CHILDREN_DATA = '$$ngAnimateChildren'; + +var isPromiseLike = function(p) { + return p && p.then ? true : false; +} + +function assertArg(arg, name, reason) { + if (!arg) { + throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required")); + } + return arg; +} + +function mergeClasses(a,b) { + if (!a && !b) return ''; + if (!a) return b; + if (!b) return a; + if (isArray(a)) a = a.join(' '); + if (isArray(b)) b = b.join(' '); + return a + ' ' + b; +} + +function packageStyles(options) { + var styles = {}; + if (options && (options.to || options.from)) { + styles.to = options.to; + styles.from = options.from; + } + return styles; +} + +function pendClasses(classes, fix, isPrefix) { + var className = ''; + classes = isArray(classes) + ? classes + : classes && isString(classes) && classes.length + ? classes.split(/\s+/) + : []; + forEach(classes, function(klass, i) { + if (klass && klass.length > 0) { + className += (i > 0) ? ' ' : ''; + className += isPrefix ? fix + klass + : klass + fix; + } + }); + return className; +} + +function removeFromArray(arr, val) { + var index = arr.indexOf(val); + if (val >= 0) { + arr.splice(index, 1); + } +} + +function stripCommentsFromElement(element) { + if (element instanceof jqLite) { + switch (element.length) { + case 0: + return []; + break; + + case 1: + // there is no point of stripping anything if the element + // is the only element within the jqLite wrapper. + // (it's important that we retain the element instance.) + if (element[0].nodeType === ELEMENT_NODE) { + return element; + } + break; + + default: + return jqLite(extractElementNode(element)); + break; + } + } + + if (element.nodeType === ELEMENT_NODE) { + return jqLite(element); + } +} + +function extractElementNode(element) { + if (!element[0]) return element; + for (var i = 0; i < element.length; i++) { + var elm = element[i]; + if (elm.nodeType == ELEMENT_NODE) { + return elm; + } + } +} + +function $$addClass($$jqLite, element, className) { + forEach(element, function(elm) { + $$jqLite.addClass(elm, className); + }); +} + +function $$removeClass($$jqLite, element, className) { + forEach(element, function(elm) { + $$jqLite.removeClass(elm, className); + }); +} + +function applyAnimationClassesFactory($$jqLite) { + return function(element, options) { + if (options.addClass) { + $$addClass($$jqLite, element, options.addClass); + options.addClass = null; + } + if (options.removeClass) { + $$removeClass($$jqLite, element, options.removeClass); + options.removeClass = null; + } + } +} + +function prepareAnimationOptions(options) { + options = options || {}; + if (!options.$$prepared) { + var domOperation = options.domOperation || noop; + options.domOperation = function() { + options.$$domOperationFired = true; + domOperation(); + domOperation = noop; + }; + options.$$prepared = true; + } + return options; +} + +function applyAnimationStyles(element, options) { + applyAnimationFromStyles(element, options); + applyAnimationToStyles(element, options); +} + +function applyAnimationFromStyles(element, options) { + if (options.from) { + element.css(options.from); + options.from = null; + } +} + +function applyAnimationToStyles(element, options) { + if (options.to) { + element.css(options.to); + options.to = null; + } +} + +function mergeAnimationOptions(element, target, newOptions) { + var toAdd = (target.addClass || '') + ' ' + (newOptions.addClass || ''); + var toRemove = (target.removeClass || '') + ' ' + (newOptions.removeClass || ''); + var classes = resolveElementClasses(element.attr('class'), toAdd, toRemove); + + extend(target, newOptions); + + if (classes.addClass) { + target.addClass = classes.addClass; + } else { + target.addClass = null; + } + + if (classes.removeClass) { + target.removeClass = classes.removeClass; + } else { + target.removeClass = null; + } + + return target; +} + +function resolveElementClasses(existing, toAdd, toRemove) { + var ADD_CLASS = 1; + var REMOVE_CLASS = -1; + + var flags = {}; + existing = splitClassesToLookup(existing); + + toAdd = splitClassesToLookup(toAdd); + forEach(toAdd, function(value, key) { + flags[key] = ADD_CLASS; + }); + + toRemove = splitClassesToLookup(toRemove); + forEach(toRemove, function(value, key) { + flags[key] = flags[key] === ADD_CLASS ? null : REMOVE_CLASS; + }); + + var classes = { + addClass: '', + removeClass: '' + }; + + forEach(flags, function(val, klass) { + var prop, allow; + if (val === ADD_CLASS) { + prop = 'addClass'; + allow = !existing[klass]; + } else if (val === REMOVE_CLASS) { + prop = 'removeClass'; + allow = existing[klass]; + } + if (allow) { + if (classes[prop].length) { + classes[prop] += ' '; + } + classes[prop] += klass; + } + }); + + function splitClassesToLookup(classes) { + if (isString(classes)) { + classes = classes.split(' '); + } + + var obj = {}; + forEach(classes, function(klass) { + // sometimes the split leaves empty string values + // incase extra spaces were applied to the options + if (klass.length) { + obj[klass] = true; + } + }); + return obj; + } + + return classes; +} + +function getDomNode(element) { + return (element instanceof angular.element) ? element[0] : element; +} + +var $$rAFSchedulerFactory = ['$$rAF', function($$rAF) { + var tickQueue = []; + var cancelFn; + + function scheduler(tasks) { + // we make a copy since RAFScheduler mutates the state + // of the passed in array variable and this would be difficult + // to track down on the outside code + tickQueue.push([].concat(tasks)); + nextTick(); + } + + /* waitUntilQuiet does two things: + * 1. It will run the FINAL `fn` value only when an uncancelled RAF has passed through + * 2. It will delay the next wave of tasks from running until the quiet `fn` has run. + * + * The motivation here is that animation code can request more time from the scheduler + * before the next wave runs. This allows for certain DOM properties such as classes to + * be resolved in time for the next animation to run. + */ + scheduler.waitUntilQuiet = function(fn) { + if (cancelFn) cancelFn(); + + cancelFn = $$rAF(function() { + cancelFn = null; + fn(); + nextTick(); + }); + }; + + return scheduler; + + function nextTick() { + if (!tickQueue.length) return; + + var updatedQueue = []; + for (var i = 0; i < tickQueue.length; i++) { + var innerQueue = tickQueue[i]; + runNextTask(innerQueue); + if (innerQueue.length) { + updatedQueue.push(innerQueue); + } + } + tickQueue = updatedQueue; + + if (!cancelFn) { + $$rAF(function() { + if (!cancelFn) nextTick(); + }); + } + } + + function runNextTask(tasks) { + var nextTask = tasks.shift(); + nextTask(); + } +}]; + +var $$AnimateChildrenDirective = [function() { + return function(scope, element, attrs) { + var val = attrs.ngAnimateChildren; + if (angular.isString(val) && val.length === 0) { //empty attribute + element.data(NG_ANIMATE_CHILDREN_DATA, true); + } else { + attrs.$observe('ngAnimateChildren', function(value) { + value = value === 'on' || value === 'true'; + element.data(NG_ANIMATE_CHILDREN_DATA, value); + }); + } + }; +}]; + +/** + * @ngdoc service + * @name $animateCss + * @kind object + * + * @description + * The `$animateCss` service is a useful utility to trigger customized CSS-based transitions/keyframes + * from a JavaScript-based animation or directly from a directive. The purpose of `$animateCss` is NOT + * to side-step how `$animate` and ngAnimate work, but the goal is to allow pre-existing animations or + * directives to create more complex animations that can be purely driven using CSS code. + * + * Note that only browsers that support CSS transitions and/or keyframe animations are capable of + * rendering animations triggered via `$animateCss` (bad news for IE9 and lower). + * + * ## Usage + * Once again, `$animateCss` is designed to be used inside of a registered JavaScript animation that + * is powered by ngAnimate. It is possible to use `$animateCss` directly inside of a directive, however, + * any automatic control over cancelling animations and/or preventing animations from being run on + * child elements will not be handled by Angular. For this to work as expected, please use `$animate` to + * trigger the animation and then setup a JavaScript animation that injects `$animateCss` to trigger + * the CSS animation. + * + * The example below shows how we can create a folding animation on an element using `ng-if`: + * + * ```html + * + *
    + * This element will go BOOM + *
    + * + * ``` + * + * Now we create the **JavaScript animation** that will trigger the CSS transition: + * + * ```js + * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { + * var height = element[0].offsetHeight; + * return $animateCss(element, { + * from: { height:'0px' }, + * to: { height:height + 'px' }, + * duration: 1 // one second + * }); + * } + * } + * }]); + * ``` + * + * ## More Advanced Uses + * + * `$animateCss` is the underlying code that ngAnimate uses to power **CSS-based animations** behind the scenes. Therefore CSS hooks + * like `.ng-EVENT`, `.ng-EVENT-active`, `.ng-EVENT-stagger` are all features that can be triggered using `$animateCss` via JavaScript code. + * + * This also means that just about any combination of adding classes, removing classes, setting styles, dynamically setting a keyframe animation, + * applying a hardcoded duration or delay value, changing the animation easing or applying a stagger animation are all options that work with + * `$animateCss`. The service itself is smart enough to figure out the combination of options and examine the element styling properties in order + * to provide a working animation that will run in CSS. + * + * The example below showcases a more advanced version of the `.fold-animation` from the example above: + * + * ```js + * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { + * var height = element[0].offsetHeight; + * return $animateCss(element, { + * addClass: 'red large-text pulse-twice', + * easing: 'ease-out', + * from: { height:'0px' }, + * to: { height:height + 'px' }, + * duration: 1 // one second + * }); + * } + * } + * }]); + * ``` + * + * Since we're adding/removing CSS classes then the CSS transition will also pick those up: + * + * ```css + * /* since a hardcoded duration value of 1 was provided in the JavaScript animation code, + * the CSS classes below will be transitioned despite them being defined as regular CSS classes */ + * .red { background:red; } + * .large-text { font-size:20px; } + * + * /* we can also use a keyframe animation and $animateCss will make it work alongside the transition */ + * .pulse-twice { + * animation: 0.5s pulse linear 2; + * -webkit-animation: 0.5s pulse linear 2; + * } + * + * @keyframes pulse { + * from { transform: scale(0.5); } + * to { transform: scale(1.5); } + * } + * + * @-webkit-keyframes pulse { + * from { -webkit-transform: scale(0.5); } + * to { -webkit-transform: scale(1.5); } + * } + * ``` + * + * Given this complex combination of CSS classes, styles and options, `$animateCss` will figure everything out and make the animation happen. + * + * ## How the Options are handled + * + * `$animateCss` is very versatile and intelligent when it comes to figuring out what configurations to apply to the element to ensure the animation + * works with the options provided. Say for example we were adding a class that contained a keyframe value and we wanted to also animate some inline + * styles using the `from` and `to` properties. + * + * ```js + * var animator = $animateCss(element, { + * from: { background:'red' }, + * to: { background:'blue' } + * }); + * animator.start(); + * ``` + * + * ```css + * .rotating-animation { + * animation:0.5s rotate linear; + * -webkit-animation:0.5s rotate linear; + * } + * + * @keyframes rotate { + * from { transform: rotate(0deg); } + * to { transform: rotate(360deg); } + * } + * + * @-webkit-keyframes rotate { + * from { -webkit-transform: rotate(0deg); } + * to { -webkit-transform: rotate(360deg); } + * } + * ``` + * + * The missing pieces here are that we do not have a transition set (within the CSS code nor within the `$animateCss` options) and the duration of the animation is + * going to be detected from what the keyframe styles on the CSS class are. In this event, `$animateCss` will automatically create an inline transition + * style matching the duration detected from the keyframe style (which is present in the CSS class that is being added) and then prepare both the transition + * and keyframe animations to run in parallel on the element. Then when the animation is underway the provided `from` and `to` CSS styles will be applied + * and spread across the transition and keyframe animation. + * + * ## What is returned + * + * `$animateCss` works in two stages: a preparation phase and an animation phase. Therefore when `$animateCss` is first called it will NOT actually + * start the animation. All that is going on here is that the element is being prepared for the animation (which means that the generated CSS classes are + * added and removed on the element). Once `$animateCss` is called it will return an object with the following properties: + * + * ```js + * var animator = $animateCss(element, { ... }); + * ``` + * + * Now what do the contents of our `animator` variable look like: + * + * ```js + * { + * // starts the animation + * start: Function, + * + * // ends (aborts) the animation + * end: Function + * } + * ``` + * + * To actually start the animation we need to run `animation.start()` which will then return a promise that we can hook into to detect when the animation ends. + * If we choose not to run the animation then we MUST run `animation.end()` to perform a cleanup on the element (since some CSS classes and stlyes may have been + * applied to the element during the preparation phase). Note that all other properties such as duration, delay, transitions and keyframes are just properties + * and that changing them will not reconfigure the parameters of the animation. + * + * ### runner.done() vs runner.then() + * It is documented that `animation.start()` will return a promise object and this is true, however, there is also an additional method available on the + * runner called `.done(callbackFn)`. The done method works the same as `.finally(callbackFn)`, however, it does **not trigger a digest to occur**. + * Therefore, for performance reasons, it's always best to use `runner.done(callback)` instead of `runner.then()`, `runner.catch()` or `runner.finally()` + * unless you really need a digest to kick off afterwards. + * + * Keep in mind that, to make this easier, ngAnimate has tweaked the JS animations API to recognize when a runner instance is returned from $animateCss + * (so there is no need to call `runner.done(doneFn)` inside of your JavaScript animation code). Check the [animation code above](#usage) to see how this works. + * + * @param {DOMElement} element the element that will be animated + * @param {object} options the animation-related options that will be applied during the animation + * + * * `event` - The DOM event (e.g. enter, leave, move). When used, a generated CSS class of `ng-EVENT` and `ng-EVENT-active` will be applied + * to the element during the animation. Multiple events can be provided when spaces are used as a separator. (Note that this will not perform any DOM operation.) + * * `easing` - The CSS easing value that will be applied to the transition or keyframe animation (or both). + * * `transition` - The raw CSS transition style that will be used (e.g. `1s linear all`). + * * `keyframe` - The raw CSS keyframe animation style that will be used (e.g. `1s my_animation linear`). + * * `from` - The starting CSS styles (a key/value object) that will be applied at the start of the animation. + * * `to` - The ending CSS styles (a key/value object) that will be applied across the animation via a CSS transition. + * * `addClass` - A space separated list of CSS classes that will be added to the element and spread across the animation. + * * `removeClass` - A space separated list of CSS classes that will be removed from the element and spread across the animation. + * * `duration` - A number value representing the total duration of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `0` + * is provided then the animation will be skipped entirely. + * * `delay` - A number value representing the total delay of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `true` is + * used then whatever delay value is detected from the CSS classes will be mirrored on the elements styles (e.g. by setting delay true then the style value + * of the element will be `transition-delay: DETECTED_VALUE`). Using `true` is useful when you want the CSS classes and inline styles to all share the same + * CSS delay value. + * * `stagger` - A numeric time value representing the delay between successively animated elements + * ({@link ngAnimate#css-staggering-animations Click here to learn how CSS-based staggering works in ngAnimate.}) + * * `staggerIndex` - The numeric index representing the stagger item (e.g. a value of 5 is equal to the sixth item in the stagger; therefore when a + * `stagger` option value of `0.1` is used then there will be a stagger delay of `600ms`) + * `applyClassesEarly` - Whether or not the classes being added or removed will be used when detecting the animation. This is set by `$animate` when enter/leave/move animations are fired to ensure that the CSS classes are resolved in time. (Note that this will prevent any transitions from occuring on the classes being added and removed.) + * + * @return {object} an object with start and end methods and details about the animation. + * + * * `start` - The method to start the animation. This will return a `Promise` when called. + * * `end` - This method will cancel the animation and remove all applied CSS classes and styles. + */ + +// Detect proper transitionend/animationend event names. +var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT; + +// If unprefixed events are not supported but webkit-prefixed are, use the latter. +// Otherwise, just use W3C names, browsers not supporting them at all will just ignore them. +// Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend` +// but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`. +// Register both events in case `window.onanimationend` is not supported because of that, +// do the same for `transitionend` as Safari is likely to exhibit similar behavior. +// Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit +// therefore there is no reason to test anymore for other vendor prefixes: +// http://caniuse.com/#search=transition +if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) { + CSS_PREFIX = '-webkit-'; + TRANSITION_PROP = 'WebkitTransition'; + TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend'; +} else { + TRANSITION_PROP = 'transition'; + TRANSITIONEND_EVENT = 'transitionend'; +} + +if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) { + CSS_PREFIX = '-webkit-'; + ANIMATION_PROP = 'WebkitAnimation'; + ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend'; +} else { + ANIMATION_PROP = 'animation'; + ANIMATIONEND_EVENT = 'animationend'; +} + +var DURATION_KEY = 'Duration'; +var PROPERTY_KEY = 'Property'; +var DELAY_KEY = 'Delay'; +var TIMING_KEY = 'TimingFunction'; +var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount'; +var ANIMATION_PLAYSTATE_KEY = 'PlayState'; +var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3; +var CLOSING_TIME_BUFFER = 1.5; +var ONE_SECOND = 1000; +var BASE_TEN = 10; + +var SAFE_FAST_FORWARD_DURATION_VALUE = 9999; + +var ANIMATION_DELAY_PROP = ANIMATION_PROP + DELAY_KEY; +var ANIMATION_DURATION_PROP = ANIMATION_PROP + DURATION_KEY; + +var TRANSITION_DELAY_PROP = TRANSITION_PROP + DELAY_KEY; +var TRANSITION_DURATION_PROP = TRANSITION_PROP + DURATION_KEY; + +var DETECT_CSS_PROPERTIES = { + transitionDuration: TRANSITION_DURATION_PROP, + transitionDelay: TRANSITION_DELAY_PROP, + transitionProperty: TRANSITION_PROP + PROPERTY_KEY, + animationDuration: ANIMATION_DURATION_PROP, + animationDelay: ANIMATION_DELAY_PROP, + animationIterationCount: ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY +}; + +var DETECT_STAGGER_CSS_PROPERTIES = { + transitionDuration: TRANSITION_DURATION_PROP, + transitionDelay: TRANSITION_DELAY_PROP, + animationDuration: ANIMATION_DURATION_PROP, + animationDelay: ANIMATION_DELAY_PROP +}; + +function computeCssStyles($window, element, properties) { + var styles = Object.create(null); + var detectedStyles = $window.getComputedStyle(element) || {}; + forEach(properties, function(formalStyleName, actualStyleName) { + var val = detectedStyles[formalStyleName]; + if (val) { + var c = val.charAt(0); + + // only numerical-based values have a negative sign or digit as the first value + if (c === '-' || c === '+' || c >= 0) { + val = parseMaxTime(val); + } + + // by setting this to null in the event that the delay is not set or is set directly as 0 + // then we can still allow for zegative values to be used later on and not mistake this + // value for being greater than any other negative value. + if (val === 0) { + val = null; + } + styles[actualStyleName] = val; + } + }); + + return styles; +} + +function parseMaxTime(str) { + var maxValue = 0; + var values = str.split(/\s*,\s*/); + forEach(values, function(value) { + // it's always safe to consider only second values and omit `ms` values since + // getComputedStyle will always handle the conversion for us + if (value.charAt(value.length - 1) == 's') { + value = value.substring(0, value.length - 1); + } + value = parseFloat(value) || 0; + maxValue = maxValue ? Math.max(value, maxValue) : value; + }); + return maxValue; +} + +function truthyTimingValue(val) { + return val === 0 || val != null; +} + +function getCssTransitionDurationStyle(duration, applyOnlyDuration) { + var style = TRANSITION_PROP; + var value = duration + 's'; + if (applyOnlyDuration) { + style += DURATION_KEY; + } else { + value += ' linear all'; + } + return [style, value]; +} + +function getCssKeyframeDurationStyle(duration) { + return [ANIMATION_DURATION_PROP, duration + 's']; +} + +function getCssDelayStyle(delay, isKeyframeAnimation) { + var prop = isKeyframeAnimation ? ANIMATION_DELAY_PROP : TRANSITION_DELAY_PROP; + return [prop, delay + 's']; +} + +function blockTransitions(node, duration) { + // we use a negative delay value since it performs blocking + // yet it doesn't kill any existing transitions running on the + // same element which makes this safe for class-based animations + var value = duration ? '-' + duration + 's' : ''; + applyInlineStyle(node, [TRANSITION_DELAY_PROP, value]); + return [TRANSITION_DELAY_PROP, value]; +} + +function blockKeyframeAnimations(node, applyBlock) { + var value = applyBlock ? 'paused' : ''; + var key = ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY; + applyInlineStyle(node, [key, value]); + return [key, value]; +} + +function applyInlineStyle(node, styleTuple) { + var prop = styleTuple[0]; + var value = styleTuple[1]; + node.style[prop] = value; +} + +function createLocalCacheLookup() { + var cache = Object.create(null); + return { + flush: function() { + cache = Object.create(null); + }, + + count: function(key) { + var entry = cache[key]; + return entry ? entry.total : 0; + }, + + get: function(key) { + var entry = cache[key]; + return entry && entry.value; + }, + + put: function(key, value) { + if (!cache[key]) { + cache[key] = { total: 1, value: value }; + } else { + cache[key].total++; + } + } + }; +} + +var $AnimateCssProvider = ['$animateProvider', function($animateProvider) { + var gcsLookup = createLocalCacheLookup(); + var gcsStaggerLookup = createLocalCacheLookup(); + + this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout', + '$document', '$sniffer', '$$rAFScheduler', + function($window, $$jqLite, $$AnimateRunner, $timeout, + $document, $sniffer, $$rAFScheduler) { + + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + + var parentCounter = 0; + function gcsHashFn(node, extraClasses) { + var KEY = "$$ngAnimateParentKey"; + var parentNode = node.parentNode; + var parentID = parentNode[KEY] || (parentNode[KEY] = ++parentCounter); + return parentID + '-' + node.getAttribute('class') + '-' + extraClasses; + } + + function computeCachedCssStyles(node, className, cacheKey, properties) { + var timings = gcsLookup.get(cacheKey); + + if (!timings) { + timings = computeCssStyles($window, node, properties); + if (timings.animationIterationCount === 'infinite') { + timings.animationIterationCount = 1; + } + } + + // we keep putting this in multiple times even though the value and the cacheKey are the same + // because we're keeping an interal tally of how many duplicate animations are detected. + gcsLookup.put(cacheKey, timings); + return timings; + } + + function computeCachedCssStaggerStyles(node, className, cacheKey, properties) { + var stagger; + + // if we have one or more existing matches of matching elements + // containing the same parent + CSS styles (which is how cacheKey works) + // then staggering is possible + if (gcsLookup.count(cacheKey) > 0) { + stagger = gcsStaggerLookup.get(cacheKey); + + if (!stagger) { + var staggerClassName = pendClasses(className, '-stagger'); + + $$jqLite.addClass(node, staggerClassName); + + stagger = computeCssStyles($window, node, properties); + + // force the conversion of a null value to zero incase not set + stagger.animationDuration = Math.max(stagger.animationDuration, 0); + stagger.transitionDuration = Math.max(stagger.transitionDuration, 0); + + $$jqLite.removeClass(node, staggerClassName); + + gcsStaggerLookup.put(cacheKey, stagger); + } + } + + return stagger || {}; + } + + var bod = getDomNode($document).body; + var rafWaitQueue = []; + function waitUntilQuiet(callback) { + rafWaitQueue.push(callback); + $$rAFScheduler.waitUntilQuiet(function() { + gcsLookup.flush(); + gcsStaggerLookup.flush(); + + //the line below will force the browser to perform a repaint so + //that all the animated elements within the animation frame will + //be properly updated and drawn on screen. This is required to + //ensure that the preparation animation is properly flushed so that + //the active state picks up from there. DO NOT REMOVE THIS LINE. + //DO NOT OPTIMIZE THIS LINE. THE MINIFIER WILL REMOVE IT OTHERWISE WHICH + //WILL RESULT IN AN UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND + //WILL TAKE YEARS AWAY FROM YOUR LIFE. + var width = bod.offsetWidth + 1; + + // we use a for loop to ensure that if the queue is changed + // during this looping then it will consider new requests + for (var i = 0; i < rafWaitQueue.length; i++) { + rafWaitQueue[i](width); + } + rafWaitQueue.length = 0; + }); + } + + return init; + + function computeTimings(node, className, cacheKey) { + var timings = computeCachedCssStyles(node, className, cacheKey, DETECT_CSS_PROPERTIES); + var aD = timings.animationDelay; + var tD = timings.transitionDelay; + timings.maxDelay = aD && tD + ? Math.max(aD, tD) + : (aD || tD); + timings.maxDuration = Math.max( + timings.animationDuration * timings.animationIterationCount, + timings.transitionDuration); + + return timings; + } + + function init(element, options) { + var node = getDomNode(element); + options = prepareAnimationOptions(options); + + var temporaryStyles = []; + var classes = element.attr('class'); + var styles = packageStyles(options); + var animationClosed; + var animationPaused; + var animationCompleted; + var runner; + var runnerHost; + var maxDelay; + var maxDelayTime; + var maxDuration; + var maxDurationTime; + + if (options.duration === 0 || (!$sniffer.animations && !$sniffer.transitions)) { + return closeAndReturnNoopAnimator(); + } + + var method = options.event && isArray(options.event) + ? options.event.join(' ') + : options.event; + + var isStructural = method && options.structural; + var structuralClassName = ''; + var addRemoveClassName = ''; + + if (isStructural) { + structuralClassName = pendClasses(method, 'ng-', true); + } else if (method) { + structuralClassName = method; + } + + if (options.addClass) { + addRemoveClassName += pendClasses(options.addClass, '-add'); + } + + if (options.removeClass) { + if (addRemoveClassName.length) { + addRemoveClassName += ' '; + } + addRemoveClassName += pendClasses(options.removeClass, '-remove'); + } + + // there may be a situation where a structural animation is combined together + // with CSS classes that need to resolve before the animation is computed. + // However this means that there is no explicit CSS code to block the animation + // from happening (by setting 0s none in the class name). If this is the case + // we need to apply the classes before the first rAF so we know to continue if + // there actually is a detected transition or keyframe animation + if (options.applyClassesEarly && addRemoveClassName.length) { + applyAnimationClasses(element, options); + addRemoveClassName = ''; + } + + var setupClasses = [structuralClassName, addRemoveClassName].join(' ').trim(); + var fullClassName = classes + ' ' + setupClasses; + var activeClasses = pendClasses(setupClasses, '-active'); + var hasToStyles = styles.to && Object.keys(styles.to).length > 0; + + // there is no way we can trigger an animation since no styles and + // no classes are being applied which would then trigger a transition + if (!hasToStyles && !setupClasses) { + return closeAndReturnNoopAnimator(); + } + + var cacheKey, stagger; + if (options.stagger > 0) { + var staggerVal = parseFloat(options.stagger); + stagger = { + transitionDelay: staggerVal, + animationDelay: staggerVal, + transitionDuration: 0, + animationDuration: 0 + }; + } else { + cacheKey = gcsHashFn(node, fullClassName); + stagger = computeCachedCssStaggerStyles(node, setupClasses, cacheKey, DETECT_STAGGER_CSS_PROPERTIES); + } + + $$jqLite.addClass(element, setupClasses); + + var applyOnlyDuration; + + if (options.transitionStyle) { + var transitionStyle = [TRANSITION_PROP, options.transitionStyle]; + applyInlineStyle(node, transitionStyle); + temporaryStyles.push(transitionStyle); + } + + if (options.duration >= 0) { + applyOnlyDuration = node.style[TRANSITION_PROP].length > 0; + var durationStyle = getCssTransitionDurationStyle(options.duration, applyOnlyDuration); + + // we set the duration so that it will be picked up by getComputedStyle later + applyInlineStyle(node, durationStyle); + temporaryStyles.push(durationStyle); + } + + if (options.keyframeStyle) { + var keyframeStyle = [ANIMATION_PROP, options.keyframeStyle]; + applyInlineStyle(node, keyframeStyle); + temporaryStyles.push(keyframeStyle); + } + + var itemIndex = stagger + ? options.staggerIndex >= 0 + ? options.staggerIndex + : gcsLookup.count(cacheKey) + : 0; + + var isFirst = itemIndex === 0; + + // this is a pre-emptive way of forcing the setup classes to be added and applied INSTANTLY + // without causing any combination of transitions to kick in. By adding a negative delay value + // it forces the setup class' transition to end immediately. We later then remove the negative + // transition delay to allow for the transition to naturally do it's thing. The beauty here is + // that if there is no transition defined then nothing will happen and this will also allow + // other transitions to be stacked on top of each other without any chopping them out. + if (isFirst) { + blockTransitions(node, SAFE_FAST_FORWARD_DURATION_VALUE); + } + + var timings = computeTimings(node, fullClassName, cacheKey); + var relativeDelay = timings.maxDelay; + maxDelay = Math.max(relativeDelay, 0); + maxDuration = timings.maxDuration; + + var flags = {}; + flags.hasTransitions = timings.transitionDuration > 0; + flags.hasAnimations = timings.animationDuration > 0; + flags.hasTransitionAll = flags.hasTransitions && timings.transitionProperty == 'all'; + flags.applyTransitionDuration = hasToStyles && ( + (flags.hasTransitions && !flags.hasTransitionAll) + || (flags.hasAnimations && !flags.hasTransitions)); + flags.applyAnimationDuration = options.duration && flags.hasAnimations; + flags.applyTransitionDelay = truthyTimingValue(options.delay) && (flags.applyTransitionDuration || flags.hasTransitions); + flags.applyAnimationDelay = truthyTimingValue(options.delay) && flags.hasAnimations; + flags.recalculateTimingStyles = addRemoveClassName.length > 0; + + if (flags.applyTransitionDuration || flags.applyAnimationDuration) { + maxDuration = options.duration ? parseFloat(options.duration) : maxDuration; + + if (flags.applyTransitionDuration) { + flags.hasTransitions = true; + timings.transitionDuration = maxDuration; + applyOnlyDuration = node.style[TRANSITION_PROP + PROPERTY_KEY].length > 0; + temporaryStyles.push(getCssTransitionDurationStyle(maxDuration, applyOnlyDuration)); + } + + if (flags.applyAnimationDuration) { + flags.hasAnimations = true; + timings.animationDuration = maxDuration; + temporaryStyles.push(getCssKeyframeDurationStyle(maxDuration)); + } + } + + if (maxDuration === 0 && !flags.recalculateTimingStyles) { + return closeAndReturnNoopAnimator(); + } + + // we need to recalculate the delay value since we used a pre-emptive negative + // delay value and the delay value is required for the final event checking. This + // property will ensure that this will happen after the RAF phase has passed. + if (options.duration == null && timings.transitionDuration > 0) { + flags.recalculateTimingStyles = flags.recalculateTimingStyles || isFirst; + } + + maxDelayTime = maxDelay * ONE_SECOND; + maxDurationTime = maxDuration * ONE_SECOND; + if (!options.skipBlocking) { + flags.blockTransition = timings.transitionDuration > 0; + flags.blockKeyframeAnimation = timings.animationDuration > 0 && + stagger.animationDelay > 0 && + stagger.animationDuration === 0; + } + + applyAnimationFromStyles(element, options); + if (!flags.blockTransition) { + blockTransitions(node, false); + } + + applyBlocking(maxDuration); + + // TODO(matsko): for 1.5 change this code to have an animator object for better debugging + return { + $$willAnimate: true, + end: endFn, + start: function() { + if (animationClosed) return; + + runnerHost = { + end: endFn, + cancel: cancelFn, + resume: null, //this will be set during the start() phase + pause: null + }; + + runner = new $$AnimateRunner(runnerHost); + + waitUntilQuiet(start); + + // we don't have access to pause/resume the animation + // since it hasn't run yet. AnimateRunner will therefore + // set noop functions for resume and pause and they will + // later be overridden once the animation is triggered + return runner; + } + }; + + function endFn() { + close(); + } + + function cancelFn() { + close(true); + } + + function close(rejected) { // jshint ignore:line + // if the promise has been called already then we shouldn't close + // the animation again + if (animationClosed || (animationCompleted && animationPaused)) return; + animationClosed = true; + animationPaused = false; + + $$jqLite.removeClass(element, setupClasses); + $$jqLite.removeClass(element, activeClasses); + + blockKeyframeAnimations(node, false); + blockTransitions(node, false); + + forEach(temporaryStyles, function(entry) { + // There is only one way to remove inline style properties entirely from elements. + // By using `removeProperty` this works, but we need to convert camel-cased CSS + // styles down to hyphenated values. + node.style[entry[0]] = ''; + }); + + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + + // the reason why we have this option is to allow a synchronous closing callback + // that is fired as SOON as the animation ends (when the CSS is removed) or if + // the animation never takes off at all. A good example is a leave animation since + // the element must be removed just after the animation is over or else the element + // will appear on screen for one animation frame causing an overbearing flicker. + if (options.onDone) { + options.onDone(); + } + + // if the preparation function fails then the promise is not setup + if (runner) { + runner.complete(!rejected); + } + } + + function applyBlocking(duration) { + if (flags.blockTransition) { + blockTransitions(node, duration); + } + + if (flags.blockKeyframeAnimation) { + blockKeyframeAnimations(node, !!duration); + } + } + + function closeAndReturnNoopAnimator() { + runner = new $$AnimateRunner({ + end: endFn, + cancel: cancelFn + }); + + close(); + + return { + $$willAnimate: false, + start: function() { + return runner; + }, + end: endFn + }; + } + + function start() { + if (animationClosed) return; + + var startTime, events = []; + + // even though we only pause keyframe animations here the pause flag + // will still happen when transitions are used. Only the transition will + // not be paused since that is not possible. If the animation ends when + // paused then it will not complete until unpaused or cancelled. + var playPause = function(playAnimation) { + if (!animationCompleted) { + animationPaused = !playAnimation; + if (timings.animationDuration) { + var value = blockKeyframeAnimations(node, animationPaused); + animationPaused + ? temporaryStyles.push(value) + : removeFromArray(temporaryStyles, value); + } + } else if (animationPaused && playAnimation) { + animationPaused = false; + close(); + } + }; + + // checking the stagger duration prevents an accidently cascade of the CSS delay style + // being inherited from the parent. If the transition duration is zero then we can safely + // rely that the delay value is an intential stagger delay style. + var maxStagger = itemIndex > 0 + && ((timings.transitionDuration && stagger.transitionDuration === 0) || + (timings.animationDuration && stagger.animationDuration === 0)) + && Math.max(stagger.animationDelay, stagger.transitionDelay); + if (maxStagger) { + $timeout(triggerAnimationStart, + Math.floor(maxStagger * itemIndex * ONE_SECOND), + false); + } else { + triggerAnimationStart(); + } + + // this will decorate the existing promise runner with pause/resume methods + runnerHost.resume = function() { + playPause(true); + }; + + runnerHost.pause = function() { + playPause(false); + }; + + function triggerAnimationStart() { + // just incase a stagger animation kicks in when the animation + // itself was cancelled entirely + if (animationClosed) return; + + applyBlocking(false); + + forEach(temporaryStyles, function(entry) { + var key = entry[0]; + var value = entry[1]; + node.style[key] = value; + }); + + applyAnimationClasses(element, options); + $$jqLite.addClass(element, activeClasses); + + if (flags.recalculateTimingStyles) { + fullClassName = node.className + ' ' + setupClasses; + cacheKey = gcsHashFn(node, fullClassName); + + timings = computeTimings(node, fullClassName, cacheKey); + relativeDelay = timings.maxDelay; + maxDelay = Math.max(relativeDelay, 0); + maxDuration = timings.maxDuration; + + if (maxDuration === 0) { + close(); + return; + } + + flags.hasTransitions = timings.transitionDuration > 0; + flags.hasAnimations = timings.animationDuration > 0; + } + + if (flags.applyTransitionDelay || flags.applyAnimationDelay) { + relativeDelay = typeof options.delay !== "boolean" && truthyTimingValue(options.delay) + ? parseFloat(options.delay) + : relativeDelay; + + maxDelay = Math.max(relativeDelay, 0); + + var delayStyle; + if (flags.applyTransitionDelay) { + timings.transitionDelay = relativeDelay; + delayStyle = getCssDelayStyle(relativeDelay); + temporaryStyles.push(delayStyle); + node.style[delayStyle[0]] = delayStyle[1]; + } + + if (flags.applyAnimationDelay) { + timings.animationDelay = relativeDelay; + delayStyle = getCssDelayStyle(relativeDelay, true); + temporaryStyles.push(delayStyle); + node.style[delayStyle[0]] = delayStyle[1]; + } + } + + maxDelayTime = maxDelay * ONE_SECOND; + maxDurationTime = maxDuration * ONE_SECOND; + + if (options.easing) { + var easeProp, easeVal = options.easing; + if (flags.hasTransitions) { + easeProp = TRANSITION_PROP + TIMING_KEY; + temporaryStyles.push([easeProp, easeVal]); + node.style[easeProp] = easeVal; + } + if (flags.hasAnimations) { + easeProp = ANIMATION_PROP + TIMING_KEY; + temporaryStyles.push([easeProp, easeVal]); + node.style[easeProp] = easeVal; + } + } + + if (timings.transitionDuration) { + events.push(TRANSITIONEND_EVENT); + } + + if (timings.animationDuration) { + events.push(ANIMATIONEND_EVENT); + } + + startTime = Date.now(); + element.on(events.join(' '), onAnimationProgress); + $timeout(onAnimationExpired, maxDelayTime + CLOSING_TIME_BUFFER * maxDurationTime); + + applyAnimationToStyles(element, options); + } + + function onAnimationExpired() { + // although an expired animation is a failed animation, getting to + // this outcome is very easy if the CSS code screws up. Therefore we + // should still continue normally as if the animation completed correctly. + close(); + } + + function onAnimationProgress(event) { + event.stopPropagation(); + var ev = event.originalEvent || event; + var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now(); + + /* Firefox (or possibly just Gecko) likes to not round values up + * when a ms measurement is used for the animation */ + var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES)); + + /* $manualTimeStamp is a mocked timeStamp value which is set + * within browserTrigger(). This is only here so that tests can + * mock animations properly. Real events fallback to event.timeStamp, + * or, if they don't, then a timeStamp is automatically created for them. + * We're checking to see if the timeStamp surpasses the expected delay, + * but we're using elapsedTime instead of the timeStamp on the 2nd + * pre-condition since animations sometimes close off early */ + if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) { + // we set this flag to ensure that if the transition is paused then, when resumed, + // the animation will automatically close itself since transitions cannot be paused. + animationCompleted = true; + close(); + } + } + } + } + }]; +}]; + +var $$AnimateCssDriverProvider = ['$$animationProvider', function($$animationProvider) { + $$animationProvider.drivers.push('$$animateCssDriver'); + + var NG_ANIMATE_SHIM_CLASS_NAME = 'ng-animate-shim'; + var NG_ANIMATE_ANCHOR_CLASS_NAME = 'ng-anchor'; + + var NG_OUT_ANCHOR_CLASS_NAME = 'ng-anchor-out'; + var NG_IN_ANCHOR_CLASS_NAME = 'ng-anchor-in'; + + this.$get = ['$animateCss', '$rootScope', '$$AnimateRunner', '$rootElement', '$document', '$sniffer', + function($animateCss, $rootScope, $$AnimateRunner, $rootElement, $document, $sniffer) { + + // only browsers that support these properties can render animations + if (!$sniffer.animations && !$sniffer.transitions) return noop; + + var bodyNode = getDomNode($document).body; + var rootNode = getDomNode($rootElement); + + var rootBodyElement = jqLite(bodyNode.parentNode === rootNode ? bodyNode : rootNode); + + return function initDriverFn(animationDetails) { + return animationDetails.from && animationDetails.to + ? prepareFromToAnchorAnimation(animationDetails.from, + animationDetails.to, + animationDetails.classes, + animationDetails.anchors) + : prepareRegularAnimation(animationDetails); + }; + + function filterCssClasses(classes) { + //remove all the `ng-` stuff + return classes.replace(/\bng-\S+\b/g, ''); + } + + function getUniqueValues(a, b) { + if (isString(a)) a = a.split(' '); + if (isString(b)) b = b.split(' '); + return a.filter(function(val) { + return b.indexOf(val) === -1; + }).join(' '); + } + + function prepareAnchoredAnimation(classes, outAnchor, inAnchor) { + var clone = jqLite(getDomNode(outAnchor).cloneNode(true)); + var startingClasses = filterCssClasses(getClassVal(clone)); + + outAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME); + inAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME); + + clone.addClass(NG_ANIMATE_ANCHOR_CLASS_NAME); + + rootBodyElement.append(clone); + + var animatorIn, animatorOut = prepareOutAnimation(); + + // the user may not end up using the `out` animation and + // only making use of the `in` animation or vice-versa. + // In either case we should allow this and not assume the + // animation is over unless both animations are not used. + if (!animatorOut) { + animatorIn = prepareInAnimation(); + if (!animatorIn) { + return end(); + } + } + + var startingAnimator = animatorOut || animatorIn; + + return { + start: function() { + var runner; + + var currentAnimation = startingAnimator.start(); + currentAnimation.done(function() { + currentAnimation = null; + if (!animatorIn) { + animatorIn = prepareInAnimation(); + if (animatorIn) { + currentAnimation = animatorIn.start(); + currentAnimation.done(function() { + currentAnimation = null; + end(); + runner.complete(); + }); + return currentAnimation; + } + } + // in the event that there is no `in` animation + end(); + runner.complete(); + }); + + runner = new $$AnimateRunner({ + end: endFn, + cancel: endFn + }); + + return runner; + + function endFn() { + if (currentAnimation) { + currentAnimation.end(); + } + } + } + }; + + function calculateAnchorStyles(anchor) { + var styles = {}; + + var coords = getDomNode(anchor).getBoundingClientRect(); + + // we iterate directly since safari messes up and doesn't return + // all the keys for the coods object when iterated + forEach(['width','height','top','left'], function(key) { + var value = coords[key]; + switch (key) { + case 'top': + value += bodyNode.scrollTop; + break; + case 'left': + value += bodyNode.scrollLeft; + break; + } + styles[key] = Math.floor(value) + 'px'; + }); + return styles; + } + + function prepareOutAnimation() { + var animator = $animateCss(clone, { + addClass: NG_OUT_ANCHOR_CLASS_NAME, + delay: true, + from: calculateAnchorStyles(outAnchor) + }); + + // read the comment within `prepareRegularAnimation` to understand + // why this check is necessary + return animator.$$willAnimate ? animator : null; + } + + function getClassVal(element) { + return element.attr('class') || ''; + } + + function prepareInAnimation() { + var endingClasses = filterCssClasses(getClassVal(inAnchor)); + var toAdd = getUniqueValues(endingClasses, startingClasses); + var toRemove = getUniqueValues(startingClasses, endingClasses); + + var animator = $animateCss(clone, { + to: calculateAnchorStyles(inAnchor), + addClass: NG_IN_ANCHOR_CLASS_NAME + ' ' + toAdd, + removeClass: NG_OUT_ANCHOR_CLASS_NAME + ' ' + toRemove, + delay: true + }); + + // read the comment within `prepareRegularAnimation` to understand + // why this check is necessary + return animator.$$willAnimate ? animator : null; + } + + function end() { + clone.remove(); + outAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME); + inAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME); + } + } + + function prepareFromToAnchorAnimation(from, to, classes, anchors) { + var fromAnimation = prepareRegularAnimation(from); + var toAnimation = prepareRegularAnimation(to); + + var anchorAnimations = []; + forEach(anchors, function(anchor) { + var outElement = anchor['out']; + var inElement = anchor['in']; + var animator = prepareAnchoredAnimation(classes, outElement, inElement); + if (animator) { + anchorAnimations.push(animator); + } + }); + + // no point in doing anything when there are no elements to animate + if (!fromAnimation && !toAnimation && anchorAnimations.length === 0) return; + + return { + start: function() { + var animationRunners = []; + + if (fromAnimation) { + animationRunners.push(fromAnimation.start()); + } + + if (toAnimation) { + animationRunners.push(toAnimation.start()); + } + + forEach(anchorAnimations, function(animation) { + animationRunners.push(animation.start()); + }); + + var runner = new $$AnimateRunner({ + end: endFn, + cancel: endFn // CSS-driven animations cannot be cancelled, only ended + }); + + $$AnimateRunner.all(animationRunners, function(status) { + runner.complete(status); + }); + + return runner; + + function endFn() { + forEach(animationRunners, function(runner) { + runner.end(); + }); + } + } + }; + } + + function prepareRegularAnimation(animationDetails) { + var element = animationDetails.element; + var options = animationDetails.options || {}; + + if (animationDetails.structural) { + // structural animations ensure that the CSS classes are always applied + // before the detection starts. + options.structural = options.applyClassesEarly = true; + + // we special case the leave animation since we want to ensure that + // the element is removed as soon as the animation is over. Otherwise + // a flicker might appear or the element may not be removed at all + options.event = animationDetails.event; + if (options.event === 'leave') { + options.onDone = options.domOperation; + } + } else { + options.event = null; + } + + var animator = $animateCss(element, options); + + // the driver lookup code inside of $$animation attempts to spawn a + // driver one by one until a driver returns a.$$willAnimate animator object. + // $animateCss will always return an object, however, it will pass in + // a flag as a hint as to whether an animation was detected or not + return animator.$$willAnimate ? animator : null; + } + }]; +}]; + +// TODO(matsko): use caching here to speed things up for detection +// TODO(matsko): add documentation +// by the time... + +var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) { + this.$get = ['$injector', '$$AnimateRunner', '$$rAFMutex', '$$jqLite', + function($injector, $$AnimateRunner, $$rAFMutex, $$jqLite) { + + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + // $animateJs(element, 'enter'); + return function(element, event, classes, options) { + // the `classes` argument is optional and if it is not used + // then the classes will be resolved from the element's className + // property as well as options.addClass/options.removeClass. + if (arguments.length === 3 && isObject(classes)) { + options = classes; + classes = null; + } + + options = prepareAnimationOptions(options); + if (!classes) { + classes = element.attr('class') || ''; + if (options.addClass) { + classes += ' ' + options.addClass; + } + if (options.removeClass) { + classes += ' ' + options.removeClass; + } + } + + var classesToAdd = options.addClass; + var classesToRemove = options.removeClass; + + // the lookupAnimations function returns a series of animation objects that are + // matched up with one or more of the CSS classes. These animation objects are + // defined via the module.animation factory function. If nothing is detected then + // we don't return anything which then makes $animation query the next driver. + var animations = lookupAnimations(classes); + var before, after; + if (animations.length) { + var afterFn, beforeFn; + if (event == 'leave') { + beforeFn = 'leave'; + afterFn = 'afterLeave'; // TODO(matsko): get rid of this + } else { + beforeFn = 'before' + event.charAt(0).toUpperCase() + event.substr(1); + afterFn = event; + } + + if (event !== 'enter' && event !== 'move') { + before = packageAnimations(element, event, options, animations, beforeFn); + } + after = packageAnimations(element, event, options, animations, afterFn); + } + + // no matching animations + if (!before && !after) return; + + function applyOptions() { + options.domOperation(); + applyAnimationClasses(element, options); + } + + return { + start: function() { + var closeActiveAnimations; + var chain = []; + + if (before) { + chain.push(function(fn) { + closeActiveAnimations = before(fn); + }); + } + + if (chain.length) { + chain.push(function(fn) { + applyOptions(); + fn(true); + }); + } else { + applyOptions(); + } + + if (after) { + chain.push(function(fn) { + closeActiveAnimations = after(fn); + }); + } + + var animationClosed = false; + var runner = new $$AnimateRunner({ + end: function() { + endAnimations(); + }, + cancel: function() { + endAnimations(true); + } + }); + + $$AnimateRunner.chain(chain, onComplete); + return runner; + + function onComplete(success) { + animationClosed = true; + applyOptions(); + applyAnimationStyles(element, options); + runner.complete(success); + } + + function endAnimations(cancelled) { + if (!animationClosed) { + (closeActiveAnimations || noop)(cancelled); + onComplete(cancelled); + } + } + } + }; + + function executeAnimationFn(fn, element, event, options, onDone) { + var args; + switch (event) { + case 'animate': + args = [element, options.from, options.to, onDone]; + break; + + case 'setClass': + args = [element, classesToAdd, classesToRemove, onDone]; + break; + + case 'addClass': + args = [element, classesToAdd, onDone]; + break; + + case 'removeClass': + args = [element, classesToRemove, onDone]; + break; + + default: + args = [element, onDone]; + break; + } + + args.push(options); + + var value = fn.apply(fn, args); + if (value) { + if (isFunction(value.start)) { + value = value.start(); + } + + if (value instanceof $$AnimateRunner) { + value.done(onDone); + } else if (isFunction(value)) { + // optional onEnd / onCancel callback + return value; + } + } + + return noop; + } + + function groupEventedAnimations(element, event, options, animations, fnName) { + var operations = []; + forEach(animations, function(ani) { + var animation = ani[fnName]; + if (!animation) return; + + // note that all of these animations will run in parallel + operations.push(function() { + var runner; + var endProgressCb; + + var resolved = false; + var onAnimationComplete = function(rejected) { + if (!resolved) { + resolved = true; + (endProgressCb || noop)(rejected); + runner.complete(!rejected); + } + }; + + runner = new $$AnimateRunner({ + end: function() { + onAnimationComplete(); + }, + cancel: function() { + onAnimationComplete(true); + } + }); + + endProgressCb = executeAnimationFn(animation, element, event, options, function(result) { + var cancelled = result === false; + onAnimationComplete(cancelled); + }); + + return runner; + }); + }); + + return operations; + } + + function packageAnimations(element, event, options, animations, fnName) { + var operations = groupEventedAnimations(element, event, options, animations, fnName); + if (operations.length === 0) { + var a,b; + if (fnName === 'beforeSetClass') { + a = groupEventedAnimations(element, 'removeClass', options, animations, 'beforeRemoveClass'); + b = groupEventedAnimations(element, 'addClass', options, animations, 'beforeAddClass'); + } else if (fnName === 'setClass') { + a = groupEventedAnimations(element, 'removeClass', options, animations, 'removeClass'); + b = groupEventedAnimations(element, 'addClass', options, animations, 'addClass'); + } + + if (a) { + operations = operations.concat(a); + } + if (b) { + operations = operations.concat(b); + } + } + + if (operations.length === 0) return; + + // TODO(matsko): add documentation + return function startAnimation(callback) { + var runners = []; + if (operations.length) { + forEach(operations, function(animateFn) { + runners.push(animateFn()); + }); + } + + runners.length ? $$AnimateRunner.all(runners, callback) : callback(); + + return function endFn(reject) { + forEach(runners, function(runner) { + reject ? runner.cancel() : runner.end(); + }); + }; + }; + } + }; + + function lookupAnimations(classes) { + classes = isArray(classes) ? classes : classes.split(' '); + var matches = [], flagMap = {}; + for (var i=0; i < classes.length; i++) { + var klass = classes[i], + animationFactory = $animateProvider.$$registeredAnimations[klass]; + if (animationFactory && !flagMap[klass]) { + matches.push($injector.get(animationFactory)); + flagMap[klass] = true; + } + } + return matches; + } + }]; +}]; + +var $$AnimateJsDriverProvider = ['$$animationProvider', function($$animationProvider) { + $$animationProvider.drivers.push('$$animateJsDriver'); + this.$get = ['$$animateJs', '$$AnimateRunner', function($$animateJs, $$AnimateRunner) { + return function initDriverFn(animationDetails) { + if (animationDetails.from && animationDetails.to) { + var fromAnimation = prepareAnimation(animationDetails.from); + var toAnimation = prepareAnimation(animationDetails.to); + if (!fromAnimation && !toAnimation) return; + + return { + start: function() { + var animationRunners = []; + + if (fromAnimation) { + animationRunners.push(fromAnimation.start()); + } + + if (toAnimation) { + animationRunners.push(toAnimation.start()); + } + + $$AnimateRunner.all(animationRunners, done); + + var runner = new $$AnimateRunner({ + end: endFnFactory(), + cancel: endFnFactory() + }); + + return runner; + + function endFnFactory() { + return function() { + forEach(animationRunners, function(runner) { + // at this point we cannot cancel animations for groups just yet. 1.5+ + runner.end(); + }); + }; + } + + function done(status) { + runner.complete(status); + } + } + }; + } else { + return prepareAnimation(animationDetails); + } + }; + + function prepareAnimation(animationDetails) { + // TODO(matsko): make sure to check for grouped animations and delegate down to normal animations + var element = animationDetails.element; + var event = animationDetails.event; + var options = animationDetails.options; + var classes = animationDetails.classes; + return $$animateJs(element, event, classes, options); + } + }]; +}]; + +var NG_ANIMATE_ATTR_NAME = 'data-ng-animate'; +var NG_ANIMATE_PIN_DATA = '$ngAnimatePin'; +var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { + var PRE_DIGEST_STATE = 1; + var RUNNING_STATE = 2; + + var rules = this.rules = { + skip: [], + cancel: [], + join: [] + }; + + function isAllowed(ruleType, element, currentAnimation, previousAnimation) { + return rules[ruleType].some(function(fn) { + return fn(element, currentAnimation, previousAnimation); + }); + } + + function hasAnimationClasses(options, and) { + options = options || {}; + var a = (options.addClass || '').length > 0; + var b = (options.removeClass || '').length > 0; + return and ? a && b : a || b; + } + + rules.join.push(function(element, newAnimation, currentAnimation) { + // if the new animation is class-based then we can just tack that on + return !newAnimation.structural && hasAnimationClasses(newAnimation.options); + }); + + rules.skip.push(function(element, newAnimation, currentAnimation) { + // there is no need to animate anything if no classes are being added and + // there is no structural animation that will be triggered + return !newAnimation.structural && !hasAnimationClasses(newAnimation.options); + }); + + rules.skip.push(function(element, newAnimation, currentAnimation) { + // why should we trigger a new structural animation if the element will + // be removed from the DOM anyway? + return currentAnimation.event == 'leave' && newAnimation.structural; + }); + + rules.skip.push(function(element, newAnimation, currentAnimation) { + // if there is a current animation then skip the class-based animation + return currentAnimation.structural && !newAnimation.structural; + }); + + rules.cancel.push(function(element, newAnimation, currentAnimation) { + // there can never be two structural animations running at the same time + return currentAnimation.structural && newAnimation.structural; + }); + + rules.cancel.push(function(element, newAnimation, currentAnimation) { + // if the previous animation is already running, but the new animation will + // be triggered, but the new animation is structural + return currentAnimation.state === RUNNING_STATE && newAnimation.structural; + }); + + rules.cancel.push(function(element, newAnimation, currentAnimation) { + var nO = newAnimation.options; + var cO = currentAnimation.options; + + // if the exact same CSS class is added/removed then it's safe to cancel it + return (nO.addClass && nO.addClass === cO.removeClass) || (nO.removeClass && nO.removeClass === cO.addClass); + }); + + this.$get = ['$$rAF', '$rootScope', '$rootElement', '$document', '$$HashMap', + '$$animation', '$$AnimateRunner', '$templateRequest', '$$jqLite', + function($$rAF, $rootScope, $rootElement, $document, $$HashMap, + $$animation, $$AnimateRunner, $templateRequest, $$jqLite) { + + var activeAnimationsLookup = new $$HashMap(); + var disabledElementsLookup = new $$HashMap(); + + var animationsEnabled = null; + + // Wait until all directive and route-related templates are downloaded and + // compiled. The $templateRequest.totalPendingRequests variable keeps track of + // all of the remote templates being currently downloaded. If there are no + // templates currently downloading then the watcher will still fire anyway. + var deregisterWatch = $rootScope.$watch( + function() { return $templateRequest.totalPendingRequests === 0; }, + function(isEmpty) { + if (!isEmpty) return; + deregisterWatch(); + + // Now that all templates have been downloaded, $animate will wait until + // the post digest queue is empty before enabling animations. By having two + // calls to $postDigest calls we can ensure that the flag is enabled at the + // very end of the post digest queue. Since all of the animations in $animate + // use $postDigest, it's important that the code below executes at the end. + // This basically means that the page is fully downloaded and compiled before + // any animations are triggered. + $rootScope.$$postDigest(function() { + $rootScope.$$postDigest(function() { + // we check for null directly in the event that the application already called + // .enabled() with whatever arguments that it provided it with + if (animationsEnabled === null) { + animationsEnabled = true; + } + }); + }); + } + ); + + var bodyElement = jqLite($document[0].body); + + var callbackRegistry = {}; + + // remember that the classNameFilter is set during the provider/config + // stage therefore we can optimize here and setup a helper function + var classNameFilter = $animateProvider.classNameFilter(); + var isAnimatableClassName = !classNameFilter + ? function() { return true; } + : function(className) { + return classNameFilter.test(className); + }; + + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + + function normalizeAnimationOptions(element, options) { + return mergeAnimationOptions(element, options, {}); + } + + function findCallbacks(element, event) { + var targetNode = getDomNode(element); + + var matches = []; + var entries = callbackRegistry[event]; + if (entries) { + forEach(entries, function(entry) { + if (entry.node.contains(targetNode)) { + matches.push(entry.callback); + } + }); + } + + return matches; + } + + function triggerCallback(event, element, phase, data) { + $$rAF(function() { + forEach(findCallbacks(element, event), function(callback) { + callback(element, phase, data); + }); + }); + } + + return { + on: function(event, container, callback) { + var node = extractElementNode(container); + callbackRegistry[event] = callbackRegistry[event] || []; + callbackRegistry[event].push({ + node: node, + callback: callback + }); + }, + + off: function(event, container, callback) { + var entries = callbackRegistry[event]; + if (!entries) return; + + callbackRegistry[event] = arguments.length === 1 + ? null + : filterFromRegistry(entries, container, callback); + + function filterFromRegistry(list, matchContainer, matchCallback) { + var containerNode = extractElementNode(matchContainer); + return list.filter(function(entry) { + var isMatch = entry.node === containerNode && + (!matchCallback || entry.callback === matchCallback); + return !isMatch; + }); + } + }, + + pin: function(element, parentElement) { + assertArg(isElement(element), 'element', 'not an element'); + assertArg(isElement(parentElement), 'parentElement', 'not an element'); + element.data(NG_ANIMATE_PIN_DATA, parentElement); + }, + + push: function(element, event, options, domOperation) { + options = options || {}; + options.domOperation = domOperation; + return queueAnimation(element, event, options); + }, + + // this method has four signatures: + // () - global getter + // (bool) - global setter + // (element) - element getter + // (element, bool) - element setter + enabled: function(element, bool) { + var argCount = arguments.length; + + if (argCount === 0) { + // () - Global getter + bool = !!animationsEnabled; + } else { + var hasElement = isElement(element); + + if (!hasElement) { + // (bool) - Global setter + bool = animationsEnabled = !!element; + } else { + var node = getDomNode(element); + var recordExists = disabledElementsLookup.get(node); + + if (argCount === 1) { + // (element) - Element getter + bool = !recordExists; + } else { + // (element, bool) - Element setter + bool = !!bool; + if (!bool) { + disabledElementsLookup.put(node, true); + } else if (recordExists) { + disabledElementsLookup.remove(node); + } + } + } + } + + return bool; + } + }; + + function queueAnimation(element, event, options) { + var node, parent; + element = stripCommentsFromElement(element); + if (element) { + node = getDomNode(element); + parent = element.parent(); + } + + options = prepareAnimationOptions(options); + + // we create a fake runner with a working promise. + // These methods will become available after the digest has passed + var runner = new $$AnimateRunner(); + + // there are situations where a directive issues an animation for + // a jqLite wrapper that contains only comment nodes... If this + // happens then there is no way we can perform an animation + if (!node) { + close(); + return runner; + } + + if (isArray(options.addClass)) { + options.addClass = options.addClass.join(' '); + } + + if (isArray(options.removeClass)) { + options.removeClass = options.removeClass.join(' '); + } + + if (options.from && !isObject(options.from)) { + options.from = null; + } + + if (options.to && !isObject(options.to)) { + options.to = null; + } + + var className = [node.className, options.addClass, options.removeClass].join(' '); + if (!isAnimatableClassName(className)) { + close(); + return runner; + } + + var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0; + + // this is a hard disable of all animations for the application or on + // the element itself, therefore there is no need to continue further + // past this point if not enabled + var skipAnimations = !animationsEnabled || disabledElementsLookup.get(node); + var existingAnimation = (!skipAnimations && activeAnimationsLookup.get(node)) || {}; + var hasExistingAnimation = !!existingAnimation.state; + + // there is no point in traversing the same collection of parent ancestors if a followup + // animation will be run on the same element that already did all that checking work + if (!skipAnimations && (!hasExistingAnimation || existingAnimation.state != PRE_DIGEST_STATE)) { + skipAnimations = !areAnimationsAllowed(element, parent, event); + } + + if (skipAnimations) { + close(); + return runner; + } + + if (isStructural) { + closeChildAnimations(element); + } + + var newAnimation = { + structural: isStructural, + element: element, + event: event, + close: close, + options: options, + runner: runner + }; + + if (hasExistingAnimation) { + var skipAnimationFlag = isAllowed('skip', element, newAnimation, existingAnimation); + if (skipAnimationFlag) { + if (existingAnimation.state === RUNNING_STATE) { + close(); + return runner; + } else { + mergeAnimationOptions(element, existingAnimation.options, options); + return existingAnimation.runner; + } + } + + var cancelAnimationFlag = isAllowed('cancel', element, newAnimation, existingAnimation); + if (cancelAnimationFlag) { + if (existingAnimation.state === RUNNING_STATE) { + // this will end the animation right away and it is safe + // to do so since the animation is already running and the + // runner callback code will run in async + existingAnimation.runner.end(); + } else if (existingAnimation.structural) { + // this means that the animation is queued into a digest, but + // hasn't started yet. Therefore it is safe to run the close + // method which will call the runner methods in async. + existingAnimation.close(); + } else { + // this will merge the existing animation options into this new follow-up animation + mergeAnimationOptions(element, newAnimation.options, existingAnimation.options); + } + } else { + // a joined animation means that this animation will take over the existing one + // so an example would involve a leave animation taking over an enter. Then when + // the postDigest kicks in the enter will be ignored. + var joinAnimationFlag = isAllowed('join', element, newAnimation, existingAnimation); + if (joinAnimationFlag) { + if (existingAnimation.state === RUNNING_STATE) { + normalizeAnimationOptions(element, options); + } else { + event = newAnimation.event = existingAnimation.event; + options = mergeAnimationOptions(element, existingAnimation.options, newAnimation.options); + return runner; + } + } + } + } else { + // normalization in this case means that it removes redundant CSS classes that + // already exist (addClass) or do not exist (removeClass) on the element + normalizeAnimationOptions(element, options); + } + + // when the options are merged and cleaned up we may end up not having to do + // an animation at all, therefore we should check this before issuing a post + // digest callback. Structural animations will always run no matter what. + var isValidAnimation = newAnimation.structural; + if (!isValidAnimation) { + // animate (from/to) can be quickly checked first, otherwise we check if any classes are present + isValidAnimation = (newAnimation.event === 'animate' && Object.keys(newAnimation.options.to || {}).length > 0) + || hasAnimationClasses(newAnimation.options); + } + + if (!isValidAnimation) { + close(); + clearElementAnimationState(element); + return runner; + } + + if (isStructural) { + closeParentClassBasedAnimations(parent); + } + + // the counter keeps track of cancelled animations + var counter = (existingAnimation.counter || 0) + 1; + newAnimation.counter = counter; + + markElementAnimationState(element, PRE_DIGEST_STATE, newAnimation); + + $rootScope.$$postDigest(function() { + var animationDetails = activeAnimationsLookup.get(node); + var animationCancelled = !animationDetails; + animationDetails = animationDetails || {}; + + // if addClass/removeClass is called before something like enter then the + // registered parent element may not be present. The code below will ensure + // that a final value for parent element is obtained + var parentElement = element.parent() || []; + + // animate/structural/class-based animations all have requirements. Otherwise there + // is no point in performing an animation. The parent node must also be set. + var isValidAnimation = parentElement.length > 0 + && (animationDetails.event === 'animate' + || animationDetails.structural + || hasAnimationClasses(animationDetails.options)); + + // this means that the previous animation was cancelled + // even if the follow-up animation is the same event + if (animationCancelled || animationDetails.counter !== counter || !isValidAnimation) { + // if another animation did not take over then we need + // to make sure that the domOperation and options are + // handled accordingly + if (animationCancelled) { + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + } + + // if the event changed from something like enter to leave then we do + // it, otherwise if it's the same then the end result will be the same too + if (animationCancelled || (isStructural && animationDetails.event !== event)) { + options.domOperation(); + runner.end(); + } + + // in the event that the element animation was not cancelled or a follow-up animation + // isn't allowed to animate from here then we need to clear the state of the element + // so that any future animations won't read the expired animation data. + if (!isValidAnimation) { + clearElementAnimationState(element); + } + + return; + } + + // this combined multiple class to addClass / removeClass into a setClass event + // so long as a structural event did not take over the animation + event = !animationDetails.structural && hasAnimationClasses(animationDetails.options, true) + ? 'setClass' + : animationDetails.event; + + if (animationDetails.structural) { + closeParentClassBasedAnimations(parentElement); + } + + markElementAnimationState(element, RUNNING_STATE); + var realRunner = $$animation(element, event, animationDetails.options); + realRunner.done(function(status) { + close(!status); + var animationDetails = activeAnimationsLookup.get(node); + if (animationDetails && animationDetails.counter === counter) { + clearElementAnimationState(getDomNode(element)); + } + notifyProgress(runner, event, 'close', {}); + }); + + // this will update the runner's flow-control events based on + // the `realRunner` object. + runner.setHost(realRunner); + notifyProgress(runner, event, 'start', {}); + }); + + return runner; + + function notifyProgress(runner, event, phase, data) { + triggerCallback(event, element, phase, data); + runner.progress(event, phase, data); + } + + function close(reject) { // jshint ignore:line + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + options.domOperation(); + runner.complete(!reject); + } + } + + function closeChildAnimations(element) { + var node = getDomNode(element); + var children = node.querySelectorAll('[' + NG_ANIMATE_ATTR_NAME + ']'); + forEach(children, function(child) { + var state = parseInt(child.getAttribute(NG_ANIMATE_ATTR_NAME)); + var animationDetails = activeAnimationsLookup.get(child); + switch (state) { + case RUNNING_STATE: + animationDetails.runner.end(); + /* falls through */ + case PRE_DIGEST_STATE: + if (animationDetails) { + activeAnimationsLookup.remove(child); + } + break; + } + }); + } + + function clearElementAnimationState(element) { + var node = getDomNode(element); + node.removeAttribute(NG_ANIMATE_ATTR_NAME); + activeAnimationsLookup.remove(node); + } + + function isMatchingElement(nodeOrElmA, nodeOrElmB) { + return getDomNode(nodeOrElmA) === getDomNode(nodeOrElmB); + } + + function closeParentClassBasedAnimations(startingElement) { + var parentNode = getDomNode(startingElement); + do { + if (!parentNode || parentNode.nodeType !== ELEMENT_NODE) break; + + var animationDetails = activeAnimationsLookup.get(parentNode); + if (animationDetails) { + examineParentAnimation(parentNode, animationDetails); + } + + parentNode = parentNode.parentNode; + } while (true); + + // since animations are detected from CSS classes, we need to flush all parent + // class-based animations so that the parent classes are all present for child + // animations to properly function (otherwise any CSS selectors may not work) + function examineParentAnimation(node, animationDetails) { + // enter/leave/move always have priority + if (animationDetails.structural || !hasAnimationClasses(animationDetails.options)) return; + + if (animationDetails.state === RUNNING_STATE) { + animationDetails.runner.end(); + } + clearElementAnimationState(node); + } + } + + function areAnimationsAllowed(element, parentElement, event) { + var bodyElementDetected = false; + var rootElementDetected = false; + var parentAnimationDetected = false; + var animateChildren; + + var parentHost = element.data(NG_ANIMATE_PIN_DATA); + if (parentHost) { + parentElement = parentHost; + } + + while (parentElement && parentElement.length) { + if (!rootElementDetected) { + // angular doesn't want to attempt to animate elements outside of the application + // therefore we need to ensure that the rootElement is an ancestor of the current element + rootElementDetected = isMatchingElement(parentElement, $rootElement); + } + + var parentNode = parentElement[0]; + if (parentNode.nodeType !== ELEMENT_NODE) { + // no point in inspecting the #document element + break; + } + + var details = activeAnimationsLookup.get(parentNode) || {}; + // either an enter, leave or move animation will commence + // therefore we can't allow any animations to take place + // but if a parent animation is class-based then that's ok + if (!parentAnimationDetected) { + parentAnimationDetected = details.structural || disabledElementsLookup.get(parentNode); + } + + if (isUndefined(animateChildren) || animateChildren === true) { + var value = parentElement.data(NG_ANIMATE_CHILDREN_DATA); + if (isDefined(value)) { + animateChildren = value; + } + } + + // there is no need to continue traversing at this point + if (parentAnimationDetected && animateChildren === false) break; + + if (!rootElementDetected) { + // angular doesn't want to attempt to animate elements outside of the application + // therefore we need to ensure that the rootElement is an ancestor of the current element + rootElementDetected = isMatchingElement(parentElement, $rootElement); + if (!rootElementDetected) { + parentHost = parentElement.data(NG_ANIMATE_PIN_DATA); + if (parentHost) { + parentElement = parentHost; + } + } + } + + if (!bodyElementDetected) { + // we also need to ensure that the element is or will be apart of the body element + // otherwise it is pointless to even issue an animation to be rendered + bodyElementDetected = isMatchingElement(parentElement, bodyElement); + } + + parentElement = parentElement.parent(); + } + + var allowAnimation = !parentAnimationDetected || animateChildren; + return allowAnimation && rootElementDetected && bodyElementDetected; + } + + function markElementAnimationState(element, state, details) { + details = details || {}; + details.state = state; + + var node = getDomNode(element); + node.setAttribute(NG_ANIMATE_ATTR_NAME, state); + + var oldValue = activeAnimationsLookup.get(node); + var newValue = oldValue + ? extend(oldValue, details) + : details; + activeAnimationsLookup.put(node, newValue); + } + }]; +}]; + +var $$rAFMutexFactory = ['$$rAF', function($$rAF) { + return function() { + var passed = false; + $$rAF(function() { + passed = true; + }); + return function(fn) { + passed ? fn() : $$rAF(fn); + }; + }; +}]; + +var $$AnimateRunnerFactory = ['$q', '$$rAFMutex', function($q, $$rAFMutex) { + var INITIAL_STATE = 0; + var DONE_PENDING_STATE = 1; + var DONE_COMPLETE_STATE = 2; + + AnimateRunner.chain = function(chain, callback) { + var index = 0; + + next(); + function next() { + if (index === chain.length) { + callback(true); + return; + } + + chain[index](function(response) { + if (response === false) { + callback(false); + return; + } + index++; + next(); + }); + } + }; + + AnimateRunner.all = function(runners, callback) { + var count = 0; + var status = true; + forEach(runners, function(runner) { + runner.done(onProgress); + }); + + function onProgress(response) { + status = status && response; + if (++count === runners.length) { + callback(status); + } + } + }; + + function AnimateRunner(host) { + this.setHost(host); + + this._doneCallbacks = []; + this._runInAnimationFrame = $$rAFMutex(); + this._state = 0; + } + + AnimateRunner.prototype = { + setHost: function(host) { + this.host = host || {}; + }, + + done: function(fn) { + if (this._state === DONE_COMPLETE_STATE) { + fn(); + } else { + this._doneCallbacks.push(fn); + } + }, + + progress: noop, + + getPromise: function() { + if (!this.promise) { + var self = this; + this.promise = $q(function(resolve, reject) { + self.done(function(status) { + status === false ? reject() : resolve(); + }); + }); + } + return this.promise; + }, + + then: function(resolveHandler, rejectHandler) { + return this.getPromise().then(resolveHandler, rejectHandler); + }, + + 'catch': function(handler) { + return this.getPromise()['catch'](handler); + }, + + 'finally': function(handler) { + return this.getPromise()['finally'](handler); + }, + + pause: function() { + if (this.host.pause) { + this.host.pause(); + } + }, + + resume: function() { + if (this.host.resume) { + this.host.resume(); + } + }, + + end: function() { + if (this.host.end) { + this.host.end(); + } + this._resolve(true); + }, + + cancel: function() { + if (this.host.cancel) { + this.host.cancel(); + } + this._resolve(false); + }, + + complete: function(response) { + var self = this; + if (self._state === INITIAL_STATE) { + self._state = DONE_PENDING_STATE; + self._runInAnimationFrame(function() { + self._resolve(response); + }); + } + }, + + _resolve: function(response) { + if (this._state !== DONE_COMPLETE_STATE) { + forEach(this._doneCallbacks, function(fn) { + fn(response); + }); + this._doneCallbacks.length = 0; + this._state = DONE_COMPLETE_STATE; + } + } + }; + + return AnimateRunner; +}]; + +var $$AnimationProvider = ['$animateProvider', function($animateProvider) { + var NG_ANIMATE_REF_ATTR = 'ng-animate-ref'; + + var drivers = this.drivers = []; + + var RUNNER_STORAGE_KEY = '$$animationRunner'; + + function setRunner(element, runner) { + element.data(RUNNER_STORAGE_KEY, runner); + } + + function removeRunner(element) { + element.removeData(RUNNER_STORAGE_KEY); + } + + function getRunner(element) { + return element.data(RUNNER_STORAGE_KEY); + } + + this.$get = ['$$jqLite', '$rootScope', '$injector', '$$AnimateRunner', '$$rAFScheduler', + function($$jqLite, $rootScope, $injector, $$AnimateRunner, $$rAFScheduler) { + + var animationQueue = []; + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + + var totalPendingClassBasedAnimations = 0; + var totalActiveClassBasedAnimations = 0; + var classBasedAnimationsQueue = []; + + // TODO(matsko): document the signature in a better way + return function(element, event, options) { + options = prepareAnimationOptions(options); + var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0; + + // there is no animation at the current moment, however + // these runner methods will get later updated with the + // methods leading into the driver's end/cancel methods + // for now they just stop the animation from starting + var runner = new $$AnimateRunner({ + end: function() { close(); }, + cancel: function() { close(true); } + }); + + if (!drivers.length) { + close(); + return runner; + } + + setRunner(element, runner); + + var classes = mergeClasses(element.attr('class'), mergeClasses(options.addClass, options.removeClass)); + var tempClasses = options.tempClasses; + if (tempClasses) { + classes += ' ' + tempClasses; + options.tempClasses = null; + } + + var classBasedIndex; + if (!isStructural) { + classBasedIndex = totalPendingClassBasedAnimations; + totalPendingClassBasedAnimations += 1; + } + + animationQueue.push({ + // this data is used by the postDigest code and passed into + // the driver step function + element: element, + classes: classes, + event: event, + classBasedIndex: classBasedIndex, + structural: isStructural, + options: options, + beforeStart: beforeStart, + close: close + }); + + element.on('$destroy', handleDestroyedElement); + + // we only want there to be one function called within the post digest + // block. This way we can group animations for all the animations that + // were apart of the same postDigest flush call. + if (animationQueue.length > 1) return runner; + + $rootScope.$$postDigest(function() { + totalActiveClassBasedAnimations = totalPendingClassBasedAnimations; + totalPendingClassBasedAnimations = 0; + classBasedAnimationsQueue.length = 0; + + var animations = []; + forEach(animationQueue, function(entry) { + // the element was destroyed early on which removed the runner + // form its storage. This means we can't animate this element + // at all and it already has been closed due to destruction. + if (getRunner(entry.element)) { + animations.push(entry); + } + }); + + // now any future animations will be in another postDigest + animationQueue.length = 0; + + forEach(groupAnimations(animations), function(animationEntry) { + if (animationEntry.structural) { + triggerAnimationStart(); + } else { + classBasedAnimationsQueue.push({ + node: getDomNode(animationEntry.element), + fn: triggerAnimationStart + }); + + if (animationEntry.classBasedIndex === totalActiveClassBasedAnimations - 1) { + // we need to sort each of the animations in order of parent to child + // relationships. This ensures that the child classes are applied at the + // right time. + classBasedAnimationsQueue = classBasedAnimationsQueue.sort(function(a,b) { + return b.node.contains(a.node); + }).map(function(entry) { + return entry.fn; + }); + + $$rAFScheduler(classBasedAnimationsQueue); + } + } + + function triggerAnimationStart() { + // it's important that we apply the `ng-animate` CSS class and the + // temporary classes before we do any driver invoking since these + // CSS classes may be required for proper CSS detection. + animationEntry.beforeStart(); + + var startAnimationFn, closeFn = animationEntry.close; + + // in the event that the element was removed before the digest runs or + // during the RAF sequencing then we should not trigger the animation. + var targetElement = animationEntry.anchors + ? (animationEntry.from.element || animationEntry.to.element) + : animationEntry.element; + + if (getRunner(targetElement)) { + var operation = invokeFirstDriver(animationEntry); + if (operation) { + startAnimationFn = operation.start; + } + } + + if (!startAnimationFn) { + closeFn(); + } else { + var animationRunner = startAnimationFn(); + animationRunner.done(function(status) { + closeFn(!status); + }); + updateAnimationRunners(animationEntry, animationRunner); + } + } + }); + }); + + return runner; + + // TODO(matsko): change to reference nodes + function getAnchorNodes(node) { + var SELECTOR = '[' + NG_ANIMATE_REF_ATTR + ']'; + var items = node.hasAttribute(NG_ANIMATE_REF_ATTR) + ? [node] + : node.querySelectorAll(SELECTOR); + var anchors = []; + forEach(items, function(node) { + var attr = node.getAttribute(NG_ANIMATE_REF_ATTR); + if (attr && attr.length) { + anchors.push(node); + } + }); + return anchors; + } + + function groupAnimations(animations) { + var preparedAnimations = []; + var refLookup = {}; + forEach(animations, function(animation, index) { + var element = animation.element; + var node = getDomNode(element); + var event = animation.event; + var enterOrMove = ['enter', 'move'].indexOf(event) >= 0; + var anchorNodes = animation.structural ? getAnchorNodes(node) : []; + + if (anchorNodes.length) { + var direction = enterOrMove ? 'to' : 'from'; + + forEach(anchorNodes, function(anchor) { + var key = anchor.getAttribute(NG_ANIMATE_REF_ATTR); + refLookup[key] = refLookup[key] || {}; + refLookup[key][direction] = { + animationID: index, + element: jqLite(anchor) + }; + }); + } else { + preparedAnimations.push(animation); + } + }); + + var usedIndicesLookup = {}; + var anchorGroups = {}; + forEach(refLookup, function(operations, key) { + var from = operations.from; + var to = operations.to; + + if (!from || !to) { + // only one of these is set therefore we can't have an + // anchor animation since all three pieces are required + var index = from ? from.animationID : to.animationID; + var indexKey = index.toString(); + if (!usedIndicesLookup[indexKey]) { + usedIndicesLookup[indexKey] = true; + preparedAnimations.push(animations[index]); + } + return; + } + + var fromAnimation = animations[from.animationID]; + var toAnimation = animations[to.animationID]; + var lookupKey = from.animationID.toString(); + if (!anchorGroups[lookupKey]) { + var group = anchorGroups[lookupKey] = { + structural: true, + beforeStart: function() { + fromAnimation.beforeStart(); + toAnimation.beforeStart(); + }, + close: function() { + fromAnimation.close(); + toAnimation.close(); + }, + classes: cssClassesIntersection(fromAnimation.classes, toAnimation.classes), + from: fromAnimation, + to: toAnimation, + anchors: [] // TODO(matsko): change to reference nodes + }; + + // the anchor animations require that the from and to elements both have at least + // one shared CSS class which effictively marries the two elements together to use + // the same animation driver and to properly sequence the anchor animation. + if (group.classes.length) { + preparedAnimations.push(group); + } else { + preparedAnimations.push(fromAnimation); + preparedAnimations.push(toAnimation); + } + } + + anchorGroups[lookupKey].anchors.push({ + 'out': from.element, 'in': to.element + }); + }); + + return preparedAnimations; + } + + function cssClassesIntersection(a,b) { + a = a.split(' '); + b = b.split(' '); + var matches = []; + + for (var i = 0; i < a.length; i++) { + var aa = a[i]; + if (aa.substring(0,3) === 'ng-') continue; + + for (var j = 0; j < b.length; j++) { + if (aa === b[j]) { + matches.push(aa); + break; + } + } + } + + return matches.join(' '); + } + + function invokeFirstDriver(animationDetails) { + // we loop in reverse order since the more general drivers (like CSS and JS) + // may attempt more elements, but custom drivers are more particular + for (var i = drivers.length - 1; i >= 0; i--) { + var driverName = drivers[i]; + if (!$injector.has(driverName)) continue; // TODO(matsko): remove this check + + var factory = $injector.get(driverName); + var driver = factory(animationDetails); + if (driver) { + return driver; + } + } + } + + function beforeStart() { + element.addClass(NG_ANIMATE_CLASSNAME); + if (tempClasses) { + $$jqLite.addClass(element, tempClasses); + } + } + + function updateAnimationRunners(animation, newRunner) { + if (animation.from && animation.to) { + update(animation.from.element); + update(animation.to.element); + } else { + update(animation.element); + } + + function update(element) { + getRunner(element).setHost(newRunner); + } + } + + function handleDestroyedElement() { + var runner = getRunner(element); + if (runner && (event !== 'leave' || !options.$$domOperationFired)) { + runner.end(); + } + } + + function close(rejected) { // jshint ignore:line + element.off('$destroy', handleDestroyedElement); + removeRunner(element); + + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + options.domOperation(); + + if (tempClasses) { + $$jqLite.removeClass(element, tempClasses); + } + + element.removeClass(NG_ANIMATE_CLASSNAME); + runner.complete(!rejected); + } + }; + }]; +}]; + +/* global angularAnimateModule: true, + + $$rAFMutexFactory, + $$rAFSchedulerFactory, + $$AnimateChildrenDirective, + $$AnimateRunnerFactory, + $$AnimateQueueProvider, + $$AnimationProvider, + $AnimateCssProvider, + $$AnimateCssDriverProvider, + $$AnimateJsProvider, + $$AnimateJsDriverProvider, +*/ + +/** + * @ngdoc module + * @name ngAnimate + * @description + * + * The `ngAnimate` module provides support for CSS-based animations (keyframes and transitions) as well as JavaScript-based animations via + * callback hooks. Animations are not enabled by default, however, by including `ngAnimate` then the animation hooks are enabled for an Angular app. + * + *
    + * + * # Usage + * Simply put, there are two ways to make use of animations when ngAnimate is used: by using **CSS** and **JavaScript**. The former works purely based + * using CSS (by using matching CSS selectors/styles) and the latter triggers animations that are registered via `module.animation()`. For + * both CSS and JS animations the sole requirement is to have a matching `CSS class` that exists both in the registered animation and within + * the HTML element that the animation will be triggered on. + * + * ## Directive Support + * The following directives are "animation aware": + * + * | Directive | Supported Animations | + * |----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------| + * | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave and move | + * | {@link ngRoute.directive:ngView#animations ngView} | enter and leave | + * | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave | + * | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave | + * | {@link ng.directive:ngIf#animations ngIf} | enter and leave | + * | {@link ng.directive:ngClass#animations ngClass} | add and remove (the CSS class(es) present) | + * | {@link ng.directive:ngShow#animations ngShow} & {@link ng.directive:ngHide#animations ngHide} | add and remove (the ng-hide class value) | + * | {@link ng.directive:form#animation-hooks form} & {@link ng.directive:ngModel#animation-hooks ngModel} | add and remove (dirty, pristine, valid, invalid & all other validations) | + * | {@link module:ngMessages#animations ngMessages} | add and remove (ng-active & ng-inactive) | + * | {@link module:ngMessages#animations ngMessage} | enter and leave | + * + * (More information can be found by visiting each the documentation associated with each directive.) + * + * ## CSS-based Animations + * + * CSS-based animations with ngAnimate are unique since they require no JavaScript code at all. By using a CSS class that we reference between our HTML + * and CSS code we can create an animation that will be picked up by Angular when an the underlying directive performs an operation. + * + * The example below shows how an `enter` animation can be made possible on a element using `ng-if`: + * + * ```html + *
    + * Fade me in out + *
    + * + * + * ``` + * + * Notice the CSS class **fade**? We can now create the CSS transition code that references this class: + * + * ```css + * /* The starting CSS styles for the enter animation */ + * .fade.ng-enter { + * transition:0.5s linear all; + * opacity:0; + * } + * + * /* The starting CSS styles for the enter animation */ + * .fade.ng-enter.ng-enter-active { + * opacity:1; + * } + * ``` + * + * The key thing to remember here is that, depending on the animation event (which each of the directives above trigger depending on what's going on) two + * generated CSS classes will be applied to the element; in the example above we have `.ng-enter` and `.ng-enter-active`. For CSS transitions, the transition + * code **must** be defined within the starting CSS class (in this case `.ng-enter`). The destination class is what the transition will animate towards. + * + * If for example we wanted to create animations for `leave` and `move` (ngRepeat triggers move) then we can do so using the same CSS naming conventions: + * + * ```css + * /* now the element will fade out before it is removed from the DOM */ + * .fade.ng-leave { + * transition:0.5s linear all; + * opacity:1; + * } + * .fade.ng-leave.ng-leave-active { + * opacity:0; + * } + * ``` + * + * We can also make use of **CSS Keyframes** by referencing the keyframe animation within the starting CSS class: + * + * ```css + * /* there is no need to define anything inside of the destination + * CSS class since the keyframe will take charge of the animation */ + * .fade.ng-leave { + * animation: my_fade_animation 0.5s linear; + * -webkit-animation: my_fade_animation 0.5s linear; + * } + * + * @keyframes my_fade_animation { + * from { opacity:1; } + * to { opacity:0; } + * } + * + * @-webkit-keyframes my_fade_animation { + * from { opacity:1; } + * to { opacity:0; } + * } + * ``` + * + * Feel free also mix transitions and keyframes together as well as any other CSS classes on the same element. + * + * ### CSS Class-based Animations + * + * Class-based animations (animations that are triggered via `ngClass`, `ngShow`, `ngHide` and some other directives) have a slightly different + * naming convention. Class-based animations are basic enough that a standard transition or keyframe can be referenced on the class being added + * and removed. + * + * For example if we wanted to do a CSS animation for `ngHide` then we place an animation on the `.ng-hide` CSS class: + * + * ```html + *
    + * Show and hide me + *
    + * + * + * + * ``` + * + * All that is going on here with ngShow/ngHide behind the scenes is the `.ng-hide` class is added/removed (when the hidden state is valid). Since + * ngShow and ngHide are animation aware then we can match up a transition and ngAnimate handles the rest. + * + * In addition the addition and removal of the CSS class, ngAnimate also provides two helper methods that we can use to further decorate the animation + * with CSS styles. + * + * ```html + *
    + * Highlight this box + *
    + * + * + * + * ``` + * + * We can also make use of CSS keyframes by placing them within the CSS classes. + * + * + * ### CSS Staggering Animations + * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a + * curtain-like effect. The ngAnimate module (versions >=1.2) supports staggering animations and the stagger effect can be + * performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for + * the animation. The style property expected within the stagger class can either be a **transition-delay** or an + * **animation-delay** property (or both if your animation contains both transitions and keyframe animations). + * + * ```css + * .my-animation.ng-enter { + * /* standard transition code */ + * transition: 1s linear all; + * opacity:0; + * } + * .my-animation.ng-enter-stagger { + * /* this will have a 100ms delay between each successive leave animation */ + * transition-delay: 0.1s; + * + * /* in case the stagger doesn't work then the duration value + * must be set to 0 to avoid an accidental CSS inheritance */ + * transition-duration: 0s; + * } + * .my-animation.ng-enter.ng-enter-active { + * /* standard transition styles */ + * opacity:1; + * } + * ``` + * + * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations + * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this + * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation + * will also be reset if one or more animation frames have passed since the multiple calls to `$animate` were fired. + * + * The following code will issue the **ng-leave-stagger** event on the element provided: + * + * ```js + * var kids = parent.children(); + * + * $animate.leave(kids[0]); //stagger index=0 + * $animate.leave(kids[1]); //stagger index=1 + * $animate.leave(kids[2]); //stagger index=2 + * $animate.leave(kids[3]); //stagger index=3 + * $animate.leave(kids[4]); //stagger index=4 + * + * window.requestAnimationFrame(function() { + * //stagger has reset itself + * $animate.leave(kids[5]); //stagger index=0 + * $animate.leave(kids[6]); //stagger index=1 + * + * $scope.$digest(); + * }); + * ``` + * + * Stagger animations are currently only supported within CSS-defined animations. + * + * ### The `ng-animate` CSS class + * + * When ngAnimate is animating an element it will apply the `ng-animate` CSS class to the element for the duration of the animation. + * This is a temporary CSS class and it will be removed once the animation is over (for both JavaScript and CSS-based animations). + * + * Therefore, animations can be applied to an element using this temporary class directly via CSS. + * + * ```css + * .zipper.ng-animate { + * transition:0.5s linear all; + * } + * .zipper.ng-enter { + * opacity:0; + * } + * .zipper.ng-enter.ng-enter-active { + * opacity:1; + * } + * .zipper.ng-leave { + * opacity:1; + * } + * .zipper.ng-leave.ng-leave-active { + * opacity:0; + * } + * ``` + * + * (Note that the `ng-animate` CSS class is reserved and it cannot be applied on an element directly since ngAnimate will always remove + * the CSS class once an animation has completed.) + * + * + * ## JavaScript-based Animations + * + * ngAnimate also allows for animations to be consumed by JavaScript code. The approach is similar to CSS-based animations (where there is a shared + * CSS class that is referenced in our HTML code) but in addition we need to register the JavaScript animation on the module. By making use of the + * `module.animation()` module function we can register the ainmation. + * + * Let's see an example of a enter/leave animation using `ngRepeat`: + * + * ```html + *
    + * {{ item }} + *
    + * ``` + * + * See the **slide** CSS class? Let's use that class to define an animation that we'll structure in our module code by using `module.animation`: + * + * ```js + * myModule.animation('.slide', [function() { + * return { + * // make note that other events (like addClass/removeClass) + * // have different function input parameters + * enter: function(element, doneFn) { + * jQuery(element).fadeIn(1000, doneFn); + * + * // remember to call doneFn so that angular + * // knows that the animation has concluded + * }, + * + * move: function(element, doneFn) { + * jQuery(element).fadeIn(1000, doneFn); + * }, + * + * leave: function(element, doneFn) { + * jQuery(element).fadeOut(1000, doneFn); + * } + * } + * }] + * ``` + * + * The nice thing about JS-based animations is that we can inject other services and make use of advanced animation libraries such as + * greensock.js and velocity.js. + * + * If our animation code class-based (meaning that something like `ngClass`, `ngHide` and `ngShow` triggers it) then we can still define + * our animations inside of the same registered animation, however, the function input arguments are a bit different: + * + * ```html + *
    + * this box is moody + *
    + * + * + * + * ``` + * + * ```js + * myModule.animation('.colorful', [function() { + * return { + * addClass: function(element, className, doneFn) { + * // do some cool animation and call the doneFn + * }, + * removeClass: function(element, className, doneFn) { + * // do some cool animation and call the doneFn + * }, + * setClass: function(element, addedClass, removedClass, doneFn) { + * // do some cool animation and call the doneFn + * } + * } + * }] + * ``` + * + * ## CSS + JS Animations Together + * + * AngularJS 1.4 and higher has taken steps to make the amalgamation of CSS and JS animations more flexible. However, unlike earlier versions of Angular, + * defining CSS and JS animations to work off of the same CSS class will not work anymore. Therefore example below will only result in **JS animations taking + * charge of the animation**: + * + * ```html + *
    + * Slide in and out + *
    + * ``` + * + * ```js + * myModule.animation('.slide', [function() { + * return { + * enter: function(element, doneFn) { + * jQuery(element).slideIn(1000, doneFn); + * } + * } + * }] + * ``` + * + * ```css + * .slide.ng-enter { + * transition:0.5s linear all; + * transform:translateY(-100px); + * } + * .slide.ng-enter.ng-enter-active { + * transform:translateY(0); + * } + * ``` + * + * Does this mean that CSS and JS animations cannot be used together? Do JS-based animations always have higher priority? We can suppliment for the + * lack of CSS animations by making use of the `$animateCss` service to trigger our own tweaked-out, CSS-based animations directly from + * our own JS-based animation code: + * + * ```js + * myModule.animation('.slide', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { +* // this will trigger `.slide.ng-enter` and `.slide.ng-enter-active`. + * var runner = $animateCss(element, { + * event: 'enter', + * structural: true + * }).start(); +* runner.done(doneFn); + * } + * } + * }] + * ``` + * + * The nice thing here is that we can save bandwidth by sticking to our CSS-based animation code and we don't need to rely on a 3rd-party animation framework. + * + * The `$animateCss` service is very powerful since we can feed in all kinds of extra properties that will be evaluated and fed into a CSS transition or + * keyframe animation. For example if we wanted to animate the height of an element while adding and removing classes then we can do so by providing that + * data into `$animateCss` directly: + * + * ```js + * myModule.animation('.slide', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { + * var runner = $animateCss(element, { + * event: 'enter', + * addClass: 'maroon-setting', + * from: { height:0 }, + * to: { height: 200 } + * }).start(); + * + * runner.done(doneFn); + * } + * } + * }] + * ``` + * + * Now we can fill in the rest via our transition CSS code: + * + * ```css + * /* the transition tells ngAnimate to make the animation happen */ + * .slide.ng-enter { transition:0.5s linear all; } + * + * /* this extra CSS class will be absorbed into the transition + * since the $animateCss code is adding the class */ + * .maroon-setting { background:red; } + * ``` + * + * And `$animateCss` will figure out the rest. Just make sure to have the `done()` callback fire the `doneFn` function to signal when the animation is over. + * + * To learn more about what's possible be sure to visit the {@link ngAnimate.$animateCss $animateCss service}. + * + * ## Animation Anchoring (via `ng-animate-ref`) + * + * ngAnimate in AngularJS 1.4 comes packed with the ability to cross-animate elements between + * structural areas of an application (like views) by pairing up elements using an attribute + * called `ng-animate-ref`. + * + * Let's say for example we have two views that are managed by `ng-view` and we want to show + * that there is a relationship between two components situated in within these views. By using the + * `ng-animate-ref` attribute we can identify that the two components are paired together and we + * can then attach an animation, which is triggered when the view changes. + * + * Say for example we have the following template code: + * + * ```html + * + *
    + *
    + * + * + * + * + * + * + * + * + * ``` + * + * Now, when the view changes (once the link is clicked), ngAnimate will examine the + * HTML contents to see if there is a match reference between any components in the view + * that is leaving and the view that is entering. It will scan both the view which is being + * removed (leave) and inserted (enter) to see if there are any paired DOM elements that + * contain a matching ref value. + * + * The two images match since they share the same ref value. ngAnimate will now create a + * transport element (which is a clone of the first image element) and it will then attempt + * to animate to the position of the second image element in the next view. For the animation to + * work a special CSS class called `ng-anchor` will be added to the transported element. + * + * We can now attach a transition onto the `.banner.ng-anchor` CSS class and then + * ngAnimate will handle the entire transition for us as well as the addition and removal of + * any changes of CSS classes between the elements: + * + * ```css + * .banner.ng-anchor { + * /* this animation will last for 1 second since there are + * two phases to the animation (an `in` and an `out` phase) */ + * transition:0.5s linear all; + * } + * ``` + * + * We also **must** include animations for the views that are being entered and removed + * (otherwise anchoring wouldn't be possible since the new view would be inserted right away). + * + * ```css + * .view-animation.ng-enter, .view-animation.ng-leave { + * transition:0.5s linear all; + * position:fixed; + * left:0; + * top:0; + * width:100%; + * } + * .view-animation.ng-enter { + * transform:translateX(100%); + * } + * .view-animation.ng-leave, + * .view-animation.ng-enter.ng-enter-active { + * transform:translateX(0%); + * } + * .view-animation.ng-leave.ng-leave-active { + * transform:translateX(-100%); + * } + * ``` + * + * Now we can jump back to the anchor animation. When the animation happens, there are two stages that occur: + * an `out` and an `in` stage. The `out` stage happens first and that is when the element is animated away + * from its origin. Once that animation is over then the `in` stage occurs which animates the + * element to its destination. The reason why there are two animations is to give enough time + * for the enter animation on the new element to be ready. + * + * The example above sets up a transition for both the in and out phases, but we can also target the out or + * in phases directly via `ng-anchor-out` and `ng-anchor-in`. + * + * ```css + * .banner.ng-anchor-out { + * transition: 0.5s linear all; + * + * /* the scale will be applied during the out animation, + * but will be animated away when the in animation runs */ + * transform: scale(1.2); + * } + * + * .banner.ng-anchor-in { + * transition: 1s linear all; + * } + * ``` + * + * + * + * + * ### Anchoring Demo + * + + + Home +
    +
    +
    +
    +
    + + angular.module('anchoringExample', ['ngAnimate', 'ngRoute']) + .config(['$routeProvider', function($routeProvider) { + $routeProvider.when('/', { + templateUrl: 'home.html', + controller: 'HomeController as home' + }); + $routeProvider.when('/profile/:id', { + templateUrl: 'profile.html', + controller: 'ProfileController as profile' + }); + }]) + .run(['$rootScope', function($rootScope) { + $rootScope.records = [ + { id:1, title: "Miss Beulah Roob" }, + { id:2, title: "Trent Morissette" }, + { id:3, title: "Miss Ava Pouros" }, + { id:4, title: "Rod Pouros" }, + { id:5, title: "Abdul Rice" }, + { id:6, title: "Laurie Rutherford Sr." }, + { id:7, title: "Nakia McLaughlin" }, + { id:8, title: "Jordon Blanda DVM" }, + { id:9, title: "Rhoda Hand" }, + { id:10, title: "Alexandrea Sauer" } + ]; + }]) + .controller('HomeController', [function() { + //empty + }]) + .controller('ProfileController', ['$rootScope', '$routeParams', function($rootScope, $routeParams) { + var index = parseInt($routeParams.id, 10); + var record = $rootScope.records[index - 1]; + + this.title = record.title; + this.id = record.id; + }]); + + +

    Welcome to the home page

    +

    Please click on an element

    + + {{ record.title }} + +
    + +
    + {{ profile.title }} +
    +
    + + .record { + display:block; + font-size:20px; + } + .profile { + background:black; + color:white; + font-size:100px; + } + .view-container { + position:relative; + } + .view-container > .view.ng-animate { + position:absolute; + top:0; + left:0; + width:100%; + min-height:500px; + } + .view.ng-enter, .view.ng-leave, + .record.ng-anchor { + transition:0.5s linear all; + } + .view.ng-enter { + transform:translateX(100%); + } + .view.ng-enter.ng-enter-active, .view.ng-leave { + transform:translateX(0%); + } + .view.ng-leave.ng-leave-active { + transform:translateX(-100%); + } + .record.ng-anchor-out { + background:red; + } + +
    + * + * ### How is the element transported? + * + * When an anchor animation occurs, ngAnimate will clone the starting element and position it exactly where the starting + * element is located on screen via absolute positioning. The cloned element will be placed inside of the root element + * of the application (where ng-app was defined) and all of the CSS classes of the starting element will be applied. The + * element will then animate into the `out` and `in` animations and will eventually reach the coordinates and match + * the dimensions of the destination element. During the entire animation a CSS class of `.ng-animate-shim` will be applied + * to both the starting and destination elements in order to hide them from being visible (the CSS styling for the class + * is: `visibility:hidden`). Once the anchor reaches its destination then it will be removed and the destination element + * will become visible since the shim class will be removed. + * + * ### How is the morphing handled? + * + * CSS Anchoring relies on transitions and keyframes and the internal code is intelligent enough to figure out + * what CSS classes differ between the starting element and the destination element. These different CSS classes + * will be added/removed on the anchor element and a transition will be applied (the transition that is provided + * in the anchor class). Long story short, ngAnimate will figure out what classes to add and remove which will + * make the transition of the element as smooth and automatic as possible. Be sure to use simple CSS classes that + * do not rely on DOM nesting structure so that the anchor element appears the same as the starting element (since + * the cloned element is placed inside of root element which is likely close to the body element). + * + * Note that if the root element is on the `` element then the cloned node will be placed inside of body. + * + * + * ## Using $animate in your directive code + * + * So far we've explored how to feed in animations into an Angular application, but how do we trigger animations within our own directives in our application? + * By injecting the `$animate` service into our directive code, we can trigger structural and class-based hooks which can then be consumed by animations. Let's + * imagine we have a greeting box that shows and hides itself when the data changes + * + * ```html + * Hi there + * ``` + * + * ```js + * ngModule.directive('greetingBox', ['$animate', function($animate) { + * return function(scope, element, attrs) { + * attrs.$observe('active', function(value) { + * value ? $animate.addClass(element, 'on') ? $animate.removeClass(element, 'on'); + * }); + * }); + * }]); + * ``` + * + * Now the `on` CSS class is added and removed on the greeting box component. Now if we add a CSS class on top of the greeting box element + * in our HTML code then we can trigger a CSS or JS animation to happen. + * + * ```css + * /* normally we would create a CSS class to reference on the element */ + * [greeting-box].on { transition:0.5s linear all; background:green; color:white; } + * ``` + * + * The `$animate` service contains a variety of other methods like `enter`, `leave`, `animate` and `setClass`. To learn more about what's + * possible be sure to visit the {@link ng.$animate $animate service API page}. + * + * + * ### Preventing Collisions With Third Party Libraries + * + * Some third-party frameworks place animation duration defaults across many element or className + * selectors in order to make their code small and reuseable. This can lead to issues with ngAnimate, which + * is expecting actual animations on these elements and has to wait for their completion. + * + * You can prevent this unwanted behavior by using a prefix on all your animation classes: + * + * ```css + * /* prefixed with animate- */ + * .animate-fade-add.animate-fade-add-active { + * transition:1s linear all; + * opacity:0; + * } + * ``` + * + * You then configure `$animate` to enforce this prefix: + * + * ```js + * $animateProvider.classNameFilter(/animate-/); + * ``` + * + * This also may provide your application with a speed boost since only specific elements containing CSS class prefix + * will be evaluated for animation when any DOM changes occur in the application. + * + * ## Callbacks and Promises + * + * When `$animate` is called it returns a promise that can be used to capture when the animation has ended. Therefore if we were to trigger + * an animation (within our directive code) then we can continue performing directive and scope related activities after the animation has + * ended by chaining onto the returned promise that animation method returns. + * + * ```js + * // somewhere within the depths of the directive + * $animate.enter(element, parent).then(function() { + * //the animation has completed + * }); + * ``` + * + * (Note that earlier versions of Angular prior to v1.4 required the promise code to be wrapped using `$scope.$apply(...)`. This is not the case + * anymore.) + * + * In addition to the animation promise, we can also make use of animation-related callbacks within our directives and controller code by registering + * an event listener using the `$animate` service. Let's say for example that an animation was triggered on our view + * routing controller to hook into that: + * + * ```js + * ngModule.controller('HomePageController', ['$animate', function($animate) { + * $animate.on('enter', ngViewElement, function(element) { + * // the animation for this route has completed + * }]); + * }]) + * ``` + * + * (Note that you will need to trigger a digest within the callback to get angular to notice any scope-related changes.) + */ + +/** + * @ngdoc service + * @name $animate + * @kind object + * + * @description + * The ngAnimate `$animate` service documentation is the same for the core `$animate` service. + * + * Click here {@link ng.$animate $animate to learn more about animations with `$animate`}. + */ +angular.module('ngAnimate', []) + .directive('ngAnimateChildren', $$AnimateChildrenDirective) + + .factory('$$rAFMutex', $$rAFMutexFactory) + .factory('$$rAFScheduler', $$rAFSchedulerFactory) + + .factory('$$AnimateRunner', $$AnimateRunnerFactory) + + .provider('$$animateQueue', $$AnimateQueueProvider) + .provider('$$animation', $$AnimationProvider) + + .provider('$animateCss', $AnimateCssProvider) + .provider('$$animateCssDriver', $$AnimateCssDriverProvider) + + .provider('$$animateJs', $$AnimateJsProvider) + .provider('$$animateJsDriver', $$AnimateJsDriverProvider); + + +})(window, window.angular); diff --git a/turtles/app/lib/bower_components/angular-animate/angular-animate.min.js b/turtles/app/lib/bower_components/angular-animate/angular-animate.min.js new file mode 100644 index 000000000..d6791a123 --- /dev/null +++ b/turtles/app/lib/bower_components/angular-animate/angular-animate.min.js @@ -0,0 +1,52 @@ +/* + AngularJS v1.4.0 + (c) 2010-2015 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(F,t,W){'use strict';function ua(a,b,c){if(!a)throw ngMinErr("areq",b||"?",c||"required");return a}function va(a,b){if(!a&&!b)return"";if(!a)return b;if(!b)return a;X(a)&&(a=a.join(" "));X(b)&&(b=b.join(" "));return a+" "+b}function Ea(a){var b={};a&&(a.to||a.from)&&(b.to=a.to,b.from=a.from);return b}function ba(a,b,c){var d="";a=X(a)?a:a&&U(a)&&a.length?a.split(/\s+/):[];u(a,function(a,s){a&&0=F&&b>=J&&(C=!0,h())}if(!K){var x,p=[],l=function(a){if(C)D&&a&&(D=!1,h());else if(D=!a,y.animationDuration)if(a=ma(k,D),D)m.push(a);else{var b=m,c=b.indexOf(a);0<=a&&b.splice(c,1)}},r=0< +U&&(y.transitionDuration&&0===T.transitionDuration||y.animationDuration&&0===T.animationDuration)&&Math.max(T.animationDelay,T.transitionDelay);r?n(b,Math.floor(r*U*1E3),!1):b();t.resume=function(){l(!0)};t.pause=function(){l(!1)}}}var k=A(a);c=ia(c);var m=[],r=a.attr("class"),v=Ea(c),K,D,C,p,t,H,F,J,G;if(0===c.duration||!l.animations&&!l.transitions)return x();var aa=c.event&&X(c.event)?c.event.join(" "):c.event,R="",N="";aa&&c.structural?R=ba(aa,"ng-",!0):aa&&(R=aa);c.addClass&&(N+=ba(c.addClass, +"-add"));c.removeClass&&(N.length&&(N+=" "),N+=ba(c.removeClass,"-remove"));c.applyClassesEarly&&N.length&&(B(a,c),N="");var Y=[R,N].join(" ").trim(),fa=r+" "+Y,W=ba(Y,"-active"),r=v.to&&0", + "license": "MIT", + "bugs": { + "url": "https://github.com/angular/angular.js/issues" + }, + "homepage": "http://angularjs.org" +} diff --git a/turtles/app/lib/bower_components/angular-bootstrap/.bower.json b/turtles/app/lib/bower_components/angular-bootstrap/.bower.json new file mode 100644 index 000000000..7fa81554d --- /dev/null +++ b/turtles/app/lib/bower_components/angular-bootstrap/.bower.json @@ -0,0 +1,32 @@ +{ + "author": { + "name": "https://github.com/angular-ui/bootstrap/graphs/contributors" + }, + "name": "angular-bootstrap", + "keywords": [ + "angular", + "angular-ui", + "bootstrap" + ], + "license": "MIT", + "ignore": [], + "description": "Native AngularJS (Angular) directives for Bootstrap.", + "version": "0.13.0", + "main": [ + "./ui-bootstrap-tpls.js" + ], + "dependencies": { + "angular": ">=1.3.0" + }, + "homepage": "https://github.com/angular-ui/bootstrap-bower", + "_release": "0.13.0", + "_resolution": { + "type": "version", + "tag": "0.13.0", + "commit": "a75d899addcafb73344b724bec647620adeebc9a" + }, + "_source": "git://github.com/angular-ui/bootstrap-bower.git", + "_target": "~0.13.0", + "_originalSource": "angular-bootstrap", + "_direct": true +} \ No newline at end of file diff --git a/turtles/app/lib/bower_components/angular-bootstrap/bower.json b/turtles/app/lib/bower_components/angular-bootstrap/bower.json new file mode 100644 index 000000000..ea65aadd5 --- /dev/null +++ b/turtles/app/lib/bower_components/angular-bootstrap/bower.json @@ -0,0 +1,19 @@ +{ + "author": { + "name": "https://github.com/angular-ui/bootstrap/graphs/contributors" + }, + "name": "angular-bootstrap", + "keywords": [ + "angular", + "angular-ui", + "bootstrap" + ], + "license": "MIT", + "ignore": [], + "description": "Native AngularJS (Angular) directives for Bootstrap.", + "version": "0.13.0", + "main": ["./ui-bootstrap-tpls.js"], + "dependencies": { + "angular": ">=1.3.0" + } +} diff --git a/turtles/app/lib/bower_components/angular-bootstrap/ui-bootstrap-csp.css b/turtles/app/lib/bower_components/angular-bootstrap/ui-bootstrap-csp.css new file mode 100644 index 000000000..d772f786d --- /dev/null +++ b/turtles/app/lib/bower_components/angular-bootstrap/ui-bootstrap-csp.css @@ -0,0 +1,6 @@ +/* Include this file in your html if you are using the CSP mode. */ + +.ng-animate.item:not(.left):not(.right) { + -webkit-transition: 0s ease-in-out left; + transition: 0s ease-in-out left +} \ No newline at end of file diff --git a/turtles/app/lib/bower_components/angular-bootstrap/ui-bootstrap-tpls.js b/turtles/app/lib/bower_components/angular-bootstrap/ui-bootstrap-tpls.js new file mode 100644 index 000000000..611966115 --- /dev/null +++ b/turtles/app/lib/bower_components/angular-bootstrap/ui-bootstrap-tpls.js @@ -0,0 +1,4840 @@ +/* + * angular-ui-bootstrap + * http://angular-ui.github.io/bootstrap/ + + * Version: 0.13.0 - 2015-05-02 + * License: MIT + */ +angular.module("ui.bootstrap", ["ui.bootstrap.tpls", "ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.transition","ui.bootstrap.typeahead"]); +angular.module("ui.bootstrap.tpls", ["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/carousel/carousel.html","template/carousel/slide.html","template/datepicker/datepicker.html","template/datepicker/day.html","template/datepicker/month.html","template/datepicker/popup.html","template/datepicker/year.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-popup.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/tooltip/tooltip-template-popup.html","template/popover/popover-template.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]); +angular.module('ui.bootstrap.collapse', []) + + .directive('collapse', ['$animate', function ($animate) { + + return { + link: function (scope, element, attrs) { + function expand() { + element.removeClass('collapse').addClass('collapsing'); + $animate.addClass(element, 'in', { + to: { height: element[0].scrollHeight + 'px' } + }).then(expandDone); + } + + function expandDone() { + element.removeClass('collapsing'); + element.css({height: 'auto'}); + } + + function collapse() { + element + // IMPORTANT: The height must be set before adding "collapsing" class. + // Otherwise, the browser attempts to animate from height 0 (in + // collapsing class) to the given height here. + .css({height: element[0].scrollHeight + 'px'}) + // initially all panel collapse have the collapse class, this removal + // prevents the animation from jumping to collapsed state + .removeClass('collapse') + .addClass('collapsing'); + + $animate.removeClass(element, 'in', { + to: {height: '0'} + }).then(collapseDone); + } + + function collapseDone() { + element.css({height: '0'}); // Required so that collapse works when animation is disabled + element.removeClass('collapsing'); + element.addClass('collapse'); + } + + scope.$watch(attrs.collapse, function (shouldCollapse) { + if (shouldCollapse) { + collapse(); + } else { + expand(); + } + }); + } + }; + }]); + +angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse']) + +.constant('accordionConfig', { + closeOthers: true +}) + +.controller('AccordionController', ['$scope', '$attrs', 'accordionConfig', function ($scope, $attrs, accordionConfig) { + + // This array keeps track of the accordion groups + this.groups = []; + + // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to + this.closeOthers = function(openGroup) { + var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers; + if ( closeOthers ) { + angular.forEach(this.groups, function (group) { + if ( group !== openGroup ) { + group.isOpen = false; + } + }); + } + }; + + // This is called from the accordion-group directive to add itself to the accordion + this.addGroup = function(groupScope) { + var that = this; + this.groups.push(groupScope); + + groupScope.$on('$destroy', function (event) { + that.removeGroup(groupScope); + }); + }; + + // This is called from the accordion-group directive when to remove itself + this.removeGroup = function(group) { + var index = this.groups.indexOf(group); + if ( index !== -1 ) { + this.groups.splice(index, 1); + } + }; + +}]) + +// The accordion directive simply sets up the directive controller +// and adds an accordion CSS class to itself element. +.directive('accordion', function () { + return { + restrict:'EA', + controller:'AccordionController', + transclude: true, + replace: false, + templateUrl: 'template/accordion/accordion.html' + }; +}) + +// The accordion-group directive indicates a block of html that will expand and collapse in an accordion +.directive('accordionGroup', function() { + return { + require:'^accordion', // We need this directive to be inside an accordion + restrict:'EA', + transclude:true, // It transcludes the contents of the directive into the template + replace: true, // The element containing the directive will be replaced with the template + templateUrl:'template/accordion/accordion-group.html', + scope: { + heading: '@', // Interpolate the heading attribute onto this scope + isOpen: '=?', + isDisabled: '=?' + }, + controller: function() { + this.setHeading = function(element) { + this.heading = element; + }; + }, + link: function(scope, element, attrs, accordionCtrl) { + accordionCtrl.addGroup(scope); + + scope.$watch('isOpen', function(value) { + if ( value ) { + accordionCtrl.closeOthers(scope); + } + }); + + scope.toggleOpen = function() { + if ( !scope.isDisabled ) { + scope.isOpen = !scope.isOpen; + } + }; + } + }; +}) + +// Use accordion-heading below an accordion-group to provide a heading containing HTML +// +// Heading containing HTML - +// +.directive('accordionHeading', function() { + return { + restrict: 'EA', + transclude: true, // Grab the contents to be used as the heading + template: '', // In effect remove this element! + replace: true, + require: '^accordionGroup', + link: function(scope, element, attr, accordionGroupCtrl, transclude) { + // Pass the heading to the accordion-group controller + // so that it can be transcluded into the right place in the template + // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat] + accordionGroupCtrl.setHeading(transclude(scope, angular.noop)); + } + }; +}) + +// Use in the accordion-group template to indicate where you want the heading to be transcluded +// You must provide the property on the accordion-group controller that will hold the transcluded element +//
    +// +// ... +//
    +.directive('accordionTransclude', function() { + return { + require: '^accordionGroup', + link: function(scope, element, attr, controller) { + scope.$watch(function() { return controller[attr.accordionTransclude]; }, function(heading) { + if ( heading ) { + element.html(''); + element.append(heading); + } + }); + } + }; +}) + +; + +angular.module('ui.bootstrap.alert', []) + +.controller('AlertController', ['$scope', '$attrs', function ($scope, $attrs) { + $scope.closeable = 'close' in $attrs; + this.close = $scope.close; +}]) + +.directive('alert', function () { + return { + restrict:'EA', + controller:'AlertController', + templateUrl:'template/alert/alert.html', + transclude:true, + replace:true, + scope: { + type: '@', + close: '&' + } + }; +}) + +.directive('dismissOnTimeout', ['$timeout', function($timeout) { + return { + require: 'alert', + link: function(scope, element, attrs, alertCtrl) { + $timeout(function(){ + alertCtrl.close(); + }, parseInt(attrs.dismissOnTimeout, 10)); + } + }; +}]); + +angular.module('ui.bootstrap.bindHtml', []) + + .directive('bindHtmlUnsafe', function () { + return function (scope, element, attr) { + element.addClass('ng-binding').data('$binding', attr.bindHtmlUnsafe); + scope.$watch(attr.bindHtmlUnsafe, function bindHtmlUnsafeWatchAction(value) { + element.html(value || ''); + }); + }; + }); +angular.module('ui.bootstrap.buttons', []) + +.constant('buttonConfig', { + activeClass: 'active', + toggleEvent: 'click' +}) + +.controller('ButtonsController', ['buttonConfig', function(buttonConfig) { + this.activeClass = buttonConfig.activeClass || 'active'; + this.toggleEvent = buttonConfig.toggleEvent || 'click'; +}]) + +.directive('btnRadio', function () { + return { + require: ['btnRadio', 'ngModel'], + controller: 'ButtonsController', + link: function (scope, element, attrs, ctrls) { + var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + //model -> UI + ngModelCtrl.$render = function () { + element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio))); + }; + + //ui->model + element.bind(buttonsCtrl.toggleEvent, function () { + var isActive = element.hasClass(buttonsCtrl.activeClass); + + if (!isActive || angular.isDefined(attrs.uncheckable)) { + scope.$apply(function () { + ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.btnRadio)); + ngModelCtrl.$render(); + }); + } + }); + } + }; +}) + +.directive('btnCheckbox', function () { + return { + require: ['btnCheckbox', 'ngModel'], + controller: 'ButtonsController', + link: function (scope, element, attrs, ctrls) { + var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + function getTrueValue() { + return getCheckboxValue(attrs.btnCheckboxTrue, true); + } + + function getFalseValue() { + return getCheckboxValue(attrs.btnCheckboxFalse, false); + } + + function getCheckboxValue(attributeValue, defaultValue) { + var val = scope.$eval(attributeValue); + return angular.isDefined(val) ? val : defaultValue; + } + + //model -> UI + ngModelCtrl.$render = function () { + element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue())); + }; + + //ui->model + element.bind(buttonsCtrl.toggleEvent, function () { + scope.$apply(function () { + ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue()); + ngModelCtrl.$render(); + }); + }); + } + }; +}); + +/** +* @ngdoc overview +* @name ui.bootstrap.carousel +* +* @description +* AngularJS version of an image carousel. +* +*/ +angular.module('ui.bootstrap.carousel', []) +.controller('CarouselController', ['$scope', '$interval', '$animate', function ($scope, $interval, $animate) { + var self = this, + slides = self.slides = $scope.slides = [], + currentIndex = -1, + currentInterval, isPlaying; + self.currentSlide = null; + + var destroyed = false; + /* direction: "prev" or "next" */ + self.select = $scope.select = function(nextSlide, direction) { + var nextIndex = self.indexOfSlide(nextSlide); + //Decide direction if it's not given + if (direction === undefined) { + direction = nextIndex > self.getCurrentIndex() ? 'next' : 'prev'; + } + if (nextSlide && nextSlide !== self.currentSlide) { + goNext(); + } + function goNext() { + // Scope has been destroyed, stop here. + if (destroyed) { return; } + + angular.extend(nextSlide, {direction: direction, active: true}); + angular.extend(self.currentSlide || {}, {direction: direction, active: false}); + if ($animate.enabled() && !$scope.noTransition && nextSlide.$element) { + $scope.$currentTransition = true; + nextSlide.$element.one('$animate:close', function closeFn() { + $scope.$currentTransition = null; + }); + } + + self.currentSlide = nextSlide; + currentIndex = nextIndex; + //every time you change slides, reset the timer + restartTimer(); + } + }; + $scope.$on('$destroy', function () { + destroyed = true; + }); + + function getSlideByIndex(index) { + if (angular.isUndefined(slides[index].index)) { + return slides[index]; + } + var i, len = slides.length; + for (i = 0; i < slides.length; ++i) { + if (slides[i].index == index) { + return slides[i]; + } + } + } + + self.getCurrentIndex = function() { + if (self.currentSlide && angular.isDefined(self.currentSlide.index)) { + return +self.currentSlide.index; + } + return currentIndex; + }; + + /* Allow outside people to call indexOf on slides array */ + self.indexOfSlide = function(slide) { + return angular.isDefined(slide.index) ? +slide.index : slides.indexOf(slide); + }; + + $scope.next = function() { + var newIndex = (self.getCurrentIndex() + 1) % slides.length; + + //Prevent this user-triggered transition from occurring if there is already one in progress + if (!$scope.$currentTransition) { + return self.select(getSlideByIndex(newIndex), 'next'); + } + }; + + $scope.prev = function() { + var newIndex = self.getCurrentIndex() - 1 < 0 ? slides.length - 1 : self.getCurrentIndex() - 1; + + //Prevent this user-triggered transition from occurring if there is already one in progress + if (!$scope.$currentTransition) { + return self.select(getSlideByIndex(newIndex), 'prev'); + } + }; + + $scope.isActive = function(slide) { + return self.currentSlide === slide; + }; + + $scope.$watch('interval', restartTimer); + $scope.$on('$destroy', resetTimer); + + function restartTimer() { + resetTimer(); + var interval = +$scope.interval; + if (!isNaN(interval) && interval > 0) { + currentInterval = $interval(timerFn, interval); + } + } + + function resetTimer() { + if (currentInterval) { + $interval.cancel(currentInterval); + currentInterval = null; + } + } + + function timerFn() { + var interval = +$scope.interval; + if (isPlaying && !isNaN(interval) && interval > 0) { + $scope.next(); + } else { + $scope.pause(); + } + } + + $scope.play = function() { + if (!isPlaying) { + isPlaying = true; + restartTimer(); + } + }; + $scope.pause = function() { + if (!$scope.noPause) { + isPlaying = false; + resetTimer(); + } + }; + + self.addSlide = function(slide, element) { + slide.$element = element; + slides.push(slide); + //if this is the first slide or the slide is set to active, select it + if(slides.length === 1 || slide.active) { + self.select(slides[slides.length-1]); + if (slides.length == 1) { + $scope.play(); + } + } else { + slide.active = false; + } + }; + + self.removeSlide = function(slide) { + if (angular.isDefined(slide.index)) { + slides.sort(function(a, b) { + return +a.index > +b.index; + }); + } + //get the index of the slide inside the carousel + var index = slides.indexOf(slide); + slides.splice(index, 1); + if (slides.length > 0 && slide.active) { + if (index >= slides.length) { + self.select(slides[index-1]); + } else { + self.select(slides[index]); + } + } else if (currentIndex > index) { + currentIndex--; + } + }; + +}]) + +/** + * @ngdoc directive + * @name ui.bootstrap.carousel.directive:carousel + * @restrict EA + * + * @description + * Carousel is the outer container for a set of image 'slides' to showcase. + * + * @param {number=} interval The time, in milliseconds, that it will take the carousel to go to the next slide. + * @param {boolean=} noTransition Whether to disable transitions on the carousel. + * @param {boolean=} noPause Whether to disable pausing on the carousel (by default, the carousel interval pauses on hover). + * + * @example + + + + + + + + + + + + + + + .carousel-indicators { + top: auto; + bottom: 15px; + } + + + */ +.directive('carousel', [function() { + return { + restrict: 'EA', + transclude: true, + replace: true, + controller: 'CarouselController', + require: 'carousel', + templateUrl: 'template/carousel/carousel.html', + scope: { + interval: '=', + noTransition: '=', + noPause: '=' + } + }; +}]) + +/** + * @ngdoc directive + * @name ui.bootstrap.carousel.directive:slide + * @restrict EA + * + * @description + * Creates a slide inside a {@link ui.bootstrap.carousel.directive:carousel carousel}. Must be placed as a child of a carousel element. + * + * @param {boolean=} active Model binding, whether or not this slide is currently active. + * @param {number=} index The index of the slide. The slides will be sorted by this parameter. + * + * @example + + +
    + + + + + + + Interval, in milliseconds: +
    Enter a negative number to stop the interval. +
    +
    + +function CarouselDemoCtrl($scope) { + $scope.myInterval = 5000; +} + + + .carousel-indicators { + top: auto; + bottom: 15px; + } + +
    +*/ + +.directive('slide', function() { + return { + require: '^carousel', + restrict: 'EA', + transclude: true, + replace: true, + templateUrl: 'template/carousel/slide.html', + scope: { + active: '=?', + index: '=?' + }, + link: function (scope, element, attrs, carouselCtrl) { + carouselCtrl.addSlide(scope, element); + //when the scope is destroyed then remove the slide from the current slides array + scope.$on('$destroy', function() { + carouselCtrl.removeSlide(scope); + }); + + scope.$watch('active', function(active) { + if (active) { + carouselCtrl.select(scope); + } + }); + } + }; +}) + +.animation('.item', [ + '$animate', +function ($animate) { + return { + beforeAddClass: function (element, className, done) { + // Due to transclusion, noTransition property is on parent's scope + if (className == 'active' && element.parent() && + !element.parent().scope().noTransition) { + var stopped = false; + var direction = element.isolateScope().direction; + var directionClass = direction == 'next' ? 'left' : 'right'; + element.addClass(direction); + $animate.addClass(element, directionClass).then(function () { + if (!stopped) { + element.removeClass(directionClass + ' ' + direction); + } + done(); + }); + + return function () { + stopped = true; + }; + } + done(); + }, + beforeRemoveClass: function (element, className, done) { + // Due to transclusion, noTransition property is on parent's scope + if (className == 'active' && element.parent() && + !element.parent().scope().noTransition) { + var stopped = false; + var direction = element.isolateScope().direction; + var directionClass = direction == 'next' ? 'left' : 'right'; + $animate.addClass(element, directionClass).then(function () { + if (!stopped) { + element.removeClass(directionClass); + } + done(); + }); + return function () { + stopped = true; + }; + } + done(); + } + }; + +}]) + + +; + +angular.module('ui.bootstrap.dateparser', []) + +.service('dateParser', ['$locale', 'orderByFilter', function($locale, orderByFilter) { + // Pulled from https://github.com/mbostock/d3/blob/master/src/format/requote.js + var SPECIAL_CHARACTERS_REGEXP = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; + + this.parsers = {}; + + var formatCodeToRegex = { + 'yyyy': { + regex: '\\d{4}', + apply: function(value) { this.year = +value; } + }, + 'yy': { + regex: '\\d{2}', + apply: function(value) { this.year = +value + 2000; } + }, + 'y': { + regex: '\\d{1,4}', + apply: function(value) { this.year = +value; } + }, + 'MMMM': { + regex: $locale.DATETIME_FORMATS.MONTH.join('|'), + apply: function(value) { this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); } + }, + 'MMM': { + regex: $locale.DATETIME_FORMATS.SHORTMONTH.join('|'), + apply: function(value) { this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); } + }, + 'MM': { + regex: '0[1-9]|1[0-2]', + apply: function(value) { this.month = value - 1; } + }, + 'M': { + regex: '[1-9]|1[0-2]', + apply: function(value) { this.month = value - 1; } + }, + 'dd': { + regex: '[0-2][0-9]{1}|3[0-1]{1}', + apply: function(value) { this.date = +value; } + }, + 'd': { + regex: '[1-2]?[0-9]{1}|3[0-1]{1}', + apply: function(value) { this.date = +value; } + }, + 'EEEE': { + regex: $locale.DATETIME_FORMATS.DAY.join('|') + }, + 'EEE': { + regex: $locale.DATETIME_FORMATS.SHORTDAY.join('|') + }, + 'HH': { + regex: '(?:0|1)[0-9]|2[0-3]', + apply: function(value) { this.hours = +value; } + }, + 'H': { + regex: '1?[0-9]|2[0-3]', + apply: function(value) { this.hours = +value; } + }, + 'mm': { + regex: '[0-5][0-9]', + apply: function(value) { this.minutes = +value; } + }, + 'm': { + regex: '[0-9]|[1-5][0-9]', + apply: function(value) { this.minutes = +value; } + }, + 'sss': { + regex: '[0-9][0-9][0-9]', + apply: function(value) { this.milliseconds = +value; } + }, + 'ss': { + regex: '[0-5][0-9]', + apply: function(value) { this.seconds = +value; } + }, + 's': { + regex: '[0-9]|[1-5][0-9]', + apply: function(value) { this.seconds = +value; } + } + }; + + function createParser(format) { + var map = [], regex = format.split(''); + + angular.forEach(formatCodeToRegex, function(data, code) { + var index = format.indexOf(code); + + if (index > -1) { + format = format.split(''); + + regex[index] = '(' + data.regex + ')'; + format[index] = '$'; // Custom symbol to define consumed part of format + for (var i = index + 1, n = index + code.length; i < n; i++) { + regex[i] = ''; + format[i] = '$'; + } + format = format.join(''); + + map.push({ index: index, apply: data.apply }); + } + }); + + return { + regex: new RegExp('^' + regex.join('') + '$'), + map: orderByFilter(map, 'index') + }; + } + + this.parse = function(input, format, baseDate) { + if ( !angular.isString(input) || !format ) { + return input; + } + + format = $locale.DATETIME_FORMATS[format] || format; + format = format.replace(SPECIAL_CHARACTERS_REGEXP, '\\$&'); + + if ( !this.parsers[format] ) { + this.parsers[format] = createParser(format); + } + + var parser = this.parsers[format], + regex = parser.regex, + map = parser.map, + results = input.match(regex); + + if ( results && results.length ) { + var fields, dt; + if (baseDate) { + fields = { + year: baseDate.getFullYear(), + month: baseDate.getMonth(), + date: baseDate.getDate(), + hours: baseDate.getHours(), + minutes: baseDate.getMinutes(), + seconds: baseDate.getSeconds(), + milliseconds: baseDate.getMilliseconds() + }; + } else { + fields = { year: 1900, month: 0, date: 1, hours: 0, minutes: 0, seconds: 0, milliseconds: 0 }; + } + + for( var i = 1, n = results.length; i < n; i++ ) { + var mapper = map[i-1]; + if ( mapper.apply ) { + mapper.apply.call(fields, results[i]); + } + } + + if ( isValid(fields.year, fields.month, fields.date) ) { + dt = new Date(fields.year, fields.month, fields.date, fields.hours, fields.minutes, fields.seconds, + fields.milliseconds || 0); + } + + return dt; + } + }; + + // Check if date is valid for specific month (and year for February). + // Month: 0 = Jan, 1 = Feb, etc + function isValid(year, month, date) { + if (date < 1) { + return false; + } + + if ( month === 1 && date > 28) { + return date === 29 && ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0); + } + + if ( month === 3 || month === 5 || month === 8 || month === 10) { + return date < 31; + } + + return true; + } +}]); + +angular.module('ui.bootstrap.position', []) + +/** + * A set of utility methods that can be use to retrieve position of DOM elements. + * It is meant to be used where we need to absolute-position DOM elements in + * relation to other, existing elements (this is the case for tooltips, popovers, + * typeahead suggestions etc.). + */ + .factory('$position', ['$document', '$window', function ($document, $window) { + + function getStyle(el, cssprop) { + if (el.currentStyle) { //IE + return el.currentStyle[cssprop]; + } else if ($window.getComputedStyle) { + return $window.getComputedStyle(el)[cssprop]; + } + // finally try and get inline style + return el.style[cssprop]; + } + + /** + * Checks if a given element is statically positioned + * @param element - raw DOM element + */ + function isStaticPositioned(element) { + return (getStyle(element, 'position') || 'static' ) === 'static'; + } + + /** + * returns the closest, non-statically positioned parentOffset of a given element + * @param element + */ + var parentOffsetEl = function (element) { + var docDomEl = $document[0]; + var offsetParent = element.offsetParent || docDomEl; + while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent) ) { + offsetParent = offsetParent.offsetParent; + } + return offsetParent || docDomEl; + }; + + return { + /** + * Provides read-only equivalent of jQuery's position function: + * http://api.jquery.com/position/ + */ + position: function (element) { + var elBCR = this.offset(element); + var offsetParentBCR = { top: 0, left: 0 }; + var offsetParentEl = parentOffsetEl(element[0]); + if (offsetParentEl != $document[0]) { + offsetParentBCR = this.offset(angular.element(offsetParentEl)); + offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop; + offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft; + } + + var boundingClientRect = element[0].getBoundingClientRect(); + return { + width: boundingClientRect.width || element.prop('offsetWidth'), + height: boundingClientRect.height || element.prop('offsetHeight'), + top: elBCR.top - offsetParentBCR.top, + left: elBCR.left - offsetParentBCR.left + }; + }, + + /** + * Provides read-only equivalent of jQuery's offset function: + * http://api.jquery.com/offset/ + */ + offset: function (element) { + var boundingClientRect = element[0].getBoundingClientRect(); + return { + width: boundingClientRect.width || element.prop('offsetWidth'), + height: boundingClientRect.height || element.prop('offsetHeight'), + top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop), + left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft) + }; + }, + + /** + * Provides coordinates for the targetEl in relation to hostEl + */ + positionElements: function (hostEl, targetEl, positionStr, appendToBody) { + + var positionStrParts = positionStr.split('-'); + var pos0 = positionStrParts[0], pos1 = positionStrParts[1] || 'center'; + + var hostElPos, + targetElWidth, + targetElHeight, + targetElPos; + + hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl); + + targetElWidth = targetEl.prop('offsetWidth'); + targetElHeight = targetEl.prop('offsetHeight'); + + var shiftWidth = { + center: function () { + return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2; + }, + left: function () { + return hostElPos.left; + }, + right: function () { + return hostElPos.left + hostElPos.width; + } + }; + + var shiftHeight = { + center: function () { + return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2; + }, + top: function () { + return hostElPos.top; + }, + bottom: function () { + return hostElPos.top + hostElPos.height; + } + }; + + switch (pos0) { + case 'right': + targetElPos = { + top: shiftHeight[pos1](), + left: shiftWidth[pos0]() + }; + break; + case 'left': + targetElPos = { + top: shiftHeight[pos1](), + left: hostElPos.left - targetElWidth + }; + break; + case 'bottom': + targetElPos = { + top: shiftHeight[pos0](), + left: shiftWidth[pos1]() + }; + break; + default: + targetElPos = { + top: hostElPos.top - targetElHeight, + left: shiftWidth[pos1]() + }; + break; + } + + return targetElPos; + } + }; + }]); + +angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootstrap.position']) + +.constant('datepickerConfig', { + formatDay: 'dd', + formatMonth: 'MMMM', + formatYear: 'yyyy', + formatDayHeader: 'EEE', + formatDayTitle: 'MMMM yyyy', + formatMonthTitle: 'yyyy', + datepickerMode: 'day', + minMode: 'day', + maxMode: 'year', + showWeeks: true, + startingDay: 0, + yearRange: 20, + minDate: null, + maxDate: null, + shortcutPropagation: false +}) + +.controller('DatepickerController', ['$scope', '$attrs', '$parse', '$interpolate', '$timeout', '$log', 'dateFilter', 'datepickerConfig', function($scope, $attrs, $parse, $interpolate, $timeout, $log, dateFilter, datepickerConfig) { + var self = this, + ngModelCtrl = { $setViewValue: angular.noop }; // nullModelCtrl; + + // Modes chain + this.modes = ['day', 'month', 'year']; + + // Configuration attributes + angular.forEach(['formatDay', 'formatMonth', 'formatYear', 'formatDayHeader', 'formatDayTitle', 'formatMonthTitle', + 'minMode', 'maxMode', 'showWeeks', 'startingDay', 'yearRange', 'shortcutPropagation'], function( key, index ) { + self[key] = angular.isDefined($attrs[key]) ? (index < 8 ? $interpolate($attrs[key])($scope.$parent) : $scope.$parent.$eval($attrs[key])) : datepickerConfig[key]; + }); + + // Watchable date attributes + angular.forEach(['minDate', 'maxDate'], function( key ) { + if ( $attrs[key] ) { + $scope.$parent.$watch($parse($attrs[key]), function(value) { + self[key] = value ? new Date(value) : null; + self.refreshView(); + }); + } else { + self[key] = datepickerConfig[key] ? new Date(datepickerConfig[key]) : null; + } + }); + + $scope.datepickerMode = $scope.datepickerMode || datepickerConfig.datepickerMode; + $scope.maxMode = self.maxMode; + $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000); + + if(angular.isDefined($attrs.initDate)) { + this.activeDate = $scope.$parent.$eval($attrs.initDate) || new Date(); + $scope.$parent.$watch($attrs.initDate, function(initDate){ + if(initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)){ + self.activeDate = initDate; + self.refreshView(); + } + }); + } else { + this.activeDate = new Date(); + } + + $scope.isActive = function(dateObject) { + if (self.compare(dateObject.date, self.activeDate) === 0) { + $scope.activeDateId = dateObject.uid; + return true; + } + return false; + }; + + this.init = function( ngModelCtrl_ ) { + ngModelCtrl = ngModelCtrl_; + + ngModelCtrl.$render = function() { + self.render(); + }; + }; + + this.render = function() { + if ( ngModelCtrl.$viewValue ) { + var date = new Date( ngModelCtrl.$viewValue ), + isValid = !isNaN(date); + + if ( isValid ) { + this.activeDate = date; + } else { + $log.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); + } + ngModelCtrl.$setValidity('date', isValid); + } + this.refreshView(); + }; + + this.refreshView = function() { + if ( this.element ) { + this._refreshView(); + + var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; + ngModelCtrl.$setValidity('date-disabled', !date || (this.element && !this.isDisabled(date))); + } + }; + + this.createDateObject = function(date, format) { + var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; + return { + date: date, + label: dateFilter(date, format), + selected: model && this.compare(date, model) === 0, + disabled: this.isDisabled(date), + current: this.compare(date, new Date()) === 0, + customClass: this.customClass(date) + }; + }; + + this.isDisabled = function( date ) { + return ((this.minDate && this.compare(date, this.minDate) < 0) || (this.maxDate && this.compare(date, this.maxDate) > 0) || ($attrs.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode}))); + }; + + this.customClass = function( date ) { + return $scope.customClass({date: date, mode: $scope.datepickerMode}); + }; + + // Split array into smaller arrays + this.split = function(arr, size) { + var arrays = []; + while (arr.length > 0) { + arrays.push(arr.splice(0, size)); + } + return arrays; + }; + + $scope.select = function( date ) { + if ( $scope.datepickerMode === self.minMode ) { + var dt = ngModelCtrl.$viewValue ? new Date( ngModelCtrl.$viewValue ) : new Date(0, 0, 0, 0, 0, 0, 0); + dt.setFullYear( date.getFullYear(), date.getMonth(), date.getDate() ); + ngModelCtrl.$setViewValue( dt ); + ngModelCtrl.$render(); + } else { + self.activeDate = date; + $scope.datepickerMode = self.modes[ self.modes.indexOf( $scope.datepickerMode ) - 1 ]; + } + }; + + $scope.move = function( direction ) { + var year = self.activeDate.getFullYear() + direction * (self.step.years || 0), + month = self.activeDate.getMonth() + direction * (self.step.months || 0); + self.activeDate.setFullYear(year, month, 1); + self.refreshView(); + }; + + $scope.toggleMode = function( direction ) { + direction = direction || 1; + + if (($scope.datepickerMode === self.maxMode && direction === 1) || ($scope.datepickerMode === self.minMode && direction === -1)) { + return; + } + + $scope.datepickerMode = self.modes[ self.modes.indexOf( $scope.datepickerMode ) + direction ]; + }; + + // Key event mapper + $scope.keys = { 13:'enter', 32:'space', 33:'pageup', 34:'pagedown', 35:'end', 36:'home', 37:'left', 38:'up', 39:'right', 40:'down' }; + + var focusElement = function() { + $timeout(function() { + self.element[0].focus(); + }, 0 , false); + }; + + // Listen for focus requests from popup directive + $scope.$on('datepicker.focus', focusElement); + + $scope.keydown = function( evt ) { + var key = $scope.keys[evt.which]; + + if ( !key || evt.shiftKey || evt.altKey ) { + return; + } + + evt.preventDefault(); + if(!self.shortcutPropagation){ + evt.stopPropagation(); + } + + if (key === 'enter' || key === 'space') { + if ( self.isDisabled(self.activeDate)) { + return; // do nothing + } + $scope.select(self.activeDate); + focusElement(); + } else if (evt.ctrlKey && (key === 'up' || key === 'down')) { + $scope.toggleMode(key === 'up' ? 1 : -1); + focusElement(); + } else { + self.handleKeyDown(key, evt); + self.refreshView(); + } + }; +}]) + +.directive( 'datepicker', function () { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/datepicker/datepicker.html', + scope: { + datepickerMode: '=?', + dateDisabled: '&', + customClass: '&', + shortcutPropagation: '&?' + }, + require: ['datepicker', '?^ngModel'], + controller: 'DatepickerController', + link: function(scope, element, attrs, ctrls) { + var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + if ( ngModelCtrl ) { + datepickerCtrl.init( ngModelCtrl ); + } + } + }; +}) + +.directive('daypicker', ['dateFilter', function (dateFilter) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/datepicker/day.html', + require: '^datepicker', + link: function(scope, element, attrs, ctrl) { + scope.showWeeks = ctrl.showWeeks; + + ctrl.step = { months: 1 }; + ctrl.element = element; + + var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + function getDaysInMonth( year, month ) { + return ((month === 1) && (year % 4 === 0) && ((year % 100 !== 0) || (year % 400 === 0))) ? 29 : DAYS_IN_MONTH[month]; + } + + function getDates(startDate, n) { + var dates = new Array(n), current = new Date(startDate), i = 0; + current.setHours(12); // Prevent repeated dates because of timezone bug + while ( i < n ) { + dates[i++] = new Date(current); + current.setDate( current.getDate() + 1 ); + } + return dates; + } + + ctrl._refreshView = function() { + var year = ctrl.activeDate.getFullYear(), + month = ctrl.activeDate.getMonth(), + firstDayOfMonth = new Date(year, month, 1), + difference = ctrl.startingDay - firstDayOfMonth.getDay(), + numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : - difference, + firstDate = new Date(firstDayOfMonth); + + if ( numDisplayedFromPreviousMonth > 0 ) { + firstDate.setDate( - numDisplayedFromPreviousMonth + 1 ); + } + + // 42 is the number of days on a six-month calendar + var days = getDates(firstDate, 42); + for (var i = 0; i < 42; i ++) { + days[i] = angular.extend(ctrl.createDateObject(days[i], ctrl.formatDay), { + secondary: days[i].getMonth() !== month, + uid: scope.uniqueId + '-' + i + }); + } + + scope.labels = new Array(7); + for (var j = 0; j < 7; j++) { + scope.labels[j] = { + abbr: dateFilter(days[j].date, ctrl.formatDayHeader), + full: dateFilter(days[j].date, 'EEEE') + }; + } + + scope.title = dateFilter(ctrl.activeDate, ctrl.formatDayTitle); + scope.rows = ctrl.split(days, 7); + + if ( scope.showWeeks ) { + scope.weekNumbers = []; + var thursdayIndex = (4 + 7 - ctrl.startingDay) % 7, + numWeeks = scope.rows.length; + for (var curWeek = 0; curWeek < numWeeks; curWeek++) { + scope.weekNumbers.push( + getISO8601WeekNumber( scope.rows[curWeek][thursdayIndex].date )); + } + } + }; + + ctrl.compare = function(date1, date2) { + return (new Date( date1.getFullYear(), date1.getMonth(), date1.getDate() ) - new Date( date2.getFullYear(), date2.getMonth(), date2.getDate() ) ); + }; + + function getISO8601WeekNumber(date) { + var checkDate = new Date(date); + checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday + var time = checkDate.getTime(); + checkDate.setMonth(0); // Compare with Jan 1 + checkDate.setDate(1); + return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; + } + + ctrl.handleKeyDown = function( key, evt ) { + var date = ctrl.activeDate.getDate(); + + if (key === 'left') { + date = date - 1; // up + } else if (key === 'up') { + date = date - 7; // down + } else if (key === 'right') { + date = date + 1; // down + } else if (key === 'down') { + date = date + 7; + } else if (key === 'pageup' || key === 'pagedown') { + var month = ctrl.activeDate.getMonth() + (key === 'pageup' ? - 1 : 1); + ctrl.activeDate.setMonth(month, 1); + date = Math.min(getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()), date); + } else if (key === 'home') { + date = 1; + } else if (key === 'end') { + date = getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()); + } + ctrl.activeDate.setDate(date); + }; + + ctrl.refreshView(); + } + }; +}]) + +.directive('monthpicker', ['dateFilter', function (dateFilter) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/datepicker/month.html', + require: '^datepicker', + link: function(scope, element, attrs, ctrl) { + ctrl.step = { years: 1 }; + ctrl.element = element; + + ctrl._refreshView = function() { + var months = new Array(12), + year = ctrl.activeDate.getFullYear(); + + for ( var i = 0; i < 12; i++ ) { + months[i] = angular.extend(ctrl.createDateObject(new Date(year, i, 1), ctrl.formatMonth), { + uid: scope.uniqueId + '-' + i + }); + } + + scope.title = dateFilter(ctrl.activeDate, ctrl.formatMonthTitle); + scope.rows = ctrl.split(months, 3); + }; + + ctrl.compare = function(date1, date2) { + return new Date( date1.getFullYear(), date1.getMonth() ) - new Date( date2.getFullYear(), date2.getMonth() ); + }; + + ctrl.handleKeyDown = function( key, evt ) { + var date = ctrl.activeDate.getMonth(); + + if (key === 'left') { + date = date - 1; // up + } else if (key === 'up') { + date = date - 3; // down + } else if (key === 'right') { + date = date + 1; // down + } else if (key === 'down') { + date = date + 3; + } else if (key === 'pageup' || key === 'pagedown') { + var year = ctrl.activeDate.getFullYear() + (key === 'pageup' ? - 1 : 1); + ctrl.activeDate.setFullYear(year); + } else if (key === 'home') { + date = 0; + } else if (key === 'end') { + date = 11; + } + ctrl.activeDate.setMonth(date); + }; + + ctrl.refreshView(); + } + }; +}]) + +.directive('yearpicker', ['dateFilter', function (dateFilter) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/datepicker/year.html', + require: '^datepicker', + link: function(scope, element, attrs, ctrl) { + var range = ctrl.yearRange; + + ctrl.step = { years: range }; + ctrl.element = element; + + function getStartingYear( year ) { + return parseInt((year - 1) / range, 10) * range + 1; + } + + ctrl._refreshView = function() { + var years = new Array(range); + + for ( var i = 0, start = getStartingYear(ctrl.activeDate.getFullYear()); i < range; i++ ) { + years[i] = angular.extend(ctrl.createDateObject(new Date(start + i, 0, 1), ctrl.formatYear), { + uid: scope.uniqueId + '-' + i + }); + } + + scope.title = [years[0].label, years[range - 1].label].join(' - '); + scope.rows = ctrl.split(years, 5); + }; + + ctrl.compare = function(date1, date2) { + return date1.getFullYear() - date2.getFullYear(); + }; + + ctrl.handleKeyDown = function( key, evt ) { + var date = ctrl.activeDate.getFullYear(); + + if (key === 'left') { + date = date - 1; // up + } else if (key === 'up') { + date = date - 5; // down + } else if (key === 'right') { + date = date + 1; // down + } else if (key === 'down') { + date = date + 5; + } else if (key === 'pageup' || key === 'pagedown') { + date += (key === 'pageup' ? - 1 : 1) * ctrl.step.years; + } else if (key === 'home') { + date = getStartingYear( ctrl.activeDate.getFullYear() ); + } else if (key === 'end') { + date = getStartingYear( ctrl.activeDate.getFullYear() ) + range - 1; + } + ctrl.activeDate.setFullYear(date); + }; + + ctrl.refreshView(); + } + }; +}]) + +.constant('datepickerPopupConfig', { + datepickerPopup: 'yyyy-MM-dd', + html5Types: { + date: 'yyyy-MM-dd', + 'datetime-local': 'yyyy-MM-ddTHH:mm:ss.sss', + 'month': 'yyyy-MM' + }, + currentText: 'Today', + clearText: 'Clear', + closeText: 'Done', + closeOnDateSelection: true, + appendToBody: false, + showButtonBar: true +}) + +.directive('datepickerPopup', ['$compile', '$parse', '$document', '$position', 'dateFilter', 'dateParser', 'datepickerPopupConfig', +function ($compile, $parse, $document, $position, dateFilter, dateParser, datepickerPopupConfig) { + return { + restrict: 'EA', + require: 'ngModel', + scope: { + isOpen: '=?', + currentText: '@', + clearText: '@', + closeText: '@', + dateDisabled: '&', + customClass: '&' + }, + link: function(scope, element, attrs, ngModel) { + var dateFormat, + closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? scope.$parent.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection, + appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? scope.$parent.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody; + + scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? scope.$parent.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar; + + scope.getText = function( key ) { + return scope[key + 'Text'] || datepickerPopupConfig[key + 'Text']; + }; + + var isHtml5DateInput = false; + if (datepickerPopupConfig.html5Types[attrs.type]) { + dateFormat = datepickerPopupConfig.html5Types[attrs.type]; + isHtml5DateInput = true; + } else { + dateFormat = attrs.datepickerPopup || datepickerPopupConfig.datepickerPopup; + attrs.$observe('datepickerPopup', function(value, oldValue) { + var newDateFormat = value || datepickerPopupConfig.datepickerPopup; + // Invalidate the $modelValue to ensure that formatters re-run + // FIXME: Refactor when PR is merged: https://github.com/angular/angular.js/pull/10764 + if (newDateFormat !== dateFormat) { + dateFormat = newDateFormat; + ngModel.$modelValue = null; + + if (!dateFormat) { + throw new Error('datepickerPopup must have a date format specified.'); + } + } + }); + } + + if (!dateFormat) { + throw new Error('datepickerPopup must have a date format specified.'); + } + + if (isHtml5DateInput && attrs.datepickerPopup) { + throw new Error('HTML5 date input types do not support custom formats.'); + } + + // popup element used to display calendar + var popupEl = angular.element('
    '); + popupEl.attr({ + 'ng-model': 'date', + 'ng-change': 'dateSelection()' + }); + + function cameltoDash( string ){ + return string.replace(/([A-Z])/g, function($1) { return '-' + $1.toLowerCase(); }); + } + + // datepicker element + var datepickerEl = angular.element(popupEl.children()[0]); + if (isHtml5DateInput) { + if (attrs.type == 'month') { + datepickerEl.attr('datepicker-mode', '"month"'); + datepickerEl.attr('min-mode', 'month'); + } + } + + if ( attrs.datepickerOptions ) { + var options = scope.$parent.$eval(attrs.datepickerOptions); + if(options.initDate) { + scope.initDate = options.initDate; + datepickerEl.attr( 'init-date', 'initDate' ); + delete options.initDate; + } + angular.forEach(options, function( value, option ) { + datepickerEl.attr( cameltoDash(option), value ); + }); + } + + scope.watchData = {}; + angular.forEach(['minDate', 'maxDate', 'datepickerMode', 'initDate', 'shortcutPropagation'], function( key ) { + if ( attrs[key] ) { + var getAttribute = $parse(attrs[key]); + scope.$parent.$watch(getAttribute, function(value){ + scope.watchData[key] = value; + }); + datepickerEl.attr(cameltoDash(key), 'watchData.' + key); + + // Propagate changes from datepicker to outside + if ( key === 'datepickerMode' ) { + var setAttribute = getAttribute.assign; + scope.$watch('watchData.' + key, function(value, oldvalue) { + if ( value !== oldvalue ) { + setAttribute(scope.$parent, value); + } + }); + } + } + }); + if (attrs.dateDisabled) { + datepickerEl.attr('date-disabled', 'dateDisabled({ date: date, mode: mode })'); + } + + if (attrs.showWeeks) { + datepickerEl.attr('show-weeks', attrs.showWeeks); + } + + if (attrs.customClass){ + datepickerEl.attr('custom-class', 'customClass({ date: date, mode: mode })'); + } + + function parseDate(viewValue) { + if (angular.isNumber(viewValue)) { + // presumably timestamp to date object + viewValue = new Date(viewValue); + } + + if (!viewValue) { + return null; + } else if (angular.isDate(viewValue) && !isNaN(viewValue)) { + return viewValue; + } else if (angular.isString(viewValue)) { + var date = dateParser.parse(viewValue, dateFormat, scope.date) || new Date(viewValue); + if (isNaN(date)) { + return undefined; + } else { + return date; + } + } else { + return undefined; + } + } + + function validator(modelValue, viewValue) { + var value = modelValue || viewValue; + if (angular.isNumber(value)) { + value = new Date(value); + } + if (!value) { + return true; + } else if (angular.isDate(value) && !isNaN(value)) { + return true; + } else if (angular.isString(value)) { + var date = dateParser.parse(value, dateFormat) || new Date(value); + return !isNaN(date); + } else { + return false; + } + } + + if (!isHtml5DateInput) { + // Internal API to maintain the correct ng-invalid-[key] class + ngModel.$$parserName = 'date'; + ngModel.$validators.date = validator; + ngModel.$parsers.unshift(parseDate); + ngModel.$formatters.push(function (value) { + scope.date = value; + return ngModel.$isEmpty(value) ? value : dateFilter(value, dateFormat); + }); + } + else { + ngModel.$formatters.push(function (value) { + scope.date = value; + return value; + }); + } + + // Inner change + scope.dateSelection = function(dt) { + if (angular.isDefined(dt)) { + scope.date = dt; + } + var date = scope.date ? dateFilter(scope.date, dateFormat) : ''; + element.val(date); + ngModel.$setViewValue(date); + + if ( closeOnDateSelection ) { + scope.isOpen = false; + element[0].focus(); + } + }; + + // Detect changes in the view from the text box + ngModel.$viewChangeListeners.push(function () { + scope.date = dateParser.parse(ngModel.$viewValue, dateFormat, scope.date) || new Date(ngModel.$viewValue); + }); + + var documentClickBind = function(event) { + if (scope.isOpen && event.target !== element[0]) { + scope.$apply(function() { + scope.isOpen = false; + }); + } + }; + + var keydown = function(evt, noApply) { + scope.keydown(evt); + }; + element.bind('keydown', keydown); + + scope.keydown = function(evt) { + if (evt.which === 27) { + evt.preventDefault(); + if (scope.isOpen) { + evt.stopPropagation(); + } + scope.close(); + } else if (evt.which === 40 && !scope.isOpen) { + scope.isOpen = true; + } + }; + + scope.$watch('isOpen', function(value) { + if (value) { + scope.$broadcast('datepicker.focus'); + scope.position = appendToBody ? $position.offset(element) : $position.position(element); + scope.position.top = scope.position.top + element.prop('offsetHeight'); + + $document.bind('click', documentClickBind); + } else { + $document.unbind('click', documentClickBind); + } + }); + + scope.select = function( date ) { + if (date === 'today') { + var today = new Date(); + if (angular.isDate(scope.date)) { + date = new Date(scope.date); + date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate()); + } else { + date = new Date(today.setHours(0, 0, 0, 0)); + } + } + scope.dateSelection( date ); + }; + + scope.close = function() { + scope.isOpen = false; + element[0].focus(); + }; + + var $popup = $compile(popupEl)(scope); + // Prevent jQuery cache memory leak (template is now redundant after linking) + popupEl.remove(); + + if ( appendToBody ) { + $document.find('body').append($popup); + } else { + element.after($popup); + } + + scope.$on('$destroy', function() { + $popup.remove(); + element.unbind('keydown', keydown); + $document.unbind('click', documentClickBind); + }); + } + }; +}]) + +.directive('datepickerPopupWrap', function() { + return { + restrict:'EA', + replace: true, + transclude: true, + templateUrl: 'template/datepicker/popup.html', + link:function (scope, element, attrs) { + element.bind('click', function(event) { + event.preventDefault(); + event.stopPropagation(); + }); + } + }; +}); + +angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) + +.constant('dropdownConfig', { + openClass: 'open' +}) + +.service('dropdownService', ['$document', '$rootScope', function($document, $rootScope) { + var openScope = null; + + this.open = function( dropdownScope ) { + if ( !openScope ) { + $document.bind('click', closeDropdown); + $document.bind('keydown', escapeKeyBind); + } + + if ( openScope && openScope !== dropdownScope ) { + openScope.isOpen = false; + } + + openScope = dropdownScope; + }; + + this.close = function( dropdownScope ) { + if ( openScope === dropdownScope ) { + openScope = null; + $document.unbind('click', closeDropdown); + $document.unbind('keydown', escapeKeyBind); + } + }; + + var closeDropdown = function( evt ) { + // This method may still be called during the same mouse event that + // unbound this event handler. So check openScope before proceeding. + if (!openScope) { return; } + + if( evt && openScope.getAutoClose() === 'disabled' ) { return ; } + + var toggleElement = openScope.getToggleElement(); + if ( evt && toggleElement && toggleElement[0].contains(evt.target) ) { + return; + } + + var $element = openScope.getElement(); + if( evt && openScope.getAutoClose() === 'outsideClick' && $element && $element[0].contains(evt.target) ) { + return; + } + + openScope.isOpen = false; + + if (!$rootScope.$$phase) { + openScope.$apply(); + } + }; + + var escapeKeyBind = function( evt ) { + if ( evt.which === 27 ) { + openScope.focusToggleElement(); + closeDropdown(); + } + }; +}]) + +.controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', '$position', '$document', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate, $position, $document) { + var self = this, + scope = $scope.$new(), // create a child scope so we are not polluting original one + openClass = dropdownConfig.openClass, + getIsOpen, + setIsOpen = angular.noop, + toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop, + appendToBody = false; + + this.init = function( element ) { + self.$element = element; + + if ( $attrs.isOpen ) { + getIsOpen = $parse($attrs.isOpen); + setIsOpen = getIsOpen.assign; + + $scope.$watch(getIsOpen, function(value) { + scope.isOpen = !!value; + }); + } + + appendToBody = angular.isDefined($attrs.dropdownAppendToBody); + + if ( appendToBody && self.dropdownMenu ) { + $document.find('body').append( self.dropdownMenu ); + element.on('$destroy', function handleDestroyEvent() { + self.dropdownMenu.remove(); + }); + } + }; + + this.toggle = function( open ) { + return scope.isOpen = arguments.length ? !!open : !scope.isOpen; + }; + + // Allow other directives to watch status + this.isOpen = function() { + return scope.isOpen; + }; + + scope.getToggleElement = function() { + return self.toggleElement; + }; + + scope.getAutoClose = function() { + return $attrs.autoClose || 'always'; //or 'outsideClick' or 'disabled' + }; + + scope.getElement = function() { + return self.$element; + }; + + scope.focusToggleElement = function() { + if ( self.toggleElement ) { + self.toggleElement[0].focus(); + } + }; + + scope.$watch('isOpen', function( isOpen, wasOpen ) { + if ( appendToBody && self.dropdownMenu ) { + var pos = $position.positionElements(self.$element, self.dropdownMenu, 'bottom-left', true); + self.dropdownMenu.css({ + top: pos.top + 'px', + left: pos.left + 'px', + display: isOpen ? 'block' : 'none' + }); + } + + $animate[isOpen ? 'addClass' : 'removeClass'](self.$element, openClass); + + if ( isOpen ) { + scope.focusToggleElement(); + dropdownService.open( scope ); + } else { + dropdownService.close( scope ); + } + + setIsOpen($scope, isOpen); + if (angular.isDefined(isOpen) && isOpen !== wasOpen) { + toggleInvoker($scope, { open: !!isOpen }); + } + }); + + $scope.$on('$locationChangeSuccess', function() { + scope.isOpen = false; + }); + + $scope.$on('$destroy', function() { + scope.$destroy(); + }); +}]) + +.directive('dropdown', function() { + return { + controller: 'DropdownController', + link: function(scope, element, attrs, dropdownCtrl) { + dropdownCtrl.init( element ); + } + }; +}) + +.directive('dropdownMenu', function() { + return { + restrict: 'AC', + require: '?^dropdown', + link: function(scope, element, attrs, dropdownCtrl) { + if ( !dropdownCtrl ) { + return; + } + dropdownCtrl.dropdownMenu = element; + } + }; +}) + +.directive('dropdownToggle', function() { + return { + require: '?^dropdown', + link: function(scope, element, attrs, dropdownCtrl) { + if ( !dropdownCtrl ) { + return; + } + + dropdownCtrl.toggleElement = element; + + var toggleDropdown = function(event) { + event.preventDefault(); + + if ( !element.hasClass('disabled') && !attrs.disabled ) { + scope.$apply(function() { + dropdownCtrl.toggle(); + }); + } + }; + + element.bind('click', toggleDropdown); + + // WAI-ARIA + element.attr({ 'aria-haspopup': true, 'aria-expanded': false }); + scope.$watch(dropdownCtrl.isOpen, function( isOpen ) { + element.attr('aria-expanded', !!isOpen); + }); + + scope.$on('$destroy', function() { + element.unbind('click', toggleDropdown); + }); + } + }; +}); + +angular.module('ui.bootstrap.modal', []) + +/** + * A helper, internal data structure that acts as a map but also allows getting / removing + * elements in the LIFO order + */ + .factory('$$stackedMap', function () { + return { + createNew: function () { + var stack = []; + + return { + add: function (key, value) { + stack.push({ + key: key, + value: value + }); + }, + get: function (key) { + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + return stack[i]; + } + } + }, + keys: function() { + var keys = []; + for (var i = 0; i < stack.length; i++) { + keys.push(stack[i].key); + } + return keys; + }, + top: function () { + return stack[stack.length - 1]; + }, + remove: function (key) { + var idx = -1; + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + idx = i; + break; + } + } + return stack.splice(idx, 1)[0]; + }, + removeTop: function () { + return stack.splice(stack.length - 1, 1)[0]; + }, + length: function () { + return stack.length; + } + }; + } + }; + }) + +/** + * A helper directive for the $modal service. It creates a backdrop element. + */ + .directive('modalBackdrop', ['$timeout', function ($timeout) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/modal/backdrop.html', + compile: function (tElement, tAttrs) { + tElement.addClass(tAttrs.backdropClass); + return linkFn; + } + }; + + function linkFn(scope, element, attrs) { + scope.animate = false; + + //trigger CSS transitions + $timeout(function () { + scope.animate = true; + }); + } + }]) + + .directive('modalWindow', ['$modalStack', '$q', function ($modalStack, $q) { + return { + restrict: 'EA', + scope: { + index: '@', + animate: '=' + }, + replace: true, + transclude: true, + templateUrl: function(tElement, tAttrs) { + return tAttrs.templateUrl || 'template/modal/window.html'; + }, + link: function (scope, element, attrs) { + element.addClass(attrs.windowClass || ''); + scope.size = attrs.size; + + scope.close = function (evt) { + var modal = $modalStack.getTop(); + if (modal && modal.value.backdrop && modal.value.backdrop != 'static' && (evt.target === evt.currentTarget)) { + evt.preventDefault(); + evt.stopPropagation(); + $modalStack.dismiss(modal.key, 'backdrop click'); + } + }; + + // This property is only added to the scope for the purpose of detecting when this directive is rendered. + // We can detect that by using this property in the template associated with this directive and then use + // {@link Attribute#$observe} on it. For more details please see {@link TableColumnResize}. + scope.$isRendered = true; + + // Deferred object that will be resolved when this modal is render. + var modalRenderDeferObj = $q.defer(); + // Observe function will be called on next digest cycle after compilation, ensuring that the DOM is ready. + // In order to use this way of finding whether DOM is ready, we need to observe a scope property used in modal's template. + attrs.$observe('modalRender', function (value) { + if (value == 'true') { + modalRenderDeferObj.resolve(); + } + }); + + modalRenderDeferObj.promise.then(function () { + // trigger CSS transitions + scope.animate = true; + + var inputsWithAutofocus = element[0].querySelectorAll('[autofocus]'); + /** + * Auto-focusing of a freshly-opened modal element causes any child elements + * with the autofocus attribute to lose focus. This is an issue on touch + * based devices which will show and then hide the onscreen keyboard. + * Attempts to refocus the autofocus element via JavaScript will not reopen + * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus + * the modal element if the modal does not contain an autofocus element. + */ + if (inputsWithAutofocus.length) { + inputsWithAutofocus[0].focus(); + } else { + element[0].focus(); + } + + // Notify {@link $modalStack} that modal is rendered. + var modal = $modalStack.getTop(); + if (modal) { + $modalStack.modalRendered(modal.key); + } + }); + } + }; + }]) + + .directive('modalAnimationClass', [ + function () { + return { + compile: function (tElement, tAttrs) { + if (tAttrs.modalAnimation) { + tElement.addClass(tAttrs.modalAnimationClass); + } + } + }; + }]) + + .directive('modalTransclude', function () { + return { + link: function($scope, $element, $attrs, controller, $transclude) { + $transclude($scope.$parent, function(clone) { + $element.empty(); + $element.append(clone); + }); + } + }; + }) + + .factory('$modalStack', ['$animate', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap', + function ($animate, $timeout, $document, $compile, $rootScope, $$stackedMap) { + + var OPENED_MODAL_CLASS = 'modal-open'; + + var backdropDomEl, backdropScope; + var openedWindows = $$stackedMap.createNew(); + var $modalStack = {}; + + function backdropIndex() { + var topBackdropIndex = -1; + var opened = openedWindows.keys(); + for (var i = 0; i < opened.length; i++) { + if (openedWindows.get(opened[i]).value.backdrop) { + topBackdropIndex = i; + } + } + return topBackdropIndex; + } + + $rootScope.$watch(backdropIndex, function(newBackdropIndex){ + if (backdropScope) { + backdropScope.index = newBackdropIndex; + } + }); + + function removeModalWindow(modalInstance) { + + var body = $document.find('body').eq(0); + var modalWindow = openedWindows.get(modalInstance).value; + + //clean up the stack + openedWindows.remove(modalInstance); + + //remove window DOM element + removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() { + body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0); + checkRemoveBackdrop(); + }); + } + + function checkRemoveBackdrop() { + //remove backdrop if no longer needed + if (backdropDomEl && backdropIndex() == -1) { + var backdropScopeRef = backdropScope; + removeAfterAnimate(backdropDomEl, backdropScope, function () { + backdropScopeRef = null; + }); + backdropDomEl = undefined; + backdropScope = undefined; + } + } + + function removeAfterAnimate(domEl, scope, done) { + // Closing animation + scope.animate = false; + + if (domEl.attr('modal-animation') && $animate.enabled()) { + // transition out + domEl.one('$animate:close', function closeFn() { + $rootScope.$evalAsync(afterAnimating); + }); + } else { + // Ensure this call is async + $timeout(afterAnimating); + } + + function afterAnimating() { + if (afterAnimating.done) { + return; + } + afterAnimating.done = true; + + domEl.remove(); + scope.$destroy(); + if (done) { + done(); + } + } + } + + $document.bind('keydown', function (evt) { + var modal; + + if (evt.which === 27) { + modal = openedWindows.top(); + if (modal && modal.value.keyboard) { + evt.preventDefault(); + $rootScope.$apply(function () { + $modalStack.dismiss(modal.key, 'escape key press'); + }); + } + } + }); + + $modalStack.open = function (modalInstance, modal) { + + var modalOpener = $document[0].activeElement; + + openedWindows.add(modalInstance, { + deferred: modal.deferred, + renderDeferred: modal.renderDeferred, + modalScope: modal.scope, + backdrop: modal.backdrop, + keyboard: modal.keyboard + }); + + var body = $document.find('body').eq(0), + currBackdropIndex = backdropIndex(); + + if (currBackdropIndex >= 0 && !backdropDomEl) { + backdropScope = $rootScope.$new(true); + backdropScope.index = currBackdropIndex; + var angularBackgroundDomEl = angular.element('
    '); + angularBackgroundDomEl.attr('backdrop-class', modal.backdropClass); + if (modal.animation) { + angularBackgroundDomEl.attr('modal-animation', 'true'); + } + backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope); + body.append(backdropDomEl); + } + + var angularDomEl = angular.element('
    '); + angularDomEl.attr({ + 'template-url': modal.windowTemplateUrl, + 'window-class': modal.windowClass, + 'size': modal.size, + 'index': openedWindows.length() - 1, + 'animate': 'animate' + }).html(modal.content); + if (modal.animation) { + angularDomEl.attr('modal-animation', 'true'); + } + + var modalDomEl = $compile(angularDomEl)(modal.scope); + openedWindows.top().value.modalDomEl = modalDomEl; + openedWindows.top().value.modalOpener = modalOpener; + body.append(modalDomEl); + body.addClass(OPENED_MODAL_CLASS); + }; + + function broadcastClosing(modalWindow, resultOrReason, closing) { + return !modalWindow.value.modalScope.$broadcast('modal.closing', resultOrReason, closing).defaultPrevented; + } + + $modalStack.close = function (modalInstance, result) { + var modalWindow = openedWindows.get(modalInstance); + if (modalWindow && broadcastClosing(modalWindow, result, true)) { + modalWindow.value.deferred.resolve(result); + removeModalWindow(modalInstance); + modalWindow.value.modalOpener.focus(); + return true; + } + return !modalWindow; + }; + + $modalStack.dismiss = function (modalInstance, reason) { + var modalWindow = openedWindows.get(modalInstance); + if (modalWindow && broadcastClosing(modalWindow, reason, false)) { + modalWindow.value.deferred.reject(reason); + removeModalWindow(modalInstance); + modalWindow.value.modalOpener.focus(); + return true; + } + return !modalWindow; + }; + + $modalStack.dismissAll = function (reason) { + var topModal = this.getTop(); + while (topModal && this.dismiss(topModal.key, reason)) { + topModal = this.getTop(); + } + }; + + $modalStack.getTop = function () { + return openedWindows.top(); + }; + + $modalStack.modalRendered = function (modalInstance) { + var modalWindow = openedWindows.get(modalInstance); + if (modalWindow) { + modalWindow.value.renderDeferred.resolve(); + } + }; + + return $modalStack; + }]) + + .provider('$modal', function () { + + var $modalProvider = { + options: { + animation: true, + backdrop: true, //can also be false or 'static' + keyboard: true + }, + $get: ['$injector', '$rootScope', '$q', '$templateRequest', '$controller', '$modalStack', + function ($injector, $rootScope, $q, $templateRequest, $controller, $modalStack) { + + var $modal = {}; + + function getTemplatePromise(options) { + return options.template ? $q.when(options.template) : + $templateRequest(angular.isFunction(options.templateUrl) ? (options.templateUrl)() : options.templateUrl); + } + + function getResolvePromises(resolves) { + var promisesArr = []; + angular.forEach(resolves, function (value) { + if (angular.isFunction(value) || angular.isArray(value)) { + promisesArr.push($q.when($injector.invoke(value))); + } + }); + return promisesArr; + } + + $modal.open = function (modalOptions) { + + var modalResultDeferred = $q.defer(); + var modalOpenedDeferred = $q.defer(); + var modalRenderDeferred = $q.defer(); + + //prepare an instance of a modal to be injected into controllers and returned to a caller + var modalInstance = { + result: modalResultDeferred.promise, + opened: modalOpenedDeferred.promise, + rendered: modalRenderDeferred.promise, + close: function (result) { + return $modalStack.close(modalInstance, result); + }, + dismiss: function (reason) { + return $modalStack.dismiss(modalInstance, reason); + } + }; + + //merge and clean up options + modalOptions = angular.extend({}, $modalProvider.options, modalOptions); + modalOptions.resolve = modalOptions.resolve || {}; + + //verify options + if (!modalOptions.template && !modalOptions.templateUrl) { + throw new Error('One of template or templateUrl options is required.'); + } + + var templateAndResolvePromise = + $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve))); + + + templateAndResolvePromise.then(function resolveSuccess(tplAndVars) { + + var modalScope = (modalOptions.scope || $rootScope).$new(); + modalScope.$close = modalInstance.close; + modalScope.$dismiss = modalInstance.dismiss; + + var ctrlInstance, ctrlLocals = {}; + var resolveIter = 1; + + //controllers + if (modalOptions.controller) { + ctrlLocals.$scope = modalScope; + ctrlLocals.$modalInstance = modalInstance; + angular.forEach(modalOptions.resolve, function (value, key) { + ctrlLocals[key] = tplAndVars[resolveIter++]; + }); + + ctrlInstance = $controller(modalOptions.controller, ctrlLocals); + if (modalOptions.controllerAs) { + modalScope[modalOptions.controllerAs] = ctrlInstance; + } + } + + $modalStack.open(modalInstance, { + scope: modalScope, + deferred: modalResultDeferred, + renderDeferred: modalRenderDeferred, + content: tplAndVars[0], + animation: modalOptions.animation, + backdrop: modalOptions.backdrop, + keyboard: modalOptions.keyboard, + backdropClass: modalOptions.backdropClass, + windowClass: modalOptions.windowClass, + windowTemplateUrl: modalOptions.windowTemplateUrl, + size: modalOptions.size + }); + + }, function resolveError(reason) { + modalResultDeferred.reject(reason); + }); + + templateAndResolvePromise.then(function () { + modalOpenedDeferred.resolve(true); + }, function (reason) { + modalOpenedDeferred.reject(reason); + }); + + return modalInstance; + }; + + return $modal; + }] + }; + + return $modalProvider; + }); + +angular.module('ui.bootstrap.pagination', []) + +.controller('PaginationController', ['$scope', '$attrs', '$parse', function ($scope, $attrs, $parse) { + var self = this, + ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl + setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop; + + this.init = function(ngModelCtrl_, config) { + ngModelCtrl = ngModelCtrl_; + this.config = config; + + ngModelCtrl.$render = function() { + self.render(); + }; + + if ($attrs.itemsPerPage) { + $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) { + self.itemsPerPage = parseInt(value, 10); + $scope.totalPages = self.calculateTotalPages(); + }); + } else { + this.itemsPerPage = config.itemsPerPage; + } + + $scope.$watch('totalItems', function() { + $scope.totalPages = self.calculateTotalPages(); + }); + + $scope.$watch('totalPages', function(value) { + setNumPages($scope.$parent, value); // Readonly variable + + if ( $scope.page > value ) { + $scope.selectPage(value); + } else { + ngModelCtrl.$render(); + } + }); + }; + + this.calculateTotalPages = function() { + var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage); + return Math.max(totalPages || 0, 1); + }; + + this.render = function() { + $scope.page = parseInt(ngModelCtrl.$viewValue, 10) || 1; + }; + + $scope.selectPage = function(page, evt) { + if ( $scope.page !== page && page > 0 && page <= $scope.totalPages) { + if (evt && evt.target) { + evt.target.blur(); + } + ngModelCtrl.$setViewValue(page); + ngModelCtrl.$render(); + } + }; + + $scope.getText = function( key ) { + return $scope[key + 'Text'] || self.config[key + 'Text']; + }; + $scope.noPrevious = function() { + return $scope.page === 1; + }; + $scope.noNext = function() { + return $scope.page === $scope.totalPages; + }; +}]) + +.constant('paginationConfig', { + itemsPerPage: 10, + boundaryLinks: false, + directionLinks: true, + firstText: 'First', + previousText: 'Previous', + nextText: 'Next', + lastText: 'Last', + rotate: true +}) + +.directive('pagination', ['$parse', 'paginationConfig', function($parse, paginationConfig) { + return { + restrict: 'EA', + scope: { + totalItems: '=', + firstText: '@', + previousText: '@', + nextText: '@', + lastText: '@' + }, + require: ['pagination', '?ngModel'], + controller: 'PaginationController', + templateUrl: 'template/pagination/pagination.html', + replace: true, + link: function(scope, element, attrs, ctrls) { + var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + if (!ngModelCtrl) { + return; // do nothing if no ng-model + } + + // Setup configuration parameters + var maxSize = angular.isDefined(attrs.maxSize) ? scope.$parent.$eval(attrs.maxSize) : paginationConfig.maxSize, + rotate = angular.isDefined(attrs.rotate) ? scope.$parent.$eval(attrs.rotate) : paginationConfig.rotate; + scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : paginationConfig.boundaryLinks; + scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : paginationConfig.directionLinks; + + paginationCtrl.init(ngModelCtrl, paginationConfig); + + if (attrs.maxSize) { + scope.$parent.$watch($parse(attrs.maxSize), function(value) { + maxSize = parseInt(value, 10); + paginationCtrl.render(); + }); + } + + // Create page object used in template + function makePage(number, text, isActive) { + return { + number: number, + text: text, + active: isActive + }; + } + + function getPages(currentPage, totalPages) { + var pages = []; + + // Default page limits + var startPage = 1, endPage = totalPages; + var isMaxSized = ( angular.isDefined(maxSize) && maxSize < totalPages ); + + // recompute if maxSize + if ( isMaxSized ) { + if ( rotate ) { + // Current page is displayed in the middle of the visible ones + startPage = Math.max(currentPage - Math.floor(maxSize/2), 1); + endPage = startPage + maxSize - 1; + + // Adjust if limit is exceeded + if (endPage > totalPages) { + endPage = totalPages; + startPage = endPage - maxSize + 1; + } + } else { + // Visible pages are paginated with maxSize + startPage = ((Math.ceil(currentPage / maxSize) - 1) * maxSize) + 1; + + // Adjust last page if limit is exceeded + endPage = Math.min(startPage + maxSize - 1, totalPages); + } + } + + // Add page number links + for (var number = startPage; number <= endPage; number++) { + var page = makePage(number, number, number === currentPage); + pages.push(page); + } + + // Add links to move between page sets + if ( isMaxSized && ! rotate ) { + if ( startPage > 1 ) { + var previousPageSet = makePage(startPage - 1, '...', false); + pages.unshift(previousPageSet); + } + + if ( endPage < totalPages ) { + var nextPageSet = makePage(endPage + 1, '...', false); + pages.push(nextPageSet); + } + } + + return pages; + } + + var originalRender = paginationCtrl.render; + paginationCtrl.render = function() { + originalRender(); + if (scope.page > 0 && scope.page <= scope.totalPages) { + scope.pages = getPages(scope.page, scope.totalPages); + } + }; + } + }; +}]) + +.constant('pagerConfig', { + itemsPerPage: 10, + previousText: '« Previous', + nextText: 'Next »', + align: true +}) + +.directive('pager', ['pagerConfig', function(pagerConfig) { + return { + restrict: 'EA', + scope: { + totalItems: '=', + previousText: '@', + nextText: '@' + }, + require: ['pager', '?ngModel'], + controller: 'PaginationController', + templateUrl: 'template/pagination/pager.html', + replace: true, + link: function(scope, element, attrs, ctrls) { + var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + if (!ngModelCtrl) { + return; // do nothing if no ng-model + } + + scope.align = angular.isDefined(attrs.align) ? scope.$parent.$eval(attrs.align) : pagerConfig.align; + paginationCtrl.init(ngModelCtrl, pagerConfig); + } + }; +}]); + +/** + * The following features are still outstanding: animation as a + * function, placement as a function, inside, support for more triggers than + * just mouse enter/leave, html tooltips, and selector delegation. + */ +angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap.bindHtml' ] ) + +/** + * The $tooltip service creates tooltip- and popover-like directives as well as + * houses global options for them. + */ +.provider( '$tooltip', function () { + // The default options tooltip and popover. + var defaultOptions = { + placement: 'top', + animation: true, + popupDelay: 0, + useContentExp: false + }; + + // Default hide triggers for each show trigger + var triggerMap = { + 'mouseenter': 'mouseleave', + 'click': 'click', + 'focus': 'blur' + }; + + // The options specified to the provider globally. + var globalOptions = {}; + + /** + * `options({})` allows global configuration of all tooltips in the + * application. + * + * var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) { + * // place tooltips left instead of top by default + * $tooltipProvider.options( { placement: 'left' } ); + * }); + */ + this.options = function( value ) { + angular.extend( globalOptions, value ); + }; + + /** + * This allows you to extend the set of trigger mappings available. E.g.: + * + * $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' ); + */ + this.setTriggers = function setTriggers ( triggers ) { + angular.extend( triggerMap, triggers ); + }; + + /** + * This is a helper function for translating camel-case to snake-case. + */ + function snake_case(name){ + var regexp = /[A-Z]/g; + var separator = '-'; + return name.replace(regexp, function(letter, pos) { + return (pos ? separator : '') + letter.toLowerCase(); + }); + } + + /** + * Returns the actual instance of the $tooltip service. + * TODO support multiple triggers + */ + this.$get = [ '$window', '$compile', '$timeout', '$document', '$position', '$interpolate', function ( $window, $compile, $timeout, $document, $position, $interpolate ) { + return function $tooltip ( type, prefix, defaultTriggerShow, options ) { + options = angular.extend( {}, defaultOptions, globalOptions, options ); + + /** + * Returns an object of show and hide triggers. + * + * If a trigger is supplied, + * it is used to show the tooltip; otherwise, it will use the `trigger` + * option passed to the `$tooltipProvider.options` method; else it will + * default to the trigger supplied to this directive factory. + * + * The hide trigger is based on the show trigger. If the `trigger` option + * was passed to the `$tooltipProvider.options` method, it will use the + * mapped trigger from `triggerMap` or the passed trigger if the map is + * undefined; otherwise, it uses the `triggerMap` value of the show + * trigger; else it will just use the show trigger. + */ + function getTriggers ( trigger ) { + var show = trigger || options.trigger || defaultTriggerShow; + var hide = triggerMap[show] || show; + return { + show: show, + hide: hide + }; + } + + var directiveName = snake_case( type ); + + var startSym = $interpolate.startSymbol(); + var endSym = $interpolate.endSymbol(); + var template = + '
    '+ + '
    '; + + return { + restrict: 'EA', + compile: function (tElem, tAttrs) { + var tooltipLinker = $compile( template ); + + return function link ( scope, element, attrs, tooltipCtrl ) { + var tooltip; + var tooltipLinkedScope; + var transitionTimeout; + var popupTimeout; + var appendToBody = angular.isDefined( options.appendToBody ) ? options.appendToBody : false; + var triggers = getTriggers( undefined ); + var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']); + var ttScope = scope.$new(true); + + var positionTooltip = function () { + if (!tooltip) { return; } + + var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody); + ttPosition.top += 'px'; + ttPosition.left += 'px'; + + // Now set the calculated positioning. + tooltip.css( ttPosition ); + }; + + // Set up the correct scope to allow transclusion later + ttScope.origScope = scope; + + // By default, the tooltip is not open. + // TODO add ability to start tooltip opened + ttScope.isOpen = false; + + function toggleTooltipBind () { + if ( ! ttScope.isOpen ) { + showTooltipBind(); + } else { + hideTooltipBind(); + } + } + + // Show the tooltip with delay if specified, otherwise show it immediately + function showTooltipBind() { + if(hasEnableExp && !scope.$eval(attrs[prefix+'Enable'])) { + return; + } + + prepareTooltip(); + + if ( ttScope.popupDelay ) { + // Do nothing if the tooltip was already scheduled to pop-up. + // This happens if show is triggered multiple times before any hide is triggered. + if (!popupTimeout) { + popupTimeout = $timeout( show, ttScope.popupDelay, false ); + popupTimeout.then(function(reposition){reposition();}); + } + } else { + show()(); + } + } + + function hideTooltipBind () { + scope.$apply(function () { + hide(); + }); + } + + // Show the tooltip popup element. + function show() { + + popupTimeout = null; + + // If there is a pending remove transition, we must cancel it, lest the + // tooltip be mysteriously removed. + if ( transitionTimeout ) { + $timeout.cancel( transitionTimeout ); + transitionTimeout = null; + } + + // Don't show empty tooltips. + if ( !(options.useContentExp ? ttScope.contentExp() : ttScope.content) ) { + return angular.noop; + } + + createTooltip(); + + // Set the initial positioning. + tooltip.css({ top: 0, left: 0, display: 'block' }); + ttScope.$digest(); + + positionTooltip(); + + // And show the tooltip. + ttScope.isOpen = true; + ttScope.$apply(); // digest required as $apply is not called + + // Return positioning function as promise callback for correct + // positioning after draw. + return positionTooltip; + } + + // Hide the tooltip popup element. + function hide() { + // First things first: we don't show it anymore. + ttScope.isOpen = false; + + //if tooltip is going to be shown after delay, we must cancel this + $timeout.cancel( popupTimeout ); + popupTimeout = null; + + // And now we remove it from the DOM. However, if we have animation, we + // need to wait for it to expire beforehand. + // FIXME: this is a placeholder for a port of the transitions library. + if ( ttScope.animation ) { + if (!transitionTimeout) { + transitionTimeout = $timeout(removeTooltip, 500); + } + } else { + removeTooltip(); + } + } + + function createTooltip() { + // There can only be one tooltip element per directive shown at once. + if (tooltip) { + removeTooltip(); + } + tooltipLinkedScope = ttScope.$new(); + tooltip = tooltipLinker(tooltipLinkedScope, function (tooltip) { + if ( appendToBody ) { + $document.find( 'body' ).append( tooltip ); + } else { + element.after( tooltip ); + } + }); + + tooltipLinkedScope.$watch(function () { + $timeout(positionTooltip, 0, false); + }); + + if (options.useContentExp) { + tooltipLinkedScope.$watch('contentExp()', function (val) { + if (!val && ttScope.isOpen ) { + hide(); + } + }); + } + } + + function removeTooltip() { + transitionTimeout = null; + if (tooltip) { + tooltip.remove(); + tooltip = null; + } + if (tooltipLinkedScope) { + tooltipLinkedScope.$destroy(); + tooltipLinkedScope = null; + } + } + + function prepareTooltip() { + prepPopupClass(); + prepPlacement(); + prepPopupDelay(); + } + + ttScope.contentExp = function () { + return scope.$eval(attrs[type]); + }; + + /** + * Observe the relevant attributes. + */ + if (!options.useContentExp) { + attrs.$observe( type, function ( val ) { + ttScope.content = val; + + if (!val && ttScope.isOpen ) { + hide(); + } + }); + } + + attrs.$observe( 'disabled', function ( val ) { + if (val && ttScope.isOpen ) { + hide(); + } + }); + + attrs.$observe( prefix+'Title', function ( val ) { + ttScope.title = val; + }); + + function prepPopupClass() { + ttScope.popupClass = attrs[prefix + 'Class']; + } + + function prepPlacement() { + var val = attrs[ prefix + 'Placement' ]; + ttScope.placement = angular.isDefined( val ) ? val : options.placement; + } + + function prepPopupDelay() { + var val = attrs[ prefix + 'PopupDelay' ]; + var delay = parseInt( val, 10 ); + ttScope.popupDelay = ! isNaN(delay) ? delay : options.popupDelay; + } + + var unregisterTriggers = function () { + element.unbind(triggers.show, showTooltipBind); + element.unbind(triggers.hide, hideTooltipBind); + }; + + function prepTriggers() { + var val = attrs[ prefix + 'Trigger' ]; + unregisterTriggers(); + + triggers = getTriggers( val ); + + if ( triggers.show === triggers.hide ) { + element.bind( triggers.show, toggleTooltipBind ); + } else { + element.bind( triggers.show, showTooltipBind ); + element.bind( triggers.hide, hideTooltipBind ); + } + } + prepTriggers(); + + var animation = scope.$eval(attrs[prefix + 'Animation']); + ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation; + + var appendToBodyVal = scope.$eval(attrs[prefix + 'AppendToBody']); + appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody; + + // if a tooltip is attached to we need to remove it on + // location change as its parent scope will probably not be destroyed + // by the change. + if ( appendToBody ) { + scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess () { + if ( ttScope.isOpen ) { + hide(); + } + }); + } + + // Make sure tooltip is destroyed and removed. + scope.$on('$destroy', function onDestroyTooltip() { + $timeout.cancel( transitionTimeout ); + $timeout.cancel( popupTimeout ); + unregisterTriggers(); + removeTooltip(); + ttScope = null; + }); + }; + } + }; + }; + }]; +}) + +// This is mostly ngInclude code but with a custom scope +.directive( 'tooltipTemplateTransclude', [ + '$animate', '$sce', '$compile', '$templateRequest', +function ($animate , $sce , $compile , $templateRequest) { + return { + link: function ( scope, elem, attrs ) { + var origScope = scope.$eval(attrs.tooltipTemplateTranscludeScope); + + var changeCounter = 0, + currentScope, + previousElement, + currentElement; + + var cleanupLastIncludeContent = function() { + if (previousElement) { + previousElement.remove(); + previousElement = null; + } + if (currentScope) { + currentScope.$destroy(); + currentScope = null; + } + if (currentElement) { + $animate.leave(currentElement).then(function() { + previousElement = null; + }); + previousElement = currentElement; + currentElement = null; + } + }; + + scope.$watch($sce.parseAsResourceUrl(attrs.tooltipTemplateTransclude), function (src) { + var thisChangeId = ++changeCounter; + + if (src) { + //set the 2nd param to true to ignore the template request error so that the inner + //contents and scope can be cleaned up. + $templateRequest(src, true).then(function(response) { + if (thisChangeId !== changeCounter) { return; } + var newScope = origScope.$new(); + var template = response; + + var clone = $compile(template)(newScope, function(clone) { + cleanupLastIncludeContent(); + $animate.enter(clone, elem); + }); + + currentScope = newScope; + currentElement = clone; + + currentScope.$emit('$includeContentLoaded', src); + }, function() { + if (thisChangeId === changeCounter) { + cleanupLastIncludeContent(); + scope.$emit('$includeContentError', src); + } + }); + scope.$emit('$includeContentRequested', src); + } else { + cleanupLastIncludeContent(); + } + }); + + scope.$on('$destroy', cleanupLastIncludeContent); + } + }; +}]) + +/** + * Note that it's intentional that these classes are *not* applied through $animate. + * They must not be animated as they're expected to be present on the tooltip on + * initialization. + */ +.directive('tooltipClasses', function () { + return { + restrict: 'A', + link: function (scope, element, attrs) { + if (scope.placement) { + element.addClass(scope.placement); + } + if (scope.popupClass) { + element.addClass(scope.popupClass); + } + if (scope.animation()) { + element.addClass(attrs.tooltipAnimationClass); + } + } + }; +}) + +.directive( 'tooltipPopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/tooltip/tooltip-popup.html' + }; +}) + +.directive( 'tooltip', [ '$tooltip', function ( $tooltip ) { + return $tooltip( 'tooltip', 'tooltip', 'mouseenter' ); +}]) + +.directive( 'tooltipTemplatePopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&', + originScope: '&' }, + templateUrl: 'template/tooltip/tooltip-template-popup.html' + }; +}) + +.directive( 'tooltipTemplate', [ '$tooltip', function ( $tooltip ) { + return $tooltip('tooltipTemplate', 'tooltip', 'mouseenter', { + useContentExp: true + }); +}]) + +.directive( 'tooltipHtmlPopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/tooltip/tooltip-html-popup.html' + }; +}) + +.directive( 'tooltipHtml', [ '$tooltip', function ( $tooltip ) { + return $tooltip('tooltipHtml', 'tooltip', 'mouseenter', { + useContentExp: true + }); +}]) + +/* +Deprecated +*/ +.directive( 'tooltipHtmlUnsafePopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html' + }; +}) + +.value('tooltipHtmlUnsafeSuppressDeprecated', false) +.directive( 'tooltipHtmlUnsafe', [ + '$tooltip', 'tooltipHtmlUnsafeSuppressDeprecated', '$log', +function ( $tooltip , tooltipHtmlUnsafeSuppressDeprecated , $log) { + if (!tooltipHtmlUnsafeSuppressDeprecated) { + $log.warn('tooltip-html-unsafe is now deprecated. Use tooltip-html or tooltip-template instead.'); + } + return $tooltip( 'tooltipHtmlUnsafe', 'tooltip', 'mouseenter' ); +}]); + +/** + * The following features are still outstanding: popup delay, animation as a + * function, placement as a function, inside, support for more triggers than + * just mouse enter/leave, html popovers, and selector delegatation. + */ +angular.module( 'ui.bootstrap.popover', [ 'ui.bootstrap.tooltip' ] ) + +.directive( 'popoverTemplatePopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { title: '@', contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&', + originScope: '&' }, + templateUrl: 'template/popover/popover-template.html' + }; +}) + +.directive( 'popoverTemplate', [ '$tooltip', function ( $tooltip ) { + return $tooltip( 'popoverTemplate', 'popover', 'click', { + useContentExp: true + } ); +}]) + +.directive( 'popoverPopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { title: '@', content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/popover/popover.html' + }; +}) + +.directive( 'popover', [ '$tooltip', function ( $tooltip ) { + return $tooltip( 'popover', 'popover', 'click' ); +}]); + +angular.module('ui.bootstrap.progressbar', []) + +.constant('progressConfig', { + animate: true, + max: 100 +}) + +.controller('ProgressController', ['$scope', '$attrs', 'progressConfig', function($scope, $attrs, progressConfig) { + var self = this, + animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate; + + this.bars = []; + $scope.max = angular.isDefined($scope.max) ? $scope.max : progressConfig.max; + + this.addBar = function(bar, element) { + if ( !animate ) { + element.css({'transition': 'none'}); + } + + this.bars.push(bar); + + bar.$watch('value', function( value ) { + bar.percent = +(100 * value / $scope.max).toFixed(2); + }); + + bar.$on('$destroy', function() { + element = null; + self.removeBar(bar); + }); + }; + + this.removeBar = function(bar) { + this.bars.splice(this.bars.indexOf(bar), 1); + }; +}]) + +.directive('progress', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + controller: 'ProgressController', + require: 'progress', + scope: {}, + templateUrl: 'template/progressbar/progress.html' + }; +}) + +.directive('bar', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + require: '^progress', + scope: { + value: '=', + max: '=?', + type: '@' + }, + templateUrl: 'template/progressbar/bar.html', + link: function(scope, element, attrs, progressCtrl) { + progressCtrl.addBar(scope, element); + } + }; +}) + +.directive('progressbar', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + controller: 'ProgressController', + scope: { + value: '=', + max: '=?', + type: '@' + }, + templateUrl: 'template/progressbar/progressbar.html', + link: function(scope, element, attrs, progressCtrl) { + progressCtrl.addBar(scope, angular.element(element.children()[0])); + } + }; +}); + +angular.module('ui.bootstrap.rating', []) + +.constant('ratingConfig', { + max: 5, + stateOn: null, + stateOff: null +}) + +.controller('RatingController', ['$scope', '$attrs', 'ratingConfig', function($scope, $attrs, ratingConfig) { + var ngModelCtrl = { $setViewValue: angular.noop }; + + this.init = function(ngModelCtrl_) { + ngModelCtrl = ngModelCtrl_; + ngModelCtrl.$render = this.render; + + ngModelCtrl.$formatters.push(function(value) { + if (angular.isNumber(value) && value << 0 !== value) { + value = Math.round(value); + } + return value; + }); + + this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn; + this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff; + + var ratingStates = angular.isDefined($attrs.ratingStates) ? $scope.$parent.$eval($attrs.ratingStates) : + new Array( angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max ); + $scope.range = this.buildTemplateObjects(ratingStates); + }; + + this.buildTemplateObjects = function(states) { + for (var i = 0, n = states.length; i < n; i++) { + states[i] = angular.extend({ index: i }, { stateOn: this.stateOn, stateOff: this.stateOff }, states[i]); + } + return states; + }; + + $scope.rate = function(value) { + if ( !$scope.readonly && value >= 0 && value <= $scope.range.length ) { + ngModelCtrl.$setViewValue(value); + ngModelCtrl.$render(); + } + }; + + $scope.enter = function(value) { + if ( !$scope.readonly ) { + $scope.value = value; + } + $scope.onHover({value: value}); + }; + + $scope.reset = function() { + $scope.value = ngModelCtrl.$viewValue; + $scope.onLeave(); + }; + + $scope.onKeydown = function(evt) { + if (/(37|38|39|40)/.test(evt.which)) { + evt.preventDefault(); + evt.stopPropagation(); + $scope.rate( $scope.value + (evt.which === 38 || evt.which === 39 ? 1 : -1) ); + } + }; + + this.render = function() { + $scope.value = ngModelCtrl.$viewValue; + }; +}]) + +.directive('rating', function() { + return { + restrict: 'EA', + require: ['rating', 'ngModel'], + scope: { + readonly: '=?', + onHover: '&', + onLeave: '&' + }, + controller: 'RatingController', + templateUrl: 'template/rating/rating.html', + replace: true, + link: function(scope, element, attrs, ctrls) { + var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + ratingCtrl.init( ngModelCtrl ); + } + }; +}); + +/** + * @ngdoc overview + * @name ui.bootstrap.tabs + * + * @description + * AngularJS version of the tabs directive. + */ + +angular.module('ui.bootstrap.tabs', []) + +.controller('TabsetController', ['$scope', function TabsetCtrl($scope) { + var ctrl = this, + tabs = ctrl.tabs = $scope.tabs = []; + + ctrl.select = function(selectedTab) { + angular.forEach(tabs, function(tab) { + if (tab.active && tab !== selectedTab) { + tab.active = false; + tab.onDeselect(); + } + }); + selectedTab.active = true; + selectedTab.onSelect(); + }; + + ctrl.addTab = function addTab(tab) { + tabs.push(tab); + // we can't run the select function on the first tab + // since that would select it twice + if (tabs.length === 1 && tab.active !== false) { + tab.active = true; + } else if (tab.active) { + ctrl.select(tab); + } + else { + tab.active = false; + } + }; + + ctrl.removeTab = function removeTab(tab) { + var index = tabs.indexOf(tab); + //Select a new tab if the tab to be removed is selected and not destroyed + if (tab.active && tabs.length > 1 && !destroyed) { + //If this is the last tab, select the previous tab. else, the next tab. + var newActiveIndex = index == tabs.length - 1 ? index - 1 : index + 1; + ctrl.select(tabs[newActiveIndex]); + } + tabs.splice(index, 1); + }; + + var destroyed; + $scope.$on('$destroy', function() { + destroyed = true; + }); +}]) + +/** + * @ngdoc directive + * @name ui.bootstrap.tabs.directive:tabset + * @restrict EA + * + * @description + * Tabset is the outer container for the tabs directive + * + * @param {boolean=} vertical Whether or not to use vertical styling for the tabs. + * @param {boolean=} justified Whether or not to use justified styling for the tabs. + * + * @example + + + + First Content! + Second Content! + +
    + + First Vertical Content! + Second Vertical Content! + + + First Justified Content! + Second Justified Content! + +
    +
    + */ +.directive('tabset', function() { + return { + restrict: 'EA', + transclude: true, + replace: true, + scope: { + type: '@' + }, + controller: 'TabsetController', + templateUrl: 'template/tabs/tabset.html', + link: function(scope, element, attrs) { + scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false; + scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false; + } + }; +}) + +/** + * @ngdoc directive + * @name ui.bootstrap.tabs.directive:tab + * @restrict EA + * + * @param {string=} heading The visible heading, or title, of the tab. Set HTML headings with {@link ui.bootstrap.tabs.directive:tabHeading tabHeading}. + * @param {string=} select An expression to evaluate when the tab is selected. + * @param {boolean=} active A binding, telling whether or not this tab is selected. + * @param {boolean=} disabled A binding, telling whether or not this tab is disabled. + * + * @description + * Creates a tab with a heading and content. Must be placed within a {@link ui.bootstrap.tabs.directive:tabset tabset}. + * + * @example + + +
    + + +
    + + First Tab + + Alert me! + Second Tab, with alert callback and html heading! + + + {{item.content}} + + +
    +
    + + function TabsDemoCtrl($scope) { + $scope.items = [ + { title:"Dynamic Title 1", content:"Dynamic Item 0" }, + { title:"Dynamic Title 2", content:"Dynamic Item 1", disabled: true } + ]; + + $scope.alertMe = function() { + setTimeout(function() { + alert("You've selected the alert tab!"); + }); + }; + }; + +
    + */ + +/** + * @ngdoc directive + * @name ui.bootstrap.tabs.directive:tabHeading + * @restrict EA + * + * @description + * Creates an HTML heading for a {@link ui.bootstrap.tabs.directive:tab tab}. Must be placed as a child of a tab element. + * + * @example + + + + + HTML in my titles?! + And some content, too! + + + Icon heading?!? + That's right. + + + + + */ +.directive('tab', ['$parse', '$log', function($parse, $log) { + return { + require: '^tabset', + restrict: 'EA', + replace: true, + templateUrl: 'template/tabs/tab.html', + transclude: true, + scope: { + active: '=?', + heading: '@', + onSelect: '&select', //This callback is called in contentHeadingTransclude + //once it inserts the tab's content into the dom + onDeselect: '&deselect' + }, + controller: function() { + //Empty controller so other directives can require being 'under' a tab + }, + compile: function(elm, attrs, transclude) { + return function postLink(scope, elm, attrs, tabsetCtrl) { + scope.$watch('active', function(active) { + if (active) { + tabsetCtrl.select(scope); + } + }); + + scope.disabled = false; + if ( attrs.disable ) { + scope.$parent.$watch($parse(attrs.disable), function(value) { + scope.disabled = !! value; + }); + } + + // Deprecation support of "disabled" parameter + // fix(tab): IE9 disabled attr renders grey text on enabled tab #2677 + // This code is duplicated from the lines above to make it easy to remove once + // the feature has been completely deprecated + if ( attrs.disabled ) { + $log.warn('Use of "disabled" attribute has been deprecated, please use "disable"'); + scope.$parent.$watch($parse(attrs.disabled), function(value) { + scope.disabled = !! value; + }); + } + + scope.select = function() { + if ( !scope.disabled ) { + scope.active = true; + } + }; + + tabsetCtrl.addTab(scope); + scope.$on('$destroy', function() { + tabsetCtrl.removeTab(scope); + }); + + //We need to transclude later, once the content container is ready. + //when this link happens, we're inside a tab heading. + scope.$transcludeFn = transclude; + }; + } + }; +}]) + +.directive('tabHeadingTransclude', [function() { + return { + restrict: 'A', + require: '^tab', + link: function(scope, elm, attrs, tabCtrl) { + scope.$watch('headingElement', function updateHeadingElement(heading) { + if (heading) { + elm.html(''); + elm.append(heading); + } + }); + } + }; +}]) + +.directive('tabContentTransclude', function() { + return { + restrict: 'A', + require: '^tabset', + link: function(scope, elm, attrs) { + var tab = scope.$eval(attrs.tabContentTransclude); + + //Now our tab is ready to be transcluded: both the tab heading area + //and the tab content area are loaded. Transclude 'em both. + tab.$transcludeFn(tab.$parent, function(contents) { + angular.forEach(contents, function(node) { + if (isTabHeading(node)) { + //Let tabHeadingTransclude know. + tab.headingElement = node; + } else { + elm.append(node); + } + }); + }); + } + }; + function isTabHeading(node) { + return node.tagName && ( + node.hasAttribute('tab-heading') || + node.hasAttribute('data-tab-heading') || + node.tagName.toLowerCase() === 'tab-heading' || + node.tagName.toLowerCase() === 'data-tab-heading' + ); + } +}) + +; + +angular.module('ui.bootstrap.timepicker', []) + +.constant('timepickerConfig', { + hourStep: 1, + minuteStep: 1, + showMeridian: true, + meridians: null, + readonlyInput: false, + mousewheel: true, + arrowkeys: true +}) + +.controller('TimepickerController', ['$scope', '$attrs', '$parse', '$log', '$locale', 'timepickerConfig', function($scope, $attrs, $parse, $log, $locale, timepickerConfig) { + var selected = new Date(), + ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl + meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS; + + this.init = function( ngModelCtrl_, inputs ) { + ngModelCtrl = ngModelCtrl_; + ngModelCtrl.$render = this.render; + + ngModelCtrl.$formatters.unshift(function (modelValue) { + return modelValue ? new Date( modelValue ) : null; + }); + + var hoursInputEl = inputs.eq(0), + minutesInputEl = inputs.eq(1); + + var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel; + if ( mousewheel ) { + this.setupMousewheelEvents( hoursInputEl, minutesInputEl ); + } + + var arrowkeys = angular.isDefined($attrs.arrowkeys) ? $scope.$parent.$eval($attrs.arrowkeys) : timepickerConfig.arrowkeys; + if (arrowkeys) { + this.setupArrowkeyEvents( hoursInputEl, minutesInputEl ); + } + + $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput; + this.setupInputEvents( hoursInputEl, minutesInputEl ); + }; + + var hourStep = timepickerConfig.hourStep; + if ($attrs.hourStep) { + $scope.$parent.$watch($parse($attrs.hourStep), function(value) { + hourStep = parseInt(value, 10); + }); + } + + var minuteStep = timepickerConfig.minuteStep; + if ($attrs.minuteStep) { + $scope.$parent.$watch($parse($attrs.minuteStep), function(value) { + minuteStep = parseInt(value, 10); + }); + } + + // 12H / 24H mode + $scope.showMeridian = timepickerConfig.showMeridian; + if ($attrs.showMeridian) { + $scope.$parent.$watch($parse($attrs.showMeridian), function(value) { + $scope.showMeridian = !!value; + + if ( ngModelCtrl.$error.time ) { + // Evaluate from template + var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate(); + if (angular.isDefined( hours ) && angular.isDefined( minutes )) { + selected.setHours( hours ); + refresh(); + } + } else { + updateTemplate(); + } + }); + } + + // Get $scope.hours in 24H mode if valid + function getHoursFromTemplate ( ) { + var hours = parseInt( $scope.hours, 10 ); + var valid = ( $scope.showMeridian ) ? (hours > 0 && hours < 13) : (hours >= 0 && hours < 24); + if ( !valid ) { + return undefined; + } + + if ( $scope.showMeridian ) { + if ( hours === 12 ) { + hours = 0; + } + if ( $scope.meridian === meridians[1] ) { + hours = hours + 12; + } + } + return hours; + } + + function getMinutesFromTemplate() { + var minutes = parseInt($scope.minutes, 10); + return ( minutes >= 0 && minutes < 60 ) ? minutes : undefined; + } + + function pad( value ) { + return ( angular.isDefined(value) && value.toString().length < 2 ) ? '0' + value : value.toString(); + } + + // Respond on mousewheel spin + this.setupMousewheelEvents = function( hoursInputEl, minutesInputEl ) { + var isScrollingUp = function(e) { + if (e.originalEvent) { + e = e.originalEvent; + } + //pick correct delta variable depending on event + var delta = (e.wheelDelta) ? e.wheelDelta : -e.deltaY; + return (e.detail || delta > 0); + }; + + hoursInputEl.bind('mousewheel wheel', function(e) { + $scope.$apply( (isScrollingUp(e)) ? $scope.incrementHours() : $scope.decrementHours() ); + e.preventDefault(); + }); + + minutesInputEl.bind('mousewheel wheel', function(e) { + $scope.$apply( (isScrollingUp(e)) ? $scope.incrementMinutes() : $scope.decrementMinutes() ); + e.preventDefault(); + }); + + }; + + // Respond on up/down arrowkeys + this.setupArrowkeyEvents = function( hoursInputEl, minutesInputEl ) { + hoursInputEl.bind('keydown', function(e) { + if ( e.which === 38 ) { // up + e.preventDefault(); + $scope.incrementHours(); + $scope.$apply(); + } + else if ( e.which === 40 ) { // down + e.preventDefault(); + $scope.decrementHours(); + $scope.$apply(); + } + }); + + minutesInputEl.bind('keydown', function(e) { + if ( e.which === 38 ) { // up + e.preventDefault(); + $scope.incrementMinutes(); + $scope.$apply(); + } + else if ( e.which === 40 ) { // down + e.preventDefault(); + $scope.decrementMinutes(); + $scope.$apply(); + } + }); + }; + + this.setupInputEvents = function( hoursInputEl, minutesInputEl ) { + if ( $scope.readonlyInput ) { + $scope.updateHours = angular.noop; + $scope.updateMinutes = angular.noop; + return; + } + + var invalidate = function(invalidHours, invalidMinutes) { + ngModelCtrl.$setViewValue( null ); + ngModelCtrl.$setValidity('time', false); + if (angular.isDefined(invalidHours)) { + $scope.invalidHours = invalidHours; + } + if (angular.isDefined(invalidMinutes)) { + $scope.invalidMinutes = invalidMinutes; + } + }; + + $scope.updateHours = function() { + var hours = getHoursFromTemplate(); + + if ( angular.isDefined(hours) ) { + selected.setHours( hours ); + refresh( 'h' ); + } else { + invalidate(true); + } + }; + + hoursInputEl.bind('blur', function(e) { + if ( !$scope.invalidHours && $scope.hours < 10) { + $scope.$apply( function() { + $scope.hours = pad( $scope.hours ); + }); + } + }); + + $scope.updateMinutes = function() { + var minutes = getMinutesFromTemplate(); + + if ( angular.isDefined(minutes) ) { + selected.setMinutes( minutes ); + refresh( 'm' ); + } else { + invalidate(undefined, true); + } + }; + + minutesInputEl.bind('blur', function(e) { + if ( !$scope.invalidMinutes && $scope.minutes < 10 ) { + $scope.$apply( function() { + $scope.minutes = pad( $scope.minutes ); + }); + } + }); + + }; + + this.render = function() { + var date = ngModelCtrl.$viewValue; + + if ( isNaN(date) ) { + ngModelCtrl.$setValidity('time', false); + $log.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); + } else { + if ( date ) { + selected = date; + } + makeValid(); + updateTemplate(); + } + }; + + // Call internally when we know that model is valid. + function refresh( keyboardChange ) { + makeValid(); + ngModelCtrl.$setViewValue( new Date(selected) ); + updateTemplate( keyboardChange ); + } + + function makeValid() { + ngModelCtrl.$setValidity('time', true); + $scope.invalidHours = false; + $scope.invalidMinutes = false; + } + + function updateTemplate( keyboardChange ) { + var hours = selected.getHours(), minutes = selected.getMinutes(); + + if ( $scope.showMeridian ) { + hours = ( hours === 0 || hours === 12 ) ? 12 : hours % 12; // Convert 24 to 12 hour system + } + + $scope.hours = keyboardChange === 'h' ? hours : pad(hours); + if (keyboardChange !== 'm') { + $scope.minutes = pad(minutes); + } + $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1]; + } + + function addMinutes( minutes ) { + var dt = new Date( selected.getTime() + minutes * 60000 ); + selected.setHours( dt.getHours(), dt.getMinutes() ); + refresh(); + } + + $scope.incrementHours = function() { + addMinutes( hourStep * 60 ); + }; + $scope.decrementHours = function() { + addMinutes( - hourStep * 60 ); + }; + $scope.incrementMinutes = function() { + addMinutes( minuteStep ); + }; + $scope.decrementMinutes = function() { + addMinutes( - minuteStep ); + }; + $scope.toggleMeridian = function() { + addMinutes( 12 * 60 * (( selected.getHours() < 12 ) ? 1 : -1) ); + }; +}]) + +.directive('timepicker', function () { + return { + restrict: 'EA', + require: ['timepicker', '?^ngModel'], + controller:'TimepickerController', + replace: true, + scope: {}, + templateUrl: 'template/timepicker/timepicker.html', + link: function(scope, element, attrs, ctrls) { + var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + if ( ngModelCtrl ) { + timepickerCtrl.init( ngModelCtrl, element.find('input') ); + } + } + }; +}); + +angular.module('ui.bootstrap.transition', []) + +.value('$transitionSuppressDeprecated', false) +/** + * $transition service provides a consistent interface to trigger CSS 3 transitions and to be informed when they complete. + * @param {DOMElement} element The DOMElement that will be animated. + * @param {string|object|function} trigger The thing that will cause the transition to start: + * - As a string, it represents the css class to be added to the element. + * - As an object, it represents a hash of style attributes to be applied to the element. + * - As a function, it represents a function to be called that will cause the transition to occur. + * @return {Promise} A promise that is resolved when the transition finishes. + */ +.factory('$transition', [ + '$q', '$timeout', '$rootScope', '$log', '$transitionSuppressDeprecated', +function($q , $timeout , $rootScope , $log , $transitionSuppressDeprecated) { + + if (!$transitionSuppressDeprecated) { + $log.warn('$transition is now deprecated. Use $animate from ngAnimate instead.'); + } + + var $transition = function(element, trigger, options) { + options = options || {}; + var deferred = $q.defer(); + var endEventName = $transition[options.animation ? 'animationEndEventName' : 'transitionEndEventName']; + + var transitionEndHandler = function(event) { + $rootScope.$apply(function() { + element.unbind(endEventName, transitionEndHandler); + deferred.resolve(element); + }); + }; + + if (endEventName) { + element.bind(endEventName, transitionEndHandler); + } + + // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur + $timeout(function() { + if ( angular.isString(trigger) ) { + element.addClass(trigger); + } else if ( angular.isFunction(trigger) ) { + trigger(element); + } else if ( angular.isObject(trigger) ) { + element.css(trigger); + } + //If browser does not support transitions, instantly resolve + if ( !endEventName ) { + deferred.resolve(element); + } + }); + + // Add our custom cancel function to the promise that is returned + // We can call this if we are about to run a new transition, which we know will prevent this transition from ending, + // i.e. it will therefore never raise a transitionEnd event for that transition + deferred.promise.cancel = function() { + if ( endEventName ) { + element.unbind(endEventName, transitionEndHandler); + } + deferred.reject('Transition cancelled'); + }; + + return deferred.promise; + }; + + // Work out the name of the transitionEnd event + var transElement = document.createElement('trans'); + var transitionEndEventNames = { + 'WebkitTransition': 'webkitTransitionEnd', + 'MozTransition': 'transitionend', + 'OTransition': 'oTransitionEnd', + 'transition': 'transitionend' + }; + var animationEndEventNames = { + 'WebkitTransition': 'webkitAnimationEnd', + 'MozTransition': 'animationend', + 'OTransition': 'oAnimationEnd', + 'transition': 'animationend' + }; + function findEndEventName(endEventNames) { + for (var name in endEventNames){ + if (transElement.style[name] !== undefined) { + return endEventNames[name]; + } + } + } + $transition.transitionEndEventName = findEndEventName(transitionEndEventNames); + $transition.animationEndEventName = findEndEventName(animationEndEventNames); + return $transition; +}]); + +angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap.bindHtml']) + +/** + * A helper service that can parse typeahead's syntax (string provided by users) + * Extracted to a separate service for ease of unit testing + */ + .factory('typeaheadParser', ['$parse', function ($parse) { + + // 00000111000000000000022200000000000000003333333333333330000000000044000 + var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/; + + return { + parse:function (input) { + + var match = input.match(TYPEAHEAD_REGEXP); + if (!match) { + throw new Error( + 'Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_"' + + ' but got "' + input + '".'); + } + + return { + itemName:match[3], + source:$parse(match[4]), + viewMapper:$parse(match[2] || match[1]), + modelMapper:$parse(match[1]) + }; + } + }; +}]) + + .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$position', 'typeaheadParser', + function ($compile, $parse, $q, $timeout, $document, $position, typeaheadParser) { + + var HOT_KEYS = [9, 13, 27, 38, 40]; + + return { + require:'ngModel', + link:function (originalScope, element, attrs, modelCtrl) { + + //SUPPORTED ATTRIBUTES (OPTIONS) + + //minimal no of characters that needs to be entered before typeahead kicks-in + var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1; + + //minimal wait time after last character typed before typeahead kicks-in + var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0; + + //should it restrict model values to the ones selected from the popup only? + var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false; + + //binding to a variable that indicates if matches are being retrieved asynchronously + var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop; + + //a callback executed when a match is selected + var onSelectCallback = $parse(attrs.typeaheadOnSelect); + + var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined; + + var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false; + + var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false; + + //INTERNAL VARIABLES + + //model setter executed upon match selection + var $setModelValue = $parse(attrs.ngModel).assign; + + //expressions used by typeahead + var parserResult = typeaheadParser.parse(attrs.typeahead); + + var hasFocus; + + //create a child scope for the typeahead directive so we are not polluting original scope + //with typeahead-specific data (matches, query etc.) + var scope = originalScope.$new(); + originalScope.$on('$destroy', function(){ + scope.$destroy(); + }); + + // WAI-ARIA + var popupId = 'typeahead-' + scope.$id + '-' + Math.floor(Math.random() * 10000); + element.attr({ + 'aria-autocomplete': 'list', + 'aria-expanded': false, + 'aria-owns': popupId + }); + + //pop-up element used to display matches + var popUpEl = angular.element('
    '); + popUpEl.attr({ + id: popupId, + matches: 'matches', + active: 'activeIdx', + select: 'select(activeIdx)', + query: 'query', + position: 'position' + }); + //custom item template + if (angular.isDefined(attrs.typeaheadTemplateUrl)) { + popUpEl.attr('template-url', attrs.typeaheadTemplateUrl); + } + + var resetMatches = function() { + scope.matches = []; + scope.activeIdx = -1; + element.attr('aria-expanded', false); + }; + + var getMatchId = function(index) { + return popupId + '-option-' + index; + }; + + // Indicate that the specified match is the active (pre-selected) item in the list owned by this typeahead. + // This attribute is added or removed automatically when the `activeIdx` changes. + scope.$watch('activeIdx', function(index) { + if (index < 0) { + element.removeAttr('aria-activedescendant'); + } else { + element.attr('aria-activedescendant', getMatchId(index)); + } + }); + + var getMatchesAsync = function(inputValue) { + + var locals = {$viewValue: inputValue}; + isLoadingSetter(originalScope, true); + $q.when(parserResult.source(originalScope, locals)).then(function(matches) { + + //it might happen that several async queries were in progress if a user were typing fast + //but we are interested only in responses that correspond to the current view value + var onCurrentRequest = (inputValue === modelCtrl.$viewValue); + if (onCurrentRequest && hasFocus) { + if (matches && matches.length > 0) { + + scope.activeIdx = focusFirst ? 0 : -1; + scope.matches.length = 0; + + //transform labels + for(var i=0; i= minSearch) { + if (waitTime > 0) { + cancelPreviousTimeout(); + scheduleSearchWithTimeout(inputValue); + } else { + getMatchesAsync(inputValue); + } + } else { + isLoadingSetter(originalScope, false); + cancelPreviousTimeout(); + resetMatches(); + } + + if (isEditable) { + return inputValue; + } else { + if (!inputValue) { + // Reset in case user had typed something previously. + modelCtrl.$setValidity('editable', true); + return inputValue; + } else { + modelCtrl.$setValidity('editable', false); + return undefined; + } + } + }); + + modelCtrl.$formatters.push(function (modelValue) { + + var candidateViewValue, emptyViewValue; + var locals = {}; + + // The validity may be set to false via $parsers (see above) if + // the model is restricted to selected values. If the model + // is set manually it is considered to be valid. + if (!isEditable) { + modelCtrl.$setValidity('editable', true); + } + + if (inputFormatter) { + + locals.$model = modelValue; + return inputFormatter(originalScope, locals); + + } else { + + //it might happen that we don't have enough info to properly render input value + //we need to check for this situation and simply return model value if we can't apply custom formatting + locals[parserResult.itemName] = modelValue; + candidateViewValue = parserResult.viewMapper(originalScope, locals); + locals[parserResult.itemName] = undefined; + emptyViewValue = parserResult.viewMapper(originalScope, locals); + + return candidateViewValue!== emptyViewValue ? candidateViewValue : modelValue; + } + }); + + scope.select = function (activeIdx) { + //called from within the $digest() cycle + var locals = {}; + var model, item; + + locals[parserResult.itemName] = item = scope.matches[activeIdx].model; + model = parserResult.modelMapper(originalScope, locals); + $setModelValue(originalScope, model); + modelCtrl.$setValidity('editable', true); + modelCtrl.$setValidity('parse', true); + + onSelectCallback(originalScope, { + $item: item, + $model: model, + $label: parserResult.viewMapper(originalScope, locals) + }); + + resetMatches(); + + //return focus to the input element if a match was selected via a mouse click event + // use timeout to avoid $rootScope:inprog error + $timeout(function() { element[0].focus(); }, 0, false); + }; + + //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27) + element.bind('keydown', function (evt) { + + //typeahead is open and an "interesting" key was pressed + if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) { + return; + } + + // if there's nothing selected (i.e. focusFirst) and enter is hit, don't do anything + if (scope.activeIdx == -1 && (evt.which === 13 || evt.which === 9)) { + return; + } + + evt.preventDefault(); + + if (evt.which === 40) { + scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length; + scope.$digest(); + + } else if (evt.which === 38) { + scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1; + scope.$digest(); + + } else if (evt.which === 13 || evt.which === 9) { + scope.$apply(function () { + scope.select(scope.activeIdx); + }); + + } else if (evt.which === 27) { + evt.stopPropagation(); + + resetMatches(); + scope.$digest(); + } + }); + + element.bind('blur', function (evt) { + hasFocus = false; + }); + + // Keep reference to click handler to unbind it. + var dismissClickHandler = function (evt) { + if (element[0] !== evt.target) { + resetMatches(); + scope.$digest(); + } + }; + + $document.bind('click', dismissClickHandler); + + originalScope.$on('$destroy', function(){ + $document.unbind('click', dismissClickHandler); + if (appendToBody) { + $popup.remove(); + } + // Prevent jQuery cache memory leak + popUpEl.remove(); + }); + + var $popup = $compile(popUpEl)(scope); + + if (appendToBody) { + $document.find('body').append($popup); + } else { + element.after($popup); + } + } + }; + +}]) + + .directive('typeaheadPopup', function () { + return { + restrict:'EA', + scope:{ + matches:'=', + query:'=', + active:'=', + position:'=', + select:'&' + }, + replace:true, + templateUrl:'template/typeahead/typeahead-popup.html', + link:function (scope, element, attrs) { + + scope.templateUrl = attrs.templateUrl; + + scope.isOpen = function () { + return scope.matches.length > 0; + }; + + scope.isActive = function (matchIdx) { + return scope.active == matchIdx; + }; + + scope.selectActive = function (matchIdx) { + scope.active = matchIdx; + }; + + scope.selectMatch = function (activeIdx) { + scope.select({activeIdx:activeIdx}); + }; + } + }; + }) + + .directive('typeaheadMatch', ['$templateRequest', '$compile', '$parse', function ($templateRequest, $compile, $parse) { + return { + restrict:'EA', + scope:{ + index:'=', + match:'=', + query:'=' + }, + link:function (scope, element, attrs) { + var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'template/typeahead/typeahead-match.html'; + $templateRequest(tplUrl).then(function(tplContent) { + $compile(tplContent.trim())(scope, function(clonedElement){ + element.replaceWith(clonedElement); + }); + }); + } + }; + }]) + + .filter('typeaheadHighlight', function() { + + function escapeRegexp(queryToEscape) { + return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1'); + } + + return function(matchItem, query) { + return query ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : matchItem; + }; + }); + +angular.module("template/accordion/accordion-group.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/accordion/accordion-group.html", + "
    \n" + + "
    \n" + + "

    \n" + + " {{heading}}\n" + + "

    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + ""); +}]); + +angular.module("template/accordion/accordion.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/accordion/accordion.html", + "
    "); +}]); + +angular.module("template/alert/alert.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/alert/alert.html", + "
    \n" + + " \n" + + "
    \n" + + "
    \n" + + ""); +}]); + +angular.module("template/carousel/carousel.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/carousel/carousel.html", + "
    \n" + + "
      1\">\n" + + "
    1. \n" + + "
    \n" + + "
    \n" + + " 1\">\n" + + " 1\">\n" + + "
    \n" + + ""); +}]); + +angular.module("template/carousel/slide.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/carousel/slide.html", + "
    \n" + + ""); +}]); + +angular.module("template/datepicker/datepicker.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/datepicker.html", + "
    \n" + + " \n" + + " \n" + + " \n" + + "
    "); +}]); + +angular.module("template/datepicker/day.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/day.html", + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
    {{label.abbr}}
    {{ weekNumbers[$index] }}\n" + + " \n" + + "
    \n" + + ""); +}]); + +angular.module("template/datepicker/month.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/month.html", + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
    \n" + + " \n" + + "
    \n" + + ""); +}]); + +angular.module("template/datepicker/popup.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/popup.html", + "
      \n" + + "
    • \n" + + "
    • \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
    • \n" + + "
    \n" + + ""); +}]); + +angular.module("template/datepicker/year.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/year.html", + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
    \n" + + " \n" + + "
    \n" + + ""); +}]); + +angular.module("template/modal/backdrop.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/modal/backdrop.html", + "
    \n" + + ""); +}]); + +angular.module("template/modal/window.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/modal/window.html", + "
    \n" + + "
    \n" + + "
    \n" + + ""); +}]); + +angular.module("template/pagination/pager.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/pagination/pager.html", + ""); +}]); + +angular.module("template/pagination/pagination.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/pagination/pagination.html", + ""); +}]); + +angular.module("template/tooltip/tooltip-html-popup.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-html-popup.html", + "
    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + ""); +}]); + +angular.module("template/tooltip/tooltip-html-unsafe-popup.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-html-unsafe-popup.html", + "
    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + ""); +}]); + +angular.module("template/tooltip/tooltip-popup.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-popup.html", + "
    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + ""); +}]); + +angular.module("template/tooltip/tooltip-template-popup.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-template-popup.html", + "
    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + ""); +}]); + +angular.module("template/popover/popover-template.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/popover/popover-template.html", + "
    \n" + + "
    \n" + + "\n" + + "
    \n" + + "

    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + ""); +}]); + +angular.module("template/popover/popover-window.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/popover/popover-window.html", + "
    \n" + + "
    \n" + + "\n" + + "
    \n" + + "

    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + ""); +}]); + +angular.module("template/popover/popover.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/popover/popover.html", + "
    \n" + + "
    \n" + + "\n" + + "
    \n" + + "

    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + ""); +}]); + +angular.module("template/progressbar/bar.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/bar.html", + "
    \n" + + ""); +}]); + +angular.module("template/progressbar/progress.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/progress.html", + "
    "); +}]); + +angular.module("template/progressbar/progressbar.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/progressbar.html", + "
    \n" + + "
    \n" + + "
    \n" + + ""); +}]); + +angular.module("template/rating/rating.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/rating/rating.html", + "\n" + + " \n" + + " ({{ $index < value ? '*' : ' ' }})\n" + + " \n" + + ""); +}]); + +angular.module("template/tabs/tab.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/tabs/tab.html", + "
  • \n" + + " {{heading}}\n" + + "
  • \n" + + ""); +}]); + +angular.module("template/tabs/tabset.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/tabs/tabset.html", + "
    \n" + + "
      \n" + + "
      \n" + + "
      \n" + + "
      \n" + + "
      \n" + + "
      \n" + + ""); +}]); + +angular.module("template/timepicker/timepicker.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/timepicker/timepicker.html", + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
       
      \n" + + " \n" + + " :\n" + + " \n" + + "
       
      \n" + + ""); +}]); + +angular.module("template/typeahead/typeahead-match.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/typeahead/typeahead-match.html", + ""); +}]); + +angular.module("template/typeahead/typeahead-popup.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/typeahead/typeahead-popup.html", + "
        \n" + + "
      • \n" + + "
        \n" + + "
      • \n" + + "
      \n" + + ""); +}]); +!angular.$$csp() && angular.element(document).find('head').prepend(''); \ No newline at end of file diff --git a/turtles/app/lib/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js b/turtles/app/lib/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js new file mode 100644 index 000000000..6d2486283 --- /dev/null +++ b/turtles/app/lib/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js @@ -0,0 +1,10 @@ +/* + * angular-ui-bootstrap + * http://angular-ui.github.io/bootstrap/ + + * Version: 0.13.0 - 2015-05-02 + * License: MIT + */ +angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.transition","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.tpls",["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/carousel/carousel.html","template/carousel/slide.html","template/datepicker/datepicker.html","template/datepicker/day.html","template/datepicker/month.html","template/datepicker/popup.html","template/datepicker/year.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-popup.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/tooltip/tooltip-template-popup.html","template/popover/popover-template.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]),angular.module("ui.bootstrap.collapse",[]).directive("collapse",["$animate",function(a){return{link:function(b,c,d){function e(){c.removeClass("collapse").addClass("collapsing"),a.addClass(c,"in",{to:{height:c[0].scrollHeight+"px"}}).then(f)}function f(){c.removeClass("collapsing"),c.css({height:"auto"})}function g(){c.css({height:c[0].scrollHeight+"px"}).removeClass("collapse").addClass("collapsing"),a.removeClass(c,"in",{to:{height:"0"}}).then(h)}function h(){c.css({height:"0"}),c.removeClass("collapsing"),c.addClass("collapse")}b.$watch(d.collapse,function(a){a?g():e()})}}}]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("accordionConfig",{closeOthers:!0}).controller("AccordionController",["$scope","$attrs","accordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(b,1)}}]).directive("accordion",function(){return{restrict:"EA",controller:"AccordionController",transclude:!0,replace:!1,templateUrl:"template/accordion/accordion.html"}}).directive("accordionGroup",function(){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/accordion/accordion-group.html",scope:{heading:"@",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(a,b,c,d){d.addGroup(a),a.$watch("isOpen",function(b){b&&d.closeOthers(a)}),a.toggleOpen=function(){a.isDisabled||(a.isOpen=!a.isOpen)}}}}).directive("accordionHeading",function(){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",link:function(a,b,c,d,e){d.setHeading(e(a,angular.noop))}}}).directive("accordionTransclude",function(){return{require:"^accordionGroup",link:function(a,b,c,d){a.$watch(function(){return d[c.accordionTransclude]},function(a){a&&(b.html(""),b.append(a))})}}}),angular.module("ui.bootstrap.alert",[]).controller("AlertController",["$scope","$attrs",function(a,b){a.closeable="close"in b,this.close=a.close}]).directive("alert",function(){return{restrict:"EA",controller:"AlertController",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"@",close:"&"}}}).directive("dismissOnTimeout",["$timeout",function(a){return{require:"alert",link:function(b,c,d,e){a(function(){e.close()},parseInt(d.dismissOnTimeout,10))}}}]),angular.module("ui.bootstrap.bindHtml",[]).directive("bindHtmlUnsafe",function(){return function(a,b,c){b.addClass("ng-binding").data("$binding",c.bindHtmlUnsafe),a.$watch(c.bindHtmlUnsafe,function(a){b.html(a||"")})}}),angular.module("ui.bootstrap.buttons",[]).constant("buttonConfig",{activeClass:"active",toggleEvent:"click"}).controller("ButtonsController",["buttonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("btnRadio",function(){return{require:["btnRadio","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){var e=d[0],f=d[1];f.$render=function(){b.toggleClass(e.activeClass,angular.equals(f.$modelValue,a.$eval(c.btnRadio)))},b.bind(e.toggleEvent,function(){var d=b.hasClass(e.activeClass);(!d||angular.isDefined(c.uncheckable))&&a.$apply(function(){f.$setViewValue(d?null:a.$eval(c.btnRadio)),f.$render()})})}}}).directive("btnCheckbox",function(){return{require:["btnCheckbox","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){function e(){return g(c.btnCheckboxTrue,!0)}function f(){return g(c.btnCheckboxFalse,!1)}function g(b,c){var d=a.$eval(b);return angular.isDefined(d)?d:c}var h=d[0],i=d[1];i.$render=function(){b.toggleClass(h.activeClass,angular.equals(i.$modelValue,e()))},b.bind(h.toggleEvent,function(){a.$apply(function(){i.$setViewValue(b.hasClass(h.activeClass)?f():e()),i.$render()})})}}}),angular.module("ui.bootstrap.carousel",[]).controller("CarouselController",["$scope","$interval","$animate",function(a,b,c){function d(a){if(angular.isUndefined(k[a].index))return k[a];{var b;k.length}for(b=0;b0&&(h=b(g,c))}function f(){h&&(b.cancel(h),h=null)}function g(){var b=+a.interval;i&&!isNaN(b)&&b>0?a.next():a.pause()}var h,i,j=this,k=j.slides=a.slides=[],l=-1;j.currentSlide=null;var m=!1;j.select=a.select=function(b,d){function f(){m||(angular.extend(b,{direction:d,active:!0}),angular.extend(j.currentSlide||{},{direction:d,active:!1}),c.enabled()&&!a.noTransition&&b.$element&&(a.$currentTransition=!0,b.$element.one("$animate:close",function(){a.$currentTransition=null})),j.currentSlide=b,l=g,e())}var g=j.indexOfSlide(b);void 0===d&&(d=g>j.getCurrentIndex()?"next":"prev"),b&&b!==j.currentSlide&&f()},a.$on("$destroy",function(){m=!0}),j.getCurrentIndex=function(){return j.currentSlide&&angular.isDefined(j.currentSlide.index)?+j.currentSlide.index:l},j.indexOfSlide=function(a){return angular.isDefined(a.index)?+a.index:k.indexOf(a)},a.next=function(){var b=(j.getCurrentIndex()+1)%k.length;return a.$currentTransition?void 0:j.select(d(b),"next")},a.prev=function(){var b=j.getCurrentIndex()-1<0?k.length-1:j.getCurrentIndex()-1;return a.$currentTransition?void 0:j.select(d(b),"prev")},a.isActive=function(a){return j.currentSlide===a},a.$watch("interval",e),a.$on("$destroy",f),a.play=function(){i||(i=!0,e())},a.pause=function(){a.noPause||(i=!1,f())},j.addSlide=function(b,c){b.$element=c,k.push(b),1===k.length||b.active?(j.select(k[k.length-1]),1==k.length&&a.play()):b.active=!1},j.removeSlide=function(a){angular.isDefined(a.index)&&k.sort(function(a,b){return+a.index>+b.index});var b=k.indexOf(a);k.splice(b,1),k.length>0&&a.active?j.select(b>=k.length?k[b-1]:k[b]):l>b&&l--}}]).directive("carousel",[function(){return{restrict:"EA",transclude:!0,replace:!0,controller:"CarouselController",require:"carousel",templateUrl:"template/carousel/carousel.html",scope:{interval:"=",noTransition:"=",noPause:"="}}}]).directive("slide",function(){return{require:"^carousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/carousel/slide.html",scope:{active:"=?",index:"=?"},link:function(a,b,c,d){d.addSlide(a,b),a.$on("$destroy",function(){d.removeSlide(a)}),a.$watch("active",function(b){b&&d.select(a)})}}}).animation(".item",["$animate",function(a){return{beforeAddClass:function(b,c,d){if("active"==c&&b.parent()&&!b.parent().scope().noTransition){var e=!1,f=b.isolateScope().direction,g="next"==f?"left":"right";return b.addClass(f),a.addClass(b,g).then(function(){e||b.removeClass(g+" "+f),d()}),function(){e=!0}}d()},beforeRemoveClass:function(b,c,d){if("active"==c&&b.parent()&&!b.parent().scope().noTransition){var e=!1,f=b.isolateScope().direction,g="next"==f?"left":"right";return a.addClass(b,g).then(function(){e||b.removeClass(g),d()}),function(){e=!0}}d()}}}]),angular.module("ui.bootstrap.dateparser",[]).service("dateParser",["$locale","orderByFilter",function(a,b){function c(a){var c=[],d=a.split("");return angular.forEach(f,function(b,e){var f=a.indexOf(e);if(f>-1){a=a.split(""),d[f]="("+b.regex+")",a[f]="$";for(var g=f+1,h=f+e.length;h>g;g++)d[g]="",a[g]="$";a=a.join(""),c.push({index:f,apply:b.apply})}}),{regex:new RegExp("^"+d.join("")+"$"),map:b(c,"index")}}function d(a,b,c){return 1>c?!1:1===b&&c>28?29===c&&(a%4===0&&a%100!==0||a%400===0):3===b||5===b||8===b||10===b?31>c:!0}var e=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;this.parsers={};var f={yyyy:{regex:"\\d{4}",apply:function(a){this.year=+a}},yy:{regex:"\\d{2}",apply:function(a){this.year=+a+2e3}},y:{regex:"\\d{1,4}",apply:function(a){this.year=+a}},MMMM:{regex:a.DATETIME_FORMATS.MONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.MONTH.indexOf(b)}},MMM:{regex:a.DATETIME_FORMATS.SHORTMONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.SHORTMONTH.indexOf(b)}},MM:{regex:"0[1-9]|1[0-2]",apply:function(a){this.month=a-1}},M:{regex:"[1-9]|1[0-2]",apply:function(a){this.month=a-1}},dd:{regex:"[0-2][0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},d:{regex:"[1-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},EEEE:{regex:a.DATETIME_FORMATS.DAY.join("|")},EEE:{regex:a.DATETIME_FORMATS.SHORTDAY.join("|")},HH:{regex:"(?:0|1)[0-9]|2[0-3]",apply:function(a){this.hours=+a}},H:{regex:"1?[0-9]|2[0-3]",apply:function(a){this.hours=+a}},mm:{regex:"[0-5][0-9]",apply:function(a){this.minutes=+a}},m:{regex:"[0-9]|[1-5][0-9]",apply:function(a){this.minutes=+a}},sss:{regex:"[0-9][0-9][0-9]",apply:function(a){this.milliseconds=+a}},ss:{regex:"[0-5][0-9]",apply:function(a){this.seconds=+a}},s:{regex:"[0-9]|[1-5][0-9]",apply:function(a){this.seconds=+a}}};this.parse=function(b,f,g){if(!angular.isString(b)||!f)return b;f=a.DATETIME_FORMATS[f]||f,f=f.replace(e,"\\$&"),this.parsers[f]||(this.parsers[f]=c(f));var h=this.parsers[f],i=h.regex,j=h.map,k=b.match(i);if(k&&k.length){var l,m;l=g?{year:g.getFullYear(),month:g.getMonth(),date:g.getDate(),hours:g.getHours(),minutes:g.getMinutes(),seconds:g.getSeconds(),milliseconds:g.getMilliseconds()}:{year:1900,month:0,date:1,hours:0,minutes:0,seconds:0,milliseconds:0};for(var n=1,o=k.length;o>n;n++){var p=j[n-1];p.apply&&p.apply.call(l,k[n])}return d(l.year,l.month,l.date)&&(m=new Date(l.year,l.month,l.date,l.hours,l.minutes,l.seconds,l.milliseconds||0)),m}}}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(a,b){function c(a,c){return a.currentStyle?a.currentStyle[c]:b.getComputedStyle?b.getComputedStyle(a)[c]:a.style[c]}function d(a){return"static"===(c(a,"position")||"static")}var e=function(b){for(var c=a[0],e=b.offsetParent||c;e&&e!==c&&d(e);)e=e.offsetParent;return e||c};return{position:function(b){var c=this.offset(b),d={top:0,left:0},f=e(b[0]);f!=a[0]&&(d=this.offset(angular.element(f)),d.top+=f.clientTop-f.scrollTop,d.left+=f.clientLeft-f.scrollLeft);var g=b[0].getBoundingClientRect();return{width:g.width||b.prop("offsetWidth"),height:g.height||b.prop("offsetHeight"),top:c.top-d.top,left:c.left-d.left}},offset:function(c){var d=c[0].getBoundingClientRect();return{width:d.width||c.prop("offsetWidth"),height:d.height||c.prop("offsetHeight"),top:d.top+(b.pageYOffset||a[0].documentElement.scrollTop),left:d.left+(b.pageXOffset||a[0].documentElement.scrollLeft)}},positionElements:function(a,b,c,d){var e,f,g,h,i=c.split("-"),j=i[0],k=i[1]||"center";e=d?this.offset(a):this.position(a),f=b.prop("offsetWidth"),g=b.prop("offsetHeight");var l={center:function(){return e.left+e.width/2-f/2},left:function(){return e.left},right:function(){return e.left+e.width}},m={center:function(){return e.top+e.height/2-g/2},top:function(){return e.top},bottom:function(){return e.top+e.height}};switch(j){case"right":h={top:m[k](),left:l[j]()};break;case"left":h={top:m[k](),left:e.left-f};break;case"bottom":h={top:m[j](),left:l[k]()};break;default:h={top:e.top-g,left:l[k]()}}return h}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.dateparser","ui.bootstrap.position"]).constant("datepickerConfig",{formatDay:"dd",formatMonth:"MMMM",formatYear:"yyyy",formatDayHeader:"EEE",formatDayTitle:"MMMM yyyy",formatMonthTitle:"yyyy",datepickerMode:"day",minMode:"day",maxMode:"year",showWeeks:!0,startingDay:0,yearRange:20,minDate:null,maxDate:null,shortcutPropagation:!1}).controller("DatepickerController",["$scope","$attrs","$parse","$interpolate","$timeout","$log","dateFilter","datepickerConfig",function(a,b,c,d,e,f,g,h){var i=this,j={$setViewValue:angular.noop};this.modes=["day","month","year"],angular.forEach(["formatDay","formatMonth","formatYear","formatDayHeader","formatDayTitle","formatMonthTitle","minMode","maxMode","showWeeks","startingDay","yearRange","shortcutPropagation"],function(c,e){i[c]=angular.isDefined(b[c])?8>e?d(b[c])(a.$parent):a.$parent.$eval(b[c]):h[c]}),angular.forEach(["minDate","maxDate"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(a){i[d]=a?new Date(a):null,i.refreshView()}):i[d]=h[d]?new Date(h[d]):null}),a.datepickerMode=a.datepickerMode||h.datepickerMode,a.maxMode=i.maxMode,a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),angular.isDefined(b.initDate)?(this.activeDate=a.$parent.$eval(b.initDate)||new Date,a.$parent.$watch(b.initDate,function(a){a&&(j.$isEmpty(j.$modelValue)||j.$invalid)&&(i.activeDate=a,i.refreshView())})):this.activeDate=new Date,a.isActive=function(b){return 0===i.compare(b.date,i.activeDate)?(a.activeDateId=b.uid,!0):!1},this.init=function(a){j=a,j.$render=function(){i.render()}},this.render=function(){if(j.$viewValue){var a=new Date(j.$viewValue),b=!isNaN(a);b?this.activeDate=a:f.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'),j.$setValidity("date",b)}this.refreshView()},this.refreshView=function(){if(this.element){this._refreshView();var a=j.$viewValue?new Date(j.$viewValue):null;j.$setValidity("date-disabled",!a||this.element&&!this.isDisabled(a))}},this.createDateObject=function(a,b){var c=j.$viewValue?new Date(j.$viewValue):null;return{date:a,label:g(a,b),selected:c&&0===this.compare(a,c),disabled:this.isDisabled(a),current:0===this.compare(a,new Date),customClass:this.customClass(a)}},this.isDisabled=function(c){return this.minDate&&this.compare(c,this.minDate)<0||this.maxDate&&this.compare(c,this.maxDate)>0||b.dateDisabled&&a.dateDisabled({date:c,mode:a.datepickerMode})},this.customClass=function(b){return a.customClass({date:b,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},a.select=function(b){if(a.datepickerMode===i.minMode){var c=j.$viewValue?new Date(j.$viewValue):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),j.$setViewValue(c),j.$render()}else i.activeDate=b,a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)-1]},a.move=function(a){var b=i.activeDate.getFullYear()+a*(i.step.years||0),c=i.activeDate.getMonth()+a*(i.step.months||0);i.activeDate.setFullYear(b,c,1),i.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===i.maxMode&&1===b||a.datepickerMode===i.minMode&&-1===b||(a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)+b])},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var k=function(){e(function(){i.element[0].focus()},0,!1)};a.$on("datepicker.focus",k),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey)if(b.preventDefault(),i.shortcutPropagation||b.stopPropagation(),"enter"===c||"space"===c){if(i.isDisabled(i.activeDate))return;a.select(i.activeDate),k()}else!b.ctrlKey||"up"!==c&&"down"!==c?(i.handleKeyDown(c,b),i.refreshView()):(a.toggleMode("up"===c?1:-1),k())}}]).directive("datepicker",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/datepicker.html",scope:{datepickerMode:"=?",dateDisabled:"&",customClass:"&",shortcutPropagation:"&?"},require:["datepicker","?^ngModel"],controller:"DatepickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f)}}}).directive("daypicker",["dateFilter",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/day.html",require:"^datepicker",link:function(b,c,d,e){function f(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?i[b]:29}function g(a,b){var c=new Array(b),d=new Date(a),e=0;for(d.setHours(12);b>e;)c[e++]=new Date(d),d.setDate(d.getDate()+1);return c}function h(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}b.showWeeks=e.showWeeks,e.step={months:1},e.element=c;var i=[31,28,31,30,31,30,31,31,30,31,30,31];e._refreshView=function(){var c=e.activeDate.getFullYear(),d=e.activeDate.getMonth(),f=new Date(c,d,1),i=e.startingDay-f.getDay(),j=i>0?7-i:-i,k=new Date(f);j>0&&k.setDate(-j+1);for(var l=g(k,42),m=0;42>m;m++)l[m]=angular.extend(e.createDateObject(l[m],e.formatDay),{secondary:l[m].getMonth()!==d,uid:b.uniqueId+"-"+m});b.labels=new Array(7);for(var n=0;7>n;n++)b.labels[n]={abbr:a(l[n].date,e.formatDayHeader),full:a(l[n].date,"EEEE")};if(b.title=a(e.activeDate,e.formatDayTitle),b.rows=e.split(l,7),b.showWeeks){b.weekNumbers=[];for(var o=(11-e.startingDay)%7,p=b.rows.length,q=0;p>q;q++)b.weekNumbers.push(h(b.rows[q][o].date))}},e.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth(),a.getDate())-new Date(b.getFullYear(),b.getMonth(),b.getDate())},e.handleKeyDown=function(a){var b=e.activeDate.getDate();if("left"===a)b-=1;else if("up"===a)b-=7;else if("right"===a)b+=1;else if("down"===a)b+=7;else if("pageup"===a||"pagedown"===a){var c=e.activeDate.getMonth()+("pageup"===a?-1:1);e.activeDate.setMonth(c,1),b=Math.min(f(e.activeDate.getFullYear(),e.activeDate.getMonth()),b)}else"home"===a?b=1:"end"===a&&(b=f(e.activeDate.getFullYear(),e.activeDate.getMonth()));e.activeDate.setDate(b)},e.refreshView()}}}]).directive("monthpicker",["dateFilter",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/month.html",require:"^datepicker",link:function(b,c,d,e){e.step={years:1},e.element=c,e._refreshView=function(){for(var c=new Array(12),d=e.activeDate.getFullYear(),f=0;12>f;f++)c[f]=angular.extend(e.createDateObject(new Date(d,f,1),e.formatMonth),{uid:b.uniqueId+"-"+f});b.title=a(e.activeDate,e.formatMonthTitle),b.rows=e.split(c,3)},e.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth())-new Date(b.getFullYear(),b.getMonth())},e.handleKeyDown=function(a){var b=e.activeDate.getMonth();if("left"===a)b-=1;else if("up"===a)b-=3;else if("right"===a)b+=1;else if("down"===a)b+=3;else if("pageup"===a||"pagedown"===a){var c=e.activeDate.getFullYear()+("pageup"===a?-1:1);e.activeDate.setFullYear(c)}else"home"===a?b=0:"end"===a&&(b=11);e.activeDate.setMonth(b)},e.refreshView()}}}]).directive("yearpicker",["dateFilter",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/year.html",require:"^datepicker",link:function(a,b,c,d){function e(a){return parseInt((a-1)/f,10)*f+1}var f=d.yearRange;d.step={years:f},d.element=b,d._refreshView=function(){for(var b=new Array(f),c=0,g=e(d.activeDate.getFullYear());f>c;c++)b[c]=angular.extend(d.createDateObject(new Date(g+c,0,1),d.formatYear),{uid:a.uniqueId+"-"+c});a.title=[b[0].label,b[f-1].label].join(" - "),a.rows=d.split(b,5)},d.compare=function(a,b){return a.getFullYear()-b.getFullYear()},d.handleKeyDown=function(a){var b=d.activeDate.getFullYear();"left"===a?b-=1:"up"===a?b-=5:"right"===a?b+=1:"down"===a?b+=5:"pageup"===a||"pagedown"===a?b+=("pageup"===a?-1:1)*d.step.years:"home"===a?b=e(d.activeDate.getFullYear()):"end"===a&&(b=e(d.activeDate.getFullYear())+f-1),d.activeDate.setFullYear(b)},d.refreshView()}}}]).constant("datepickerPopupConfig",{datepickerPopup:"yyyy-MM-dd",html5Types:{date:"yyyy-MM-dd","datetime-local":"yyyy-MM-ddTHH:mm:ss.sss",month:"yyyy-MM"},currentText:"Today",clearText:"Clear",closeText:"Done",closeOnDateSelection:!0,appendToBody:!1,showButtonBar:!0}).directive("datepickerPopup",["$compile","$parse","$document","$position","dateFilter","dateParser","datepickerPopupConfig",function(a,b,c,d,e,f,g){return{restrict:"EA",require:"ngModel",scope:{isOpen:"=?",currentText:"@",clearText:"@",closeText:"@",dateDisabled:"&",customClass:"&"},link:function(h,i,j,k){function l(a){return a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})}function m(a){if(angular.isNumber(a)&&(a=new Date(a)),a){if(angular.isDate(a)&&!isNaN(a))return a;if(angular.isString(a)){var b=f.parse(a,o,h.date)||new Date(a);return isNaN(b)?void 0:b}return void 0}return null}function n(a,b){var c=a||b;if(angular.isNumber(c)&&(c=new Date(c)),c){if(angular.isDate(c)&&!isNaN(c))return!0;if(angular.isString(c)){var d=f.parse(c,o)||new Date(c);return!isNaN(d)}return!1}return!0}var o,p=angular.isDefined(j.closeOnDateSelection)?h.$parent.$eval(j.closeOnDateSelection):g.closeOnDateSelection,q=angular.isDefined(j.datepickerAppendToBody)?h.$parent.$eval(j.datepickerAppendToBody):g.appendToBody;h.showButtonBar=angular.isDefined(j.showButtonBar)?h.$parent.$eval(j.showButtonBar):g.showButtonBar,h.getText=function(a){return h[a+"Text"]||g[a+"Text"]};var r=!1;if(g.html5Types[j.type]?(o=g.html5Types[j.type],r=!0):(o=j.datepickerPopup||g.datepickerPopup,j.$observe("datepickerPopup",function(a){var b=a||g.datepickerPopup;if(b!==o&&(o=b,k.$modelValue=null,!o))throw new Error("datepickerPopup must have a date format specified.")})),!o)throw new Error("datepickerPopup must have a date format specified.");if(r&&j.datepickerPopup)throw new Error("HTML5 date input types do not support custom formats.");var s=angular.element("
      ");s.attr({"ng-model":"date","ng-change":"dateSelection()"});var t=angular.element(s.children()[0]);if(r&&"month"==j.type&&(t.attr("datepicker-mode",'"month"'),t.attr("min-mode","month")),j.datepickerOptions){var u=h.$parent.$eval(j.datepickerOptions);u.initDate&&(h.initDate=u.initDate,t.attr("init-date","initDate"),delete u.initDate),angular.forEach(u,function(a,b){t.attr(l(b),a)})}h.watchData={},angular.forEach(["minDate","maxDate","datepickerMode","initDate","shortcutPropagation"],function(a){if(j[a]){var c=b(j[a]);if(h.$parent.$watch(c,function(b){h.watchData[a]=b}),t.attr(l(a),"watchData."+a),"datepickerMode"===a){var d=c.assign;h.$watch("watchData."+a,function(a,b){a!==b&&d(h.$parent,a)})}}}),j.dateDisabled&&t.attr("date-disabled","dateDisabled({ date: date, mode: mode })"),j.showWeeks&&t.attr("show-weeks",j.showWeeks),j.customClass&&t.attr("custom-class","customClass({ date: date, mode: mode })"),r?k.$formatters.push(function(a){return h.date=a,a}):(k.$$parserName="date",k.$validators.date=n,k.$parsers.unshift(m),k.$formatters.push(function(a){return h.date=a,k.$isEmpty(a)?a:e(a,o)})),h.dateSelection=function(a){angular.isDefined(a)&&(h.date=a);var b=h.date?e(h.date,o):"";i.val(b),k.$setViewValue(b),p&&(h.isOpen=!1,i[0].focus())},k.$viewChangeListeners.push(function(){h.date=f.parse(k.$viewValue,o,h.date)||new Date(k.$viewValue)});var v=function(a){h.isOpen&&a.target!==i[0]&&h.$apply(function(){h.isOpen=!1})},w=function(a){h.keydown(a)};i.bind("keydown",w),h.keydown=function(a){27===a.which?(a.preventDefault(),h.isOpen&&a.stopPropagation(),h.close()):40!==a.which||h.isOpen||(h.isOpen=!0)},h.$watch("isOpen",function(a){a?(h.$broadcast("datepicker.focus"),h.position=q?d.offset(i):d.position(i),h.position.top=h.position.top+i.prop("offsetHeight"),c.bind("click",v)):c.unbind("click",v)}),h.select=function(a){if("today"===a){var b=new Date;angular.isDate(h.date)?(a=new Date(h.date),a.setFullYear(b.getFullYear(),b.getMonth(),b.getDate())):a=new Date(b.setHours(0,0,0,0))}h.dateSelection(a)},h.close=function(){h.isOpen=!1,i[0].focus()};var x=a(s)(h);s.remove(),q?c.find("body").append(x):i.after(x),h.$on("$destroy",function(){x.remove(),i.unbind("keydown",w),c.unbind("click",v)})}}}]).directive("datepickerPopupWrap",function(){return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"template/datepicker/popup.html",link:function(a,b){b.bind("click",function(a){a.preventDefault(),a.stopPropagation()})}}}),angular.module("ui.bootstrap.dropdown",["ui.bootstrap.position"]).constant("dropdownConfig",{openClass:"open"}).service("dropdownService",["$document","$rootScope",function(a,b){var c=null;this.open=function(b){c||(a.bind("click",d),a.bind("keydown",e)),c&&c!==b&&(c.isOpen=!1),c=b},this.close=function(b){c===b&&(c=null,a.unbind("click",d),a.unbind("keydown",e))};var d=function(a){if(c&&(!a||"disabled"!==c.getAutoClose())){var d=c.getToggleElement();if(!(a&&d&&d[0].contains(a.target))){var e=c.getElement();a&&"outsideClick"===c.getAutoClose()&&e&&e[0].contains(a.target)||(c.isOpen=!1,b.$$phase||c.$apply())}}},e=function(a){27===a.which&&(c.focusToggleElement(),d())}}]).controller("DropdownController",["$scope","$attrs","$parse","dropdownConfig","dropdownService","$animate","$position","$document",function(a,b,c,d,e,f,g,h){var i,j=this,k=a.$new(),l=d.openClass,m=angular.noop,n=b.onToggle?c(b.onToggle):angular.noop,o=!1;this.init=function(d){j.$element=d,b.isOpen&&(i=c(b.isOpen),m=i.assign,a.$watch(i,function(a){k.isOpen=!!a})),o=angular.isDefined(b.dropdownAppendToBody),o&&j.dropdownMenu&&(h.find("body").append(j.dropdownMenu),d.on("$destroy",function(){j.dropdownMenu.remove()}))},this.toggle=function(a){return k.isOpen=arguments.length?!!a:!k.isOpen},this.isOpen=function(){return k.isOpen},k.getToggleElement=function(){return j.toggleElement},k.getAutoClose=function(){return b.autoClose||"always"},k.getElement=function(){return j.$element},k.focusToggleElement=function(){j.toggleElement&&j.toggleElement[0].focus()},k.$watch("isOpen",function(b,c){if(o&&j.dropdownMenu){var d=g.positionElements(j.$element,j.dropdownMenu,"bottom-left",!0);j.dropdownMenu.css({top:d.top+"px",left:d.left+"px",display:b?"block":"none"})}f[b?"addClass":"removeClass"](j.$element,l),b?(k.focusToggleElement(),e.open(k)):e.close(k),m(a,b),angular.isDefined(b)&&b!==c&&n(a,{open:!!b})}),a.$on("$locationChangeSuccess",function(){k.isOpen=!1}),a.$on("$destroy",function(){k.$destroy()})}]).directive("dropdown",function(){return{controller:"DropdownController",link:function(a,b,c,d){d.init(b)}}}).directive("dropdownMenu",function(){return{restrict:"AC",require:"?^dropdown",link:function(a,b,c,d){d&&(d.dropdownMenu=b)}}}).directive("dropdownToggle",function(){return{require:"?^dropdown",link:function(a,b,c,d){if(d){d.toggleElement=b;var e=function(e){e.preventDefault(),b.hasClass("disabled")||c.disabled||a.$apply(function(){d.toggle()})};b.bind("click",e),b.attr({"aria-haspopup":!0,"aria-expanded":!1}),a.$watch(d.isOpen,function(a){b.attr("aria-expanded",!!a)}),a.$on("$destroy",function(){b.unbind("click",e)})}}}}),angular.module("ui.bootstrap.modal",[]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c0),i()})}function i(){if(l&&-1==g()){var a=m;j(l,m,function(){a=null}),l=void 0,m=void 0}}function j(c,d,f){function g(){g.done||(g.done=!0,c.remove(),d.$destroy(),f&&f())}d.animate=!1,c.attr("modal-animation")&&a.enabled()?c.one("$animate:close",function(){e.$evalAsync(g)}):b(g)}function k(a,b,c){return!a.value.modalScope.$broadcast("modal.closing",b,c).defaultPrevented}var l,m,n="modal-open",o=f.createNew(),p={};return e.$watch(g,function(a){m&&(m.index=a)}),c.bind("keydown",function(a){var b;27===a.which&&(b=o.top(),b&&b.value.keyboard&&(a.preventDefault(),e.$apply(function(){p.dismiss(b.key,"escape key press")})))}),p.open=function(a,b){var f=c[0].activeElement;o.add(a,{deferred:b.deferred,renderDeferred:b.renderDeferred,modalScope:b.scope,backdrop:b.backdrop,keyboard:b.keyboard});var h=c.find("body").eq(0),i=g();if(i>=0&&!l){m=e.$new(!0),m.index=i;var j=angular.element('
      ');j.attr("backdrop-class",b.backdropClass),b.animation&&j.attr("modal-animation","true"),l=d(j)(m),h.append(l)}var k=angular.element('
      ');k.attr({"template-url":b.windowTemplateUrl,"window-class":b.windowClass,size:b.size,index:o.length()-1,animate:"animate"}).html(b.content),b.animation&&k.attr("modal-animation","true");var p=d(k)(b.scope);o.top().value.modalDomEl=p,o.top().value.modalOpener=f,h.append(p),h.addClass(n)},p.close=function(a,b){var c=o.get(a);return c&&k(c,b,!0)?(c.value.deferred.resolve(b),h(a),c.value.modalOpener.focus(),!0):!c},p.dismiss=function(a,b){var c=o.get(a);return c&&k(c,b,!1)?(c.value.deferred.reject(b),h(a),c.value.modalOpener.focus(),!0):!c},p.dismissAll=function(a){for(var b=this.getTop();b&&this.dismiss(b.key,a);)b=this.getTop()},p.getTop=function(){return o.top()},p.modalRendered=function(a){var b=o.get(a);b&&b.value.renderDeferred.resolve()},p}]).provider("$modal",function(){var a={options:{animation:!0,backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$templateRequest","$controller","$modalStack",function(b,c,d,e,f,g){function h(a){return a.template?d.when(a.template):e(angular.isFunction(a.templateUrl)?a.templateUrl():a.templateUrl)}function i(a){var c=[];return angular.forEach(a,function(a){(angular.isFunction(a)||angular.isArray(a))&&c.push(d.when(b.invoke(a))) +}),c}var j={};return j.open=function(b){var e=d.defer(),j=d.defer(),k=d.defer(),l={result:e.promise,opened:j.promise,rendered:k.promise,close:function(a){return g.close(l,a)},dismiss:function(a){return g.dismiss(l,a)}};if(b=angular.extend({},a.options,b),b.resolve=b.resolve||{},!b.template&&!b.templateUrl)throw new Error("One of template or templateUrl options is required.");var m=d.all([h(b)].concat(i(b.resolve)));return m.then(function(a){var d=(b.scope||c).$new();d.$close=l.close,d.$dismiss=l.dismiss;var h,i={},j=1;b.controller&&(i.$scope=d,i.$modalInstance=l,angular.forEach(b.resolve,function(b,c){i[c]=a[j++]}),h=f(b.controller,i),b.controllerAs&&(d[b.controllerAs]=h)),g.open(l,{scope:d,deferred:e,renderDeferred:k,content:a[0],animation:b.animation,backdrop:b.backdrop,keyboard:b.keyboard,backdropClass:b.backdropClass,windowClass:b.windowClass,windowTemplateUrl:b.windowTemplateUrl,size:b.size})},function(a){e.reject(a)}),m.then(function(){j.resolve(!0)},function(a){j.reject(a)}),l},j}]};return a}),angular.module("ui.bootstrap.pagination",[]).controller("PaginationController",["$scope","$attrs","$parse",function(a,b,c){var d=this,e={$setViewValue:angular.noop},f=b.numPages?c(b.numPages).assign:angular.noop;this.init=function(g,h){e=g,this.config=h,e.$render=function(){d.render()},b.itemsPerPage?a.$parent.$watch(c(b.itemsPerPage),function(b){d.itemsPerPage=parseInt(b,10),a.totalPages=d.calculateTotalPages()}):this.itemsPerPage=h.itemsPerPage,a.$watch("totalItems",function(){a.totalPages=d.calculateTotalPages()}),a.$watch("totalPages",function(b){f(a.$parent,b),a.page>b?a.selectPage(b):e.$render()})},this.calculateTotalPages=function(){var b=this.itemsPerPage<1?1:Math.ceil(a.totalItems/this.itemsPerPage);return Math.max(b||0,1)},this.render=function(){a.page=parseInt(e.$viewValue,10)||1},a.selectPage=function(b,c){a.page!==b&&b>0&&b<=a.totalPages&&(c&&c.target&&c.target.blur(),e.$setViewValue(b),e.$render())},a.getText=function(b){return a[b+"Text"]||d.config[b+"Text"]},a.noPrevious=function(){return 1===a.page},a.noNext=function(){return a.page===a.totalPages}}]).constant("paginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("pagination",["$parse","paginationConfig",function(a,b){return{restrict:"EA",scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@"},require:["pagination","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pagination.html",replace:!0,link:function(c,d,e,f){function g(a,b,c){return{number:a,text:b,active:c}}function h(a,b){var c=[],d=1,e=b,f=angular.isDefined(k)&&b>k;f&&(l?(d=Math.max(a-Math.floor(k/2),1),e=d+k-1,e>b&&(e=b,d=e-k+1)):(d=(Math.ceil(a/k)-1)*k+1,e=Math.min(d+k-1,b)));for(var h=d;e>=h;h++){var i=g(h,h,h===a);c.push(i)}if(f&&!l){if(d>1){var j=g(d-1,"...",!1);c.unshift(j)}if(b>e){var m=g(e+1,"...",!1);c.push(m)}}return c}var i=f[0],j=f[1];if(j){var k=angular.isDefined(e.maxSize)?c.$parent.$eval(e.maxSize):b.maxSize,l=angular.isDefined(e.rotate)?c.$parent.$eval(e.rotate):b.rotate;c.boundaryLinks=angular.isDefined(e.boundaryLinks)?c.$parent.$eval(e.boundaryLinks):b.boundaryLinks,c.directionLinks=angular.isDefined(e.directionLinks)?c.$parent.$eval(e.directionLinks):b.directionLinks,i.init(j,b),e.maxSize&&c.$parent.$watch(a(e.maxSize),function(a){k=parseInt(a,10),i.render()});var m=i.render;i.render=function(){m(),c.page>0&&c.page<=c.totalPages&&(c.pages=h(c.page,c.totalPages))}}}}}]).constant("pagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("pager",["pagerConfig",function(a){return{restrict:"EA",scope:{totalItems:"=",previousText:"@",nextText:"@"},require:["pager","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pager.html",replace:!0,link:function(b,c,d,e){var f=e[0],g=e[1];g&&(b.align=angular.isDefined(d.align)?b.$parent.$eval(d.align):a.align,f.init(g,a))}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).provider("$tooltip",function(){function a(a){var b=/[A-Z]/g,c="-";return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var b={placement:"top",animation:!0,popupDelay:0,useContentExp:!1},c={mouseenter:"mouseleave",click:"click",focus:"blur"},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$document","$position","$interpolate",function(e,f,g,h,i,j){return function(e,k,l,m){function n(a){var b=a||m.trigger||l,d=c[b]||b;return{show:b,hide:d}}m=angular.extend({},b,d,m);var o=a(e),p=j.startSymbol(),q=j.endSymbol(),r="
      ';return{restrict:"EA",compile:function(){var a=f(r);return function(b,c,d){function f(){E.isOpen?l():j()}function j(){(!D||b.$eval(d[k+"Enable"]))&&(s(),E.popupDelay?A||(A=g(o,E.popupDelay,!1),A.then(function(a){a()})):o()())}function l(){b.$apply(function(){p()})}function o(){return A=null,z&&(g.cancel(z),z=null),(m.useContentExp?E.contentExp():E.content)?(q(),x.css({top:0,left:0,display:"block"}),E.$digest(),F(),E.isOpen=!0,E.$apply(),F):angular.noop}function p(){E.isOpen=!1,g.cancel(A),A=null,E.animation?z||(z=g(r,500)):r()}function q(){x&&r(),y=E.$new(),x=a(y,function(a){B?h.find("body").append(a):c.after(a)}),y.$watch(function(){g(F,0,!1)}),m.useContentExp&&y.$watch("contentExp()",function(a){!a&&E.isOpen&&p()})}function r(){z=null,x&&(x.remove(),x=null),y&&(y.$destroy(),y=null)}function s(){t(),u(),v()}function t(){E.popupClass=d[k+"Class"]}function u(){var a=d[k+"Placement"];E.placement=angular.isDefined(a)?a:m.placement}function v(){var a=d[k+"PopupDelay"],b=parseInt(a,10);E.popupDelay=isNaN(b)?m.popupDelay:b}function w(){var a=d[k+"Trigger"];G(),C=n(a),C.show===C.hide?c.bind(C.show,f):(c.bind(C.show,j),c.bind(C.hide,l))}var x,y,z,A,B=angular.isDefined(m.appendToBody)?m.appendToBody:!1,C=n(void 0),D=angular.isDefined(d[k+"Enable"]),E=b.$new(!0),F=function(){if(x){var a=i.positionElements(c,x,E.placement,B);a.top+="px",a.left+="px",x.css(a)}};E.origScope=b,E.isOpen=!1,E.contentExp=function(){return b.$eval(d[e])},m.useContentExp||d.$observe(e,function(a){E.content=a,!a&&E.isOpen&&p()}),d.$observe("disabled",function(a){a&&E.isOpen&&p()}),d.$observe(k+"Title",function(a){E.title=a});var G=function(){c.unbind(C.show,j),c.unbind(C.hide,l)};w();var H=b.$eval(d[k+"Animation"]);E.animation=angular.isDefined(H)?!!H:m.animation;var I=b.$eval(d[k+"AppendToBody"]);B=angular.isDefined(I)?I:B,B&&b.$on("$locationChangeSuccess",function(){E.isOpen&&p()}),b.$on("$destroy",function(){g.cancel(z),g.cancel(A),G(),r(),E=null})}}}}}]}).directive("tooltipTemplateTransclude",["$animate","$sce","$compile","$templateRequest",function(a,b,c,d){return{link:function(e,f,g){var h,i,j,k=e.$eval(g.tooltipTemplateTranscludeScope),l=0,m=function(){i&&(i.remove(),i=null),h&&(h.$destroy(),h=null),j&&(a.leave(j).then(function(){i=null}),i=j,j=null)};e.$watch(b.parseAsResourceUrl(g.tooltipTemplateTransclude),function(b){var g=++l;b?(d(b,!0).then(function(d){if(g===l){var e=k.$new(),i=d,n=c(i)(e,function(b){m(),a.enter(b,f)});h=e,j=n,h.$emit("$includeContentLoaded",b)}},function(){g===l&&(m(),e.$emit("$includeContentError",b))}),e.$emit("$includeContentRequested",b)):m()}),e.$on("$destroy",m)}}}]).directive("tooltipClasses",function(){return{restrict:"A",link:function(a,b,c){a.placement&&b.addClass(a.placement),a.popupClass&&b.addClass(a.popupClass),a.animation()&&b.addClass(c.tooltipAnimationClass)}}}).directive("tooltipPopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$tooltip",function(a){return a("tooltip","tooltip","mouseenter")}]).directive("tooltipTemplatePopup",function(){return{restrict:"EA",replace:!0,scope:{contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&",originScope:"&"},templateUrl:"template/tooltip/tooltip-template-popup.html"}}).directive("tooltipTemplate",["$tooltip",function(a){return a("tooltipTemplate","tooltip","mouseenter",{useContentExp:!0})}]).directive("tooltipHtmlPopup",function(){return{restrict:"EA",replace:!0,scope:{contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-popup.html"}}).directive("tooltipHtml",["$tooltip",function(a){return a("tooltipHtml","tooltip","mouseenter",{useContentExp:!0})}]).directive("tooltipHtmlUnsafePopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-unsafe-popup.html"}}).value("tooltipHtmlUnsafeSuppressDeprecated",!1).directive("tooltipHtmlUnsafe",["$tooltip","tooltipHtmlUnsafeSuppressDeprecated","$log",function(a,b,c){return b||c.warn("tooltip-html-unsafe is now deprecated. Use tooltip-html or tooltip-template instead."),a("tooltipHtmlUnsafe","tooltip","mouseenter")}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("popoverTemplatePopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&",originScope:"&"},templateUrl:"template/popover/popover-template.html"}}).directive("popoverTemplate",["$tooltip",function(a){return a("popoverTemplate","popover","click",{useContentExp:!0})}]).directive("popoverPopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html"}}).directive("popover",["$tooltip",function(a){return a("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",[]).constant("progressConfig",{animate:!0,max:100}).controller("ProgressController",["$scope","$attrs","progressConfig",function(a,b,c){var d=this,e=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=angular.isDefined(a.max)?a.max:c.max,this.addBar=function(b,c){e||c.css({transition:"none"}),this.bars.push(b),b.$watch("value",function(c){b.percent=+(100*c/a.max).toFixed(2)}),b.$on("$destroy",function(){c=null,d.removeBar(b)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1)}}]).directive("progress",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",require:"progress",scope:{},templateUrl:"template/progressbar/progress.html"}}).directive("bar",function(){return{restrict:"EA",replace:!0,transclude:!0,require:"^progress",scope:{value:"=",max:"=?",type:"@"},templateUrl:"template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b)}}}).directive("progressbar",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",scope:{value:"=",max:"=?",type:"@"},templateUrl:"template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]))}}}),angular.module("ui.bootstrap.rating",[]).constant("ratingConfig",{max:5,stateOn:null,stateOff:null}).controller("RatingController",["$scope","$attrs","ratingConfig",function(a,b,c){var d={$setViewValue:angular.noop};this.init=function(e){d=e,d.$render=this.render,d.$formatters.push(function(a){return angular.isNumber(a)&&a<<0!==a&&(a=Math.round(a)),a}),this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):c.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):c.stateOff;var f=angular.isDefined(b.ratingStates)?a.$parent.$eval(b.ratingStates):new Array(angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max);a.range=this.buildTemplateObjects(f)},this.buildTemplateObjects=function(a){for(var b=0,c=a.length;c>b;b++)a[b]=angular.extend({index:b},{stateOn:this.stateOn,stateOff:this.stateOff},a[b]);return a},a.rate=function(b){!a.readonly&&b>=0&&b<=a.range.length&&(d.$setViewValue(b),d.$render())},a.enter=function(b){a.readonly||(a.value=b),a.onHover({value:b})},a.reset=function(){a.value=d.$viewValue,a.onLeave()},a.onKeydown=function(b){/(37|38|39|40)/.test(b.which)&&(b.preventDefault(),b.stopPropagation(),a.rate(a.value+(38===b.which||39===b.which?1:-1)))},this.render=function(){a.value=d.$viewValue}}]).directive("rating",function(){return{restrict:"EA",require:["rating","ngModel"],scope:{readonly:"=?",onHover:"&",onLeave:"&"},controller:"RatingController",templateUrl:"template/rating/rating.html",replace:!0,link:function(a,b,c,d){var e=d[0],f=d[1];e.init(f)}}}),angular.module("ui.bootstrap.tabs",[]).controller("TabsetController",["$scope",function(a){var b=this,c=b.tabs=a.tabs=[];b.select=function(a){angular.forEach(c,function(b){b.active&&b!==a&&(b.active=!1,b.onDeselect())}),a.active=!0,a.onSelect()},b.addTab=function(a){c.push(a),1===c.length&&a.active!==!1?a.active=!0:a.active?b.select(a):a.active=!1},b.removeTab=function(a){var e=c.indexOf(a);if(a.active&&c.length>1&&!d){var f=e==c.length-1?e-1:e+1;b.select(c[f])}c.splice(e,1)};var d;a.$on("$destroy",function(){d=!0})}]).directive("tabset",function(){return{restrict:"EA",transclude:!0,replace:!0,scope:{type:"@"},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1}}}).directive("tab",["$parse","$log",function(a,b){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{active:"=?",heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},compile:function(c,d,e){return function(c,d,f,g){c.$watch("active",function(a){a&&g.select(c)}),c.disabled=!1,f.disable&&c.$parent.$watch(a(f.disable),function(a){c.disabled=!!a}),f.disabled&&(b.warn('Use of "disabled" attribute has been deprecated, please use "disable"'),c.$parent.$watch(a(f.disabled),function(a){c.disabled=!!a})),c.select=function(){c.disabled||(c.active=!0)},g.addTab(c),c.$on("$destroy",function(){g.removeTab(c)}),c.$transcludeFn=e}}}}]).directive("tabHeadingTransclude",[function(){return{restrict:"A",require:"^tab",link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}]).directive("tabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(b,c,d){var e=b.$eval(d.tabContentTransclude);e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.timepicker",[]).constant("timepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:null,readonlyInput:!1,mousewheel:!0,arrowkeys:!0}).controller("TimepickerController",["$scope","$attrs","$parse","$log","$locale","timepickerConfig",function(a,b,c,d,e,f){function g(){var b=parseInt(a.hours,10),c=a.showMeridian?b>0&&13>b:b>=0&&24>b;return c?(a.showMeridian&&(12===b&&(b=0),a.meridian===p[1]&&(b+=12)),b):void 0}function h(){var b=parseInt(a.minutes,10);return b>=0&&60>b?b:void 0}function i(a){return angular.isDefined(a)&&a.toString().length<2?"0"+a:a.toString()}function j(a){k(),o.$setViewValue(new Date(n)),l(a)}function k(){o.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1}function l(b){var c=n.getHours(),d=n.getMinutes();a.showMeridian&&(c=0===c||12===c?12:c%12),a.hours="h"===b?c:i(c),"m"!==b&&(a.minutes=i(d)),a.meridian=n.getHours()<12?p[0]:p[1]}function m(a){var b=new Date(n.getTime()+6e4*a);n.setHours(b.getHours(),b.getMinutes()),j()}var n=new Date,o={$setViewValue:angular.noop},p=angular.isDefined(b.meridians)?a.$parent.$eval(b.meridians):f.meridians||e.DATETIME_FORMATS.AMPMS;this.init=function(c,d){o=c,o.$render=this.render,o.$formatters.unshift(function(a){return a?new Date(a):null});var e=d.eq(0),g=d.eq(1),h=angular.isDefined(b.mousewheel)?a.$parent.$eval(b.mousewheel):f.mousewheel;h&&this.setupMousewheelEvents(e,g);var i=angular.isDefined(b.arrowkeys)?a.$parent.$eval(b.arrowkeys):f.arrowkeys;i&&this.setupArrowkeyEvents(e,g),a.readonlyInput=angular.isDefined(b.readonlyInput)?a.$parent.$eval(b.readonlyInput):f.readonlyInput,this.setupInputEvents(e,g)};var q=f.hourStep;b.hourStep&&a.$parent.$watch(c(b.hourStep),function(a){q=parseInt(a,10)});var r=f.minuteStep;b.minuteStep&&a.$parent.$watch(c(b.minuteStep),function(a){r=parseInt(a,10)}),a.showMeridian=f.showMeridian,b.showMeridian&&a.$parent.$watch(c(b.showMeridian),function(b){if(a.showMeridian=!!b,o.$error.time){var c=g(),d=h();angular.isDefined(c)&&angular.isDefined(d)&&(n.setHours(c),j())}else l()}),this.setupMousewheelEvents=function(b,c){var d=function(a){a.originalEvent&&(a=a.originalEvent);var b=a.wheelDelta?a.wheelDelta:-a.deltaY;return a.detail||b>0};b.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementHours():a.decrementHours()),b.preventDefault()}),c.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementMinutes():a.decrementMinutes()),b.preventDefault()})},this.setupArrowkeyEvents=function(b,c){b.bind("keydown",function(b){38===b.which?(b.preventDefault(),a.incrementHours(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementHours(),a.$apply())}),c.bind("keydown",function(b){38===b.which?(b.preventDefault(),a.incrementMinutes(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementMinutes(),a.$apply())})},this.setupInputEvents=function(b,c){if(a.readonlyInput)return a.updateHours=angular.noop,void(a.updateMinutes=angular.noop);var d=function(b,c){o.$setViewValue(null),o.$setValidity("time",!1),angular.isDefined(b)&&(a.invalidHours=b),angular.isDefined(c)&&(a.invalidMinutes=c)};a.updateHours=function(){var a=g();angular.isDefined(a)?(n.setHours(a),j("h")):d(!0)},b.bind("blur",function(){!a.invalidHours&&a.hours<10&&a.$apply(function(){a.hours=i(a.hours)})}),a.updateMinutes=function(){var a=h();angular.isDefined(a)?(n.setMinutes(a),j("m")):d(void 0,!0)},c.bind("blur",function(){!a.invalidMinutes&&a.minutes<10&&a.$apply(function(){a.minutes=i(a.minutes)})})},this.render=function(){var a=o.$viewValue;isNaN(a)?(o.$setValidity("time",!1),d.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(a&&(n=a),k(),l())},a.incrementHours=function(){m(60*q)},a.decrementHours=function(){m(60*-q)},a.incrementMinutes=function(){m(r)},a.decrementMinutes=function(){m(-r)},a.toggleMeridian=function(){m(720*(n.getHours()<12?1:-1))}}]).directive("timepicker",function(){return{restrict:"EA",require:["timepicker","?^ngModel"],controller:"TimepickerController",replace:!0,scope:{},templateUrl:"template/timepicker/timepicker.html",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f,b.find("input"))}}}),angular.module("ui.bootstrap.transition",[]).value("$transitionSuppressDeprecated",!1).factory("$transition",["$q","$timeout","$rootScope","$log","$transitionSuppressDeprecated",function(a,b,c,d,e){function f(a){for(var b in a)if(void 0!==h.style[b])return a[b]}e||d.warn("$transition is now deprecated. Use $animate from ngAnimate instead.");var g=function(d,e,f){f=f||{};var h=a.defer(),i=g[f.animation?"animationEndEventName":"transitionEndEventName"],j=function(){c.$apply(function(){d.unbind(i,j),h.resolve(d)})};return i&&d.bind(i,j),b(function(){angular.isString(e)?d.addClass(e):angular.isFunction(e)?e(d):angular.isObject(e)&&d.css(e),i||h.resolve(d)}),h.promise.cancel=function(){i&&d.unbind(i,j),h.reject("Transition cancelled")},h.promise},h=document.createElement("trans"),i={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},j={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return g.transitionEndEventName=f(i),g.animationEndEventName=f(j),g}]),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).factory("typeaheadParser",["$parse",function(a){var b=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_" but got "'+c+'".');return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$position","typeaheadParser",function(a,b,c,d,e,f,g){var h=[9,13,27,38,40];return{require:"ngModel",link:function(i,j,k,l){var m,n=i.$eval(k.typeaheadMinLength)||1,o=i.$eval(k.typeaheadWaitMs)||0,p=i.$eval(k.typeaheadEditable)!==!1,q=b(k.typeaheadLoading).assign||angular.noop,r=b(k.typeaheadOnSelect),s=k.typeaheadInputFormatter?b(k.typeaheadInputFormatter):void 0,t=k.typeaheadAppendToBody?i.$eval(k.typeaheadAppendToBody):!1,u=i.$eval(k.typeaheadFocusFirst)!==!1,v=b(k.ngModel).assign,w=g.parse(k.typeahead),x=i.$new();i.$on("$destroy",function(){x.$destroy()});var y="typeahead-"+x.$id+"-"+Math.floor(1e4*Math.random());j.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":y});var z=angular.element("
      ");z.attr({id:y,matches:"matches",active:"activeIdx",select:"select(activeIdx)",query:"query",position:"position"}),angular.isDefined(k.typeaheadTemplateUrl)&&z.attr("template-url",k.typeaheadTemplateUrl);var A=function(){x.matches=[],x.activeIdx=-1,j.attr("aria-expanded",!1)},B=function(a){return y+"-option-"+a};x.$watch("activeIdx",function(a){0>a?j.removeAttr("aria-activedescendant"):j.attr("aria-activedescendant",B(a))});var C=function(a){var b={$viewValue:a};q(i,!0),c.when(w.source(i,b)).then(function(c){var d=a===l.$viewValue;if(d&&m)if(c&&c.length>0){x.activeIdx=u?0:-1,x.matches.length=0;for(var e=0;e=n?o>0?(F(),E(a)):C(a):(q(i,!1),F(),A()),p?a:a?void l.$setValidity("editable",!1):(l.$setValidity("editable",!0),a)}),l.$formatters.push(function(a){var b,c,d={};return p||l.$setValidity("editable",!0),s?(d.$model=a,s(i,d)):(d[w.itemName]=a,b=w.viewMapper(i,d),d[w.itemName]=void 0,c=w.viewMapper(i,d),b!==c?b:a)}),x.select=function(a){var b,c,e={};e[w.itemName]=c=x.matches[a].model,b=w.modelMapper(i,e),v(i,b),l.$setValidity("editable",!0),l.$setValidity("parse",!0),r(i,{$item:c,$model:b,$label:w.viewMapper(i,e)}),A(),d(function(){j[0].focus()},0,!1)},j.bind("keydown",function(a){0!==x.matches.length&&-1!==h.indexOf(a.which)&&(-1!=x.activeIdx||13!==a.which&&9!==a.which)&&(a.preventDefault(),40===a.which?(x.activeIdx=(x.activeIdx+1)%x.matches.length,x.$digest()):38===a.which?(x.activeIdx=(x.activeIdx>0?x.activeIdx:x.matches.length)-1,x.$digest()):13===a.which||9===a.which?x.$apply(function(){x.select(x.activeIdx)}):27===a.which&&(a.stopPropagation(),A(),x.$digest()))}),j.bind("blur",function(){m=!1});var G=function(a){j[0]!==a.target&&(A(),x.$digest())};e.bind("click",G),i.$on("$destroy",function(){e.unbind("click",G),t&&H.remove(),z.remove()});var H=a(z)(x);t?e.find("body").append(H):j.after(H)}}}]).directive("typeaheadPopup",function(){return{restrict:"EA",scope:{matches:"=",query:"=",active:"=",position:"=",select:"&"},replace:!0,templateUrl:"template/typeahead/typeahead-popup.html",link:function(a,b,c){a.templateUrl=c.templateUrl,a.isOpen=function(){return a.matches.length>0},a.isActive=function(b){return a.active==b},a.selectActive=function(b){a.active=b},a.selectMatch=function(b){a.select({activeIdx:b})}}}}).directive("typeaheadMatch",["$templateRequest","$compile","$parse",function(a,b,c){return{restrict:"EA",scope:{index:"=",match:"=",query:"="},link:function(d,e,f){var g=c(f.templateUrl)(d.$parent)||"template/typeahead/typeahead-match.html";a(g).then(function(a){b(a.trim())(d,function(a){e.replaceWith(a)})})}}}]).filter("typeaheadHighlight",function(){function a(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(b,c){return c?(""+b).replace(new RegExp(a(c),"gi"),"$&"):b}}),angular.module("template/accordion/accordion-group.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion-group.html",'
      \n
      \n

      \n {{heading}}\n

      \n
      \n
      \n
      \n
      \n
      \n')}]),angular.module("template/accordion/accordion.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion.html",'
      ')}]),angular.module("template/alert/alert.html",[]).run(["$templateCache",function(a){a.put("template/alert/alert.html",'\n')}]),angular.module("template/carousel/carousel.html",[]).run(["$templateCache",function(a){a.put("template/carousel/carousel.html",'\n')}]),angular.module("template/carousel/slide.html",[]).run(["$templateCache",function(a){a.put("template/carousel/slide.html",'
      \n')}]),angular.module("template/datepicker/datepicker.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/datepicker.html",'
      \n \n \n \n
      ')}]),angular.module("template/datepicker/day.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/day.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
      {{label.abbr}}
      {{ weekNumbers[$index] }}\n \n
      \n')}]),angular.module("template/datepicker/month.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/month.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n
      \n \n
      \n')}]),angular.module("template/datepicker/popup.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/popup.html",'\n')}]),angular.module("template/datepicker/year.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/year.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n
      \n \n
      \n') +}]),angular.module("template/modal/backdrop.html",[]).run(["$templateCache",function(a){a.put("template/modal/backdrop.html",'\n')}]),angular.module("template/modal/window.html",[]).run(["$templateCache",function(a){a.put("template/modal/window.html",'\n')}]),angular.module("template/pagination/pager.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pager.html",'')}]),angular.module("template/pagination/pagination.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pagination.html",'')}]),angular.module("template/tooltip/tooltip-html-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-html-popup.html",'
      \n
      \n
      \n
      \n')}]),angular.module("template/tooltip/tooltip-html-unsafe-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-html-unsafe-popup.html",'
      \n
      \n
      \n
      \n')}]),angular.module("template/tooltip/tooltip-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-popup.html",'
      \n
      \n
      \n
      \n')}]),angular.module("template/tooltip/tooltip-template-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-template-popup.html",'
      \n
      \n
      \n
      \n')}]),angular.module("template/popover/popover-template.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover-template.html",'
      \n
      \n\n
      \n

      \n
      \n
      \n
      \n')}]),angular.module("template/popover/popover-window.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover-window.html",'
      \n
      \n\n
      \n

      \n
      \n
      \n
      \n')}]),angular.module("template/popover/popover.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover.html",'
      \n
      \n\n
      \n

      \n
      \n
      \n
      \n')}]),angular.module("template/progressbar/bar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/bar.html",'
      \n')}]),angular.module("template/progressbar/progress.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progress.html",'
      ')}]),angular.module("template/progressbar/progressbar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progressbar.html",'
      \n
      \n
      \n')}]),angular.module("template/rating/rating.html",[]).run(["$templateCache",function(a){a.put("template/rating/rating.html",'\n \n ({{ $index < value ? \'*\' : \' \' }})\n \n')}]),angular.module("template/tabs/tab.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tab.html",'
    • \n {{heading}}\n
    • \n')}]),angular.module("template/tabs/tabset.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tabset.html",'
      \n \n
      \n
      \n
      \n
      \n
      \n')}]),angular.module("template/timepicker/timepicker.html",[]).run(["$templateCache",function(a){a.put("template/timepicker/timepicker.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
       
      \n \n :\n \n
       
      \n')}]),angular.module("template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-match.html",'')}]),angular.module("template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-popup.html",'\n')}]),!angular.$$csp()&&angular.element(document).find("head").prepend(''); \ No newline at end of file diff --git a/turtles/app/lib/bower_components/angular-bootstrap/ui-bootstrap.js b/turtles/app/lib/bower_components/angular-bootstrap/ui-bootstrap.js new file mode 100644 index 000000000..0f31fe499 --- /dev/null +++ b/turtles/app/lib/bower_components/angular-bootstrap/ui-bootstrap.js @@ -0,0 +1,4461 @@ +/* + * angular-ui-bootstrap + * http://angular-ui.github.io/bootstrap/ + + * Version: 0.13.0 - 2015-05-02 + * License: MIT + */ +angular.module("ui.bootstrap", ["ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.transition","ui.bootstrap.typeahead"]); +angular.module('ui.bootstrap.collapse', []) + + .directive('collapse', ['$animate', function ($animate) { + + return { + link: function (scope, element, attrs) { + function expand() { + element.removeClass('collapse').addClass('collapsing'); + $animate.addClass(element, 'in', { + to: { height: element[0].scrollHeight + 'px' } + }).then(expandDone); + } + + function expandDone() { + element.removeClass('collapsing'); + element.css({height: 'auto'}); + } + + function collapse() { + element + // IMPORTANT: The height must be set before adding "collapsing" class. + // Otherwise, the browser attempts to animate from height 0 (in + // collapsing class) to the given height here. + .css({height: element[0].scrollHeight + 'px'}) + // initially all panel collapse have the collapse class, this removal + // prevents the animation from jumping to collapsed state + .removeClass('collapse') + .addClass('collapsing'); + + $animate.removeClass(element, 'in', { + to: {height: '0'} + }).then(collapseDone); + } + + function collapseDone() { + element.css({height: '0'}); // Required so that collapse works when animation is disabled + element.removeClass('collapsing'); + element.addClass('collapse'); + } + + scope.$watch(attrs.collapse, function (shouldCollapse) { + if (shouldCollapse) { + collapse(); + } else { + expand(); + } + }); + } + }; + }]); + +angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse']) + +.constant('accordionConfig', { + closeOthers: true +}) + +.controller('AccordionController', ['$scope', '$attrs', 'accordionConfig', function ($scope, $attrs, accordionConfig) { + + // This array keeps track of the accordion groups + this.groups = []; + + // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to + this.closeOthers = function(openGroup) { + var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers; + if ( closeOthers ) { + angular.forEach(this.groups, function (group) { + if ( group !== openGroup ) { + group.isOpen = false; + } + }); + } + }; + + // This is called from the accordion-group directive to add itself to the accordion + this.addGroup = function(groupScope) { + var that = this; + this.groups.push(groupScope); + + groupScope.$on('$destroy', function (event) { + that.removeGroup(groupScope); + }); + }; + + // This is called from the accordion-group directive when to remove itself + this.removeGroup = function(group) { + var index = this.groups.indexOf(group); + if ( index !== -1 ) { + this.groups.splice(index, 1); + } + }; + +}]) + +// The accordion directive simply sets up the directive controller +// and adds an accordion CSS class to itself element. +.directive('accordion', function () { + return { + restrict:'EA', + controller:'AccordionController', + transclude: true, + replace: false, + templateUrl: 'template/accordion/accordion.html' + }; +}) + +// The accordion-group directive indicates a block of html that will expand and collapse in an accordion +.directive('accordionGroup', function() { + return { + require:'^accordion', // We need this directive to be inside an accordion + restrict:'EA', + transclude:true, // It transcludes the contents of the directive into the template + replace: true, // The element containing the directive will be replaced with the template + templateUrl:'template/accordion/accordion-group.html', + scope: { + heading: '@', // Interpolate the heading attribute onto this scope + isOpen: '=?', + isDisabled: '=?' + }, + controller: function() { + this.setHeading = function(element) { + this.heading = element; + }; + }, + link: function(scope, element, attrs, accordionCtrl) { + accordionCtrl.addGroup(scope); + + scope.$watch('isOpen', function(value) { + if ( value ) { + accordionCtrl.closeOthers(scope); + } + }); + + scope.toggleOpen = function() { + if ( !scope.isDisabled ) { + scope.isOpen = !scope.isOpen; + } + }; + } + }; +}) + +// Use accordion-heading below an accordion-group to provide a heading containing HTML +// +// Heading containing HTML - +// +.directive('accordionHeading', function() { + return { + restrict: 'EA', + transclude: true, // Grab the contents to be used as the heading + template: '', // In effect remove this element! + replace: true, + require: '^accordionGroup', + link: function(scope, element, attr, accordionGroupCtrl, transclude) { + // Pass the heading to the accordion-group controller + // so that it can be transcluded into the right place in the template + // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat] + accordionGroupCtrl.setHeading(transclude(scope, angular.noop)); + } + }; +}) + +// Use in the accordion-group template to indicate where you want the heading to be transcluded +// You must provide the property on the accordion-group controller that will hold the transcluded element +//
      +// +// ... +//
      +.directive('accordionTransclude', function() { + return { + require: '^accordionGroup', + link: function(scope, element, attr, controller) { + scope.$watch(function() { return controller[attr.accordionTransclude]; }, function(heading) { + if ( heading ) { + element.html(''); + element.append(heading); + } + }); + } + }; +}) + +; + +angular.module('ui.bootstrap.alert', []) + +.controller('AlertController', ['$scope', '$attrs', function ($scope, $attrs) { + $scope.closeable = 'close' in $attrs; + this.close = $scope.close; +}]) + +.directive('alert', function () { + return { + restrict:'EA', + controller:'AlertController', + templateUrl:'template/alert/alert.html', + transclude:true, + replace:true, + scope: { + type: '@', + close: '&' + } + }; +}) + +.directive('dismissOnTimeout', ['$timeout', function($timeout) { + return { + require: 'alert', + link: function(scope, element, attrs, alertCtrl) { + $timeout(function(){ + alertCtrl.close(); + }, parseInt(attrs.dismissOnTimeout, 10)); + } + }; +}]); + +angular.module('ui.bootstrap.bindHtml', []) + + .directive('bindHtmlUnsafe', function () { + return function (scope, element, attr) { + element.addClass('ng-binding').data('$binding', attr.bindHtmlUnsafe); + scope.$watch(attr.bindHtmlUnsafe, function bindHtmlUnsafeWatchAction(value) { + element.html(value || ''); + }); + }; + }); +angular.module('ui.bootstrap.buttons', []) + +.constant('buttonConfig', { + activeClass: 'active', + toggleEvent: 'click' +}) + +.controller('ButtonsController', ['buttonConfig', function(buttonConfig) { + this.activeClass = buttonConfig.activeClass || 'active'; + this.toggleEvent = buttonConfig.toggleEvent || 'click'; +}]) + +.directive('btnRadio', function () { + return { + require: ['btnRadio', 'ngModel'], + controller: 'ButtonsController', + link: function (scope, element, attrs, ctrls) { + var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + //model -> UI + ngModelCtrl.$render = function () { + element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio))); + }; + + //ui->model + element.bind(buttonsCtrl.toggleEvent, function () { + var isActive = element.hasClass(buttonsCtrl.activeClass); + + if (!isActive || angular.isDefined(attrs.uncheckable)) { + scope.$apply(function () { + ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.btnRadio)); + ngModelCtrl.$render(); + }); + } + }); + } + }; +}) + +.directive('btnCheckbox', function () { + return { + require: ['btnCheckbox', 'ngModel'], + controller: 'ButtonsController', + link: function (scope, element, attrs, ctrls) { + var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + function getTrueValue() { + return getCheckboxValue(attrs.btnCheckboxTrue, true); + } + + function getFalseValue() { + return getCheckboxValue(attrs.btnCheckboxFalse, false); + } + + function getCheckboxValue(attributeValue, defaultValue) { + var val = scope.$eval(attributeValue); + return angular.isDefined(val) ? val : defaultValue; + } + + //model -> UI + ngModelCtrl.$render = function () { + element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue())); + }; + + //ui->model + element.bind(buttonsCtrl.toggleEvent, function () { + scope.$apply(function () { + ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue()); + ngModelCtrl.$render(); + }); + }); + } + }; +}); + +/** +* @ngdoc overview +* @name ui.bootstrap.carousel +* +* @description +* AngularJS version of an image carousel. +* +*/ +angular.module('ui.bootstrap.carousel', []) +.controller('CarouselController', ['$scope', '$interval', '$animate', function ($scope, $interval, $animate) { + var self = this, + slides = self.slides = $scope.slides = [], + currentIndex = -1, + currentInterval, isPlaying; + self.currentSlide = null; + + var destroyed = false; + /* direction: "prev" or "next" */ + self.select = $scope.select = function(nextSlide, direction) { + var nextIndex = self.indexOfSlide(nextSlide); + //Decide direction if it's not given + if (direction === undefined) { + direction = nextIndex > self.getCurrentIndex() ? 'next' : 'prev'; + } + if (nextSlide && nextSlide !== self.currentSlide) { + goNext(); + } + function goNext() { + // Scope has been destroyed, stop here. + if (destroyed) { return; } + + angular.extend(nextSlide, {direction: direction, active: true}); + angular.extend(self.currentSlide || {}, {direction: direction, active: false}); + if ($animate.enabled() && !$scope.noTransition && nextSlide.$element) { + $scope.$currentTransition = true; + nextSlide.$element.one('$animate:close', function closeFn() { + $scope.$currentTransition = null; + }); + } + + self.currentSlide = nextSlide; + currentIndex = nextIndex; + //every time you change slides, reset the timer + restartTimer(); + } + }; + $scope.$on('$destroy', function () { + destroyed = true; + }); + + function getSlideByIndex(index) { + if (angular.isUndefined(slides[index].index)) { + return slides[index]; + } + var i, len = slides.length; + for (i = 0; i < slides.length; ++i) { + if (slides[i].index == index) { + return slides[i]; + } + } + } + + self.getCurrentIndex = function() { + if (self.currentSlide && angular.isDefined(self.currentSlide.index)) { + return +self.currentSlide.index; + } + return currentIndex; + }; + + /* Allow outside people to call indexOf on slides array */ + self.indexOfSlide = function(slide) { + return angular.isDefined(slide.index) ? +slide.index : slides.indexOf(slide); + }; + + $scope.next = function() { + var newIndex = (self.getCurrentIndex() + 1) % slides.length; + + //Prevent this user-triggered transition from occurring if there is already one in progress + if (!$scope.$currentTransition) { + return self.select(getSlideByIndex(newIndex), 'next'); + } + }; + + $scope.prev = function() { + var newIndex = self.getCurrentIndex() - 1 < 0 ? slides.length - 1 : self.getCurrentIndex() - 1; + + //Prevent this user-triggered transition from occurring if there is already one in progress + if (!$scope.$currentTransition) { + return self.select(getSlideByIndex(newIndex), 'prev'); + } + }; + + $scope.isActive = function(slide) { + return self.currentSlide === slide; + }; + + $scope.$watch('interval', restartTimer); + $scope.$on('$destroy', resetTimer); + + function restartTimer() { + resetTimer(); + var interval = +$scope.interval; + if (!isNaN(interval) && interval > 0) { + currentInterval = $interval(timerFn, interval); + } + } + + function resetTimer() { + if (currentInterval) { + $interval.cancel(currentInterval); + currentInterval = null; + } + } + + function timerFn() { + var interval = +$scope.interval; + if (isPlaying && !isNaN(interval) && interval > 0) { + $scope.next(); + } else { + $scope.pause(); + } + } + + $scope.play = function() { + if (!isPlaying) { + isPlaying = true; + restartTimer(); + } + }; + $scope.pause = function() { + if (!$scope.noPause) { + isPlaying = false; + resetTimer(); + } + }; + + self.addSlide = function(slide, element) { + slide.$element = element; + slides.push(slide); + //if this is the first slide or the slide is set to active, select it + if(slides.length === 1 || slide.active) { + self.select(slides[slides.length-1]); + if (slides.length == 1) { + $scope.play(); + } + } else { + slide.active = false; + } + }; + + self.removeSlide = function(slide) { + if (angular.isDefined(slide.index)) { + slides.sort(function(a, b) { + return +a.index > +b.index; + }); + } + //get the index of the slide inside the carousel + var index = slides.indexOf(slide); + slides.splice(index, 1); + if (slides.length > 0 && slide.active) { + if (index >= slides.length) { + self.select(slides[index-1]); + } else { + self.select(slides[index]); + } + } else if (currentIndex > index) { + currentIndex--; + } + }; + +}]) + +/** + * @ngdoc directive + * @name ui.bootstrap.carousel.directive:carousel + * @restrict EA + * + * @description + * Carousel is the outer container for a set of image 'slides' to showcase. + * + * @param {number=} interval The time, in milliseconds, that it will take the carousel to go to the next slide. + * @param {boolean=} noTransition Whether to disable transitions on the carousel. + * @param {boolean=} noPause Whether to disable pausing on the carousel (by default, the carousel interval pauses on hover). + * + * @example + + + + + + + + + + + + + + + .carousel-indicators { + top: auto; + bottom: 15px; + } + + + */ +.directive('carousel', [function() { + return { + restrict: 'EA', + transclude: true, + replace: true, + controller: 'CarouselController', + require: 'carousel', + templateUrl: 'template/carousel/carousel.html', + scope: { + interval: '=', + noTransition: '=', + noPause: '=' + } + }; +}]) + +/** + * @ngdoc directive + * @name ui.bootstrap.carousel.directive:slide + * @restrict EA + * + * @description + * Creates a slide inside a {@link ui.bootstrap.carousel.directive:carousel carousel}. Must be placed as a child of a carousel element. + * + * @param {boolean=} active Model binding, whether or not this slide is currently active. + * @param {number=} index The index of the slide. The slides will be sorted by this parameter. + * + * @example + + +
      + + + + + + + Interval, in milliseconds: +
      Enter a negative number to stop the interval. +
      +
      + +function CarouselDemoCtrl($scope) { + $scope.myInterval = 5000; +} + + + .carousel-indicators { + top: auto; + bottom: 15px; + } + +
      +*/ + +.directive('slide', function() { + return { + require: '^carousel', + restrict: 'EA', + transclude: true, + replace: true, + templateUrl: 'template/carousel/slide.html', + scope: { + active: '=?', + index: '=?' + }, + link: function (scope, element, attrs, carouselCtrl) { + carouselCtrl.addSlide(scope, element); + //when the scope is destroyed then remove the slide from the current slides array + scope.$on('$destroy', function() { + carouselCtrl.removeSlide(scope); + }); + + scope.$watch('active', function(active) { + if (active) { + carouselCtrl.select(scope); + } + }); + } + }; +}) + +.animation('.item', [ + '$animate', +function ($animate) { + return { + beforeAddClass: function (element, className, done) { + // Due to transclusion, noTransition property is on parent's scope + if (className == 'active' && element.parent() && + !element.parent().scope().noTransition) { + var stopped = false; + var direction = element.isolateScope().direction; + var directionClass = direction == 'next' ? 'left' : 'right'; + element.addClass(direction); + $animate.addClass(element, directionClass).then(function () { + if (!stopped) { + element.removeClass(directionClass + ' ' + direction); + } + done(); + }); + + return function () { + stopped = true; + }; + } + done(); + }, + beforeRemoveClass: function (element, className, done) { + // Due to transclusion, noTransition property is on parent's scope + if (className == 'active' && element.parent() && + !element.parent().scope().noTransition) { + var stopped = false; + var direction = element.isolateScope().direction; + var directionClass = direction == 'next' ? 'left' : 'right'; + $animate.addClass(element, directionClass).then(function () { + if (!stopped) { + element.removeClass(directionClass); + } + done(); + }); + return function () { + stopped = true; + }; + } + done(); + } + }; + +}]) + + +; + +angular.module('ui.bootstrap.dateparser', []) + +.service('dateParser', ['$locale', 'orderByFilter', function($locale, orderByFilter) { + // Pulled from https://github.com/mbostock/d3/blob/master/src/format/requote.js + var SPECIAL_CHARACTERS_REGEXP = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; + + this.parsers = {}; + + var formatCodeToRegex = { + 'yyyy': { + regex: '\\d{4}', + apply: function(value) { this.year = +value; } + }, + 'yy': { + regex: '\\d{2}', + apply: function(value) { this.year = +value + 2000; } + }, + 'y': { + regex: '\\d{1,4}', + apply: function(value) { this.year = +value; } + }, + 'MMMM': { + regex: $locale.DATETIME_FORMATS.MONTH.join('|'), + apply: function(value) { this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); } + }, + 'MMM': { + regex: $locale.DATETIME_FORMATS.SHORTMONTH.join('|'), + apply: function(value) { this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); } + }, + 'MM': { + regex: '0[1-9]|1[0-2]', + apply: function(value) { this.month = value - 1; } + }, + 'M': { + regex: '[1-9]|1[0-2]', + apply: function(value) { this.month = value - 1; } + }, + 'dd': { + regex: '[0-2][0-9]{1}|3[0-1]{1}', + apply: function(value) { this.date = +value; } + }, + 'd': { + regex: '[1-2]?[0-9]{1}|3[0-1]{1}', + apply: function(value) { this.date = +value; } + }, + 'EEEE': { + regex: $locale.DATETIME_FORMATS.DAY.join('|') + }, + 'EEE': { + regex: $locale.DATETIME_FORMATS.SHORTDAY.join('|') + }, + 'HH': { + regex: '(?:0|1)[0-9]|2[0-3]', + apply: function(value) { this.hours = +value; } + }, + 'H': { + regex: '1?[0-9]|2[0-3]', + apply: function(value) { this.hours = +value; } + }, + 'mm': { + regex: '[0-5][0-9]', + apply: function(value) { this.minutes = +value; } + }, + 'm': { + regex: '[0-9]|[1-5][0-9]', + apply: function(value) { this.minutes = +value; } + }, + 'sss': { + regex: '[0-9][0-9][0-9]', + apply: function(value) { this.milliseconds = +value; } + }, + 'ss': { + regex: '[0-5][0-9]', + apply: function(value) { this.seconds = +value; } + }, + 's': { + regex: '[0-9]|[1-5][0-9]', + apply: function(value) { this.seconds = +value; } + } + }; + + function createParser(format) { + var map = [], regex = format.split(''); + + angular.forEach(formatCodeToRegex, function(data, code) { + var index = format.indexOf(code); + + if (index > -1) { + format = format.split(''); + + regex[index] = '(' + data.regex + ')'; + format[index] = '$'; // Custom symbol to define consumed part of format + for (var i = index + 1, n = index + code.length; i < n; i++) { + regex[i] = ''; + format[i] = '$'; + } + format = format.join(''); + + map.push({ index: index, apply: data.apply }); + } + }); + + return { + regex: new RegExp('^' + regex.join('') + '$'), + map: orderByFilter(map, 'index') + }; + } + + this.parse = function(input, format, baseDate) { + if ( !angular.isString(input) || !format ) { + return input; + } + + format = $locale.DATETIME_FORMATS[format] || format; + format = format.replace(SPECIAL_CHARACTERS_REGEXP, '\\$&'); + + if ( !this.parsers[format] ) { + this.parsers[format] = createParser(format); + } + + var parser = this.parsers[format], + regex = parser.regex, + map = parser.map, + results = input.match(regex); + + if ( results && results.length ) { + var fields, dt; + if (baseDate) { + fields = { + year: baseDate.getFullYear(), + month: baseDate.getMonth(), + date: baseDate.getDate(), + hours: baseDate.getHours(), + minutes: baseDate.getMinutes(), + seconds: baseDate.getSeconds(), + milliseconds: baseDate.getMilliseconds() + }; + } else { + fields = { year: 1900, month: 0, date: 1, hours: 0, minutes: 0, seconds: 0, milliseconds: 0 }; + } + + for( var i = 1, n = results.length; i < n; i++ ) { + var mapper = map[i-1]; + if ( mapper.apply ) { + mapper.apply.call(fields, results[i]); + } + } + + if ( isValid(fields.year, fields.month, fields.date) ) { + dt = new Date(fields.year, fields.month, fields.date, fields.hours, fields.minutes, fields.seconds, + fields.milliseconds || 0); + } + + return dt; + } + }; + + // Check if date is valid for specific month (and year for February). + // Month: 0 = Jan, 1 = Feb, etc + function isValid(year, month, date) { + if (date < 1) { + return false; + } + + if ( month === 1 && date > 28) { + return date === 29 && ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0); + } + + if ( month === 3 || month === 5 || month === 8 || month === 10) { + return date < 31; + } + + return true; + } +}]); + +angular.module('ui.bootstrap.position', []) + +/** + * A set of utility methods that can be use to retrieve position of DOM elements. + * It is meant to be used where we need to absolute-position DOM elements in + * relation to other, existing elements (this is the case for tooltips, popovers, + * typeahead suggestions etc.). + */ + .factory('$position', ['$document', '$window', function ($document, $window) { + + function getStyle(el, cssprop) { + if (el.currentStyle) { //IE + return el.currentStyle[cssprop]; + } else if ($window.getComputedStyle) { + return $window.getComputedStyle(el)[cssprop]; + } + // finally try and get inline style + return el.style[cssprop]; + } + + /** + * Checks if a given element is statically positioned + * @param element - raw DOM element + */ + function isStaticPositioned(element) { + return (getStyle(element, 'position') || 'static' ) === 'static'; + } + + /** + * returns the closest, non-statically positioned parentOffset of a given element + * @param element + */ + var parentOffsetEl = function (element) { + var docDomEl = $document[0]; + var offsetParent = element.offsetParent || docDomEl; + while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent) ) { + offsetParent = offsetParent.offsetParent; + } + return offsetParent || docDomEl; + }; + + return { + /** + * Provides read-only equivalent of jQuery's position function: + * http://api.jquery.com/position/ + */ + position: function (element) { + var elBCR = this.offset(element); + var offsetParentBCR = { top: 0, left: 0 }; + var offsetParentEl = parentOffsetEl(element[0]); + if (offsetParentEl != $document[0]) { + offsetParentBCR = this.offset(angular.element(offsetParentEl)); + offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop; + offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft; + } + + var boundingClientRect = element[0].getBoundingClientRect(); + return { + width: boundingClientRect.width || element.prop('offsetWidth'), + height: boundingClientRect.height || element.prop('offsetHeight'), + top: elBCR.top - offsetParentBCR.top, + left: elBCR.left - offsetParentBCR.left + }; + }, + + /** + * Provides read-only equivalent of jQuery's offset function: + * http://api.jquery.com/offset/ + */ + offset: function (element) { + var boundingClientRect = element[0].getBoundingClientRect(); + return { + width: boundingClientRect.width || element.prop('offsetWidth'), + height: boundingClientRect.height || element.prop('offsetHeight'), + top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop), + left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft) + }; + }, + + /** + * Provides coordinates for the targetEl in relation to hostEl + */ + positionElements: function (hostEl, targetEl, positionStr, appendToBody) { + + var positionStrParts = positionStr.split('-'); + var pos0 = positionStrParts[0], pos1 = positionStrParts[1] || 'center'; + + var hostElPos, + targetElWidth, + targetElHeight, + targetElPos; + + hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl); + + targetElWidth = targetEl.prop('offsetWidth'); + targetElHeight = targetEl.prop('offsetHeight'); + + var shiftWidth = { + center: function () { + return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2; + }, + left: function () { + return hostElPos.left; + }, + right: function () { + return hostElPos.left + hostElPos.width; + } + }; + + var shiftHeight = { + center: function () { + return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2; + }, + top: function () { + return hostElPos.top; + }, + bottom: function () { + return hostElPos.top + hostElPos.height; + } + }; + + switch (pos0) { + case 'right': + targetElPos = { + top: shiftHeight[pos1](), + left: shiftWidth[pos0]() + }; + break; + case 'left': + targetElPos = { + top: shiftHeight[pos1](), + left: hostElPos.left - targetElWidth + }; + break; + case 'bottom': + targetElPos = { + top: shiftHeight[pos0](), + left: shiftWidth[pos1]() + }; + break; + default: + targetElPos = { + top: hostElPos.top - targetElHeight, + left: shiftWidth[pos1]() + }; + break; + } + + return targetElPos; + } + }; + }]); + +angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootstrap.position']) + +.constant('datepickerConfig', { + formatDay: 'dd', + formatMonth: 'MMMM', + formatYear: 'yyyy', + formatDayHeader: 'EEE', + formatDayTitle: 'MMMM yyyy', + formatMonthTitle: 'yyyy', + datepickerMode: 'day', + minMode: 'day', + maxMode: 'year', + showWeeks: true, + startingDay: 0, + yearRange: 20, + minDate: null, + maxDate: null, + shortcutPropagation: false +}) + +.controller('DatepickerController', ['$scope', '$attrs', '$parse', '$interpolate', '$timeout', '$log', 'dateFilter', 'datepickerConfig', function($scope, $attrs, $parse, $interpolate, $timeout, $log, dateFilter, datepickerConfig) { + var self = this, + ngModelCtrl = { $setViewValue: angular.noop }; // nullModelCtrl; + + // Modes chain + this.modes = ['day', 'month', 'year']; + + // Configuration attributes + angular.forEach(['formatDay', 'formatMonth', 'formatYear', 'formatDayHeader', 'formatDayTitle', 'formatMonthTitle', + 'minMode', 'maxMode', 'showWeeks', 'startingDay', 'yearRange', 'shortcutPropagation'], function( key, index ) { + self[key] = angular.isDefined($attrs[key]) ? (index < 8 ? $interpolate($attrs[key])($scope.$parent) : $scope.$parent.$eval($attrs[key])) : datepickerConfig[key]; + }); + + // Watchable date attributes + angular.forEach(['minDate', 'maxDate'], function( key ) { + if ( $attrs[key] ) { + $scope.$parent.$watch($parse($attrs[key]), function(value) { + self[key] = value ? new Date(value) : null; + self.refreshView(); + }); + } else { + self[key] = datepickerConfig[key] ? new Date(datepickerConfig[key]) : null; + } + }); + + $scope.datepickerMode = $scope.datepickerMode || datepickerConfig.datepickerMode; + $scope.maxMode = self.maxMode; + $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000); + + if(angular.isDefined($attrs.initDate)) { + this.activeDate = $scope.$parent.$eval($attrs.initDate) || new Date(); + $scope.$parent.$watch($attrs.initDate, function(initDate){ + if(initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)){ + self.activeDate = initDate; + self.refreshView(); + } + }); + } else { + this.activeDate = new Date(); + } + + $scope.isActive = function(dateObject) { + if (self.compare(dateObject.date, self.activeDate) === 0) { + $scope.activeDateId = dateObject.uid; + return true; + } + return false; + }; + + this.init = function( ngModelCtrl_ ) { + ngModelCtrl = ngModelCtrl_; + + ngModelCtrl.$render = function() { + self.render(); + }; + }; + + this.render = function() { + if ( ngModelCtrl.$viewValue ) { + var date = new Date( ngModelCtrl.$viewValue ), + isValid = !isNaN(date); + + if ( isValid ) { + this.activeDate = date; + } else { + $log.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); + } + ngModelCtrl.$setValidity('date', isValid); + } + this.refreshView(); + }; + + this.refreshView = function() { + if ( this.element ) { + this._refreshView(); + + var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; + ngModelCtrl.$setValidity('date-disabled', !date || (this.element && !this.isDisabled(date))); + } + }; + + this.createDateObject = function(date, format) { + var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; + return { + date: date, + label: dateFilter(date, format), + selected: model && this.compare(date, model) === 0, + disabled: this.isDisabled(date), + current: this.compare(date, new Date()) === 0, + customClass: this.customClass(date) + }; + }; + + this.isDisabled = function( date ) { + return ((this.minDate && this.compare(date, this.minDate) < 0) || (this.maxDate && this.compare(date, this.maxDate) > 0) || ($attrs.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode}))); + }; + + this.customClass = function( date ) { + return $scope.customClass({date: date, mode: $scope.datepickerMode}); + }; + + // Split array into smaller arrays + this.split = function(arr, size) { + var arrays = []; + while (arr.length > 0) { + arrays.push(arr.splice(0, size)); + } + return arrays; + }; + + $scope.select = function( date ) { + if ( $scope.datepickerMode === self.minMode ) { + var dt = ngModelCtrl.$viewValue ? new Date( ngModelCtrl.$viewValue ) : new Date(0, 0, 0, 0, 0, 0, 0); + dt.setFullYear( date.getFullYear(), date.getMonth(), date.getDate() ); + ngModelCtrl.$setViewValue( dt ); + ngModelCtrl.$render(); + } else { + self.activeDate = date; + $scope.datepickerMode = self.modes[ self.modes.indexOf( $scope.datepickerMode ) - 1 ]; + } + }; + + $scope.move = function( direction ) { + var year = self.activeDate.getFullYear() + direction * (self.step.years || 0), + month = self.activeDate.getMonth() + direction * (self.step.months || 0); + self.activeDate.setFullYear(year, month, 1); + self.refreshView(); + }; + + $scope.toggleMode = function( direction ) { + direction = direction || 1; + + if (($scope.datepickerMode === self.maxMode && direction === 1) || ($scope.datepickerMode === self.minMode && direction === -1)) { + return; + } + + $scope.datepickerMode = self.modes[ self.modes.indexOf( $scope.datepickerMode ) + direction ]; + }; + + // Key event mapper + $scope.keys = { 13:'enter', 32:'space', 33:'pageup', 34:'pagedown', 35:'end', 36:'home', 37:'left', 38:'up', 39:'right', 40:'down' }; + + var focusElement = function() { + $timeout(function() { + self.element[0].focus(); + }, 0 , false); + }; + + // Listen for focus requests from popup directive + $scope.$on('datepicker.focus', focusElement); + + $scope.keydown = function( evt ) { + var key = $scope.keys[evt.which]; + + if ( !key || evt.shiftKey || evt.altKey ) { + return; + } + + evt.preventDefault(); + if(!self.shortcutPropagation){ + evt.stopPropagation(); + } + + if (key === 'enter' || key === 'space') { + if ( self.isDisabled(self.activeDate)) { + return; // do nothing + } + $scope.select(self.activeDate); + focusElement(); + } else if (evt.ctrlKey && (key === 'up' || key === 'down')) { + $scope.toggleMode(key === 'up' ? 1 : -1); + focusElement(); + } else { + self.handleKeyDown(key, evt); + self.refreshView(); + } + }; +}]) + +.directive( 'datepicker', function () { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/datepicker/datepicker.html', + scope: { + datepickerMode: '=?', + dateDisabled: '&', + customClass: '&', + shortcutPropagation: '&?' + }, + require: ['datepicker', '?^ngModel'], + controller: 'DatepickerController', + link: function(scope, element, attrs, ctrls) { + var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + if ( ngModelCtrl ) { + datepickerCtrl.init( ngModelCtrl ); + } + } + }; +}) + +.directive('daypicker', ['dateFilter', function (dateFilter) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/datepicker/day.html', + require: '^datepicker', + link: function(scope, element, attrs, ctrl) { + scope.showWeeks = ctrl.showWeeks; + + ctrl.step = { months: 1 }; + ctrl.element = element; + + var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + function getDaysInMonth( year, month ) { + return ((month === 1) && (year % 4 === 0) && ((year % 100 !== 0) || (year % 400 === 0))) ? 29 : DAYS_IN_MONTH[month]; + } + + function getDates(startDate, n) { + var dates = new Array(n), current = new Date(startDate), i = 0; + current.setHours(12); // Prevent repeated dates because of timezone bug + while ( i < n ) { + dates[i++] = new Date(current); + current.setDate( current.getDate() + 1 ); + } + return dates; + } + + ctrl._refreshView = function() { + var year = ctrl.activeDate.getFullYear(), + month = ctrl.activeDate.getMonth(), + firstDayOfMonth = new Date(year, month, 1), + difference = ctrl.startingDay - firstDayOfMonth.getDay(), + numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : - difference, + firstDate = new Date(firstDayOfMonth); + + if ( numDisplayedFromPreviousMonth > 0 ) { + firstDate.setDate( - numDisplayedFromPreviousMonth + 1 ); + } + + // 42 is the number of days on a six-month calendar + var days = getDates(firstDate, 42); + for (var i = 0; i < 42; i ++) { + days[i] = angular.extend(ctrl.createDateObject(days[i], ctrl.formatDay), { + secondary: days[i].getMonth() !== month, + uid: scope.uniqueId + '-' + i + }); + } + + scope.labels = new Array(7); + for (var j = 0; j < 7; j++) { + scope.labels[j] = { + abbr: dateFilter(days[j].date, ctrl.formatDayHeader), + full: dateFilter(days[j].date, 'EEEE') + }; + } + + scope.title = dateFilter(ctrl.activeDate, ctrl.formatDayTitle); + scope.rows = ctrl.split(days, 7); + + if ( scope.showWeeks ) { + scope.weekNumbers = []; + var thursdayIndex = (4 + 7 - ctrl.startingDay) % 7, + numWeeks = scope.rows.length; + for (var curWeek = 0; curWeek < numWeeks; curWeek++) { + scope.weekNumbers.push( + getISO8601WeekNumber( scope.rows[curWeek][thursdayIndex].date )); + } + } + }; + + ctrl.compare = function(date1, date2) { + return (new Date( date1.getFullYear(), date1.getMonth(), date1.getDate() ) - new Date( date2.getFullYear(), date2.getMonth(), date2.getDate() ) ); + }; + + function getISO8601WeekNumber(date) { + var checkDate = new Date(date); + checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday + var time = checkDate.getTime(); + checkDate.setMonth(0); // Compare with Jan 1 + checkDate.setDate(1); + return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; + } + + ctrl.handleKeyDown = function( key, evt ) { + var date = ctrl.activeDate.getDate(); + + if (key === 'left') { + date = date - 1; // up + } else if (key === 'up') { + date = date - 7; // down + } else if (key === 'right') { + date = date + 1; // down + } else if (key === 'down') { + date = date + 7; + } else if (key === 'pageup' || key === 'pagedown') { + var month = ctrl.activeDate.getMonth() + (key === 'pageup' ? - 1 : 1); + ctrl.activeDate.setMonth(month, 1); + date = Math.min(getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()), date); + } else if (key === 'home') { + date = 1; + } else if (key === 'end') { + date = getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()); + } + ctrl.activeDate.setDate(date); + }; + + ctrl.refreshView(); + } + }; +}]) + +.directive('monthpicker', ['dateFilter', function (dateFilter) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/datepicker/month.html', + require: '^datepicker', + link: function(scope, element, attrs, ctrl) { + ctrl.step = { years: 1 }; + ctrl.element = element; + + ctrl._refreshView = function() { + var months = new Array(12), + year = ctrl.activeDate.getFullYear(); + + for ( var i = 0; i < 12; i++ ) { + months[i] = angular.extend(ctrl.createDateObject(new Date(year, i, 1), ctrl.formatMonth), { + uid: scope.uniqueId + '-' + i + }); + } + + scope.title = dateFilter(ctrl.activeDate, ctrl.formatMonthTitle); + scope.rows = ctrl.split(months, 3); + }; + + ctrl.compare = function(date1, date2) { + return new Date( date1.getFullYear(), date1.getMonth() ) - new Date( date2.getFullYear(), date2.getMonth() ); + }; + + ctrl.handleKeyDown = function( key, evt ) { + var date = ctrl.activeDate.getMonth(); + + if (key === 'left') { + date = date - 1; // up + } else if (key === 'up') { + date = date - 3; // down + } else if (key === 'right') { + date = date + 1; // down + } else if (key === 'down') { + date = date + 3; + } else if (key === 'pageup' || key === 'pagedown') { + var year = ctrl.activeDate.getFullYear() + (key === 'pageup' ? - 1 : 1); + ctrl.activeDate.setFullYear(year); + } else if (key === 'home') { + date = 0; + } else if (key === 'end') { + date = 11; + } + ctrl.activeDate.setMonth(date); + }; + + ctrl.refreshView(); + } + }; +}]) + +.directive('yearpicker', ['dateFilter', function (dateFilter) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/datepicker/year.html', + require: '^datepicker', + link: function(scope, element, attrs, ctrl) { + var range = ctrl.yearRange; + + ctrl.step = { years: range }; + ctrl.element = element; + + function getStartingYear( year ) { + return parseInt((year - 1) / range, 10) * range + 1; + } + + ctrl._refreshView = function() { + var years = new Array(range); + + for ( var i = 0, start = getStartingYear(ctrl.activeDate.getFullYear()); i < range; i++ ) { + years[i] = angular.extend(ctrl.createDateObject(new Date(start + i, 0, 1), ctrl.formatYear), { + uid: scope.uniqueId + '-' + i + }); + } + + scope.title = [years[0].label, years[range - 1].label].join(' - '); + scope.rows = ctrl.split(years, 5); + }; + + ctrl.compare = function(date1, date2) { + return date1.getFullYear() - date2.getFullYear(); + }; + + ctrl.handleKeyDown = function( key, evt ) { + var date = ctrl.activeDate.getFullYear(); + + if (key === 'left') { + date = date - 1; // up + } else if (key === 'up') { + date = date - 5; // down + } else if (key === 'right') { + date = date + 1; // down + } else if (key === 'down') { + date = date + 5; + } else if (key === 'pageup' || key === 'pagedown') { + date += (key === 'pageup' ? - 1 : 1) * ctrl.step.years; + } else if (key === 'home') { + date = getStartingYear( ctrl.activeDate.getFullYear() ); + } else if (key === 'end') { + date = getStartingYear( ctrl.activeDate.getFullYear() ) + range - 1; + } + ctrl.activeDate.setFullYear(date); + }; + + ctrl.refreshView(); + } + }; +}]) + +.constant('datepickerPopupConfig', { + datepickerPopup: 'yyyy-MM-dd', + html5Types: { + date: 'yyyy-MM-dd', + 'datetime-local': 'yyyy-MM-ddTHH:mm:ss.sss', + 'month': 'yyyy-MM' + }, + currentText: 'Today', + clearText: 'Clear', + closeText: 'Done', + closeOnDateSelection: true, + appendToBody: false, + showButtonBar: true +}) + +.directive('datepickerPopup', ['$compile', '$parse', '$document', '$position', 'dateFilter', 'dateParser', 'datepickerPopupConfig', +function ($compile, $parse, $document, $position, dateFilter, dateParser, datepickerPopupConfig) { + return { + restrict: 'EA', + require: 'ngModel', + scope: { + isOpen: '=?', + currentText: '@', + clearText: '@', + closeText: '@', + dateDisabled: '&', + customClass: '&' + }, + link: function(scope, element, attrs, ngModel) { + var dateFormat, + closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? scope.$parent.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection, + appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? scope.$parent.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody; + + scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? scope.$parent.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar; + + scope.getText = function( key ) { + return scope[key + 'Text'] || datepickerPopupConfig[key + 'Text']; + }; + + var isHtml5DateInput = false; + if (datepickerPopupConfig.html5Types[attrs.type]) { + dateFormat = datepickerPopupConfig.html5Types[attrs.type]; + isHtml5DateInput = true; + } else { + dateFormat = attrs.datepickerPopup || datepickerPopupConfig.datepickerPopup; + attrs.$observe('datepickerPopup', function(value, oldValue) { + var newDateFormat = value || datepickerPopupConfig.datepickerPopup; + // Invalidate the $modelValue to ensure that formatters re-run + // FIXME: Refactor when PR is merged: https://github.com/angular/angular.js/pull/10764 + if (newDateFormat !== dateFormat) { + dateFormat = newDateFormat; + ngModel.$modelValue = null; + + if (!dateFormat) { + throw new Error('datepickerPopup must have a date format specified.'); + } + } + }); + } + + if (!dateFormat) { + throw new Error('datepickerPopup must have a date format specified.'); + } + + if (isHtml5DateInput && attrs.datepickerPopup) { + throw new Error('HTML5 date input types do not support custom formats.'); + } + + // popup element used to display calendar + var popupEl = angular.element('
      '); + popupEl.attr({ + 'ng-model': 'date', + 'ng-change': 'dateSelection()' + }); + + function cameltoDash( string ){ + return string.replace(/([A-Z])/g, function($1) { return '-' + $1.toLowerCase(); }); + } + + // datepicker element + var datepickerEl = angular.element(popupEl.children()[0]); + if (isHtml5DateInput) { + if (attrs.type == 'month') { + datepickerEl.attr('datepicker-mode', '"month"'); + datepickerEl.attr('min-mode', 'month'); + } + } + + if ( attrs.datepickerOptions ) { + var options = scope.$parent.$eval(attrs.datepickerOptions); + if(options.initDate) { + scope.initDate = options.initDate; + datepickerEl.attr( 'init-date', 'initDate' ); + delete options.initDate; + } + angular.forEach(options, function( value, option ) { + datepickerEl.attr( cameltoDash(option), value ); + }); + } + + scope.watchData = {}; + angular.forEach(['minDate', 'maxDate', 'datepickerMode', 'initDate', 'shortcutPropagation'], function( key ) { + if ( attrs[key] ) { + var getAttribute = $parse(attrs[key]); + scope.$parent.$watch(getAttribute, function(value){ + scope.watchData[key] = value; + }); + datepickerEl.attr(cameltoDash(key), 'watchData.' + key); + + // Propagate changes from datepicker to outside + if ( key === 'datepickerMode' ) { + var setAttribute = getAttribute.assign; + scope.$watch('watchData.' + key, function(value, oldvalue) { + if ( value !== oldvalue ) { + setAttribute(scope.$parent, value); + } + }); + } + } + }); + if (attrs.dateDisabled) { + datepickerEl.attr('date-disabled', 'dateDisabled({ date: date, mode: mode })'); + } + + if (attrs.showWeeks) { + datepickerEl.attr('show-weeks', attrs.showWeeks); + } + + if (attrs.customClass){ + datepickerEl.attr('custom-class', 'customClass({ date: date, mode: mode })'); + } + + function parseDate(viewValue) { + if (angular.isNumber(viewValue)) { + // presumably timestamp to date object + viewValue = new Date(viewValue); + } + + if (!viewValue) { + return null; + } else if (angular.isDate(viewValue) && !isNaN(viewValue)) { + return viewValue; + } else if (angular.isString(viewValue)) { + var date = dateParser.parse(viewValue, dateFormat, scope.date) || new Date(viewValue); + if (isNaN(date)) { + return undefined; + } else { + return date; + } + } else { + return undefined; + } + } + + function validator(modelValue, viewValue) { + var value = modelValue || viewValue; + if (angular.isNumber(value)) { + value = new Date(value); + } + if (!value) { + return true; + } else if (angular.isDate(value) && !isNaN(value)) { + return true; + } else if (angular.isString(value)) { + var date = dateParser.parse(value, dateFormat) || new Date(value); + return !isNaN(date); + } else { + return false; + } + } + + if (!isHtml5DateInput) { + // Internal API to maintain the correct ng-invalid-[key] class + ngModel.$$parserName = 'date'; + ngModel.$validators.date = validator; + ngModel.$parsers.unshift(parseDate); + ngModel.$formatters.push(function (value) { + scope.date = value; + return ngModel.$isEmpty(value) ? value : dateFilter(value, dateFormat); + }); + } + else { + ngModel.$formatters.push(function (value) { + scope.date = value; + return value; + }); + } + + // Inner change + scope.dateSelection = function(dt) { + if (angular.isDefined(dt)) { + scope.date = dt; + } + var date = scope.date ? dateFilter(scope.date, dateFormat) : ''; + element.val(date); + ngModel.$setViewValue(date); + + if ( closeOnDateSelection ) { + scope.isOpen = false; + element[0].focus(); + } + }; + + // Detect changes in the view from the text box + ngModel.$viewChangeListeners.push(function () { + scope.date = dateParser.parse(ngModel.$viewValue, dateFormat, scope.date) || new Date(ngModel.$viewValue); + }); + + var documentClickBind = function(event) { + if (scope.isOpen && event.target !== element[0]) { + scope.$apply(function() { + scope.isOpen = false; + }); + } + }; + + var keydown = function(evt, noApply) { + scope.keydown(evt); + }; + element.bind('keydown', keydown); + + scope.keydown = function(evt) { + if (evt.which === 27) { + evt.preventDefault(); + if (scope.isOpen) { + evt.stopPropagation(); + } + scope.close(); + } else if (evt.which === 40 && !scope.isOpen) { + scope.isOpen = true; + } + }; + + scope.$watch('isOpen', function(value) { + if (value) { + scope.$broadcast('datepicker.focus'); + scope.position = appendToBody ? $position.offset(element) : $position.position(element); + scope.position.top = scope.position.top + element.prop('offsetHeight'); + + $document.bind('click', documentClickBind); + } else { + $document.unbind('click', documentClickBind); + } + }); + + scope.select = function( date ) { + if (date === 'today') { + var today = new Date(); + if (angular.isDate(scope.date)) { + date = new Date(scope.date); + date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate()); + } else { + date = new Date(today.setHours(0, 0, 0, 0)); + } + } + scope.dateSelection( date ); + }; + + scope.close = function() { + scope.isOpen = false; + element[0].focus(); + }; + + var $popup = $compile(popupEl)(scope); + // Prevent jQuery cache memory leak (template is now redundant after linking) + popupEl.remove(); + + if ( appendToBody ) { + $document.find('body').append($popup); + } else { + element.after($popup); + } + + scope.$on('$destroy', function() { + $popup.remove(); + element.unbind('keydown', keydown); + $document.unbind('click', documentClickBind); + }); + } + }; +}]) + +.directive('datepickerPopupWrap', function() { + return { + restrict:'EA', + replace: true, + transclude: true, + templateUrl: 'template/datepicker/popup.html', + link:function (scope, element, attrs) { + element.bind('click', function(event) { + event.preventDefault(); + event.stopPropagation(); + }); + } + }; +}); + +angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) + +.constant('dropdownConfig', { + openClass: 'open' +}) + +.service('dropdownService', ['$document', '$rootScope', function($document, $rootScope) { + var openScope = null; + + this.open = function( dropdownScope ) { + if ( !openScope ) { + $document.bind('click', closeDropdown); + $document.bind('keydown', escapeKeyBind); + } + + if ( openScope && openScope !== dropdownScope ) { + openScope.isOpen = false; + } + + openScope = dropdownScope; + }; + + this.close = function( dropdownScope ) { + if ( openScope === dropdownScope ) { + openScope = null; + $document.unbind('click', closeDropdown); + $document.unbind('keydown', escapeKeyBind); + } + }; + + var closeDropdown = function( evt ) { + // This method may still be called during the same mouse event that + // unbound this event handler. So check openScope before proceeding. + if (!openScope) { return; } + + if( evt && openScope.getAutoClose() === 'disabled' ) { return ; } + + var toggleElement = openScope.getToggleElement(); + if ( evt && toggleElement && toggleElement[0].contains(evt.target) ) { + return; + } + + var $element = openScope.getElement(); + if( evt && openScope.getAutoClose() === 'outsideClick' && $element && $element[0].contains(evt.target) ) { + return; + } + + openScope.isOpen = false; + + if (!$rootScope.$$phase) { + openScope.$apply(); + } + }; + + var escapeKeyBind = function( evt ) { + if ( evt.which === 27 ) { + openScope.focusToggleElement(); + closeDropdown(); + } + }; +}]) + +.controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', '$position', '$document', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate, $position, $document) { + var self = this, + scope = $scope.$new(), // create a child scope so we are not polluting original one + openClass = dropdownConfig.openClass, + getIsOpen, + setIsOpen = angular.noop, + toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop, + appendToBody = false; + + this.init = function( element ) { + self.$element = element; + + if ( $attrs.isOpen ) { + getIsOpen = $parse($attrs.isOpen); + setIsOpen = getIsOpen.assign; + + $scope.$watch(getIsOpen, function(value) { + scope.isOpen = !!value; + }); + } + + appendToBody = angular.isDefined($attrs.dropdownAppendToBody); + + if ( appendToBody && self.dropdownMenu ) { + $document.find('body').append( self.dropdownMenu ); + element.on('$destroy', function handleDestroyEvent() { + self.dropdownMenu.remove(); + }); + } + }; + + this.toggle = function( open ) { + return scope.isOpen = arguments.length ? !!open : !scope.isOpen; + }; + + // Allow other directives to watch status + this.isOpen = function() { + return scope.isOpen; + }; + + scope.getToggleElement = function() { + return self.toggleElement; + }; + + scope.getAutoClose = function() { + return $attrs.autoClose || 'always'; //or 'outsideClick' or 'disabled' + }; + + scope.getElement = function() { + return self.$element; + }; + + scope.focusToggleElement = function() { + if ( self.toggleElement ) { + self.toggleElement[0].focus(); + } + }; + + scope.$watch('isOpen', function( isOpen, wasOpen ) { + if ( appendToBody && self.dropdownMenu ) { + var pos = $position.positionElements(self.$element, self.dropdownMenu, 'bottom-left', true); + self.dropdownMenu.css({ + top: pos.top + 'px', + left: pos.left + 'px', + display: isOpen ? 'block' : 'none' + }); + } + + $animate[isOpen ? 'addClass' : 'removeClass'](self.$element, openClass); + + if ( isOpen ) { + scope.focusToggleElement(); + dropdownService.open( scope ); + } else { + dropdownService.close( scope ); + } + + setIsOpen($scope, isOpen); + if (angular.isDefined(isOpen) && isOpen !== wasOpen) { + toggleInvoker($scope, { open: !!isOpen }); + } + }); + + $scope.$on('$locationChangeSuccess', function() { + scope.isOpen = false; + }); + + $scope.$on('$destroy', function() { + scope.$destroy(); + }); +}]) + +.directive('dropdown', function() { + return { + controller: 'DropdownController', + link: function(scope, element, attrs, dropdownCtrl) { + dropdownCtrl.init( element ); + } + }; +}) + +.directive('dropdownMenu', function() { + return { + restrict: 'AC', + require: '?^dropdown', + link: function(scope, element, attrs, dropdownCtrl) { + if ( !dropdownCtrl ) { + return; + } + dropdownCtrl.dropdownMenu = element; + } + }; +}) + +.directive('dropdownToggle', function() { + return { + require: '?^dropdown', + link: function(scope, element, attrs, dropdownCtrl) { + if ( !dropdownCtrl ) { + return; + } + + dropdownCtrl.toggleElement = element; + + var toggleDropdown = function(event) { + event.preventDefault(); + + if ( !element.hasClass('disabled') && !attrs.disabled ) { + scope.$apply(function() { + dropdownCtrl.toggle(); + }); + } + }; + + element.bind('click', toggleDropdown); + + // WAI-ARIA + element.attr({ 'aria-haspopup': true, 'aria-expanded': false }); + scope.$watch(dropdownCtrl.isOpen, function( isOpen ) { + element.attr('aria-expanded', !!isOpen); + }); + + scope.$on('$destroy', function() { + element.unbind('click', toggleDropdown); + }); + } + }; +}); + +angular.module('ui.bootstrap.modal', []) + +/** + * A helper, internal data structure that acts as a map but also allows getting / removing + * elements in the LIFO order + */ + .factory('$$stackedMap', function () { + return { + createNew: function () { + var stack = []; + + return { + add: function (key, value) { + stack.push({ + key: key, + value: value + }); + }, + get: function (key) { + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + return stack[i]; + } + } + }, + keys: function() { + var keys = []; + for (var i = 0; i < stack.length; i++) { + keys.push(stack[i].key); + } + return keys; + }, + top: function () { + return stack[stack.length - 1]; + }, + remove: function (key) { + var idx = -1; + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + idx = i; + break; + } + } + return stack.splice(idx, 1)[0]; + }, + removeTop: function () { + return stack.splice(stack.length - 1, 1)[0]; + }, + length: function () { + return stack.length; + } + }; + } + }; + }) + +/** + * A helper directive for the $modal service. It creates a backdrop element. + */ + .directive('modalBackdrop', ['$timeout', function ($timeout) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/modal/backdrop.html', + compile: function (tElement, tAttrs) { + tElement.addClass(tAttrs.backdropClass); + return linkFn; + } + }; + + function linkFn(scope, element, attrs) { + scope.animate = false; + + //trigger CSS transitions + $timeout(function () { + scope.animate = true; + }); + } + }]) + + .directive('modalWindow', ['$modalStack', '$q', function ($modalStack, $q) { + return { + restrict: 'EA', + scope: { + index: '@', + animate: '=' + }, + replace: true, + transclude: true, + templateUrl: function(tElement, tAttrs) { + return tAttrs.templateUrl || 'template/modal/window.html'; + }, + link: function (scope, element, attrs) { + element.addClass(attrs.windowClass || ''); + scope.size = attrs.size; + + scope.close = function (evt) { + var modal = $modalStack.getTop(); + if (modal && modal.value.backdrop && modal.value.backdrop != 'static' && (evt.target === evt.currentTarget)) { + evt.preventDefault(); + evt.stopPropagation(); + $modalStack.dismiss(modal.key, 'backdrop click'); + } + }; + + // This property is only added to the scope for the purpose of detecting when this directive is rendered. + // We can detect that by using this property in the template associated with this directive and then use + // {@link Attribute#$observe} on it. For more details please see {@link TableColumnResize}. + scope.$isRendered = true; + + // Deferred object that will be resolved when this modal is render. + var modalRenderDeferObj = $q.defer(); + // Observe function will be called on next digest cycle after compilation, ensuring that the DOM is ready. + // In order to use this way of finding whether DOM is ready, we need to observe a scope property used in modal's template. + attrs.$observe('modalRender', function (value) { + if (value == 'true') { + modalRenderDeferObj.resolve(); + } + }); + + modalRenderDeferObj.promise.then(function () { + // trigger CSS transitions + scope.animate = true; + + var inputsWithAutofocus = element[0].querySelectorAll('[autofocus]'); + /** + * Auto-focusing of a freshly-opened modal element causes any child elements + * with the autofocus attribute to lose focus. This is an issue on touch + * based devices which will show and then hide the onscreen keyboard. + * Attempts to refocus the autofocus element via JavaScript will not reopen + * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus + * the modal element if the modal does not contain an autofocus element. + */ + if (inputsWithAutofocus.length) { + inputsWithAutofocus[0].focus(); + } else { + element[0].focus(); + } + + // Notify {@link $modalStack} that modal is rendered. + var modal = $modalStack.getTop(); + if (modal) { + $modalStack.modalRendered(modal.key); + } + }); + } + }; + }]) + + .directive('modalAnimationClass', [ + function () { + return { + compile: function (tElement, tAttrs) { + if (tAttrs.modalAnimation) { + tElement.addClass(tAttrs.modalAnimationClass); + } + } + }; + }]) + + .directive('modalTransclude', function () { + return { + link: function($scope, $element, $attrs, controller, $transclude) { + $transclude($scope.$parent, function(clone) { + $element.empty(); + $element.append(clone); + }); + } + }; + }) + + .factory('$modalStack', ['$animate', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap', + function ($animate, $timeout, $document, $compile, $rootScope, $$stackedMap) { + + var OPENED_MODAL_CLASS = 'modal-open'; + + var backdropDomEl, backdropScope; + var openedWindows = $$stackedMap.createNew(); + var $modalStack = {}; + + function backdropIndex() { + var topBackdropIndex = -1; + var opened = openedWindows.keys(); + for (var i = 0; i < opened.length; i++) { + if (openedWindows.get(opened[i]).value.backdrop) { + topBackdropIndex = i; + } + } + return topBackdropIndex; + } + + $rootScope.$watch(backdropIndex, function(newBackdropIndex){ + if (backdropScope) { + backdropScope.index = newBackdropIndex; + } + }); + + function removeModalWindow(modalInstance) { + + var body = $document.find('body').eq(0); + var modalWindow = openedWindows.get(modalInstance).value; + + //clean up the stack + openedWindows.remove(modalInstance); + + //remove window DOM element + removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() { + body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0); + checkRemoveBackdrop(); + }); + } + + function checkRemoveBackdrop() { + //remove backdrop if no longer needed + if (backdropDomEl && backdropIndex() == -1) { + var backdropScopeRef = backdropScope; + removeAfterAnimate(backdropDomEl, backdropScope, function () { + backdropScopeRef = null; + }); + backdropDomEl = undefined; + backdropScope = undefined; + } + } + + function removeAfterAnimate(domEl, scope, done) { + // Closing animation + scope.animate = false; + + if (domEl.attr('modal-animation') && $animate.enabled()) { + // transition out + domEl.one('$animate:close', function closeFn() { + $rootScope.$evalAsync(afterAnimating); + }); + } else { + // Ensure this call is async + $timeout(afterAnimating); + } + + function afterAnimating() { + if (afterAnimating.done) { + return; + } + afterAnimating.done = true; + + domEl.remove(); + scope.$destroy(); + if (done) { + done(); + } + } + } + + $document.bind('keydown', function (evt) { + var modal; + + if (evt.which === 27) { + modal = openedWindows.top(); + if (modal && modal.value.keyboard) { + evt.preventDefault(); + $rootScope.$apply(function () { + $modalStack.dismiss(modal.key, 'escape key press'); + }); + } + } + }); + + $modalStack.open = function (modalInstance, modal) { + + var modalOpener = $document[0].activeElement; + + openedWindows.add(modalInstance, { + deferred: modal.deferred, + renderDeferred: modal.renderDeferred, + modalScope: modal.scope, + backdrop: modal.backdrop, + keyboard: modal.keyboard + }); + + var body = $document.find('body').eq(0), + currBackdropIndex = backdropIndex(); + + if (currBackdropIndex >= 0 && !backdropDomEl) { + backdropScope = $rootScope.$new(true); + backdropScope.index = currBackdropIndex; + var angularBackgroundDomEl = angular.element('
      '); + angularBackgroundDomEl.attr('backdrop-class', modal.backdropClass); + if (modal.animation) { + angularBackgroundDomEl.attr('modal-animation', 'true'); + } + backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope); + body.append(backdropDomEl); + } + + var angularDomEl = angular.element('
      '); + angularDomEl.attr({ + 'template-url': modal.windowTemplateUrl, + 'window-class': modal.windowClass, + 'size': modal.size, + 'index': openedWindows.length() - 1, + 'animate': 'animate' + }).html(modal.content); + if (modal.animation) { + angularDomEl.attr('modal-animation', 'true'); + } + + var modalDomEl = $compile(angularDomEl)(modal.scope); + openedWindows.top().value.modalDomEl = modalDomEl; + openedWindows.top().value.modalOpener = modalOpener; + body.append(modalDomEl); + body.addClass(OPENED_MODAL_CLASS); + }; + + function broadcastClosing(modalWindow, resultOrReason, closing) { + return !modalWindow.value.modalScope.$broadcast('modal.closing', resultOrReason, closing).defaultPrevented; + } + + $modalStack.close = function (modalInstance, result) { + var modalWindow = openedWindows.get(modalInstance); + if (modalWindow && broadcastClosing(modalWindow, result, true)) { + modalWindow.value.deferred.resolve(result); + removeModalWindow(modalInstance); + modalWindow.value.modalOpener.focus(); + return true; + } + return !modalWindow; + }; + + $modalStack.dismiss = function (modalInstance, reason) { + var modalWindow = openedWindows.get(modalInstance); + if (modalWindow && broadcastClosing(modalWindow, reason, false)) { + modalWindow.value.deferred.reject(reason); + removeModalWindow(modalInstance); + modalWindow.value.modalOpener.focus(); + return true; + } + return !modalWindow; + }; + + $modalStack.dismissAll = function (reason) { + var topModal = this.getTop(); + while (topModal && this.dismiss(topModal.key, reason)) { + topModal = this.getTop(); + } + }; + + $modalStack.getTop = function () { + return openedWindows.top(); + }; + + $modalStack.modalRendered = function (modalInstance) { + var modalWindow = openedWindows.get(modalInstance); + if (modalWindow) { + modalWindow.value.renderDeferred.resolve(); + } + }; + + return $modalStack; + }]) + + .provider('$modal', function () { + + var $modalProvider = { + options: { + animation: true, + backdrop: true, //can also be false or 'static' + keyboard: true + }, + $get: ['$injector', '$rootScope', '$q', '$templateRequest', '$controller', '$modalStack', + function ($injector, $rootScope, $q, $templateRequest, $controller, $modalStack) { + + var $modal = {}; + + function getTemplatePromise(options) { + return options.template ? $q.when(options.template) : + $templateRequest(angular.isFunction(options.templateUrl) ? (options.templateUrl)() : options.templateUrl); + } + + function getResolvePromises(resolves) { + var promisesArr = []; + angular.forEach(resolves, function (value) { + if (angular.isFunction(value) || angular.isArray(value)) { + promisesArr.push($q.when($injector.invoke(value))); + } + }); + return promisesArr; + } + + $modal.open = function (modalOptions) { + + var modalResultDeferred = $q.defer(); + var modalOpenedDeferred = $q.defer(); + var modalRenderDeferred = $q.defer(); + + //prepare an instance of a modal to be injected into controllers and returned to a caller + var modalInstance = { + result: modalResultDeferred.promise, + opened: modalOpenedDeferred.promise, + rendered: modalRenderDeferred.promise, + close: function (result) { + return $modalStack.close(modalInstance, result); + }, + dismiss: function (reason) { + return $modalStack.dismiss(modalInstance, reason); + } + }; + + //merge and clean up options + modalOptions = angular.extend({}, $modalProvider.options, modalOptions); + modalOptions.resolve = modalOptions.resolve || {}; + + //verify options + if (!modalOptions.template && !modalOptions.templateUrl) { + throw new Error('One of template or templateUrl options is required.'); + } + + var templateAndResolvePromise = + $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve))); + + + templateAndResolvePromise.then(function resolveSuccess(tplAndVars) { + + var modalScope = (modalOptions.scope || $rootScope).$new(); + modalScope.$close = modalInstance.close; + modalScope.$dismiss = modalInstance.dismiss; + + var ctrlInstance, ctrlLocals = {}; + var resolveIter = 1; + + //controllers + if (modalOptions.controller) { + ctrlLocals.$scope = modalScope; + ctrlLocals.$modalInstance = modalInstance; + angular.forEach(modalOptions.resolve, function (value, key) { + ctrlLocals[key] = tplAndVars[resolveIter++]; + }); + + ctrlInstance = $controller(modalOptions.controller, ctrlLocals); + if (modalOptions.controllerAs) { + modalScope[modalOptions.controllerAs] = ctrlInstance; + } + } + + $modalStack.open(modalInstance, { + scope: modalScope, + deferred: modalResultDeferred, + renderDeferred: modalRenderDeferred, + content: tplAndVars[0], + animation: modalOptions.animation, + backdrop: modalOptions.backdrop, + keyboard: modalOptions.keyboard, + backdropClass: modalOptions.backdropClass, + windowClass: modalOptions.windowClass, + windowTemplateUrl: modalOptions.windowTemplateUrl, + size: modalOptions.size + }); + + }, function resolveError(reason) { + modalResultDeferred.reject(reason); + }); + + templateAndResolvePromise.then(function () { + modalOpenedDeferred.resolve(true); + }, function (reason) { + modalOpenedDeferred.reject(reason); + }); + + return modalInstance; + }; + + return $modal; + }] + }; + + return $modalProvider; + }); + +angular.module('ui.bootstrap.pagination', []) + +.controller('PaginationController', ['$scope', '$attrs', '$parse', function ($scope, $attrs, $parse) { + var self = this, + ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl + setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop; + + this.init = function(ngModelCtrl_, config) { + ngModelCtrl = ngModelCtrl_; + this.config = config; + + ngModelCtrl.$render = function() { + self.render(); + }; + + if ($attrs.itemsPerPage) { + $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) { + self.itemsPerPage = parseInt(value, 10); + $scope.totalPages = self.calculateTotalPages(); + }); + } else { + this.itemsPerPage = config.itemsPerPage; + } + + $scope.$watch('totalItems', function() { + $scope.totalPages = self.calculateTotalPages(); + }); + + $scope.$watch('totalPages', function(value) { + setNumPages($scope.$parent, value); // Readonly variable + + if ( $scope.page > value ) { + $scope.selectPage(value); + } else { + ngModelCtrl.$render(); + } + }); + }; + + this.calculateTotalPages = function() { + var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage); + return Math.max(totalPages || 0, 1); + }; + + this.render = function() { + $scope.page = parseInt(ngModelCtrl.$viewValue, 10) || 1; + }; + + $scope.selectPage = function(page, evt) { + if ( $scope.page !== page && page > 0 && page <= $scope.totalPages) { + if (evt && evt.target) { + evt.target.blur(); + } + ngModelCtrl.$setViewValue(page); + ngModelCtrl.$render(); + } + }; + + $scope.getText = function( key ) { + return $scope[key + 'Text'] || self.config[key + 'Text']; + }; + $scope.noPrevious = function() { + return $scope.page === 1; + }; + $scope.noNext = function() { + return $scope.page === $scope.totalPages; + }; +}]) + +.constant('paginationConfig', { + itemsPerPage: 10, + boundaryLinks: false, + directionLinks: true, + firstText: 'First', + previousText: 'Previous', + nextText: 'Next', + lastText: 'Last', + rotate: true +}) + +.directive('pagination', ['$parse', 'paginationConfig', function($parse, paginationConfig) { + return { + restrict: 'EA', + scope: { + totalItems: '=', + firstText: '@', + previousText: '@', + nextText: '@', + lastText: '@' + }, + require: ['pagination', '?ngModel'], + controller: 'PaginationController', + templateUrl: 'template/pagination/pagination.html', + replace: true, + link: function(scope, element, attrs, ctrls) { + var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + if (!ngModelCtrl) { + return; // do nothing if no ng-model + } + + // Setup configuration parameters + var maxSize = angular.isDefined(attrs.maxSize) ? scope.$parent.$eval(attrs.maxSize) : paginationConfig.maxSize, + rotate = angular.isDefined(attrs.rotate) ? scope.$parent.$eval(attrs.rotate) : paginationConfig.rotate; + scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : paginationConfig.boundaryLinks; + scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : paginationConfig.directionLinks; + + paginationCtrl.init(ngModelCtrl, paginationConfig); + + if (attrs.maxSize) { + scope.$parent.$watch($parse(attrs.maxSize), function(value) { + maxSize = parseInt(value, 10); + paginationCtrl.render(); + }); + } + + // Create page object used in template + function makePage(number, text, isActive) { + return { + number: number, + text: text, + active: isActive + }; + } + + function getPages(currentPage, totalPages) { + var pages = []; + + // Default page limits + var startPage = 1, endPage = totalPages; + var isMaxSized = ( angular.isDefined(maxSize) && maxSize < totalPages ); + + // recompute if maxSize + if ( isMaxSized ) { + if ( rotate ) { + // Current page is displayed in the middle of the visible ones + startPage = Math.max(currentPage - Math.floor(maxSize/2), 1); + endPage = startPage + maxSize - 1; + + // Adjust if limit is exceeded + if (endPage > totalPages) { + endPage = totalPages; + startPage = endPage - maxSize + 1; + } + } else { + // Visible pages are paginated with maxSize + startPage = ((Math.ceil(currentPage / maxSize) - 1) * maxSize) + 1; + + // Adjust last page if limit is exceeded + endPage = Math.min(startPage + maxSize - 1, totalPages); + } + } + + // Add page number links + for (var number = startPage; number <= endPage; number++) { + var page = makePage(number, number, number === currentPage); + pages.push(page); + } + + // Add links to move between page sets + if ( isMaxSized && ! rotate ) { + if ( startPage > 1 ) { + var previousPageSet = makePage(startPage - 1, '...', false); + pages.unshift(previousPageSet); + } + + if ( endPage < totalPages ) { + var nextPageSet = makePage(endPage + 1, '...', false); + pages.push(nextPageSet); + } + } + + return pages; + } + + var originalRender = paginationCtrl.render; + paginationCtrl.render = function() { + originalRender(); + if (scope.page > 0 && scope.page <= scope.totalPages) { + scope.pages = getPages(scope.page, scope.totalPages); + } + }; + } + }; +}]) + +.constant('pagerConfig', { + itemsPerPage: 10, + previousText: '« Previous', + nextText: 'Next »', + align: true +}) + +.directive('pager', ['pagerConfig', function(pagerConfig) { + return { + restrict: 'EA', + scope: { + totalItems: '=', + previousText: '@', + nextText: '@' + }, + require: ['pager', '?ngModel'], + controller: 'PaginationController', + templateUrl: 'template/pagination/pager.html', + replace: true, + link: function(scope, element, attrs, ctrls) { + var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + if (!ngModelCtrl) { + return; // do nothing if no ng-model + } + + scope.align = angular.isDefined(attrs.align) ? scope.$parent.$eval(attrs.align) : pagerConfig.align; + paginationCtrl.init(ngModelCtrl, pagerConfig); + } + }; +}]); + +/** + * The following features are still outstanding: animation as a + * function, placement as a function, inside, support for more triggers than + * just mouse enter/leave, html tooltips, and selector delegation. + */ +angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap.bindHtml' ] ) + +/** + * The $tooltip service creates tooltip- and popover-like directives as well as + * houses global options for them. + */ +.provider( '$tooltip', function () { + // The default options tooltip and popover. + var defaultOptions = { + placement: 'top', + animation: true, + popupDelay: 0, + useContentExp: false + }; + + // Default hide triggers for each show trigger + var triggerMap = { + 'mouseenter': 'mouseleave', + 'click': 'click', + 'focus': 'blur' + }; + + // The options specified to the provider globally. + var globalOptions = {}; + + /** + * `options({})` allows global configuration of all tooltips in the + * application. + * + * var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) { + * // place tooltips left instead of top by default + * $tooltipProvider.options( { placement: 'left' } ); + * }); + */ + this.options = function( value ) { + angular.extend( globalOptions, value ); + }; + + /** + * This allows you to extend the set of trigger mappings available. E.g.: + * + * $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' ); + */ + this.setTriggers = function setTriggers ( triggers ) { + angular.extend( triggerMap, triggers ); + }; + + /** + * This is a helper function for translating camel-case to snake-case. + */ + function snake_case(name){ + var regexp = /[A-Z]/g; + var separator = '-'; + return name.replace(regexp, function(letter, pos) { + return (pos ? separator : '') + letter.toLowerCase(); + }); + } + + /** + * Returns the actual instance of the $tooltip service. + * TODO support multiple triggers + */ + this.$get = [ '$window', '$compile', '$timeout', '$document', '$position', '$interpolate', function ( $window, $compile, $timeout, $document, $position, $interpolate ) { + return function $tooltip ( type, prefix, defaultTriggerShow, options ) { + options = angular.extend( {}, defaultOptions, globalOptions, options ); + + /** + * Returns an object of show and hide triggers. + * + * If a trigger is supplied, + * it is used to show the tooltip; otherwise, it will use the `trigger` + * option passed to the `$tooltipProvider.options` method; else it will + * default to the trigger supplied to this directive factory. + * + * The hide trigger is based on the show trigger. If the `trigger` option + * was passed to the `$tooltipProvider.options` method, it will use the + * mapped trigger from `triggerMap` or the passed trigger if the map is + * undefined; otherwise, it uses the `triggerMap` value of the show + * trigger; else it will just use the show trigger. + */ + function getTriggers ( trigger ) { + var show = trigger || options.trigger || defaultTriggerShow; + var hide = triggerMap[show] || show; + return { + show: show, + hide: hide + }; + } + + var directiveName = snake_case( type ); + + var startSym = $interpolate.startSymbol(); + var endSym = $interpolate.endSymbol(); + var template = + '
      '+ + '
      '; + + return { + restrict: 'EA', + compile: function (tElem, tAttrs) { + var tooltipLinker = $compile( template ); + + return function link ( scope, element, attrs, tooltipCtrl ) { + var tooltip; + var tooltipLinkedScope; + var transitionTimeout; + var popupTimeout; + var appendToBody = angular.isDefined( options.appendToBody ) ? options.appendToBody : false; + var triggers = getTriggers( undefined ); + var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']); + var ttScope = scope.$new(true); + + var positionTooltip = function () { + if (!tooltip) { return; } + + var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody); + ttPosition.top += 'px'; + ttPosition.left += 'px'; + + // Now set the calculated positioning. + tooltip.css( ttPosition ); + }; + + // Set up the correct scope to allow transclusion later + ttScope.origScope = scope; + + // By default, the tooltip is not open. + // TODO add ability to start tooltip opened + ttScope.isOpen = false; + + function toggleTooltipBind () { + if ( ! ttScope.isOpen ) { + showTooltipBind(); + } else { + hideTooltipBind(); + } + } + + // Show the tooltip with delay if specified, otherwise show it immediately + function showTooltipBind() { + if(hasEnableExp && !scope.$eval(attrs[prefix+'Enable'])) { + return; + } + + prepareTooltip(); + + if ( ttScope.popupDelay ) { + // Do nothing if the tooltip was already scheduled to pop-up. + // This happens if show is triggered multiple times before any hide is triggered. + if (!popupTimeout) { + popupTimeout = $timeout( show, ttScope.popupDelay, false ); + popupTimeout.then(function(reposition){reposition();}); + } + } else { + show()(); + } + } + + function hideTooltipBind () { + scope.$apply(function () { + hide(); + }); + } + + // Show the tooltip popup element. + function show() { + + popupTimeout = null; + + // If there is a pending remove transition, we must cancel it, lest the + // tooltip be mysteriously removed. + if ( transitionTimeout ) { + $timeout.cancel( transitionTimeout ); + transitionTimeout = null; + } + + // Don't show empty tooltips. + if ( !(options.useContentExp ? ttScope.contentExp() : ttScope.content) ) { + return angular.noop; + } + + createTooltip(); + + // Set the initial positioning. + tooltip.css({ top: 0, left: 0, display: 'block' }); + ttScope.$digest(); + + positionTooltip(); + + // And show the tooltip. + ttScope.isOpen = true; + ttScope.$apply(); // digest required as $apply is not called + + // Return positioning function as promise callback for correct + // positioning after draw. + return positionTooltip; + } + + // Hide the tooltip popup element. + function hide() { + // First things first: we don't show it anymore. + ttScope.isOpen = false; + + //if tooltip is going to be shown after delay, we must cancel this + $timeout.cancel( popupTimeout ); + popupTimeout = null; + + // And now we remove it from the DOM. However, if we have animation, we + // need to wait for it to expire beforehand. + // FIXME: this is a placeholder for a port of the transitions library. + if ( ttScope.animation ) { + if (!transitionTimeout) { + transitionTimeout = $timeout(removeTooltip, 500); + } + } else { + removeTooltip(); + } + } + + function createTooltip() { + // There can only be one tooltip element per directive shown at once. + if (tooltip) { + removeTooltip(); + } + tooltipLinkedScope = ttScope.$new(); + tooltip = tooltipLinker(tooltipLinkedScope, function (tooltip) { + if ( appendToBody ) { + $document.find( 'body' ).append( tooltip ); + } else { + element.after( tooltip ); + } + }); + + tooltipLinkedScope.$watch(function () { + $timeout(positionTooltip, 0, false); + }); + + if (options.useContentExp) { + tooltipLinkedScope.$watch('contentExp()', function (val) { + if (!val && ttScope.isOpen ) { + hide(); + } + }); + } + } + + function removeTooltip() { + transitionTimeout = null; + if (tooltip) { + tooltip.remove(); + tooltip = null; + } + if (tooltipLinkedScope) { + tooltipLinkedScope.$destroy(); + tooltipLinkedScope = null; + } + } + + function prepareTooltip() { + prepPopupClass(); + prepPlacement(); + prepPopupDelay(); + } + + ttScope.contentExp = function () { + return scope.$eval(attrs[type]); + }; + + /** + * Observe the relevant attributes. + */ + if (!options.useContentExp) { + attrs.$observe( type, function ( val ) { + ttScope.content = val; + + if (!val && ttScope.isOpen ) { + hide(); + } + }); + } + + attrs.$observe( 'disabled', function ( val ) { + if (val && ttScope.isOpen ) { + hide(); + } + }); + + attrs.$observe( prefix+'Title', function ( val ) { + ttScope.title = val; + }); + + function prepPopupClass() { + ttScope.popupClass = attrs[prefix + 'Class']; + } + + function prepPlacement() { + var val = attrs[ prefix + 'Placement' ]; + ttScope.placement = angular.isDefined( val ) ? val : options.placement; + } + + function prepPopupDelay() { + var val = attrs[ prefix + 'PopupDelay' ]; + var delay = parseInt( val, 10 ); + ttScope.popupDelay = ! isNaN(delay) ? delay : options.popupDelay; + } + + var unregisterTriggers = function () { + element.unbind(triggers.show, showTooltipBind); + element.unbind(triggers.hide, hideTooltipBind); + }; + + function prepTriggers() { + var val = attrs[ prefix + 'Trigger' ]; + unregisterTriggers(); + + triggers = getTriggers( val ); + + if ( triggers.show === triggers.hide ) { + element.bind( triggers.show, toggleTooltipBind ); + } else { + element.bind( triggers.show, showTooltipBind ); + element.bind( triggers.hide, hideTooltipBind ); + } + } + prepTriggers(); + + var animation = scope.$eval(attrs[prefix + 'Animation']); + ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation; + + var appendToBodyVal = scope.$eval(attrs[prefix + 'AppendToBody']); + appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody; + + // if a tooltip is attached to we need to remove it on + // location change as its parent scope will probably not be destroyed + // by the change. + if ( appendToBody ) { + scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess () { + if ( ttScope.isOpen ) { + hide(); + } + }); + } + + // Make sure tooltip is destroyed and removed. + scope.$on('$destroy', function onDestroyTooltip() { + $timeout.cancel( transitionTimeout ); + $timeout.cancel( popupTimeout ); + unregisterTriggers(); + removeTooltip(); + ttScope = null; + }); + }; + } + }; + }; + }]; +}) + +// This is mostly ngInclude code but with a custom scope +.directive( 'tooltipTemplateTransclude', [ + '$animate', '$sce', '$compile', '$templateRequest', +function ($animate , $sce , $compile , $templateRequest) { + return { + link: function ( scope, elem, attrs ) { + var origScope = scope.$eval(attrs.tooltipTemplateTranscludeScope); + + var changeCounter = 0, + currentScope, + previousElement, + currentElement; + + var cleanupLastIncludeContent = function() { + if (previousElement) { + previousElement.remove(); + previousElement = null; + } + if (currentScope) { + currentScope.$destroy(); + currentScope = null; + } + if (currentElement) { + $animate.leave(currentElement).then(function() { + previousElement = null; + }); + previousElement = currentElement; + currentElement = null; + } + }; + + scope.$watch($sce.parseAsResourceUrl(attrs.tooltipTemplateTransclude), function (src) { + var thisChangeId = ++changeCounter; + + if (src) { + //set the 2nd param to true to ignore the template request error so that the inner + //contents and scope can be cleaned up. + $templateRequest(src, true).then(function(response) { + if (thisChangeId !== changeCounter) { return; } + var newScope = origScope.$new(); + var template = response; + + var clone = $compile(template)(newScope, function(clone) { + cleanupLastIncludeContent(); + $animate.enter(clone, elem); + }); + + currentScope = newScope; + currentElement = clone; + + currentScope.$emit('$includeContentLoaded', src); + }, function() { + if (thisChangeId === changeCounter) { + cleanupLastIncludeContent(); + scope.$emit('$includeContentError', src); + } + }); + scope.$emit('$includeContentRequested', src); + } else { + cleanupLastIncludeContent(); + } + }); + + scope.$on('$destroy', cleanupLastIncludeContent); + } + }; +}]) + +/** + * Note that it's intentional that these classes are *not* applied through $animate. + * They must not be animated as they're expected to be present on the tooltip on + * initialization. + */ +.directive('tooltipClasses', function () { + return { + restrict: 'A', + link: function (scope, element, attrs) { + if (scope.placement) { + element.addClass(scope.placement); + } + if (scope.popupClass) { + element.addClass(scope.popupClass); + } + if (scope.animation()) { + element.addClass(attrs.tooltipAnimationClass); + } + } + }; +}) + +.directive( 'tooltipPopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/tooltip/tooltip-popup.html' + }; +}) + +.directive( 'tooltip', [ '$tooltip', function ( $tooltip ) { + return $tooltip( 'tooltip', 'tooltip', 'mouseenter' ); +}]) + +.directive( 'tooltipTemplatePopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&', + originScope: '&' }, + templateUrl: 'template/tooltip/tooltip-template-popup.html' + }; +}) + +.directive( 'tooltipTemplate', [ '$tooltip', function ( $tooltip ) { + return $tooltip('tooltipTemplate', 'tooltip', 'mouseenter', { + useContentExp: true + }); +}]) + +.directive( 'tooltipHtmlPopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/tooltip/tooltip-html-popup.html' + }; +}) + +.directive( 'tooltipHtml', [ '$tooltip', function ( $tooltip ) { + return $tooltip('tooltipHtml', 'tooltip', 'mouseenter', { + useContentExp: true + }); +}]) + +/* +Deprecated +*/ +.directive( 'tooltipHtmlUnsafePopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html' + }; +}) + +.value('tooltipHtmlUnsafeSuppressDeprecated', false) +.directive( 'tooltipHtmlUnsafe', [ + '$tooltip', 'tooltipHtmlUnsafeSuppressDeprecated', '$log', +function ( $tooltip , tooltipHtmlUnsafeSuppressDeprecated , $log) { + if (!tooltipHtmlUnsafeSuppressDeprecated) { + $log.warn('tooltip-html-unsafe is now deprecated. Use tooltip-html or tooltip-template instead.'); + } + return $tooltip( 'tooltipHtmlUnsafe', 'tooltip', 'mouseenter' ); +}]); + +/** + * The following features are still outstanding: popup delay, animation as a + * function, placement as a function, inside, support for more triggers than + * just mouse enter/leave, html popovers, and selector delegatation. + */ +angular.module( 'ui.bootstrap.popover', [ 'ui.bootstrap.tooltip' ] ) + +.directive( 'popoverTemplatePopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { title: '@', contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&', + originScope: '&' }, + templateUrl: 'template/popover/popover-template.html' + }; +}) + +.directive( 'popoverTemplate', [ '$tooltip', function ( $tooltip ) { + return $tooltip( 'popoverTemplate', 'popover', 'click', { + useContentExp: true + } ); +}]) + +.directive( 'popoverPopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { title: '@', content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/popover/popover.html' + }; +}) + +.directive( 'popover', [ '$tooltip', function ( $tooltip ) { + return $tooltip( 'popover', 'popover', 'click' ); +}]); + +angular.module('ui.bootstrap.progressbar', []) + +.constant('progressConfig', { + animate: true, + max: 100 +}) + +.controller('ProgressController', ['$scope', '$attrs', 'progressConfig', function($scope, $attrs, progressConfig) { + var self = this, + animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate; + + this.bars = []; + $scope.max = angular.isDefined($scope.max) ? $scope.max : progressConfig.max; + + this.addBar = function(bar, element) { + if ( !animate ) { + element.css({'transition': 'none'}); + } + + this.bars.push(bar); + + bar.$watch('value', function( value ) { + bar.percent = +(100 * value / $scope.max).toFixed(2); + }); + + bar.$on('$destroy', function() { + element = null; + self.removeBar(bar); + }); + }; + + this.removeBar = function(bar) { + this.bars.splice(this.bars.indexOf(bar), 1); + }; +}]) + +.directive('progress', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + controller: 'ProgressController', + require: 'progress', + scope: {}, + templateUrl: 'template/progressbar/progress.html' + }; +}) + +.directive('bar', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + require: '^progress', + scope: { + value: '=', + max: '=?', + type: '@' + }, + templateUrl: 'template/progressbar/bar.html', + link: function(scope, element, attrs, progressCtrl) { + progressCtrl.addBar(scope, element); + } + }; +}) + +.directive('progressbar', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + controller: 'ProgressController', + scope: { + value: '=', + max: '=?', + type: '@' + }, + templateUrl: 'template/progressbar/progressbar.html', + link: function(scope, element, attrs, progressCtrl) { + progressCtrl.addBar(scope, angular.element(element.children()[0])); + } + }; +}); + +angular.module('ui.bootstrap.rating', []) + +.constant('ratingConfig', { + max: 5, + stateOn: null, + stateOff: null +}) + +.controller('RatingController', ['$scope', '$attrs', 'ratingConfig', function($scope, $attrs, ratingConfig) { + var ngModelCtrl = { $setViewValue: angular.noop }; + + this.init = function(ngModelCtrl_) { + ngModelCtrl = ngModelCtrl_; + ngModelCtrl.$render = this.render; + + ngModelCtrl.$formatters.push(function(value) { + if (angular.isNumber(value) && value << 0 !== value) { + value = Math.round(value); + } + return value; + }); + + this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn; + this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff; + + var ratingStates = angular.isDefined($attrs.ratingStates) ? $scope.$parent.$eval($attrs.ratingStates) : + new Array( angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max ); + $scope.range = this.buildTemplateObjects(ratingStates); + }; + + this.buildTemplateObjects = function(states) { + for (var i = 0, n = states.length; i < n; i++) { + states[i] = angular.extend({ index: i }, { stateOn: this.stateOn, stateOff: this.stateOff }, states[i]); + } + return states; + }; + + $scope.rate = function(value) { + if ( !$scope.readonly && value >= 0 && value <= $scope.range.length ) { + ngModelCtrl.$setViewValue(value); + ngModelCtrl.$render(); + } + }; + + $scope.enter = function(value) { + if ( !$scope.readonly ) { + $scope.value = value; + } + $scope.onHover({value: value}); + }; + + $scope.reset = function() { + $scope.value = ngModelCtrl.$viewValue; + $scope.onLeave(); + }; + + $scope.onKeydown = function(evt) { + if (/(37|38|39|40)/.test(evt.which)) { + evt.preventDefault(); + evt.stopPropagation(); + $scope.rate( $scope.value + (evt.which === 38 || evt.which === 39 ? 1 : -1) ); + } + }; + + this.render = function() { + $scope.value = ngModelCtrl.$viewValue; + }; +}]) + +.directive('rating', function() { + return { + restrict: 'EA', + require: ['rating', 'ngModel'], + scope: { + readonly: '=?', + onHover: '&', + onLeave: '&' + }, + controller: 'RatingController', + templateUrl: 'template/rating/rating.html', + replace: true, + link: function(scope, element, attrs, ctrls) { + var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + ratingCtrl.init( ngModelCtrl ); + } + }; +}); + +/** + * @ngdoc overview + * @name ui.bootstrap.tabs + * + * @description + * AngularJS version of the tabs directive. + */ + +angular.module('ui.bootstrap.tabs', []) + +.controller('TabsetController', ['$scope', function TabsetCtrl($scope) { + var ctrl = this, + tabs = ctrl.tabs = $scope.tabs = []; + + ctrl.select = function(selectedTab) { + angular.forEach(tabs, function(tab) { + if (tab.active && tab !== selectedTab) { + tab.active = false; + tab.onDeselect(); + } + }); + selectedTab.active = true; + selectedTab.onSelect(); + }; + + ctrl.addTab = function addTab(tab) { + tabs.push(tab); + // we can't run the select function on the first tab + // since that would select it twice + if (tabs.length === 1 && tab.active !== false) { + tab.active = true; + } else if (tab.active) { + ctrl.select(tab); + } + else { + tab.active = false; + } + }; + + ctrl.removeTab = function removeTab(tab) { + var index = tabs.indexOf(tab); + //Select a new tab if the tab to be removed is selected and not destroyed + if (tab.active && tabs.length > 1 && !destroyed) { + //If this is the last tab, select the previous tab. else, the next tab. + var newActiveIndex = index == tabs.length - 1 ? index - 1 : index + 1; + ctrl.select(tabs[newActiveIndex]); + } + tabs.splice(index, 1); + }; + + var destroyed; + $scope.$on('$destroy', function() { + destroyed = true; + }); +}]) + +/** + * @ngdoc directive + * @name ui.bootstrap.tabs.directive:tabset + * @restrict EA + * + * @description + * Tabset is the outer container for the tabs directive + * + * @param {boolean=} vertical Whether or not to use vertical styling for the tabs. + * @param {boolean=} justified Whether or not to use justified styling for the tabs. + * + * @example + + + + First Content! + Second Content! + +
      + + First Vertical Content! + Second Vertical Content! + + + First Justified Content! + Second Justified Content! + +
      +
      + */ +.directive('tabset', function() { + return { + restrict: 'EA', + transclude: true, + replace: true, + scope: { + type: '@' + }, + controller: 'TabsetController', + templateUrl: 'template/tabs/tabset.html', + link: function(scope, element, attrs) { + scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false; + scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false; + } + }; +}) + +/** + * @ngdoc directive + * @name ui.bootstrap.tabs.directive:tab + * @restrict EA + * + * @param {string=} heading The visible heading, or title, of the tab. Set HTML headings with {@link ui.bootstrap.tabs.directive:tabHeading tabHeading}. + * @param {string=} select An expression to evaluate when the tab is selected. + * @param {boolean=} active A binding, telling whether or not this tab is selected. + * @param {boolean=} disabled A binding, telling whether or not this tab is disabled. + * + * @description + * Creates a tab with a heading and content. Must be placed within a {@link ui.bootstrap.tabs.directive:tabset tabset}. + * + * @example + + +
      + + +
      + + First Tab + + Alert me! + Second Tab, with alert callback and html heading! + + + {{item.content}} + + +
      +
      + + function TabsDemoCtrl($scope) { + $scope.items = [ + { title:"Dynamic Title 1", content:"Dynamic Item 0" }, + { title:"Dynamic Title 2", content:"Dynamic Item 1", disabled: true } + ]; + + $scope.alertMe = function() { + setTimeout(function() { + alert("You've selected the alert tab!"); + }); + }; + }; + +
      + */ + +/** + * @ngdoc directive + * @name ui.bootstrap.tabs.directive:tabHeading + * @restrict EA + * + * @description + * Creates an HTML heading for a {@link ui.bootstrap.tabs.directive:tab tab}. Must be placed as a child of a tab element. + * + * @example + + + + + HTML in my titles?! + And some content, too! + + + Icon heading?!? + That's right. + + + + + */ +.directive('tab', ['$parse', '$log', function($parse, $log) { + return { + require: '^tabset', + restrict: 'EA', + replace: true, + templateUrl: 'template/tabs/tab.html', + transclude: true, + scope: { + active: '=?', + heading: '@', + onSelect: '&select', //This callback is called in contentHeadingTransclude + //once it inserts the tab's content into the dom + onDeselect: '&deselect' + }, + controller: function() { + //Empty controller so other directives can require being 'under' a tab + }, + compile: function(elm, attrs, transclude) { + return function postLink(scope, elm, attrs, tabsetCtrl) { + scope.$watch('active', function(active) { + if (active) { + tabsetCtrl.select(scope); + } + }); + + scope.disabled = false; + if ( attrs.disable ) { + scope.$parent.$watch($parse(attrs.disable), function(value) { + scope.disabled = !! value; + }); + } + + // Deprecation support of "disabled" parameter + // fix(tab): IE9 disabled attr renders grey text on enabled tab #2677 + // This code is duplicated from the lines above to make it easy to remove once + // the feature has been completely deprecated + if ( attrs.disabled ) { + $log.warn('Use of "disabled" attribute has been deprecated, please use "disable"'); + scope.$parent.$watch($parse(attrs.disabled), function(value) { + scope.disabled = !! value; + }); + } + + scope.select = function() { + if ( !scope.disabled ) { + scope.active = true; + } + }; + + tabsetCtrl.addTab(scope); + scope.$on('$destroy', function() { + tabsetCtrl.removeTab(scope); + }); + + //We need to transclude later, once the content container is ready. + //when this link happens, we're inside a tab heading. + scope.$transcludeFn = transclude; + }; + } + }; +}]) + +.directive('tabHeadingTransclude', [function() { + return { + restrict: 'A', + require: '^tab', + link: function(scope, elm, attrs, tabCtrl) { + scope.$watch('headingElement', function updateHeadingElement(heading) { + if (heading) { + elm.html(''); + elm.append(heading); + } + }); + } + }; +}]) + +.directive('tabContentTransclude', function() { + return { + restrict: 'A', + require: '^tabset', + link: function(scope, elm, attrs) { + var tab = scope.$eval(attrs.tabContentTransclude); + + //Now our tab is ready to be transcluded: both the tab heading area + //and the tab content area are loaded. Transclude 'em both. + tab.$transcludeFn(tab.$parent, function(contents) { + angular.forEach(contents, function(node) { + if (isTabHeading(node)) { + //Let tabHeadingTransclude know. + tab.headingElement = node; + } else { + elm.append(node); + } + }); + }); + } + }; + function isTabHeading(node) { + return node.tagName && ( + node.hasAttribute('tab-heading') || + node.hasAttribute('data-tab-heading') || + node.tagName.toLowerCase() === 'tab-heading' || + node.tagName.toLowerCase() === 'data-tab-heading' + ); + } +}) + +; + +angular.module('ui.bootstrap.timepicker', []) + +.constant('timepickerConfig', { + hourStep: 1, + minuteStep: 1, + showMeridian: true, + meridians: null, + readonlyInput: false, + mousewheel: true, + arrowkeys: true +}) + +.controller('TimepickerController', ['$scope', '$attrs', '$parse', '$log', '$locale', 'timepickerConfig', function($scope, $attrs, $parse, $log, $locale, timepickerConfig) { + var selected = new Date(), + ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl + meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS; + + this.init = function( ngModelCtrl_, inputs ) { + ngModelCtrl = ngModelCtrl_; + ngModelCtrl.$render = this.render; + + ngModelCtrl.$formatters.unshift(function (modelValue) { + return modelValue ? new Date( modelValue ) : null; + }); + + var hoursInputEl = inputs.eq(0), + minutesInputEl = inputs.eq(1); + + var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel; + if ( mousewheel ) { + this.setupMousewheelEvents( hoursInputEl, minutesInputEl ); + } + + var arrowkeys = angular.isDefined($attrs.arrowkeys) ? $scope.$parent.$eval($attrs.arrowkeys) : timepickerConfig.arrowkeys; + if (arrowkeys) { + this.setupArrowkeyEvents( hoursInputEl, minutesInputEl ); + } + + $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput; + this.setupInputEvents( hoursInputEl, minutesInputEl ); + }; + + var hourStep = timepickerConfig.hourStep; + if ($attrs.hourStep) { + $scope.$parent.$watch($parse($attrs.hourStep), function(value) { + hourStep = parseInt(value, 10); + }); + } + + var minuteStep = timepickerConfig.minuteStep; + if ($attrs.minuteStep) { + $scope.$parent.$watch($parse($attrs.minuteStep), function(value) { + minuteStep = parseInt(value, 10); + }); + } + + // 12H / 24H mode + $scope.showMeridian = timepickerConfig.showMeridian; + if ($attrs.showMeridian) { + $scope.$parent.$watch($parse($attrs.showMeridian), function(value) { + $scope.showMeridian = !!value; + + if ( ngModelCtrl.$error.time ) { + // Evaluate from template + var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate(); + if (angular.isDefined( hours ) && angular.isDefined( minutes )) { + selected.setHours( hours ); + refresh(); + } + } else { + updateTemplate(); + } + }); + } + + // Get $scope.hours in 24H mode if valid + function getHoursFromTemplate ( ) { + var hours = parseInt( $scope.hours, 10 ); + var valid = ( $scope.showMeridian ) ? (hours > 0 && hours < 13) : (hours >= 0 && hours < 24); + if ( !valid ) { + return undefined; + } + + if ( $scope.showMeridian ) { + if ( hours === 12 ) { + hours = 0; + } + if ( $scope.meridian === meridians[1] ) { + hours = hours + 12; + } + } + return hours; + } + + function getMinutesFromTemplate() { + var minutes = parseInt($scope.minutes, 10); + return ( minutes >= 0 && minutes < 60 ) ? minutes : undefined; + } + + function pad( value ) { + return ( angular.isDefined(value) && value.toString().length < 2 ) ? '0' + value : value.toString(); + } + + // Respond on mousewheel spin + this.setupMousewheelEvents = function( hoursInputEl, minutesInputEl ) { + var isScrollingUp = function(e) { + if (e.originalEvent) { + e = e.originalEvent; + } + //pick correct delta variable depending on event + var delta = (e.wheelDelta) ? e.wheelDelta : -e.deltaY; + return (e.detail || delta > 0); + }; + + hoursInputEl.bind('mousewheel wheel', function(e) { + $scope.$apply( (isScrollingUp(e)) ? $scope.incrementHours() : $scope.decrementHours() ); + e.preventDefault(); + }); + + minutesInputEl.bind('mousewheel wheel', function(e) { + $scope.$apply( (isScrollingUp(e)) ? $scope.incrementMinutes() : $scope.decrementMinutes() ); + e.preventDefault(); + }); + + }; + + // Respond on up/down arrowkeys + this.setupArrowkeyEvents = function( hoursInputEl, minutesInputEl ) { + hoursInputEl.bind('keydown', function(e) { + if ( e.which === 38 ) { // up + e.preventDefault(); + $scope.incrementHours(); + $scope.$apply(); + } + else if ( e.which === 40 ) { // down + e.preventDefault(); + $scope.decrementHours(); + $scope.$apply(); + } + }); + + minutesInputEl.bind('keydown', function(e) { + if ( e.which === 38 ) { // up + e.preventDefault(); + $scope.incrementMinutes(); + $scope.$apply(); + } + else if ( e.which === 40 ) { // down + e.preventDefault(); + $scope.decrementMinutes(); + $scope.$apply(); + } + }); + }; + + this.setupInputEvents = function( hoursInputEl, minutesInputEl ) { + if ( $scope.readonlyInput ) { + $scope.updateHours = angular.noop; + $scope.updateMinutes = angular.noop; + return; + } + + var invalidate = function(invalidHours, invalidMinutes) { + ngModelCtrl.$setViewValue( null ); + ngModelCtrl.$setValidity('time', false); + if (angular.isDefined(invalidHours)) { + $scope.invalidHours = invalidHours; + } + if (angular.isDefined(invalidMinutes)) { + $scope.invalidMinutes = invalidMinutes; + } + }; + + $scope.updateHours = function() { + var hours = getHoursFromTemplate(); + + if ( angular.isDefined(hours) ) { + selected.setHours( hours ); + refresh( 'h' ); + } else { + invalidate(true); + } + }; + + hoursInputEl.bind('blur', function(e) { + if ( !$scope.invalidHours && $scope.hours < 10) { + $scope.$apply( function() { + $scope.hours = pad( $scope.hours ); + }); + } + }); + + $scope.updateMinutes = function() { + var minutes = getMinutesFromTemplate(); + + if ( angular.isDefined(minutes) ) { + selected.setMinutes( minutes ); + refresh( 'm' ); + } else { + invalidate(undefined, true); + } + }; + + minutesInputEl.bind('blur', function(e) { + if ( !$scope.invalidMinutes && $scope.minutes < 10 ) { + $scope.$apply( function() { + $scope.minutes = pad( $scope.minutes ); + }); + } + }); + + }; + + this.render = function() { + var date = ngModelCtrl.$viewValue; + + if ( isNaN(date) ) { + ngModelCtrl.$setValidity('time', false); + $log.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); + } else { + if ( date ) { + selected = date; + } + makeValid(); + updateTemplate(); + } + }; + + // Call internally when we know that model is valid. + function refresh( keyboardChange ) { + makeValid(); + ngModelCtrl.$setViewValue( new Date(selected) ); + updateTemplate( keyboardChange ); + } + + function makeValid() { + ngModelCtrl.$setValidity('time', true); + $scope.invalidHours = false; + $scope.invalidMinutes = false; + } + + function updateTemplate( keyboardChange ) { + var hours = selected.getHours(), minutes = selected.getMinutes(); + + if ( $scope.showMeridian ) { + hours = ( hours === 0 || hours === 12 ) ? 12 : hours % 12; // Convert 24 to 12 hour system + } + + $scope.hours = keyboardChange === 'h' ? hours : pad(hours); + if (keyboardChange !== 'm') { + $scope.minutes = pad(minutes); + } + $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1]; + } + + function addMinutes( minutes ) { + var dt = new Date( selected.getTime() + minutes * 60000 ); + selected.setHours( dt.getHours(), dt.getMinutes() ); + refresh(); + } + + $scope.incrementHours = function() { + addMinutes( hourStep * 60 ); + }; + $scope.decrementHours = function() { + addMinutes( - hourStep * 60 ); + }; + $scope.incrementMinutes = function() { + addMinutes( minuteStep ); + }; + $scope.decrementMinutes = function() { + addMinutes( - minuteStep ); + }; + $scope.toggleMeridian = function() { + addMinutes( 12 * 60 * (( selected.getHours() < 12 ) ? 1 : -1) ); + }; +}]) + +.directive('timepicker', function () { + return { + restrict: 'EA', + require: ['timepicker', '?^ngModel'], + controller:'TimepickerController', + replace: true, + scope: {}, + templateUrl: 'template/timepicker/timepicker.html', + link: function(scope, element, attrs, ctrls) { + var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + if ( ngModelCtrl ) { + timepickerCtrl.init( ngModelCtrl, element.find('input') ); + } + } + }; +}); + +angular.module('ui.bootstrap.transition', []) + +.value('$transitionSuppressDeprecated', false) +/** + * $transition service provides a consistent interface to trigger CSS 3 transitions and to be informed when they complete. + * @param {DOMElement} element The DOMElement that will be animated. + * @param {string|object|function} trigger The thing that will cause the transition to start: + * - As a string, it represents the css class to be added to the element. + * - As an object, it represents a hash of style attributes to be applied to the element. + * - As a function, it represents a function to be called that will cause the transition to occur. + * @return {Promise} A promise that is resolved when the transition finishes. + */ +.factory('$transition', [ + '$q', '$timeout', '$rootScope', '$log', '$transitionSuppressDeprecated', +function($q , $timeout , $rootScope , $log , $transitionSuppressDeprecated) { + + if (!$transitionSuppressDeprecated) { + $log.warn('$transition is now deprecated. Use $animate from ngAnimate instead.'); + } + + var $transition = function(element, trigger, options) { + options = options || {}; + var deferred = $q.defer(); + var endEventName = $transition[options.animation ? 'animationEndEventName' : 'transitionEndEventName']; + + var transitionEndHandler = function(event) { + $rootScope.$apply(function() { + element.unbind(endEventName, transitionEndHandler); + deferred.resolve(element); + }); + }; + + if (endEventName) { + element.bind(endEventName, transitionEndHandler); + } + + // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur + $timeout(function() { + if ( angular.isString(trigger) ) { + element.addClass(trigger); + } else if ( angular.isFunction(trigger) ) { + trigger(element); + } else if ( angular.isObject(trigger) ) { + element.css(trigger); + } + //If browser does not support transitions, instantly resolve + if ( !endEventName ) { + deferred.resolve(element); + } + }); + + // Add our custom cancel function to the promise that is returned + // We can call this if we are about to run a new transition, which we know will prevent this transition from ending, + // i.e. it will therefore never raise a transitionEnd event for that transition + deferred.promise.cancel = function() { + if ( endEventName ) { + element.unbind(endEventName, transitionEndHandler); + } + deferred.reject('Transition cancelled'); + }; + + return deferred.promise; + }; + + // Work out the name of the transitionEnd event + var transElement = document.createElement('trans'); + var transitionEndEventNames = { + 'WebkitTransition': 'webkitTransitionEnd', + 'MozTransition': 'transitionend', + 'OTransition': 'oTransitionEnd', + 'transition': 'transitionend' + }; + var animationEndEventNames = { + 'WebkitTransition': 'webkitAnimationEnd', + 'MozTransition': 'animationend', + 'OTransition': 'oAnimationEnd', + 'transition': 'animationend' + }; + function findEndEventName(endEventNames) { + for (var name in endEventNames){ + if (transElement.style[name] !== undefined) { + return endEventNames[name]; + } + } + } + $transition.transitionEndEventName = findEndEventName(transitionEndEventNames); + $transition.animationEndEventName = findEndEventName(animationEndEventNames); + return $transition; +}]); + +angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap.bindHtml']) + +/** + * A helper service that can parse typeahead's syntax (string provided by users) + * Extracted to a separate service for ease of unit testing + */ + .factory('typeaheadParser', ['$parse', function ($parse) { + + // 00000111000000000000022200000000000000003333333333333330000000000044000 + var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/; + + return { + parse:function (input) { + + var match = input.match(TYPEAHEAD_REGEXP); + if (!match) { + throw new Error( + 'Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_"' + + ' but got "' + input + '".'); + } + + return { + itemName:match[3], + source:$parse(match[4]), + viewMapper:$parse(match[2] || match[1]), + modelMapper:$parse(match[1]) + }; + } + }; +}]) + + .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$position', 'typeaheadParser', + function ($compile, $parse, $q, $timeout, $document, $position, typeaheadParser) { + + var HOT_KEYS = [9, 13, 27, 38, 40]; + + return { + require:'ngModel', + link:function (originalScope, element, attrs, modelCtrl) { + + //SUPPORTED ATTRIBUTES (OPTIONS) + + //minimal no of characters that needs to be entered before typeahead kicks-in + var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1; + + //minimal wait time after last character typed before typeahead kicks-in + var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0; + + //should it restrict model values to the ones selected from the popup only? + var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false; + + //binding to a variable that indicates if matches are being retrieved asynchronously + var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop; + + //a callback executed when a match is selected + var onSelectCallback = $parse(attrs.typeaheadOnSelect); + + var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined; + + var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false; + + var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false; + + //INTERNAL VARIABLES + + //model setter executed upon match selection + var $setModelValue = $parse(attrs.ngModel).assign; + + //expressions used by typeahead + var parserResult = typeaheadParser.parse(attrs.typeahead); + + var hasFocus; + + //create a child scope for the typeahead directive so we are not polluting original scope + //with typeahead-specific data (matches, query etc.) + var scope = originalScope.$new(); + originalScope.$on('$destroy', function(){ + scope.$destroy(); + }); + + // WAI-ARIA + var popupId = 'typeahead-' + scope.$id + '-' + Math.floor(Math.random() * 10000); + element.attr({ + 'aria-autocomplete': 'list', + 'aria-expanded': false, + 'aria-owns': popupId + }); + + //pop-up element used to display matches + var popUpEl = angular.element('
      '); + popUpEl.attr({ + id: popupId, + matches: 'matches', + active: 'activeIdx', + select: 'select(activeIdx)', + query: 'query', + position: 'position' + }); + //custom item template + if (angular.isDefined(attrs.typeaheadTemplateUrl)) { + popUpEl.attr('template-url', attrs.typeaheadTemplateUrl); + } + + var resetMatches = function() { + scope.matches = []; + scope.activeIdx = -1; + element.attr('aria-expanded', false); + }; + + var getMatchId = function(index) { + return popupId + '-option-' + index; + }; + + // Indicate that the specified match is the active (pre-selected) item in the list owned by this typeahead. + // This attribute is added or removed automatically when the `activeIdx` changes. + scope.$watch('activeIdx', function(index) { + if (index < 0) { + element.removeAttr('aria-activedescendant'); + } else { + element.attr('aria-activedescendant', getMatchId(index)); + } + }); + + var getMatchesAsync = function(inputValue) { + + var locals = {$viewValue: inputValue}; + isLoadingSetter(originalScope, true); + $q.when(parserResult.source(originalScope, locals)).then(function(matches) { + + //it might happen that several async queries were in progress if a user were typing fast + //but we are interested only in responses that correspond to the current view value + var onCurrentRequest = (inputValue === modelCtrl.$viewValue); + if (onCurrentRequest && hasFocus) { + if (matches && matches.length > 0) { + + scope.activeIdx = focusFirst ? 0 : -1; + scope.matches.length = 0; + + //transform labels + for(var i=0; i= minSearch) { + if (waitTime > 0) { + cancelPreviousTimeout(); + scheduleSearchWithTimeout(inputValue); + } else { + getMatchesAsync(inputValue); + } + } else { + isLoadingSetter(originalScope, false); + cancelPreviousTimeout(); + resetMatches(); + } + + if (isEditable) { + return inputValue; + } else { + if (!inputValue) { + // Reset in case user had typed something previously. + modelCtrl.$setValidity('editable', true); + return inputValue; + } else { + modelCtrl.$setValidity('editable', false); + return undefined; + } + } + }); + + modelCtrl.$formatters.push(function (modelValue) { + + var candidateViewValue, emptyViewValue; + var locals = {}; + + // The validity may be set to false via $parsers (see above) if + // the model is restricted to selected values. If the model + // is set manually it is considered to be valid. + if (!isEditable) { + modelCtrl.$setValidity('editable', true); + } + + if (inputFormatter) { + + locals.$model = modelValue; + return inputFormatter(originalScope, locals); + + } else { + + //it might happen that we don't have enough info to properly render input value + //we need to check for this situation and simply return model value if we can't apply custom formatting + locals[parserResult.itemName] = modelValue; + candidateViewValue = parserResult.viewMapper(originalScope, locals); + locals[parserResult.itemName] = undefined; + emptyViewValue = parserResult.viewMapper(originalScope, locals); + + return candidateViewValue!== emptyViewValue ? candidateViewValue : modelValue; + } + }); + + scope.select = function (activeIdx) { + //called from within the $digest() cycle + var locals = {}; + var model, item; + + locals[parserResult.itemName] = item = scope.matches[activeIdx].model; + model = parserResult.modelMapper(originalScope, locals); + $setModelValue(originalScope, model); + modelCtrl.$setValidity('editable', true); + modelCtrl.$setValidity('parse', true); + + onSelectCallback(originalScope, { + $item: item, + $model: model, + $label: parserResult.viewMapper(originalScope, locals) + }); + + resetMatches(); + + //return focus to the input element if a match was selected via a mouse click event + // use timeout to avoid $rootScope:inprog error + $timeout(function() { element[0].focus(); }, 0, false); + }; + + //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27) + element.bind('keydown', function (evt) { + + //typeahead is open and an "interesting" key was pressed + if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) { + return; + } + + // if there's nothing selected (i.e. focusFirst) and enter is hit, don't do anything + if (scope.activeIdx == -1 && (evt.which === 13 || evt.which === 9)) { + return; + } + + evt.preventDefault(); + + if (evt.which === 40) { + scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length; + scope.$digest(); + + } else if (evt.which === 38) { + scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1; + scope.$digest(); + + } else if (evt.which === 13 || evt.which === 9) { + scope.$apply(function () { + scope.select(scope.activeIdx); + }); + + } else if (evt.which === 27) { + evt.stopPropagation(); + + resetMatches(); + scope.$digest(); + } + }); + + element.bind('blur', function (evt) { + hasFocus = false; + }); + + // Keep reference to click handler to unbind it. + var dismissClickHandler = function (evt) { + if (element[0] !== evt.target) { + resetMatches(); + scope.$digest(); + } + }; + + $document.bind('click', dismissClickHandler); + + originalScope.$on('$destroy', function(){ + $document.unbind('click', dismissClickHandler); + if (appendToBody) { + $popup.remove(); + } + // Prevent jQuery cache memory leak + popUpEl.remove(); + }); + + var $popup = $compile(popUpEl)(scope); + + if (appendToBody) { + $document.find('body').append($popup); + } else { + element.after($popup); + } + } + }; + +}]) + + .directive('typeaheadPopup', function () { + return { + restrict:'EA', + scope:{ + matches:'=', + query:'=', + active:'=', + position:'=', + select:'&' + }, + replace:true, + templateUrl:'template/typeahead/typeahead-popup.html', + link:function (scope, element, attrs) { + + scope.templateUrl = attrs.templateUrl; + + scope.isOpen = function () { + return scope.matches.length > 0; + }; + + scope.isActive = function (matchIdx) { + return scope.active == matchIdx; + }; + + scope.selectActive = function (matchIdx) { + scope.active = matchIdx; + }; + + scope.selectMatch = function (activeIdx) { + scope.select({activeIdx:activeIdx}); + }; + } + }; + }) + + .directive('typeaheadMatch', ['$templateRequest', '$compile', '$parse', function ($templateRequest, $compile, $parse) { + return { + restrict:'EA', + scope:{ + index:'=', + match:'=', + query:'=' + }, + link:function (scope, element, attrs) { + var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'template/typeahead/typeahead-match.html'; + $templateRequest(tplUrl).then(function(tplContent) { + $compile(tplContent.trim())(scope, function(clonedElement){ + element.replaceWith(clonedElement); + }); + }); + } + }; + }]) + + .filter('typeaheadHighlight', function() { + + function escapeRegexp(queryToEscape) { + return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1'); + } + + return function(matchItem, query) { + return query ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : matchItem; + }; + }); +!angular.$$csp() && angular.element(document).find('head').prepend(''); \ No newline at end of file diff --git a/turtles/app/lib/bower_components/angular-bootstrap/ui-bootstrap.min.js b/turtles/app/lib/bower_components/angular-bootstrap/ui-bootstrap.min.js new file mode 100644 index 000000000..c3f5c2403 --- /dev/null +++ b/turtles/app/lib/bower_components/angular-bootstrap/ui-bootstrap.min.js @@ -0,0 +1,9 @@ +/* + * angular-ui-bootstrap + * http://angular-ui.github.io/bootstrap/ + + * Version: 0.13.0 - 2015-05-02 + * License: MIT + */ +angular.module("ui.bootstrap",["ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.transition","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.collapse",[]).directive("collapse",["$animate",function(a){return{link:function(b,c,d){function e(){c.removeClass("collapse").addClass("collapsing"),a.addClass(c,"in",{to:{height:c[0].scrollHeight+"px"}}).then(f)}function f(){c.removeClass("collapsing"),c.css({height:"auto"})}function g(){c.css({height:c[0].scrollHeight+"px"}).removeClass("collapse").addClass("collapsing"),a.removeClass(c,"in",{to:{height:"0"}}).then(h)}function h(){c.css({height:"0"}),c.removeClass("collapsing"),c.addClass("collapse")}b.$watch(d.collapse,function(a){a?g():e()})}}}]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("accordionConfig",{closeOthers:!0}).controller("AccordionController",["$scope","$attrs","accordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(b,1)}}]).directive("accordion",function(){return{restrict:"EA",controller:"AccordionController",transclude:!0,replace:!1,templateUrl:"template/accordion/accordion.html"}}).directive("accordionGroup",function(){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/accordion/accordion-group.html",scope:{heading:"@",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(a,b,c,d){d.addGroup(a),a.$watch("isOpen",function(b){b&&d.closeOthers(a)}),a.toggleOpen=function(){a.isDisabled||(a.isOpen=!a.isOpen)}}}}).directive("accordionHeading",function(){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",link:function(a,b,c,d,e){d.setHeading(e(a,angular.noop))}}}).directive("accordionTransclude",function(){return{require:"^accordionGroup",link:function(a,b,c,d){a.$watch(function(){return d[c.accordionTransclude]},function(a){a&&(b.html(""),b.append(a))})}}}),angular.module("ui.bootstrap.alert",[]).controller("AlertController",["$scope","$attrs",function(a,b){a.closeable="close"in b,this.close=a.close}]).directive("alert",function(){return{restrict:"EA",controller:"AlertController",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"@",close:"&"}}}).directive("dismissOnTimeout",["$timeout",function(a){return{require:"alert",link:function(b,c,d,e){a(function(){e.close()},parseInt(d.dismissOnTimeout,10))}}}]),angular.module("ui.bootstrap.bindHtml",[]).directive("bindHtmlUnsafe",function(){return function(a,b,c){b.addClass("ng-binding").data("$binding",c.bindHtmlUnsafe),a.$watch(c.bindHtmlUnsafe,function(a){b.html(a||"")})}}),angular.module("ui.bootstrap.buttons",[]).constant("buttonConfig",{activeClass:"active",toggleEvent:"click"}).controller("ButtonsController",["buttonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("btnRadio",function(){return{require:["btnRadio","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){var e=d[0],f=d[1];f.$render=function(){b.toggleClass(e.activeClass,angular.equals(f.$modelValue,a.$eval(c.btnRadio)))},b.bind(e.toggleEvent,function(){var d=b.hasClass(e.activeClass);(!d||angular.isDefined(c.uncheckable))&&a.$apply(function(){f.$setViewValue(d?null:a.$eval(c.btnRadio)),f.$render()})})}}}).directive("btnCheckbox",function(){return{require:["btnCheckbox","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){function e(){return g(c.btnCheckboxTrue,!0)}function f(){return g(c.btnCheckboxFalse,!1)}function g(b,c){var d=a.$eval(b);return angular.isDefined(d)?d:c}var h=d[0],i=d[1];i.$render=function(){b.toggleClass(h.activeClass,angular.equals(i.$modelValue,e()))},b.bind(h.toggleEvent,function(){a.$apply(function(){i.$setViewValue(b.hasClass(h.activeClass)?f():e()),i.$render()})})}}}),angular.module("ui.bootstrap.carousel",[]).controller("CarouselController",["$scope","$interval","$animate",function(a,b,c){function d(a){if(angular.isUndefined(k[a].index))return k[a];{var b;k.length}for(b=0;b0&&(h=b(g,c))}function f(){h&&(b.cancel(h),h=null)}function g(){var b=+a.interval;i&&!isNaN(b)&&b>0?a.next():a.pause()}var h,i,j=this,k=j.slides=a.slides=[],l=-1;j.currentSlide=null;var m=!1;j.select=a.select=function(b,d){function f(){m||(angular.extend(b,{direction:d,active:!0}),angular.extend(j.currentSlide||{},{direction:d,active:!1}),c.enabled()&&!a.noTransition&&b.$element&&(a.$currentTransition=!0,b.$element.one("$animate:close",function(){a.$currentTransition=null})),j.currentSlide=b,l=g,e())}var g=j.indexOfSlide(b);void 0===d&&(d=g>j.getCurrentIndex()?"next":"prev"),b&&b!==j.currentSlide&&f()},a.$on("$destroy",function(){m=!0}),j.getCurrentIndex=function(){return j.currentSlide&&angular.isDefined(j.currentSlide.index)?+j.currentSlide.index:l},j.indexOfSlide=function(a){return angular.isDefined(a.index)?+a.index:k.indexOf(a)},a.next=function(){var b=(j.getCurrentIndex()+1)%k.length;return a.$currentTransition?void 0:j.select(d(b),"next")},a.prev=function(){var b=j.getCurrentIndex()-1<0?k.length-1:j.getCurrentIndex()-1;return a.$currentTransition?void 0:j.select(d(b),"prev")},a.isActive=function(a){return j.currentSlide===a},a.$watch("interval",e),a.$on("$destroy",f),a.play=function(){i||(i=!0,e())},a.pause=function(){a.noPause||(i=!1,f())},j.addSlide=function(b,c){b.$element=c,k.push(b),1===k.length||b.active?(j.select(k[k.length-1]),1==k.length&&a.play()):b.active=!1},j.removeSlide=function(a){angular.isDefined(a.index)&&k.sort(function(a,b){return+a.index>+b.index});var b=k.indexOf(a);k.splice(b,1),k.length>0&&a.active?j.select(b>=k.length?k[b-1]:k[b]):l>b&&l--}}]).directive("carousel",[function(){return{restrict:"EA",transclude:!0,replace:!0,controller:"CarouselController",require:"carousel",templateUrl:"template/carousel/carousel.html",scope:{interval:"=",noTransition:"=",noPause:"="}}}]).directive("slide",function(){return{require:"^carousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/carousel/slide.html",scope:{active:"=?",index:"=?"},link:function(a,b,c,d){d.addSlide(a,b),a.$on("$destroy",function(){d.removeSlide(a)}),a.$watch("active",function(b){b&&d.select(a)})}}}).animation(".item",["$animate",function(a){return{beforeAddClass:function(b,c,d){if("active"==c&&b.parent()&&!b.parent().scope().noTransition){var e=!1,f=b.isolateScope().direction,g="next"==f?"left":"right";return b.addClass(f),a.addClass(b,g).then(function(){e||b.removeClass(g+" "+f),d()}),function(){e=!0}}d()},beforeRemoveClass:function(b,c,d){if("active"==c&&b.parent()&&!b.parent().scope().noTransition){var e=!1,f=b.isolateScope().direction,g="next"==f?"left":"right";return a.addClass(b,g).then(function(){e||b.removeClass(g),d()}),function(){e=!0}}d()}}}]),angular.module("ui.bootstrap.dateparser",[]).service("dateParser",["$locale","orderByFilter",function(a,b){function c(a){var c=[],d=a.split("");return angular.forEach(f,function(b,e){var f=a.indexOf(e);if(f>-1){a=a.split(""),d[f]="("+b.regex+")",a[f]="$";for(var g=f+1,h=f+e.length;h>g;g++)d[g]="",a[g]="$";a=a.join(""),c.push({index:f,apply:b.apply})}}),{regex:new RegExp("^"+d.join("")+"$"),map:b(c,"index")}}function d(a,b,c){return 1>c?!1:1===b&&c>28?29===c&&(a%4===0&&a%100!==0||a%400===0):3===b||5===b||8===b||10===b?31>c:!0}var e=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;this.parsers={};var f={yyyy:{regex:"\\d{4}",apply:function(a){this.year=+a}},yy:{regex:"\\d{2}",apply:function(a){this.year=+a+2e3}},y:{regex:"\\d{1,4}",apply:function(a){this.year=+a}},MMMM:{regex:a.DATETIME_FORMATS.MONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.MONTH.indexOf(b)}},MMM:{regex:a.DATETIME_FORMATS.SHORTMONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.SHORTMONTH.indexOf(b)}},MM:{regex:"0[1-9]|1[0-2]",apply:function(a){this.month=a-1}},M:{regex:"[1-9]|1[0-2]",apply:function(a){this.month=a-1}},dd:{regex:"[0-2][0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},d:{regex:"[1-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},EEEE:{regex:a.DATETIME_FORMATS.DAY.join("|")},EEE:{regex:a.DATETIME_FORMATS.SHORTDAY.join("|")},HH:{regex:"(?:0|1)[0-9]|2[0-3]",apply:function(a){this.hours=+a}},H:{regex:"1?[0-9]|2[0-3]",apply:function(a){this.hours=+a}},mm:{regex:"[0-5][0-9]",apply:function(a){this.minutes=+a}},m:{regex:"[0-9]|[1-5][0-9]",apply:function(a){this.minutes=+a}},sss:{regex:"[0-9][0-9][0-9]",apply:function(a){this.milliseconds=+a}},ss:{regex:"[0-5][0-9]",apply:function(a){this.seconds=+a}},s:{regex:"[0-9]|[1-5][0-9]",apply:function(a){this.seconds=+a}}};this.parse=function(b,f,g){if(!angular.isString(b)||!f)return b;f=a.DATETIME_FORMATS[f]||f,f=f.replace(e,"\\$&"),this.parsers[f]||(this.parsers[f]=c(f));var h=this.parsers[f],i=h.regex,j=h.map,k=b.match(i);if(k&&k.length){var l,m;l=g?{year:g.getFullYear(),month:g.getMonth(),date:g.getDate(),hours:g.getHours(),minutes:g.getMinutes(),seconds:g.getSeconds(),milliseconds:g.getMilliseconds()}:{year:1900,month:0,date:1,hours:0,minutes:0,seconds:0,milliseconds:0};for(var n=1,o=k.length;o>n;n++){var p=j[n-1];p.apply&&p.apply.call(l,k[n])}return d(l.year,l.month,l.date)&&(m=new Date(l.year,l.month,l.date,l.hours,l.minutes,l.seconds,l.milliseconds||0)),m}}}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(a,b){function c(a,c){return a.currentStyle?a.currentStyle[c]:b.getComputedStyle?b.getComputedStyle(a)[c]:a.style[c]}function d(a){return"static"===(c(a,"position")||"static")}var e=function(b){for(var c=a[0],e=b.offsetParent||c;e&&e!==c&&d(e);)e=e.offsetParent;return e||c};return{position:function(b){var c=this.offset(b),d={top:0,left:0},f=e(b[0]);f!=a[0]&&(d=this.offset(angular.element(f)),d.top+=f.clientTop-f.scrollTop,d.left+=f.clientLeft-f.scrollLeft);var g=b[0].getBoundingClientRect();return{width:g.width||b.prop("offsetWidth"),height:g.height||b.prop("offsetHeight"),top:c.top-d.top,left:c.left-d.left}},offset:function(c){var d=c[0].getBoundingClientRect();return{width:d.width||c.prop("offsetWidth"),height:d.height||c.prop("offsetHeight"),top:d.top+(b.pageYOffset||a[0].documentElement.scrollTop),left:d.left+(b.pageXOffset||a[0].documentElement.scrollLeft)}},positionElements:function(a,b,c,d){var e,f,g,h,i=c.split("-"),j=i[0],k=i[1]||"center";e=d?this.offset(a):this.position(a),f=b.prop("offsetWidth"),g=b.prop("offsetHeight");var l={center:function(){return e.left+e.width/2-f/2},left:function(){return e.left},right:function(){return e.left+e.width}},m={center:function(){return e.top+e.height/2-g/2},top:function(){return e.top},bottom:function(){return e.top+e.height}};switch(j){case"right":h={top:m[k](),left:l[j]()};break;case"left":h={top:m[k](),left:e.left-f};break;case"bottom":h={top:m[j](),left:l[k]()};break;default:h={top:e.top-g,left:l[k]()}}return h}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.dateparser","ui.bootstrap.position"]).constant("datepickerConfig",{formatDay:"dd",formatMonth:"MMMM",formatYear:"yyyy",formatDayHeader:"EEE",formatDayTitle:"MMMM yyyy",formatMonthTitle:"yyyy",datepickerMode:"day",minMode:"day",maxMode:"year",showWeeks:!0,startingDay:0,yearRange:20,minDate:null,maxDate:null,shortcutPropagation:!1}).controller("DatepickerController",["$scope","$attrs","$parse","$interpolate","$timeout","$log","dateFilter","datepickerConfig",function(a,b,c,d,e,f,g,h){var i=this,j={$setViewValue:angular.noop};this.modes=["day","month","year"],angular.forEach(["formatDay","formatMonth","formatYear","formatDayHeader","formatDayTitle","formatMonthTitle","minMode","maxMode","showWeeks","startingDay","yearRange","shortcutPropagation"],function(c,e){i[c]=angular.isDefined(b[c])?8>e?d(b[c])(a.$parent):a.$parent.$eval(b[c]):h[c]}),angular.forEach(["minDate","maxDate"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(a){i[d]=a?new Date(a):null,i.refreshView()}):i[d]=h[d]?new Date(h[d]):null}),a.datepickerMode=a.datepickerMode||h.datepickerMode,a.maxMode=i.maxMode,a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),angular.isDefined(b.initDate)?(this.activeDate=a.$parent.$eval(b.initDate)||new Date,a.$parent.$watch(b.initDate,function(a){a&&(j.$isEmpty(j.$modelValue)||j.$invalid)&&(i.activeDate=a,i.refreshView())})):this.activeDate=new Date,a.isActive=function(b){return 0===i.compare(b.date,i.activeDate)?(a.activeDateId=b.uid,!0):!1},this.init=function(a){j=a,j.$render=function(){i.render()}},this.render=function(){if(j.$viewValue){var a=new Date(j.$viewValue),b=!isNaN(a);b?this.activeDate=a:f.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'),j.$setValidity("date",b)}this.refreshView()},this.refreshView=function(){if(this.element){this._refreshView();var a=j.$viewValue?new Date(j.$viewValue):null;j.$setValidity("date-disabled",!a||this.element&&!this.isDisabled(a))}},this.createDateObject=function(a,b){var c=j.$viewValue?new Date(j.$viewValue):null;return{date:a,label:g(a,b),selected:c&&0===this.compare(a,c),disabled:this.isDisabled(a),current:0===this.compare(a,new Date),customClass:this.customClass(a)}},this.isDisabled=function(c){return this.minDate&&this.compare(c,this.minDate)<0||this.maxDate&&this.compare(c,this.maxDate)>0||b.dateDisabled&&a.dateDisabled({date:c,mode:a.datepickerMode})},this.customClass=function(b){return a.customClass({date:b,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},a.select=function(b){if(a.datepickerMode===i.minMode){var c=j.$viewValue?new Date(j.$viewValue):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),j.$setViewValue(c),j.$render()}else i.activeDate=b,a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)-1]},a.move=function(a){var b=i.activeDate.getFullYear()+a*(i.step.years||0),c=i.activeDate.getMonth()+a*(i.step.months||0);i.activeDate.setFullYear(b,c,1),i.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===i.maxMode&&1===b||a.datepickerMode===i.minMode&&-1===b||(a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)+b])},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var k=function(){e(function(){i.element[0].focus()},0,!1)};a.$on("datepicker.focus",k),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey)if(b.preventDefault(),i.shortcutPropagation||b.stopPropagation(),"enter"===c||"space"===c){if(i.isDisabled(i.activeDate))return;a.select(i.activeDate),k()}else!b.ctrlKey||"up"!==c&&"down"!==c?(i.handleKeyDown(c,b),i.refreshView()):(a.toggleMode("up"===c?1:-1),k())}}]).directive("datepicker",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/datepicker.html",scope:{datepickerMode:"=?",dateDisabled:"&",customClass:"&",shortcutPropagation:"&?"},require:["datepicker","?^ngModel"],controller:"DatepickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f)}}}).directive("daypicker",["dateFilter",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/day.html",require:"^datepicker",link:function(b,c,d,e){function f(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?i[b]:29}function g(a,b){var c=new Array(b),d=new Date(a),e=0;for(d.setHours(12);b>e;)c[e++]=new Date(d),d.setDate(d.getDate()+1);return c}function h(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}b.showWeeks=e.showWeeks,e.step={months:1},e.element=c;var i=[31,28,31,30,31,30,31,31,30,31,30,31];e._refreshView=function(){var c=e.activeDate.getFullYear(),d=e.activeDate.getMonth(),f=new Date(c,d,1),i=e.startingDay-f.getDay(),j=i>0?7-i:-i,k=new Date(f);j>0&&k.setDate(-j+1);for(var l=g(k,42),m=0;42>m;m++)l[m]=angular.extend(e.createDateObject(l[m],e.formatDay),{secondary:l[m].getMonth()!==d,uid:b.uniqueId+"-"+m});b.labels=new Array(7);for(var n=0;7>n;n++)b.labels[n]={abbr:a(l[n].date,e.formatDayHeader),full:a(l[n].date,"EEEE")};if(b.title=a(e.activeDate,e.formatDayTitle),b.rows=e.split(l,7),b.showWeeks){b.weekNumbers=[];for(var o=(11-e.startingDay)%7,p=b.rows.length,q=0;p>q;q++)b.weekNumbers.push(h(b.rows[q][o].date))}},e.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth(),a.getDate())-new Date(b.getFullYear(),b.getMonth(),b.getDate())},e.handleKeyDown=function(a){var b=e.activeDate.getDate();if("left"===a)b-=1;else if("up"===a)b-=7;else if("right"===a)b+=1;else if("down"===a)b+=7;else if("pageup"===a||"pagedown"===a){var c=e.activeDate.getMonth()+("pageup"===a?-1:1);e.activeDate.setMonth(c,1),b=Math.min(f(e.activeDate.getFullYear(),e.activeDate.getMonth()),b)}else"home"===a?b=1:"end"===a&&(b=f(e.activeDate.getFullYear(),e.activeDate.getMonth()));e.activeDate.setDate(b)},e.refreshView()}}}]).directive("monthpicker",["dateFilter",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/month.html",require:"^datepicker",link:function(b,c,d,e){e.step={years:1},e.element=c,e._refreshView=function(){for(var c=new Array(12),d=e.activeDate.getFullYear(),f=0;12>f;f++)c[f]=angular.extend(e.createDateObject(new Date(d,f,1),e.formatMonth),{uid:b.uniqueId+"-"+f});b.title=a(e.activeDate,e.formatMonthTitle),b.rows=e.split(c,3)},e.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth())-new Date(b.getFullYear(),b.getMonth())},e.handleKeyDown=function(a){var b=e.activeDate.getMonth();if("left"===a)b-=1;else if("up"===a)b-=3;else if("right"===a)b+=1;else if("down"===a)b+=3;else if("pageup"===a||"pagedown"===a){var c=e.activeDate.getFullYear()+("pageup"===a?-1:1);e.activeDate.setFullYear(c)}else"home"===a?b=0:"end"===a&&(b=11);e.activeDate.setMonth(b)},e.refreshView()}}}]).directive("yearpicker",["dateFilter",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/year.html",require:"^datepicker",link:function(a,b,c,d){function e(a){return parseInt((a-1)/f,10)*f+1}var f=d.yearRange;d.step={years:f},d.element=b,d._refreshView=function(){for(var b=new Array(f),c=0,g=e(d.activeDate.getFullYear());f>c;c++)b[c]=angular.extend(d.createDateObject(new Date(g+c,0,1),d.formatYear),{uid:a.uniqueId+"-"+c});a.title=[b[0].label,b[f-1].label].join(" - "),a.rows=d.split(b,5)},d.compare=function(a,b){return a.getFullYear()-b.getFullYear()},d.handleKeyDown=function(a){var b=d.activeDate.getFullYear();"left"===a?b-=1:"up"===a?b-=5:"right"===a?b+=1:"down"===a?b+=5:"pageup"===a||"pagedown"===a?b+=("pageup"===a?-1:1)*d.step.years:"home"===a?b=e(d.activeDate.getFullYear()):"end"===a&&(b=e(d.activeDate.getFullYear())+f-1),d.activeDate.setFullYear(b)},d.refreshView()}}}]).constant("datepickerPopupConfig",{datepickerPopup:"yyyy-MM-dd",html5Types:{date:"yyyy-MM-dd","datetime-local":"yyyy-MM-ddTHH:mm:ss.sss",month:"yyyy-MM"},currentText:"Today",clearText:"Clear",closeText:"Done",closeOnDateSelection:!0,appendToBody:!1,showButtonBar:!0}).directive("datepickerPopup",["$compile","$parse","$document","$position","dateFilter","dateParser","datepickerPopupConfig",function(a,b,c,d,e,f,g){return{restrict:"EA",require:"ngModel",scope:{isOpen:"=?",currentText:"@",clearText:"@",closeText:"@",dateDisabled:"&",customClass:"&"},link:function(h,i,j,k){function l(a){return a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})}function m(a){if(angular.isNumber(a)&&(a=new Date(a)),a){if(angular.isDate(a)&&!isNaN(a))return a;if(angular.isString(a)){var b=f.parse(a,o,h.date)||new Date(a);return isNaN(b)?void 0:b}return void 0}return null}function n(a,b){var c=a||b;if(angular.isNumber(c)&&(c=new Date(c)),c){if(angular.isDate(c)&&!isNaN(c))return!0;if(angular.isString(c)){var d=f.parse(c,o)||new Date(c);return!isNaN(d)}return!1}return!0}var o,p=angular.isDefined(j.closeOnDateSelection)?h.$parent.$eval(j.closeOnDateSelection):g.closeOnDateSelection,q=angular.isDefined(j.datepickerAppendToBody)?h.$parent.$eval(j.datepickerAppendToBody):g.appendToBody;h.showButtonBar=angular.isDefined(j.showButtonBar)?h.$parent.$eval(j.showButtonBar):g.showButtonBar,h.getText=function(a){return h[a+"Text"]||g[a+"Text"]};var r=!1;if(g.html5Types[j.type]?(o=g.html5Types[j.type],r=!0):(o=j.datepickerPopup||g.datepickerPopup,j.$observe("datepickerPopup",function(a){var b=a||g.datepickerPopup;if(b!==o&&(o=b,k.$modelValue=null,!o))throw new Error("datepickerPopup must have a date format specified.")})),!o)throw new Error("datepickerPopup must have a date format specified.");if(r&&j.datepickerPopup)throw new Error("HTML5 date input types do not support custom formats.");var s=angular.element("
      ");s.attr({"ng-model":"date","ng-change":"dateSelection()"});var t=angular.element(s.children()[0]);if(r&&"month"==j.type&&(t.attr("datepicker-mode",'"month"'),t.attr("min-mode","month")),j.datepickerOptions){var u=h.$parent.$eval(j.datepickerOptions);u.initDate&&(h.initDate=u.initDate,t.attr("init-date","initDate"),delete u.initDate),angular.forEach(u,function(a,b){t.attr(l(b),a)})}h.watchData={},angular.forEach(["minDate","maxDate","datepickerMode","initDate","shortcutPropagation"],function(a){if(j[a]){var c=b(j[a]);if(h.$parent.$watch(c,function(b){h.watchData[a]=b}),t.attr(l(a),"watchData."+a),"datepickerMode"===a){var d=c.assign;h.$watch("watchData."+a,function(a,b){a!==b&&d(h.$parent,a)})}}}),j.dateDisabled&&t.attr("date-disabled","dateDisabled({ date: date, mode: mode })"),j.showWeeks&&t.attr("show-weeks",j.showWeeks),j.customClass&&t.attr("custom-class","customClass({ date: date, mode: mode })"),r?k.$formatters.push(function(a){return h.date=a,a}):(k.$$parserName="date",k.$validators.date=n,k.$parsers.unshift(m),k.$formatters.push(function(a){return h.date=a,k.$isEmpty(a)?a:e(a,o)})),h.dateSelection=function(a){angular.isDefined(a)&&(h.date=a);var b=h.date?e(h.date,o):"";i.val(b),k.$setViewValue(b),p&&(h.isOpen=!1,i[0].focus())},k.$viewChangeListeners.push(function(){h.date=f.parse(k.$viewValue,o,h.date)||new Date(k.$viewValue)});var v=function(a){h.isOpen&&a.target!==i[0]&&h.$apply(function(){h.isOpen=!1})},w=function(a){h.keydown(a)};i.bind("keydown",w),h.keydown=function(a){27===a.which?(a.preventDefault(),h.isOpen&&a.stopPropagation(),h.close()):40!==a.which||h.isOpen||(h.isOpen=!0)},h.$watch("isOpen",function(a){a?(h.$broadcast("datepicker.focus"),h.position=q?d.offset(i):d.position(i),h.position.top=h.position.top+i.prop("offsetHeight"),c.bind("click",v)):c.unbind("click",v)}),h.select=function(a){if("today"===a){var b=new Date;angular.isDate(h.date)?(a=new Date(h.date),a.setFullYear(b.getFullYear(),b.getMonth(),b.getDate())):a=new Date(b.setHours(0,0,0,0))}h.dateSelection(a)},h.close=function(){h.isOpen=!1,i[0].focus()};var x=a(s)(h);s.remove(),q?c.find("body").append(x):i.after(x),h.$on("$destroy",function(){x.remove(),i.unbind("keydown",w),c.unbind("click",v)})}}}]).directive("datepickerPopupWrap",function(){return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"template/datepicker/popup.html",link:function(a,b){b.bind("click",function(a){a.preventDefault(),a.stopPropagation()})}}}),angular.module("ui.bootstrap.dropdown",["ui.bootstrap.position"]).constant("dropdownConfig",{openClass:"open"}).service("dropdownService",["$document","$rootScope",function(a,b){var c=null;this.open=function(b){c||(a.bind("click",d),a.bind("keydown",e)),c&&c!==b&&(c.isOpen=!1),c=b},this.close=function(b){c===b&&(c=null,a.unbind("click",d),a.unbind("keydown",e))};var d=function(a){if(c&&(!a||"disabled"!==c.getAutoClose())){var d=c.getToggleElement();if(!(a&&d&&d[0].contains(a.target))){var e=c.getElement();a&&"outsideClick"===c.getAutoClose()&&e&&e[0].contains(a.target)||(c.isOpen=!1,b.$$phase||c.$apply())}}},e=function(a){27===a.which&&(c.focusToggleElement(),d())}}]).controller("DropdownController",["$scope","$attrs","$parse","dropdownConfig","dropdownService","$animate","$position","$document",function(a,b,c,d,e,f,g,h){var i,j=this,k=a.$new(),l=d.openClass,m=angular.noop,n=b.onToggle?c(b.onToggle):angular.noop,o=!1;this.init=function(d){j.$element=d,b.isOpen&&(i=c(b.isOpen),m=i.assign,a.$watch(i,function(a){k.isOpen=!!a})),o=angular.isDefined(b.dropdownAppendToBody),o&&j.dropdownMenu&&(h.find("body").append(j.dropdownMenu),d.on("$destroy",function(){j.dropdownMenu.remove()}))},this.toggle=function(a){return k.isOpen=arguments.length?!!a:!k.isOpen},this.isOpen=function(){return k.isOpen},k.getToggleElement=function(){return j.toggleElement},k.getAutoClose=function(){return b.autoClose||"always"},k.getElement=function(){return j.$element},k.focusToggleElement=function(){j.toggleElement&&j.toggleElement[0].focus()},k.$watch("isOpen",function(b,c){if(o&&j.dropdownMenu){var d=g.positionElements(j.$element,j.dropdownMenu,"bottom-left",!0);j.dropdownMenu.css({top:d.top+"px",left:d.left+"px",display:b?"block":"none"})}f[b?"addClass":"removeClass"](j.$element,l),b?(k.focusToggleElement(),e.open(k)):e.close(k),m(a,b),angular.isDefined(b)&&b!==c&&n(a,{open:!!b})}),a.$on("$locationChangeSuccess",function(){k.isOpen=!1}),a.$on("$destroy",function(){k.$destroy()})}]).directive("dropdown",function(){return{controller:"DropdownController",link:function(a,b,c,d){d.init(b)}}}).directive("dropdownMenu",function(){return{restrict:"AC",require:"?^dropdown",link:function(a,b,c,d){d&&(d.dropdownMenu=b)}}}).directive("dropdownToggle",function(){return{require:"?^dropdown",link:function(a,b,c,d){if(d){d.toggleElement=b;var e=function(e){e.preventDefault(),b.hasClass("disabled")||c.disabled||a.$apply(function(){d.toggle()})};b.bind("click",e),b.attr({"aria-haspopup":!0,"aria-expanded":!1}),a.$watch(d.isOpen,function(a){b.attr("aria-expanded",!!a)}),a.$on("$destroy",function(){b.unbind("click",e)})}}}}),angular.module("ui.bootstrap.modal",[]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c0),i()})}function i(){if(l&&-1==g()){var a=m;j(l,m,function(){a=null}),l=void 0,m=void 0}}function j(c,d,f){function g(){g.done||(g.done=!0,c.remove(),d.$destroy(),f&&f())}d.animate=!1,c.attr("modal-animation")&&a.enabled()?c.one("$animate:close",function(){e.$evalAsync(g)}):b(g)}function k(a,b,c){return!a.value.modalScope.$broadcast("modal.closing",b,c).defaultPrevented}var l,m,n="modal-open",o=f.createNew(),p={};return e.$watch(g,function(a){m&&(m.index=a)}),c.bind("keydown",function(a){var b;27===a.which&&(b=o.top(),b&&b.value.keyboard&&(a.preventDefault(),e.$apply(function(){p.dismiss(b.key,"escape key press")})))}),p.open=function(a,b){var f=c[0].activeElement;o.add(a,{deferred:b.deferred,renderDeferred:b.renderDeferred,modalScope:b.scope,backdrop:b.backdrop,keyboard:b.keyboard});var h=c.find("body").eq(0),i=g();if(i>=0&&!l){m=e.$new(!0),m.index=i;var j=angular.element('
      ');j.attr("backdrop-class",b.backdropClass),b.animation&&j.attr("modal-animation","true"),l=d(j)(m),h.append(l)}var k=angular.element('
      ');k.attr({"template-url":b.windowTemplateUrl,"window-class":b.windowClass,size:b.size,index:o.length()-1,animate:"animate"}).html(b.content),b.animation&&k.attr("modal-animation","true");var p=d(k)(b.scope);o.top().value.modalDomEl=p,o.top().value.modalOpener=f,h.append(p),h.addClass(n)},p.close=function(a,b){var c=o.get(a);return c&&k(c,b,!0)?(c.value.deferred.resolve(b),h(a),c.value.modalOpener.focus(),!0):!c},p.dismiss=function(a,b){var c=o.get(a);return c&&k(c,b,!1)?(c.value.deferred.reject(b),h(a),c.value.modalOpener.focus(),!0):!c},p.dismissAll=function(a){for(var b=this.getTop();b&&this.dismiss(b.key,a);)b=this.getTop()},p.getTop=function(){return o.top()},p.modalRendered=function(a){var b=o.get(a);b&&b.value.renderDeferred.resolve()},p}]).provider("$modal",function(){var a={options:{animation:!0,backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$templateRequest","$controller","$modalStack",function(b,c,d,e,f,g){function h(a){return a.template?d.when(a.template):e(angular.isFunction(a.templateUrl)?a.templateUrl():a.templateUrl)}function i(a){var c=[];return angular.forEach(a,function(a){(angular.isFunction(a)||angular.isArray(a))&&c.push(d.when(b.invoke(a)))}),c}var j={};return j.open=function(b){var e=d.defer(),j=d.defer(),k=d.defer(),l={result:e.promise,opened:j.promise,rendered:k.promise,close:function(a){return g.close(l,a)},dismiss:function(a){return g.dismiss(l,a)}};if(b=angular.extend({},a.options,b),b.resolve=b.resolve||{},!b.template&&!b.templateUrl)throw new Error("One of template or templateUrl options is required.");var m=d.all([h(b)].concat(i(b.resolve)));return m.then(function(a){var d=(b.scope||c).$new();d.$close=l.close,d.$dismiss=l.dismiss;var h,i={},j=1;b.controller&&(i.$scope=d,i.$modalInstance=l,angular.forEach(b.resolve,function(b,c){i[c]=a[j++]}),h=f(b.controller,i),b.controllerAs&&(d[b.controllerAs]=h)),g.open(l,{scope:d,deferred:e,renderDeferred:k,content:a[0],animation:b.animation,backdrop:b.backdrop,keyboard:b.keyboard,backdropClass:b.backdropClass,windowClass:b.windowClass,windowTemplateUrl:b.windowTemplateUrl,size:b.size})},function(a){e.reject(a)}),m.then(function(){j.resolve(!0)},function(a){j.reject(a)}),l},j}]};return a}),angular.module("ui.bootstrap.pagination",[]).controller("PaginationController",["$scope","$attrs","$parse",function(a,b,c){var d=this,e={$setViewValue:angular.noop},f=b.numPages?c(b.numPages).assign:angular.noop; +this.init=function(g,h){e=g,this.config=h,e.$render=function(){d.render()},b.itemsPerPage?a.$parent.$watch(c(b.itemsPerPage),function(b){d.itemsPerPage=parseInt(b,10),a.totalPages=d.calculateTotalPages()}):this.itemsPerPage=h.itemsPerPage,a.$watch("totalItems",function(){a.totalPages=d.calculateTotalPages()}),a.$watch("totalPages",function(b){f(a.$parent,b),a.page>b?a.selectPage(b):e.$render()})},this.calculateTotalPages=function(){var b=this.itemsPerPage<1?1:Math.ceil(a.totalItems/this.itemsPerPage);return Math.max(b||0,1)},this.render=function(){a.page=parseInt(e.$viewValue,10)||1},a.selectPage=function(b,c){a.page!==b&&b>0&&b<=a.totalPages&&(c&&c.target&&c.target.blur(),e.$setViewValue(b),e.$render())},a.getText=function(b){return a[b+"Text"]||d.config[b+"Text"]},a.noPrevious=function(){return 1===a.page},a.noNext=function(){return a.page===a.totalPages}}]).constant("paginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("pagination",["$parse","paginationConfig",function(a,b){return{restrict:"EA",scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@"},require:["pagination","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pagination.html",replace:!0,link:function(c,d,e,f){function g(a,b,c){return{number:a,text:b,active:c}}function h(a,b){var c=[],d=1,e=b,f=angular.isDefined(k)&&b>k;f&&(l?(d=Math.max(a-Math.floor(k/2),1),e=d+k-1,e>b&&(e=b,d=e-k+1)):(d=(Math.ceil(a/k)-1)*k+1,e=Math.min(d+k-1,b)));for(var h=d;e>=h;h++){var i=g(h,h,h===a);c.push(i)}if(f&&!l){if(d>1){var j=g(d-1,"...",!1);c.unshift(j)}if(b>e){var m=g(e+1,"...",!1);c.push(m)}}return c}var i=f[0],j=f[1];if(j){var k=angular.isDefined(e.maxSize)?c.$parent.$eval(e.maxSize):b.maxSize,l=angular.isDefined(e.rotate)?c.$parent.$eval(e.rotate):b.rotate;c.boundaryLinks=angular.isDefined(e.boundaryLinks)?c.$parent.$eval(e.boundaryLinks):b.boundaryLinks,c.directionLinks=angular.isDefined(e.directionLinks)?c.$parent.$eval(e.directionLinks):b.directionLinks,i.init(j,b),e.maxSize&&c.$parent.$watch(a(e.maxSize),function(a){k=parseInt(a,10),i.render()});var m=i.render;i.render=function(){m(),c.page>0&&c.page<=c.totalPages&&(c.pages=h(c.page,c.totalPages))}}}}}]).constant("pagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("pager",["pagerConfig",function(a){return{restrict:"EA",scope:{totalItems:"=",previousText:"@",nextText:"@"},require:["pager","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pager.html",replace:!0,link:function(b,c,d,e){var f=e[0],g=e[1];g&&(b.align=angular.isDefined(d.align)?b.$parent.$eval(d.align):a.align,f.init(g,a))}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).provider("$tooltip",function(){function a(a){var b=/[A-Z]/g,c="-";return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var b={placement:"top",animation:!0,popupDelay:0,useContentExp:!1},c={mouseenter:"mouseleave",click:"click",focus:"blur"},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$document","$position","$interpolate",function(e,f,g,h,i,j){return function(e,k,l,m){function n(a){var b=a||m.trigger||l,d=c[b]||b;return{show:b,hide:d}}m=angular.extend({},b,d,m);var o=a(e),p=j.startSymbol(),q=j.endSymbol(),r="
      ';return{restrict:"EA",compile:function(){var a=f(r);return function(b,c,d){function f(){E.isOpen?l():j()}function j(){(!D||b.$eval(d[k+"Enable"]))&&(s(),E.popupDelay?A||(A=g(o,E.popupDelay,!1),A.then(function(a){a()})):o()())}function l(){b.$apply(function(){p()})}function o(){return A=null,z&&(g.cancel(z),z=null),(m.useContentExp?E.contentExp():E.content)?(q(),x.css({top:0,left:0,display:"block"}),E.$digest(),F(),E.isOpen=!0,E.$apply(),F):angular.noop}function p(){E.isOpen=!1,g.cancel(A),A=null,E.animation?z||(z=g(r,500)):r()}function q(){x&&r(),y=E.$new(),x=a(y,function(a){B?h.find("body").append(a):c.after(a)}),y.$watch(function(){g(F,0,!1)}),m.useContentExp&&y.$watch("contentExp()",function(a){!a&&E.isOpen&&p()})}function r(){z=null,x&&(x.remove(),x=null),y&&(y.$destroy(),y=null)}function s(){t(),u(),v()}function t(){E.popupClass=d[k+"Class"]}function u(){var a=d[k+"Placement"];E.placement=angular.isDefined(a)?a:m.placement}function v(){var a=d[k+"PopupDelay"],b=parseInt(a,10);E.popupDelay=isNaN(b)?m.popupDelay:b}function w(){var a=d[k+"Trigger"];G(),C=n(a),C.show===C.hide?c.bind(C.show,f):(c.bind(C.show,j),c.bind(C.hide,l))}var x,y,z,A,B=angular.isDefined(m.appendToBody)?m.appendToBody:!1,C=n(void 0),D=angular.isDefined(d[k+"Enable"]),E=b.$new(!0),F=function(){if(x){var a=i.positionElements(c,x,E.placement,B);a.top+="px",a.left+="px",x.css(a)}};E.origScope=b,E.isOpen=!1,E.contentExp=function(){return b.$eval(d[e])},m.useContentExp||d.$observe(e,function(a){E.content=a,!a&&E.isOpen&&p()}),d.$observe("disabled",function(a){a&&E.isOpen&&p()}),d.$observe(k+"Title",function(a){E.title=a});var G=function(){c.unbind(C.show,j),c.unbind(C.hide,l)};w();var H=b.$eval(d[k+"Animation"]);E.animation=angular.isDefined(H)?!!H:m.animation;var I=b.$eval(d[k+"AppendToBody"]);B=angular.isDefined(I)?I:B,B&&b.$on("$locationChangeSuccess",function(){E.isOpen&&p()}),b.$on("$destroy",function(){g.cancel(z),g.cancel(A),G(),r(),E=null})}}}}}]}).directive("tooltipTemplateTransclude",["$animate","$sce","$compile","$templateRequest",function(a,b,c,d){return{link:function(e,f,g){var h,i,j,k=e.$eval(g.tooltipTemplateTranscludeScope),l=0,m=function(){i&&(i.remove(),i=null),h&&(h.$destroy(),h=null),j&&(a.leave(j).then(function(){i=null}),i=j,j=null)};e.$watch(b.parseAsResourceUrl(g.tooltipTemplateTransclude),function(b){var g=++l;b?(d(b,!0).then(function(d){if(g===l){var e=k.$new(),i=d,n=c(i)(e,function(b){m(),a.enter(b,f)});h=e,j=n,h.$emit("$includeContentLoaded",b)}},function(){g===l&&(m(),e.$emit("$includeContentError",b))}),e.$emit("$includeContentRequested",b)):m()}),e.$on("$destroy",m)}}}]).directive("tooltipClasses",function(){return{restrict:"A",link:function(a,b,c){a.placement&&b.addClass(a.placement),a.popupClass&&b.addClass(a.popupClass),a.animation()&&b.addClass(c.tooltipAnimationClass)}}}).directive("tooltipPopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$tooltip",function(a){return a("tooltip","tooltip","mouseenter")}]).directive("tooltipTemplatePopup",function(){return{restrict:"EA",replace:!0,scope:{contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&",originScope:"&"},templateUrl:"template/tooltip/tooltip-template-popup.html"}}).directive("tooltipTemplate",["$tooltip",function(a){return a("tooltipTemplate","tooltip","mouseenter",{useContentExp:!0})}]).directive("tooltipHtmlPopup",function(){return{restrict:"EA",replace:!0,scope:{contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-popup.html"}}).directive("tooltipHtml",["$tooltip",function(a){return a("tooltipHtml","tooltip","mouseenter",{useContentExp:!0})}]).directive("tooltipHtmlUnsafePopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-unsafe-popup.html"}}).value("tooltipHtmlUnsafeSuppressDeprecated",!1).directive("tooltipHtmlUnsafe",["$tooltip","tooltipHtmlUnsafeSuppressDeprecated","$log",function(a,b,c){return b||c.warn("tooltip-html-unsafe is now deprecated. Use tooltip-html or tooltip-template instead."),a("tooltipHtmlUnsafe","tooltip","mouseenter")}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("popoverTemplatePopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&",originScope:"&"},templateUrl:"template/popover/popover-template.html"}}).directive("popoverTemplate",["$tooltip",function(a){return a("popoverTemplate","popover","click",{useContentExp:!0})}]).directive("popoverPopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html"}}).directive("popover",["$tooltip",function(a){return a("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",[]).constant("progressConfig",{animate:!0,max:100}).controller("ProgressController",["$scope","$attrs","progressConfig",function(a,b,c){var d=this,e=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=angular.isDefined(a.max)?a.max:c.max,this.addBar=function(b,c){e||c.css({transition:"none"}),this.bars.push(b),b.$watch("value",function(c){b.percent=+(100*c/a.max).toFixed(2)}),b.$on("$destroy",function(){c=null,d.removeBar(b)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1)}}]).directive("progress",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",require:"progress",scope:{},templateUrl:"template/progressbar/progress.html"}}).directive("bar",function(){return{restrict:"EA",replace:!0,transclude:!0,require:"^progress",scope:{value:"=",max:"=?",type:"@"},templateUrl:"template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b)}}}).directive("progressbar",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",scope:{value:"=",max:"=?",type:"@"},templateUrl:"template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]))}}}),angular.module("ui.bootstrap.rating",[]).constant("ratingConfig",{max:5,stateOn:null,stateOff:null}).controller("RatingController",["$scope","$attrs","ratingConfig",function(a,b,c){var d={$setViewValue:angular.noop};this.init=function(e){d=e,d.$render=this.render,d.$formatters.push(function(a){return angular.isNumber(a)&&a<<0!==a&&(a=Math.round(a)),a}),this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):c.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):c.stateOff;var f=angular.isDefined(b.ratingStates)?a.$parent.$eval(b.ratingStates):new Array(angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max);a.range=this.buildTemplateObjects(f)},this.buildTemplateObjects=function(a){for(var b=0,c=a.length;c>b;b++)a[b]=angular.extend({index:b},{stateOn:this.stateOn,stateOff:this.stateOff},a[b]);return a},a.rate=function(b){!a.readonly&&b>=0&&b<=a.range.length&&(d.$setViewValue(b),d.$render())},a.enter=function(b){a.readonly||(a.value=b),a.onHover({value:b})},a.reset=function(){a.value=d.$viewValue,a.onLeave()},a.onKeydown=function(b){/(37|38|39|40)/.test(b.which)&&(b.preventDefault(),b.stopPropagation(),a.rate(a.value+(38===b.which||39===b.which?1:-1)))},this.render=function(){a.value=d.$viewValue}}]).directive("rating",function(){return{restrict:"EA",require:["rating","ngModel"],scope:{readonly:"=?",onHover:"&",onLeave:"&"},controller:"RatingController",templateUrl:"template/rating/rating.html",replace:!0,link:function(a,b,c,d){var e=d[0],f=d[1];e.init(f)}}}),angular.module("ui.bootstrap.tabs",[]).controller("TabsetController",["$scope",function(a){var b=this,c=b.tabs=a.tabs=[];b.select=function(a){angular.forEach(c,function(b){b.active&&b!==a&&(b.active=!1,b.onDeselect())}),a.active=!0,a.onSelect()},b.addTab=function(a){c.push(a),1===c.length&&a.active!==!1?a.active=!0:a.active?b.select(a):a.active=!1},b.removeTab=function(a){var e=c.indexOf(a);if(a.active&&c.length>1&&!d){var f=e==c.length-1?e-1:e+1;b.select(c[f])}c.splice(e,1)};var d;a.$on("$destroy",function(){d=!0})}]).directive("tabset",function(){return{restrict:"EA",transclude:!0,replace:!0,scope:{type:"@"},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1}}}).directive("tab",["$parse","$log",function(a,b){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{active:"=?",heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},compile:function(c,d,e){return function(c,d,f,g){c.$watch("active",function(a){a&&g.select(c)}),c.disabled=!1,f.disable&&c.$parent.$watch(a(f.disable),function(a){c.disabled=!!a}),f.disabled&&(b.warn('Use of "disabled" attribute has been deprecated, please use "disable"'),c.$parent.$watch(a(f.disabled),function(a){c.disabled=!!a})),c.select=function(){c.disabled||(c.active=!0)},g.addTab(c),c.$on("$destroy",function(){g.removeTab(c)}),c.$transcludeFn=e}}}}]).directive("tabHeadingTransclude",[function(){return{restrict:"A",require:"^tab",link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}]).directive("tabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(b,c,d){var e=b.$eval(d.tabContentTransclude);e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.timepicker",[]).constant("timepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:null,readonlyInput:!1,mousewheel:!0,arrowkeys:!0}).controller("TimepickerController",["$scope","$attrs","$parse","$log","$locale","timepickerConfig",function(a,b,c,d,e,f){function g(){var b=parseInt(a.hours,10),c=a.showMeridian?b>0&&13>b:b>=0&&24>b;return c?(a.showMeridian&&(12===b&&(b=0),a.meridian===p[1]&&(b+=12)),b):void 0}function h(){var b=parseInt(a.minutes,10);return b>=0&&60>b?b:void 0}function i(a){return angular.isDefined(a)&&a.toString().length<2?"0"+a:a.toString()}function j(a){k(),o.$setViewValue(new Date(n)),l(a)}function k(){o.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1}function l(b){var c=n.getHours(),d=n.getMinutes();a.showMeridian&&(c=0===c||12===c?12:c%12),a.hours="h"===b?c:i(c),"m"!==b&&(a.minutes=i(d)),a.meridian=n.getHours()<12?p[0]:p[1]}function m(a){var b=new Date(n.getTime()+6e4*a);n.setHours(b.getHours(),b.getMinutes()),j()}var n=new Date,o={$setViewValue:angular.noop},p=angular.isDefined(b.meridians)?a.$parent.$eval(b.meridians):f.meridians||e.DATETIME_FORMATS.AMPMS;this.init=function(c,d){o=c,o.$render=this.render,o.$formatters.unshift(function(a){return a?new Date(a):null});var e=d.eq(0),g=d.eq(1),h=angular.isDefined(b.mousewheel)?a.$parent.$eval(b.mousewheel):f.mousewheel;h&&this.setupMousewheelEvents(e,g);var i=angular.isDefined(b.arrowkeys)?a.$parent.$eval(b.arrowkeys):f.arrowkeys;i&&this.setupArrowkeyEvents(e,g),a.readonlyInput=angular.isDefined(b.readonlyInput)?a.$parent.$eval(b.readonlyInput):f.readonlyInput,this.setupInputEvents(e,g)};var q=f.hourStep;b.hourStep&&a.$parent.$watch(c(b.hourStep),function(a){q=parseInt(a,10)});var r=f.minuteStep;b.minuteStep&&a.$parent.$watch(c(b.minuteStep),function(a){r=parseInt(a,10)}),a.showMeridian=f.showMeridian,b.showMeridian&&a.$parent.$watch(c(b.showMeridian),function(b){if(a.showMeridian=!!b,o.$error.time){var c=g(),d=h();angular.isDefined(c)&&angular.isDefined(d)&&(n.setHours(c),j())}else l()}),this.setupMousewheelEvents=function(b,c){var d=function(a){a.originalEvent&&(a=a.originalEvent);var b=a.wheelDelta?a.wheelDelta:-a.deltaY;return a.detail||b>0};b.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementHours():a.decrementHours()),b.preventDefault()}),c.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementMinutes():a.decrementMinutes()),b.preventDefault()})},this.setupArrowkeyEvents=function(b,c){b.bind("keydown",function(b){38===b.which?(b.preventDefault(),a.incrementHours(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementHours(),a.$apply())}),c.bind("keydown",function(b){38===b.which?(b.preventDefault(),a.incrementMinutes(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementMinutes(),a.$apply())})},this.setupInputEvents=function(b,c){if(a.readonlyInput)return a.updateHours=angular.noop,void(a.updateMinutes=angular.noop);var d=function(b,c){o.$setViewValue(null),o.$setValidity("time",!1),angular.isDefined(b)&&(a.invalidHours=b),angular.isDefined(c)&&(a.invalidMinutes=c)};a.updateHours=function(){var a=g();angular.isDefined(a)?(n.setHours(a),j("h")):d(!0)},b.bind("blur",function(){!a.invalidHours&&a.hours<10&&a.$apply(function(){a.hours=i(a.hours)})}),a.updateMinutes=function(){var a=h();angular.isDefined(a)?(n.setMinutes(a),j("m")):d(void 0,!0)},c.bind("blur",function(){!a.invalidMinutes&&a.minutes<10&&a.$apply(function(){a.minutes=i(a.minutes)})})},this.render=function(){var a=o.$viewValue;isNaN(a)?(o.$setValidity("time",!1),d.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(a&&(n=a),k(),l())},a.incrementHours=function(){m(60*q)},a.decrementHours=function(){m(60*-q)},a.incrementMinutes=function(){m(r)},a.decrementMinutes=function(){m(-r)},a.toggleMeridian=function(){m(720*(n.getHours()<12?1:-1))}}]).directive("timepicker",function(){return{restrict:"EA",require:["timepicker","?^ngModel"],controller:"TimepickerController",replace:!0,scope:{},templateUrl:"template/timepicker/timepicker.html",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f,b.find("input"))}}}),angular.module("ui.bootstrap.transition",[]).value("$transitionSuppressDeprecated",!1).factory("$transition",["$q","$timeout","$rootScope","$log","$transitionSuppressDeprecated",function(a,b,c,d,e){function f(a){for(var b in a)if(void 0!==h.style[b])return a[b]}e||d.warn("$transition is now deprecated. Use $animate from ngAnimate instead.");var g=function(d,e,f){f=f||{};var h=a.defer(),i=g[f.animation?"animationEndEventName":"transitionEndEventName"],j=function(){c.$apply(function(){d.unbind(i,j),h.resolve(d)})};return i&&d.bind(i,j),b(function(){angular.isString(e)?d.addClass(e):angular.isFunction(e)?e(d):angular.isObject(e)&&d.css(e),i||h.resolve(d)}),h.promise.cancel=function(){i&&d.unbind(i,j),h.reject("Transition cancelled")},h.promise},h=document.createElement("trans"),i={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},j={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return g.transitionEndEventName=f(i),g.animationEndEventName=f(j),g}]),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).factory("typeaheadParser",["$parse",function(a){var b=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_" but got "'+c+'".');return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$position","typeaheadParser",function(a,b,c,d,e,f,g){var h=[9,13,27,38,40];return{require:"ngModel",link:function(i,j,k,l){var m,n=i.$eval(k.typeaheadMinLength)||1,o=i.$eval(k.typeaheadWaitMs)||0,p=i.$eval(k.typeaheadEditable)!==!1,q=b(k.typeaheadLoading).assign||angular.noop,r=b(k.typeaheadOnSelect),s=k.typeaheadInputFormatter?b(k.typeaheadInputFormatter):void 0,t=k.typeaheadAppendToBody?i.$eval(k.typeaheadAppendToBody):!1,u=i.$eval(k.typeaheadFocusFirst)!==!1,v=b(k.ngModel).assign,w=g.parse(k.typeahead),x=i.$new();i.$on("$destroy",function(){x.$destroy()});var y="typeahead-"+x.$id+"-"+Math.floor(1e4*Math.random());j.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":y});var z=angular.element("
      ");z.attr({id:y,matches:"matches",active:"activeIdx",select:"select(activeIdx)",query:"query",position:"position"}),angular.isDefined(k.typeaheadTemplateUrl)&&z.attr("template-url",k.typeaheadTemplateUrl);var A=function(){x.matches=[],x.activeIdx=-1,j.attr("aria-expanded",!1)},B=function(a){return y+"-option-"+a};x.$watch("activeIdx",function(a){0>a?j.removeAttr("aria-activedescendant"):j.attr("aria-activedescendant",B(a))});var C=function(a){var b={$viewValue:a};q(i,!0),c.when(w.source(i,b)).then(function(c){var d=a===l.$viewValue;if(d&&m)if(c&&c.length>0){x.activeIdx=u?0:-1,x.matches.length=0;for(var e=0;e=n?o>0?(F(),E(a)):C(a):(q(i,!1),F(),A()),p?a:a?void l.$setValidity("editable",!1):(l.$setValidity("editable",!0),a)}),l.$formatters.push(function(a){var b,c,d={};return p||l.$setValidity("editable",!0),s?(d.$model=a,s(i,d)):(d[w.itemName]=a,b=w.viewMapper(i,d),d[w.itemName]=void 0,c=w.viewMapper(i,d),b!==c?b:a)}),x.select=function(a){var b,c,e={};e[w.itemName]=c=x.matches[a].model,b=w.modelMapper(i,e),v(i,b),l.$setValidity("editable",!0),l.$setValidity("parse",!0),r(i,{$item:c,$model:b,$label:w.viewMapper(i,e)}),A(),d(function(){j[0].focus()},0,!1)},j.bind("keydown",function(a){0!==x.matches.length&&-1!==h.indexOf(a.which)&&(-1!=x.activeIdx||13!==a.which&&9!==a.which)&&(a.preventDefault(),40===a.which?(x.activeIdx=(x.activeIdx+1)%x.matches.length,x.$digest()):38===a.which?(x.activeIdx=(x.activeIdx>0?x.activeIdx:x.matches.length)-1,x.$digest()):13===a.which||9===a.which?x.$apply(function(){x.select(x.activeIdx)}):27===a.which&&(a.stopPropagation(),A(),x.$digest()))}),j.bind("blur",function(){m=!1});var G=function(a){j[0]!==a.target&&(A(),x.$digest())};e.bind("click",G),i.$on("$destroy",function(){e.unbind("click",G),t&&H.remove(),z.remove()});var H=a(z)(x);t?e.find("body").append(H):j.after(H)}}}]).directive("typeaheadPopup",function(){return{restrict:"EA",scope:{matches:"=",query:"=",active:"=",position:"=",select:"&"},replace:!0,templateUrl:"template/typeahead/typeahead-popup.html",link:function(a,b,c){a.templateUrl=c.templateUrl,a.isOpen=function(){return a.matches.length>0},a.isActive=function(b){return a.active==b},a.selectActive=function(b){a.active=b},a.selectMatch=function(b){a.select({activeIdx:b})}}}}).directive("typeaheadMatch",["$templateRequest","$compile","$parse",function(a,b,c){return{restrict:"EA",scope:{index:"=",match:"=",query:"="},link:function(d,e,f){var g=c(f.templateUrl)(d.$parent)||"template/typeahead/typeahead-match.html";a(g).then(function(a){b(a.trim())(d,function(a){e.replaceWith(a)})})}}}]).filter("typeaheadHighlight",function(){function a(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(b,c){return c?(""+b).replace(new RegExp(a(c),"gi"),"$&"):b}}),!angular.$$csp()&&angular.element(document).find("head").prepend(''); \ No newline at end of file diff --git a/turtles/app/lib/bower_components/angular/.bower.json b/turtles/app/lib/bower_components/angular/.bower.json new file mode 100644 index 000000000..8a311ecca --- /dev/null +++ b/turtles/app/lib/bower_components/angular/.bower.json @@ -0,0 +1,17 @@ +{ + "name": "angular", + "version": "1.4.0", + "main": "./angular.js", + "ignore": [], + "dependencies": {}, + "homepage": "https://github.com/angular/bower-angular", + "_release": "1.4.0", + "_resolution": { + "type": "version", + "tag": "v1.4.0", + "commit": "e2f2cf7dc4a3ef1859ab28e657eca0e9edb588ba" + }, + "_source": "git://github.com/angular/bower-angular.git", + "_target": ">=1.3.0", + "_originalSource": "angular" +} \ No newline at end of file diff --git a/turtles/app/lib/bower_components/angular/README.md b/turtles/app/lib/bower_components/angular/README.md new file mode 100644 index 000000000..d1bc0eddf --- /dev/null +++ b/turtles/app/lib/bower_components/angular/README.md @@ -0,0 +1,64 @@ +# packaged angular + +This repo is for distribution on `npm` and `bower`. The source for this module is in the +[main AngularJS repo](https://github.com/angular/angular.js). +Please file issues and pull requests against that repo. + +## Install + +You can install this package either with `npm` or with `bower`. + +### npm + +```shell +npm install angular +``` + +Then add a ` +``` + +Or `require('angular')` from your code. + +### bower + +```shell +bower install angular +``` + +Then add a ` +``` + +## Documentation + +Documentation is available on the +[AngularJS docs site](http://docs.angularjs.org/). + +## License + +The MIT License + +Copyright (c) 2010-2015 Google, Inc. http://angularjs.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/turtles/app/lib/bower_components/angular/angular-csp.css b/turtles/app/lib/bower_components/angular/angular-csp.css new file mode 100644 index 000000000..f3cd926cb --- /dev/null +++ b/turtles/app/lib/bower_components/angular/angular-csp.css @@ -0,0 +1,21 @@ +/* Include this file in your html if you are using the CSP mode. */ + +@charset "UTF-8"; + +[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], +.ng-cloak, .x-ng-cloak, +.ng-hide:not(.ng-hide-animate) { + display: none !important; +} + +ng\:form { + display: block; +} + +.ng-animate-shim { + visibility:hidden; +} + +.ng-anchor { + position:absolute; +} diff --git a/turtles/app/lib/bower_components/angular/angular.js b/turtles/app/lib/bower_components/angular/angular.js new file mode 100644 index 000000000..af94745a9 --- /dev/null +++ b/turtles/app/lib/bower_components/angular/angular.js @@ -0,0 +1,28133 @@ +/** + * @license AngularJS v1.4.0 + * (c) 2010-2015 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, document, undefined) {'use strict'; + +/** + * @description + * + * This object provides a utility for producing rich Error messages within + * Angular. It can be called as follows: + * + * var exampleMinErr = minErr('example'); + * throw exampleMinErr('one', 'This {0} is {1}', foo, bar); + * + * The above creates an instance of minErr in the example namespace. The + * resulting error will have a namespaced error code of example.one. The + * resulting error will replace {0} with the value of foo, and {1} with the + * value of bar. The object is not restricted in the number of arguments it can + * take. + * + * If fewer arguments are specified than necessary for interpolation, the extra + * interpolation markers will be preserved in the final string. + * + * Since data will be parsed statically during a build step, some restrictions + * are applied with respect to how minErr instances are created and called. + * Instances should have names of the form namespaceMinErr for a minErr created + * using minErr('namespace') . Error codes, namespaces and template strings + * should all be static strings, not variables or general expressions. + * + * @param {string} module The namespace to use for the new minErr instance. + * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning + * error from returned function, for cases when a particular type of error is useful. + * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance + */ + +function minErr(module, ErrorConstructor) { + ErrorConstructor = ErrorConstructor || Error; + return function() { + var SKIP_INDEXES = 2; + + var templateArgs = arguments, + code = templateArgs[0], + message = '[' + (module ? module + ':' : '') + code + '] ', + template = templateArgs[1], + paramPrefix, i; + + message += template.replace(/\{\d+\}/g, function(match) { + var index = +match.slice(1, -1), + shiftedIndex = index + SKIP_INDEXES; + + if (shiftedIndex < templateArgs.length) { + return toDebugString(templateArgs[shiftedIndex]); + } + + return match; + }); + + message += '\nhttp://errors.angularjs.org/1.4.0/' + + (module ? module + '/' : '') + code; + + for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') { + message += paramPrefix + 'p' + (i - SKIP_INDEXES) + '=' + + encodeURIComponent(toDebugString(templateArgs[i])); + } + + return new ErrorConstructor(message); + }; +} + +/* We need to tell jshint what variables are being exported */ +/* global angular: true, + msie: true, + jqLite: true, + jQuery: true, + slice: true, + splice: true, + push: true, + toString: true, + ngMinErr: true, + angularModule: true, + uid: true, + REGEX_STRING_REGEXP: true, + VALIDITY_STATE_PROPERTY: true, + + lowercase: true, + uppercase: true, + manualLowercase: true, + manualUppercase: true, + nodeName_: true, + isArrayLike: true, + forEach: true, + forEachSorted: true, + reverseParams: true, + nextUid: true, + setHashKey: true, + extend: true, + toInt: true, + inherit: true, + merge: true, + noop: true, + identity: true, + valueFn: true, + isUndefined: true, + isDefined: true, + isObject: true, + isBlankObject: true, + isString: true, + isNumber: true, + isDate: true, + isArray: true, + isFunction: true, + isRegExp: true, + isWindow: true, + isScope: true, + isFile: true, + isFormData: true, + isBlob: true, + isBoolean: true, + isPromiseLike: true, + trim: true, + escapeForRegexp: true, + isElement: true, + makeMap: true, + includes: true, + arrayRemove: true, + copy: true, + shallowCopy: true, + equals: true, + csp: true, + jq: true, + concat: true, + sliceArgs: true, + bind: true, + toJsonReplacer: true, + toJson: true, + fromJson: true, + convertTimezoneToLocal: true, + timezoneToOffset: true, + startingTag: true, + tryDecodeURIComponent: true, + parseKeyValue: true, + toKeyValue: true, + encodeUriSegment: true, + encodeUriQuery: true, + angularInit: true, + bootstrap: true, + getTestability: true, + snake_case: true, + bindJQuery: true, + assertArg: true, + assertArgFn: true, + assertNotHasOwnProperty: true, + getter: true, + getBlockNodes: true, + hasOwnProperty: true, + createMap: true, + + NODE_TYPE_ELEMENT: true, + NODE_TYPE_ATTRIBUTE: true, + NODE_TYPE_TEXT: true, + NODE_TYPE_COMMENT: true, + NODE_TYPE_DOCUMENT: true, + NODE_TYPE_DOCUMENT_FRAGMENT: true, +*/ + +//////////////////////////////////// + +/** + * @ngdoc module + * @name ng + * @module ng + * @description + * + * # ng (core module) + * The ng module is loaded by default when an AngularJS application is started. The module itself + * contains the essential components for an AngularJS application to function. The table below + * lists a high level breakdown of each of the services/factories, filters, directives and testing + * components available within this core module. + * + *
      + */ + +var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/; + +// The name of a form control's ValidityState property. +// This is used so that it's possible for internal tests to create mock ValidityStates. +var VALIDITY_STATE_PROPERTY = 'validity'; + +/** + * @ngdoc function + * @name angular.lowercase + * @module ng + * @kind function + * + * @description Converts the specified string to lowercase. + * @param {string} string String to be converted to lowercase. + * @returns {string} Lowercased string. + */ +var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;}; +var hasOwnProperty = Object.prototype.hasOwnProperty; + +/** + * @ngdoc function + * @name angular.uppercase + * @module ng + * @kind function + * + * @description Converts the specified string to uppercase. + * @param {string} string String to be converted to uppercase. + * @returns {string} Uppercased string. + */ +var uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;}; + + +var manualLowercase = function(s) { + /* jshint bitwise: false */ + return isString(s) + ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);}) + : s; +}; +var manualUppercase = function(s) { + /* jshint bitwise: false */ + return isString(s) + ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);}) + : s; +}; + + +// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish +// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods +// with correct but slower alternatives. +if ('i' !== 'I'.toLowerCase()) { + lowercase = manualLowercase; + uppercase = manualUppercase; +} + + +var + msie, // holds major version number for IE, or NaN if UA is not IE. + jqLite, // delay binding since jQuery could be loaded after us. + jQuery, // delay binding + slice = [].slice, + splice = [].splice, + push = [].push, + toString = Object.prototype.toString, + getPrototypeOf = Object.getPrototypeOf, + ngMinErr = minErr('ng'), + + /** @name angular */ + angular = window.angular || (window.angular = {}), + angularModule, + uid = 0; + +/** + * documentMode is an IE-only property + * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx + */ +msie = document.documentMode; + + +/** + * @private + * @param {*} obj + * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, + * String ...) + */ +function isArrayLike(obj) { + if (obj == null || isWindow(obj)) { + return false; + } + + // Support: iOS 8.2 (not reproducible in simulator) + // "length" in obj used to prevent JIT error (gh-11508) + var length = "length" in Object(obj) && obj.length; + + if (obj.nodeType === NODE_TYPE_ELEMENT && length) { + return true; + } + + return isString(obj) || isArray(obj) || length === 0 || + typeof length === 'number' && length > 0 && (length - 1) in obj; +} + +/** + * @ngdoc function + * @name angular.forEach + * @module ng + * @kind function + * + * @description + * Invokes the `iterator` function once for each item in `obj` collection, which can be either an + * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value` + * is the value of an object property or an array element, `key` is the object property key or + * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional. + * + * It is worth noting that `.forEach` does not iterate over inherited properties because it filters + * using the `hasOwnProperty` method. + * + * Unlike ES262's + * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18), + * Providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just + * return the value provided. + * + ```js + var values = {name: 'misko', gender: 'male'}; + var log = []; + angular.forEach(values, function(value, key) { + this.push(key + ': ' + value); + }, log); + expect(log).toEqual(['name: misko', 'gender: male']); + ``` + * + * @param {Object|Array} obj Object to iterate over. + * @param {Function} iterator Iterator function. + * @param {Object=} context Object to become context (`this`) for the iterator function. + * @returns {Object|Array} Reference to `obj`. + */ + +function forEach(obj, iterator, context) { + var key, length; + if (obj) { + if (isFunction(obj)) { + for (key in obj) { + // Need to check if hasOwnProperty exists, + // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function + if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) { + iterator.call(context, obj[key], key, obj); + } + } + } else if (isArray(obj) || isArrayLike(obj)) { + var isPrimitive = typeof obj !== 'object'; + for (key = 0, length = obj.length; key < length; key++) { + if (isPrimitive || key in obj) { + iterator.call(context, obj[key], key, obj); + } + } + } else if (obj.forEach && obj.forEach !== forEach) { + obj.forEach(iterator, context, obj); + } else if (isBlankObject(obj)) { + // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty + for (key in obj) { + iterator.call(context, obj[key], key, obj); + } + } else if (typeof obj.hasOwnProperty === 'function') { + // Slow path for objects inheriting Object.prototype, hasOwnProperty check needed + for (key in obj) { + if (obj.hasOwnProperty(key)) { + iterator.call(context, obj[key], key, obj); + } + } + } else { + // Slow path for objects which do not have a method `hasOwnProperty` + for (key in obj) { + if (hasOwnProperty.call(obj, key)) { + iterator.call(context, obj[key], key, obj); + } + } + } + } + return obj; +} + +function forEachSorted(obj, iterator, context) { + var keys = Object.keys(obj).sort(); + for (var i = 0; i < keys.length; i++) { + iterator.call(context, obj[keys[i]], keys[i]); + } + return keys; +} + + +/** + * when using forEach the params are value, key, but it is often useful to have key, value. + * @param {function(string, *)} iteratorFn + * @returns {function(*, string)} + */ +function reverseParams(iteratorFn) { + return function(value, key) { iteratorFn(key, value); }; +} + +/** + * A consistent way of creating unique IDs in angular. + * + * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before + * we hit number precision issues in JavaScript. + * + * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M + * + * @returns {number} an unique alpha-numeric string + */ +function nextUid() { + return ++uid; +} + + +/** + * Set or clear the hashkey for an object. + * @param obj object + * @param h the hashkey (!truthy to delete the hashkey) + */ +function setHashKey(obj, h) { + if (h) { + obj.$$hashKey = h; + } else { + delete obj.$$hashKey; + } +} + + +function baseExtend(dst, objs, deep) { + var h = dst.$$hashKey; + + for (var i = 0, ii = objs.length; i < ii; ++i) { + var obj = objs[i]; + if (!isObject(obj) && !isFunction(obj)) continue; + var keys = Object.keys(obj); + for (var j = 0, jj = keys.length; j < jj; j++) { + var key = keys[j]; + var src = obj[key]; + + if (deep && isObject(src)) { + if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {}; + baseExtend(dst[key], [src], true); + } else { + dst[key] = src; + } + } + } + + setHashKey(dst, h); + return dst; +} + +/** + * @ngdoc function + * @name angular.extend + * @module ng + * @kind function + * + * @description + * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s) + * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so + * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`. + * + * **Note:** Keep in mind that `angular.extend` does not support recursive merge (deep copy). Use + * {@link angular.merge} for this. + * + * @param {Object} dst Destination object. + * @param {...Object} src Source object(s). + * @returns {Object} Reference to `dst`. + */ +function extend(dst) { + return baseExtend(dst, slice.call(arguments, 1), false); +} + + +/** +* @ngdoc function +* @name angular.merge +* @module ng +* @kind function +* +* @description +* Deeply extends the destination object `dst` by copying own enumerable properties from the `src` object(s) +* to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so +* by passing an empty object as the target: `var object = angular.merge({}, object1, object2)`. +* +* Unlike {@link angular.extend extend()}, `merge()` recursively descends into object properties of source +* objects, performing a deep copy. +* +* @param {Object} dst Destination object. +* @param {...Object} src Source object(s). +* @returns {Object} Reference to `dst`. +*/ +function merge(dst) { + return baseExtend(dst, slice.call(arguments, 1), true); +} + + + +function toInt(str) { + return parseInt(str, 10); +} + + +function inherit(parent, extra) { + return extend(Object.create(parent), extra); +} + +/** + * @ngdoc function + * @name angular.noop + * @module ng + * @kind function + * + * @description + * A function that performs no operations. This function can be useful when writing code in the + * functional style. + ```js + function foo(callback) { + var result = calculateResult(); + (callback || angular.noop)(result); + } + ``` + */ +function noop() {} +noop.$inject = []; + + +/** + * @ngdoc function + * @name angular.identity + * @module ng + * @kind function + * + * @description + * A function that returns its first argument. This function is useful when writing code in the + * functional style. + * + ```js + function transformer(transformationFn, value) { + return (transformationFn || angular.identity)(value); + }; + ``` + * @param {*} value to be returned. + * @returns {*} the value passed in. + */ +function identity($) {return $;} +identity.$inject = []; + + +function valueFn(value) {return function() {return value;};} + +/** + * @ngdoc function + * @name angular.isUndefined + * @module ng + * @kind function + * + * @description + * Determines if a reference is undefined. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is undefined. + */ +function isUndefined(value) {return typeof value === 'undefined';} + + +/** + * @ngdoc function + * @name angular.isDefined + * @module ng + * @kind function + * + * @description + * Determines if a reference is defined. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is defined. + */ +function isDefined(value) {return typeof value !== 'undefined';} + + +/** + * @ngdoc function + * @name angular.isObject + * @module ng + * @kind function + * + * @description + * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not + * considered to be objects. Note that JavaScript arrays are objects. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is an `Object` but not `null`. + */ +function isObject(value) { + // http://jsperf.com/isobject4 + return value !== null && typeof value === 'object'; +} + + +/** + * Determine if a value is an object with a null prototype + * + * @returns {boolean} True if `value` is an `Object` with a null prototype + */ +function isBlankObject(value) { + return value !== null && typeof value === 'object' && !getPrototypeOf(value); +} + + +/** + * @ngdoc function + * @name angular.isString + * @module ng + * @kind function + * + * @description + * Determines if a reference is a `String`. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `String`. + */ +function isString(value) {return typeof value === 'string';} + + +/** + * @ngdoc function + * @name angular.isNumber + * @module ng + * @kind function + * + * @description + * Determines if a reference is a `Number`. + * + * This includes the "special" numbers `NaN`, `+Infinity` and `-Infinity`. + * + * If you wish to exclude these then you can use the native + * [`isFinite'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite) + * method. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `Number`. + */ +function isNumber(value) {return typeof value === 'number';} + + +/** + * @ngdoc function + * @name angular.isDate + * @module ng + * @kind function + * + * @description + * Determines if a value is a date. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `Date`. + */ +function isDate(value) { + return toString.call(value) === '[object Date]'; +} + + +/** + * @ngdoc function + * @name angular.isArray + * @module ng + * @kind function + * + * @description + * Determines if a reference is an `Array`. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is an `Array`. + */ +var isArray = Array.isArray; + +/** + * @ngdoc function + * @name angular.isFunction + * @module ng + * @kind function + * + * @description + * Determines if a reference is a `Function`. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `Function`. + */ +function isFunction(value) {return typeof value === 'function';} + + +/** + * Determines if a value is a regular expression object. + * + * @private + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `RegExp`. + */ +function isRegExp(value) { + return toString.call(value) === '[object RegExp]'; +} + + +/** + * Checks if `obj` is a window object. + * + * @private + * @param {*} obj Object to check + * @returns {boolean} True if `obj` is a window obj. + */ +function isWindow(obj) { + return obj && obj.window === obj; +} + + +function isScope(obj) { + return obj && obj.$evalAsync && obj.$watch; +} + + +function isFile(obj) { + return toString.call(obj) === '[object File]'; +} + + +function isFormData(obj) { + return toString.call(obj) === '[object FormData]'; +} + + +function isBlob(obj) { + return toString.call(obj) === '[object Blob]'; +} + + +function isBoolean(value) { + return typeof value === 'boolean'; +} + + +function isPromiseLike(obj) { + return obj && isFunction(obj.then); +} + + +var TYPED_ARRAY_REGEXP = /^\[object (Uint8(Clamped)?)|(Uint16)|(Uint32)|(Int8)|(Int16)|(Int32)|(Float(32)|(64))Array\]$/; +function isTypedArray(value) { + return TYPED_ARRAY_REGEXP.test(toString.call(value)); +} + + +var trim = function(value) { + return isString(value) ? value.trim() : value; +}; + +// Copied from: +// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021 +// Prereq: s is a string. +var escapeForRegexp = function(s) { + return s.replace(/([-()\[\]{}+?*.$\^|,:#= 0) { + array.splice(index, 1); + } + return index; +} + +/** + * @ngdoc function + * @name angular.copy + * @module ng + * @kind function + * + * @description + * Creates a deep copy of `source`, which should be an object or an array. + * + * * If no destination is supplied, a copy of the object or array is created. + * * If a destination is provided, all of its elements (for arrays) or properties (for objects) + * are deleted and then all elements/properties from the source are copied to it. + * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned. + * * If `source` is identical to 'destination' an exception will be thrown. + * + * @param {*} source The source that will be used to make a copy. + * Can be any type, including primitives, `null`, and `undefined`. + * @param {(Object|Array)=} destination Destination into which the source is copied. If + * provided, must be of the same type as `source`. + * @returns {*} The copy or updated `destination`, if `destination` was specified. + * + * @example + + +
      +
      + Name:
      + E-mail:
      + Gender: male + female
      + + +
      +
      form = {{user | json}}
      +
      master = {{master | json}}
      +
      + + +
      +
      + */ +function copy(source, destination, stackSource, stackDest) { + if (isWindow(source) || isScope(source)) { + throw ngMinErr('cpws', + "Can't copy! Making copies of Window or Scope instances is not supported."); + } + if (isTypedArray(destination)) { + throw ngMinErr('cpta', + "Can't copy! TypedArray destination cannot be mutated."); + } + + if (!destination) { + destination = source; + if (source) { + if (isArray(source)) { + destination = copy(source, [], stackSource, stackDest); + } else if (isTypedArray(source)) { + destination = new source.constructor(source); + } else if (isDate(source)) { + destination = new Date(source.getTime()); + } else if (isRegExp(source)) { + destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]); + destination.lastIndex = source.lastIndex; + } else if (isObject(source)) { + var emptyObject = Object.create(getPrototypeOf(source)); + destination = copy(source, emptyObject, stackSource, stackDest); + } + } + } else { + if (source === destination) throw ngMinErr('cpi', + "Can't copy! Source and destination are identical."); + + stackSource = stackSource || []; + stackDest = stackDest || []; + + if (isObject(source)) { + var index = stackSource.indexOf(source); + if (index !== -1) return stackDest[index]; + + stackSource.push(source); + stackDest.push(destination); + } + + var result, key; + if (isArray(source)) { + destination.length = 0; + for (var i = 0; i < source.length; i++) { + result = copy(source[i], null, stackSource, stackDest); + if (isObject(source[i])) { + stackSource.push(source[i]); + stackDest.push(result); + } + destination.push(result); + } + } else { + var h = destination.$$hashKey; + if (isArray(destination)) { + destination.length = 0; + } else { + forEach(destination, function(value, key) { + delete destination[key]; + }); + } + if (isBlankObject(source)) { + // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty + for (key in source) { + putValue(key, source[key], destination, stackSource, stackDest); + } + } else if (source && typeof source.hasOwnProperty === 'function') { + // Slow path, which must rely on hasOwnProperty + for (key in source) { + if (source.hasOwnProperty(key)) { + putValue(key, source[key], destination, stackSource, stackDest); + } + } + } else { + // Slowest path --- hasOwnProperty can't be called as a method + for (key in source) { + if (hasOwnProperty.call(source, key)) { + putValue(key, source[key], destination, stackSource, stackDest); + } + } + } + setHashKey(destination,h); + } + } + return destination; + + function putValue(key, val, destination, stackSource, stackDest) { + // No context allocation, trivial outer scope, easily inlined + var result = copy(val, null, stackSource, stackDest); + if (isObject(val)) { + stackSource.push(val); + stackDest.push(result); + } + destination[key] = result; + } +} + +/** + * Creates a shallow copy of an object, an array or a primitive. + * + * Assumes that there are no proto properties for objects. + */ +function shallowCopy(src, dst) { + if (isArray(src)) { + dst = dst || []; + + for (var i = 0, ii = src.length; i < ii; i++) { + dst[i] = src[i]; + } + } else if (isObject(src)) { + dst = dst || {}; + + for (var key in src) { + if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) { + dst[key] = src[key]; + } + } + } + + return dst || src; +} + + +/** + * @ngdoc function + * @name angular.equals + * @module ng + * @kind function + * + * @description + * Determines if two objects or two values are equivalent. Supports value types, regular + * expressions, arrays and objects. + * + * Two objects or values are considered equivalent if at least one of the following is true: + * + * * Both objects or values pass `===` comparison. + * * Both objects or values are of the same type and all of their properties are equal by + * comparing them with `angular.equals`. + * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal) + * * Both values represent the same regular expression (In JavaScript, + * /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual + * representation matches). + * + * During a property comparison, properties of `function` type and properties with names + * that begin with `$` are ignored. + * + * Scope and DOMWindow objects are being compared only by identify (`===`). + * + * @param {*} o1 Object or value to compare. + * @param {*} o2 Object or value to compare. + * @returns {boolean} True if arguments are equal. + */ +function equals(o1, o2) { + if (o1 === o2) return true; + if (o1 === null || o2 === null) return false; + if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN + var t1 = typeof o1, t2 = typeof o2, length, key, keySet; + if (t1 == t2) { + if (t1 == 'object') { + if (isArray(o1)) { + if (!isArray(o2)) return false; + if ((length = o1.length) == o2.length) { + for (key = 0; key < length; key++) { + if (!equals(o1[key], o2[key])) return false; + } + return true; + } + } else if (isDate(o1)) { + if (!isDate(o2)) return false; + return equals(o1.getTime(), o2.getTime()); + } else if (isRegExp(o1)) { + return isRegExp(o2) ? o1.toString() == o2.toString() : false; + } else { + if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || + isArray(o2) || isDate(o2) || isRegExp(o2)) return false; + keySet = createMap(); + for (key in o1) { + if (key.charAt(0) === '$' || isFunction(o1[key])) continue; + if (!equals(o1[key], o2[key])) return false; + keySet[key] = true; + } + for (key in o2) { + if (!(key in keySet) && + key.charAt(0) !== '$' && + o2[key] !== undefined && + !isFunction(o2[key])) return false; + } + return true; + } + } + } + return false; +} + +var csp = function() { + if (isDefined(csp.isActive_)) return csp.isActive_; + + var active = !!(document.querySelector('[ng-csp]') || + document.querySelector('[data-ng-csp]')); + + if (!active) { + try { + /* jshint -W031, -W054 */ + new Function(''); + /* jshint +W031, +W054 */ + } catch (e) { + active = true; + } + } + + return (csp.isActive_ = active); +}; + +/** + * @ngdoc directive + * @module ng + * @name ngJq + * + * @element ANY + * @param {string=} ngJq the name of the library available under `window` + * to be used for angular.element + * @description + * Use this directive to force the angular.element library. This should be + * used to force either jqLite by leaving ng-jq blank or setting the name of + * the jquery variable under window (eg. jQuery). + * + * Since angular looks for this directive when it is loaded (doesn't wait for the + * DOMContentLoaded event), it must be placed on an element that comes before the script + * which loads angular. Also, only the first instance of `ng-jq` will be used and all + * others ignored. + * + * @example + * This example shows how to force jqLite using the `ngJq` directive to the `html` tag. + ```html + + + ... + ... + + ``` + * @example + * This example shows how to use a jQuery based library of a different name. + * The library name must be available at the top most 'window'. + ```html + + + ... + ... + + ``` + */ +var jq = function() { + if (isDefined(jq.name_)) return jq.name_; + var el; + var i, ii = ngAttrPrefixes.length, prefix, name; + for (i = 0; i < ii; ++i) { + prefix = ngAttrPrefixes[i]; + if (el = document.querySelector('[' + prefix.replace(':', '\\:') + 'jq]')) { + name = el.getAttribute(prefix + 'jq'); + break; + } + } + + return (jq.name_ = name); +}; + +function concat(array1, array2, index) { + return array1.concat(slice.call(array2, index)); +} + +function sliceArgs(args, startIndex) { + return slice.call(args, startIndex || 0); +} + + +/* jshint -W101 */ +/** + * @ngdoc function + * @name angular.bind + * @module ng + * @kind function + * + * @description + * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for + * `fn`). You can supply optional `args` that are prebound to the function. This feature is also + * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as + * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application). + * + * @param {Object} self Context which `fn` should be evaluated in. + * @param {function()} fn Function to be bound. + * @param {...*} args Optional arguments to be prebound to the `fn` function call. + * @returns {function()} Function that wraps the `fn` with all the specified bindings. + */ +/* jshint +W101 */ +function bind(self, fn) { + var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : []; + if (isFunction(fn) && !(fn instanceof RegExp)) { + return curryArgs.length + ? function() { + return arguments.length + ? fn.apply(self, concat(curryArgs, arguments, 0)) + : fn.apply(self, curryArgs); + } + : function() { + return arguments.length + ? fn.apply(self, arguments) + : fn.call(self); + }; + } else { + // in IE, native methods are not functions so they cannot be bound (note: they don't need to be) + return fn; + } +} + + +function toJsonReplacer(key, value) { + var val = value; + + if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') { + val = undefined; + } else if (isWindow(value)) { + val = '$WINDOW'; + } else if (value && document === value) { + val = '$DOCUMENT'; + } else if (isScope(value)) { + val = '$SCOPE'; + } + + return val; +} + + +/** + * @ngdoc function + * @name angular.toJson + * @module ng + * @kind function + * + * @description + * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be + * stripped since angular uses this notation internally. + * + * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON. + * @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace. + * If set to an integer, the JSON output will contain that many spaces per indentation. + * @returns {string|undefined} JSON-ified string representing `obj`. + */ +function toJson(obj, pretty) { + if (typeof obj === 'undefined') return undefined; + if (!isNumber(pretty)) { + pretty = pretty ? 2 : null; + } + return JSON.stringify(obj, toJsonReplacer, pretty); +} + + +/** + * @ngdoc function + * @name angular.fromJson + * @module ng + * @kind function + * + * @description + * Deserializes a JSON string. + * + * @param {string} json JSON string to deserialize. + * @returns {Object|Array|string|number} Deserialized JSON string. + */ +function fromJson(json) { + return isString(json) + ? JSON.parse(json) + : json; +} + + +function timezoneToOffset(timezone, fallback) { + var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000; + return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset; +} + + +function addDateMinutes(date, minutes) { + date = new Date(date.getTime()); + date.setMinutes(date.getMinutes() + minutes); + return date; +} + + +function convertTimezoneToLocal(date, timezone, reverse) { + reverse = reverse ? -1 : 1; + var timezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset()); + return addDateMinutes(date, reverse * (timezoneOffset - date.getTimezoneOffset())); +} + + +/** + * @returns {string} Returns the string representation of the element. + */ +function startingTag(element) { + element = jqLite(element).clone(); + try { + // turns out IE does not let you set .html() on elements which + // are not allowed to have children. So we just ignore it. + element.empty(); + } catch (e) {} + var elemHtml = jqLite('
      ').append(element).html(); + try { + return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) : + elemHtml. + match(/^(<[^>]+>)/)[1]. + replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); }); + } catch (e) { + return lowercase(elemHtml); + } + +} + + +///////////////////////////////////////////////// + +/** + * Tries to decode the URI component without throwing an exception. + * + * @private + * @param str value potential URI component to check. + * @returns {boolean} True if `value` can be decoded + * with the decodeURIComponent function. + */ +function tryDecodeURIComponent(value) { + try { + return decodeURIComponent(value); + } catch (e) { + // Ignore any invalid uri component + } +} + + +/** + * Parses an escaped url query string into key-value pairs. + * @returns {Object.} + */ +function parseKeyValue(/**string*/keyValue) { + var obj = {}, key_value, key; + forEach((keyValue || "").split('&'), function(keyValue) { + if (keyValue) { + key_value = keyValue.replace(/\+/g,'%20').split('='); + key = tryDecodeURIComponent(key_value[0]); + if (isDefined(key)) { + var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true; + if (!hasOwnProperty.call(obj, key)) { + obj[key] = val; + } else if (isArray(obj[key])) { + obj[key].push(val); + } else { + obj[key] = [obj[key],val]; + } + } + } + }); + return obj; +} + +function toKeyValue(obj) { + var parts = []; + forEach(obj, function(value, key) { + if (isArray(value)) { + forEach(value, function(arrayValue) { + parts.push(encodeUriQuery(key, true) + + (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true))); + }); + } else { + parts.push(encodeUriQuery(key, true) + + (value === true ? '' : '=' + encodeUriQuery(value, true))); + } + }); + return parts.length ? parts.join('&') : ''; +} + + +/** + * We need our custom method because encodeURIComponent is too aggressive and doesn't follow + * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path + * segments: + * segment = *pchar + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * pct-encoded = "%" HEXDIG HEXDIG + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ +function encodeUriSegment(val) { + return encodeUriQuery(val, true). + replace(/%26/gi, '&'). + replace(/%3D/gi, '='). + replace(/%2B/gi, '+'); +} + + +/** + * This method is intended for encoding *key* or *value* parts of query component. We need a custom + * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be + * encoded per http://tools.ietf.org/html/rfc3986: + * query = *( pchar / "/" / "?" ) + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * pct-encoded = "%" HEXDIG HEXDIG + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ +function encodeUriQuery(val, pctEncodeSpaces) { + return encodeURIComponent(val). + replace(/%40/gi, '@'). + replace(/%3A/gi, ':'). + replace(/%24/g, '$'). + replace(/%2C/gi, ','). + replace(/%3B/gi, ';'). + replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); +} + +var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-']; + +function getNgAttribute(element, ngAttr) { + var attr, i, ii = ngAttrPrefixes.length; + for (i = 0; i < ii; ++i) { + attr = ngAttrPrefixes[i] + ngAttr; + if (isString(attr = element.getAttribute(attr))) { + return attr; + } + } + return null; +} + +/** + * @ngdoc directive + * @name ngApp + * @module ng + * + * @element ANY + * @param {angular.Module} ngApp an optional application + * {@link angular.module module} name to load. + * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be + * created in "strict-di" mode. This means that the application will fail to invoke functions which + * do not use explicit function annotation (and are thus unsuitable for minification), as described + * in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in + * tracking down the root of these bugs. + * + * @description + * + * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive + * designates the **root element** of the application and is typically placed near the root element + * of the page - e.g. on the `` or `` tags. + * + * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp` + * found in the document will be used to define the root element to auto-bootstrap as an + * application. To run multiple applications in an HTML document you must manually bootstrap them using + * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other. + * + * You can specify an **AngularJS module** to be used as the root module for the application. This + * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It + * should contain the application code needed or have dependencies on other modules that will + * contain the code. See {@link angular.module} for more information. + * + * In the example below if the `ngApp` directive were not placed on the `html` element then the + * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}` + * would not be resolved to `3`. + * + * `ngApp` is the easiest, and most common way to bootstrap an application. + * + + +
      + I can add: {{a}} + {{b}} = {{ a+b }} +
      +
      + + angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) { + $scope.a = 1; + $scope.b = 2; + }); + +
      + * + * Using `ngStrictDi`, you would see something like this: + * + + +
      +
      + I can add: {{a}} + {{b}} = {{ a+b }} + +

      This renders because the controller does not fail to + instantiate, by using explicit annotation style (see + script.js for details) +

      +
      + +
      + Name:
      + Hello, {{name}}! + +

      This renders because the controller does not fail to + instantiate, by using explicit annotation style + (see script.js for details) +

      +
      + +
      + I can add: {{a}} + {{b}} = {{ a+b }} + +

      The controller could not be instantiated, due to relying + on automatic function annotations (which are disabled in + strict mode). As such, the content of this section is not + interpolated, and there should be an error in your web console. +

      +
      +
      +
      + + angular.module('ngAppStrictDemo', []) + // BadController will fail to instantiate, due to relying on automatic function annotation, + // rather than an explicit annotation + .controller('BadController', function($scope) { + $scope.a = 1; + $scope.b = 2; + }) + // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated, + // due to using explicit annotations using the array style and $inject property, respectively. + .controller('GoodController1', ['$scope', function($scope) { + $scope.a = 1; + $scope.b = 2; + }]) + .controller('GoodController2', GoodController2); + function GoodController2($scope) { + $scope.name = "World"; + } + GoodController2.$inject = ['$scope']; + + + div[ng-controller] { + margin-bottom: 1em; + -webkit-border-radius: 4px; + border-radius: 4px; + border: 1px solid; + padding: .5em; + } + div[ng-controller^=Good] { + border-color: #d6e9c6; + background-color: #dff0d8; + color: #3c763d; + } + div[ng-controller^=Bad] { + border-color: #ebccd1; + background-color: #f2dede; + color: #a94442; + margin-bottom: 0; + } + +
      + */ +function angularInit(element, bootstrap) { + var appElement, + module, + config = {}; + + // The element `element` has priority over any other element + forEach(ngAttrPrefixes, function(prefix) { + var name = prefix + 'app'; + + if (!appElement && element.hasAttribute && element.hasAttribute(name)) { + appElement = element; + module = element.getAttribute(name); + } + }); + forEach(ngAttrPrefixes, function(prefix) { + var name = prefix + 'app'; + var candidate; + + if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\:') + ']'))) { + appElement = candidate; + module = candidate.getAttribute(name); + } + }); + if (appElement) { + config.strictDi = getNgAttribute(appElement, "strict-di") !== null; + bootstrap(appElement, module ? [module] : [], config); + } +} + +/** + * @ngdoc function + * @name angular.bootstrap + * @module ng + * @description + * Use this function to manually start up angular application. + * + * See: {@link guide/bootstrap Bootstrap} + * + * Note that Protractor based end-to-end tests cannot use this function to bootstrap manually. + * They must use {@link ng.directive:ngApp ngApp}. + * + * Angular will detect if it has been loaded into the browser more than once and only allow the + * first loaded script to be bootstrapped and will report a warning to the browser console for + * each of the subsequent scripts. This prevents strange results in applications, where otherwise + * multiple instances of Angular try to work on the DOM. + * + * ```html + * + * + * + *
      + * {{greeting}} + *
      + * + * + * + * + * + * ``` + * + * @param {DOMElement} element DOM element which is the root of angular application. + * @param {Array=} modules an array of modules to load into the application. + * Each item in the array should be the name of a predefined module or a (DI annotated) + * function that will be invoked by the injector as a `config` block. + * See: {@link angular.module modules} + * @param {Object=} config an object for defining configuration options for the application. The + * following keys are supported: + * + * * `strictDi` - disable automatic function annotation for the application. This is meant to + * assist in finding bugs which break minified code. Defaults to `false`. + * + * @returns {auto.$injector} Returns the newly created injector for this app. + */ +function bootstrap(element, modules, config) { + if (!isObject(config)) config = {}; + var defaultConfig = { + strictDi: false + }; + config = extend(defaultConfig, config); + var doBootstrap = function() { + element = jqLite(element); + + if (element.injector()) { + var tag = (element[0] === document) ? 'document' : startingTag(element); + //Encode angle brackets to prevent input from being sanitized to empty string #8683 + throw ngMinErr( + 'btstrpd', + "App Already Bootstrapped with this Element '{0}'", + tag.replace(//,'>')); + } + + modules = modules || []; + modules.unshift(['$provide', function($provide) { + $provide.value('$rootElement', element); + }]); + + if (config.debugInfoEnabled) { + // Pushing so that this overrides `debugInfoEnabled` setting defined in user's `modules`. + modules.push(['$compileProvider', function($compileProvider) { + $compileProvider.debugInfoEnabled(true); + }]); + } + + modules.unshift('ng'); + var injector = createInjector(modules, config.strictDi); + injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', + function bootstrapApply(scope, element, compile, injector) { + scope.$apply(function() { + element.data('$injector', injector); + compile(element)(scope); + }); + }] + ); + return injector; + }; + + var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/; + var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/; + + if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) { + config.debugInfoEnabled = true; + window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, ''); + } + + if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) { + return doBootstrap(); + } + + window.name = window.name.replace(NG_DEFER_BOOTSTRAP, ''); + angular.resumeBootstrap = function(extraModules) { + forEach(extraModules, function(module) { + modules.push(module); + }); + return doBootstrap(); + }; + + if (isFunction(angular.resumeDeferredBootstrap)) { + angular.resumeDeferredBootstrap(); + } +} + +/** + * @ngdoc function + * @name angular.reloadWithDebugInfo + * @module ng + * @description + * Use this function to reload the current application with debug information turned on. + * This takes precedence over a call to `$compileProvider.debugInfoEnabled(false)`. + * + * See {@link ng.$compileProvider#debugInfoEnabled} for more. + */ +function reloadWithDebugInfo() { + window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name; + window.location.reload(); +} + +/** + * @name angular.getTestability + * @module ng + * @description + * Get the testability service for the instance of Angular on the given + * element. + * @param {DOMElement} element DOM element which is the root of angular application. + */ +function getTestability(rootElement) { + var injector = angular.element(rootElement).injector(); + if (!injector) { + throw ngMinErr('test', + 'no injector found for element argument to getTestability'); + } + return injector.get('$$testability'); +} + +var SNAKE_CASE_REGEXP = /[A-Z]/g; +function snake_case(name, separator) { + separator = separator || '_'; + return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) { + return (pos ? separator : '') + letter.toLowerCase(); + }); +} + +var bindJQueryFired = false; +var skipDestroyOnNextJQueryCleanData; +function bindJQuery() { + var originalCleanData; + + if (bindJQueryFired) { + return; + } + + // bind to jQuery if present; + var jqName = jq(); + jQuery = window.jQuery; // use default jQuery. + if (isDefined(jqName)) { // `ngJq` present + jQuery = jqName === null ? undefined : window[jqName]; // if empty; use jqLite. if not empty, use jQuery specified by `ngJq`. + } + + // Use jQuery if it exists with proper functionality, otherwise default to us. + // Angular 1.2+ requires jQuery 1.7+ for on()/off() support. + // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older + // versions. It will not work for sure with jQuery <1.7, though. + if (jQuery && jQuery.fn.on) { + jqLite = jQuery; + extend(jQuery.fn, { + scope: JQLitePrototype.scope, + isolateScope: JQLitePrototype.isolateScope, + controller: JQLitePrototype.controller, + injector: JQLitePrototype.injector, + inheritedData: JQLitePrototype.inheritedData + }); + + // All nodes removed from the DOM via various jQuery APIs like .remove() + // are passed through jQuery.cleanData. Monkey-patch this method to fire + // the $destroy event on all removed nodes. + originalCleanData = jQuery.cleanData; + jQuery.cleanData = function(elems) { + var events; + if (!skipDestroyOnNextJQueryCleanData) { + for (var i = 0, elem; (elem = elems[i]) != null; i++) { + events = jQuery._data(elem, "events"); + if (events && events.$destroy) { + jQuery(elem).triggerHandler('$destroy'); + } + } + } else { + skipDestroyOnNextJQueryCleanData = false; + } + originalCleanData(elems); + }; + } else { + jqLite = JQLite; + } + + angular.element = jqLite; + + // Prevent double-proxying. + bindJQueryFired = true; +} + +/** + * throw error if the argument is falsy. + */ +function assertArg(arg, name, reason) { + if (!arg) { + throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required")); + } + return arg; +} + +function assertArgFn(arg, name, acceptArrayAnnotation) { + if (acceptArrayAnnotation && isArray(arg)) { + arg = arg[arg.length - 1]; + } + + assertArg(isFunction(arg), name, 'not a function, got ' + + (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg)); + return arg; +} + +/** + * throw error if the name given is hasOwnProperty + * @param {String} name the name to test + * @param {String} context the context in which the name is used, such as module or directive + */ +function assertNotHasOwnProperty(name, context) { + if (name === 'hasOwnProperty') { + throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context); + } +} + +/** + * Return the value accessible from the object by path. Any undefined traversals are ignored + * @param {Object} obj starting object + * @param {String} path path to traverse + * @param {boolean} [bindFnToScope=true] + * @returns {Object} value as accessible by path + */ +//TODO(misko): this function needs to be removed +function getter(obj, path, bindFnToScope) { + if (!path) return obj; + var keys = path.split('.'); + var key; + var lastInstance = obj; + var len = keys.length; + + for (var i = 0; i < len; i++) { + key = keys[i]; + if (obj) { + obj = (lastInstance = obj)[key]; + } + } + if (!bindFnToScope && isFunction(obj)) { + return bind(lastInstance, obj); + } + return obj; +} + +/** + * Return the DOM siblings between the first and last node in the given array. + * @param {Array} array like object + * @returns {jqLite} jqLite collection containing the nodes + */ +function getBlockNodes(nodes) { + // TODO(perf): just check if all items in `nodes` are siblings and if they are return the original + // collection, otherwise update the original collection. + var node = nodes[0]; + var endNode = nodes[nodes.length - 1]; + var blockNodes = [node]; + + do { + node = node.nextSibling; + if (!node) break; + blockNodes.push(node); + } while (node !== endNode); + + return jqLite(blockNodes); +} + + +/** + * Creates a new object without a prototype. This object is useful for lookup without having to + * guard against prototypically inherited properties via hasOwnProperty. + * + * Related micro-benchmarks: + * - http://jsperf.com/object-create2 + * - http://jsperf.com/proto-map-lookup/2 + * - http://jsperf.com/for-in-vs-object-keys2 + * + * @returns {Object} + */ +function createMap() { + return Object.create(null); +} + +var NODE_TYPE_ELEMENT = 1; +var NODE_TYPE_ATTRIBUTE = 2; +var NODE_TYPE_TEXT = 3; +var NODE_TYPE_COMMENT = 8; +var NODE_TYPE_DOCUMENT = 9; +var NODE_TYPE_DOCUMENT_FRAGMENT = 11; + +/** + * @ngdoc type + * @name angular.Module + * @module ng + * @description + * + * Interface for configuring angular {@link angular.module modules}. + */ + +function setupModuleLoader(window) { + + var $injectorMinErr = minErr('$injector'); + var ngMinErr = minErr('ng'); + + function ensure(obj, name, factory) { + return obj[name] || (obj[name] = factory()); + } + + var angular = ensure(window, 'angular', Object); + + // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap + angular.$$minErr = angular.$$minErr || minErr; + + return ensure(angular, 'module', function() { + /** @type {Object.} */ + var modules = {}; + + /** + * @ngdoc function + * @name angular.module + * @module ng + * @description + * + * The `angular.module` is a global place for creating, registering and retrieving Angular + * modules. + * All modules (angular core or 3rd party) that should be available to an application must be + * registered using this mechanism. + * + * When passed two or more arguments, a new module is created. If passed only one argument, an + * existing module (the name passed as the first argument to `module`) is retrieved. + * + * + * # Module + * + * A module is a collection of services, directives, controllers, filters, and configuration information. + * `angular.module` is used to configure the {@link auto.$injector $injector}. + * + * ```js + * // Create a new module + * var myModule = angular.module('myModule', []); + * + * // register a new service + * myModule.value('appName', 'MyCoolApp'); + * + * // configure existing services inside initialization blocks. + * myModule.config(['$locationProvider', function($locationProvider) { + * // Configure existing providers + * $locationProvider.hashPrefix('!'); + * }]); + * ``` + * + * Then you can create an injector and load your modules like this: + * + * ```js + * var injector = angular.injector(['ng', 'myModule']) + * ``` + * + * However it's more likely that you'll just use + * {@link ng.directive:ngApp ngApp} or + * {@link angular.bootstrap} to simplify this process for you. + * + * @param {!string} name The name of the module to create or retrieve. + * @param {!Array.=} requires If specified then new module is being created. If + * unspecified then the module is being retrieved for further configuration. + * @param {Function=} configFn Optional configuration function for the module. Same as + * {@link angular.Module#config Module#config()}. + * @returns {module} new module with the {@link angular.Module} api. + */ + return function module(name, requires, configFn) { + var assertNotHasOwnProperty = function(name, context) { + if (name === 'hasOwnProperty') { + throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context); + } + }; + + assertNotHasOwnProperty(name, 'module'); + if (requires && modules.hasOwnProperty(name)) { + modules[name] = null; + } + return ensure(modules, name, function() { + if (!requires) { + throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " + + "the module name or forgot to load it. If registering a module ensure that you " + + "specify the dependencies as the second argument.", name); + } + + /** @type {!Array.>} */ + var invokeQueue = []; + + /** @type {!Array.} */ + var configBlocks = []; + + /** @type {!Array.} */ + var runBlocks = []; + + var config = invokeLater('$injector', 'invoke', 'push', configBlocks); + + /** @type {angular.Module} */ + var moduleInstance = { + // Private state + _invokeQueue: invokeQueue, + _configBlocks: configBlocks, + _runBlocks: runBlocks, + + /** + * @ngdoc property + * @name angular.Module#requires + * @module ng + * + * @description + * Holds the list of modules which the injector will load before the current module is + * loaded. + */ + requires: requires, + + /** + * @ngdoc property + * @name angular.Module#name + * @module ng + * + * @description + * Name of the module. + */ + name: name, + + + /** + * @ngdoc method + * @name angular.Module#provider + * @module ng + * @param {string} name service name + * @param {Function} providerType Construction function for creating new instance of the + * service. + * @description + * See {@link auto.$provide#provider $provide.provider()}. + */ + provider: invokeLater('$provide', 'provider'), + + /** + * @ngdoc method + * @name angular.Module#factory + * @module ng + * @param {string} name service name + * @param {Function} providerFunction Function for creating new instance of the service. + * @description + * See {@link auto.$provide#factory $provide.factory()}. + */ + factory: invokeLater('$provide', 'factory'), + + /** + * @ngdoc method + * @name angular.Module#service + * @module ng + * @param {string} name service name + * @param {Function} constructor A constructor function that will be instantiated. + * @description + * See {@link auto.$provide#service $provide.service()}. + */ + service: invokeLater('$provide', 'service'), + + /** + * @ngdoc method + * @name angular.Module#value + * @module ng + * @param {string} name service name + * @param {*} object Service instance object. + * @description + * See {@link auto.$provide#value $provide.value()}. + */ + value: invokeLater('$provide', 'value'), + + /** + * @ngdoc method + * @name angular.Module#constant + * @module ng + * @param {string} name constant name + * @param {*} object Constant value. + * @description + * Because the constant are fixed, they get applied before other provide methods. + * See {@link auto.$provide#constant $provide.constant()}. + */ + constant: invokeLater('$provide', 'constant', 'unshift'), + + /** + * @ngdoc method + * @name angular.Module#decorator + * @module ng + * @param {string} The name of the service to decorate. + * @param {Function} This function will be invoked when the service needs to be + * instantiated and should return the decorated service instance. + * @description + * See {@link auto.$provide#decorator $provide.decorator()}. + */ + decorator: invokeLater('$provide', 'decorator'), + + /** + * @ngdoc method + * @name angular.Module#animation + * @module ng + * @param {string} name animation name + * @param {Function} animationFactory Factory function for creating new instance of an + * animation. + * @description + * + * **NOTE**: animations take effect only if the **ngAnimate** module is loaded. + * + * + * Defines an animation hook that can be later used with + * {@link $animate $animate} service and directives that use this service. + * + * ```js + * module.animation('.animation-name', function($inject1, $inject2) { + * return { + * eventName : function(element, done) { + * //code to run the animation + * //once complete, then run done() + * return function cancellationFunction(element) { + * //code to cancel the animation + * } + * } + * } + * }) + * ``` + * + * See {@link ng.$animateProvider#register $animateProvider.register()} and + * {@link ngAnimate ngAnimate module} for more information. + */ + animation: invokeLater('$animateProvider', 'register'), + + /** + * @ngdoc method + * @name angular.Module#filter + * @module ng + * @param {string} name Filter name - this must be a valid angular expression identifier + * @param {Function} filterFactory Factory function for creating new instance of filter. + * @description + * See {@link ng.$filterProvider#register $filterProvider.register()}. + * + *
      + * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`. + * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace + * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores + * (`myapp_subsection_filterx`). + *
      + */ + filter: invokeLater('$filterProvider', 'register'), + + /** + * @ngdoc method + * @name angular.Module#controller + * @module ng + * @param {string|Object} name Controller name, or an object map of controllers where the + * keys are the names and the values are the constructors. + * @param {Function} constructor Controller constructor function. + * @description + * See {@link ng.$controllerProvider#register $controllerProvider.register()}. + */ + controller: invokeLater('$controllerProvider', 'register'), + + /** + * @ngdoc method + * @name angular.Module#directive + * @module ng + * @param {string|Object} name Directive name, or an object map of directives where the + * keys are the names and the values are the factories. + * @param {Function} directiveFactory Factory function for creating new instance of + * directives. + * @description + * See {@link ng.$compileProvider#directive $compileProvider.directive()}. + */ + directive: invokeLater('$compileProvider', 'directive'), + + /** + * @ngdoc method + * @name angular.Module#config + * @module ng + * @param {Function} configFn Execute this function on module load. Useful for service + * configuration. + * @description + * Use this method to register work which needs to be performed on module loading. + * For more about how to configure services, see + * {@link providers#provider-recipe Provider Recipe}. + */ + config: config, + + /** + * @ngdoc method + * @name angular.Module#run + * @module ng + * @param {Function} initializationFn Execute this function after injector creation. + * Useful for application initialization. + * @description + * Use this method to register work which should be performed when the injector is done + * loading all modules. + */ + run: function(block) { + runBlocks.push(block); + return this; + } + }; + + if (configFn) { + config(configFn); + } + + return moduleInstance; + + /** + * @param {string} provider + * @param {string} method + * @param {String=} insertMethod + * @returns {angular.Module} + */ + function invokeLater(provider, method, insertMethod, queue) { + if (!queue) queue = invokeQueue; + return function() { + queue[insertMethod || 'push']([provider, method, arguments]); + return moduleInstance; + }; + } + }); + }; + }); + +} + +/* global: toDebugString: true */ + +function serializeObject(obj) { + var seen = []; + + return JSON.stringify(obj, function(key, val) { + val = toJsonReplacer(key, val); + if (isObject(val)) { + + if (seen.indexOf(val) >= 0) return '<>'; + + seen.push(val); + } + return val; + }); +} + +function toDebugString(obj) { + if (typeof obj === 'function') { + return obj.toString().replace(/ \{[\s\S]*$/, ''); + } else if (typeof obj === 'undefined') { + return 'undefined'; + } else if (typeof obj !== 'string') { + return serializeObject(obj); + } + return obj; +} + +/* global angularModule: true, + version: true, + + $LocaleProvider, + $CompileProvider, + + htmlAnchorDirective, + inputDirective, + inputDirective, + formDirective, + scriptDirective, + selectDirective, + styleDirective, + optionDirective, + ngBindDirective, + ngBindHtmlDirective, + ngBindTemplateDirective, + ngClassDirective, + ngClassEvenDirective, + ngClassOddDirective, + ngCspDirective, + ngCloakDirective, + ngControllerDirective, + ngFormDirective, + ngHideDirective, + ngIfDirective, + ngIncludeDirective, + ngIncludeFillContentDirective, + ngInitDirective, + ngNonBindableDirective, + ngPluralizeDirective, + ngRepeatDirective, + ngShowDirective, + ngStyleDirective, + ngSwitchDirective, + ngSwitchWhenDirective, + ngSwitchDefaultDirective, + ngOptionsDirective, + ngTranscludeDirective, + ngModelDirective, + ngListDirective, + ngChangeDirective, + patternDirective, + patternDirective, + requiredDirective, + requiredDirective, + minlengthDirective, + minlengthDirective, + maxlengthDirective, + maxlengthDirective, + ngValueDirective, + ngModelOptionsDirective, + ngAttributeAliasDirectives, + ngEventDirectives, + + $AnchorScrollProvider, + $AnimateProvider, + $$CoreAnimateQueueProvider, + $$CoreAnimateRunnerProvider, + $BrowserProvider, + $CacheFactoryProvider, + $ControllerProvider, + $DocumentProvider, + $ExceptionHandlerProvider, + $FilterProvider, + $InterpolateProvider, + $IntervalProvider, + $$HashMapProvider, + $HttpProvider, + $HttpParamSerializerProvider, + $HttpParamSerializerJQLikeProvider, + $HttpBackendProvider, + $LocationProvider, + $LogProvider, + $ParseProvider, + $RootScopeProvider, + $QProvider, + $$QProvider, + $$SanitizeUriProvider, + $SceProvider, + $SceDelegateProvider, + $SnifferProvider, + $TemplateCacheProvider, + $TemplateRequestProvider, + $$TestabilityProvider, + $TimeoutProvider, + $$RAFProvider, + $$AsyncCallbackProvider, + $WindowProvider, + $$jqLiteProvider, + $$CookieReaderProvider +*/ + + +/** + * @ngdoc object + * @name angular.version + * @module ng + * @description + * An object that contains information about the current AngularJS version. This object has the + * following properties: + * + * - `full` – `{string}` – Full version string, such as "0.9.18". + * - `major` – `{number}` – Major version number, such as "0". + * - `minor` – `{number}` – Minor version number, such as "9". + * - `dot` – `{number}` – Dot version number, such as "18". + * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat". + */ +var version = { + full: '1.4.0', // all of these placeholder strings will be replaced by grunt's + major: 1, // package task + minor: 4, + dot: 0, + codeName: 'jaracimrman-existence' +}; + + +function publishExternalAPI(angular) { + extend(angular, { + 'bootstrap': bootstrap, + 'copy': copy, + 'extend': extend, + 'merge': merge, + 'equals': equals, + 'element': jqLite, + 'forEach': forEach, + 'injector': createInjector, + 'noop': noop, + 'bind': bind, + 'toJson': toJson, + 'fromJson': fromJson, + 'identity': identity, + 'isUndefined': isUndefined, + 'isDefined': isDefined, + 'isString': isString, + 'isFunction': isFunction, + 'isObject': isObject, + 'isNumber': isNumber, + 'isElement': isElement, + 'isArray': isArray, + 'version': version, + 'isDate': isDate, + 'lowercase': lowercase, + 'uppercase': uppercase, + 'callbacks': {counter: 0}, + 'getTestability': getTestability, + '$$minErr': minErr, + '$$csp': csp, + 'reloadWithDebugInfo': reloadWithDebugInfo + }); + + angularModule = setupModuleLoader(window); + try { + angularModule('ngLocale'); + } catch (e) { + angularModule('ngLocale', []).provider('$locale', $LocaleProvider); + } + + angularModule('ng', ['ngLocale'], ['$provide', + function ngModule($provide) { + // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it. + $provide.provider({ + $$sanitizeUri: $$SanitizeUriProvider + }); + $provide.provider('$compile', $CompileProvider). + directive({ + a: htmlAnchorDirective, + input: inputDirective, + textarea: inputDirective, + form: formDirective, + script: scriptDirective, + select: selectDirective, + style: styleDirective, + option: optionDirective, + ngBind: ngBindDirective, + ngBindHtml: ngBindHtmlDirective, + ngBindTemplate: ngBindTemplateDirective, + ngClass: ngClassDirective, + ngClassEven: ngClassEvenDirective, + ngClassOdd: ngClassOddDirective, + ngCloak: ngCloakDirective, + ngController: ngControllerDirective, + ngForm: ngFormDirective, + ngHide: ngHideDirective, + ngIf: ngIfDirective, + ngInclude: ngIncludeDirective, + ngInit: ngInitDirective, + ngNonBindable: ngNonBindableDirective, + ngPluralize: ngPluralizeDirective, + ngRepeat: ngRepeatDirective, + ngShow: ngShowDirective, + ngStyle: ngStyleDirective, + ngSwitch: ngSwitchDirective, + ngSwitchWhen: ngSwitchWhenDirective, + ngSwitchDefault: ngSwitchDefaultDirective, + ngOptions: ngOptionsDirective, + ngTransclude: ngTranscludeDirective, + ngModel: ngModelDirective, + ngList: ngListDirective, + ngChange: ngChangeDirective, + pattern: patternDirective, + ngPattern: patternDirective, + required: requiredDirective, + ngRequired: requiredDirective, + minlength: minlengthDirective, + ngMinlength: minlengthDirective, + maxlength: maxlengthDirective, + ngMaxlength: maxlengthDirective, + ngValue: ngValueDirective, + ngModelOptions: ngModelOptionsDirective + }). + directive({ + ngInclude: ngIncludeFillContentDirective + }). + directive(ngAttributeAliasDirectives). + directive(ngEventDirectives); + $provide.provider({ + $anchorScroll: $AnchorScrollProvider, + $animate: $AnimateProvider, + $$animateQueue: $$CoreAnimateQueueProvider, + $$AnimateRunner: $$CoreAnimateRunnerProvider, + $browser: $BrowserProvider, + $cacheFactory: $CacheFactoryProvider, + $controller: $ControllerProvider, + $document: $DocumentProvider, + $exceptionHandler: $ExceptionHandlerProvider, + $filter: $FilterProvider, + $interpolate: $InterpolateProvider, + $interval: $IntervalProvider, + $http: $HttpProvider, + $httpParamSerializer: $HttpParamSerializerProvider, + $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, + $httpBackend: $HttpBackendProvider, + $location: $LocationProvider, + $log: $LogProvider, + $parse: $ParseProvider, + $rootScope: $RootScopeProvider, + $q: $QProvider, + $$q: $$QProvider, + $sce: $SceProvider, + $sceDelegate: $SceDelegateProvider, + $sniffer: $SnifferProvider, + $templateCache: $TemplateCacheProvider, + $templateRequest: $TemplateRequestProvider, + $$testability: $$TestabilityProvider, + $timeout: $TimeoutProvider, + $window: $WindowProvider, + $$rAF: $$RAFProvider, + $$asyncCallback: $$AsyncCallbackProvider, + $$jqLite: $$jqLiteProvider, + $$HashMap: $$HashMapProvider, + $$cookieReader: $$CookieReaderProvider + }); + } + ]); +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* global JQLitePrototype: true, + addEventListenerFn: true, + removeEventListenerFn: true, + BOOLEAN_ATTR: true, + ALIASED_ATTR: true, +*/ + +////////////////////////////////// +//JQLite +////////////////////////////////// + +/** + * @ngdoc function + * @name angular.element + * @module ng + * @kind function + * + * @description + * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element. + * + * If jQuery is available, `angular.element` is an alias for the + * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element` + * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite." + * + *
      jqLite is a tiny, API-compatible subset of jQuery that allows + * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most + * commonly needed functionality with the goal of having a very small footprint.
      + * + * To use `jQuery`, simply ensure it is loaded before the `angular.js` file. + * + *
      **Note:** all element references in Angular are always wrapped with jQuery or + * jqLite; they are never raw DOM references.
      + * + * ## Angular's jqLite + * jqLite provides only the following jQuery methods: + * + * - [`addClass()`](http://api.jquery.com/addClass/) + * - [`after()`](http://api.jquery.com/after/) + * - [`append()`](http://api.jquery.com/append/) + * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters + * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData + * - [`children()`](http://api.jquery.com/children/) - Does not support selectors + * - [`clone()`](http://api.jquery.com/clone/) + * - [`contents()`](http://api.jquery.com/contents/) + * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`. As a setter, does not convert numbers to strings or append 'px'. + * - [`data()`](http://api.jquery.com/data/) + * - [`detach()`](http://api.jquery.com/detach/) + * - [`empty()`](http://api.jquery.com/empty/) + * - [`eq()`](http://api.jquery.com/eq/) + * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name + * - [`hasClass()`](http://api.jquery.com/hasClass/) + * - [`html()`](http://api.jquery.com/html/) + * - [`next()`](http://api.jquery.com/next/) - Does not support selectors + * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData + * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors + * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors + * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors + * - [`prepend()`](http://api.jquery.com/prepend/) + * - [`prop()`](http://api.jquery.com/prop/) + * - [`ready()`](http://api.jquery.com/ready/) + * - [`remove()`](http://api.jquery.com/remove/) + * - [`removeAttr()`](http://api.jquery.com/removeAttr/) + * - [`removeClass()`](http://api.jquery.com/removeClass/) + * - [`removeData()`](http://api.jquery.com/removeData/) + * - [`replaceWith()`](http://api.jquery.com/replaceWith/) + * - [`text()`](http://api.jquery.com/text/) + * - [`toggleClass()`](http://api.jquery.com/toggleClass/) + * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers. + * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces + * - [`val()`](http://api.jquery.com/val/) + * - [`wrap()`](http://api.jquery.com/wrap/) + * + * ## jQuery/jqLite Extras + * Angular also provides the following additional methods and events to both jQuery and jqLite: + * + * ### Events + * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event + * on all DOM nodes being removed. This can be used to clean up any 3rd party bindings to the DOM + * element before it is removed. + * + * ### Methods + * - `controller(name)` - retrieves the controller of the current element or its parent. By default + * retrieves controller associated with the `ngController` directive. If `name` is provided as + * camelCase directive name, then the controller for this directive will be retrieved (e.g. + * `'ngModel'`). + * - `injector()` - retrieves the injector of the current element or its parent. + * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current + * element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to + * be enabled. + * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the + * current element. This getter should be used only on elements that contain a directive which starts a new isolate + * scope. Calling `scope()` on this element always returns the original non-isolate scope. + * Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled. + * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top + * parent element is reached. + * + * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery. + * @returns {Object} jQuery object. + */ + +JQLite.expando = 'ng339'; + +var jqCache = JQLite.cache = {}, + jqId = 1, + addEventListenerFn = function(element, type, fn) { + element.addEventListener(type, fn, false); + }, + removeEventListenerFn = function(element, type, fn) { + element.removeEventListener(type, fn, false); + }; + +/* + * !!! This is an undocumented "private" function !!! + */ +JQLite._data = function(node) { + //jQuery always returns an object on cache miss + return this.cache[node[this.expando]] || {}; +}; + +function jqNextId() { return ++jqId; } + + +var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; +var MOZ_HACK_REGEXP = /^moz([A-Z])/; +var MOUSE_EVENT_MAP= { mouseleave: "mouseout", mouseenter: "mouseover"}; +var jqLiteMinErr = minErr('jqLite'); + +/** + * Converts snake_case to camelCase. + * Also there is special case for Moz prefix starting with upper case letter. + * @param name Name to normalize + */ +function camelCase(name) { + return name. + replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { + return offset ? letter.toUpperCase() : letter; + }). + replace(MOZ_HACK_REGEXP, 'Moz$1'); +} + +var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/; +var HTML_REGEXP = /<|&#?\w+;/; +var TAG_NAME_REGEXP = /<([\w:]+)/; +var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; + +var wrapMap = { + 'option': [1, ''], + + 'thead': [1, '', '
      '], + 'col': [2, '', '
      '], + 'tr': [2, '', '
      '], + 'td': [3, '', '
      '], + '_default': [0, "", ""] +}; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + + +function jqLiteIsTextNode(html) { + return !HTML_REGEXP.test(html); +} + +function jqLiteAcceptsData(node) { + // The window object can accept data but has no nodeType + // Otherwise we are only interested in elements (1) and documents (9) + var nodeType = node.nodeType; + return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT; +} + +function jqLiteBuildFragment(html, context) { + var tmp, tag, wrap, + fragment = context.createDocumentFragment(), + nodes = [], i; + + if (jqLiteIsTextNode(html)) { + // Convert non-html into a text node + nodes.push(context.createTextNode(html)); + } else { + // Convert html into DOM nodes + tmp = tmp || fragment.appendChild(context.createElement("div")); + tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase(); + wrap = wrapMap[tag] || wrapMap._default; + tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1>") + wrap[2]; + + // Descend through wrappers to the right content + i = wrap[0]; + while (i--) { + tmp = tmp.lastChild; + } + + nodes = concat(nodes, tmp.childNodes); + + tmp = fragment.firstChild; + tmp.textContent = ""; + } + + // Remove wrapper from fragment + fragment.textContent = ""; + fragment.innerHTML = ""; // Clear inner HTML + forEach(nodes, function(node) { + fragment.appendChild(node); + }); + + return fragment; +} + +function jqLiteParseHTML(html, context) { + context = context || document; + var parsed; + + if ((parsed = SINGLE_TAG_REGEXP.exec(html))) { + return [context.createElement(parsed[1])]; + } + + if ((parsed = jqLiteBuildFragment(html, context))) { + return parsed.childNodes; + } + + return []; +} + +///////////////////////////////////////////// +function JQLite(element) { + if (element instanceof JQLite) { + return element; + } + + var argIsString; + + if (isString(element)) { + element = trim(element); + argIsString = true; + } + if (!(this instanceof JQLite)) { + if (argIsString && element.charAt(0) != '<') { + throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element'); + } + return new JQLite(element); + } + + if (argIsString) { + jqLiteAddNodes(this, jqLiteParseHTML(element)); + } else { + jqLiteAddNodes(this, element); + } +} + +function jqLiteClone(element) { + return element.cloneNode(true); +} + +function jqLiteDealoc(element, onlyDescendants) { + if (!onlyDescendants) jqLiteRemoveData(element); + + if (element.querySelectorAll) { + var descendants = element.querySelectorAll('*'); + for (var i = 0, l = descendants.length; i < l; i++) { + jqLiteRemoveData(descendants[i]); + } + } +} + +function jqLiteOff(element, type, fn, unsupported) { + if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument'); + + var expandoStore = jqLiteExpandoStore(element); + var events = expandoStore && expandoStore.events; + var handle = expandoStore && expandoStore.handle; + + if (!handle) return; //no listeners registered + + if (!type) { + for (type in events) { + if (type !== '$destroy') { + removeEventListenerFn(element, type, handle); + } + delete events[type]; + } + } else { + forEach(type.split(' '), function(type) { + if (isDefined(fn)) { + var listenerFns = events[type]; + arrayRemove(listenerFns || [], fn); + if (listenerFns && listenerFns.length > 0) { + return; + } + } + + removeEventListenerFn(element, type, handle); + delete events[type]; + }); + } +} + +function jqLiteRemoveData(element, name) { + var expandoId = element.ng339; + var expandoStore = expandoId && jqCache[expandoId]; + + if (expandoStore) { + if (name) { + delete expandoStore.data[name]; + return; + } + + if (expandoStore.handle) { + if (expandoStore.events.$destroy) { + expandoStore.handle({}, '$destroy'); + } + jqLiteOff(element); + } + delete jqCache[expandoId]; + element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it + } +} + + +function jqLiteExpandoStore(element, createIfNecessary) { + var expandoId = element.ng339, + expandoStore = expandoId && jqCache[expandoId]; + + if (createIfNecessary && !expandoStore) { + element.ng339 = expandoId = jqNextId(); + expandoStore = jqCache[expandoId] = {events: {}, data: {}, handle: undefined}; + } + + return expandoStore; +} + + +function jqLiteData(element, key, value) { + if (jqLiteAcceptsData(element)) { + + var isSimpleSetter = isDefined(value); + var isSimpleGetter = !isSimpleSetter && key && !isObject(key); + var massGetter = !key; + var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter); + var data = expandoStore && expandoStore.data; + + if (isSimpleSetter) { // data('key', value) + data[key] = value; + } else { + if (massGetter) { // data() + return data; + } else { + if (isSimpleGetter) { // data('key') + // don't force creation of expandoStore if it doesn't exist yet + return data && data[key]; + } else { // mass-setter: data({key1: val1, key2: val2}) + extend(data, key); + } + } + } + } +} + +function jqLiteHasClass(element, selector) { + if (!element.getAttribute) return false; + return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " "). + indexOf(" " + selector + " ") > -1); +} + +function jqLiteRemoveClass(element, cssClasses) { + if (cssClasses && element.setAttribute) { + forEach(cssClasses.split(' '), function(cssClass) { + element.setAttribute('class', trim( + (" " + (element.getAttribute('class') || '') + " ") + .replace(/[\n\t]/g, " ") + .replace(" " + trim(cssClass) + " ", " ")) + ); + }); + } +} + +function jqLiteAddClass(element, cssClasses) { + if (cssClasses && element.setAttribute) { + var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ') + .replace(/[\n\t]/g, " "); + + forEach(cssClasses.split(' '), function(cssClass) { + cssClass = trim(cssClass); + if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) { + existingClasses += cssClass + ' '; + } + }); + + element.setAttribute('class', trim(existingClasses)); + } +} + + +function jqLiteAddNodes(root, elements) { + // THIS CODE IS VERY HOT. Don't make changes without benchmarking. + + if (elements) { + + // if a Node (the most common case) + if (elements.nodeType) { + root[root.length++] = elements; + } else { + var length = elements.length; + + // if an Array or NodeList and not a Window + if (typeof length === 'number' && elements.window !== elements) { + if (length) { + for (var i = 0; i < length; i++) { + root[root.length++] = elements[i]; + } + } + } else { + root[root.length++] = elements; + } + } + } +} + + +function jqLiteController(element, name) { + return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller'); +} + +function jqLiteInheritedData(element, name, value) { + // if element is the document object work with the html element instead + // this makes $(document).scope() possible + if (element.nodeType == NODE_TYPE_DOCUMENT) { + element = element.documentElement; + } + var names = isArray(name) ? name : [name]; + + while (element) { + for (var i = 0, ii = names.length; i < ii; i++) { + if ((value = jqLite.data(element, names[i])) !== undefined) return value; + } + + // If dealing with a document fragment node with a host element, and no parent, use the host + // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM + // to lookup parent controllers. + element = element.parentNode || (element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host); + } +} + +function jqLiteEmpty(element) { + jqLiteDealoc(element, true); + while (element.firstChild) { + element.removeChild(element.firstChild); + } +} + +function jqLiteRemove(element, keepData) { + if (!keepData) jqLiteDealoc(element); + var parent = element.parentNode; + if (parent) parent.removeChild(element); +} + + +function jqLiteDocumentLoaded(action, win) { + win = win || window; + if (win.document.readyState === 'complete') { + // Force the action to be run async for consistent behaviour + // from the action's point of view + // i.e. it will definitely not be in a $apply + win.setTimeout(action); + } else { + // No need to unbind this handler as load is only ever called once + jqLite(win).on('load', action); + } +} + +////////////////////////////////////////// +// Functions which are declared directly. +////////////////////////////////////////// +var JQLitePrototype = JQLite.prototype = { + ready: function(fn) { + var fired = false; + + function trigger() { + if (fired) return; + fired = true; + fn(); + } + + // check if document is already loaded + if (document.readyState === 'complete') { + setTimeout(trigger); + } else { + this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9 + // we can not use jqLite since we are not done loading and jQuery could be loaded later. + // jshint -W064 + JQLite(window).on('load', trigger); // fallback to window.onload for others + // jshint +W064 + } + }, + toString: function() { + var value = []; + forEach(this, function(e) { value.push('' + e);}); + return '[' + value.join(', ') + ']'; + }, + + eq: function(index) { + return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]); + }, + + length: 0, + push: push, + sort: [].sort, + splice: [].splice +}; + +////////////////////////////////////////// +// Functions iterating getter/setters. +// these functions return self on setter and +// value on get. +////////////////////////////////////////// +var BOOLEAN_ATTR = {}; +forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) { + BOOLEAN_ATTR[lowercase(value)] = value; +}); +var BOOLEAN_ELEMENTS = {}; +forEach('input,select,option,textarea,button,form,details'.split(','), function(value) { + BOOLEAN_ELEMENTS[value] = true; +}); +var ALIASED_ATTR = { + 'ngMinlength': 'minlength', + 'ngMaxlength': 'maxlength', + 'ngMin': 'min', + 'ngMax': 'max', + 'ngPattern': 'pattern' +}; + +function getBooleanAttrName(element, name) { + // check dom last since we will most likely fail on name + var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()]; + + // booleanAttr is here twice to minimize DOM access + return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr; +} + +function getAliasedAttrName(element, name) { + var nodeName = element.nodeName; + return (nodeName === 'INPUT' || nodeName === 'TEXTAREA') && ALIASED_ATTR[name]; +} + +forEach({ + data: jqLiteData, + removeData: jqLiteRemoveData +}, function(fn, name) { + JQLite[name] = fn; +}); + +forEach({ + data: jqLiteData, + inheritedData: jqLiteInheritedData, + + scope: function(element) { + // Can't use jqLiteData here directly so we stay compatible with jQuery! + return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']); + }, + + isolateScope: function(element) { + // Can't use jqLiteData here directly so we stay compatible with jQuery! + return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate'); + }, + + controller: jqLiteController, + + injector: function(element) { + return jqLiteInheritedData(element, '$injector'); + }, + + removeAttr: function(element, name) { + element.removeAttribute(name); + }, + + hasClass: jqLiteHasClass, + + css: function(element, name, value) { + name = camelCase(name); + + if (isDefined(value)) { + element.style[name] = value; + } else { + return element.style[name]; + } + }, + + attr: function(element, name, value) { + var nodeType = element.nodeType; + if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT) { + return; + } + var lowercasedName = lowercase(name); + if (BOOLEAN_ATTR[lowercasedName]) { + if (isDefined(value)) { + if (!!value) { + element[name] = true; + element.setAttribute(name, lowercasedName); + } else { + element[name] = false; + element.removeAttribute(lowercasedName); + } + } else { + return (element[name] || + (element.attributes.getNamedItem(name) || noop).specified) + ? lowercasedName + : undefined; + } + } else if (isDefined(value)) { + element.setAttribute(name, value); + } else if (element.getAttribute) { + // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code + // some elements (e.g. Document) don't have get attribute, so return undefined + var ret = element.getAttribute(name, 2); + // normalize non-existing attributes to undefined (as jQuery) + return ret === null ? undefined : ret; + } + }, + + prop: function(element, name, value) { + if (isDefined(value)) { + element[name] = value; + } else { + return element[name]; + } + }, + + text: (function() { + getText.$dv = ''; + return getText; + + function getText(element, value) { + if (isUndefined(value)) { + var nodeType = element.nodeType; + return (nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT) ? element.textContent : ''; + } + element.textContent = value; + } + })(), + + val: function(element, value) { + if (isUndefined(value)) { + if (element.multiple && nodeName_(element) === 'select') { + var result = []; + forEach(element.options, function(option) { + if (option.selected) { + result.push(option.value || option.text); + } + }); + return result.length === 0 ? null : result; + } + return element.value; + } + element.value = value; + }, + + html: function(element, value) { + if (isUndefined(value)) { + return element.innerHTML; + } + jqLiteDealoc(element, true); + element.innerHTML = value; + }, + + empty: jqLiteEmpty +}, function(fn, name) { + /** + * Properties: writes return selection, reads return first value + */ + JQLite.prototype[name] = function(arg1, arg2) { + var i, key; + var nodeCount = this.length; + + // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it + // in a way that survives minification. + // jqLiteEmpty takes no arguments but is a setter. + if (fn !== jqLiteEmpty && + (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) { + if (isObject(arg1)) { + + // we are a write, but the object properties are the key/values + for (i = 0; i < nodeCount; i++) { + if (fn === jqLiteData) { + // data() takes the whole object in jQuery + fn(this[i], arg1); + } else { + for (key in arg1) { + fn(this[i], key, arg1[key]); + } + } + } + // return self for chaining + return this; + } else { + // we are a read, so read the first child. + // TODO: do we still need this? + var value = fn.$dv; + // Only if we have $dv do we iterate over all, otherwise it is just the first element. + var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount; + for (var j = 0; j < jj; j++) { + var nodeValue = fn(this[j], arg1, arg2); + value = value ? value + nodeValue : nodeValue; + } + return value; + } + } else { + // we are a write, so apply to all children + for (i = 0; i < nodeCount; i++) { + fn(this[i], arg1, arg2); + } + // return self for chaining + return this; + } + }; +}); + +function createEventHandler(element, events) { + var eventHandler = function(event, type) { + // jQuery specific api + event.isDefaultPrevented = function() { + return event.defaultPrevented; + }; + + var eventFns = events[type || event.type]; + var eventFnsLength = eventFns ? eventFns.length : 0; + + if (!eventFnsLength) return; + + if (isUndefined(event.immediatePropagationStopped)) { + var originalStopImmediatePropagation = event.stopImmediatePropagation; + event.stopImmediatePropagation = function() { + event.immediatePropagationStopped = true; + + if (event.stopPropagation) { + event.stopPropagation(); + } + + if (originalStopImmediatePropagation) { + originalStopImmediatePropagation.call(event); + } + }; + } + + event.isImmediatePropagationStopped = function() { + return event.immediatePropagationStopped === true; + }; + + // Copy event handlers in case event handlers array is modified during execution. + if ((eventFnsLength > 1)) { + eventFns = shallowCopy(eventFns); + } + + for (var i = 0; i < eventFnsLength; i++) { + if (!event.isImmediatePropagationStopped()) { + eventFns[i].call(element, event); + } + } + }; + + // TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all + // events on `element` + eventHandler.elem = element; + return eventHandler; +} + +////////////////////////////////////////// +// Functions iterating traversal. +// These functions chain results into a single +// selector. +////////////////////////////////////////// +forEach({ + removeData: jqLiteRemoveData, + + on: function jqLiteOn(element, type, fn, unsupported) { + if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters'); + + // Do not add event handlers to non-elements because they will not be cleaned up. + if (!jqLiteAcceptsData(element)) { + return; + } + + var expandoStore = jqLiteExpandoStore(element, true); + var events = expandoStore.events; + var handle = expandoStore.handle; + + if (!handle) { + handle = expandoStore.handle = createEventHandler(element, events); + } + + // http://jsperf.com/string-indexof-vs-split + var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type]; + var i = types.length; + + while (i--) { + type = types[i]; + var eventFns = events[type]; + + if (!eventFns) { + events[type] = []; + + if (type === 'mouseenter' || type === 'mouseleave') { + // Refer to jQuery's implementation of mouseenter & mouseleave + // Read about mouseenter and mouseleave: + // http://www.quirksmode.org/js/events_mouse.html#link8 + + jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) { + var target = this, related = event.relatedTarget; + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if (!related || (related !== target && !target.contains(related))) { + handle(event, type); + } + }); + + } else { + if (type !== '$destroy') { + addEventListenerFn(element, type, handle); + } + } + eventFns = events[type]; + } + eventFns.push(fn); + } + }, + + off: jqLiteOff, + + one: function(element, type, fn) { + element = jqLite(element); + + //add the listener twice so that when it is called + //you can remove the original function and still be + //able to call element.off(ev, fn) normally + element.on(type, function onFn() { + element.off(type, fn); + element.off(type, onFn); + }); + element.on(type, fn); + }, + + replaceWith: function(element, replaceNode) { + var index, parent = element.parentNode; + jqLiteDealoc(element); + forEach(new JQLite(replaceNode), function(node) { + if (index) { + parent.insertBefore(node, index.nextSibling); + } else { + parent.replaceChild(node, element); + } + index = node; + }); + }, + + children: function(element) { + var children = []; + forEach(element.childNodes, function(element) { + if (element.nodeType === NODE_TYPE_ELEMENT) { + children.push(element); + } + }); + return children; + }, + + contents: function(element) { + return element.contentDocument || element.childNodes || []; + }, + + append: function(element, node) { + var nodeType = element.nodeType; + if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return; + + node = new JQLite(node); + + for (var i = 0, ii = node.length; i < ii; i++) { + var child = node[i]; + element.appendChild(child); + } + }, + + prepend: function(element, node) { + if (element.nodeType === NODE_TYPE_ELEMENT) { + var index = element.firstChild; + forEach(new JQLite(node), function(child) { + element.insertBefore(child, index); + }); + } + }, + + wrap: function(element, wrapNode) { + wrapNode = jqLite(wrapNode).eq(0).clone()[0]; + var parent = element.parentNode; + if (parent) { + parent.replaceChild(wrapNode, element); + } + wrapNode.appendChild(element); + }, + + remove: jqLiteRemove, + + detach: function(element) { + jqLiteRemove(element, true); + }, + + after: function(element, newElement) { + var index = element, parent = element.parentNode; + newElement = new JQLite(newElement); + + for (var i = 0, ii = newElement.length; i < ii; i++) { + var node = newElement[i]; + parent.insertBefore(node, index.nextSibling); + index = node; + } + }, + + addClass: jqLiteAddClass, + removeClass: jqLiteRemoveClass, + + toggleClass: function(element, selector, condition) { + if (selector) { + forEach(selector.split(' '), function(className) { + var classCondition = condition; + if (isUndefined(classCondition)) { + classCondition = !jqLiteHasClass(element, className); + } + (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className); + }); + } + }, + + parent: function(element) { + var parent = element.parentNode; + return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null; + }, + + next: function(element) { + return element.nextElementSibling; + }, + + find: function(element, selector) { + if (element.getElementsByTagName) { + return element.getElementsByTagName(selector); + } else { + return []; + } + }, + + clone: jqLiteClone, + + triggerHandler: function(element, event, extraParameters) { + + var dummyEvent, eventFnsCopy, handlerArgs; + var eventName = event.type || event; + var expandoStore = jqLiteExpandoStore(element); + var events = expandoStore && expandoStore.events; + var eventFns = events && events[eventName]; + + if (eventFns) { + // Create a dummy event to pass to the handlers + dummyEvent = { + preventDefault: function() { this.defaultPrevented = true; }, + isDefaultPrevented: function() { return this.defaultPrevented === true; }, + stopImmediatePropagation: function() { this.immediatePropagationStopped = true; }, + isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; }, + stopPropagation: noop, + type: eventName, + target: element + }; + + // If a custom event was provided then extend our dummy event with it + if (event.type) { + dummyEvent = extend(dummyEvent, event); + } + + // Copy event handlers in case event handlers array is modified during execution. + eventFnsCopy = shallowCopy(eventFns); + handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent]; + + forEach(eventFnsCopy, function(fn) { + if (!dummyEvent.isImmediatePropagationStopped()) { + fn.apply(element, handlerArgs); + } + }); + } + } +}, function(fn, name) { + /** + * chaining functions + */ + JQLite.prototype[name] = function(arg1, arg2, arg3) { + var value; + + for (var i = 0, ii = this.length; i < ii; i++) { + if (isUndefined(value)) { + value = fn(this[i], arg1, arg2, arg3); + if (isDefined(value)) { + // any function which returns a value needs to be wrapped + value = jqLite(value); + } + } else { + jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3)); + } + } + return isDefined(value) ? value : this; + }; + + // bind legacy bind/unbind to on/off + JQLite.prototype.bind = JQLite.prototype.on; + JQLite.prototype.unbind = JQLite.prototype.off; +}); + + +// Provider for private $$jqLite service +function $$jqLiteProvider() { + this.$get = function $$jqLite() { + return extend(JQLite, { + hasClass: function(node, classes) { + if (node.attr) node = node[0]; + return jqLiteHasClass(node, classes); + }, + addClass: function(node, classes) { + if (node.attr) node = node[0]; + return jqLiteAddClass(node, classes); + }, + removeClass: function(node, classes) { + if (node.attr) node = node[0]; + return jqLiteRemoveClass(node, classes); + } + }); + }; +} + +/** + * Computes a hash of an 'obj'. + * Hash of a: + * string is string + * number is number as string + * object is either result of calling $$hashKey function on the object or uniquely generated id, + * that is also assigned to the $$hashKey property of the object. + * + * @param obj + * @returns {string} hash string such that the same input will have the same hash string. + * The resulting string key is in 'type:hashKey' format. + */ +function hashKey(obj, nextUidFn) { + var key = obj && obj.$$hashKey; + + if (key) { + if (typeof key === 'function') { + key = obj.$$hashKey(); + } + return key; + } + + var objType = typeof obj; + if (objType == 'function' || (objType == 'object' && obj !== null)) { + key = obj.$$hashKey = objType + ':' + (nextUidFn || nextUid)(); + } else { + key = objType + ':' + obj; + } + + return key; +} + +/** + * HashMap which can use objects as keys + */ +function HashMap(array, isolatedUid) { + if (isolatedUid) { + var uid = 0; + this.nextUid = function() { + return ++uid; + }; + } + forEach(array, this.put, this); +} +HashMap.prototype = { + /** + * Store key value pair + * @param key key to store can be any type + * @param value value to store can be any type + */ + put: function(key, value) { + this[hashKey(key, this.nextUid)] = value; + }, + + /** + * @param key + * @returns {Object} the value for the key + */ + get: function(key) { + return this[hashKey(key, this.nextUid)]; + }, + + /** + * Remove the key/value pair + * @param key + */ + remove: function(key) { + var value = this[key = hashKey(key, this.nextUid)]; + delete this[key]; + return value; + } +}; + +var $$HashMapProvider = [function() { + this.$get = [function() { + return HashMap; + }]; +}]; + +/** + * @ngdoc function + * @module ng + * @name angular.injector + * @kind function + * + * @description + * Creates an injector object that can be used for retrieving services as well as for + * dependency injection (see {@link guide/di dependency injection}). + * + * @param {Array.} modules A list of module functions or their aliases. See + * {@link angular.module}. The `ng` module must be explicitly added. + * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which + * disallows argument name annotation inference. + * @returns {injector} Injector object. See {@link auto.$injector $injector}. + * + * @example + * Typical usage + * ```js + * // create an injector + * var $injector = angular.injector(['ng']); + * + * // use the injector to kick off your application + * // use the type inference to auto inject arguments, or use implicit injection + * $injector.invoke(function($rootScope, $compile, $document) { + * $compile($document)($rootScope); + * $rootScope.$digest(); + * }); + * ``` + * + * Sometimes you want to get access to the injector of a currently running Angular app + * from outside Angular. Perhaps, you want to inject and compile some markup after the + * application has been bootstrapped. You can do this using the extra `injector()` added + * to JQuery/jqLite elements. See {@link angular.element}. + * + * *This is fairly rare but could be the case if a third party library is injecting the + * markup.* + * + * In the following example a new block of HTML containing a `ng-controller` + * directive is added to the end of the document body by JQuery. We then compile and link + * it into the current AngularJS scope. + * + * ```js + * var $div = $('
      {{content.label}}
      '); + * $(document.body).append($div); + * + * angular.element(document).injector().invoke(function($compile) { + * var scope = angular.element($div).scope(); + * $compile($div)(scope); + * }); + * ``` + */ + + +/** + * @ngdoc module + * @name auto + * @description + * + * Implicit module which gets automatically added to each {@link auto.$injector $injector}. + */ + +var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; +var FN_ARG_SPLIT = /,/; +var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; +var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; +var $injectorMinErr = minErr('$injector'); + +function anonFn(fn) { + // For anonymous functions, showing at the very least the function signature can help in + // debugging. + var fnText = fn.toString().replace(STRIP_COMMENTS, ''), + args = fnText.match(FN_ARGS); + if (args) { + return 'function(' + (args[1] || '').replace(/[\s\r\n]+/, ' ') + ')'; + } + return 'fn'; +} + +function annotate(fn, strictDi, name) { + var $inject, + fnText, + argDecl, + last; + + if (typeof fn === 'function') { + if (!($inject = fn.$inject)) { + $inject = []; + if (fn.length) { + if (strictDi) { + if (!isString(name) || !name) { + name = fn.name || anonFn(fn); + } + throw $injectorMinErr('strictdi', + '{0} is not using explicit annotation and cannot be invoked in strict mode', name); + } + fnText = fn.toString().replace(STRIP_COMMENTS, ''); + argDecl = fnText.match(FN_ARGS); + forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) { + arg.replace(FN_ARG, function(all, underscore, name) { + $inject.push(name); + }); + }); + } + fn.$inject = $inject; + } + } else if (isArray(fn)) { + last = fn.length - 1; + assertArgFn(fn[last], 'fn'); + $inject = fn.slice(0, last); + } else { + assertArgFn(fn, 'fn', true); + } + return $inject; +} + +/////////////////////////////////////// + +/** + * @ngdoc service + * @name $injector + * + * @description + * + * `$injector` is used to retrieve object instances as defined by + * {@link auto.$provide provider}, instantiate types, invoke methods, + * and load modules. + * + * The following always holds true: + * + * ```js + * var $injector = angular.injector(); + * expect($injector.get('$injector')).toBe($injector); + * expect($injector.invoke(function($injector) { + * return $injector; + * })).toBe($injector); + * ``` + * + * # Injection Function Annotation + * + * JavaScript does not have annotations, and annotations are needed for dependency injection. The + * following are all valid ways of annotating function with injection arguments and are equivalent. + * + * ```js + * // inferred (only works if code not minified/obfuscated) + * $injector.invoke(function(serviceA){}); + * + * // annotated + * function explicit(serviceA) {}; + * explicit.$inject = ['serviceA']; + * $injector.invoke(explicit); + * + * // inline + * $injector.invoke(['serviceA', function(serviceA){}]); + * ``` + * + * ## Inference + * + * In JavaScript calling `toString()` on a function returns the function definition. The definition + * can then be parsed and the function arguments can be extracted. This method of discovering + * annotations is disallowed when the injector is in strict mode. + * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the + * argument names. + * + * ## `$inject` Annotation + * By adding an `$inject` property onto a function the injection parameters can be specified. + * + * ## Inline + * As an array of injection names, where the last item in the array is the function to call. + */ + +/** + * @ngdoc method + * @name $injector#get + * + * @description + * Return an instance of the service. + * + * @param {string} name The name of the instance to retrieve. + * @param {string=} caller An optional string to provide the origin of the function call for error messages. + * @return {*} The instance. + */ + +/** + * @ngdoc method + * @name $injector#invoke + * + * @description + * Invoke the method and supply the method arguments from the `$injector`. + * + * @param {Function|Array.} fn The injectable function to invoke. Function parameters are + * injected according to the {@link guide/di $inject Annotation} rules. + * @param {Object=} self The `this` for the invoked method. + * @param {Object=} locals Optional object. If preset then any argument names are read from this + * object first, before the `$injector` is consulted. + * @returns {*} the value returned by the invoked `fn` function. + */ + +/** + * @ngdoc method + * @name $injector#has + * + * @description + * Allows the user to query if the particular service exists. + * + * @param {string} name Name of the service to query. + * @returns {boolean} `true` if injector has given service. + */ + +/** + * @ngdoc method + * @name $injector#instantiate + * @description + * Create a new instance of JS type. The method takes a constructor function, invokes the new + * operator, and supplies all of the arguments to the constructor function as specified by the + * constructor annotation. + * + * @param {Function} Type Annotated constructor function. + * @param {Object=} locals Optional object. If preset then any argument names are read from this + * object first, before the `$injector` is consulted. + * @returns {Object} new instance of `Type`. + */ + +/** + * @ngdoc method + * @name $injector#annotate + * + * @description + * Returns an array of service names which the function is requesting for injection. This API is + * used by the injector to determine which services need to be injected into the function when the + * function is invoked. There are three ways in which the function can be annotated with the needed + * dependencies. + * + * # Argument names + * + * The simplest form is to extract the dependencies from the arguments of the function. This is done + * by converting the function into a string using `toString()` method and extracting the argument + * names. + * ```js + * // Given + * function MyController($scope, $route) { + * // ... + * } + * + * // Then + * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']); + * ``` + * + * You can disallow this method by using strict injection mode. + * + * This method does not work with code minification / obfuscation. For this reason the following + * annotation strategies are supported. + * + * # The `$inject` property + * + * If a function has an `$inject` property and its value is an array of strings, then the strings + * represent names of services to be injected into the function. + * ```js + * // Given + * var MyController = function(obfuscatedScope, obfuscatedRoute) { + * // ... + * } + * // Define function dependencies + * MyController['$inject'] = ['$scope', '$route']; + * + * // Then + * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']); + * ``` + * + * # The array notation + * + * It is often desirable to inline Injected functions and that's when setting the `$inject` property + * is very inconvenient. In these situations using the array notation to specify the dependencies in + * a way that survives minification is a better choice: + * + * ```js + * // We wish to write this (not minification / obfuscation safe) + * injector.invoke(function($compile, $rootScope) { + * // ... + * }); + * + * // We are forced to write break inlining + * var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) { + * // ... + * }; + * tmpFn.$inject = ['$compile', '$rootScope']; + * injector.invoke(tmpFn); + * + * // To better support inline function the inline annotation is supported + * injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) { + * // ... + * }]); + * + * // Therefore + * expect(injector.annotate( + * ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}]) + * ).toEqual(['$compile', '$rootScope']); + * ``` + * + * @param {Function|Array.} fn Function for which dependent service names need to + * be retrieved as described above. + * + * @param {boolean=} [strictDi=false] Disallow argument name annotation inference. + * + * @returns {Array.} The names of the services which the function requires. + */ + + + + +/** + * @ngdoc service + * @name $provide + * + * @description + * + * The {@link auto.$provide $provide} service has a number of methods for registering components + * with the {@link auto.$injector $injector}. Many of these functions are also exposed on + * {@link angular.Module}. + * + * An Angular **service** is a singleton object created by a **service factory**. These **service + * factories** are functions which, in turn, are created by a **service provider**. + * The **service providers** are constructor functions. When instantiated they must contain a + * property called `$get`, which holds the **service factory** function. + * + * When you request a service, the {@link auto.$injector $injector} is responsible for finding the + * correct **service provider**, instantiating it and then calling its `$get` **service factory** + * function to get the instance of the **service**. + * + * Often services have no configuration options and there is no need to add methods to the service + * provider. The provider will be no more than a constructor function with a `$get` property. For + * these cases the {@link auto.$provide $provide} service has additional helper methods to register + * services without specifying a provider. + * + * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the + * {@link auto.$injector $injector} + * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by + * providers and services. + * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by + * services, not providers. + * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`, + * that will be wrapped in a **service provider** object, whose `$get` property will contain the + * given factory function. + * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class` + * that will be wrapped in a **service provider** object, whose `$get` property will instantiate + * a new object using the given constructor function. + * + * See the individual methods for more information and examples. + */ + +/** + * @ngdoc method + * @name $provide#provider + * @description + * + * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions + * are constructor functions, whose instances are responsible for "providing" a factory for a + * service. + * + * Service provider names start with the name of the service they provide followed by `Provider`. + * For example, the {@link ng.$log $log} service has a provider called + * {@link ng.$logProvider $logProvider}. + * + * Service provider objects can have additional methods which allow configuration of the provider + * and its service. Importantly, you can configure what kind of service is created by the `$get` + * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a + * method {@link ng.$logProvider#debugEnabled debugEnabled} + * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the + * console or not. + * + * @param {string} name The name of the instance. NOTE: the provider will be available under `name + + 'Provider'` key. + * @param {(Object|function())} provider If the provider is: + * + * - `Object`: then it should have a `$get` method. The `$get` method will be invoked using + * {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created. + * - `Constructor`: a new instance of the provider will be created using + * {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`. + * + * @returns {Object} registered provider instance + + * @example + * + * The following example shows how to create a simple event tracking service and register it using + * {@link auto.$provide#provider $provide.provider()}. + * + * ```js + * // Define the eventTracker provider + * function EventTrackerProvider() { + * var trackingUrl = '/track'; + * + * // A provider method for configuring where the tracked events should been saved + * this.setTrackingUrl = function(url) { + * trackingUrl = url; + * }; + * + * // The service factory function + * this.$get = ['$http', function($http) { + * var trackedEvents = {}; + * return { + * // Call this to track an event + * event: function(event) { + * var count = trackedEvents[event] || 0; + * count += 1; + * trackedEvents[event] = count; + * return count; + * }, + * // Call this to save the tracked events to the trackingUrl + * save: function() { + * $http.post(trackingUrl, trackedEvents); + * } + * }; + * }]; + * } + * + * describe('eventTracker', function() { + * var postSpy; + * + * beforeEach(module(function($provide) { + * // Register the eventTracker provider + * $provide.provider('eventTracker', EventTrackerProvider); + * })); + * + * beforeEach(module(function(eventTrackerProvider) { + * // Configure eventTracker provider + * eventTrackerProvider.setTrackingUrl('/custom-track'); + * })); + * + * it('tracks events', inject(function(eventTracker) { + * expect(eventTracker.event('login')).toEqual(1); + * expect(eventTracker.event('login')).toEqual(2); + * })); + * + * it('saves to the tracking url', inject(function(eventTracker, $http) { + * postSpy = spyOn($http, 'post'); + * eventTracker.event('login'); + * eventTracker.save(); + * expect(postSpy).toHaveBeenCalled(); + * expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track'); + * expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track'); + * expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 }); + * })); + * }); + * ``` + */ + +/** + * @ngdoc method + * @name $provide#factory + * @description + * + * Register a **service factory**, which will be called to return the service instance. + * This is short for registering a service where its provider consists of only a `$get` property, + * which is the given service factory function. + * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to + * configure your service in a provider. + * + * @param {string} name The name of the instance. + * @param {Function|Array.} $getFn The injectable $getFn for the instance creation. + * Internally this is a short hand for `$provide.provider(name, {$get: $getFn})`. + * @returns {Object} registered provider instance + * + * @example + * Here is an example of registering a service + * ```js + * $provide.factory('ping', ['$http', function($http) { + * return function ping() { + * return $http.send('/ping'); + * }; + * }]); + * ``` + * You would then inject and use this service like this: + * ```js + * someModule.controller('Ctrl', ['ping', function(ping) { + * ping(); + * }]); + * ``` + */ + + +/** + * @ngdoc method + * @name $provide#service + * @description + * + * Register a **service constructor**, which will be invoked with `new` to create the service + * instance. + * This is short for registering a service where its provider's `$get` property is the service + * constructor function that will be used to instantiate the service instance. + * + * You should use {@link auto.$provide#service $provide.service(class)} if you define your service + * as a type/class. + * + * @param {string} name The name of the instance. + * @param {Function|Array.} constructor An injectable class (constructor function) + * that will be instantiated. + * @returns {Object} registered provider instance + * + * @example + * Here is an example of registering a service using + * {@link auto.$provide#service $provide.service(class)}. + * ```js + * var Ping = function($http) { + * this.$http = $http; + * }; + * + * Ping.$inject = ['$http']; + * + * Ping.prototype.send = function() { + * return this.$http.get('/ping'); + * }; + * $provide.service('ping', Ping); + * ``` + * You would then inject and use this service like this: + * ```js + * someModule.controller('Ctrl', ['ping', function(ping) { + * ping.send(); + * }]); + * ``` + */ + + +/** + * @ngdoc method + * @name $provide#value + * @description + * + * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a + * number, an array, an object or a function. This is short for registering a service where its + * provider's `$get` property is a factory function that takes no arguments and returns the **value + * service**. + * + * Value services are similar to constant services, except that they cannot be injected into a + * module configuration function (see {@link angular.Module#config}) but they can be overridden by + * an Angular + * {@link auto.$provide#decorator decorator}. + * + * @param {string} name The name of the instance. + * @param {*} value The value. + * @returns {Object} registered provider instance + * + * @example + * Here are some examples of creating value services. + * ```js + * $provide.value('ADMIN_USER', 'admin'); + * + * $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 }); + * + * $provide.value('halfOf', function(value) { + * return value / 2; + * }); + * ``` + */ + + +/** + * @ngdoc method + * @name $provide#constant + * @description + * + * Register a **constant service**, such as a string, a number, an array, an object or a function, + * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be + * injected into a module configuration function (see {@link angular.Module#config}) and it cannot + * be overridden by an Angular {@link auto.$provide#decorator decorator}. + * + * @param {string} name The name of the constant. + * @param {*} value The constant value. + * @returns {Object} registered instance + * + * @example + * Here a some examples of creating constants: + * ```js + * $provide.constant('SHARD_HEIGHT', 306); + * + * $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']); + * + * $provide.constant('double', function(value) { + * return value * 2; + * }); + * ``` + */ + + +/** + * @ngdoc method + * @name $provide#decorator + * @description + * + * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator + * intercepts the creation of a service, allowing it to override or modify the behaviour of the + * service. The object returned by the decorator may be the original service, or a new service + * object which replaces or wraps and delegates to the original service. + * + * @param {string} name The name of the service to decorate. + * @param {Function|Array.} decorator This function will be invoked when the service needs to be + * instantiated and should return the decorated service instance. The function is called using + * the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable. + * Local injection arguments: + * + * * `$delegate` - The original service instance, which can be monkey patched, configured, + * decorated or delegated to. + * + * @example + * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting + * calls to {@link ng.$log#error $log.warn()}. + * ```js + * $provide.decorator('$log', ['$delegate', function($delegate) { + * $delegate.warn = $delegate.error; + * return $delegate; + * }]); + * ``` + */ + + +function createInjector(modulesToLoad, strictDi) { + strictDi = (strictDi === true); + var INSTANTIATING = {}, + providerSuffix = 'Provider', + path = [], + loadedModules = new HashMap([], true), + providerCache = { + $provide: { + provider: supportObject(provider), + factory: supportObject(factory), + service: supportObject(service), + value: supportObject(value), + constant: supportObject(constant), + decorator: decorator + } + }, + providerInjector = (providerCache.$injector = + createInternalInjector(providerCache, function(serviceName, caller) { + if (angular.isString(caller)) { + path.push(caller); + } + throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- ')); + })), + instanceCache = {}, + instanceInjector = (instanceCache.$injector = + createInternalInjector(instanceCache, function(serviceName, caller) { + var provider = providerInjector.get(serviceName + providerSuffix, caller); + return instanceInjector.invoke(provider.$get, provider, undefined, serviceName); + })); + + + forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); }); + + return instanceInjector; + + //////////////////////////////////// + // $provider + //////////////////////////////////// + + function supportObject(delegate) { + return function(key, value) { + if (isObject(key)) { + forEach(key, reverseParams(delegate)); + } else { + return delegate(key, value); + } + }; + } + + function provider(name, provider_) { + assertNotHasOwnProperty(name, 'service'); + if (isFunction(provider_) || isArray(provider_)) { + provider_ = providerInjector.instantiate(provider_); + } + if (!provider_.$get) { + throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name); + } + return providerCache[name + providerSuffix] = provider_; + } + + function enforceReturnValue(name, factory) { + return function enforcedReturnValue() { + var result = instanceInjector.invoke(factory, this); + if (isUndefined(result)) { + throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name); + } + return result; + }; + } + + function factory(name, factoryFn, enforce) { + return provider(name, { + $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn + }); + } + + function service(name, constructor) { + return factory(name, ['$injector', function($injector) { + return $injector.instantiate(constructor); + }]); + } + + function value(name, val) { return factory(name, valueFn(val), false); } + + function constant(name, value) { + assertNotHasOwnProperty(name, 'constant'); + providerCache[name] = value; + instanceCache[name] = value; + } + + function decorator(serviceName, decorFn) { + var origProvider = providerInjector.get(serviceName + providerSuffix), + orig$get = origProvider.$get; + + origProvider.$get = function() { + var origInstance = instanceInjector.invoke(orig$get, origProvider); + return instanceInjector.invoke(decorFn, null, {$delegate: origInstance}); + }; + } + + //////////////////////////////////// + // Module Loading + //////////////////////////////////// + function loadModules(modulesToLoad) { + var runBlocks = [], moduleFn; + forEach(modulesToLoad, function(module) { + if (loadedModules.get(module)) return; + loadedModules.put(module, true); + + function runInvokeQueue(queue) { + var i, ii; + for (i = 0, ii = queue.length; i < ii; i++) { + var invokeArgs = queue[i], + provider = providerInjector.get(invokeArgs[0]); + + provider[invokeArgs[1]].apply(provider, invokeArgs[2]); + } + } + + try { + if (isString(module)) { + moduleFn = angularModule(module); + runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks); + runInvokeQueue(moduleFn._invokeQueue); + runInvokeQueue(moduleFn._configBlocks); + } else if (isFunction(module)) { + runBlocks.push(providerInjector.invoke(module)); + } else if (isArray(module)) { + runBlocks.push(providerInjector.invoke(module)); + } else { + assertArgFn(module, 'module'); + } + } catch (e) { + if (isArray(module)) { + module = module[module.length - 1]; + } + if (e.message && e.stack && e.stack.indexOf(e.message) == -1) { + // Safari & FF's stack traces don't contain error.message content + // unlike those of Chrome and IE + // So if stack doesn't contain message, we create a new string that contains both. + // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here. + /* jshint -W022 */ + e = e.message + '\n' + e.stack; + } + throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}", + module, e.stack || e.message || e); + } + }); + return runBlocks; + } + + //////////////////////////////////// + // internal Injector + //////////////////////////////////// + + function createInternalInjector(cache, factory) { + + function getService(serviceName, caller) { + if (cache.hasOwnProperty(serviceName)) { + if (cache[serviceName] === INSTANTIATING) { + throw $injectorMinErr('cdep', 'Circular dependency found: {0}', + serviceName + ' <- ' + path.join(' <- ')); + } + return cache[serviceName]; + } else { + try { + path.unshift(serviceName); + cache[serviceName] = INSTANTIATING; + return cache[serviceName] = factory(serviceName, caller); + } catch (err) { + if (cache[serviceName] === INSTANTIATING) { + delete cache[serviceName]; + } + throw err; + } finally { + path.shift(); + } + } + } + + function invoke(fn, self, locals, serviceName) { + if (typeof locals === 'string') { + serviceName = locals; + locals = null; + } + + var args = [], + $inject = createInjector.$$annotate(fn, strictDi, serviceName), + length, i, + key; + + for (i = 0, length = $inject.length; i < length; i++) { + key = $inject[i]; + if (typeof key !== 'string') { + throw $injectorMinErr('itkn', + 'Incorrect injection token! Expected service name as string, got {0}', key); + } + args.push( + locals && locals.hasOwnProperty(key) + ? locals[key] + : getService(key, serviceName) + ); + } + if (isArray(fn)) { + fn = fn[length]; + } + + // http://jsperf.com/angularjs-invoke-apply-vs-switch + // #5388 + return fn.apply(self, args); + } + + function instantiate(Type, locals, serviceName) { + // Check if Type is annotated and use just the given function at n-1 as parameter + // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]); + // Object creation: http://jsperf.com/create-constructor/2 + var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype || null); + var returnedValue = invoke(Type, instance, locals, serviceName); + + return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance; + } + + return { + invoke: invoke, + instantiate: instantiate, + get: getService, + annotate: createInjector.$$annotate, + has: function(name) { + return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name); + } + }; + } +} + +createInjector.$$annotate = annotate; + +/** + * @ngdoc provider + * @name $anchorScrollProvider + * + * @description + * Use `$anchorScrollProvider` to disable automatic scrolling whenever + * {@link ng.$location#hash $location.hash()} changes. + */ +function $AnchorScrollProvider() { + + var autoScrollingEnabled = true; + + /** + * @ngdoc method + * @name $anchorScrollProvider#disableAutoScrolling + * + * @description + * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to + * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.
      + * Use this method to disable automatic scrolling. + * + * If automatic scrolling is disabled, one must explicitly call + * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the + * current hash. + */ + this.disableAutoScrolling = function() { + autoScrollingEnabled = false; + }; + + /** + * @ngdoc service + * @name $anchorScroll + * @kind function + * @requires $window + * @requires $location + * @requires $rootScope + * + * @description + * When called, it scrolls to the element related to the specified `hash` or (if omitted) to the + * current value of {@link ng.$location#hash $location.hash()}, according to the rules specified + * in the + * [HTML5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document). + * + * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to + * match any anchor whenever it changes. This can be disabled by calling + * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}. + * + * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a + * vertical scroll-offset (either fixed or dynamic). + * + * @param {string=} hash The hash specifying the element to scroll to. If omitted, the value of + * {@link ng.$location#hash $location.hash()} will be used. + * + * @property {(number|function|jqLite)} yOffset + * If set, specifies a vertical scroll-offset. This is often useful when there are fixed + * positioned elements at the top of the page, such as navbars, headers etc. + * + * `yOffset` can be specified in various ways: + * - **number**: A fixed number of pixels to be used as offset.

      + * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return + * a number representing the offset (in pixels).

      + * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from + * the top of the page to the element's bottom will be used as offset.
      + * **Note**: The element will be taken into account only as long as its `position` is set to + * `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust + * their height and/or positioning according to the viewport's size. + * + *
      + *
      + * In order for `yOffset` to work properly, scrolling should take place on the document's root and + * not some child element. + *
      + * + * @example + + +
      + Go to bottom + You're at the bottom! +
      +
      + + angular.module('anchorScrollExample', []) + .controller('ScrollController', ['$scope', '$location', '$anchorScroll', + function ($scope, $location, $anchorScroll) { + $scope.gotoBottom = function() { + // set the location.hash to the id of + // the element you wish to scroll to. + $location.hash('bottom'); + + // call $anchorScroll() + $anchorScroll(); + }; + }]); + + + #scrollArea { + height: 280px; + overflow: auto; + } + + #bottom { + display: block; + margin-top: 2000px; + } + +
      + * + *
      + * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value). + * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details. + * + * @example + + + +
      + Anchor {{x}} of 5 +
      +
      + + angular.module('anchorScrollOffsetExample', []) + .run(['$anchorScroll', function($anchorScroll) { + $anchorScroll.yOffset = 50; // always scroll by 50 extra pixels + }]) + .controller('headerCtrl', ['$anchorScroll', '$location', '$scope', + function ($anchorScroll, $location, $scope) { + $scope.gotoAnchor = function(x) { + var newHash = 'anchor' + x; + if ($location.hash() !== newHash) { + // set the $location.hash to `newHash` and + // $anchorScroll will automatically scroll to it + $location.hash('anchor' + x); + } else { + // call $anchorScroll() explicitly, + // since $location.hash hasn't changed + $anchorScroll(); + } + }; + } + ]); + + + body { + padding-top: 50px; + } + + .anchor { + border: 2px dashed DarkOrchid; + padding: 10px 10px 200px 10px; + } + + .fixed-header { + background-color: rgba(0, 0, 0, 0.2); + height: 50px; + position: fixed; + top: 0; left: 0; right: 0; + } + + .fixed-header > a { + display: inline-block; + margin: 5px 15px; + } + +
      + */ + this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) { + var document = $window.document; + + // Helper function to get first anchor from a NodeList + // (using `Array#some()` instead of `angular#forEach()` since it's more performant + // and working in all supported browsers.) + function getFirstAnchor(list) { + var result = null; + Array.prototype.some.call(list, function(element) { + if (nodeName_(element) === 'a') { + result = element; + return true; + } + }); + return result; + } + + function getYOffset() { + + var offset = scroll.yOffset; + + if (isFunction(offset)) { + offset = offset(); + } else if (isElement(offset)) { + var elem = offset[0]; + var style = $window.getComputedStyle(elem); + if (style.position !== 'fixed') { + offset = 0; + } else { + offset = elem.getBoundingClientRect().bottom; + } + } else if (!isNumber(offset)) { + offset = 0; + } + + return offset; + } + + function scrollTo(elem) { + if (elem) { + elem.scrollIntoView(); + + var offset = getYOffset(); + + if (offset) { + // `offset` is the number of pixels we should scroll UP in order to align `elem` properly. + // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the + // top of the viewport. + // + // IF the number of pixels from the top of `elem` to the end of the page's content is less + // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some + // way down the page. + // + // This is often the case for elements near the bottom of the page. + // + // In such cases we do not need to scroll the whole `offset` up, just the difference between + // the top of the element and the offset, which is enough to align the top of `elem` at the + // desired position. + var elemTop = elem.getBoundingClientRect().top; + $window.scrollBy(0, elemTop - offset); + } + } else { + $window.scrollTo(0, 0); + } + } + + function scroll(hash) { + hash = isString(hash) ? hash : $location.hash(); + var elm; + + // empty hash, scroll to the top of the page + if (!hash) scrollTo(null); + + // element with given id + else if ((elm = document.getElementById(hash))) scrollTo(elm); + + // first anchor with given name :-D + else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm); + + // no element and hash == 'top', scroll to the top of the page + else if (hash === 'top') scrollTo(null); + } + + // does not scroll when user clicks on anchor link that is currently on + // (no url change, no $location.hash() change), browser native does scroll + if (autoScrollingEnabled) { + $rootScope.$watch(function autoScrollWatch() {return $location.hash();}, + function autoScrollWatchAction(newVal, oldVal) { + // skip the initial scroll if $location.hash is empty + if (newVal === oldVal && newVal === '') return; + + jqLiteDocumentLoaded(function() { + $rootScope.$evalAsync(scroll); + }); + }); + } + + return scroll; + }]; +} + +var $animateMinErr = minErr('$animate'); +var ELEMENT_NODE = 1; +var NG_ANIMATE_CLASSNAME = 'ng-animate'; + +function mergeClasses(a,b) { + if (!a && !b) return ''; + if (!a) return b; + if (!b) return a; + if (isArray(a)) a = a.join(' '); + if (isArray(b)) b = b.join(' '); + return a + ' ' + b; +} + +function extractElementNode(element) { + for (var i = 0; i < element.length; i++) { + var elm = element[i]; + if (elm.nodeType === ELEMENT_NODE) { + return elm; + } + } +} + +function splitClasses(classes) { + if (isString(classes)) { + classes = classes.split(' '); + } + + // Use createMap() to prevent class assumptions involving property names in + // Object.prototype + var obj = createMap(); + forEach(classes, function(klass) { + // sometimes the split leaves empty string values + // incase extra spaces were applied to the options + if (klass.length) { + obj[klass] = true; + } + }); + return obj; +} + +// if any other type of options value besides an Object value is +// passed into the $animate.method() animation then this helper code +// will be run which will ignore it. While this patch is not the +// greatest solution to this, a lot of existing plugins depend on +// $animate to either call the callback (< 1.2) or return a promise +// that can be changed. This helper function ensures that the options +// are wiped clean incase a callback function is provided. +function prepareAnimateOptions(options) { + return isObject(options) + ? options + : {}; +} + +var $$CoreAnimateRunnerProvider = function() { + this.$get = ['$q', '$$rAF', function($q, $$rAF) { + function AnimateRunner() {} + AnimateRunner.all = noop; + AnimateRunner.chain = noop; + AnimateRunner.prototype = { + end: noop, + cancel: noop, + resume: noop, + pause: noop, + complete: noop, + then: function(pass, fail) { + return $q(function(resolve) { + $$rAF(function() { + resolve(); + }); + }).then(pass, fail); + } + }; + return AnimateRunner; + }]; +}; + +// this is prefixed with Core since it conflicts with +// the animateQueueProvider defined in ngAnimate/animateQueue.js +var $$CoreAnimateQueueProvider = function() { + var postDigestQueue = new HashMap(); + var postDigestElements = []; + + this.$get = ['$$AnimateRunner', '$rootScope', + function($$AnimateRunner, $rootScope) { + return { + enabled: noop, + on: noop, + off: noop, + pin: noop, + + push: function(element, event, options, domOperation) { + domOperation && domOperation(); + + options = options || {}; + options.from && element.css(options.from); + options.to && element.css(options.to); + + if (options.addClass || options.removeClass) { + addRemoveClassesPostDigest(element, options.addClass, options.removeClass); + } + + return new $$AnimateRunner(); // jshint ignore:line + } + }; + + function addRemoveClassesPostDigest(element, add, remove) { + var data = postDigestQueue.get(element); + var classVal; + + if (!data) { + postDigestQueue.put(element, data = {}); + postDigestElements.push(element); + } + + if (add) { + forEach(add.split(' '), function(className) { + if (className) { + data[className] = true; + } + }); + } + + if (remove) { + forEach(remove.split(' '), function(className) { + if (className) { + data[className] = false; + } + }); + } + + if (postDigestElements.length > 1) return; + + $rootScope.$$postDigest(function() { + forEach(postDigestElements, function(element) { + var data = postDigestQueue.get(element); + if (data) { + var existing = splitClasses(element.attr('class')); + var toAdd = ''; + var toRemove = ''; + forEach(data, function(status, className) { + var hasClass = !!existing[className]; + if (status !== hasClass) { + if (status) { + toAdd += (toAdd.length ? ' ' : '') + className; + } else { + toRemove += (toRemove.length ? ' ' : '') + className; + } + } + }); + + forEach(element, function(elm) { + toAdd && jqLiteAddClass(elm, toAdd); + toRemove && jqLiteRemoveClass(elm, toRemove); + }); + postDigestQueue.remove(element); + } + }); + + postDigestElements.length = 0; + }); + } + }]; +}; + +/** + * @ngdoc provider + * @name $animateProvider + * + * @description + * Default implementation of $animate that doesn't perform any animations, instead just + * synchronously performs DOM updates and resolves the returned runner promise. + * + * In order to enable animations the `ngAnimate` module has to be loaded. + * + * To see the functional implementation check out `src/ngAnimate/animate.js`. + */ +var $AnimateProvider = ['$provide', function($provide) { + var provider = this; + + this.$$registeredAnimations = Object.create(null); + + /** + * @ngdoc method + * @name $animateProvider#register + * + * @description + * Registers a new injectable animation factory function. The factory function produces the + * animation object which contains callback functions for each event that is expected to be + * animated. + * + * * `eventFn`: `function(element, ... , doneFunction, options)` + * The element to animate, the `doneFunction` and the options fed into the animation. Depending + * on the type of animation additional arguments will be injected into the animation function. The + * list below explains the function signatures for the different animation methods: + * + * - setClass: function(element, addedClasses, removedClasses, doneFunction, options) + * - addClass: function(element, addedClasses, doneFunction, options) + * - removeClass: function(element, removedClasses, doneFunction, options) + * - enter, leave, move: function(element, doneFunction, options) + * - animate: function(element, fromStyles, toStyles, doneFunction, options) + * + * Make sure to trigger the `doneFunction` once the animation is fully complete. + * + * ```js + * return { + * //enter, leave, move signature + * eventFn : function(element, done, options) { + * //code to run the animation + * //once complete, then run done() + * return function endFunction(wasCancelled) { + * //code to cancel the animation + * } + * } + * } + * ``` + * + * @param {string} name The name of the animation (this is what the class-based CSS value will be compared to). + * @param {Function} factory The factory function that will be executed to return the animation + * object. + */ + this.register = function(name, factory) { + if (name && name.charAt(0) !== '.') { + throw $animateMinErr('notcsel', "Expecting class selector starting with '.' got '{0}'.", name); + } + + var key = name + '-animation'; + provider.$$registeredAnimations[name.substr(1)] = key; + $provide.factory(key, factory); + }; + + /** + * @ngdoc method + * @name $animateProvider#classNameFilter + * + * @description + * Sets and/or returns the CSS class regular expression that is checked when performing + * an animation. Upon bootstrap the classNameFilter value is not set at all and will + * therefore enable $animate to attempt to perform an animation on any element that is triggered. + * When setting the `classNameFilter` value, animations will only be performed on elements + * that successfully match the filter expression. This in turn can boost performance + * for low-powered devices as well as applications containing a lot of structural operations. + * @param {RegExp=} expression The className expression which will be checked against all animations + * @return {RegExp} The current CSS className expression value. If null then there is no expression value + */ + this.classNameFilter = function(expression) { + if (arguments.length === 1) { + this.$$classNameFilter = (expression instanceof RegExp) ? expression : null; + if (this.$$classNameFilter) { + var reservedRegex = new RegExp("(\\s+|\\/)" + NG_ANIMATE_CLASSNAME + "(\\s+|\\/)"); + if (reservedRegex.test(this.$$classNameFilter.toString())) { + throw $animateMinErr('nongcls','$animateProvider.classNameFilter(regex) prohibits accepting a regex value which matches/contains the "{0}" CSS class.', NG_ANIMATE_CLASSNAME); + + } + } + } + return this.$$classNameFilter; + }; + + this.$get = ['$$animateQueue', function($$animateQueue) { + function domInsert(element, parentElement, afterElement) { + // if for some reason the previous element was removed + // from the dom sometime before this code runs then let's + // just stick to using the parent element as the anchor + if (afterElement) { + var afterNode = extractElementNode(afterElement); + if (afterNode && !afterNode.parentNode && !afterNode.previousElementSibling) { + afterElement = null; + } + } + afterElement ? afterElement.after(element) : parentElement.prepend(element); + } + + /** + * @ngdoc service + * @name $animate + * @description The $animate service exposes a series of DOM utility methods that provide support + * for animation hooks. The default behavior is the application of DOM operations, however, + * when an animation is detected (and animations are enabled), $animate will do the heavy lifting + * to ensure that animation runs with the triggered DOM operation. + * + * By default $animate doesn't trigger an animations. This is because the `ngAnimate` module isn't + * included and only when it is active then the animation hooks that `$animate` triggers will be + * functional. Once active then all structural `ng-` directives will trigger animations as they perform + * their DOM-related operations (enter, leave and move). Other directives such as `ngClass`, + * `ngShow`, `ngHide` and `ngMessages` also provide support for animations. + * + * It is recommended that the`$animate` service is always used when executing DOM-related procedures within directives. + * + * To learn more about enabling animation support, click here to visit the + * {@link ngAnimate ngAnimate module page}. + */ + return { + // we don't call it directly since non-existant arguments may + // be interpreted as null within the sub enabled function + + /** + * + * @ngdoc method + * @name $animate#on + * @kind function + * @description Sets up an event listener to fire whenever the animation event (enter, leave, move, etc...) + * has fired on the given element or among any of its children. Once the listener is fired, the provided callback + * is fired with the following params: + * + * ```js + * $animate.on('enter', container, + * function callback(element, phase) { + * // cool we detected an enter animation within the container + * } + * ); + * ``` + * + * @param {string} event the animation event that will be captured (e.g. enter, leave, move, addClass, removeClass, etc...) + * @param {DOMElement} container the container element that will capture each of the animation events that are fired on itself + * as well as among its children + * @param {Function} callback the callback function that will be fired when the listener is triggered + * + * The arguments present in the callback function are: + * * `element` - The captured DOM element that the animation was fired on. + * * `phase` - The phase of the animation. The two possible phases are **start** (when the animation starts) and **close** (when it ends). + */ + on: $$animateQueue.on, + + /** + * + * @ngdoc method + * @name $animate#off + * @kind function + * @description Deregisters an event listener based on the event which has been associated with the provided element. This method + * can be used in three different ways depending on the arguments: + * + * ```js + * // remove all the animation event listeners listening for `enter` + * $animate.off('enter'); + * + * // remove all the animation event listeners listening for `enter` on the given element and its children + * $animate.off('enter', container); + * + * // remove the event listener function provided by `listenerFn` that is set + * // to listen for `enter` on the given `element` as well as its children + * $animate.off('enter', container, callback); + * ``` + * + * @param {string} event the animation event (e.g. enter, leave, move, addClass, removeClass, etc...) + * @param {DOMElement=} container the container element the event listener was placed on + * @param {Function=} callback the callback function that was registered as the listener + */ + off: $$animateQueue.off, + + /** + * @ngdoc method + * @name $animate#pin + * @kind function + * @description Associates the provided element with a host parent element to allow the element to be animated even if it exists + * outside of the DOM structure of the Angular application. By doing so, any animation triggered via `$animate` can be issued on the + * element despite being outside the realm of the application or within another application. Say for example if the application + * was bootstrapped on an element that is somewhere inside of the `` tag, but we wanted to allow for an element to be situated + * as a direct child of `document.body`, then this can be achieved by pinning the element via `$animate.pin(element)`. Keep in mind + * that calling `$animate.pin(element, parentElement)` will not actually insert into the DOM anywhere; it will just create the association. + * + * Note that this feature is only active when the `ngAnimate` module is used. + * + * @param {DOMElement} element the external element that will be pinned + * @param {DOMElement} parentElement the host parent element that will be associated with the external element + */ + pin: $$animateQueue.pin, + + /** + * + * @ngdoc method + * @name $animate#enabled + * @kind function + * @description Used to get and set whether animations are enabled or not on the entire application or on an element and its children. This + * function can be called in four ways: + * + * ```js + * // returns true or false + * $animate.enabled(); + * + * // changes the enabled state for all animations + * $animate.enabled(false); + * $animate.enabled(true); + * + * // returns true or false if animations are enabled for an element + * $animate.enabled(element); + * + * // changes the enabled state for an element and its children + * $animate.enabled(element, true); + * $animate.enabled(element, false); + * ``` + * + * @param {DOMElement=} element the element that will be considered for checking/setting the enabled state + * @param {boolean=} enabled whether or not the animations will be enabled for the element + * + * @return {boolean} whether or not animations are enabled + */ + enabled: $$animateQueue.enabled, + + /** + * @ngdoc method + * @name $animate#cancel + * @kind function + * @description Cancels the provided animation. + * + * @param {Promise} animationPromise The animation promise that is returned when an animation is started. + */ + cancel: function(runner) { + runner.end && runner.end(); + }, + + /** + * + * @ngdoc method + * @name $animate#enter + * @kind function + * @description Inserts the element into the DOM either after the `after` element (if provided) or + * as the first child within the `parent` element and then triggers an animation. + * A promise is returned that will be resolved during the next digest once the animation + * has completed. + * + * @param {DOMElement} element the element which will be inserted into the DOM + * @param {DOMElement} parent the parent element which will append the element as + * a child (so long as the after element is not present) + * @param {DOMElement=} after the sibling element after which the element will be appended + * @param {object=} options an optional collection of options/styles that will be applied to the element + * + * @return {Promise} the animation callback promise + */ + enter: function(element, parent, after, options) { + parent = parent && jqLite(parent); + after = after && jqLite(after); + parent = parent || after.parent(); + domInsert(element, parent, after); + return $$animateQueue.push(element, 'enter', prepareAnimateOptions(options)); + }, + + /** + * + * @ngdoc method + * @name $animate#move + * @kind function + * @description Inserts (moves) the element into its new position in the DOM either after + * the `after` element (if provided) or as the first child within the `parent` element + * and then triggers an animation. A promise is returned that will be resolved + * during the next digest once the animation has completed. + * + * @param {DOMElement} element the element which will be moved into the new DOM position + * @param {DOMElement} parent the parent element which will append the element as + * a child (so long as the after element is not present) + * @param {DOMElement=} after the sibling element after which the element will be appended + * @param {object=} options an optional collection of options/styles that will be applied to the element + * + * @return {Promise} the animation callback promise + */ + move: function(element, parent, after, options) { + parent = parent && jqLite(parent); + after = after && jqLite(after); + parent = parent || after.parent(); + domInsert(element, parent, after); + return $$animateQueue.push(element, 'move', prepareAnimateOptions(options)); + }, + + /** + * @ngdoc method + * @name $animate#leave + * @kind function + * @description Triggers an animation and then removes the element from the DOM. + * When the function is called a promise is returned that will be resolved during the next + * digest once the animation has completed. + * + * @param {DOMElement} element the element which will be removed from the DOM + * @param {object=} options an optional collection of options/styles that will be applied to the element + * + * @return {Promise} the animation callback promise + */ + leave: function(element, options) { + return $$animateQueue.push(element, 'leave', prepareAnimateOptions(options), function() { + element.remove(); + }); + }, + + /** + * @ngdoc method + * @name $animate#addClass + * @kind function + * + * @description Triggers an addClass animation surrounding the addition of the provided CSS class(es). Upon + * execution, the addClass operation will only be handled after the next digest and it will not trigger an + * animation if element already contains the CSS class or if the class is removed at a later step. + * Note that class-based animations are treated differently compared to structural animations + * (like enter, move and leave) since the CSS classes may be added/removed at different points + * depending if CSS or JavaScript animations are used. + * + * @param {DOMElement} element the element which the CSS classes will be applied to + * @param {string} className the CSS class(es) that will be added (multiple classes are separated via spaces) + * @param {object=} options an optional collection of options/styles that will be applied to the element + * + * @return {Promise} the animation callback promise + */ + addClass: function(element, className, options) { + options = prepareAnimateOptions(options); + options.addClass = mergeClasses(options.addclass, className); + return $$animateQueue.push(element, 'addClass', options); + }, + + /** + * @ngdoc method + * @name $animate#removeClass + * @kind function + * + * @description Triggers a removeClass animation surrounding the removal of the provided CSS class(es). Upon + * execution, the removeClass operation will only be handled after the next digest and it will not trigger an + * animation if element does not contain the CSS class or if the class is added at a later step. + * Note that class-based animations are treated differently compared to structural animations + * (like enter, move and leave) since the CSS classes may be added/removed at different points + * depending if CSS or JavaScript animations are used. + * + * @param {DOMElement} element the element which the CSS classes will be applied to + * @param {string} className the CSS class(es) that will be removed (multiple classes are separated via spaces) + * @param {object=} options an optional collection of options/styles that will be applied to the element + * + * @return {Promise} the animation callback promise + */ + removeClass: function(element, className, options) { + options = prepareAnimateOptions(options); + options.removeClass = mergeClasses(options.removeClass, className); + return $$animateQueue.push(element, 'removeClass', options); + }, + + /** + * @ngdoc method + * @name $animate#setClass + * @kind function + * + * @description Performs both the addition and removal of a CSS classes on an element and (during the process) + * triggers an animation surrounding the class addition/removal. Much like `$animate.addClass` and + * `$animate.removeClass`, `setClass` will only evaluate the classes being added/removed once a digest has + * passed. Note that class-based animations are treated differently compared to structural animations + * (like enter, move and leave) since the CSS classes may be added/removed at different points + * depending if CSS or JavaScript animations are used. + * + * @param {DOMElement} element the element which the CSS classes will be applied to + * @param {string} add the CSS class(es) that will be added (multiple classes are separated via spaces) + * @param {string} remove the CSS class(es) that will be removed (multiple classes are separated via spaces) + * @param {object=} options an optional collection of options/styles that will be applied to the element + * + * @return {Promise} the animation callback promise + */ + setClass: function(element, add, remove, options) { + options = prepareAnimateOptions(options); + options.addClass = mergeClasses(options.addClass, add); + options.removeClass = mergeClasses(options.removeClass, remove); + return $$animateQueue.push(element, 'setClass', options); + }, + + /** + * @ngdoc method + * @name $animate#animate + * @kind function + * + * @description Performs an inline animation on the element which applies the provided to and from CSS styles to the element. + * If any detected CSS transition, keyframe or JavaScript matches the provided className value then the animation will take + * on the provided styles. For example, if a transition animation is set for the given className then the provided from and + * to styles will be applied alongside the given transition. If a JavaScript animation is detected then the provided styles + * will be given in as function paramters into the `animate` method (or as apart of the `options` parameter). + * + * @param {DOMElement} element the element which the CSS styles will be applied to + * @param {object} from the from (starting) CSS styles that will be applied to the element and across the animation. + * @param {object} to the to (destination) CSS styles that will be applied to the element and across the animation. + * @param {string=} className an optional CSS class that will be applied to the element for the duration of the animation. If + * this value is left as empty then a CSS class of `ng-inline-animate` will be applied to the element. + * (Note that if no animation is detected then this value will not be appplied to the element.) + * @param {object=} options an optional collection of options/styles that will be applied to the element + * + * @return {Promise} the animation callback promise + */ + animate: function(element, from, to, className, options) { + options = prepareAnimateOptions(options); + options.from = options.from ? extend(options.from, from) : from; + options.to = options.to ? extend(options.to, to) : to; + + className = className || 'ng-inline-animate'; + options.tempClasses = mergeClasses(options.tempClasses, className); + return $$animateQueue.push(element, 'animate', options); + } + }; + }]; +}]; + +function $$AsyncCallbackProvider() { + this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) { + return $$rAF.supported + ? function(fn) { return $$rAF(fn); } + : function(fn) { + return $timeout(fn, 0, false); + }; + }]; +} + +/* global stripHash: true */ + +/** + * ! This is a private undocumented service ! + * + * @name $browser + * @requires $log + * @description + * This object has two goals: + * + * - hide all the global state in the browser caused by the window object + * - abstract away all the browser specific features and inconsistencies + * + * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser` + * service, which can be used for convenient testing of the application without the interaction with + * the real browser apis. + */ +/** + * @param {object} window The global window object. + * @param {object} document jQuery wrapped document. + * @param {object} $log window.console or an object with the same interface. + * @param {object} $sniffer $sniffer service + */ +function Browser(window, document, $log, $sniffer) { + var self = this, + rawDocument = document[0], + location = window.location, + history = window.history, + setTimeout = window.setTimeout, + clearTimeout = window.clearTimeout, + pendingDeferIds = {}; + + self.isMock = false; + + var outstandingRequestCount = 0; + var outstandingRequestCallbacks = []; + + // TODO(vojta): remove this temporary api + self.$$completeOutstandingRequest = completeOutstandingRequest; + self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; }; + + /** + * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks` + * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed. + */ + function completeOutstandingRequest(fn) { + try { + fn.apply(null, sliceArgs(arguments, 1)); + } finally { + outstandingRequestCount--; + if (outstandingRequestCount === 0) { + while (outstandingRequestCallbacks.length) { + try { + outstandingRequestCallbacks.pop()(); + } catch (e) { + $log.error(e); + } + } + } + } + } + + function getHash(url) { + var index = url.indexOf('#'); + return index === -1 ? '' : url.substr(index + 1); + } + + /** + * @private + * Note: this method is used only by scenario runner + * TODO(vojta): prefix this method with $$ ? + * @param {function()} callback Function that will be called when no outstanding request + */ + self.notifyWhenNoOutstandingRequests = function(callback) { + if (outstandingRequestCount === 0) { + callback(); + } else { + outstandingRequestCallbacks.push(callback); + } + }; + + ////////////////////////////////////////////////////////////// + // URL API + ////////////////////////////////////////////////////////////// + + var cachedState, lastHistoryState, + lastBrowserUrl = location.href, + baseElement = document.find('base'), + reloadLocation = null; + + cacheState(); + lastHistoryState = cachedState; + + /** + * @name $browser#url + * + * @description + * GETTER: + * Without any argument, this method just returns current value of location.href. + * + * SETTER: + * With at least one argument, this method sets url to new value. + * If html5 history api supported, pushState/replaceState is used, otherwise + * location.href/location.replace is used. + * Returns its own instance to allow chaining + * + * NOTE: this api is intended for use only by the $location service. Please use the + * {@link ng.$location $location service} to change url. + * + * @param {string} url New url (when used as setter) + * @param {boolean=} replace Should new url replace current history record? + * @param {object=} state object to use with pushState/replaceState + */ + self.url = function(url, replace, state) { + // In modern browsers `history.state` is `null` by default; treating it separately + // from `undefined` would cause `$browser.url('/foo')` to change `history.state` + // to undefined via `pushState`. Instead, let's change `undefined` to `null` here. + if (isUndefined(state)) { + state = null; + } + + // Android Browser BFCache causes location, history reference to become stale. + if (location !== window.location) location = window.location; + if (history !== window.history) history = window.history; + + // setter + if (url) { + var sameState = lastHistoryState === state; + + // Don't change anything if previous and current URLs and states match. This also prevents + // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode. + // See https://github.com/angular/angular.js/commit/ffb2701 + if (lastBrowserUrl === url && (!$sniffer.history || sameState)) { + return self; + } + var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url); + lastBrowserUrl = url; + lastHistoryState = state; + // Don't use history API if only the hash changed + // due to a bug in IE10/IE11 which leads + // to not firing a `hashchange` nor `popstate` event + // in some cases (see #9143). + if ($sniffer.history && (!sameBase || !sameState)) { + history[replace ? 'replaceState' : 'pushState'](state, '', url); + cacheState(); + // Do the assignment again so that those two variables are referentially identical. + lastHistoryState = cachedState; + } else { + if (!sameBase) { + reloadLocation = url; + } + if (replace) { + location.replace(url); + } else if (!sameBase) { + location.href = url; + } else { + location.hash = getHash(url); + } + } + return self; + // getter + } else { + // - reloadLocation is needed as browsers don't allow to read out + // the new location.href if a reload happened. + // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172 + return reloadLocation || location.href.replace(/%27/g,"'"); + } + }; + + /** + * @name $browser#state + * + * @description + * This method is a getter. + * + * Return history.state or null if history.state is undefined. + * + * @returns {object} state + */ + self.state = function() { + return cachedState; + }; + + var urlChangeListeners = [], + urlChangeInit = false; + + function cacheStateAndFireUrlChange() { + cacheState(); + fireUrlChange(); + } + + function getCurrentState() { + try { + return history.state; + } catch (e) { + // MSIE can reportedly throw when there is no state (UNCONFIRMED). + } + } + + // This variable should be used *only* inside the cacheState function. + var lastCachedState = null; + function cacheState() { + // This should be the only place in $browser where `history.state` is read. + cachedState = getCurrentState(); + cachedState = isUndefined(cachedState) ? null : cachedState; + + // Prevent callbacks fo fire twice if both hashchange & popstate were fired. + if (equals(cachedState, lastCachedState)) { + cachedState = lastCachedState; + } + lastCachedState = cachedState; + } + + function fireUrlChange() { + if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) { + return; + } + + lastBrowserUrl = self.url(); + lastHistoryState = cachedState; + forEach(urlChangeListeners, function(listener) { + listener(self.url(), cachedState); + }); + } + + /** + * @name $browser#onUrlChange + * + * @description + * Register callback function that will be called, when url changes. + * + * It's only called when the url is changed from outside of angular: + * - user types different url into address bar + * - user clicks on history (forward/back) button + * - user clicks on a link + * + * It's not called when url is changed by $browser.url() method + * + * The listener gets called with new url as parameter. + * + * NOTE: this api is intended for use only by the $location service. Please use the + * {@link ng.$location $location service} to monitor url changes in angular apps. + * + * @param {function(string)} listener Listener function to be called when url changes. + * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous. + */ + self.onUrlChange = function(callback) { + // TODO(vojta): refactor to use node's syntax for events + if (!urlChangeInit) { + // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera) + // don't fire popstate when user change the address bar and don't fire hashchange when url + // changed by push/replaceState + + // html5 history api - popstate event + if ($sniffer.history) jqLite(window).on('popstate', cacheStateAndFireUrlChange); + // hashchange event + jqLite(window).on('hashchange', cacheStateAndFireUrlChange); + + urlChangeInit = true; + } + + urlChangeListeners.push(callback); + return callback; + }; + + /** + * @private + * Remove popstate and hashchange handler from window. + * + * NOTE: this api is intended for use only by $rootScope. + */ + self.$$applicationDestroyed = function() { + jqLite(window).off('hashchange popstate', cacheStateAndFireUrlChange); + }; + + /** + * Checks whether the url has changed outside of Angular. + * Needs to be exported to be able to check for changes that have been done in sync, + * as hashchange/popstate events fire in async. + */ + self.$$checkUrlChange = fireUrlChange; + + ////////////////////////////////////////////////////////////// + // Misc API + ////////////////////////////////////////////////////////////// + + /** + * @name $browser#baseHref + * + * @description + * Returns current + * (always relative - without domain) + * + * @returns {string} The current base href + */ + self.baseHref = function() { + var href = baseElement.attr('href'); + return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : ''; + }; + + /** + * @name $browser#defer + * @param {function()} fn A function, who's execution should be deferred. + * @param {number=} [delay=0] of milliseconds to defer the function execution. + * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`. + * + * @description + * Executes a fn asynchronously via `setTimeout(fn, delay)`. + * + * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using + * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed + * via `$browser.defer.flush()`. + * + */ + self.defer = function(fn, delay) { + var timeoutId; + outstandingRequestCount++; + timeoutId = setTimeout(function() { + delete pendingDeferIds[timeoutId]; + completeOutstandingRequest(fn); + }, delay || 0); + pendingDeferIds[timeoutId] = true; + return timeoutId; + }; + + + /** + * @name $browser#defer.cancel + * + * @description + * Cancels a deferred task identified with `deferId`. + * + * @param {*} deferId Token returned by the `$browser.defer` function. + * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully + * canceled. + */ + self.defer.cancel = function(deferId) { + if (pendingDeferIds[deferId]) { + delete pendingDeferIds[deferId]; + clearTimeout(deferId); + completeOutstandingRequest(noop); + return true; + } + return false; + }; + +} + +function $BrowserProvider() { + this.$get = ['$window', '$log', '$sniffer', '$document', + function($window, $log, $sniffer, $document) { + return new Browser($window, $document, $log, $sniffer); + }]; +} + +/** + * @ngdoc service + * @name $cacheFactory + * + * @description + * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to + * them. + * + * ```js + * + * var cache = $cacheFactory('cacheId'); + * expect($cacheFactory.get('cacheId')).toBe(cache); + * expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined(); + * + * cache.put("key", "value"); + * cache.put("another key", "another value"); + * + * // We've specified no options on creation + * expect(cache.info()).toEqual({id: 'cacheId', size: 2}); + * + * ``` + * + * + * @param {string} cacheId Name or id of the newly created cache. + * @param {object=} options Options object that specifies the cache behavior. Properties: + * + * - `{number=}` `capacity` — turns the cache into LRU cache. + * + * @returns {object} Newly created cache object with the following set of methods: + * + * - `{object}` `info()` — Returns id, size, and options of cache. + * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns + * it. + * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss. + * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache. + * - `{void}` `removeAll()` — Removes all cached values. + * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory. + * + * @example + + +
      + + + + +

      Cached Values

      +
      + + : + +
      + +

      Cache Info

      +
      + + : + +
      +
      +
      + + angular.module('cacheExampleApp', []). + controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) { + $scope.keys = []; + $scope.cache = $cacheFactory('cacheId'); + $scope.put = function(key, value) { + if ($scope.cache.get(key) === undefined) { + $scope.keys.push(key); + } + $scope.cache.put(key, value === undefined ? null : value); + }; + }]); + + + p { + margin: 10px 0 3px; + } + +
      + */ +function $CacheFactoryProvider() { + + this.$get = function() { + var caches = {}; + + function cacheFactory(cacheId, options) { + if (cacheId in caches) { + throw minErr('$cacheFactory')('iid', "CacheId '{0}' is already taken!", cacheId); + } + + var size = 0, + stats = extend({}, options, {id: cacheId}), + data = {}, + capacity = (options && options.capacity) || Number.MAX_VALUE, + lruHash = {}, + freshEnd = null, + staleEnd = null; + + /** + * @ngdoc type + * @name $cacheFactory.Cache + * + * @description + * A cache object used to store and retrieve data, primarily used by + * {@link $http $http} and the {@link ng.directive:script script} directive to cache + * templates and other data. + * + * ```js + * angular.module('superCache') + * .factory('superCache', ['$cacheFactory', function($cacheFactory) { + * return $cacheFactory('super-cache'); + * }]); + * ``` + * + * Example test: + * + * ```js + * it('should behave like a cache', inject(function(superCache) { + * superCache.put('key', 'value'); + * superCache.put('another key', 'another value'); + * + * expect(superCache.info()).toEqual({ + * id: 'super-cache', + * size: 2 + * }); + * + * superCache.remove('another key'); + * expect(superCache.get('another key')).toBeUndefined(); + * + * superCache.removeAll(); + * expect(superCache.info()).toEqual({ + * id: 'super-cache', + * size: 0 + * }); + * })); + * ``` + */ + return caches[cacheId] = { + + /** + * @ngdoc method + * @name $cacheFactory.Cache#put + * @kind function + * + * @description + * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be + * retrieved later, and incrementing the size of the cache if the key was not already + * present in the cache. If behaving like an LRU cache, it will also remove stale + * entries from the set. + * + * It will not insert undefined values into the cache. + * + * @param {string} key the key under which the cached data is stored. + * @param {*} value the value to store alongside the key. If it is undefined, the key + * will not be stored. + * @returns {*} the value stored. + */ + put: function(key, value) { + if (isUndefined(value)) return; + if (capacity < Number.MAX_VALUE) { + var lruEntry = lruHash[key] || (lruHash[key] = {key: key}); + + refresh(lruEntry); + } + + if (!(key in data)) size++; + data[key] = value; + + if (size > capacity) { + this.remove(staleEnd.key); + } + + return value; + }, + + /** + * @ngdoc method + * @name $cacheFactory.Cache#get + * @kind function + * + * @description + * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object. + * + * @param {string} key the key of the data to be retrieved + * @returns {*} the value stored. + */ + get: function(key) { + if (capacity < Number.MAX_VALUE) { + var lruEntry = lruHash[key]; + + if (!lruEntry) return; + + refresh(lruEntry); + } + + return data[key]; + }, + + + /** + * @ngdoc method + * @name $cacheFactory.Cache#remove + * @kind function + * + * @description + * Removes an entry from the {@link $cacheFactory.Cache Cache} object. + * + * @param {string} key the key of the entry to be removed + */ + remove: function(key) { + if (capacity < Number.MAX_VALUE) { + var lruEntry = lruHash[key]; + + if (!lruEntry) return; + + if (lruEntry == freshEnd) freshEnd = lruEntry.p; + if (lruEntry == staleEnd) staleEnd = lruEntry.n; + link(lruEntry.n,lruEntry.p); + + delete lruHash[key]; + } + + delete data[key]; + size--; + }, + + + /** + * @ngdoc method + * @name $cacheFactory.Cache#removeAll + * @kind function + * + * @description + * Clears the cache object of any entries. + */ + removeAll: function() { + data = {}; + size = 0; + lruHash = {}; + freshEnd = staleEnd = null; + }, + + + /** + * @ngdoc method + * @name $cacheFactory.Cache#destroy + * @kind function + * + * @description + * Destroys the {@link $cacheFactory.Cache Cache} object entirely, + * removing it from the {@link $cacheFactory $cacheFactory} set. + */ + destroy: function() { + data = null; + stats = null; + lruHash = null; + delete caches[cacheId]; + }, + + + /** + * @ngdoc method + * @name $cacheFactory.Cache#info + * @kind function + * + * @description + * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}. + * + * @returns {object} an object with the following properties: + *
        + *
      • **id**: the id of the cache instance
      • + *
      • **size**: the number of entries kept in the cache instance
      • + *
      • **...**: any additional properties from the options object when creating the + * cache.
      • + *
      + */ + info: function() { + return extend({}, stats, {size: size}); + } + }; + + + /** + * makes the `entry` the freshEnd of the LRU linked list + */ + function refresh(entry) { + if (entry != freshEnd) { + if (!staleEnd) { + staleEnd = entry; + } else if (staleEnd == entry) { + staleEnd = entry.n; + } + + link(entry.n, entry.p); + link(entry, freshEnd); + freshEnd = entry; + freshEnd.n = null; + } + } + + + /** + * bidirectionally links two entries of the LRU linked list + */ + function link(nextEntry, prevEntry) { + if (nextEntry != prevEntry) { + if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify + if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify + } + } + } + + + /** + * @ngdoc method + * @name $cacheFactory#info + * + * @description + * Get information about all the caches that have been created + * + * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info` + */ + cacheFactory.info = function() { + var info = {}; + forEach(caches, function(cache, cacheId) { + info[cacheId] = cache.info(); + }); + return info; + }; + + + /** + * @ngdoc method + * @name $cacheFactory#get + * + * @description + * Get access to a cache object by the `cacheId` used when it was created. + * + * @param {string} cacheId Name or id of a cache to access. + * @returns {object} Cache object identified by the cacheId or undefined if no such cache. + */ + cacheFactory.get = function(cacheId) { + return caches[cacheId]; + }; + + + return cacheFactory; + }; +} + +/** + * @ngdoc service + * @name $templateCache + * + * @description + * The first time a template is used, it is loaded in the template cache for quick retrieval. You + * can load templates directly into the cache in a `script` tag, or by consuming the + * `$templateCache` service directly. + * + * Adding via the `script` tag: + * + * ```html + * + * ``` + * + * **Note:** the `script` tag containing the template does not need to be included in the `head` of + * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE, + * element with ng-app attribute), otherwise the template will be ignored. + * + * Adding via the `$templateCache` service: + * + * ```js + * var myApp = angular.module('myApp', []); + * myApp.run(function($templateCache) { + * $templateCache.put('templateId.html', 'This is the content of the template'); + * }); + * ``` + * + * To retrieve the template later, simply use it in your HTML: + * ```html + *
      + * ``` + * + * or get it via Javascript: + * ```js + * $templateCache.get('templateId.html') + * ``` + * + * See {@link ng.$cacheFactory $cacheFactory}. + * + */ +function $TemplateCacheProvider() { + this.$get = ['$cacheFactory', function($cacheFactory) { + return $cacheFactory('templates'); + }]; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE! + * + * DOM-related variables: + * + * - "node" - DOM Node + * - "element" - DOM Element or Node + * - "$node" or "$element" - jqLite-wrapped node or element + * + * + * Compiler related stuff: + * + * - "linkFn" - linking fn of a single directive + * - "nodeLinkFn" - function that aggregates all linking fns for a particular node + * - "childLinkFn" - function that aggregates all linking fns for child nodes of a particular node + * - "compositeLinkFn" - function that aggregates all linking fns for a compilation root (nodeList) + */ + + +/** + * @ngdoc service + * @name $compile + * @kind function + * + * @description + * Compiles an HTML string or DOM into a template and produces a template function, which + * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together. + * + * The compilation is a process of walking the DOM tree and matching DOM elements to + * {@link ng.$compileProvider#directive directives}. + * + *
      + * **Note:** This document is an in-depth reference of all directive options. + * For a gentle introduction to directives with examples of common use cases, + * see the {@link guide/directive directive guide}. + *
      + * + * ## Comprehensive Directive API + * + * There are many different options for a directive. + * + * The difference resides in the return value of the factory function. + * You can either return a "Directive Definition Object" (see below) that defines the directive properties, + * or just the `postLink` function (all other properties will have the default values). + * + *
      + * **Best Practice:** It's recommended to use the "directive definition object" form. + *
      + * + * Here's an example directive declared with a Directive Definition Object: + * + * ```js + * var myModule = angular.module(...); + * + * myModule.directive('directiveName', function factory(injectables) { + * var directiveDefinitionObject = { + * priority: 0, + * template: '
      ', // or // function(tElement, tAttrs) { ... }, + * // or + * // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... }, + * transclude: false, + * restrict: 'A', + * templateNamespace: 'html', + * scope: false, + * controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... }, + * controllerAs: 'stringIdentifier', + * bindToController: false, + * require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'], + * compile: function compile(tElement, tAttrs, transclude) { + * return { + * pre: function preLink(scope, iElement, iAttrs, controller) { ... }, + * post: function postLink(scope, iElement, iAttrs, controller) { ... } + * } + * // or + * // return function postLink( ... ) { ... } + * }, + * // or + * // link: { + * // pre: function preLink(scope, iElement, iAttrs, controller) { ... }, + * // post: function postLink(scope, iElement, iAttrs, controller) { ... } + * // } + * // or + * // link: function postLink( ... ) { ... } + * }; + * return directiveDefinitionObject; + * }); + * ``` + * + *
      + * **Note:** Any unspecified options will use the default value. You can see the default values below. + *
      + * + * Therefore the above can be simplified as: + * + * ```js + * var myModule = angular.module(...); + * + * myModule.directive('directiveName', function factory(injectables) { + * var directiveDefinitionObject = { + * link: function postLink(scope, iElement, iAttrs) { ... } + * }; + * return directiveDefinitionObject; + * // or + * // return function postLink(scope, iElement, iAttrs) { ... } + * }); + * ``` + * + * + * + * ### Directive Definition Object + * + * The directive definition object provides instructions to the {@link ng.$compile + * compiler}. The attributes are: + * + * #### `multiElement` + * When this property is set to true, the HTML compiler will collect DOM nodes between + * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them + * together as the directive elements. It is recommended that this feature be used on directives + * which are not strictly behavioural (such as {@link ngClick}), and which + * do not manipulate or replace child nodes (such as {@link ngInclude}). + * + * #### `priority` + * When there are multiple directives defined on a single DOM element, sometimes it + * is necessary to specify the order in which the directives are applied. The `priority` is used + * to sort the directives before their `compile` functions get called. Priority is defined as a + * number. Directives with greater numerical `priority` are compiled first. Pre-link functions + * are also run in priority order, but post-link functions are run in reverse order. The order + * of directives with the same priority is undefined. The default priority is `0`. + * + * #### `terminal` + * If set to true then the current `priority` will be the last set of directives + * which will execute (any directives at the current priority will still execute + * as the order of execution on same `priority` is undefined). Note that expressions + * and other directives used in the directive's template will also be excluded from execution. + * + * #### `scope` + * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the + * same element request a new scope, only one new scope is created. The new scope rule does not + * apply for the root of the template since the root of the template always gets a new scope. + * + * **If set to `{}` (object hash),** then a new "isolate" scope is created. The 'isolate' scope differs from + * normal scope in that it does not prototypically inherit from the parent scope. This is useful + * when creating reusable components, which should not accidentally read or modify data in the + * parent scope. + * + * The 'isolate' scope takes an object hash which defines a set of local scope properties + * derived from the parent scope. These local properties are useful for aliasing values for + * templates. Locals definition is a hash of local scope property to its source: + * + * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is + * always a string since DOM attributes are strings. If no `attr` name is specified then the + * attribute name is assumed to be the same as the local name. + * Given `` and widget definition + * of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect + * the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the + * `localName` property on the widget scope. The `name` is read from the parent scope (not + * component scope). + * + * * `=` or `=attr` - set up bi-directional binding between a local scope property and the + * parent scope property of name defined via the value of the `attr` attribute. If no `attr` + * name is specified then the attribute name is assumed to be the same as the local name. + * Given `` and widget definition of + * `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the + * value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected + * in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent + * scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You + * can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If + * you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use + * `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional). + * + * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope. + * If no `attr` name is specified then the attribute name is assumed to be the same as the + * local name. Given `` and widget definition of + * `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to + * a function wrapper for the `count = count + value` expression. Often it's desirable to + * pass data from the isolated scope via an expression to the parent scope, this can be + * done by passing a map of local variable names and values into the expression wrapper fn. + * For example, if the expression is `increment(amount)` then we can specify the amount value + * by calling the `localFn` as `localFn({amount: 22})`. + * + * + * #### `bindToController` + * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will + * allow a component to have its properties bound to the controller, rather than to scope. When the controller + * is instantiated, the initial values of the isolate scope bindings are already available. + * + * #### `controller` + * Controller constructor function. The controller is instantiated before the + * pre-linking phase and it is shared with other directives (see + * `require` attribute). This allows the directives to communicate with each other and augment + * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals: + * + * * `$scope` - Current scope associated with the element + * * `$element` - Current element + * * `$attrs` - Current attributes object for the element + * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope: + * `function([scope], cloneLinkingFn, futureParentElement)`. + * * `scope`: optional argument to override the scope. + * * `cloneLinkingFn`: optional argument to create clones of the original transcluded content. + * * `futureParentElement`: + * * defines the parent to which the `cloneLinkingFn` will add the cloned elements. + * * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`. + * * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements) + * and when the `cloneLinkinFn` is passed, + * as those elements need to created and cloned in a special way when they are defined outside their + * usual containers (e.g. like ``). + * * See also the `directive.templateNamespace` property. + * + * + * #### `require` + * Require another directive and inject its controller as the fourth argument to the linking function. The + * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the + * injected argument will be an array in corresponding order. If no such directive can be + * found, or if the directive does not have a controller, then an error is raised (unless no link function + * is specified, in which case error checking is skipped). The name can be prefixed with: + * + * * (no prefix) - Locate the required controller on the current element. Throw an error if not found. + * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found. + * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found. + * * `^^` - Locate the required controller by searching the element's parents. Throw an error if not found. + * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass + * `null` to the `link` fn if not found. + * * `?^^` - Attempt to locate the required controller by searching the element's parents, or pass + * `null` to the `link` fn if not found. + * + * + * #### `controllerAs` + * Identifier name for a reference to the controller in the directive's scope. + * This allows the controller to be referenced from the directive template. The directive + * needs to define a scope for this configuration to be used. Useful in the case when + * directive is used as component. + * + * + * #### `restrict` + * String of subset of `EACM` which restricts the directive to a specific directive + * declaration style. If omitted, the defaults (elements and attributes) are used. + * + * * `E` - Element name (default): `` + * * `A` - Attribute (default): `
      ` + * * `C` - Class: `
      ` + * * `M` - Comment: `` + * + * + * #### `templateNamespace` + * String representing the document type used by the markup in the template. + * AngularJS needs this information as those elements need to be created and cloned + * in a special way when they are defined outside their usual containers like `` and ``. + * + * * `html` - All root nodes in the template are HTML. Root nodes may also be + * top-level elements such as `` or ``. + * * `svg` - The root nodes in the template are SVG elements (excluding ``). + * * `math` - The root nodes in the template are MathML elements (excluding ``). + * + * If no `templateNamespace` is specified, then the namespace is considered to be `html`. + * + * #### `template` + * HTML markup that may: + * * Replace the contents of the directive's element (default). + * * Replace the directive's element itself (if `replace` is true - DEPRECATED). + * * Wrap the contents of the directive's element (if `transclude` is true). + * + * Value may be: + * + * * A string. For example `
      {{delete_str}}
      `. + * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile` + * function api below) and returns a string value. + * + * + * #### `templateUrl` + * This is similar to `template` but the template is loaded from the specified URL, asynchronously. + * + * Because template loading is asynchronous the compiler will suspend compilation of directives on that element + * for later when the template has been resolved. In the meantime it will continue to compile and link + * sibling and parent elements as though this element had not contained any directives. + * + * The compiler does not suspend the entire compilation to wait for templates to be loaded because this + * would result in the whole app "stalling" until all templates are loaded asynchronously - even in the + * case when only one deeply nested directive has `templateUrl`. + * + * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache} + * + * You can specify `templateUrl` as a string representing the URL or as a function which takes two + * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns + * a string value representing the url. In either case, the template URL is passed through {@link + * $sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}. + * + * + * #### `replace` ([*DEPRECATED*!], will be removed in next major release - i.e. v2.0) + * specify what the template should replace. Defaults to `false`. + * + * * `true` - the template will replace the directive's element. + * * `false` - the template will replace the contents of the directive's element. + * + * The replacement process migrates all of the attributes / classes from the old element to the new + * one. See the {@link guide/directive#template-expanding-directive + * Directives Guide} for an example. + * + * There are very few scenarios where element replacement is required for the application function, + * the main one being reusable custom components that are used within SVG contexts + * (because SVG doesn't work with custom elements in the DOM tree). + * + * #### `transclude` + * Extract the contents of the element where the directive appears and make it available to the directive. + * The contents are compiled and provided to the directive as a **transclusion function**. See the + * {@link $compile#transclusion Transclusion} section below. + * + * There are two kinds of transclusion depending upon whether you want to transclude just the contents of the + * directive's element or the entire element: + * + * * `true` - transclude the content (i.e. the child nodes) of the directive's element. + * * `'element'` - transclude the whole of the directive's element including any directives on this + * element that defined at a lower priority than this directive. When used, the `template` + * property is ignored. + * + * + * #### `compile` + * + * ```js + * function compile(tElement, tAttrs, transclude) { ... } + * ``` + * + * The compile function deals with transforming the template DOM. Since most directives do not do + * template transformation, it is not used often. The compile function takes the following arguments: + * + * * `tElement` - template element - The element where the directive has been declared. It is + * safe to do template transformation on the element and child elements only. + * + * * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared + * between all directive compile functions. + * + * * `transclude` - [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)` + * + *
      + * **Note:** The template instance and the link instance may be different objects if the template has + * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that + * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration + * should be done in a linking function rather than in a compile function. + *
      + + *
      + * **Note:** The compile function cannot handle directives that recursively use themselves in their + * own templates or compile functions. Compiling these directives results in an infinite loop and a + * stack overflow errors. + * + * This can be avoided by manually using $compile in the postLink function to imperatively compile + * a directive's template instead of relying on automatic template compilation via `template` or + * `templateUrl` declaration or manual compilation inside the compile function. + *
      + * + *
      + * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it + * e.g. does not know about the right outer scope. Please use the transclude function that is passed + * to the link function instead. + *
      + + * A compile function can have a return value which can be either a function or an object. + * + * * returning a (post-link) function - is equivalent to registering the linking function via the + * `link` property of the config object when the compile function is empty. + * + * * returning an object with function(s) registered via `pre` and `post` properties - allows you to + * control when a linking function should be called during the linking phase. See info about + * pre-linking and post-linking functions below. + * + * + * #### `link` + * This property is used only if the `compile` property is not defined. + * + * ```js + * function link(scope, iElement, iAttrs, controller, transcludeFn) { ... } + * ``` + * + * The link function is responsible for registering DOM listeners as well as updating the DOM. It is + * executed after the template has been cloned. This is where most of the directive logic will be + * put. + * + * * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the + * directive for registering {@link ng.$rootScope.Scope#$watch watches}. + * + * * `iElement` - instance element - The element where the directive is to be used. It is safe to + * manipulate the children of the element only in `postLink` function since the children have + * already been linked. + * + * * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared + * between all directive linking functions. + * + * * `controller` - the directive's required controller instance(s) - Instances are shared + * among all directives, which allows the directives to use the controllers as a communication + * channel. The exact value depends on the directive's `require` property: + * * `string`: the controller instance + * * `array`: array of controller instances + * * no controller(s) required: `undefined` + * + * If a required controller cannot be found, and it is optional, the instance is `null`, + * otherwise the {@link error:$compile:ctreq Missing Required Controller} error is thrown. + * + * * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope. + * This is the same as the `$transclude` + * parameter of directive controllers, see there for details. + * `function([scope], cloneLinkingFn, futureParentElement)`. + * + * #### Pre-linking function + * + * Executed before the child elements are linked. Not safe to do DOM transformation since the + * compiler linking function will fail to locate the correct elements for linking. + * + * #### Post-linking function + * + * Executed after the child elements are linked. + * + * Note that child elements that contain `templateUrl` directives will not have been compiled + * and linked since they are waiting for their template to load asynchronously and their own + * compilation and linking has been suspended until that occurs. + * + * It is safe to do DOM transformation in the post-linking function on elements that are not waiting + * for their async templates to be resolved. + * + * + * ### Transclusion + * + * Transclusion is the process of extracting a collection of DOM element from one part of the DOM and + * copying them to another part of the DOM, while maintaining their connection to the original AngularJS + * scope from where they were taken. + * + * Transclusion is used (often with {@link ngTransclude}) to insert the + * original contents of a directive's element into a specified place in the template of the directive. + * The benefit of transclusion, over simply moving the DOM elements manually, is that the transcluded + * content has access to the properties on the scope from which it was taken, even if the directive + * has isolated scope. + * See the {@link guide/directive#creating-a-directive-that-wraps-other-elements Directives Guide}. + * + * This makes it possible for the widget to have private state for its template, while the transcluded + * content has access to its originating scope. + * + *
      + * **Note:** When testing an element transclude directive you must not place the directive at the root of the + * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives + * Testing Transclusion Directives}. + *
      + * + * #### Transclusion Functions + * + * When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion + * function** to the directive's `link` function and `controller`. This transclusion function is a special + * **linking function** that will return the compiled contents linked to a new transclusion scope. + * + *
      + * If you are just using {@link ngTransclude} then you don't need to worry about this function, since + * ngTransclude will deal with it for us. + *
      + * + * If you want to manually control the insertion and removal of the transcluded content in your directive + * then you must use this transclude function. When you call a transclude function it returns a a jqLite/JQuery + * object that contains the compiled DOM, which is linked to the correct transclusion scope. + * + * When you call a transclusion function you can pass in a **clone attach function**. This function accepts + * two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded + * content and the `scope` is the newly created transclusion scope, to which the clone is bound. + * + *
      + * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a translude function + * since you then get a fresh clone of the original DOM and also have access to the new transclusion scope. + *
      + * + * It is normal practice to attach your transcluded content (`clone`) to the DOM inside your **clone + * attach function**: + * + * ```js + * var transcludedContent, transclusionScope; + * + * $transclude(function(clone, scope) { + * element.append(clone); + * transcludedContent = clone; + * transclusionScope = scope; + * }); + * ``` + * + * Later, if you want to remove the transcluded content from your DOM then you should also destroy the + * associated transclusion scope: + * + * ```js + * transcludedContent.remove(); + * transclusionScope.$destroy(); + * ``` + * + *
      + * **Best Practice**: if you intend to add and remove transcluded content manually in your directive + * (by calling the transclude function to get the DOM and calling `element.remove()` to remove it), + * then you are also responsible for calling `$destroy` on the transclusion scope. + *
      + * + * The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat} + * automatically destroy their transluded clones as necessary so you do not need to worry about this if + * you are simply using {@link ngTransclude} to inject the transclusion into your directive. + * + * + * #### Transclusion Scopes + * + * When you call a transclude function it returns a DOM fragment that is pre-bound to a **transclusion + * scope**. This scope is special, in that it is a child of the directive's scope (and so gets destroyed + * when the directive's scope gets destroyed) but it inherits the properties of the scope from which it + * was taken. + * + * For example consider a directive that uses transclusion and isolated scope. The DOM hierarchy might look + * like this: + * + * ```html + *
      + *
      + *
      + *
      + *
      + *
      + * ``` + * + * The `$parent` scope hierarchy will look like this: + * + * ``` + * - $rootScope + * - isolate + * - transclusion + * ``` + * + * but the scopes will inherit prototypically from different scopes to their `$parent`. + * + * ``` + * - $rootScope + * - transclusion + * - isolate + * ``` + * + * + * ### Attributes + * + * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the + * `link()` or `compile()` functions. It has a variety of uses. + * + * accessing *Normalized attribute names:* + * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'. + * the attributes object allows for normalized access to + * the attributes. + * + * * *Directive inter-communication:* All directives share the same instance of the attributes + * object which allows the directives to use the attributes object as inter directive + * communication. + * + * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object + * allowing other directives to read the interpolated value. + * + * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes + * that contain interpolation (e.g. `src="{{bar}}"`). Not only is this very efficient but it's also + * the only way to easily get the actual value because during the linking phase the interpolation + * hasn't been evaluated yet and so the value is at this time set to `undefined`. + * + * ```js + * function linkingFn(scope, elm, attrs, ctrl) { + * // get the attribute value + * console.log(attrs.ngModel); + * + * // change the attribute + * attrs.$set('ngModel', 'new value'); + * + * // observe changes to interpolated attribute + * attrs.$observe('ngModel', function(value) { + * console.log('ngModel has changed value to ' + value); + * }); + * } + * ``` + * + * ## Example + * + *
      + * **Note**: Typically directives are registered with `module.directive`. The example below is + * to illustrate how `$compile` works. + *
      + * + + + +
      +
      +
      +
      +
      +
      + + it('should auto compile', function() { + var textarea = $('textarea'); + var output = $('div[compile]'); + // The initial state reads 'Hello Angular'. + expect(output.getText()).toBe('Hello Angular'); + textarea.clear(); + textarea.sendKeys('{{name}}!'); + expect(output.getText()).toBe('Angular!'); + }); + +
      + + * + * + * @param {string|DOMElement} element Element or HTML string to compile into a template function. + * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED. + * + *
      + * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it + * e.g. will not use the right outer scope. Please pass the transclude function as a + * `parentBoundTranscludeFn` to the link function instead. + *
      + * + * @param {number} maxPriority only apply directives lower than given priority (Only effects the + * root element(s), not their children) + * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template + * (a DOM element/tree) to a scope. Where: + * + * * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to. + * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the + * `template` and call the `cloneAttachFn` function allowing the caller to attach the + * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is + * called as:
      `cloneAttachFn(clonedElement, scope)` where: + * + * * `clonedElement` - is a clone of the original `element` passed into the compiler. + * * `scope` - is the current scope with which the linking function is working with. + * + * * `options` - An optional object hash with linking options. If `options` is provided, then the following + * keys may be used to control linking behavior: + * + * * `parentBoundTranscludeFn` - the transclude function made available to + * directives; if given, it will be passed through to the link functions of + * directives found in `element` during compilation. + * * `transcludeControllers` - an object hash with keys that map controller names + * to controller instances; if given, it will make the controllers + * available to directives. + * * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add + * the cloned elements; only needed for transcludes that are allowed to contain non html + * elements (e.g. SVG elements). See also the directive.controller property. + * + * Calling the linking function returns the element of the template. It is either the original + * element passed in, or the clone of the element if the `cloneAttachFn` is provided. + * + * After linking the view is not updated until after a call to $digest which typically is done by + * Angular automatically. + * + * If you need access to the bound view, there are two ways to do it: + * + * - If you are not asking the linking function to clone the template, create the DOM element(s) + * before you send them to the compiler and keep this reference around. + * ```js + * var element = $compile('

      {{total}}

      ')(scope); + * ``` + * + * - if on the other hand, you need the element to be cloned, the view reference from the original + * example would not point to the clone, but rather to the original template that was cloned. In + * this case, you can access the clone via the cloneAttachFn: + * ```js + * var templateElement = angular.element('

      {{total}}

      '), + * scope = ....; + * + * var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) { + * //attach the clone to DOM document at the right place + * }); + * + * //now we have reference to the cloned DOM via `clonedElement` + * ``` + * + * + * For information on how the compiler works, see the + * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide. + */ + +var $compileMinErr = minErr('$compile'); + +/** + * @ngdoc provider + * @name $compileProvider + * + * @description + */ +$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider']; +function $CompileProvider($provide, $$sanitizeUriProvider) { + var hasDirectives = {}, + Suffix = 'Directive', + COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\w\-]+)\s+(.*)$/, + CLASS_DIRECTIVE_REGEXP = /(([\w\-]+)(?:\:([^;]+))?;?)/, + ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'), + REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/; + + // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes + // The assumption is that future DOM event attribute names will begin with + // 'on' and be composed of only English letters. + var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/; + + function parseIsolateBindings(scope, directiveName, isController) { + var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/; + + var bindings = {}; + + forEach(scope, function(definition, scopeName) { + var match = definition.match(LOCAL_REGEXP); + + if (!match) { + throw $compileMinErr('iscp', + "Invalid {3} for directive '{0}'." + + " Definition: {... {1}: '{2}' ...}", + directiveName, scopeName, definition, + (isController ? "controller bindings definition" : + "isolate scope definition")); + } + + bindings[scopeName] = { + mode: match[1][0], + collection: match[2] === '*', + optional: match[3] === '?', + attrName: match[4] || scopeName + }; + }); + + return bindings; + } + + function parseDirectiveBindings(directive, directiveName) { + var bindings = { + isolateScope: null, + bindToController: null + }; + if (isObject(directive.scope)) { + if (directive.bindToController === true) { + bindings.bindToController = parseIsolateBindings(directive.scope, + directiveName, true); + bindings.isolateScope = {}; + } else { + bindings.isolateScope = parseIsolateBindings(directive.scope, + directiveName, false); + } + } + if (isObject(directive.bindToController)) { + bindings.bindToController = + parseIsolateBindings(directive.bindToController, directiveName, true); + } + if (isObject(bindings.bindToController)) { + var controller = directive.controller; + var controllerAs = directive.controllerAs; + if (!controller) { + // There is no controller, there may or may not be a controllerAs property + throw $compileMinErr('noctrl', + "Cannot bind to controller without directive '{0}'s controller.", + directiveName); + } else if (!identifierForController(controller, controllerAs)) { + // There is a controller, but no identifier or controllerAs property + throw $compileMinErr('noident', + "Cannot bind to controller without identifier for directive '{0}'.", + directiveName); + } + } + return bindings; + } + + function assertValidDirectiveName(name) { + var letter = name.charAt(0); + if (!letter || letter !== lowercase(letter)) { + throw $compileMinErr('baddir', "Directive name '{0}' is invalid. The first character must be a lowercase letter", name); + } + if (name !== name.trim()) { + throw $compileMinErr('baddir', + "Directive name '{0}' is invalid. The name should not contain leading or trailing whitespaces", + name); + } + } + + /** + * @ngdoc method + * @name $compileProvider#directive + * @kind function + * + * @description + * Register a new directive with the compiler. + * + * @param {string|Object} name Name of the directive in camel-case (i.e. ngBind which + * will match as ng-bind), or an object map of directives where the keys are the + * names and the values are the factories. + * @param {Function|Array} directiveFactory An injectable directive factory function. See + * {@link guide/directive} for more info. + * @returns {ng.$compileProvider} Self for chaining. + */ + this.directive = function registerDirective(name, directiveFactory) { + assertNotHasOwnProperty(name, 'directive'); + if (isString(name)) { + assertValidDirectiveName(name); + assertArg(directiveFactory, 'directiveFactory'); + if (!hasDirectives.hasOwnProperty(name)) { + hasDirectives[name] = []; + $provide.factory(name + Suffix, ['$injector', '$exceptionHandler', + function($injector, $exceptionHandler) { + var directives = []; + forEach(hasDirectives[name], function(directiveFactory, index) { + try { + var directive = $injector.invoke(directiveFactory); + if (isFunction(directive)) { + directive = { compile: valueFn(directive) }; + } else if (!directive.compile && directive.link) { + directive.compile = valueFn(directive.link); + } + directive.priority = directive.priority || 0; + directive.index = index; + directive.name = directive.name || name; + directive.require = directive.require || (directive.controller && directive.name); + directive.restrict = directive.restrict || 'EA'; + var bindings = directive.$$bindings = + parseDirectiveBindings(directive, directive.name); + if (isObject(bindings.isolateScope)) { + directive.$$isolateBindings = bindings.isolateScope; + } + directives.push(directive); + } catch (e) { + $exceptionHandler(e); + } + }); + return directives; + }]); + } + hasDirectives[name].push(directiveFactory); + } else { + forEach(name, reverseParams(registerDirective)); + } + return this; + }; + + + /** + * @ngdoc method + * @name $compileProvider#aHrefSanitizationWhitelist + * @kind function + * + * @description + * Retrieves or overrides the default regular expression that is used for whitelisting of safe + * urls during a[href] sanitization. + * + * The sanitization is a security measure aimed at preventing XSS attacks via html links. + * + * Any url about to be assigned to a[href] via data-binding is first normalized and turned into + * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist` + * regular expression. If a match is found, the original url is written into the dom. Otherwise, + * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * + * @param {RegExp=} regexp New regexp to whitelist urls with. + * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for + * chaining otherwise. + */ + this.aHrefSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp); + return this; + } else { + return $$sanitizeUriProvider.aHrefSanitizationWhitelist(); + } + }; + + + /** + * @ngdoc method + * @name $compileProvider#imgSrcSanitizationWhitelist + * @kind function + * + * @description + * Retrieves or overrides the default regular expression that is used for whitelisting of safe + * urls during img[src] sanitization. + * + * The sanitization is a security measure aimed at prevent XSS attacks via html links. + * + * Any url about to be assigned to img[src] via data-binding is first normalized and turned into + * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist` + * regular expression. If a match is found, the original url is written into the dom. Otherwise, + * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * + * @param {RegExp=} regexp New regexp to whitelist urls with. + * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for + * chaining otherwise. + */ + this.imgSrcSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp); + return this; + } else { + return $$sanitizeUriProvider.imgSrcSanitizationWhitelist(); + } + }; + + /** + * @ngdoc method + * @name $compileProvider#debugInfoEnabled + * + * @param {boolean=} enabled update the debugInfoEnabled state if provided, otherwise just return the + * current debugInfoEnabled state + * @returns {*} current value if used as getter or itself (chaining) if used as setter + * + * @kind function + * + * @description + * Call this method to enable/disable various debug runtime information in the compiler such as adding + * binding information and a reference to the current scope on to DOM elements. + * If enabled, the compiler will add the following to DOM elements that have been bound to the scope + * * `ng-binding` CSS class + * * `$binding` data property containing an array of the binding expressions + * + * You may want to disable this in production for a significant performance boost. See + * {@link guide/production#disabling-debug-data Disabling Debug Data} for more. + * + * The default value is true. + */ + var debugInfoEnabled = true; + this.debugInfoEnabled = function(enabled) { + if (isDefined(enabled)) { + debugInfoEnabled = enabled; + return this; + } + return debugInfoEnabled; + }; + + this.$get = [ + '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse', + '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri', + function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse, + $controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) { + + var Attributes = function(element, attributesToCopy) { + if (attributesToCopy) { + var keys = Object.keys(attributesToCopy); + var i, l, key; + + for (i = 0, l = keys.length; i < l; i++) { + key = keys[i]; + this[key] = attributesToCopy[key]; + } + } else { + this.$attr = {}; + } + + this.$$element = element; + }; + + Attributes.prototype = { + /** + * @ngdoc method + * @name $compile.directive.Attributes#$normalize + * @kind function + * + * @description + * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or + * `data-`) to its normalized, camelCase form. + * + * Also there is special case for Moz prefix starting with upper case letter. + * + * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives} + * + * @param {string} name Name to normalize + */ + $normalize: directiveNormalize, + + + /** + * @ngdoc method + * @name $compile.directive.Attributes#$addClass + * @kind function + * + * @description + * Adds the CSS class value specified by the classVal parameter to the element. If animations + * are enabled then an animation will be triggered for the class addition. + * + * @param {string} classVal The className value that will be added to the element + */ + $addClass: function(classVal) { + if (classVal && classVal.length > 0) { + $animate.addClass(this.$$element, classVal); + } + }, + + /** + * @ngdoc method + * @name $compile.directive.Attributes#$removeClass + * @kind function + * + * @description + * Removes the CSS class value specified by the classVal parameter from the element. If + * animations are enabled then an animation will be triggered for the class removal. + * + * @param {string} classVal The className value that will be removed from the element + */ + $removeClass: function(classVal) { + if (classVal && classVal.length > 0) { + $animate.removeClass(this.$$element, classVal); + } + }, + + /** + * @ngdoc method + * @name $compile.directive.Attributes#$updateClass + * @kind function + * + * @description + * Adds and removes the appropriate CSS class values to the element based on the difference + * between the new and old CSS class values (specified as newClasses and oldClasses). + * + * @param {string} newClasses The current CSS className value + * @param {string} oldClasses The former CSS className value + */ + $updateClass: function(newClasses, oldClasses) { + var toAdd = tokenDifference(newClasses, oldClasses); + if (toAdd && toAdd.length) { + $animate.addClass(this.$$element, toAdd); + } + + var toRemove = tokenDifference(oldClasses, newClasses); + if (toRemove && toRemove.length) { + $animate.removeClass(this.$$element, toRemove); + } + }, + + /** + * Set a normalized attribute on the element in a way such that all directives + * can share the attribute. This function properly handles boolean attributes. + * @param {string} key Normalized key. (ie ngAttribute) + * @param {string|boolean} value The value to set. If `null` attribute will be deleted. + * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute. + * Defaults to true. + * @param {string=} attrName Optional none normalized name. Defaults to key. + */ + $set: function(key, value, writeAttr, attrName) { + // TODO: decide whether or not to throw an error if "class" + //is set through this function since it may cause $updateClass to + //become unstable. + + var node = this.$$element[0], + booleanKey = getBooleanAttrName(node, key), + aliasedKey = getAliasedAttrName(node, key), + observer = key, + nodeName; + + if (booleanKey) { + this.$$element.prop(key, value); + attrName = booleanKey; + } else if (aliasedKey) { + this[aliasedKey] = value; + observer = aliasedKey; + } + + this[key] = value; + + // translate normalized key to actual key + if (attrName) { + this.$attr[key] = attrName; + } else { + attrName = this.$attr[key]; + if (!attrName) { + this.$attr[key] = attrName = snake_case(key, '-'); + } + } + + nodeName = nodeName_(this.$$element); + + if ((nodeName === 'a' && key === 'href') || + (nodeName === 'img' && key === 'src')) { + // sanitize a[href] and img[src] values + this[key] = value = $$sanitizeUri(value, key === 'src'); + } else if (nodeName === 'img' && key === 'srcset') { + // sanitize img[srcset] values + var result = ""; + + // first check if there are spaces because it's not the same pattern + var trimmedSrcset = trim(value); + // ( 999x ,| 999w ,| ,|, ) + var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/; + var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/; + + // split srcset into tuple of uri and descriptor except for the last item + var rawUris = trimmedSrcset.split(pattern); + + // for each tuples + var nbrUrisWith2parts = Math.floor(rawUris.length / 2); + for (var i = 0; i < nbrUrisWith2parts; i++) { + var innerIdx = i * 2; + // sanitize the uri + result += $$sanitizeUri(trim(rawUris[innerIdx]), true); + // add the descriptor + result += (" " + trim(rawUris[innerIdx + 1])); + } + + // split the last item into uri and descriptor + var lastTuple = trim(rawUris[i * 2]).split(/\s/); + + // sanitize the last uri + result += $$sanitizeUri(trim(lastTuple[0]), true); + + // and add the last descriptor if any + if (lastTuple.length === 2) { + result += (" " + trim(lastTuple[1])); + } + this[key] = value = result; + } + + if (writeAttr !== false) { + if (value === null || value === undefined) { + this.$$element.removeAttr(attrName); + } else { + this.$$element.attr(attrName, value); + } + } + + // fire observers + var $$observers = this.$$observers; + $$observers && forEach($$observers[observer], function(fn) { + try { + fn(value); + } catch (e) { + $exceptionHandler(e); + } + }); + }, + + + /** + * @ngdoc method + * @name $compile.directive.Attributes#$observe + * @kind function + * + * @description + * Observes an interpolated attribute. + * + * The observer function will be invoked once during the next `$digest` following + * compilation. The observer is then invoked whenever the interpolated value + * changes. + * + * @param {string} key Normalized key. (ie ngAttribute) . + * @param {function(interpolatedValue)} fn Function that will be called whenever + the interpolated value of the attribute changes. + * See the {@link guide/directive#text-and-attribute-bindings Directives} guide for more info. + * @returns {function()} Returns a deregistration function for this observer. + */ + $observe: function(key, fn) { + var attrs = this, + $$observers = (attrs.$$observers || (attrs.$$observers = createMap())), + listeners = ($$observers[key] || ($$observers[key] = [])); + + listeners.push(fn); + $rootScope.$evalAsync(function() { + if (!listeners.$$inter && attrs.hasOwnProperty(key)) { + // no one registered attribute interpolation function, so lets call it manually + fn(attrs[key]); + } + }); + + return function() { + arrayRemove(listeners, fn); + }; + } + }; + + + function safeAddClass($element, className) { + try { + $element.addClass(className); + } catch (e) { + // ignore, since it means that we are trying to set class on + // SVG element, where class name is read-only. + } + } + + + var startSymbol = $interpolate.startSymbol(), + endSymbol = $interpolate.endSymbol(), + denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}') + ? identity + : function denormalizeTemplate(template) { + return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol); + }, + NG_ATTR_BINDING = /^ngAttr[A-Z]/; + + compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) { + var bindings = $element.data('$binding') || []; + + if (isArray(binding)) { + bindings = bindings.concat(binding); + } else { + bindings.push(binding); + } + + $element.data('$binding', bindings); + } : noop; + + compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) { + safeAddClass($element, 'ng-binding'); + } : noop; + + compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) { + var dataName = isolated ? (noTemplate ? '$isolateScopeNoTemplate' : '$isolateScope') : '$scope'; + $element.data(dataName, scope); + } : noop; + + compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) { + safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope'); + } : noop; + + return compile; + + //================================ + + function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, + previousCompileContext) { + if (!($compileNodes instanceof jqLite)) { + // jquery always rewraps, whereas we need to preserve the original selector so that we can + // modify it. + $compileNodes = jqLite($compileNodes); + } + // We can not compile top level text elements since text nodes can be merged and we will + // not be able to attach scope data to them, so we will wrap them in + forEach($compileNodes, function(node, index) { + if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/) /* non-empty */ ) { + $compileNodes[index] = jqLite(node).wrap('').parent()[0]; + } + }); + var compositeLinkFn = + compileNodes($compileNodes, transcludeFn, $compileNodes, + maxPriority, ignoreDirective, previousCompileContext); + compile.$$addScopeClass($compileNodes); + var namespace = null; + return function publicLinkFn(scope, cloneConnectFn, options) { + assertArg(scope, 'scope'); + + options = options || {}; + var parentBoundTranscludeFn = options.parentBoundTranscludeFn, + transcludeControllers = options.transcludeControllers, + futureParentElement = options.futureParentElement; + + // When `parentBoundTranscludeFn` is passed, it is a + // `controllersBoundTransclude` function (it was previously passed + // as `transclude` to directive.link) so we must unwrap it to get + // its `boundTranscludeFn` + if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) { + parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude; + } + + if (!namespace) { + namespace = detectNamespaceForChildElements(futureParentElement); + } + var $linkNode; + if (namespace !== 'html') { + // When using a directive with replace:true and templateUrl the $compileNodes + // (or a child element inside of them) + // might change, so we need to recreate the namespace adapted compileNodes + // for call to the link function. + // Note: This will already clone the nodes... + $linkNode = jqLite( + wrapTemplate(namespace, jqLite('
      ').append($compileNodes).html()) + ); + } else if (cloneConnectFn) { + // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart + // and sometimes changes the structure of the DOM. + $linkNode = JQLitePrototype.clone.call($compileNodes); + } else { + $linkNode = $compileNodes; + } + + if (transcludeControllers) { + for (var controllerName in transcludeControllers) { + $linkNode.data('$' + controllerName + 'Controller', transcludeControllers[controllerName].instance); + } + } + + compile.$$addScopeInfo($linkNode, scope); + + if (cloneConnectFn) cloneConnectFn($linkNode, scope); + if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn); + return $linkNode; + }; + } + + function detectNamespaceForChildElements(parentElement) { + // TODO: Make this detect MathML as well... + var node = parentElement && parentElement[0]; + if (!node) { + return 'html'; + } else { + return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg' : 'html'; + } + } + + /** + * Compile function matches each node in nodeList against the directives. Once all directives + * for a particular node are collected their compile functions are executed. The compile + * functions return values - the linking functions - are combined into a composite linking + * function, which is the a linking function for the node. + * + * @param {NodeList} nodeList an array of nodes or NodeList to compile + * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the + * scope argument is auto-generated to the new child of the transcluded parent scope. + * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then + * the rootElement must be set the jqLite collection of the compile root. This is + * needed so that the jqLite collection items can be replaced with widgets. + * @param {number=} maxPriority Max directive priority. + * @returns {Function} A composite linking function of all of the matched directives or null. + */ + function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective, + previousCompileContext) { + var linkFns = [], + attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound; + + for (var i = 0; i < nodeList.length; i++) { + attrs = new Attributes(); + + // we must always refer to nodeList[i] since the nodes can be replaced underneath us. + directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined, + ignoreDirective); + + nodeLinkFn = (directives.length) + ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement, + null, [], [], previousCompileContext) + : null; + + if (nodeLinkFn && nodeLinkFn.scope) { + compile.$$addScopeClass(attrs.$$element); + } + + childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || + !(childNodes = nodeList[i].childNodes) || + !childNodes.length) + ? null + : compileNodes(childNodes, + nodeLinkFn ? ( + (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement) + && nodeLinkFn.transclude) : transcludeFn); + + if (nodeLinkFn || childLinkFn) { + linkFns.push(i, nodeLinkFn, childLinkFn); + linkFnFound = true; + nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn; + } + + //use the previous context only for the first element in the virtual group + previousCompileContext = null; + } + + // return a linking function if we have found anything, null otherwise + return linkFnFound ? compositeLinkFn : null; + + function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) { + var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn; + var stableNodeList; + + + if (nodeLinkFnFound) { + // copy nodeList so that if a nodeLinkFn removes or adds an element at this DOM level our + // offsets don't get screwed up + var nodeListLength = nodeList.length; + stableNodeList = new Array(nodeListLength); + + // create a sparse array by only copying the elements which have a linkFn + for (i = 0; i < linkFns.length; i+=3) { + idx = linkFns[i]; + stableNodeList[idx] = nodeList[idx]; + } + } else { + stableNodeList = nodeList; + } + + for (i = 0, ii = linkFns.length; i < ii;) { + node = stableNodeList[linkFns[i++]]; + nodeLinkFn = linkFns[i++]; + childLinkFn = linkFns[i++]; + + if (nodeLinkFn) { + if (nodeLinkFn.scope) { + childScope = scope.$new(); + compile.$$addScopeInfo(jqLite(node), childScope); + var destroyBindings = nodeLinkFn.$$destroyBindings; + if (destroyBindings) { + nodeLinkFn.$$destroyBindings = null; + childScope.$on('$destroyed', destroyBindings); + } + } else { + childScope = scope; + } + + if (nodeLinkFn.transcludeOnThisElement) { + childBoundTranscludeFn = createBoundTranscludeFn( + scope, nodeLinkFn.transclude, parentBoundTranscludeFn, + nodeLinkFn.elementTranscludeOnThisElement); + + } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) { + childBoundTranscludeFn = parentBoundTranscludeFn; + + } else if (!parentBoundTranscludeFn && transcludeFn) { + childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn); + + } else { + childBoundTranscludeFn = null; + } + + nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn, + nodeLinkFn); + + } else if (childLinkFn) { + childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn); + } + } + } + } + + function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn, elementTransclusion) { + + var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) { + + if (!transcludedScope) { + transcludedScope = scope.$new(false, containingScope); + transcludedScope.$$transcluded = true; + } + + return transcludeFn(transcludedScope, cloneFn, { + parentBoundTranscludeFn: previousBoundTranscludeFn, + transcludeControllers: controllers, + futureParentElement: futureParentElement + }); + }; + + return boundTranscludeFn; + } + + /** + * Looks for directives on the given node and adds them to the directive collection which is + * sorted. + * + * @param node Node to search. + * @param directives An array to which the directives are added to. This array is sorted before + * the function returns. + * @param attrs The shared attrs object which is used to populate the normalized attributes. + * @param {number=} maxPriority Max directive priority. + */ + function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) { + var nodeType = node.nodeType, + attrsMap = attrs.$attr, + match, + className; + + switch (nodeType) { + case NODE_TYPE_ELEMENT: /* Element */ + // use the node name: + addDirective(directives, + directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective); + + // iterate over the attributes + for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes, + j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) { + var attrStartName = false; + var attrEndName = false; + + attr = nAttrs[j]; + name = attr.name; + value = trim(attr.value); + + // support ngAttr attribute binding + ngAttrName = directiveNormalize(name); + if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) { + name = name.replace(PREFIX_REGEXP, '') + .substr(8).replace(/_(.)/g, function(match, letter) { + return letter.toUpperCase(); + }); + } + + var directiveNName = ngAttrName.replace(/(Start|End)$/, ''); + if (directiveIsMultiElement(directiveNName)) { + if (ngAttrName === directiveNName + 'Start') { + attrStartName = name; + attrEndName = name.substr(0, name.length - 5) + 'end'; + name = name.substr(0, name.length - 6); + } + } + + nName = directiveNormalize(name.toLowerCase()); + attrsMap[nName] = name; + if (isNgAttr || !attrs.hasOwnProperty(nName)) { + attrs[nName] = value; + if (getBooleanAttrName(node, nName)) { + attrs[nName] = true; // presence means true + } + } + addAttrInterpolateDirective(node, directives, value, nName, isNgAttr); + addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName, + attrEndName); + } + + // use class as directive + className = node.className; + if (isObject(className)) { + // Maybe SVGAnimatedString + className = className.animVal; + } + if (isString(className) && className !== '') { + while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) { + nName = directiveNormalize(match[2]); + if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) { + attrs[nName] = trim(match[3]); + } + className = className.substr(match.index + match[0].length); + } + } + break; + case NODE_TYPE_TEXT: /* Text Node */ + addTextInterpolateDirective(directives, node.nodeValue); + break; + case NODE_TYPE_COMMENT: /* Comment */ + try { + match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue); + if (match) { + nName = directiveNormalize(match[1]); + if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) { + attrs[nName] = trim(match[2]); + } + } + } catch (e) { + // turns out that under some circumstances IE9 throws errors when one attempts to read + // comment's node value. + // Just ignore it and continue. (Can't seem to reproduce in test case.) + } + break; + } + + directives.sort(byPriority); + return directives; + } + + /** + * Given a node with an directive-start it collects all of the siblings until it finds + * directive-end. + * @param node + * @param attrStart + * @param attrEnd + * @returns {*} + */ + function groupScan(node, attrStart, attrEnd) { + var nodes = []; + var depth = 0; + if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) { + do { + if (!node) { + throw $compileMinErr('uterdir', + "Unterminated attribute, found '{0}' but no matching '{1}' found.", + attrStart, attrEnd); + } + if (node.nodeType == NODE_TYPE_ELEMENT) { + if (node.hasAttribute(attrStart)) depth++; + if (node.hasAttribute(attrEnd)) depth--; + } + nodes.push(node); + node = node.nextSibling; + } while (depth > 0); + } else { + nodes.push(node); + } + + return jqLite(nodes); + } + + /** + * Wrapper for linking function which converts normal linking function into a grouped + * linking function. + * @param linkFn + * @param attrStart + * @param attrEnd + * @returns {Function} + */ + function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) { + return function(scope, element, attrs, controllers, transcludeFn) { + element = groupScan(element[0], attrStart, attrEnd); + return linkFn(scope, element, attrs, controllers, transcludeFn); + }; + } + + /** + * Once the directives have been collected, their compile functions are executed. This method + * is responsible for inlining directive templates as well as terminating the application + * of the directives if the terminal directive has been reached. + * + * @param {Array} directives Array of collected directives to execute their compile function. + * this needs to be pre-sorted by priority order. + * @param {Node} compileNode The raw DOM node to apply the compile functions to + * @param {Object} templateAttrs The shared attribute function + * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the + * scope argument is auto-generated to the new + * child of the transcluded parent scope. + * @param {JQLite} jqCollection If we are working on the root of the compile tree then this + * argument has the root jqLite array so that we can replace nodes + * on it. + * @param {Object=} originalReplaceDirective An optional directive that will be ignored when + * compiling the transclusion. + * @param {Array.} preLinkFns + * @param {Array.} postLinkFns + * @param {Object} previousCompileContext Context used for previous compilation of the current + * node + * @returns {Function} linkFn + */ + function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, + jqCollection, originalReplaceDirective, preLinkFns, postLinkFns, + previousCompileContext) { + previousCompileContext = previousCompileContext || {}; + + var terminalPriority = -Number.MAX_VALUE, + newScopeDirective, + controllerDirectives = previousCompileContext.controllerDirectives, + newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective, + templateDirective = previousCompileContext.templateDirective, + nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective, + hasTranscludeDirective = false, + hasTemplate = false, + hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective, + $compileNode = templateAttrs.$$element = jqLite(compileNode), + directive, + directiveName, + $template, + replaceDirective = originalReplaceDirective, + childTranscludeFn = transcludeFn, + linkFn, + directiveValue; + + // executes all directives on the current element + for (var i = 0, ii = directives.length; i < ii; i++) { + directive = directives[i]; + var attrStart = directive.$$start; + var attrEnd = directive.$$end; + + // collect multiblock sections + if (attrStart) { + $compileNode = groupScan(compileNode, attrStart, attrEnd); + } + $template = undefined; + + if (terminalPriority > directive.priority) { + break; // prevent further processing of directives + } + + if (directiveValue = directive.scope) { + + // skip the check for directives with async templates, we'll check the derived sync + // directive when the template arrives + if (!directive.templateUrl) { + if (isObject(directiveValue)) { + // This directive is trying to add an isolated scope. + // Check that there is no scope of any kind already + assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective, + directive, $compileNode); + newIsolateScopeDirective = directive; + } else { + // This directive is trying to add a child scope. + // Check that there is no isolated scope already + assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive, + $compileNode); + } + } + + newScopeDirective = newScopeDirective || directive; + } + + directiveName = directive.name; + + if (!directive.templateUrl && directive.controller) { + directiveValue = directive.controller; + controllerDirectives = controllerDirectives || createMap(); + assertNoDuplicate("'" + directiveName + "' controller", + controllerDirectives[directiveName], directive, $compileNode); + controllerDirectives[directiveName] = directive; + } + + if (directiveValue = directive.transclude) { + hasTranscludeDirective = true; + + // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion. + // This option should only be used by directives that know how to safely handle element transclusion, + // where the transcluded nodes are added or replaced after linking. + if (!directive.$$tlb) { + assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode); + nonTlbTranscludeDirective = directive; + } + + if (directiveValue == 'element') { + hasElementTranscludeDirective = true; + terminalPriority = directive.priority; + $template = $compileNode; + $compileNode = templateAttrs.$$element = + jqLite(document.createComment(' ' + directiveName + ': ' + + templateAttrs[directiveName] + ' ')); + compileNode = $compileNode[0]; + replaceWith(jqCollection, sliceArgs($template), compileNode); + + childTranscludeFn = compile($template, transcludeFn, terminalPriority, + replaceDirective && replaceDirective.name, { + // Don't pass in: + // - controllerDirectives - otherwise we'll create duplicates controllers + // - newIsolateScopeDirective or templateDirective - combining templates with + // element transclusion doesn't make sense. + // + // We need only nonTlbTranscludeDirective so that we prevent putting transclusion + // on the same element more than once. + nonTlbTranscludeDirective: nonTlbTranscludeDirective + }); + } else { + $template = jqLite(jqLiteClone(compileNode)).contents(); + $compileNode.empty(); // clear contents + childTranscludeFn = compile($template, transcludeFn); + } + } + + if (directive.template) { + hasTemplate = true; + assertNoDuplicate('template', templateDirective, directive, $compileNode); + templateDirective = directive; + + directiveValue = (isFunction(directive.template)) + ? directive.template($compileNode, templateAttrs) + : directive.template; + + directiveValue = denormalizeTemplate(directiveValue); + + if (directive.replace) { + replaceDirective = directive; + if (jqLiteIsTextNode(directiveValue)) { + $template = []; + } else { + $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue))); + } + compileNode = $template[0]; + + if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) { + throw $compileMinErr('tplrt', + "Template for directive '{0}' must have exactly one root element. {1}", + directiveName, ''); + } + + replaceWith(jqCollection, $compileNode, compileNode); + + var newTemplateAttrs = {$attr: {}}; + + // combine directives from the original node and from the template: + // - take the array of directives for this element + // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed) + // - collect directives from the template and sort them by priority + // - combine directives as: processed + template + unprocessed + var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs); + var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1)); + + if (newIsolateScopeDirective) { + markDirectivesAsIsolate(templateDirectives); + } + directives = directives.concat(templateDirectives).concat(unprocessedDirectives); + mergeTemplateAttributes(templateAttrs, newTemplateAttrs); + + ii = directives.length; + } else { + $compileNode.html(directiveValue); + } + } + + if (directive.templateUrl) { + hasTemplate = true; + assertNoDuplicate('template', templateDirective, directive, $compileNode); + templateDirective = directive; + + if (directive.replace) { + replaceDirective = directive; + } + + nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode, + templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, { + controllerDirectives: controllerDirectives, + newIsolateScopeDirective: newIsolateScopeDirective, + templateDirective: templateDirective, + nonTlbTranscludeDirective: nonTlbTranscludeDirective + }); + ii = directives.length; + } else if (directive.compile) { + try { + linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn); + if (isFunction(linkFn)) { + addLinkFns(null, linkFn, attrStart, attrEnd); + } else if (linkFn) { + addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd); + } + } catch (e) { + $exceptionHandler(e, startingTag($compileNode)); + } + } + + if (directive.terminal) { + nodeLinkFn.terminal = true; + terminalPriority = Math.max(terminalPriority, directive.priority); + } + + } + + nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true; + nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective; + nodeLinkFn.elementTranscludeOnThisElement = hasElementTranscludeDirective; + nodeLinkFn.templateOnThisElement = hasTemplate; + nodeLinkFn.transclude = childTranscludeFn; + + previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective; + + // might be normal or delayed nodeLinkFn depending on if templateUrl is present + return nodeLinkFn; + + //////////////////// + + function addLinkFns(pre, post, attrStart, attrEnd) { + if (pre) { + if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd); + pre.require = directive.require; + pre.directiveName = directiveName; + if (newIsolateScopeDirective === directive || directive.$$isolateScope) { + pre = cloneAndAnnotateFn(pre, {isolateScope: true}); + } + preLinkFns.push(pre); + } + if (post) { + if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd); + post.require = directive.require; + post.directiveName = directiveName; + if (newIsolateScopeDirective === directive || directive.$$isolateScope) { + post = cloneAndAnnotateFn(post, {isolateScope: true}); + } + postLinkFns.push(post); + } + } + + + function getControllers(directiveName, require, $element, elementControllers) { + var value; + + if (isString(require)) { + var match = require.match(REQUIRE_PREFIX_REGEXP); + var name = require.substring(match[0].length); + var inheritType = match[1] || match[3]; + var optional = match[2] === '?'; + + //If only parents then start at the parent element + if (inheritType === '^^') { + $element = $element.parent(); + //Otherwise attempt getting the controller from elementControllers in case + //the element is transcluded (and has no data) and to avoid .data if possible + } else { + value = elementControllers && elementControllers[name]; + value = value && value.instance; + } + + if (!value) { + var dataName = '$' + name + 'Controller'; + value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName); + } + + if (!value && !optional) { + throw $compileMinErr('ctreq', + "Controller '{0}', required by directive '{1}', can't be found!", + name, directiveName); + } + } else if (isArray(require)) { + value = []; + for (var i = 0, ii = require.length; i < ii; i++) { + value[i] = getControllers(directiveName, require[i], $element, elementControllers); + } + } + + return value || null; + } + + function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope) { + var elementControllers = createMap(); + for (var controllerKey in controllerDirectives) { + var directive = controllerDirectives[controllerKey]; + var locals = { + $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, + $element: $element, + $attrs: attrs, + $transclude: transcludeFn + }; + + var controller = directive.controller; + if (controller == '@') { + controller = attrs[directive.name]; + } + + var controllerInstance = $controller(controller, locals, true, directive.controllerAs); + + // For directives with element transclusion the element is a comment, + // but jQuery .data doesn't support attaching data to comment nodes as it's hard to + // clean up (http://bugs.jquery.com/ticket/8335). + // Instead, we save the controllers for the element in a local hash and attach to .data + // later, once we have the actual element. + elementControllers[directive.name] = controllerInstance; + if (!hasElementTranscludeDirective) { + $element.data('$' + directive.name + 'Controller', controllerInstance.instance); + } + } + return elementControllers; + } + + function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn, + thisLinkFn) { + var i, ii, linkFn, controller, isolateScope, elementControllers, transcludeFn, $element, + attrs; + + if (compileNode === linkNode) { + attrs = templateAttrs; + $element = templateAttrs.$$element; + } else { + $element = jqLite(linkNode); + attrs = new Attributes($element, templateAttrs); + } + + if (newIsolateScopeDirective) { + isolateScope = scope.$new(true); + } + + if (boundTranscludeFn) { + // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn` + // is later passed as `parentBoundTranscludeFn` to `publicLinkFn` + transcludeFn = controllersBoundTransclude; + transcludeFn.$$boundTransclude = boundTranscludeFn; + } + + if (controllerDirectives) { + elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope); + } + + if (newIsolateScopeDirective) { + // Initialize isolate scope bindings for new isolate scope directive. + compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective || + templateDirective === newIsolateScopeDirective.$$originalDirective))); + compile.$$addScopeClass($element, true); + isolateScope.$$isolateBindings = + newIsolateScopeDirective.$$isolateBindings; + initializeDirectiveBindings(scope, attrs, isolateScope, + isolateScope.$$isolateBindings, + newIsolateScopeDirective, isolateScope); + } + if (elementControllers) { + // Initialize bindToController bindings for new/isolate scopes + var scopeDirective = newIsolateScopeDirective || newScopeDirective; + var bindings; + var controllerForBindings; + if (scopeDirective && elementControllers[scopeDirective.name]) { + bindings = scopeDirective.$$bindings.bindToController; + controller = elementControllers[scopeDirective.name]; + + if (controller && controller.identifier && bindings) { + controllerForBindings = controller; + thisLinkFn.$$destroyBindings = + initializeDirectiveBindings(scope, attrs, controller.instance, + bindings, scopeDirective); + } + } + for (i in elementControllers) { + controller = elementControllers[i]; + var controllerResult = controller(); + if (controllerResult !== controller.instance) { + controller.instance = controllerResult; + $element.data('$' + directive.name + 'Controller', controllerResult); + if (controller === controllerForBindings) { + // Remove and re-install bindToController bindings + thisLinkFn.$$destroyBindings(); + thisLinkFn.$$destroyBindings = + initializeDirectiveBindings(scope, attrs, controllerResult, bindings, scopeDirective); + } + } + } + } + + // PRELINKING + for (i = 0, ii = preLinkFns.length; i < ii; i++) { + linkFn = preLinkFns[i]; + invokeLinkFn(linkFn, + linkFn.isolateScope ? isolateScope : scope, + $element, + attrs, + linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), + transcludeFn + ); + } + + // RECURSION + // We only pass the isolate scope, if the isolate directive has a template, + // otherwise the child elements do not belong to the isolate directive. + var scopeToChild = scope; + if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) { + scopeToChild = isolateScope; + } + childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn); + + // POSTLINKING + for (i = postLinkFns.length - 1; i >= 0; i--) { + linkFn = postLinkFns[i]; + invokeLinkFn(linkFn, + linkFn.isolateScope ? isolateScope : scope, + $element, + attrs, + linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), + transcludeFn + ); + } + + // This is the function that is injected as `$transclude`. + // Note: all arguments are optional! + function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) { + var transcludeControllers; + + // No scope passed in: + if (!isScope(scope)) { + futureParentElement = cloneAttachFn; + cloneAttachFn = scope; + scope = undefined; + } + + if (hasElementTranscludeDirective) { + transcludeControllers = elementControllers; + } + if (!futureParentElement) { + futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element; + } + return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild); + } + } + } + + function markDirectivesAsIsolate(directives) { + // mark all directives as needing isolate scope. + for (var j = 0, jj = directives.length; j < jj; j++) { + directives[j] = inherit(directives[j], {$$isolateScope: true}); + } + } + + /** + * looks up the directive and decorates it with exception handling and proper parameters. We + * call this the boundDirective. + * + * @param {string} name name of the directive to look up. + * @param {string} location The directive must be found in specific format. + * String containing any of theses characters: + * + * * `E`: element name + * * `A': attribute + * * `C`: class + * * `M`: comment + * @returns {boolean} true if directive was added. + */ + function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName, + endAttrName) { + if (name === ignoreDirective) return null; + var match = null; + if (hasDirectives.hasOwnProperty(name)) { + for (var directive, directives = $injector.get(name + Suffix), + i = 0, ii = directives.length; i < ii; i++) { + try { + directive = directives[i]; + if ((maxPriority === undefined || maxPriority > directive.priority) && + directive.restrict.indexOf(location) != -1) { + if (startAttrName) { + directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName}); + } + tDirectives.push(directive); + match = directive; + } + } catch (e) { $exceptionHandler(e); } + } + } + return match; + } + + + /** + * looks up the directive and returns true if it is a multi-element directive, + * and therefore requires DOM nodes between -start and -end markers to be grouped + * together. + * + * @param {string} name name of the directive to look up. + * @returns true if directive was registered as multi-element. + */ + function directiveIsMultiElement(name) { + if (hasDirectives.hasOwnProperty(name)) { + for (var directive, directives = $injector.get(name + Suffix), + i = 0, ii = directives.length; i < ii; i++) { + directive = directives[i]; + if (directive.multiElement) { + return true; + } + } + } + return false; + } + + /** + * When the element is replaced with HTML template then the new attributes + * on the template need to be merged with the existing attributes in the DOM. + * The desired effect is to have both of the attributes present. + * + * @param {object} dst destination attributes (original DOM) + * @param {object} src source attributes (from the directive template) + */ + function mergeTemplateAttributes(dst, src) { + var srcAttr = src.$attr, + dstAttr = dst.$attr, + $element = dst.$$element; + + // reapply the old attributes to the new element + forEach(dst, function(value, key) { + if (key.charAt(0) != '$') { + if (src[key] && src[key] !== value) { + value += (key === 'style' ? ';' : ' ') + src[key]; + } + dst.$set(key, value, true, srcAttr[key]); + } + }); + + // copy the new attributes on the old attrs object + forEach(src, function(value, key) { + if (key == 'class') { + safeAddClass($element, value); + dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value; + } else if (key == 'style') { + $element.attr('style', $element.attr('style') + ';' + value); + dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value; + // `dst` will never contain hasOwnProperty as DOM parser won't let it. + // You will get an "InvalidCharacterError: DOM Exception 5" error if you + // have an attribute like "has-own-property" or "data-has-own-property", etc. + } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) { + dst[key] = value; + dstAttr[key] = srcAttr[key]; + } + }); + } + + + function compileTemplateUrl(directives, $compileNode, tAttrs, + $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) { + var linkQueue = [], + afterTemplateNodeLinkFn, + afterTemplateChildLinkFn, + beforeTemplateCompileNode = $compileNode[0], + origAsyncDirective = directives.shift(), + derivedSyncDirective = inherit(origAsyncDirective, { + templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective + }), + templateUrl = (isFunction(origAsyncDirective.templateUrl)) + ? origAsyncDirective.templateUrl($compileNode, tAttrs) + : origAsyncDirective.templateUrl, + templateNamespace = origAsyncDirective.templateNamespace; + + $compileNode.empty(); + + $templateRequest($sce.getTrustedResourceUrl(templateUrl)) + .then(function(content) { + var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn; + + content = denormalizeTemplate(content); + + if (origAsyncDirective.replace) { + if (jqLiteIsTextNode(content)) { + $template = []; + } else { + $template = removeComments(wrapTemplate(templateNamespace, trim(content))); + } + compileNode = $template[0]; + + if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) { + throw $compileMinErr('tplrt', + "Template for directive '{0}' must have exactly one root element. {1}", + origAsyncDirective.name, templateUrl); + } + + tempTemplateAttrs = {$attr: {}}; + replaceWith($rootElement, $compileNode, compileNode); + var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs); + + if (isObject(origAsyncDirective.scope)) { + markDirectivesAsIsolate(templateDirectives); + } + directives = templateDirectives.concat(directives); + mergeTemplateAttributes(tAttrs, tempTemplateAttrs); + } else { + compileNode = beforeTemplateCompileNode; + $compileNode.html(content); + } + + directives.unshift(derivedSyncDirective); + + afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, + childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns, + previousCompileContext); + forEach($rootElement, function(node, i) { + if (node == compileNode) { + $rootElement[i] = $compileNode[0]; + } + }); + afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn); + + while (linkQueue.length) { + var scope = linkQueue.shift(), + beforeTemplateLinkNode = linkQueue.shift(), + linkRootElement = linkQueue.shift(), + boundTranscludeFn = linkQueue.shift(), + linkNode = $compileNode[0]; + + if (scope.$$destroyed) continue; + + if (beforeTemplateLinkNode !== beforeTemplateCompileNode) { + var oldClasses = beforeTemplateLinkNode.className; + + if (!(previousCompileContext.hasElementTranscludeDirective && + origAsyncDirective.replace)) { + // it was cloned therefore we have to clone as well. + linkNode = jqLiteClone(compileNode); + } + replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode); + + // Copy in CSS classes from original node + safeAddClass(jqLite(linkNode), oldClasses); + } + if (afterTemplateNodeLinkFn.transcludeOnThisElement) { + childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn); + } else { + childBoundTranscludeFn = boundTranscludeFn; + } + afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, + childBoundTranscludeFn, afterTemplateNodeLinkFn); + } + linkQueue = null; + }); + + return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) { + var childBoundTranscludeFn = boundTranscludeFn; + if (scope.$$destroyed) return; + if (linkQueue) { + linkQueue.push(scope, + node, + rootElement, + childBoundTranscludeFn); + } else { + if (afterTemplateNodeLinkFn.transcludeOnThisElement) { + childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn); + } + afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn, + afterTemplateNodeLinkFn); + } + }; + } + + + /** + * Sorting function for bound directives. + */ + function byPriority(a, b) { + var diff = b.priority - a.priority; + if (diff !== 0) return diff; + if (a.name !== b.name) return (a.name < b.name) ? -1 : 1; + return a.index - b.index; + } + + + function assertNoDuplicate(what, previousDirective, directive, element) { + if (previousDirective) { + throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}', + previousDirective.name, directive.name, what, startingTag(element)); + } + } + + + function addTextInterpolateDirective(directives, text) { + var interpolateFn = $interpolate(text, true); + if (interpolateFn) { + directives.push({ + priority: 0, + compile: function textInterpolateCompileFn(templateNode) { + var templateNodeParent = templateNode.parent(), + hasCompileParent = !!templateNodeParent.length; + + // When transcluding a template that has bindings in the root + // we don't have a parent and thus need to add the class during linking fn. + if (hasCompileParent) compile.$$addBindingClass(templateNodeParent); + + return function textInterpolateLinkFn(scope, node) { + var parent = node.parent(); + if (!hasCompileParent) compile.$$addBindingClass(parent); + compile.$$addBindingInfo(parent, interpolateFn.expressions); + scope.$watch(interpolateFn, function interpolateFnWatchAction(value) { + node[0].nodeValue = value; + }); + }; + } + }); + } + } + + + function wrapTemplate(type, template) { + type = lowercase(type || 'html'); + switch (type) { + case 'svg': + case 'math': + var wrapper = document.createElement('div'); + wrapper.innerHTML = '<' + type + '>' + template + ''; + return wrapper.childNodes[0].childNodes; + default: + return template; + } + } + + + function getTrustedContext(node, attrNormalizedName) { + if (attrNormalizedName == "srcdoc") { + return $sce.HTML; + } + var tag = nodeName_(node); + // maction[xlink:href] can source SVG. It's not limited to . + if (attrNormalizedName == "xlinkHref" || + (tag == "form" && attrNormalizedName == "action") || + (tag != "img" && (attrNormalizedName == "src" || + attrNormalizedName == "ngSrc"))) { + return $sce.RESOURCE_URL; + } + } + + + function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) { + var trustedContext = getTrustedContext(node, name); + allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing; + + var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing); + + // no interpolation found -> ignore + if (!interpolateFn) return; + + + if (name === "multiple" && nodeName_(node) === "select") { + throw $compileMinErr("selmulti", + "Binding to the 'multiple' attribute is not supported. Element: {0}", + startingTag(node)); + } + + directives.push({ + priority: 100, + compile: function() { + return { + pre: function attrInterpolatePreLinkFn(scope, element, attr) { + var $$observers = (attr.$$observers || (attr.$$observers = {})); + + if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { + throw $compileMinErr('nodomevents', + "Interpolations for HTML DOM event attributes are disallowed. Please use the " + + "ng- versions (such as ng-click instead of onclick) instead."); + } + + // If the attribute has changed since last $interpolate()ed + var newValue = attr[name]; + if (newValue !== value) { + // we need to interpolate again since the attribute value has been updated + // (e.g. by another directive's compile function) + // ensure unset/empty values make interpolateFn falsy + interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing); + value = newValue; + } + + // if attribute was updated so that there is no interpolation going on we don't want to + // register any observers + if (!interpolateFn) return; + + // initialize attr object so that it's ready in case we need the value for isolate + // scope initialization, otherwise the value would not be available from isolate + // directive's linking fn during linking phase + attr[name] = interpolateFn(scope); + + ($$observers[name] || ($$observers[name] = [])).$$inter = true; + (attr.$$observers && attr.$$observers[name].$$scope || scope). + $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) { + //special case for class attribute addition + removal + //so that class changes can tap into the animation + //hooks provided by the $animate service. Be sure to + //skip animations when the first digest occurs (when + //both the new and the old values are the same) since + //the CSS classes are the non-interpolated values + if (name === 'class' && newValue != oldValue) { + attr.$updateClass(newValue, oldValue); + } else { + attr.$set(name, newValue); + } + }); + } + }; + } + }); + } + + + /** + * This is a special jqLite.replaceWith, which can replace items which + * have no parents, provided that the containing jqLite collection is provided. + * + * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes + * in the root of the tree. + * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep + * the shell, but replace its DOM node reference. + * @param {Node} newNode The new DOM node. + */ + function replaceWith($rootElement, elementsToRemove, newNode) { + var firstElementToRemove = elementsToRemove[0], + removeCount = elementsToRemove.length, + parent = firstElementToRemove.parentNode, + i, ii; + + if ($rootElement) { + for (i = 0, ii = $rootElement.length; i < ii; i++) { + if ($rootElement[i] == firstElementToRemove) { + $rootElement[i++] = newNode; + for (var j = i, j2 = j + removeCount - 1, + jj = $rootElement.length; + j < jj; j++, j2++) { + if (j2 < jj) { + $rootElement[j] = $rootElement[j2]; + } else { + delete $rootElement[j]; + } + } + $rootElement.length -= removeCount - 1; + + // If the replaced element is also the jQuery .context then replace it + // .context is a deprecated jQuery api, so we should set it only when jQuery set it + // http://api.jquery.com/context/ + if ($rootElement.context === firstElementToRemove) { + $rootElement.context = newNode; + } + break; + } + } + } + + if (parent) { + parent.replaceChild(newNode, firstElementToRemove); + } + + // TODO(perf): what's this document fragment for? is it needed? can we at least reuse it? + var fragment = document.createDocumentFragment(); + fragment.appendChild(firstElementToRemove); + + // Copy over user data (that includes Angular's $scope etc.). Don't copy private + // data here because there's no public interface in jQuery to do that and copying over + // event listeners (which is the main use of private data) wouldn't work anyway. + jqLite(newNode).data(jqLite(firstElementToRemove).data()); + + // Remove data of the replaced element. We cannot just call .remove() + // on the element it since that would deallocate scope that is needed + // for the new node. Instead, remove the data "manually". + if (!jQuery) { + delete jqLite.cache[firstElementToRemove[jqLite.expando]]; + } else { + // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after + // the replaced element. The cleanData version monkey-patched by Angular would cause + // the scope to be trashed and we do need the very same scope to work with the new + // element. However, we cannot just cache the non-patched version and use it here as + // that would break if another library patches the method after Angular does (one + // example is jQuery UI). Instead, set a flag indicating scope destroying should be + // skipped this one time. + skipDestroyOnNextJQueryCleanData = true; + jQuery.cleanData([firstElementToRemove]); + } + + for (var k = 1, kk = elementsToRemove.length; k < kk; k++) { + var element = elementsToRemove[k]; + jqLite(element).remove(); // must do this way to clean up expando + fragment.appendChild(element); + delete elementsToRemove[k]; + } + + elementsToRemove[0] = newNode; + elementsToRemove.length = 1; + } + + + function cloneAndAnnotateFn(fn, annotation) { + return extend(function() { return fn.apply(null, arguments); }, fn, annotation); + } + + + function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) { + try { + linkFn(scope, $element, attrs, controllers, transcludeFn); + } catch (e) { + $exceptionHandler(e, startingTag($element)); + } + } + + + // Set up $watches for isolate scope and controller bindings. This process + // only occurs for isolate scopes and new scopes with controllerAs. + function initializeDirectiveBindings(scope, attrs, destination, bindings, + directive, newScope) { + var onNewScopeDestroyed; + forEach(bindings, function(definition, scopeName) { + var attrName = definition.attrName, + optional = definition.optional, + mode = definition.mode, // @, =, or & + lastValue, + parentGet, parentSet, compare; + + switch (mode) { + + case '@': + attrs.$observe(attrName, function(value) { + destination[scopeName] = value; + }); + attrs.$$observers[attrName].$$scope = scope; + if (attrs[attrName]) { + // If the attribute has been provided then we trigger an interpolation to ensure + // the value is there for use in the link fn + destination[scopeName] = $interpolate(attrs[attrName])(scope); + } + break; + + case '=': + if (optional && !attrs[attrName]) { + return; + } + parentGet = $parse(attrs[attrName]); + if (parentGet.literal) { + compare = equals; + } else { + compare = function(a, b) { return a === b || (a !== a && b !== b); }; + } + parentSet = parentGet.assign || function() { + // reset the change, or we will throw this exception on every $digest + lastValue = destination[scopeName] = parentGet(scope); + throw $compileMinErr('nonassign', + "Expression '{0}' used with directive '{1}' is non-assignable!", + attrs[attrName], directive.name); + }; + lastValue = destination[scopeName] = parentGet(scope); + var parentValueWatch = function parentValueWatch(parentValue) { + if (!compare(parentValue, destination[scopeName])) { + // we are out of sync and need to copy + if (!compare(parentValue, lastValue)) { + // parent changed and it has precedence + destination[scopeName] = parentValue; + } else { + // if the parent can be assigned then do so + parentSet(scope, parentValue = destination[scopeName]); + } + } + return lastValue = parentValue; + }; + parentValueWatch.$stateful = true; + var unwatch; + if (definition.collection) { + unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch); + } else { + unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal); + } + onNewScopeDestroyed = (onNewScopeDestroyed || []); + onNewScopeDestroyed.push(unwatch); + break; + + case '&': + // Don't assign Object.prototype method to scope + if (!attrs.hasOwnProperty(attrName) && optional) break; + + parentGet = $parse(attrs[attrName]); + + // Don't assign noop to destination if expression is not valid + if (parentGet === noop && optional) break; + + destination[scopeName] = function(locals) { + return parentGet(scope, locals); + }; + break; + } + }); + var destroyBindings = onNewScopeDestroyed ? function destroyBindings() { + for (var i = 0, ii = onNewScopeDestroyed.length; i < ii; ++i) { + onNewScopeDestroyed[i](); + } + } : noop; + if (newScope && destroyBindings !== noop) { + newScope.$on('$destroy', destroyBindings); + return noop; + } + return destroyBindings; + } + }]; +} + +var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i; +/** + * Converts all accepted directives format into proper directive name. + * @param name Name to normalize + */ +function directiveNormalize(name) { + return camelCase(name.replace(PREFIX_REGEXP, '')); +} + +/** + * @ngdoc type + * @name $compile.directive.Attributes + * + * @description + * A shared object between directive compile / linking functions which contains normalized DOM + * element attributes. The values reflect current binding state `{{ }}`. The normalization is + * needed since all of these are treated as equivalent in Angular: + * + * ``` + * + * ``` + */ + +/** + * @ngdoc property + * @name $compile.directive.Attributes#$attr + * + * @description + * A map of DOM element attribute names to the normalized name. This is + * needed to do reverse lookup from normalized name back to actual name. + */ + + +/** + * @ngdoc method + * @name $compile.directive.Attributes#$set + * @kind function + * + * @description + * Set DOM element attribute value. + * + * + * @param {string} name Normalized element attribute name of the property to modify. The name is + * reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr} + * property to the original name. + * @param {string} value Value to set the attribute to. The value can be an interpolated string. + */ + + + +/** + * Closure compiler type information + */ + +function nodesetLinkingFn( + /* angular.Scope */ scope, + /* NodeList */ nodeList, + /* Element */ rootElement, + /* function(Function) */ boundTranscludeFn +) {} + +function directiveLinkingFn( + /* nodesetLinkingFn */ nodesetLinkingFn, + /* angular.Scope */ scope, + /* Node */ node, + /* Element */ rootElement, + /* function(Function) */ boundTranscludeFn +) {} + +function tokenDifference(str1, str2) { + var values = '', + tokens1 = str1.split(/\s+/), + tokens2 = str2.split(/\s+/); + + outer: + for (var i = 0; i < tokens1.length; i++) { + var token = tokens1[i]; + for (var j = 0; j < tokens2.length; j++) { + if (token == tokens2[j]) continue outer; + } + values += (values.length > 0 ? ' ' : '') + token; + } + return values; +} + +function removeComments(jqNodes) { + jqNodes = jqLite(jqNodes); + var i = jqNodes.length; + + if (i <= 1) { + return jqNodes; + } + + while (i--) { + var node = jqNodes[i]; + if (node.nodeType === NODE_TYPE_COMMENT) { + splice.call(jqNodes, i, 1); + } + } + return jqNodes; +} + +var $controllerMinErr = minErr('$controller'); + + +var CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/; +function identifierForController(controller, ident) { + if (ident && isString(ident)) return ident; + if (isString(controller)) { + var match = CNTRL_REG.exec(controller); + if (match) return match[3]; + } +} + + +/** + * @ngdoc provider + * @name $controllerProvider + * @description + * The {@link ng.$controller $controller service} is used by Angular to create new + * controllers. + * + * This provider allows controller registration via the + * {@link ng.$controllerProvider#register register} method. + */ +function $ControllerProvider() { + var controllers = {}, + globals = false; + + /** + * @ngdoc method + * @name $controllerProvider#register + * @param {string|Object} name Controller name, or an object map of controllers where the keys are + * the names and the values are the constructors. + * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI + * annotations in the array notation). + */ + this.register = function(name, constructor) { + assertNotHasOwnProperty(name, 'controller'); + if (isObject(name)) { + extend(controllers, name); + } else { + controllers[name] = constructor; + } + }; + + /** + * @ngdoc method + * @name $controllerProvider#allowGlobals + * @description If called, allows `$controller` to find controller constructors on `window` + */ + this.allowGlobals = function() { + globals = true; + }; + + + this.$get = ['$injector', '$window', function($injector, $window) { + + /** + * @ngdoc service + * @name $controller + * @requires $injector + * + * @param {Function|string} constructor If called with a function then it's considered to be the + * controller constructor function. Otherwise it's considered to be a string which is used + * to retrieve the controller constructor using the following steps: + * + * * check if a controller with given name is registered via `$controllerProvider` + * * check if evaluating the string on the current scope returns a constructor + * * if $controllerProvider#allowGlobals, check `window[constructor]` on the global + * `window` object (not recommended) + * + * The string can use the `controller as property` syntax, where the controller instance is published + * as the specified property on the `scope`; the `scope` must be injected into `locals` param for this + * to work correctly. + * + * @param {Object} locals Injection locals for Controller. + * @return {Object} Instance of given controller. + * + * @description + * `$controller` service is responsible for instantiating controllers. + * + * It's just a simple call to {@link auto.$injector $injector}, but extracted into + * a service, so that one can override this service with [BC version](https://gist.github.com/1649788). + */ + return function(expression, locals, later, ident) { + // PRIVATE API: + // param `later` --- indicates that the controller's constructor is invoked at a later time. + // If true, $controller will allocate the object with the correct + // prototype chain, but will not invoke the controller until a returned + // callback is invoked. + // param `ident` --- An optional label which overrides the label parsed from the controller + // expression, if any. + var instance, match, constructor, identifier; + later = later === true; + if (ident && isString(ident)) { + identifier = ident; + } + + if (isString(expression)) { + match = expression.match(CNTRL_REG); + if (!match) { + throw $controllerMinErr('ctrlfmt', + "Badly formed controller string '{0}'. " + + "Must match `__name__ as __id__` or `__name__`.", expression); + } + constructor = match[1], + identifier = identifier || match[3]; + expression = controllers.hasOwnProperty(constructor) + ? controllers[constructor] + : getter(locals.$scope, constructor, true) || + (globals ? getter($window, constructor, true) : undefined); + + assertArgFn(expression, constructor, true); + } + + if (later) { + // Instantiate controller later: + // This machinery is used to create an instance of the object before calling the + // controller's constructor itself. + // + // This allows properties to be added to the controller before the constructor is + // invoked. Primarily, this is used for isolate scope bindings in $compile. + // + // This feature is not intended for use by applications, and is thus not documented + // publicly. + // Object creation: http://jsperf.com/create-constructor/2 + var controllerPrototype = (isArray(expression) ? + expression[expression.length - 1] : expression).prototype; + instance = Object.create(controllerPrototype || null); + + if (identifier) { + addIdentifier(locals, identifier, instance, constructor || expression.name); + } + + var instantiate; + return instantiate = extend(function() { + var result = $injector.invoke(expression, instance, locals, constructor); + if (result !== instance && (isObject(result) || isFunction(result))) { + instance = result; + if (identifier) { + // If result changed, re-assign controllerAs value to scope. + addIdentifier(locals, identifier, instance, constructor || expression.name); + } + } + return instance; + }, { + instance: instance, + identifier: identifier + }); + } + + instance = $injector.instantiate(expression, locals, constructor); + + if (identifier) { + addIdentifier(locals, identifier, instance, constructor || expression.name); + } + + return instance; + }; + + function addIdentifier(locals, identifier, instance, name) { + if (!(locals && isObject(locals.$scope))) { + throw minErr('$controller')('noscp', + "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.", + name, identifier); + } + + locals.$scope[identifier] = instance; + } + }]; +} + +/** + * @ngdoc service + * @name $document + * @requires $window + * + * @description + * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object. + * + * @example + + +
      +

      $document title:

      +

      window.document title:

      +
      +
      + + angular.module('documentExample', []) + .controller('ExampleController', ['$scope', '$document', function($scope, $document) { + $scope.title = $document[0].title; + $scope.windowTitle = angular.element(window.document)[0].title; + }]); + +
      + */ +function $DocumentProvider() { + this.$get = ['$window', function(window) { + return jqLite(window.document); + }]; +} + +/** + * @ngdoc service + * @name $exceptionHandler + * @requires ng.$log + * + * @description + * Any uncaught exception in angular expressions is delegated to this service. + * The default implementation simply delegates to `$log.error` which logs it into + * the browser console. + * + * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by + * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing. + * + * ## Example: + * + * ```js + * angular.module('exceptionOverride', []).factory('$exceptionHandler', function() { + * return function(exception, cause) { + * exception.message += ' (caused by "' + cause + '")'; + * throw exception; + * }; + * }); + * ``` + * + * This example will override the normal action of `$exceptionHandler`, to make angular + * exceptions fail hard when they happen, instead of just logging to the console. + * + *
      + * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind` + * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler} + * (unless executed during a digest). + * + * If you wish, you can manually delegate exceptions, e.g. + * `try { ... } catch(e) { $exceptionHandler(e); }` + * + * @param {Error} exception Exception associated with the error. + * @param {string=} cause optional information about the context in which + * the error was thrown. + * + */ +function $ExceptionHandlerProvider() { + this.$get = ['$log', function($log) { + return function(exception, cause) { + $log.error.apply($log, arguments); + }; + }]; +} + +var APPLICATION_JSON = 'application/json'; +var CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'}; +var JSON_START = /^\[|^\{(?!\{)/; +var JSON_ENDS = { + '[': /]$/, + '{': /}$/ +}; +var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/; + +function serializeValue(v) { + if (isObject(v)) { + return isDate(v) ? v.toISOString() : toJson(v); + } + return v; +} + + +function $HttpParamSerializerProvider() { + /** + * @ngdoc service + * @name $httpParamSerializer + * @description + * + * Default $http params serializer that converts objects to a part of a request URL + * according to the following rules: + * * `{'foo': 'bar'}` results in `foo=bar` + * * `{'foo': Date.now()}` results in `foo=2015-04-01T09%3A50%3A49.262Z` (`toISOString()` and encoded representation of a Date object) + * * `{'foo': ['bar', 'baz']}` results in `foo=bar&foo=baz` (repeated key for each array element) + * * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D"` (stringified and encoded representation of an object) + * */ + this.$get = function() { + return function ngParamSerializer(params) { + if (!params) return ''; + var parts = []; + forEachSorted(params, function(value, key) { + if (value === null || isUndefined(value)) return; + if (isArray(value)) { + forEach(value, function(v, k) { + parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(v))); + }); + } else { + parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(value))); + } + }); + + return parts.join('&'); + }; + }; +} + +function $HttpParamSerializerJQLikeProvider() { + /** + * @ngdoc service + * @name $httpParamSerializerJQLike + * @description + * + * Alternative $http params serializer that follows jQuery's [`param()`](http://api.jquery.com/jquery.param/) method logic. + * */ + this.$get = function() { + return function jQueryLikeParamSerializer(params) { + if (!params) return ''; + var parts = []; + serialize(params, '', true); + return parts.join('&'); + + function serialize(toSerialize, prefix, topLevel) { + if (toSerialize === null || isUndefined(toSerialize)) return; + if (isArray(toSerialize)) { + forEach(toSerialize, function(value) { + serialize(value, prefix + '[]'); + }); + } else if (isObject(toSerialize) && !isDate(toSerialize)) { + forEachSorted(toSerialize, function(value, key) { + serialize(value, prefix + + (topLevel ? '' : '[') + + key + + (topLevel ? '' : ']')); + }); + } else { + parts.push(encodeUriQuery(prefix) + '=' + encodeUriQuery(serializeValue(toSerialize))); + } + } + }; + }; +} + +function defaultHttpResponseTransform(data, headers) { + if (isString(data)) { + // Strip json vulnerability protection prefix and trim whitespace + var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim(); + + if (tempData) { + var contentType = headers('Content-Type'); + if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) { + data = fromJson(tempData); + } + } + } + + return data; +} + +function isJsonLike(str) { + var jsonStart = str.match(JSON_START); + return jsonStart && JSON_ENDS[jsonStart[0]].test(str); +} + +/** + * Parse headers into key value object + * + * @param {string} headers Raw headers as a string + * @returns {Object} Parsed headers as key value object + */ +function parseHeaders(headers) { + var parsed = createMap(), i; + + function fillInParsed(key, val) { + if (key) { + parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; + } + } + + if (isString(headers)) { + forEach(headers.split('\n'), function(line) { + i = line.indexOf(':'); + fillInParsed(lowercase(trim(line.substr(0, i))), trim(line.substr(i + 1))); + }); + } else if (isObject(headers)) { + forEach(headers, function(headerVal, headerKey) { + fillInParsed(lowercase(headerKey), trim(headerVal)); + }); + } + + return parsed; +} + + +/** + * Returns a function that provides access to parsed headers. + * + * Headers are lazy parsed when first requested. + * @see parseHeaders + * + * @param {(string|Object)} headers Headers to provide access to. + * @returns {function(string=)} Returns a getter function which if called with: + * + * - if called with single an argument returns a single header value or null + * - if called with no arguments returns an object containing all headers. + */ +function headersGetter(headers) { + var headersObj; + + return function(name) { + if (!headersObj) headersObj = parseHeaders(headers); + + if (name) { + var value = headersObj[lowercase(name)]; + if (value === void 0) { + value = null; + } + return value; + } + + return headersObj; + }; +} + + +/** + * Chain all given functions + * + * This function is used for both request and response transforming + * + * @param {*} data Data to transform. + * @param {function(string=)} headers HTTP headers getter fn. + * @param {number} status HTTP status code of the response. + * @param {(Function|Array.)} fns Function or an array of functions. + * @returns {*} Transformed data. + */ +function transformData(data, headers, status, fns) { + if (isFunction(fns)) { + return fns(data, headers, status); + } + + forEach(fns, function(fn) { + data = fn(data, headers, status); + }); + + return data; +} + + +function isSuccess(status) { + return 200 <= status && status < 300; +} + + +/** + * @ngdoc provider + * @name $httpProvider + * @description + * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service. + * */ +function $HttpProvider() { + /** + * @ngdoc property + * @name $httpProvider#defaults + * @description + * + * Object containing default values for all {@link ng.$http $http} requests. + * + * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`} + * that will provide the cache for all requests who set their `cache` property to `true`. + * If you set the `default.cache = false` then only requests that specify their own custom + * cache object will be cached. See {@link $http#caching $http Caching} for more information. + * + * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token. + * Defaults value is `'XSRF-TOKEN'`. + * + * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the + * XSRF token. Defaults value is `'X-XSRF-TOKEN'`. + * + * - **`defaults.headers`** - {Object} - Default headers for all $http requests. + * Refer to {@link ng.$http#setting-http-headers $http} for documentation on + * setting default headers. + * - **`defaults.headers.common`** + * - **`defaults.headers.post`** + * - **`defaults.headers.put`** + * - **`defaults.headers.patch`** + * + * - **`defaults.paramSerializer`** - {string|function(Object):string} - A function used to prepare string representation + * of request parameters (specified as an object). + * If specified as string, it is interpreted as a function registered with the {@link auto.$injector $injector}. + * Defaults to {@link ng.$httpParamSerializer $httpParamSerializer}. + * + **/ + var defaults = this.defaults = { + // transform incoming response data + transformResponse: [defaultHttpResponseTransform], + + // transform outgoing request data + transformRequest: [function(d) { + return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d; + }], + + // default headers + headers: { + common: { + 'Accept': 'application/json, text/plain, */*' + }, + post: shallowCopy(CONTENT_TYPE_APPLICATION_JSON), + put: shallowCopy(CONTENT_TYPE_APPLICATION_JSON), + patch: shallowCopy(CONTENT_TYPE_APPLICATION_JSON) + }, + + xsrfCookieName: 'XSRF-TOKEN', + xsrfHeaderName: 'X-XSRF-TOKEN', + + paramSerializer: '$httpParamSerializer' + }; + + var useApplyAsync = false; + /** + * @ngdoc method + * @name $httpProvider#useApplyAsync + * @description + * + * Configure $http service to combine processing of multiple http responses received at around + * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in + * significant performance improvement for bigger applications that make many HTTP requests + * concurrently (common during application bootstrap). + * + * Defaults to false. If no value is specified, returns the current configured value. + * + * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred + * "apply" on the next tick, giving time for subsequent requests in a roughly ~10ms window + * to load and share the same digest cycle. + * + * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining. + * otherwise, returns the current configured value. + **/ + this.useApplyAsync = function(value) { + if (isDefined(value)) { + useApplyAsync = !!value; + return this; + } + return useApplyAsync; + }; + + /** + * @ngdoc property + * @name $httpProvider#interceptors + * @description + * + * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http} + * pre-processing of request or postprocessing of responses. + * + * These service factories are ordered by request, i.e. they are applied in the same order as the + * array, on request, but reverse order, on response. + * + * {@link ng.$http#interceptors Interceptors detailed info} + **/ + var interceptorFactories = this.interceptors = []; + + this.$get = ['$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector', + function($httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector) { + + var defaultCache = $cacheFactory('$http'); + + /** + * Make sure that default param serializer is exposed as a function + */ + defaults.paramSerializer = isString(defaults.paramSerializer) ? + $injector.get(defaults.paramSerializer) : defaults.paramSerializer; + + /** + * Interceptors stored in reverse order. Inner interceptors before outer interceptors. + * The reversal is needed so that we can build up the interception chain around the + * server request. + */ + var reversedInterceptors = []; + + forEach(interceptorFactories, function(interceptorFactory) { + reversedInterceptors.unshift(isString(interceptorFactory) + ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory)); + }); + + /** + * @ngdoc service + * @kind function + * @name $http + * @requires ng.$httpBackend + * @requires $cacheFactory + * @requires $rootScope + * @requires $q + * @requires $injector + * + * @description + * The `$http` service is a core Angular service that facilitates communication with the remote + * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest) + * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP). + * + * For unit testing applications that use `$http` service, see + * {@link ngMock.$httpBackend $httpBackend mock}. + * + * For a higher level of abstraction, please check out the {@link ngResource.$resource + * $resource} service. + * + * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by + * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage + * it is important to familiarize yourself with these APIs and the guarantees they provide. + * + * + * ## General usage + * The `$http` service is a function which takes a single argument — a configuration object — + * that is used to generate an HTTP request and returns a {@link ng.$q promise} + * with two $http specific methods: `success` and `error`. + * + * ```js + * // Simple GET request example : + * $http.get('/someUrl'). + * success(function(data, status, headers, config) { + * // this callback will be called asynchronously + * // when the response is available + * }). + * error(function(data, status, headers, config) { + * // called asynchronously if an error occurs + * // or server returns response with an error status. + * }); + * ``` + * + * ```js + * // Simple POST request example (passing data) : + * $http.post('/someUrl', {msg:'hello word!'}). + * success(function(data, status, headers, config) { + * // this callback will be called asynchronously + * // when the response is available + * }). + * error(function(data, status, headers, config) { + * // called asynchronously if an error occurs + * // or server returns response with an error status. + * }); + * ``` + * + * + * Since the returned value of calling the $http function is a `promise`, you can also use + * the `then` method to register callbacks, and these callbacks will receive a single argument – + * an object representing the response. See the API signature and type info below for more + * details. + * + * A response status code between 200 and 299 is considered a success status and + * will result in the success callback being called. Note that if the response is a redirect, + * XMLHttpRequest will transparently follow it, meaning that the error callback will not be + * called for such responses. + * + * ## Writing Unit Tests that use $http + * When unit testing (using {@link ngMock ngMock}), it is necessary to call + * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending + * request using trained responses. + * + * ``` + * $httpBackend.expectGET(...); + * $http.get(...); + * $httpBackend.flush(); + * ``` + * + * ## Shortcut methods + * + * Shortcut methods are also available. All shortcut methods require passing in the URL, and + * request data must be passed in for POST/PUT requests. + * + * ```js + * $http.get('/someUrl').success(successCallback); + * $http.post('/someUrl', data).success(successCallback); + * ``` + * + * Complete list of shortcut methods: + * + * - {@link ng.$http#get $http.get} + * - {@link ng.$http#head $http.head} + * - {@link ng.$http#post $http.post} + * - {@link ng.$http#put $http.put} + * - {@link ng.$http#delete $http.delete} + * - {@link ng.$http#jsonp $http.jsonp} + * - {@link ng.$http#patch $http.patch} + * + * + * ## Setting HTTP Headers + * + * The $http service will automatically add certain HTTP headers to all requests. These defaults + * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration + * object, which currently contains this default configuration: + * + * - `$httpProvider.defaults.headers.common` (headers that are common for all requests): + * - `Accept: application/json, text/plain, * / *` + * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests) + * - `Content-Type: application/json` + * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests) + * - `Content-Type: application/json` + * + * To add or overwrite these defaults, simply add or remove a property from these configuration + * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object + * with the lowercased HTTP method name as the key, e.g. + * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }`. + * + * The defaults can also be set at runtime via the `$http.defaults` object in the same + * fashion. For example: + * + * ``` + * module.run(function($http) { + * $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w' + * }); + * ``` + * + * In addition, you can supply a `headers` property in the config object passed when + * calling `$http(config)`, which overrides the defaults without changing them globally. + * + * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis, + * Use the `headers` property, setting the desired header to `undefined`. For example: + * + * ```js + * var req = { + * method: 'POST', + * url: 'http://example.com', + * headers: { + * 'Content-Type': undefined + * }, + * data: { test: 'test' } + * } + * + * $http(req).success(function(){...}).error(function(){...}); + * ``` + * + * ## Transforming Requests and Responses + * + * Both requests and responses can be transformed using transformation functions: `transformRequest` + * and `transformResponse`. These properties can be a single function that returns + * the transformed value (`function(data, headersGetter, status)`) or an array of such transformation functions, + * which allows you to `push` or `unshift` a new transformation function into the transformation chain. + * + * ### Default Transformations + * + * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and + * `defaults.transformResponse` properties. If a request does not provide its own transformations + * then these will be applied. + * + * You can augment or replace the default transformations by modifying these properties by adding to or + * replacing the array. + * + * Angular provides the following default transformations: + * + * Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`): + * + * - If the `data` property of the request configuration object contains an object, serialize it + * into JSON format. + * + * Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`): + * + * - If XSRF prefix is detected, strip it (see Security Considerations section below). + * - If JSON response is detected, deserialize it using a JSON parser. + * + * + * ### Overriding the Default Transformations Per Request + * + * If you wish override the request/response transformations only for a single request then provide + * `transformRequest` and/or `transformResponse` properties on the configuration object passed + * into `$http`. + * + * Note that if you provide these properties on the config object the default transformations will be + * overwritten. If you wish to augment the default transformations then you must include them in your + * local transformation array. + * + * The following code demonstrates adding a new response transformation to be run after the default response + * transformations have been run. + * + * ```js + * function appendTransform(defaults, transform) { + * + * // We can't guarantee that the default transformation is an array + * defaults = angular.isArray(defaults) ? defaults : [defaults]; + * + * // Append the new transformation to the defaults + * return defaults.concat(transform); + * } + * + * $http({ + * url: '...', + * method: 'GET', + * transformResponse: appendTransform($http.defaults.transformResponse, function(value) { + * return doTransform(value); + * }) + * }); + * ``` + * + * + * ## Caching + * + * To enable caching, set the request configuration `cache` property to `true` (to use default + * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}). + * When the cache is enabled, `$http` stores the response from the server in the specified + * cache. The next time the same request is made, the response is served from the cache without + * sending a request to the server. + * + * Note that even if the response is served from cache, delivery of the data is asynchronous in + * the same way that real requests are. + * + * If there are multiple GET requests for the same URL that should be cached using the same + * cache, but the cache is not populated yet, only one request to the server will be made and + * the remaining requests will be fulfilled using the response from the first request. + * + * You can change the default cache to a new object (built with + * {@link ng.$cacheFactory `$cacheFactory`}) by updating the + * {@link ng.$http#defaults `$http.defaults.cache`} property. All requests who set + * their `cache` property to `true` will now use this cache object. + * + * If you set the default cache to `false` then only requests that specify their own custom + * cache object will be cached. + * + * ## Interceptors + * + * Before you start creating interceptors, be sure to understand the + * {@link ng.$q $q and deferred/promise APIs}. + * + * For purposes of global error handling, authentication, or any kind of synchronous or + * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be + * able to intercept requests before they are handed to the server and + * responses before they are handed over to the application code that + * initiated these requests. The interceptors leverage the {@link ng.$q + * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing. + * + * The interceptors are service factories that are registered with the `$httpProvider` by + * adding them to the `$httpProvider.interceptors` array. The factory is called and + * injected with dependencies (if specified) and returns the interceptor. + * + * There are two kinds of interceptors (and two kinds of rejection interceptors): + * + * * `request`: interceptors get called with a http `config` object. The function is free to + * modify the `config` object or create a new one. The function needs to return the `config` + * object directly, or a promise containing the `config` or a new `config` object. + * * `requestError`: interceptor gets called when a previous interceptor threw an error or + * resolved with a rejection. + * * `response`: interceptors get called with http `response` object. The function is free to + * modify the `response` object or create a new one. The function needs to return the `response` + * object directly, or as a promise containing the `response` or a new `response` object. + * * `responseError`: interceptor gets called when a previous interceptor threw an error or + * resolved with a rejection. + * + * + * ```js + * // register the interceptor as a service + * $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) { + * return { + * // optional method + * 'request': function(config) { + * // do something on success + * return config; + * }, + * + * // optional method + * 'requestError': function(rejection) { + * // do something on error + * if (canRecover(rejection)) { + * return responseOrNewPromise + * } + * return $q.reject(rejection); + * }, + * + * + * + * // optional method + * 'response': function(response) { + * // do something on success + * return response; + * }, + * + * // optional method + * 'responseError': function(rejection) { + * // do something on error + * if (canRecover(rejection)) { + * return responseOrNewPromise + * } + * return $q.reject(rejection); + * } + * }; + * }); + * + * $httpProvider.interceptors.push('myHttpInterceptor'); + * + * + * // alternatively, register the interceptor via an anonymous factory + * $httpProvider.interceptors.push(function($q, dependency1, dependency2) { + * return { + * 'request': function(config) { + * // same as above + * }, + * + * 'response': function(response) { + * // same as above + * } + * }; + * }); + * ``` + * + * ## Security Considerations + * + * When designing web applications, consider security threats from: + * + * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx) + * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) + * + * Both server and the client must cooperate in order to eliminate these threats. Angular comes + * pre-configured with strategies that address these issues, but for this to work backend server + * cooperation is required. + * + * ### JSON Vulnerability Protection + * + * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx) + * allows third party website to turn your JSON resource URL into + * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To + * counter this your server can prefix all JSON requests with following string `")]}',\n"`. + * Angular will automatically strip the prefix before processing it as JSON. + * + * For example if your server needs to return: + * ```js + * ['one','two'] + * ``` + * + * which is vulnerable to attack, your server can return: + * ```js + * )]}', + * ['one','two'] + * ``` + * + * Angular will strip the prefix, before processing the JSON. + * + * + * ### Cross Site Request Forgery (XSRF) Protection + * + * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which + * an unauthorized site can gain your user's private data. Angular provides a mechanism + * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie + * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only + * JavaScript that runs on your domain could read the cookie, your server can be assured that + * the XHR came from JavaScript running on your domain. The header will not be set for + * cross-domain requests. + * + * To take advantage of this, your server needs to set a token in a JavaScript readable session + * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the + * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure + * that only JavaScript running on your domain could have sent the request. The token must be + * unique for each user and must be verifiable by the server (to prevent the JavaScript from + * making up its own tokens). We recommend that the token is a digest of your site's + * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography)) + * for added security. + * + * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName + * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time, + * or the per-request config object. + * + * + * @param {object} config Object describing the request to be made and how it should be + * processed. The object has following properties: + * + * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc) + * - **url** – `{string}` – Absolute or relative URL of the resource that is being requested. + * - **params** – `{Object.}` – Map of strings or objects which will be turned + * to `?key1=value1&key2=value2` after the url. If the value is not a string, it will be + * JSONified. + * - **data** – `{string|Object}` – Data to be sent as the request message data. + * - **headers** – `{Object}` – Map of strings or functions which return strings representing + * HTTP headers to send to the server. If the return value of a function is null, the + * header will not be sent. Functions accept a config object as an argument. + * - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token. + * - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token. + * - **transformRequest** – + * `{function(data, headersGetter)|Array.}` – + * transform function or an array of such functions. The transform function takes the http + * request body and headers and returns its transformed (typically serialized) version. + * See {@link ng.$http#overriding-the-default-transformations-per-request + * Overriding the Default Transformations} + * - **transformResponse** – + * `{function(data, headersGetter, status)|Array.}` – + * transform function or an array of such functions. The transform function takes the http + * response body, headers and status and returns its transformed (typically deserialized) version. + * See {@link ng.$http#overriding-the-default-transformations-per-request + * Overriding the Default Transformations} + * - **paramSerializer** - {string|function(Object):string} - A function used to prepare string representation + * of request parameters (specified as an object). + * Is specified as string, it is interpreted as function registered in with the {$injector}. + * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the + * GET request, otherwise if a cache instance built with + * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for + * caching. + * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} + * that should abort the request when resolved. + * - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the + * XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials) + * for more information. + * - **responseType** - `{string}` - see + * [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType). + * + * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the + * standard `then` method and two http specific methods: `success` and `error`. The `then` + * method takes two arguments a success and an error callback which will be called with a + * response object. The `success` and `error` methods take a single argument - a function that + * will be called when the request succeeds or fails respectively. The arguments passed into + * these functions are destructured representation of the response object passed into the + * `then` method. The response object has these properties: + * + * - **data** – `{string|Object}` – The response body transformed with the transform + * functions. + * - **status** – `{number}` – HTTP status code of the response. + * - **headers** – `{function([headerName])}` – Header getter function. + * - **config** – `{Object}` – The configuration object that was used to generate the request. + * - **statusText** – `{string}` – HTTP status text of the response. + * + * @property {Array.} pendingRequests Array of config objects for currently pending + * requests. This is primarily meant to be used for debugging purposes. + * + * + * @example + + +
      + + +
      + + + +
      http status code: {{status}}
      +
      http response data: {{data}}
      +
      +
      + + angular.module('httpExample', []) + .controller('FetchController', ['$scope', '$http', '$templateCache', + function($scope, $http, $templateCache) { + $scope.method = 'GET'; + $scope.url = 'http-hello.html'; + + $scope.fetch = function() { + $scope.code = null; + $scope.response = null; + + $http({method: $scope.method, url: $scope.url, cache: $templateCache}). + success(function(data, status) { + $scope.status = status; + $scope.data = data; + }). + error(function(data, status) { + $scope.data = data || "Request failed"; + $scope.status = status; + }); + }; + + $scope.updateModel = function(method, url) { + $scope.method = method; + $scope.url = url; + }; + }]); + + + Hello, $http! + + + var status = element(by.binding('status')); + var data = element(by.binding('data')); + var fetchBtn = element(by.id('fetchbtn')); + var sampleGetBtn = element(by.id('samplegetbtn')); + var sampleJsonpBtn = element(by.id('samplejsonpbtn')); + var invalidJsonpBtn = element(by.id('invalidjsonpbtn')); + + it('should make an xhr GET request', function() { + sampleGetBtn.click(); + fetchBtn.click(); + expect(status.getText()).toMatch('200'); + expect(data.getText()).toMatch(/Hello, \$http!/); + }); + +// Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185 +// it('should make a JSONP request to angularjs.org', function() { +// sampleJsonpBtn.click(); +// fetchBtn.click(); +// expect(status.getText()).toMatch('200'); +// expect(data.getText()).toMatch(/Super Hero!/); +// }); + + it('should make JSONP request to invalid URL and invoke the error handler', + function() { + invalidJsonpBtn.click(); + fetchBtn.click(); + expect(status.getText()).toMatch('0'); + expect(data.getText()).toMatch('Request failed'); + }); + +
      + */ + function $http(requestConfig) { + + if (!angular.isObject(requestConfig)) { + throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig); + } + + var config = extend({ + method: 'get', + transformRequest: defaults.transformRequest, + transformResponse: defaults.transformResponse, + paramSerializer: defaults.paramSerializer + }, requestConfig); + + config.headers = mergeHeaders(requestConfig); + config.method = uppercase(config.method); + config.paramSerializer = isString(config.paramSerializer) ? + $injector.get(config.paramSerializer) : config.paramSerializer; + + var serverRequest = function(config) { + var headers = config.headers; + var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest); + + // strip content-type if data is undefined + if (isUndefined(reqData)) { + forEach(headers, function(value, header) { + if (lowercase(header) === 'content-type') { + delete headers[header]; + } + }); + } + + if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) { + config.withCredentials = defaults.withCredentials; + } + + // send request + return sendReq(config, reqData).then(transformResponse, transformResponse); + }; + + var chain = [serverRequest, undefined]; + var promise = $q.when(config); + + // apply interceptors + forEach(reversedInterceptors, function(interceptor) { + if (interceptor.request || interceptor.requestError) { + chain.unshift(interceptor.request, interceptor.requestError); + } + if (interceptor.response || interceptor.responseError) { + chain.push(interceptor.response, interceptor.responseError); + } + }); + + while (chain.length) { + var thenFn = chain.shift(); + var rejectFn = chain.shift(); + + promise = promise.then(thenFn, rejectFn); + } + + promise.success = function(fn) { + assertArgFn(fn, 'fn'); + + promise.then(function(response) { + fn(response.data, response.status, response.headers, config); + }); + return promise; + }; + + promise.error = function(fn) { + assertArgFn(fn, 'fn'); + + promise.then(null, function(response) { + fn(response.data, response.status, response.headers, config); + }); + return promise; + }; + + return promise; + + function transformResponse(response) { + // make a copy since the response must be cacheable + var resp = extend({}, response); + if (!response.data) { + resp.data = response.data; + } else { + resp.data = transformData(response.data, response.headers, response.status, config.transformResponse); + } + return (isSuccess(response.status)) + ? resp + : $q.reject(resp); + } + + function executeHeaderFns(headers, config) { + var headerContent, processedHeaders = {}; + + forEach(headers, function(headerFn, header) { + if (isFunction(headerFn)) { + headerContent = headerFn(config); + if (headerContent != null) { + processedHeaders[header] = headerContent; + } + } else { + processedHeaders[header] = headerFn; + } + }); + + return processedHeaders; + } + + function mergeHeaders(config) { + var defHeaders = defaults.headers, + reqHeaders = extend({}, config.headers), + defHeaderName, lowercaseDefHeaderName, reqHeaderName; + + defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]); + + // using for-in instead of forEach to avoid unecessary iteration after header has been found + defaultHeadersIteration: + for (defHeaderName in defHeaders) { + lowercaseDefHeaderName = lowercase(defHeaderName); + + for (reqHeaderName in reqHeaders) { + if (lowercase(reqHeaderName) === lowercaseDefHeaderName) { + continue defaultHeadersIteration; + } + } + + reqHeaders[defHeaderName] = defHeaders[defHeaderName]; + } + + // execute if header value is a function for merged headers + return executeHeaderFns(reqHeaders, shallowCopy(config)); + } + } + + $http.pendingRequests = []; + + /** + * @ngdoc method + * @name $http#get + * + * @description + * Shortcut method to perform `GET` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#delete + * + * @description + * Shortcut method to perform `DELETE` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#head + * + * @description + * Shortcut method to perform `HEAD` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#jsonp + * + * @description + * Shortcut method to perform `JSONP` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request. + * The name of the callback should be the string `JSON_CALLBACK`. + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + createShortMethods('get', 'delete', 'head', 'jsonp'); + + /** + * @ngdoc method + * @name $http#post + * + * @description + * Shortcut method to perform `POST` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {*} data Request content + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#put + * + * @description + * Shortcut method to perform `PUT` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {*} data Request content + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#patch + * + * @description + * Shortcut method to perform `PATCH` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {*} data Request content + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + createShortMethodsWithData('post', 'put', 'patch'); + + /** + * @ngdoc property + * @name $http#defaults + * + * @description + * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of + * default headers, withCredentials as well as request and response transformations. + * + * See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above. + */ + $http.defaults = defaults; + + + return $http; + + + function createShortMethods(names) { + forEach(arguments, function(name) { + $http[name] = function(url, config) { + return $http(extend({}, config || {}, { + method: name, + url: url + })); + }; + }); + } + + + function createShortMethodsWithData(name) { + forEach(arguments, function(name) { + $http[name] = function(url, data, config) { + return $http(extend({}, config || {}, { + method: name, + url: url, + data: data + })); + }; + }); + } + + + /** + * Makes the request. + * + * !!! ACCESSES CLOSURE VARS: + * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests + */ + function sendReq(config, reqData) { + var deferred = $q.defer(), + promise = deferred.promise, + cache, + cachedResp, + reqHeaders = config.headers, + url = buildUrl(config.url, config.paramSerializer(config.params)); + + $http.pendingRequests.push(config); + promise.then(removePendingReq, removePendingReq); + + + if ((config.cache || defaults.cache) && config.cache !== false && + (config.method === 'GET' || config.method === 'JSONP')) { + cache = isObject(config.cache) ? config.cache + : isObject(defaults.cache) ? defaults.cache + : defaultCache; + } + + if (cache) { + cachedResp = cache.get(url); + if (isDefined(cachedResp)) { + if (isPromiseLike(cachedResp)) { + // cached request has already been sent, but there is no response yet + cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult); + } else { + // serving from cache + if (isArray(cachedResp)) { + resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]); + } else { + resolvePromise(cachedResp, 200, {}, 'OK'); + } + } + } else { + // put the promise for the non-transformed response into cache as a placeholder + cache.put(url, promise); + } + } + + + // if we won't have the response in cache, set the xsrf headers and + // send the request to the backend + if (isUndefined(cachedResp)) { + var xsrfValue = urlIsSameOrigin(config.url) + ? $$cookieReader()[config.xsrfCookieName || defaults.xsrfCookieName] + : undefined; + if (xsrfValue) { + reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue; + } + + $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout, + config.withCredentials, config.responseType); + } + + return promise; + + + /** + * Callback registered to $httpBackend(): + * - caches the response if desired + * - resolves the raw $http promise + * - calls $apply + */ + function done(status, response, headersString, statusText) { + if (cache) { + if (isSuccess(status)) { + cache.put(url, [status, response, parseHeaders(headersString), statusText]); + } else { + // remove promise from the cache + cache.remove(url); + } + } + + function resolveHttpPromise() { + resolvePromise(response, status, headersString, statusText); + } + + if (useApplyAsync) { + $rootScope.$applyAsync(resolveHttpPromise); + } else { + resolveHttpPromise(); + if (!$rootScope.$$phase) $rootScope.$apply(); + } + } + + + /** + * Resolves the raw $http promise. + */ + function resolvePromise(response, status, headers, statusText) { + // normalize internal statuses to 0 + status = Math.max(status, 0); + + (isSuccess(status) ? deferred.resolve : deferred.reject)({ + data: response, + status: status, + headers: headersGetter(headers), + config: config, + statusText: statusText + }); + } + + function resolvePromiseWithResult(result) { + resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText); + } + + function removePendingReq() { + var idx = $http.pendingRequests.indexOf(config); + if (idx !== -1) $http.pendingRequests.splice(idx, 1); + } + } + + + function buildUrl(url, serializedParams) { + if (serializedParams.length > 0) { + url += ((url.indexOf('?') == -1) ? '?' : '&') + serializedParams; + } + return url; + } + }]; +} + +function createXhr() { + return new window.XMLHttpRequest(); +} + +/** + * @ngdoc service + * @name $httpBackend + * @requires $window + * @requires $document + * + * @description + * HTTP backend used by the {@link ng.$http service} that delegates to + * XMLHttpRequest object or JSONP and deals with browser incompatibilities. + * + * You should never need to use this service directly, instead use the higher-level abstractions: + * {@link ng.$http $http} or {@link ngResource.$resource $resource}. + * + * During testing this implementation is swapped with {@link ngMock.$httpBackend mock + * $httpBackend} which can be trained with responses. + */ +function $HttpBackendProvider() { + this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) { + return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]); + }]; +} + +function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { + // TODO(vojta): fix the signature + return function(method, url, post, callback, headers, timeout, withCredentials, responseType) { + $browser.$$incOutstandingRequestCount(); + url = url || $browser.url(); + + if (lowercase(method) == 'jsonp') { + var callbackId = '_' + (callbacks.counter++).toString(36); + callbacks[callbackId] = function(data) { + callbacks[callbackId].data = data; + callbacks[callbackId].called = true; + }; + + var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId), + callbackId, function(status, text) { + completeRequest(callback, status, callbacks[callbackId].data, "", text); + callbacks[callbackId] = noop; + }); + } else { + + var xhr = createXhr(); + + xhr.open(method, url, true); + forEach(headers, function(value, key) { + if (isDefined(value)) { + xhr.setRequestHeader(key, value); + } + }); + + xhr.onload = function requestLoaded() { + var statusText = xhr.statusText || ''; + + // responseText is the old-school way of retrieving response (supported by IE8 & 9) + // response/responseType properties were introduced in XHR Level2 spec (supported by IE10) + var response = ('response' in xhr) ? xhr.response : xhr.responseText; + + // normalize IE9 bug (http://bugs.jquery.com/ticket/1450) + var status = xhr.status === 1223 ? 204 : xhr.status; + + // fix status code when it is 0 (0 status is undocumented). + // Occurs when accessing file resources or on Android 4.1 stock browser + // while retrieving files from application cache. + if (status === 0) { + status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0; + } + + completeRequest(callback, + status, + response, + xhr.getAllResponseHeaders(), + statusText); + }; + + var requestError = function() { + // The response is always empty + // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error + completeRequest(callback, -1, null, null, ''); + }; + + xhr.onerror = requestError; + xhr.onabort = requestError; + + if (withCredentials) { + xhr.withCredentials = true; + } + + if (responseType) { + try { + xhr.responseType = responseType; + } catch (e) { + // WebKit added support for the json responseType value on 09/03/2013 + // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are + // known to throw when setting the value "json" as the response type. Other older + // browsers implementing the responseType + // + // The json response type can be ignored if not supported, because JSON payloads are + // parsed on the client-side regardless. + if (responseType !== 'json') { + throw e; + } + } + } + + xhr.send(post); + } + + if (timeout > 0) { + var timeoutId = $browserDefer(timeoutRequest, timeout); + } else if (isPromiseLike(timeout)) { + timeout.then(timeoutRequest); + } + + + function timeoutRequest() { + jsonpDone && jsonpDone(); + xhr && xhr.abort(); + } + + function completeRequest(callback, status, response, headersString, statusText) { + // cancel timeout and subsequent timeout promise resolution + if (timeoutId !== undefined) { + $browserDefer.cancel(timeoutId); + } + jsonpDone = xhr = null; + + callback(status, response, headersString, statusText); + $browser.$$completeOutstandingRequest(noop); + } + }; + + function jsonpReq(url, callbackId, done) { + // we can't use jQuery/jqLite here because jQuery does crazy stuff with script elements, e.g.: + // - fetches local scripts via XHR and evals them + // - adds and immediately removes script elements from the document + var script = rawDocument.createElement('script'), callback = null; + script.type = "text/javascript"; + script.src = url; + script.async = true; + + callback = function(event) { + removeEventListenerFn(script, "load", callback); + removeEventListenerFn(script, "error", callback); + rawDocument.body.removeChild(script); + script = null; + var status = -1; + var text = "unknown"; + + if (event) { + if (event.type === "load" && !callbacks[callbackId].called) { + event = { type: "error" }; + } + text = event.type; + status = event.type === "error" ? 404 : 200; + } + + if (done) { + done(status, text); + } + }; + + addEventListenerFn(script, "load", callback); + addEventListenerFn(script, "error", callback); + rawDocument.body.appendChild(script); + return callback; + } +} + +var $interpolateMinErr = angular.$interpolateMinErr = minErr('$interpolate'); +$interpolateMinErr.throwNoconcat = function(text) { + throw $interpolateMinErr('noconcat', + "Error while interpolating: {0}\nStrict Contextual Escaping disallows " + + "interpolations that concatenate multiple expressions when a trusted value is " + + "required. See http://docs.angularjs.org/api/ng.$sce", text); +}; + +$interpolateMinErr.interr = function(text, err) { + return $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, err.toString()); +}; + +/** + * @ngdoc provider + * @name $interpolateProvider + * + * @description + * + * Used for configuring the interpolation markup. Defaults to `{{` and `}}`. + * + * @example + + + +
      + //demo.label// +
      +
      + + it('should interpolate binding with custom symbols', function() { + expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.'); + }); + +
      + */ +function $InterpolateProvider() { + var startSymbol = '{{'; + var endSymbol = '}}'; + + /** + * @ngdoc method + * @name $interpolateProvider#startSymbol + * @description + * Symbol to denote start of expression in the interpolated string. Defaults to `{{`. + * + * @param {string=} value new value to set the starting symbol to. + * @returns {string|self} Returns the symbol when used as getter and self if used as setter. + */ + this.startSymbol = function(value) { + if (value) { + startSymbol = value; + return this; + } else { + return startSymbol; + } + }; + + /** + * @ngdoc method + * @name $interpolateProvider#endSymbol + * @description + * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`. + * + * @param {string=} value new value to set the ending symbol to. + * @returns {string|self} Returns the symbol when used as getter and self if used as setter. + */ + this.endSymbol = function(value) { + if (value) { + endSymbol = value; + return this; + } else { + return endSymbol; + } + }; + + + this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) { + var startSymbolLength = startSymbol.length, + endSymbolLength = endSymbol.length, + escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'), + escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g'); + + function escape(ch) { + return '\\\\\\' + ch; + } + + function unescapeText(text) { + return text.replace(escapedStartRegexp, startSymbol). + replace(escapedEndRegexp, endSymbol); + } + + function stringify(value) { + if (value == null) { // null || undefined + return ''; + } + switch (typeof value) { + case 'string': + break; + case 'number': + value = '' + value; + break; + default: + value = toJson(value); + } + + return value; + } + + /** + * @ngdoc service + * @name $interpolate + * @kind function + * + * @requires $parse + * @requires $sce + * + * @description + * + * Compiles a string with markup into an interpolation function. This service is used by the + * HTML {@link ng.$compile $compile} service for data binding. See + * {@link ng.$interpolateProvider $interpolateProvider} for configuring the + * interpolation markup. + * + * + * ```js + * var $interpolate = ...; // injected + * var exp = $interpolate('Hello {{name | uppercase}}!'); + * expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!'); + * ``` + * + * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is + * `true`, the interpolation function will return `undefined` unless all embedded expressions + * evaluate to a value other than `undefined`. + * + * ```js + * var $interpolate = ...; // injected + * var context = {greeting: 'Hello', name: undefined }; + * + * // default "forgiving" mode + * var exp = $interpolate('{{greeting}} {{name}}!'); + * expect(exp(context)).toEqual('Hello !'); + * + * // "allOrNothing" mode + * exp = $interpolate('{{greeting}} {{name}}!', false, null, true); + * expect(exp(context)).toBeUndefined(); + * context.name = 'Angular'; + * expect(exp(context)).toEqual('Hello Angular!'); + * ``` + * + * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior. + * + * ####Escaped Interpolation + * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers + * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash). + * It will be rendered as a regular start/end marker, and will not be interpreted as an expression + * or binding. + * + * This enables web-servers to prevent script injection attacks and defacing attacks, to some + * degree, while also enabling code examples to work without relying on the + * {@link ng.directive:ngNonBindable ngNonBindable} directive. + * + * **For security purposes, it is strongly encouraged that web servers escape user-supplied data, + * replacing angle brackets (<, >) with &lt; and &gt; respectively, and replacing all + * interpolation start/end markers with their escaped counterparts.** + * + * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered + * output when the $interpolate service processes the text. So, for HTML elements interpolated + * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter + * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such, + * this is typically useful only when user-data is used in rendering a template from the server, or + * when otherwise untrusted data is used by a directive. + * + * + * + *
      + *

      {{apptitle}}: \{\{ username = "defaced value"; \}\} + *

      + *

      {{username}} attempts to inject code which will deface the + * application, but fails to accomplish their task, because the server has correctly + * escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash) + * characters.

      + *

      Instead, the result of the attempted script injection is visible, and can be removed + * from the database by an administrator.

      + *
      + *
      + *
      + * + * @param {string} text The text with markup to interpolate. + * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have + * embedded expression in order to return an interpolation function. Strings with no + * embedded expression will return null for the interpolation function. + * @param {string=} trustedContext when provided, the returned function passes the interpolated + * result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult, + * trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that + * provides Strict Contextual Escaping for details. + * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined + * unless all embedded expressions evaluate to a value other than `undefined`. + * @returns {function(context)} an interpolation function which is used to compute the + * interpolated string. The function has these parameters: + * + * - `context`: evaluation context for all expressions embedded in the interpolated text + */ + function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) { + allOrNothing = !!allOrNothing; + var startIndex, + endIndex, + index = 0, + expressions = [], + parseFns = [], + textLength = text.length, + exp, + concat = [], + expressionPositions = []; + + while (index < textLength) { + if (((startIndex = text.indexOf(startSymbol, index)) != -1) && + ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1)) { + if (index !== startIndex) { + concat.push(unescapeText(text.substring(index, startIndex))); + } + exp = text.substring(startIndex + startSymbolLength, endIndex); + expressions.push(exp); + parseFns.push($parse(exp, parseStringifyInterceptor)); + index = endIndex + endSymbolLength; + expressionPositions.push(concat.length); + concat.push(''); + } else { + // we did not find an interpolation, so we have to add the remainder to the separators array + if (index !== textLength) { + concat.push(unescapeText(text.substring(index))); + } + break; + } + } + + // Concatenating expressions makes it hard to reason about whether some combination of + // concatenated values are unsafe to use and could easily lead to XSS. By requiring that a + // single expression be used for iframe[src], object[src], etc., we ensure that the value + // that's used is assigned or constructed by some JS code somewhere that is more testable or + // make it obvious that you bound the value to some user controlled value. This helps reduce + // the load when auditing for XSS issues. + if (trustedContext && concat.length > 1) { + $interpolateMinErr.throwNoconcat(text); + } + + if (!mustHaveExpression || expressions.length) { + var compute = function(values) { + for (var i = 0, ii = expressions.length; i < ii; i++) { + if (allOrNothing && isUndefined(values[i])) return; + concat[expressionPositions[i]] = values[i]; + } + return concat.join(''); + }; + + var getValue = function(value) { + return trustedContext ? + $sce.getTrusted(trustedContext, value) : + $sce.valueOf(value); + }; + + return extend(function interpolationFn(context) { + var i = 0; + var ii = expressions.length; + var values = new Array(ii); + + try { + for (; i < ii; i++) { + values[i] = parseFns[i](context); + } + + return compute(values); + } catch (err) { + $exceptionHandler($interpolateMinErr.interr(text, err)); + } + + }, { + // all of these properties are undocumented for now + exp: text, //just for compatibility with regular watchers created via $watch + expressions: expressions, + $$watchDelegate: function(scope, listener) { + var lastValue; + return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) { + var currValue = compute(values); + if (isFunction(listener)) { + listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope); + } + lastValue = currValue; + }); + } + }); + } + + function parseStringifyInterceptor(value) { + try { + value = getValue(value); + return allOrNothing && !isDefined(value) ? value : stringify(value); + } catch (err) { + $exceptionHandler($interpolateMinErr.interr(text, err)); + } + } + } + + + /** + * @ngdoc method + * @name $interpolate#startSymbol + * @description + * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`. + * + * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change + * the symbol. + * + * @returns {string} start symbol. + */ + $interpolate.startSymbol = function() { + return startSymbol; + }; + + + /** + * @ngdoc method + * @name $interpolate#endSymbol + * @description + * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`. + * + * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change + * the symbol. + * + * @returns {string} end symbol. + */ + $interpolate.endSymbol = function() { + return endSymbol; + }; + + return $interpolate; + }]; +} + +function $IntervalProvider() { + this.$get = ['$rootScope', '$window', '$q', '$$q', + function($rootScope, $window, $q, $$q) { + var intervals = {}; + + + /** + * @ngdoc service + * @name $interval + * + * @description + * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay` + * milliseconds. + * + * The return value of registering an interval function is a promise. This promise will be + * notified upon each tick of the interval, and will be resolved after `count` iterations, or + * run indefinitely if `count` is not defined. The value of the notification will be the + * number of iterations that have run. + * To cancel an interval, call `$interval.cancel(promise)`. + * + * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to + * move forward by `millis` milliseconds and trigger any functions scheduled to run in that + * time. + * + *
      + * **Note**: Intervals created by this service must be explicitly destroyed when you are finished + * with them. In particular they are not automatically destroyed when a controller's scope or a + * directive's element are destroyed. + * You should take this into consideration and make sure to always cancel the interval at the + * appropriate moment. See the example below for more details on how and when to do this. + *
      + * + * @param {function()} fn A function that should be called repeatedly. + * @param {number} delay Number of milliseconds between each function call. + * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat + * indefinitely. + * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise + * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. + * @param {...*=} Pass additional parameters to the executed function. + * @returns {promise} A promise which will be notified on each iteration. + * + * @example + * + * + * + * + *
      + *
      + *
      + * Current time is: + *
      + * Blood 1 : {{blood_1}} + * Blood 2 : {{blood_2}} + * + * + * + *
      + *
      + * + *
      + *
      + */ + function interval(fn, delay, count, invokeApply) { + var hasParams = arguments.length > 4, + args = hasParams ? sliceArgs(arguments, 4) : [], + setInterval = $window.setInterval, + clearInterval = $window.clearInterval, + iteration = 0, + skipApply = (isDefined(invokeApply) && !invokeApply), + deferred = (skipApply ? $$q : $q).defer(), + promise = deferred.promise; + + count = isDefined(count) ? count : 0; + + promise.then(null, null, (!hasParams) ? fn : function() { + fn.apply(null, args); + }); + + promise.$$intervalId = setInterval(function tick() { + deferred.notify(iteration++); + + if (count > 0 && iteration >= count) { + deferred.resolve(iteration); + clearInterval(promise.$$intervalId); + delete intervals[promise.$$intervalId]; + } + + if (!skipApply) $rootScope.$apply(); + + }, delay); + + intervals[promise.$$intervalId] = deferred; + + return promise; + } + + + /** + * @ngdoc method + * @name $interval#cancel + * + * @description + * Cancels a task associated with the `promise`. + * + * @param {promise} promise returned by the `$interval` function. + * @returns {boolean} Returns `true` if the task was successfully canceled. + */ + interval.cancel = function(promise) { + if (promise && promise.$$intervalId in intervals) { + intervals[promise.$$intervalId].reject('canceled'); + $window.clearInterval(promise.$$intervalId); + delete intervals[promise.$$intervalId]; + return true; + } + return false; + }; + + return interval; + }]; +} + +/** + * @ngdoc service + * @name $locale + * + * @description + * $locale service provides localization rules for various Angular components. As of right now the + * only public api is: + * + * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`) + */ +function $LocaleProvider() { + this.$get = function() { + return { + id: 'en-us', + + NUMBER_FORMATS: { + DECIMAL_SEP: '.', + GROUP_SEP: ',', + PATTERNS: [ + { // Decimal Pattern + minInt: 1, + minFrac: 0, + maxFrac: 3, + posPre: '', + posSuf: '', + negPre: '-', + negSuf: '', + gSize: 3, + lgSize: 3 + },{ //Currency Pattern + minInt: 1, + minFrac: 2, + maxFrac: 2, + posPre: '\u00A4', + posSuf: '', + negPre: '(\u00A4', + negSuf: ')', + gSize: 3, + lgSize: 3 + } + ], + CURRENCY_SYM: '$' + }, + + DATETIME_FORMATS: { + MONTH: + 'January,February,March,April,May,June,July,August,September,October,November,December' + .split(','), + SHORTMONTH: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','), + DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','), + SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','), + AMPMS: ['AM','PM'], + medium: 'MMM d, y h:mm:ss a', + 'short': 'M/d/yy h:mm a', + fullDate: 'EEEE, MMMM d, y', + longDate: 'MMMM d, y', + mediumDate: 'MMM d, y', + shortDate: 'M/d/yy', + mediumTime: 'h:mm:ss a', + shortTime: 'h:mm a', + ERANAMES: [ + "Before Christ", + "Anno Domini" + ], + ERAS: [ + "BC", + "AD" + ] + }, + + pluralCat: function(num) { + if (num === 1) { + return 'one'; + } + return 'other'; + } + }; + }; +} + +var PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/, + DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21}; +var $locationMinErr = minErr('$location'); + + +/** + * Encode path using encodeUriSegment, ignoring forward slashes + * + * @param {string} path Path to encode + * @returns {string} + */ +function encodePath(path) { + var segments = path.split('/'), + i = segments.length; + + while (i--) { + segments[i] = encodeUriSegment(segments[i]); + } + + return segments.join('/'); +} + +function parseAbsoluteUrl(absoluteUrl, locationObj) { + var parsedUrl = urlResolve(absoluteUrl); + + locationObj.$$protocol = parsedUrl.protocol; + locationObj.$$host = parsedUrl.hostname; + locationObj.$$port = toInt(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null; +} + + +function parseAppUrl(relativeUrl, locationObj) { + var prefixed = (relativeUrl.charAt(0) !== '/'); + if (prefixed) { + relativeUrl = '/' + relativeUrl; + } + var match = urlResolve(relativeUrl); + locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ? + match.pathname.substring(1) : match.pathname); + locationObj.$$search = parseKeyValue(match.search); + locationObj.$$hash = decodeURIComponent(match.hash); + + // make sure path starts with '/'; + if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') { + locationObj.$$path = '/' + locationObj.$$path; + } +} + + +/** + * + * @param {string} begin + * @param {string} whole + * @returns {string} returns text from whole after begin or undefined if it does not begin with + * expected string. + */ +function beginsWith(begin, whole) { + if (whole.indexOf(begin) === 0) { + return whole.substr(begin.length); + } +} + + +function stripHash(url) { + var index = url.indexOf('#'); + return index == -1 ? url : url.substr(0, index); +} + +function trimEmptyHash(url) { + return url.replace(/(#.+)|#$/, '$1'); +} + + +function stripFile(url) { + return url.substr(0, stripHash(url).lastIndexOf('/') + 1); +} + +/* return the server only (scheme://host:port) */ +function serverBase(url) { + return url.substring(0, url.indexOf('/', url.indexOf('//') + 2)); +} + + +/** + * LocationHtml5Url represents an url + * This object is exposed as $location service when HTML5 mode is enabled and supported + * + * @constructor + * @param {string} appBase application base URL + * @param {string} basePrefix url path prefix + */ +function LocationHtml5Url(appBase, basePrefix) { + this.$$html5 = true; + basePrefix = basePrefix || ''; + var appBaseNoFile = stripFile(appBase); + parseAbsoluteUrl(appBase, this); + + + /** + * Parse given html5 (regular) url string into properties + * @param {string} url HTML5 url + * @private + */ + this.$$parse = function(url) { + var pathUrl = beginsWith(appBaseNoFile, url); + if (!isString(pathUrl)) { + throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url, + appBaseNoFile); + } + + parseAppUrl(pathUrl, this); + + if (!this.$$path) { + this.$$path = '/'; + } + + this.$$compose(); + }; + + /** + * Compose url and update `absUrl` property + * @private + */ + this.$$compose = function() { + var search = toKeyValue(this.$$search), + hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; + + this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; + this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/' + }; + + this.$$parseLinkUrl = function(url, relHref) { + if (relHref && relHref[0] === '#') { + // special case for links to hash fragments: + // keep the old url and only replace the hash fragment + this.hash(relHref.slice(1)); + return true; + } + var appUrl, prevAppUrl; + var rewrittenUrl; + + if ((appUrl = beginsWith(appBase, url)) !== undefined) { + prevAppUrl = appUrl; + if ((appUrl = beginsWith(basePrefix, appUrl)) !== undefined) { + rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl); + } else { + rewrittenUrl = appBase + prevAppUrl; + } + } else if ((appUrl = beginsWith(appBaseNoFile, url)) !== undefined) { + rewrittenUrl = appBaseNoFile + appUrl; + } else if (appBaseNoFile == url + '/') { + rewrittenUrl = appBaseNoFile; + } + if (rewrittenUrl) { + this.$$parse(rewrittenUrl); + } + return !!rewrittenUrl; + }; +} + + +/** + * LocationHashbangUrl represents url + * This object is exposed as $location service when developer doesn't opt into html5 mode. + * It also serves as the base class for html5 mode fallback on legacy browsers. + * + * @constructor + * @param {string} appBase application base URL + * @param {string} hashPrefix hashbang prefix + */ +function LocationHashbangUrl(appBase, hashPrefix) { + var appBaseNoFile = stripFile(appBase); + + parseAbsoluteUrl(appBase, this); + + + /** + * Parse given hashbang url into properties + * @param {string} url Hashbang url + * @private + */ + this.$$parse = function(url) { + var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url); + var withoutHashUrl; + + if (withoutBaseUrl.charAt(0) === '#') { + + // The rest of the url starts with a hash so we have + // got either a hashbang path or a plain hash fragment + withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl); + if (isUndefined(withoutHashUrl)) { + // There was no hashbang prefix so we just have a hash fragment + withoutHashUrl = withoutBaseUrl; + } + + } else { + // There was no hashbang path nor hash fragment: + // If we are in HTML5 mode we use what is left as the path; + // Otherwise we ignore what is left + withoutHashUrl = this.$$html5 ? withoutBaseUrl : ''; + } + + parseAppUrl(withoutHashUrl, this); + + this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase); + + this.$$compose(); + + /* + * In Windows, on an anchor node on documents loaded from + * the filesystem, the browser will return a pathname + * prefixed with the drive name ('/C:/path') when a + * pathname without a drive is set: + * * a.setAttribute('href', '/foo') + * * a.pathname === '/C:/foo' //true + * + * Inside of Angular, we're always using pathnames that + * do not include drive names for routing. + */ + function removeWindowsDriveName(path, url, base) { + /* + Matches paths for file protocol on windows, + such as /C:/foo/bar, and captures only /foo/bar. + */ + var windowsFilePathExp = /^\/[A-Z]:(\/.*)/; + + var firstPathSegmentMatch; + + //Get the relative path from the input URL. + if (url.indexOf(base) === 0) { + url = url.replace(base, ''); + } + + // The input URL intentionally contains a first path segment that ends with a colon. + if (windowsFilePathExp.exec(url)) { + return path; + } + + firstPathSegmentMatch = windowsFilePathExp.exec(path); + return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path; + } + }; + + /** + * Compose hashbang url and update `absUrl` property + * @private + */ + this.$$compose = function() { + var search = toKeyValue(this.$$search), + hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; + + this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; + this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : ''); + }; + + this.$$parseLinkUrl = function(url, relHref) { + if (stripHash(appBase) == stripHash(url)) { + this.$$parse(url); + return true; + } + return false; + }; +} + + +/** + * LocationHashbangUrl represents url + * This object is exposed as $location service when html5 history api is enabled but the browser + * does not support it. + * + * @constructor + * @param {string} appBase application base URL + * @param {string} hashPrefix hashbang prefix + */ +function LocationHashbangInHtml5Url(appBase, hashPrefix) { + this.$$html5 = true; + LocationHashbangUrl.apply(this, arguments); + + var appBaseNoFile = stripFile(appBase); + + this.$$parseLinkUrl = function(url, relHref) { + if (relHref && relHref[0] === '#') { + // special case for links to hash fragments: + // keep the old url and only replace the hash fragment + this.hash(relHref.slice(1)); + return true; + } + + var rewrittenUrl; + var appUrl; + + if (appBase == stripHash(url)) { + rewrittenUrl = url; + } else if ((appUrl = beginsWith(appBaseNoFile, url))) { + rewrittenUrl = appBase + hashPrefix + appUrl; + } else if (appBaseNoFile === url + '/') { + rewrittenUrl = appBaseNoFile; + } + if (rewrittenUrl) { + this.$$parse(rewrittenUrl); + } + return !!rewrittenUrl; + }; + + this.$$compose = function() { + var search = toKeyValue(this.$$search), + hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; + + this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; + // include hashPrefix in $$absUrl when $$url is empty so IE8 & 9 do not reload page because of removal of '#' + this.$$absUrl = appBase + hashPrefix + this.$$url; + }; + +} + + +var locationPrototype = { + + /** + * Are we in html5 mode? + * @private + */ + $$html5: false, + + /** + * Has any change been replacing? + * @private + */ + $$replace: false, + + /** + * @ngdoc method + * @name $location#absUrl + * + * @description + * This method is getter only. + * + * Return full url representation with all segments encoded according to rules specified in + * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt). + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var absUrl = $location.absUrl(); + * // => "http://example.com/#/some/path?foo=bar&baz=xoxo" + * ``` + * + * @return {string} full url + */ + absUrl: locationGetter('$$absUrl'), + + /** + * @ngdoc method + * @name $location#url + * + * @description + * This method is getter / setter. + * + * Return url (e.g. `/path?a=b#hash`) when called without any parameter. + * + * Change path, search and hash, when called with parameter and return `$location`. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var url = $location.url(); + * // => "/some/path?foo=bar&baz=xoxo" + * ``` + * + * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`) + * @return {string} url + */ + url: function(url) { + if (isUndefined(url)) { + return this.$$url; + } + + var match = PATH_MATCH.exec(url); + if (match[1] || url === '') this.path(decodeURIComponent(match[1])); + if (match[2] || match[1] || url === '') this.search(match[3] || ''); + this.hash(match[5] || ''); + + return this; + }, + + /** + * @ngdoc method + * @name $location#protocol + * + * @description + * This method is getter only. + * + * Return protocol of current url. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var protocol = $location.protocol(); + * // => "http" + * ``` + * + * @return {string} protocol of current url + */ + protocol: locationGetter('$$protocol'), + + /** + * @ngdoc method + * @name $location#host + * + * @description + * This method is getter only. + * + * Return host of current url. + * + * Note: compared to the non-angular version `location.host` which returns `hostname:port`, this returns the `hostname` portion only. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var host = $location.host(); + * // => "example.com" + * + * // given url http://user:password@example.com:8080/#/some/path?foo=bar&baz=xoxo + * host = $location.host(); + * // => "example.com" + * host = location.host; + * // => "example.com:8080" + * ``` + * + * @return {string} host of current url. + */ + host: locationGetter('$$host'), + + /** + * @ngdoc method + * @name $location#port + * + * @description + * This method is getter only. + * + * Return port of current url. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var port = $location.port(); + * // => 80 + * ``` + * + * @return {Number} port + */ + port: locationGetter('$$port'), + + /** + * @ngdoc method + * @name $location#path + * + * @description + * This method is getter / setter. + * + * Return path of current url when called without any parameter. + * + * Change path when called with parameter and return `$location`. + * + * Note: Path should always begin with forward slash (/), this method will add the forward slash + * if it is missing. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var path = $location.path(); + * // => "/some/path" + * ``` + * + * @param {(string|number)=} path New path + * @return {string} path + */ + path: locationGetterSetter('$$path', function(path) { + path = path !== null ? path.toString() : ''; + return path.charAt(0) == '/' ? path : '/' + path; + }), + + /** + * @ngdoc method + * @name $location#search + * + * @description + * This method is getter / setter. + * + * Return search part (as object) of current url when called without any parameter. + * + * Change search part when called with parameter and return `$location`. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var searchObject = $location.search(); + * // => {foo: 'bar', baz: 'xoxo'} + * + * // set foo to 'yipee' + * $location.search('foo', 'yipee'); + * // $location.search() => {foo: 'yipee', baz: 'xoxo'} + * ``` + * + * @param {string|Object.|Object.>} search New search params - string or + * hash object. + * + * When called with a single argument the method acts as a setter, setting the `search` component + * of `$location` to the specified value. + * + * If the argument is a hash object containing an array of values, these values will be encoded + * as duplicate search parameters in the url. + * + * @param {(string|Number|Array|boolean)=} paramValue If `search` is a string or number, then `paramValue` + * will override only a single search property. + * + * If `paramValue` is an array, it will override the property of the `search` component of + * `$location` specified via the first argument. + * + * If `paramValue` is `null`, the property specified via the first argument will be deleted. + * + * If `paramValue` is `true`, the property specified via the first argument will be added with no + * value nor trailing equal sign. + * + * @return {Object} If called with no arguments returns the parsed `search` object. If called with + * one or more arguments returns `$location` object itself. + */ + search: function(search, paramValue) { + switch (arguments.length) { + case 0: + return this.$$search; + case 1: + if (isString(search) || isNumber(search)) { + search = search.toString(); + this.$$search = parseKeyValue(search); + } else if (isObject(search)) { + search = copy(search, {}); + // remove object undefined or null properties + forEach(search, function(value, key) { + if (value == null) delete search[key]; + }); + + this.$$search = search; + } else { + throw $locationMinErr('isrcharg', + 'The first argument of the `$location#search()` call must be a string or an object.'); + } + break; + default: + if (isUndefined(paramValue) || paramValue === null) { + delete this.$$search[search]; + } else { + this.$$search[search] = paramValue; + } + } + + this.$$compose(); + return this; + }, + + /** + * @ngdoc method + * @name $location#hash + * + * @description + * This method is getter / setter. + * + * Return hash fragment when called without any parameter. + * + * Change hash fragment when called with parameter and return `$location`. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue + * var hash = $location.hash(); + * // => "hashValue" + * ``` + * + * @param {(string|number)=} hash New hash fragment + * @return {string} hash + */ + hash: locationGetterSetter('$$hash', function(hash) { + return hash !== null ? hash.toString() : ''; + }), + + /** + * @ngdoc method + * @name $location#replace + * + * @description + * If called, all changes to $location during current `$digest` will be replacing current history + * record, instead of adding new one. + */ + replace: function() { + this.$$replace = true; + return this; + } +}; + +forEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) { + Location.prototype = Object.create(locationPrototype); + + /** + * @ngdoc method + * @name $location#state + * + * @description + * This method is getter / setter. + * + * Return the history state object when called without any parameter. + * + * Change the history state object when called with one parameter and return `$location`. + * The state object is later passed to `pushState` or `replaceState`. + * + * NOTE: This method is supported only in HTML5 mode and only in browsers supporting + * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support + * older browsers (like IE9 or Android < 4.0), don't use this method. + * + * @param {object=} state State object for pushState or replaceState + * @return {object} state + */ + Location.prototype.state = function(state) { + if (!arguments.length) { + return this.$$state; + } + + if (Location !== LocationHtml5Url || !this.$$html5) { + throw $locationMinErr('nostate', 'History API state support is available only ' + + 'in HTML5 mode and only in browsers supporting HTML5 History API'); + } + // The user might modify `stateObject` after invoking `$location.state(stateObject)` + // but we're changing the $$state reference to $browser.state() during the $digest + // so the modification window is narrow. + this.$$state = isUndefined(state) ? null : state; + + return this; + }; +}); + + +function locationGetter(property) { + return function() { + return this[property]; + }; +} + + +function locationGetterSetter(property, preprocess) { + return function(value) { + if (isUndefined(value)) { + return this[property]; + } + + this[property] = preprocess(value); + this.$$compose(); + + return this; + }; +} + + +/** + * @ngdoc service + * @name $location + * + * @requires $rootElement + * + * @description + * The $location service parses the URL in the browser address bar (based on the + * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL + * available to your application. Changes to the URL in the address bar are reflected into + * $location service and changes to $location are reflected into the browser address bar. + * + * **The $location service:** + * + * - Exposes the current URL in the browser address bar, so you can + * - Watch and observe the URL. + * - Change the URL. + * - Synchronizes the URL with the browser when the user + * - Changes the address bar. + * - Clicks the back or forward button (or clicks a History link). + * - Clicks on a link. + * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash). + * + * For more information see {@link guide/$location Developer Guide: Using $location} + */ + +/** + * @ngdoc provider + * @name $locationProvider + * @description + * Use the `$locationProvider` to configure how the application deep linking paths are stored. + */ +function $LocationProvider() { + var hashPrefix = '', + html5Mode = { + enabled: false, + requireBase: true, + rewriteLinks: true + }; + + /** + * @ngdoc method + * @name $locationProvider#hashPrefix + * @description + * @param {string=} prefix Prefix for hash part (containing path and search) + * @returns {*} current value if used as getter or itself (chaining) if used as setter + */ + this.hashPrefix = function(prefix) { + if (isDefined(prefix)) { + hashPrefix = prefix; + return this; + } else { + return hashPrefix; + } + }; + + /** + * @ngdoc method + * @name $locationProvider#html5Mode + * @description + * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value. + * If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported + * properties: + * - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to + * change urls where supported. Will fall back to hash-prefixed paths in browsers that do not + * support `pushState`. + * - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies + * whether or not a tag is required to be present. If `enabled` and `requireBase` are + * true, and a base tag is not present, an error will be thrown when `$location` is injected. + * See the {@link guide/$location $location guide for more information} + * - **rewriteLinks** - `{boolean}` - (default: `true`) When html5Mode is enabled, + * enables/disables url rewriting for relative links. + * + * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter + */ + this.html5Mode = function(mode) { + if (isBoolean(mode)) { + html5Mode.enabled = mode; + return this; + } else if (isObject(mode)) { + + if (isBoolean(mode.enabled)) { + html5Mode.enabled = mode.enabled; + } + + if (isBoolean(mode.requireBase)) { + html5Mode.requireBase = mode.requireBase; + } + + if (isBoolean(mode.rewriteLinks)) { + html5Mode.rewriteLinks = mode.rewriteLinks; + } + + return this; + } else { + return html5Mode; + } + }; + + /** + * @ngdoc event + * @name $location#$locationChangeStart + * @eventType broadcast on root scope + * @description + * Broadcasted before a URL will change. + * + * This change can be prevented by calling + * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more + * details about event object. Upon successful change + * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired. + * + * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when + * the browser supports the HTML5 History API. + * + * @param {Object} angularEvent Synthetic event object. + * @param {string} newUrl New URL + * @param {string=} oldUrl URL that was before it was changed. + * @param {string=} newState New history state object + * @param {string=} oldState History state object that was before it was changed. + */ + + /** + * @ngdoc event + * @name $location#$locationChangeSuccess + * @eventType broadcast on root scope + * @description + * Broadcasted after a URL was changed. + * + * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when + * the browser supports the HTML5 History API. + * + * @param {Object} angularEvent Synthetic event object. + * @param {string} newUrl New URL + * @param {string=} oldUrl URL that was before it was changed. + * @param {string=} newState New history state object + * @param {string=} oldState History state object that was before it was changed. + */ + + this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window', + function($rootScope, $browser, $sniffer, $rootElement, $window) { + var $location, + LocationMode, + baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to '' + initialUrl = $browser.url(), + appBase; + + if (html5Mode.enabled) { + if (!baseHref && html5Mode.requireBase) { + throw $locationMinErr('nobase', + "$location in HTML5 mode requires a tag to be present!"); + } + appBase = serverBase(initialUrl) + (baseHref || '/'); + LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url; + } else { + appBase = stripHash(initialUrl); + LocationMode = LocationHashbangUrl; + } + $location = new LocationMode(appBase, '#' + hashPrefix); + $location.$$parseLinkUrl(initialUrl, initialUrl); + + $location.$$state = $browser.state(); + + var IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i; + + function setBrowserUrlWithFallback(url, replace, state) { + var oldUrl = $location.url(); + var oldState = $location.$$state; + try { + $browser.url(url, replace, state); + + // Make sure $location.state() returns referentially identical (not just deeply equal) + // state object; this makes possible quick checking if the state changed in the digest + // loop. Checking deep equality would be too expensive. + $location.$$state = $browser.state(); + } catch (e) { + // Restore old values if pushState fails + $location.url(oldUrl); + $location.$$state = oldState; + + throw e; + } + } + + $rootElement.on('click', function(event) { + // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser) + // currently we open nice url link and redirect then + + if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which == 2 || event.button == 2) return; + + var elm = jqLite(event.target); + + // traverse the DOM up to find first A tag + while (nodeName_(elm[0]) !== 'a') { + // ignore rewriting if no A tag (reached root element, or no parent - removed from document) + if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return; + } + + var absHref = elm.prop('href'); + // get the actual href attribute - see + // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx + var relHref = elm.attr('href') || elm.attr('xlink:href'); + + if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') { + // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during + // an animation. + absHref = urlResolve(absHref.animVal).href; + } + + // Ignore when url is started with javascript: or mailto: + if (IGNORE_URI_REGEXP.test(absHref)) return; + + if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) { + if ($location.$$parseLinkUrl(absHref, relHref)) { + // We do a preventDefault for all urls that are part of the angular application, + // in html5mode and also without, so that we are able to abort navigation without + // getting double entries in the location history. + event.preventDefault(); + // update location manually + if ($location.absUrl() != $browser.url()) { + $rootScope.$apply(); + // hack to work around FF6 bug 684208 when scenario runner clicks on links + $window.angular['ff-684208-preventDefault'] = true; + } + } + } + }); + + + // rewrite hashbang url <> html5 url + if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) { + $browser.url($location.absUrl(), true); + } + + var initializing = true; + + // update $location when $browser url changes + $browser.onUrlChange(function(newUrl, newState) { + $rootScope.$evalAsync(function() { + var oldUrl = $location.absUrl(); + var oldState = $location.$$state; + var defaultPrevented; + + $location.$$parse(newUrl); + $location.$$state = newState; + + defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl, + newState, oldState).defaultPrevented; + + // if the location was changed by a `$locationChangeStart` handler then stop + // processing this location change + if ($location.absUrl() !== newUrl) return; + + if (defaultPrevented) { + $location.$$parse(oldUrl); + $location.$$state = oldState; + setBrowserUrlWithFallback(oldUrl, false, oldState); + } else { + initializing = false; + afterLocationChange(oldUrl, oldState); + } + }); + if (!$rootScope.$$phase) $rootScope.$digest(); + }); + + // update browser + $rootScope.$watch(function $locationWatch() { + var oldUrl = trimEmptyHash($browser.url()); + var newUrl = trimEmptyHash($location.absUrl()); + var oldState = $browser.state(); + var currentReplace = $location.$$replace; + var urlOrStateChanged = oldUrl !== newUrl || + ($location.$$html5 && $sniffer.history && oldState !== $location.$$state); + + if (initializing || urlOrStateChanged) { + initializing = false; + + $rootScope.$evalAsync(function() { + var newUrl = $location.absUrl(); + var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl, + $location.$$state, oldState).defaultPrevented; + + // if the location was changed by a `$locationChangeStart` handler then stop + // processing this location change + if ($location.absUrl() !== newUrl) return; + + if (defaultPrevented) { + $location.$$parse(oldUrl); + $location.$$state = oldState; + } else { + if (urlOrStateChanged) { + setBrowserUrlWithFallback(newUrl, currentReplace, + oldState === $location.$$state ? null : $location.$$state); + } + afterLocationChange(oldUrl, oldState); + } + }); + } + + $location.$$replace = false; + + // we don't need to return anything because $evalAsync will make the digest loop dirty when + // there is a change + }); + + return $location; + + function afterLocationChange(oldUrl, oldState) { + $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl, + $location.$$state, oldState); + } +}]; +} + +/** + * @ngdoc service + * @name $log + * @requires $window + * + * @description + * Simple service for logging. Default implementation safely writes the message + * into the browser's console (if present). + * + * The main purpose of this service is to simplify debugging and troubleshooting. + * + * The default is to log `debug` messages. You can use + * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this. + * + * @example + + + angular.module('logExample', []) + .controller('LogController', ['$scope', '$log', function($scope, $log) { + $scope.$log = $log; + $scope.message = 'Hello World!'; + }]); + + +
      +

      Reload this page with open console, enter text and hit the log button...

      + + + + + + +
      +
      +
      + */ + +/** + * @ngdoc provider + * @name $logProvider + * @description + * Use the `$logProvider` to configure how the application logs messages + */ +function $LogProvider() { + var debug = true, + self = this; + + /** + * @ngdoc method + * @name $logProvider#debugEnabled + * @description + * @param {boolean=} flag enable or disable debug level messages + * @returns {*} current value if used as getter or itself (chaining) if used as setter + */ + this.debugEnabled = function(flag) { + if (isDefined(flag)) { + debug = flag; + return this; + } else { + return debug; + } + }; + + this.$get = ['$window', function($window) { + return { + /** + * @ngdoc method + * @name $log#log + * + * @description + * Write a log message + */ + log: consoleLog('log'), + + /** + * @ngdoc method + * @name $log#info + * + * @description + * Write an information message + */ + info: consoleLog('info'), + + /** + * @ngdoc method + * @name $log#warn + * + * @description + * Write a warning message + */ + warn: consoleLog('warn'), + + /** + * @ngdoc method + * @name $log#error + * + * @description + * Write an error message + */ + error: consoleLog('error'), + + /** + * @ngdoc method + * @name $log#debug + * + * @description + * Write a debug message + */ + debug: (function() { + var fn = consoleLog('debug'); + + return function() { + if (debug) { + fn.apply(self, arguments); + } + }; + }()) + }; + + function formatError(arg) { + if (arg instanceof Error) { + if (arg.stack) { + arg = (arg.message && arg.stack.indexOf(arg.message) === -1) + ? 'Error: ' + arg.message + '\n' + arg.stack + : arg.stack; + } else if (arg.sourceURL) { + arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line; + } + } + return arg; + } + + function consoleLog(type) { + var console = $window.console || {}, + logFn = console[type] || console.log || noop, + hasApply = false; + + // Note: reading logFn.apply throws an error in IE11 in IE8 document mode. + // The reason behind this is that console.log has type "object" in IE8... + try { + hasApply = !!logFn.apply; + } catch (e) {} + + if (hasApply) { + return function() { + var args = []; + forEach(arguments, function(arg) { + args.push(formatError(arg)); + }); + return logFn.apply(console, args); + }; + } + + // we are IE which either doesn't have window.console => this is noop and we do nothing, + // or we are IE where console.log doesn't have apply so we log at least first 2 args + return function(arg1, arg2) { + logFn(arg1, arg2 == null ? '' : arg2); + }; + } + }]; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +var $parseMinErr = minErr('$parse'); + +// Sandboxing Angular Expressions +// ------------------------------ +// Angular expressions are generally considered safe because these expressions only have direct +// access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by +// obtaining a reference to native JS functions such as the Function constructor. +// +// As an example, consider the following Angular expression: +// +// {}.toString.constructor('alert("evil JS code")') +// +// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits +// against the expression language, but not to prevent exploits that were enabled by exposing +// sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good +// practice and therefore we are not even trying to protect against interaction with an object +// explicitly exposed in this way. +// +// In general, it is not possible to access a Window object from an angular expression unless a +// window or some DOM object that has a reference to window is published onto a Scope. +// Similarly we prevent invocations of function known to be dangerous, as well as assignments to +// native objects. +// +// See https://docs.angularjs.org/guide/security + + +function ensureSafeMemberName(name, fullExpression) { + if (name === "__defineGetter__" || name === "__defineSetter__" + || name === "__lookupGetter__" || name === "__lookupSetter__" + || name === "__proto__") { + throw $parseMinErr('isecfld', + 'Attempting to access a disallowed field in Angular expressions! ' + + 'Expression: {0}', fullExpression); + } + return name; +} + +function ensureSafeObject(obj, fullExpression) { + // nifty check if obj is Function that is fast and works across iframes and other contexts + if (obj) { + if (obj.constructor === obj) { + throw $parseMinErr('isecfn', + 'Referencing Function in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } else if (// isWindow(obj) + obj.window === obj) { + throw $parseMinErr('isecwindow', + 'Referencing the Window in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } else if (// isElement(obj) + obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) { + throw $parseMinErr('isecdom', + 'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } else if (// block Object so that we can't get hold of dangerous Object.* methods + obj === Object) { + throw $parseMinErr('isecobj', + 'Referencing Object in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } + } + return obj; +} + +var CALL = Function.prototype.call; +var APPLY = Function.prototype.apply; +var BIND = Function.prototype.bind; + +function ensureSafeFunction(obj, fullExpression) { + if (obj) { + if (obj.constructor === obj) { + throw $parseMinErr('isecfn', + 'Referencing Function in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } else if (obj === CALL || obj === APPLY || obj === BIND) { + throw $parseMinErr('isecff', + 'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } + } +} + +var OPERATORS = createMap(); +forEach('+ - * / % === !== == != < > <= >= && || ! = |'.split(' '), function(operator) { OPERATORS[operator] = true; }); +var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'}; + + +///////////////////////////////////////// + + +/** + * @constructor + */ +var Lexer = function(options) { + this.options = options; +}; + +Lexer.prototype = { + constructor: Lexer, + + lex: function(text) { + this.text = text; + this.index = 0; + this.tokens = []; + + while (this.index < this.text.length) { + var ch = this.text.charAt(this.index); + if (ch === '"' || ch === "'") { + this.readString(ch); + } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) { + this.readNumber(); + } else if (this.isIdent(ch)) { + this.readIdent(); + } else if (this.is(ch, '(){}[].,;:?')) { + this.tokens.push({index: this.index, text: ch}); + this.index++; + } else if (this.isWhitespace(ch)) { + this.index++; + } else { + var ch2 = ch + this.peek(); + var ch3 = ch2 + this.peek(2); + var op1 = OPERATORS[ch]; + var op2 = OPERATORS[ch2]; + var op3 = OPERATORS[ch3]; + if (op1 || op2 || op3) { + var token = op3 ? ch3 : (op2 ? ch2 : ch); + this.tokens.push({index: this.index, text: token, operator: true}); + this.index += token.length; + } else { + this.throwError('Unexpected next character ', this.index, this.index + 1); + } + } + } + return this.tokens; + }, + + is: function(ch, chars) { + return chars.indexOf(ch) !== -1; + }, + + peek: function(i) { + var num = i || 1; + return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false; + }, + + isNumber: function(ch) { + return ('0' <= ch && ch <= '9') && typeof ch === "string"; + }, + + isWhitespace: function(ch) { + // IE treats non-breaking space as \u00A0 + return (ch === ' ' || ch === '\r' || ch === '\t' || + ch === '\n' || ch === '\v' || ch === '\u00A0'); + }, + + isIdent: function(ch) { + return ('a' <= ch && ch <= 'z' || + 'A' <= ch && ch <= 'Z' || + '_' === ch || ch === '$'); + }, + + isExpOperator: function(ch) { + return (ch === '-' || ch === '+' || this.isNumber(ch)); + }, + + throwError: function(error, start, end) { + end = end || this.index; + var colStr = (isDefined(start) + ? 's ' + start + '-' + this.index + ' [' + this.text.substring(start, end) + ']' + : ' ' + end); + throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].', + error, colStr, this.text); + }, + + readNumber: function() { + var number = ''; + var start = this.index; + while (this.index < this.text.length) { + var ch = lowercase(this.text.charAt(this.index)); + if (ch == '.' || this.isNumber(ch)) { + number += ch; + } else { + var peekCh = this.peek(); + if (ch == 'e' && this.isExpOperator(peekCh)) { + number += ch; + } else if (this.isExpOperator(ch) && + peekCh && this.isNumber(peekCh) && + number.charAt(number.length - 1) == 'e') { + number += ch; + } else if (this.isExpOperator(ch) && + (!peekCh || !this.isNumber(peekCh)) && + number.charAt(number.length - 1) == 'e') { + this.throwError('Invalid exponent'); + } else { + break; + } + } + this.index++; + } + this.tokens.push({ + index: start, + text: number, + constant: true, + value: Number(number) + }); + }, + + readIdent: function() { + var start = this.index; + while (this.index < this.text.length) { + var ch = this.text.charAt(this.index); + if (!(this.isIdent(ch) || this.isNumber(ch))) { + break; + } + this.index++; + } + this.tokens.push({ + index: start, + text: this.text.slice(start, this.index), + identifier: true + }); + }, + + readString: function(quote) { + var start = this.index; + this.index++; + var string = ''; + var rawString = quote; + var escape = false; + while (this.index < this.text.length) { + var ch = this.text.charAt(this.index); + rawString += ch; + if (escape) { + if (ch === 'u') { + var hex = this.text.substring(this.index + 1, this.index + 5); + if (!hex.match(/[\da-f]{4}/i)) { + this.throwError('Invalid unicode escape [\\u' + hex + ']'); + } + this.index += 4; + string += String.fromCharCode(parseInt(hex, 16)); + } else { + var rep = ESCAPE[ch]; + string = string + (rep || ch); + } + escape = false; + } else if (ch === '\\') { + escape = true; + } else if (ch === quote) { + this.index++; + this.tokens.push({ + index: start, + text: rawString, + constant: true, + value: string + }); + return; + } else { + string += ch; + } + this.index++; + } + this.throwError('Unterminated quote', start); + } +}; + +var AST = function(lexer, options) { + this.lexer = lexer; + this.options = options; +}; + +AST.Program = 'Program'; +AST.ExpressionStatement = 'ExpressionStatement'; +AST.AssignmentExpression = 'AssignmentExpression'; +AST.ConditionalExpression = 'ConditionalExpression'; +AST.LogicalExpression = 'LogicalExpression'; +AST.BinaryExpression = 'BinaryExpression'; +AST.UnaryExpression = 'UnaryExpression'; +AST.CallExpression = 'CallExpression'; +AST.MemberExpression = 'MemberExpression'; +AST.Identifier = 'Identifier'; +AST.Literal = 'Literal'; +AST.ArrayExpression = 'ArrayExpression'; +AST.Property = 'Property'; +AST.ObjectExpression = 'ObjectExpression'; +AST.ThisExpression = 'ThisExpression'; + +// Internal use only +AST.NGValueParameter = 'NGValueParameter'; + +AST.prototype = { + ast: function(text) { + this.text = text; + this.tokens = this.lexer.lex(text); + + var value = this.program(); + + if (this.tokens.length !== 0) { + this.throwError('is an unexpected token', this.tokens[0]); + } + + return value; + }, + + program: function() { + var body = []; + while (true) { + if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']')) + body.push(this.expressionStatement()); + if (!this.expect(';')) { + return { type: AST.Program, body: body}; + } + } + }, + + expressionStatement: function() { + return { type: AST.ExpressionStatement, expression: this.filterChain() }; + }, + + filterChain: function() { + var left = this.expression(); + var token; + while ((token = this.expect('|'))) { + left = this.filter(left); + } + return left; + }, + + expression: function() { + return this.assignment(); + }, + + assignment: function() { + var result = this.ternary(); + if (this.expect('=')) { + result = { type: AST.AssignmentExpression, left: result, right: this.assignment(), operator: '='}; + } + return result; + }, + + ternary: function() { + var test = this.logicalOR(); + var alternate; + var consequent; + if (this.expect('?')) { + alternate = this.expression(); + if (this.consume(':')) { + consequent = this.expression(); + return { type: AST.ConditionalExpression, test: test, alternate: alternate, consequent: consequent}; + } + } + return test; + }, + + logicalOR: function() { + var left = this.logicalAND(); + while (this.expect('||')) { + left = { type: AST.LogicalExpression, operator: '||', left: left, right: this.logicalAND() }; + } + return left; + }, + + logicalAND: function() { + var left = this.equality(); + while (this.expect('&&')) { + left = { type: AST.LogicalExpression, operator: '&&', left: left, right: this.equality()}; + } + return left; + }, + + equality: function() { + var left = this.relational(); + var token; + while ((token = this.expect('==','!=','===','!=='))) { + left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.relational() }; + } + return left; + }, + + relational: function() { + var left = this.additive(); + var token; + while ((token = this.expect('<', '>', '<=', '>='))) { + left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.additive() }; + } + return left; + }, + + additive: function() { + var left = this.multiplicative(); + var token; + while ((token = this.expect('+','-'))) { + left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.multiplicative() }; + } + return left; + }, + + multiplicative: function() { + var left = this.unary(); + var token; + while ((token = this.expect('*','/','%'))) { + left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.unary() }; + } + return left; + }, + + unary: function() { + var token; + if ((token = this.expect('+', '-', '!'))) { + return { type: AST.UnaryExpression, operator: token.text, prefix: true, argument: this.unary() }; + } else { + return this.primary(); + } + }, + + primary: function() { + var primary; + if (this.expect('(')) { + primary = this.filterChain(); + this.consume(')'); + } else if (this.expect('[')) { + primary = this.arrayDeclaration(); + } else if (this.expect('{')) { + primary = this.object(); + } else if (this.constants.hasOwnProperty(this.peek().text)) { + primary = copy(this.constants[this.consume().text]); + } else if (this.peek().identifier) { + primary = this.identifier(); + } else if (this.peek().constant) { + primary = this.constant(); + } else { + this.throwError('not a primary expression', this.peek()); + } + + var next; + while ((next = this.expect('(', '[', '.'))) { + if (next.text === '(') { + primary = {type: AST.CallExpression, callee: primary, arguments: this.parseArguments() }; + this.consume(')'); + } else if (next.text === '[') { + primary = { type: AST.MemberExpression, object: primary, property: this.expression(), computed: true }; + this.consume(']'); + } else if (next.text === '.') { + primary = { type: AST.MemberExpression, object: primary, property: this.identifier(), computed: false }; + } else { + this.throwError('IMPOSSIBLE'); + } + } + return primary; + }, + + filter: function(baseExpression) { + var args = [baseExpression]; + var result = {type: AST.CallExpression, callee: this.identifier(), arguments: args, filter: true}; + + while (this.expect(':')) { + args.push(this.expression()); + } + + return result; + }, + + parseArguments: function() { + var args = []; + if (this.peekToken().text !== ')') { + do { + args.push(this.expression()); + } while (this.expect(',')); + } + return args; + }, + + identifier: function() { + var token = this.consume(); + if (!token.identifier) { + this.throwError('is not a valid identifier', token); + } + return { type: AST.Identifier, name: token.text }; + }, + + constant: function() { + // TODO check that it is a constant + return { type: AST.Literal, value: this.consume().value }; + }, + + arrayDeclaration: function() { + var elements = []; + if (this.peekToken().text !== ']') { + do { + if (this.peek(']')) { + // Support trailing commas per ES5.1. + break; + } + elements.push(this.expression()); + } while (this.expect(',')); + } + this.consume(']'); + + return { type: AST.ArrayExpression, elements: elements }; + }, + + object: function() { + var properties = [], property; + if (this.peekToken().text !== '}') { + do { + if (this.peek('}')) { + // Support trailing commas per ES5.1. + break; + } + property = {type: AST.Property, kind: 'init'}; + if (this.peek().constant) { + property.key = this.constant(); + } else if (this.peek().identifier) { + property.key = this.identifier(); + } else { + this.throwError("invalid key", this.peek()); + } + this.consume(':'); + property.value = this.expression(); + properties.push(property); + } while (this.expect(',')); + } + this.consume('}'); + + return {type: AST.ObjectExpression, properties: properties }; + }, + + throwError: function(msg, token) { + throw $parseMinErr('syntax', + 'Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].', + token.text, msg, (token.index + 1), this.text, this.text.substring(token.index)); + }, + + consume: function(e1) { + if (this.tokens.length === 0) { + throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text); + } + + var token = this.expect(e1); + if (!token) { + this.throwError('is unexpected, expecting [' + e1 + ']', this.peek()); + } + return token; + }, + + peekToken: function() { + if (this.tokens.length === 0) { + throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text); + } + return this.tokens[0]; + }, + + peek: function(e1, e2, e3, e4) { + return this.peekAhead(0, e1, e2, e3, e4); + }, + + peekAhead: function(i, e1, e2, e3, e4) { + if (this.tokens.length > i) { + var token = this.tokens[i]; + var t = token.text; + if (t === e1 || t === e2 || t === e3 || t === e4 || + (!e1 && !e2 && !e3 && !e4)) { + return token; + } + } + return false; + }, + + expect: function(e1, e2, e3, e4) { + var token = this.peek(e1, e2, e3, e4); + if (token) { + this.tokens.shift(); + return token; + } + return false; + }, + + + /* `undefined` is not a constant, it is an identifier, + * but using it as an identifier is not supported + */ + constants: { + 'true': { type: AST.Literal, value: true }, + 'false': { type: AST.Literal, value: false }, + 'null': { type: AST.Literal, value: null }, + 'undefined': {type: AST.Literal, value: undefined }, + 'this': {type: AST.ThisExpression } + } +}; + +function ifDefined(v, d) { + return typeof v !== 'undefined' ? v : d; +} + +function plusFn(l, r) { + if (typeof l === 'undefined') return r; + if (typeof r === 'undefined') return l; + return l + r; +} + +function isStateless($filter, filterName) { + var fn = $filter(filterName); + return !fn.$stateful; +} + +function findConstantAndWatchExpressions(ast, $filter) { + var allConstants; + var argsToWatch; + switch (ast.type) { + case AST.Program: + allConstants = true; + forEach(ast.body, function(expr) { + findConstantAndWatchExpressions(expr.expression, $filter); + allConstants = allConstants && expr.expression.constant; + }); + ast.constant = allConstants; + break; + case AST.Literal: + ast.constant = true; + ast.toWatch = []; + break; + case AST.UnaryExpression: + findConstantAndWatchExpressions(ast.argument, $filter); + ast.constant = ast.argument.constant; + ast.toWatch = ast.argument.toWatch; + break; + case AST.BinaryExpression: + findConstantAndWatchExpressions(ast.left, $filter); + findConstantAndWatchExpressions(ast.right, $filter); + ast.constant = ast.left.constant && ast.right.constant; + ast.toWatch = ast.left.toWatch.concat(ast.right.toWatch); + break; + case AST.LogicalExpression: + findConstantAndWatchExpressions(ast.left, $filter); + findConstantAndWatchExpressions(ast.right, $filter); + ast.constant = ast.left.constant && ast.right.constant; + ast.toWatch = ast.constant ? [] : [ast]; + break; + case AST.ConditionalExpression: + findConstantAndWatchExpressions(ast.test, $filter); + findConstantAndWatchExpressions(ast.alternate, $filter); + findConstantAndWatchExpressions(ast.consequent, $filter); + ast.constant = ast.test.constant && ast.alternate.constant && ast.consequent.constant; + ast.toWatch = ast.constant ? [] : [ast]; + break; + case AST.Identifier: + ast.constant = false; + ast.toWatch = [ast]; + break; + case AST.MemberExpression: + findConstantAndWatchExpressions(ast.object, $filter); + if (ast.computed) { + findConstantAndWatchExpressions(ast.property, $filter); + } + ast.constant = ast.object.constant && (!ast.computed || ast.property.constant); + ast.toWatch = [ast]; + break; + case AST.CallExpression: + allConstants = ast.filter ? isStateless($filter, ast.callee.name) : false; + argsToWatch = []; + forEach(ast.arguments, function(expr) { + findConstantAndWatchExpressions(expr, $filter); + allConstants = allConstants && expr.constant; + if (!expr.constant) { + argsToWatch.push.apply(argsToWatch, expr.toWatch); + } + }); + ast.constant = allConstants; + ast.toWatch = ast.filter && isStateless($filter, ast.callee.name) ? argsToWatch : [ast]; + break; + case AST.AssignmentExpression: + findConstantAndWatchExpressions(ast.left, $filter); + findConstantAndWatchExpressions(ast.right, $filter); + ast.constant = ast.left.constant && ast.right.constant; + ast.toWatch = [ast]; + break; + case AST.ArrayExpression: + allConstants = true; + argsToWatch = []; + forEach(ast.elements, function(expr) { + findConstantAndWatchExpressions(expr, $filter); + allConstants = allConstants && expr.constant; + if (!expr.constant) { + argsToWatch.push.apply(argsToWatch, expr.toWatch); + } + }); + ast.constant = allConstants; + ast.toWatch = argsToWatch; + break; + case AST.ObjectExpression: + allConstants = true; + argsToWatch = []; + forEach(ast.properties, function(property) { + findConstantAndWatchExpressions(property.value, $filter); + allConstants = allConstants && property.value.constant; + if (!property.value.constant) { + argsToWatch.push.apply(argsToWatch, property.value.toWatch); + } + }); + ast.constant = allConstants; + ast.toWatch = argsToWatch; + break; + case AST.ThisExpression: + ast.constant = false; + ast.toWatch = []; + break; + } +} + +function getInputs(body) { + if (body.length != 1) return; + var lastExpression = body[0].expression; + var candidate = lastExpression.toWatch; + if (candidate.length !== 1) return candidate; + return candidate[0] !== lastExpression ? candidate : undefined; +} + +function isAssignable(ast) { + return ast.type === AST.Identifier || ast.type === AST.MemberExpression; +} + +function assignableAST(ast) { + if (ast.body.length === 1 && isAssignable(ast.body[0].expression)) { + return {type: AST.AssignmentExpression, left: ast.body[0].expression, right: {type: AST.NGValueParameter}, operator: '='}; + } +} + +function isLiteral(ast) { + return ast.body.length === 0 || + ast.body.length === 1 && ( + ast.body[0].expression.type === AST.Literal || + ast.body[0].expression.type === AST.ArrayExpression || + ast.body[0].expression.type === AST.ObjectExpression); +} + +function isConstant(ast) { + return ast.constant; +} + +function ASTCompiler(astBuilder, $filter) { + this.astBuilder = astBuilder; + this.$filter = $filter; +} + +ASTCompiler.prototype = { + compile: function(expression, expensiveChecks) { + var self = this; + var ast = this.astBuilder.ast(expression); + this.state = { + nextId: 0, + filters: {}, + expensiveChecks: expensiveChecks, + fn: {vars: [], body: [], own: {}}, + assign: {vars: [], body: [], own: {}}, + inputs: [] + }; + findConstantAndWatchExpressions(ast, self.$filter); + var extra = ''; + var assignable; + this.stage = 'assign'; + if ((assignable = assignableAST(ast))) { + this.state.computing = 'assign'; + var result = this.nextId(); + this.recurse(assignable, result); + extra = 'fn.assign=' + this.generateFunction('assign', 's,v,l'); + } + var toWatch = getInputs(ast.body); + self.stage = 'inputs'; + forEach(toWatch, function(watch, key) { + var fnKey = 'fn' + key; + self.state[fnKey] = {vars: [], body: [], own: {}}; + self.state.computing = fnKey; + var intoId = self.nextId(); + self.recurse(watch, intoId); + self.return_(intoId); + self.state.inputs.push(fnKey); + watch.watchId = key; + }); + this.state.computing = 'fn'; + this.stage = 'main'; + this.recurse(ast); + var fnString = + // The build and minification steps remove the string "use strict" from the code, but this is done using a regex. + // This is a workaround for this until we do a better job at only removing the prefix only when we should. + '"' + this.USE + ' ' + this.STRICT + '";\n' + + this.filterPrefix() + + 'var fn=' + this.generateFunction('fn', 's,l,a,i') + + extra + + this.watchFns() + + 'return fn;'; + + /* jshint -W054 */ + var fn = (new Function('$filter', + 'ensureSafeMemberName', + 'ensureSafeObject', + 'ensureSafeFunction', + 'ifDefined', + 'plus', + 'text', + fnString))( + this.$filter, + ensureSafeMemberName, + ensureSafeObject, + ensureSafeFunction, + ifDefined, + plusFn, + expression); + /* jshint +W054 */ + this.state = this.stage = undefined; + fn.literal = isLiteral(ast); + fn.constant = isConstant(ast); + return fn; + }, + + USE: 'use', + + STRICT: 'strict', + + watchFns: function() { + var result = []; + var fns = this.state.inputs; + var self = this; + forEach(fns, function(name) { + result.push('var ' + name + '=' + self.generateFunction(name, 's')); + }); + if (fns.length) { + result.push('fn.inputs=[' + fns.join(',') + '];'); + } + return result.join(''); + }, + + generateFunction: function(name, params) { + return 'function(' + params + '){' + + this.varsPrefix(name) + + this.body(name) + + '};'; + }, + + filterPrefix: function() { + var parts = []; + var self = this; + forEach(this.state.filters, function(id, filter) { + parts.push(id + '=$filter(' + self.escape(filter) + ')'); + }); + if (parts.length) return 'var ' + parts.join(',') + ';'; + return ''; + }, + + varsPrefix: function(section) { + return this.state[section].vars.length ? 'var ' + this.state[section].vars.join(',') + ';' : ''; + }, + + body: function(section) { + return this.state[section].body.join(''); + }, + + recurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { + var left, right, self = this, args, expression; + recursionFn = recursionFn || noop; + if (!skipWatchIdCheck && isDefined(ast.watchId)) { + intoId = intoId || this.nextId(); + this.if_('i', + this.lazyAssign(intoId, this.computedMember('i', ast.watchId)), + this.lazyRecurse(ast, intoId, nameId, recursionFn, create, true) + ); + return; + } + switch (ast.type) { + case AST.Program: + forEach(ast.body, function(expression, pos) { + self.recurse(expression.expression, undefined, undefined, function(expr) { right = expr; }); + if (pos !== ast.body.length - 1) { + self.current().body.push(right, ';'); + } else { + self.return_(right); + } + }); + break; + case AST.Literal: + expression = this.escape(ast.value); + this.assign(intoId, expression); + recursionFn(expression); + break; + case AST.UnaryExpression: + this.recurse(ast.argument, undefined, undefined, function(expr) { right = expr; }); + expression = ast.operator + '(' + this.ifDefined(right, 0) + ')'; + this.assign(intoId, expression); + recursionFn(expression); + break; + case AST.BinaryExpression: + this.recurse(ast.left, undefined, undefined, function(expr) { left = expr; }); + this.recurse(ast.right, undefined, undefined, function(expr) { right = expr; }); + if (ast.operator === '+') { + expression = this.plus(left, right); + } else if (ast.operator === '-') { + expression = this.ifDefined(left, 0) + ast.operator + this.ifDefined(right, 0); + } else { + expression = '(' + left + ')' + ast.operator + '(' + right + ')'; + } + this.assign(intoId, expression); + recursionFn(expression); + break; + case AST.LogicalExpression: + intoId = intoId || this.nextId(); + self.recurse(ast.left, intoId); + self.if_(ast.operator === '&&' ? intoId : self.not(intoId), self.lazyRecurse(ast.right, intoId)); + recursionFn(intoId); + break; + case AST.ConditionalExpression: + intoId = intoId || this.nextId(); + self.recurse(ast.test, intoId); + self.if_(intoId, self.lazyRecurse(ast.alternate, intoId), self.lazyRecurse(ast.consequent, intoId)); + recursionFn(intoId); + break; + case AST.Identifier: + intoId = intoId || this.nextId(); + if (nameId) { + nameId.context = self.stage === 'inputs' ? 's' : this.assign(this.nextId(), this.getHasOwnProperty('l', ast.name) + '?l:s'); + nameId.computed = false; + nameId.name = ast.name; + } + ensureSafeMemberName(ast.name); + self.if_(self.stage === 'inputs' || self.not(self.getHasOwnProperty('l', ast.name)), + function() { + self.if_(self.stage === 'inputs' || 's', function() { + if (create && create !== 1) { + self.if_( + self.not(self.nonComputedMember('s', ast.name)), + self.lazyAssign(self.nonComputedMember('s', ast.name), '{}')); + } + self.assign(intoId, self.nonComputedMember('s', ast.name)); + }); + }, intoId && self.lazyAssign(intoId, self.nonComputedMember('l', ast.name)) + ); + if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.name)) { + self.addEnsureSafeObject(intoId); + } + recursionFn(intoId); + break; + case AST.MemberExpression: + left = nameId && (nameId.context = this.nextId()) || this.nextId(); + intoId = intoId || this.nextId(); + self.recurse(ast.object, left, undefined, function() { + self.if_(self.notNull(left), function() { + if (ast.computed) { + right = self.nextId(); + self.recurse(ast.property, right); + self.addEnsureSafeMemberName(right); + if (create && create !== 1) { + self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), '{}')); + } + expression = self.ensureSafeObject(self.computedMember(left, right)); + self.assign(intoId, expression); + if (nameId) { + nameId.computed = true; + nameId.name = right; + } + } else { + ensureSafeMemberName(ast.property.name); + if (create && create !== 1) { + self.if_(self.not(self.nonComputedMember(left, ast.property.name)), self.lazyAssign(self.nonComputedMember(left, ast.property.name), '{}')); + } + expression = self.nonComputedMember(left, ast.property.name); + if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.property.name)) { + expression = self.ensureSafeObject(expression); + } + self.assign(intoId, expression); + if (nameId) { + nameId.computed = false; + nameId.name = ast.property.name; + } + } + recursionFn(intoId); + }); + }, !!create); + break; + case AST.CallExpression: + intoId = intoId || this.nextId(); + if (ast.filter) { + right = self.filter(ast.callee.name); + args = []; + forEach(ast.arguments, function(expr) { + var argument = self.nextId(); + self.recurse(expr, argument); + args.push(argument); + }); + expression = right + '(' + args.join(',') + ')'; + self.assign(intoId, expression); + recursionFn(intoId); + } else { + right = self.nextId(); + left = {}; + args = []; + self.recurse(ast.callee, right, left, function() { + self.if_(self.notNull(right), function() { + self.addEnsureSafeFunction(right); + forEach(ast.arguments, function(expr) { + self.recurse(expr, self.nextId(), undefined, function(argument) { + args.push(self.ensureSafeObject(argument)); + }); + }); + if (left.name) { + if (!self.state.expensiveChecks) { + self.addEnsureSafeObject(left.context); + } + expression = self.member(left.context, left.name, left.computed) + '(' + args.join(',') + ')'; + } else { + expression = right + '(' + args.join(',') + ')'; + } + expression = self.ensureSafeObject(expression); + self.assign(intoId, expression); + recursionFn(intoId); + }); + }); + } + break; + case AST.AssignmentExpression: + right = this.nextId(); + left = {}; + if (!isAssignable(ast.left)) { + throw $parseMinErr('lval', 'Trying to assing a value to a non l-value'); + } + this.recurse(ast.left, undefined, left, function() { + self.if_(self.notNull(left.context), function() { + self.recurse(ast.right, right); + self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); + expression = self.member(left.context, left.name, left.computed) + ast.operator + right; + self.assign(intoId, expression); + recursionFn(intoId || expression); + }); + }, 1); + break; + case AST.ArrayExpression: + args = []; + forEach(ast.elements, function(expr) { + self.recurse(expr, self.nextId(), undefined, function(argument) { + args.push(argument); + }); + }); + expression = '[' + args.join(',') + ']'; + this.assign(intoId, expression); + recursionFn(expression); + break; + case AST.ObjectExpression: + args = []; + forEach(ast.properties, function(property) { + self.recurse(property.value, self.nextId(), undefined, function(expr) { + args.push(self.escape( + property.key.type === AST.Identifier ? property.key.name : + ('' + property.key.value)) + + ':' + expr); + }); + }); + expression = '{' + args.join(',') + '}'; + this.assign(intoId, expression); + recursionFn(expression); + break; + case AST.ThisExpression: + this.assign(intoId, 's'); + recursionFn('s'); + break; + case AST.NGValueParameter: + this.assign(intoId, 'v'); + recursionFn('v'); + break; + } + }, + + getHasOwnProperty: function(element, property) { + var key = element + '.' + property; + var own = this.current().own; + if (!own.hasOwnProperty(key)) { + own[key] = this.nextId(false, element + '&&(' + this.escape(property) + ' in ' + element + ')'); + } + return own[key]; + }, + + assign: function(id, value) { + if (!id) return; + this.current().body.push(id, '=', value, ';'); + return id; + }, + + filter: function(filterName) { + if (!this.state.filters.hasOwnProperty(filterName)) { + this.state.filters[filterName] = this.nextId(true); + } + return this.state.filters[filterName]; + }, + + ifDefined: function(id, defaultValue) { + return 'ifDefined(' + id + ',' + this.escape(defaultValue) + ')'; + }, + + plus: function(left, right) { + return 'plus(' + left + ',' + right + ')'; + }, + + return_: function(id) { + this.current().body.push('return ', id, ';'); + }, + + if_: function(test, alternate, consequent) { + if (test === true) { + alternate(); + } else { + var body = this.current().body; + body.push('if(', test, '){'); + alternate(); + body.push('}'); + if (consequent) { + body.push('else{'); + consequent(); + body.push('}'); + } + } + }, + + not: function(expression) { + return '!(' + expression + ')'; + }, + + notNull: function(expression) { + return expression + '!=null'; + }, + + nonComputedMember: function(left, right) { + return left + '.' + right; + }, + + computedMember: function(left, right) { + return left + '[' + right + ']'; + }, + + member: function(left, right, computed) { + if (computed) return this.computedMember(left, right); + return this.nonComputedMember(left, right); + }, + + addEnsureSafeObject: function(item) { + this.current().body.push(this.ensureSafeObject(item), ';'); + }, + + addEnsureSafeMemberName: function(item) { + this.current().body.push(this.ensureSafeMemberName(item), ';'); + }, + + addEnsureSafeFunction: function(item) { + this.current().body.push(this.ensureSafeFunction(item), ';'); + }, + + ensureSafeObject: function(item) { + return 'ensureSafeObject(' + item + ',text)'; + }, + + ensureSafeMemberName: function(item) { + return 'ensureSafeMemberName(' + item + ',text)'; + }, + + ensureSafeFunction: function(item) { + return 'ensureSafeFunction(' + item + ',text)'; + }, + + lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { + var self = this; + return function() { + self.recurse(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck); + }; + }, + + lazyAssign: function(id, value) { + var self = this; + return function() { + self.assign(id, value); + }; + }, + + stringEscapeRegex: /[^ a-zA-Z0-9]/g, + + stringEscapeFn: function(c) { + return '\\u' + ('0000' + c.charCodeAt(0).toString(16)).slice(-4); + }, + + escape: function(value) { + if (isString(value)) return "'" + value.replace(this.stringEscapeRegex, this.stringEscapeFn) + "'"; + if (isNumber(value)) return value.toString(); + if (value === true) return 'true'; + if (value === false) return 'false'; + if (value === null) return 'null'; + if (typeof value === 'undefined') return 'undefined'; + + throw $parseMinErr('esc', 'IMPOSSIBLE'); + }, + + nextId: function(skip, init) { + var id = 'v' + (this.state.nextId++); + if (!skip) { + this.current().vars.push(id + (init ? '=' + init : '')); + } + return id; + }, + + current: function() { + return this.state[this.state.computing]; + } +}; + + +function ASTInterpreter(astBuilder, $filter) { + this.astBuilder = astBuilder; + this.$filter = $filter; +} + +ASTInterpreter.prototype = { + compile: function(expression, expensiveChecks) { + var self = this; + var ast = this.astBuilder.ast(expression); + this.expression = expression; + this.expensiveChecks = expensiveChecks; + findConstantAndWatchExpressions(ast, self.$filter); + var assignable; + var assign; + if ((assignable = assignableAST(ast))) { + assign = this.recurse(assignable); + } + var toWatch = getInputs(ast.body); + var inputs; + if (toWatch) { + inputs = []; + forEach(toWatch, function(watch, key) { + var input = self.recurse(watch); + watch.input = input; + inputs.push(input); + watch.watchId = key; + }); + } + var expressions = []; + forEach(ast.body, function(expression) { + expressions.push(self.recurse(expression.expression)); + }); + var fn = ast.body.length === 0 ? function() {} : + ast.body.length === 1 ? expressions[0] : + function(scope, locals) { + var lastValue; + forEach(expressions, function(exp) { + lastValue = exp(scope, locals); + }); + return lastValue; + }; + if (assign) { + fn.assign = function(scope, value, locals) { + return assign(scope, locals, value); + }; + } + if (inputs) { + fn.inputs = inputs; + } + fn.literal = isLiteral(ast); + fn.constant = isConstant(ast); + return fn; + }, + + recurse: function(ast, context, create) { + var left, right, self = this, args, expression; + if (ast.input) { + return this.inputs(ast.input, ast.watchId); + } + switch (ast.type) { + case AST.Literal: + return this.value(ast.value, context); + case AST.UnaryExpression: + right = this.recurse(ast.argument); + return this['unary' + ast.operator](right, context); + case AST.BinaryExpression: + left = this.recurse(ast.left); + right = this.recurse(ast.right); + return this['binary' + ast.operator](left, right, context); + case AST.LogicalExpression: + left = this.recurse(ast.left); + right = this.recurse(ast.right); + return this['binary' + ast.operator](left, right, context); + case AST.ConditionalExpression: + return this['ternary?:']( + this.recurse(ast.test), + this.recurse(ast.alternate), + this.recurse(ast.consequent), + context + ); + case AST.Identifier: + ensureSafeMemberName(ast.name, self.expression); + return self.identifier(ast.name, + self.expensiveChecks || isPossiblyDangerousMemberName(ast.name), + context, create, self.expression); + case AST.MemberExpression: + left = this.recurse(ast.object, false, !!create); + if (!ast.computed) { + ensureSafeMemberName(ast.property.name, self.expression); + right = ast.property.name; + } + if (ast.computed) right = this.recurse(ast.property); + return ast.computed ? + this.computedMember(left, right, context, create, self.expression) : + this.nonComputedMember(left, right, self.expensiveChecks, context, create, self.expression); + case AST.CallExpression: + args = []; + forEach(ast.arguments, function(expr) { + args.push(self.recurse(expr)); + }); + if (ast.filter) right = this.$filter(ast.callee.name); + if (!ast.filter) right = this.recurse(ast.callee, true); + return ast.filter ? + function(scope, locals, assign, inputs) { + var values = []; + for (var i = 0; i < args.length; ++i) { + values.push(args[i](scope, locals, assign, inputs)); + } + var value = right.apply(undefined, values, inputs); + return context ? {context: undefined, name: undefined, value: value} : value; + } : + function(scope, locals, assign, inputs) { + var rhs = right(scope, locals, assign, inputs); + var value; + if (rhs.value != null) { + ensureSafeObject(rhs.context, self.expression); + ensureSafeFunction(rhs.value, self.expression); + var values = []; + for (var i = 0; i < args.length; ++i) { + values.push(ensureSafeObject(args[i](scope, locals, assign, inputs), self.expression)); + } + value = ensureSafeObject(rhs.value.apply(rhs.context, values), self.expression); + } + return context ? {value: value} : value; + }; + case AST.AssignmentExpression: + left = this.recurse(ast.left, true, 1); + right = this.recurse(ast.right); + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs = right(scope, locals, assign, inputs); + ensureSafeObject(lhs.value, self.expression); + lhs.context[lhs.name] = rhs; + return context ? {value: rhs} : rhs; + }; + case AST.ArrayExpression: + args = []; + forEach(ast.elements, function(expr) { + args.push(self.recurse(expr)); + }); + return function(scope, locals, assign, inputs) { + var value = []; + for (var i = 0; i < args.length; ++i) { + value.push(args[i](scope, locals, assign, inputs)); + } + return context ? {value: value} : value; + }; + case AST.ObjectExpression: + args = []; + forEach(ast.properties, function(property) { + args.push({key: property.key.type === AST.Identifier ? + property.key.name : + ('' + property.key.value), + value: self.recurse(property.value) + }); + }); + return function(scope, locals, assign, inputs) { + var value = {}; + for (var i = 0; i < args.length; ++i) { + value[args[i].key] = args[i].value(scope, locals, assign, inputs); + } + return context ? {value: value} : value; + }; + case AST.ThisExpression: + return function(scope) { + return context ? {value: scope} : scope; + }; + case AST.NGValueParameter: + return function(scope, locals, assign, inputs) { + return context ? {value: assign} : assign; + }; + } + }, + + 'unary+': function(argument, context) { + return function(scope, locals, assign, inputs) { + var arg = argument(scope, locals, assign, inputs); + if (isDefined(arg)) { + arg = +arg; + } else { + arg = 0; + } + return context ? {value: arg} : arg; + }; + }, + 'unary-': function(argument, context) { + return function(scope, locals, assign, inputs) { + var arg = argument(scope, locals, assign, inputs); + if (isDefined(arg)) { + arg = -arg; + } else { + arg = 0; + } + return context ? {value: arg} : arg; + }; + }, + 'unary!': function(argument, context) { + return function(scope, locals, assign, inputs) { + var arg = !argument(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary+': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs = right(scope, locals, assign, inputs); + var arg = plusFn(lhs, rhs); + return context ? {value: arg} : arg; + }; + }, + 'binary-': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs = right(scope, locals, assign, inputs); + var arg = (isDefined(lhs) ? lhs : 0) - (isDefined(rhs) ? rhs : 0); + return context ? {value: arg} : arg; + }; + }, + 'binary*': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) * right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary/': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) / right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary%': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) % right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary===': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) === right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary!==': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) !== right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary==': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) == right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary!=': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) != right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary<': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) < right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary>': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) > right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary<=': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) <= right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary>=': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) >= right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary&&': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) && right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary||': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) || right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'ternary?:': function(test, alternate, consequent, context) { + return function(scope, locals, assign, inputs) { + var arg = test(scope, locals, assign, inputs) ? alternate(scope, locals, assign, inputs) : consequent(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + value: function(value, context) { + return function() { return context ? {context: undefined, name: undefined, value: value} : value; }; + }, + identifier: function(name, expensiveChecks, context, create, expression) { + return function(scope, locals, assign, inputs) { + var base = locals && (name in locals) ? locals : scope; + if (create && create !== 1 && base && !(base[name])) { + base[name] = {}; + } + var value = base ? base[name] : undefined; + if (expensiveChecks) { + ensureSafeObject(value, expression); + } + if (context) { + return {context: base, name: name, value: value}; + } else { + return value; + } + }; + }, + computedMember: function(left, right, context, create, expression) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs; + var value; + if (lhs != null) { + rhs = right(scope, locals, assign, inputs); + ensureSafeMemberName(rhs, expression); + if (create && create !== 1 && lhs && !(lhs[rhs])) { + lhs[rhs] = {}; + } + value = lhs[rhs]; + ensureSafeObject(value, expression); + } + if (context) { + return {context: lhs, name: rhs, value: value}; + } else { + return value; + } + }; + }, + nonComputedMember: function(left, right, expensiveChecks, context, create, expression) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + if (create && create !== 1 && lhs && !(lhs[right])) { + lhs[right] = {}; + } + var value = lhs != null ? lhs[right] : undefined; + if (expensiveChecks || isPossiblyDangerousMemberName(right)) { + ensureSafeObject(value, expression); + } + if (context) { + return {context: lhs, name: right, value: value}; + } else { + return value; + } + }; + }, + inputs: function(input, watchId) { + return function(scope, value, locals, inputs) { + if (inputs) return inputs[watchId]; + return input(scope, value, locals); + }; + } +}; + +/** + * @constructor + */ +var Parser = function(lexer, $filter, options) { + this.lexer = lexer; + this.$filter = $filter; + this.options = options; + this.ast = new AST(this.lexer); + this.astCompiler = options.csp ? new ASTInterpreter(this.ast, $filter) : + new ASTCompiler(this.ast, $filter); +}; + +Parser.prototype = { + constructor: Parser, + + parse: function(text) { + return this.astCompiler.compile(text, this.options.expensiveChecks); + } +}; + +////////////////////////////////////////////////// +// Parser helper functions +////////////////////////////////////////////////// + +function setter(obj, path, setValue, fullExp) { + ensureSafeObject(obj, fullExp); + + var element = path.split('.'), key; + for (var i = 0; element.length > 1; i++) { + key = ensureSafeMemberName(element.shift(), fullExp); + var propertyObj = ensureSafeObject(obj[key], fullExp); + if (!propertyObj) { + propertyObj = {}; + obj[key] = propertyObj; + } + obj = propertyObj; + } + key = ensureSafeMemberName(element.shift(), fullExp); + ensureSafeObject(obj[key], fullExp); + obj[key] = setValue; + return setValue; +} + +var getterFnCacheDefault = createMap(); +var getterFnCacheExpensive = createMap(); + +function isPossiblyDangerousMemberName(name) { + return name == 'constructor'; +} + +var objectValueOf = Object.prototype.valueOf; + +function getValueOf(value) { + return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value); +} + +/////////////////////////////////// + +/** + * @ngdoc service + * @name $parse + * @kind function + * + * @description + * + * Converts Angular {@link guide/expression expression} into a function. + * + * ```js + * var getter = $parse('user.name'); + * var setter = getter.assign; + * var context = {user:{name:'angular'}}; + * var locals = {user:{name:'local'}}; + * + * expect(getter(context)).toEqual('angular'); + * setter(context, 'newValue'); + * expect(context.user.name).toEqual('newValue'); + * expect(getter(context, locals)).toEqual('local'); + * ``` + * + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + * + * The returned function also has the following properties: + * * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript + * literal. + * * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript + * constant literals. + * * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be + * set to a function to change its value on the given context. + * + */ + + +/** + * @ngdoc provider + * @name $parseProvider + * + * @description + * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse} + * service. + */ +function $ParseProvider() { + var cacheDefault = createMap(); + var cacheExpensive = createMap(); + + this.$get = ['$filter', '$sniffer', function($filter, $sniffer) { + var $parseOptions = { + csp: $sniffer.csp, + expensiveChecks: false + }, + $parseOptionsExpensive = { + csp: $sniffer.csp, + expensiveChecks: true + }; + + return function $parse(exp, interceptorFn, expensiveChecks) { + var parsedExpression, oneTime, cacheKey; + + switch (typeof exp) { + case 'string': + exp = exp.trim(); + cacheKey = exp; + + var cache = (expensiveChecks ? cacheExpensive : cacheDefault); + parsedExpression = cache[cacheKey]; + + if (!parsedExpression) { + if (exp.charAt(0) === ':' && exp.charAt(1) === ':') { + oneTime = true; + exp = exp.substring(2); + } + var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions; + var lexer = new Lexer(parseOptions); + var parser = new Parser(lexer, $filter, parseOptions); + parsedExpression = parser.parse(exp); + if (parsedExpression.constant) { + parsedExpression.$$watchDelegate = constantWatchDelegate; + } else if (oneTime) { + parsedExpression.$$watchDelegate = parsedExpression.literal ? + oneTimeLiteralWatchDelegate : oneTimeWatchDelegate; + } else if (parsedExpression.inputs) { + parsedExpression.$$watchDelegate = inputsWatchDelegate; + } + cache[cacheKey] = parsedExpression; + } + return addInterceptor(parsedExpression, interceptorFn); + + case 'function': + return addInterceptor(exp, interceptorFn); + + default: + return noop; + } + }; + + function expressionInputDirtyCheck(newValue, oldValueOfValue) { + + if (newValue == null || oldValueOfValue == null) { // null/undefined + return newValue === oldValueOfValue; + } + + if (typeof newValue === 'object') { + + // attempt to convert the value to a primitive type + // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can + // be cheaply dirty-checked + newValue = getValueOf(newValue); + + if (typeof newValue === 'object') { + // objects/arrays are not supported - deep-watching them would be too expensive + return false; + } + + // fall-through to the primitive equality check + } + + //Primitive or NaN + return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue); + } + + function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) { + var inputExpressions = parsedExpression.inputs; + var lastResult; + + if (inputExpressions.length === 1) { + var oldInputValueOf = expressionInputDirtyCheck; // init to something unique so that equals check fails + inputExpressions = inputExpressions[0]; + return scope.$watch(function expressionInputWatch(scope) { + var newInputValue = inputExpressions(scope); + if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf)) { + lastResult = parsedExpression(scope, undefined, undefined, [newInputValue]); + oldInputValueOf = newInputValue && getValueOf(newInputValue); + } + return lastResult; + }, listener, objectEquality, prettyPrintExpression); + } + + var oldInputValueOfValues = []; + var oldInputValues = []; + for (var i = 0, ii = inputExpressions.length; i < ii; i++) { + oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails + oldInputValues[i] = null; + } + + return scope.$watch(function expressionInputsWatch(scope) { + var changed = false; + + for (var i = 0, ii = inputExpressions.length; i < ii; i++) { + var newInputValue = inputExpressions[i](scope); + if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) { + oldInputValues[i] = newInputValue; + oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue); + } + } + + if (changed) { + lastResult = parsedExpression(scope, undefined, undefined, oldInputValues); + } + + return lastResult; + }, listener, objectEquality, prettyPrintExpression); + } + + function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) { + var unwatch, lastValue; + return unwatch = scope.$watch(function oneTimeWatch(scope) { + return parsedExpression(scope); + }, function oneTimeListener(value, old, scope) { + lastValue = value; + if (isFunction(listener)) { + listener.apply(this, arguments); + } + if (isDefined(value)) { + scope.$$postDigest(function() { + if (isDefined(lastValue)) { + unwatch(); + } + }); + } + }, objectEquality); + } + + function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) { + var unwatch, lastValue; + return unwatch = scope.$watch(function oneTimeWatch(scope) { + return parsedExpression(scope); + }, function oneTimeListener(value, old, scope) { + lastValue = value; + if (isFunction(listener)) { + listener.call(this, value, old, scope); + } + if (isAllDefined(value)) { + scope.$$postDigest(function() { + if (isAllDefined(lastValue)) unwatch(); + }); + } + }, objectEquality); + + function isAllDefined(value) { + var allDefined = true; + forEach(value, function(val) { + if (!isDefined(val)) allDefined = false; + }); + return allDefined; + } + } + + function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) { + var unwatch; + return unwatch = scope.$watch(function constantWatch(scope) { + return parsedExpression(scope); + }, function constantListener(value, old, scope) { + if (isFunction(listener)) { + listener.apply(this, arguments); + } + unwatch(); + }, objectEquality); + } + + function addInterceptor(parsedExpression, interceptorFn) { + if (!interceptorFn) return parsedExpression; + var watchDelegate = parsedExpression.$$watchDelegate; + + var regularWatch = + watchDelegate !== oneTimeLiteralWatchDelegate && + watchDelegate !== oneTimeWatchDelegate; + + var fn = regularWatch ? function regularInterceptedExpression(scope, locals, assign, inputs) { + var value = parsedExpression(scope, locals, assign, inputs); + return interceptorFn(value, scope, locals); + } : function oneTimeInterceptedExpression(scope, locals, assign, inputs) { + var value = parsedExpression(scope, locals, assign, inputs); + var result = interceptorFn(value, scope, locals); + // we only return the interceptor's result if the + // initial value is defined (for bind-once) + return isDefined(value) ? result : value; + }; + + // Propagate $$watchDelegates other then inputsWatchDelegate + if (parsedExpression.$$watchDelegate && + parsedExpression.$$watchDelegate !== inputsWatchDelegate) { + fn.$$watchDelegate = parsedExpression.$$watchDelegate; + } else if (!interceptorFn.$stateful) { + // If there is an interceptor, but no watchDelegate then treat the interceptor like + // we treat filters - it is assumed to be a pure function unless flagged with $stateful + fn.$$watchDelegate = inputsWatchDelegate; + fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression]; + } + + return fn; + } + }]; +} + +/** + * @ngdoc service + * @name $q + * @requires $rootScope + * + * @description + * A service that helps you run functions asynchronously, and use their return values (or exceptions) + * when they are done processing. + * + * This is an implementation of promises/deferred objects inspired by + * [Kris Kowal's Q](https://github.com/kriskowal/q). + * + * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred + * implementations, and the other which resembles ES6 promises to some degree. + * + * # $q constructor + * + * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver` + * function as the first argument. This is similar to the native Promise implementation from ES6 Harmony, + * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). + * + * While the constructor-style use is supported, not all of the supporting methods from ES6 Harmony promises are + * available yet. + * + * It can be used like so: + * + * ```js + * // for the purpose of this example let's assume that variables `$q` and `okToGreet` + * // are available in the current lexical scope (they could have been injected or passed in). + * + * function asyncGreet(name) { + * // perform some asynchronous operation, resolve or reject the promise when appropriate. + * return $q(function(resolve, reject) { + * setTimeout(function() { + * if (okToGreet(name)) { + * resolve('Hello, ' + name + '!'); + * } else { + * reject('Greeting ' + name + ' is not allowed.'); + * } + * }, 1000); + * }); + * } + * + * var promise = asyncGreet('Robin Hood'); + * promise.then(function(greeting) { + * alert('Success: ' + greeting); + * }, function(reason) { + * alert('Failed: ' + reason); + * }); + * ``` + * + * Note: progress/notify callbacks are not currently supported via the ES6-style interface. + * + * However, the more traditional CommonJS-style usage is still available, and documented below. + * + * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an + * interface for interacting with an object that represents the result of an action that is + * performed asynchronously, and may or may not be finished at any given point in time. + * + * From the perspective of dealing with error handling, deferred and promise APIs are to + * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming. + * + * ```js + * // for the purpose of this example let's assume that variables `$q` and `okToGreet` + * // are available in the current lexical scope (they could have been injected or passed in). + * + * function asyncGreet(name) { + * var deferred = $q.defer(); + * + * setTimeout(function() { + * deferred.notify('About to greet ' + name + '.'); + * + * if (okToGreet(name)) { + * deferred.resolve('Hello, ' + name + '!'); + * } else { + * deferred.reject('Greeting ' + name + ' is not allowed.'); + * } + * }, 1000); + * + * return deferred.promise; + * } + * + * var promise = asyncGreet('Robin Hood'); + * promise.then(function(greeting) { + * alert('Success: ' + greeting); + * }, function(reason) { + * alert('Failed: ' + reason); + * }, function(update) { + * alert('Got notification: ' + update); + * }); + * ``` + * + * At first it might not be obvious why this extra complexity is worth the trouble. The payoff + * comes in the way of guarantees that promise and deferred APIs make, see + * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md. + * + * Additionally the promise api allows for composition that is very hard to do with the + * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach. + * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the + * section on serial or parallel joining of promises. + * + * # The Deferred API + * + * A new instance of deferred is constructed by calling `$q.defer()`. + * + * The purpose of the deferred object is to expose the associated Promise instance as well as APIs + * that can be used for signaling the successful or unsuccessful completion, as well as the status + * of the task. + * + * **Methods** + * + * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection + * constructed via `$q.reject`, the promise will be rejected instead. + * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to + * resolving it with a rejection constructed via `$q.reject`. + * - `notify(value)` - provides updates on the status of the promise's execution. This may be called + * multiple times before the promise is either resolved or rejected. + * + * **Properties** + * + * - promise – `{Promise}` – promise object associated with this deferred. + * + * + * # The Promise API + * + * A new promise instance is created when a deferred instance is created and can be retrieved by + * calling `deferred.promise`. + * + * The purpose of the promise object is to allow for interested parties to get access to the result + * of the deferred task when it completes. + * + * **Methods** + * + * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or + * will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously + * as soon as the result is available. The callbacks are called with a single argument: the result + * or rejection reason. Additionally, the notify callback may be called zero or more times to + * provide a progress indication, before the promise is resolved or rejected. + * + * This method *returns a new promise* which is resolved or rejected via the return value of the + * `successCallback`, `errorCallback` (unless that value is a promise, in which case it is resolved + * with the value which is resolved in that promise using + * [promise chaining](http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promises-queues)). + * It also notifies via the return value of the `notifyCallback` method. The promise cannot be + * resolved or rejected from the notifyCallback method. + * + * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)` + * + * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise, + * but to do so without modifying the final value. This is useful to release resources or do some + * clean-up that needs to be done whether the promise was rejected or resolved. See the [full + * specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for + * more information. + * + * # Chaining promises + * + * Because calling the `then` method of a promise returns a new derived promise, it is easily + * possible to create a chain of promises: + * + * ```js + * promiseB = promiseA.then(function(result) { + * return result + 1; + * }); + * + * // promiseB will be resolved immediately after promiseA is resolved and its value + * // will be the result of promiseA incremented by 1 + * ``` + * + * It is possible to create chains of any length and since a promise can be resolved with another + * promise (which will defer its resolution further), it is possible to pause/defer resolution of + * the promises at any point in the chain. This makes it possible to implement powerful APIs like + * $http's response interceptors. + * + * + * # Differences between Kris Kowal's Q and $q + * + * There are two main differences: + * + * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation + * mechanism in angular, which means faster propagation of resolution or rejection into your + * models and avoiding unnecessary browser repaints, which would result in flickering UI. + * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains + * all the important functionality needed for common async tasks. + * + * # Testing + * + * ```js + * it('should simulate promise', inject(function($q, $rootScope) { + * var deferred = $q.defer(); + * var promise = deferred.promise; + * var resolvedValue; + * + * promise.then(function(value) { resolvedValue = value; }); + * expect(resolvedValue).toBeUndefined(); + * + * // Simulate resolving of promise + * deferred.resolve(123); + * // Note that the 'then' function does not get called synchronously. + * // This is because we want the promise API to always be async, whether or not + * // it got called synchronously or asynchronously. + * expect(resolvedValue).toBeUndefined(); + * + * // Propagate promise resolution to 'then' functions using $apply(). + * $rootScope.$apply(); + * expect(resolvedValue).toEqual(123); + * })); + * ``` + * + * @param {function(function, function)} resolver Function which is responsible for resolving or + * rejecting the newly created promise. The first parameter is a function which resolves the + * promise, the second parameter is a function which rejects the promise. + * + * @returns {Promise} The newly created promise. + */ +function $QProvider() { + + this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) { + return qFactory(function(callback) { + $rootScope.$evalAsync(callback); + }, $exceptionHandler); + }]; +} + +function $$QProvider() { + this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) { + return qFactory(function(callback) { + $browser.defer(callback); + }, $exceptionHandler); + }]; +} + +/** + * Constructs a promise manager. + * + * @param {function(function)} nextTick Function for executing functions in the next turn. + * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for + * debugging purposes. + * @returns {object} Promise manager. + */ +function qFactory(nextTick, exceptionHandler) { + var $qMinErr = minErr('$q', TypeError); + function callOnce(self, resolveFn, rejectFn) { + var called = false; + function wrap(fn) { + return function(value) { + if (called) return; + called = true; + fn.call(self, value); + }; + } + + return [wrap(resolveFn), wrap(rejectFn)]; + } + + /** + * @ngdoc method + * @name ng.$q#defer + * @kind function + * + * @description + * Creates a `Deferred` object which represents a task which will finish in the future. + * + * @returns {Deferred} Returns a new instance of deferred. + */ + var defer = function() { + return new Deferred(); + }; + + function Promise() { + this.$$state = { status: 0 }; + } + + Promise.prototype = { + then: function(onFulfilled, onRejected, progressBack) { + var result = new Deferred(); + + this.$$state.pending = this.$$state.pending || []; + this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]); + if (this.$$state.status > 0) scheduleProcessQueue(this.$$state); + + return result.promise; + }, + + "catch": function(callback) { + return this.then(null, callback); + }, + + "finally": function(callback, progressBack) { + return this.then(function(value) { + return handleCallback(value, true, callback); + }, function(error) { + return handleCallback(error, false, callback); + }, progressBack); + } + }; + + //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native + function simpleBind(context, fn) { + return function(value) { + fn.call(context, value); + }; + } + + function processQueue(state) { + var fn, deferred, pending; + + pending = state.pending; + state.processScheduled = false; + state.pending = undefined; + for (var i = 0, ii = pending.length; i < ii; ++i) { + deferred = pending[i][0]; + fn = pending[i][state.status]; + try { + if (isFunction(fn)) { + deferred.resolve(fn(state.value)); + } else if (state.status === 1) { + deferred.resolve(state.value); + } else { + deferred.reject(state.value); + } + } catch (e) { + deferred.reject(e); + exceptionHandler(e); + } + } + } + + function scheduleProcessQueue(state) { + if (state.processScheduled || !state.pending) return; + state.processScheduled = true; + nextTick(function() { processQueue(state); }); + } + + function Deferred() { + this.promise = new Promise(); + //Necessary to support unbound execution :/ + this.resolve = simpleBind(this, this.resolve); + this.reject = simpleBind(this, this.reject); + this.notify = simpleBind(this, this.notify); + } + + Deferred.prototype = { + resolve: function(val) { + if (this.promise.$$state.status) return; + if (val === this.promise) { + this.$$reject($qMinErr( + 'qcycle', + "Expected promise to be resolved with value other than itself '{0}'", + val)); + } else { + this.$$resolve(val); + } + + }, + + $$resolve: function(val) { + var then, fns; + + fns = callOnce(this, this.$$resolve, this.$$reject); + try { + if ((isObject(val) || isFunction(val))) then = val && val.then; + if (isFunction(then)) { + this.promise.$$state.status = -1; + then.call(val, fns[0], fns[1], this.notify); + } else { + this.promise.$$state.value = val; + this.promise.$$state.status = 1; + scheduleProcessQueue(this.promise.$$state); + } + } catch (e) { + fns[1](e); + exceptionHandler(e); + } + }, + + reject: function(reason) { + if (this.promise.$$state.status) return; + this.$$reject(reason); + }, + + $$reject: function(reason) { + this.promise.$$state.value = reason; + this.promise.$$state.status = 2; + scheduleProcessQueue(this.promise.$$state); + }, + + notify: function(progress) { + var callbacks = this.promise.$$state.pending; + + if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) { + nextTick(function() { + var callback, result; + for (var i = 0, ii = callbacks.length; i < ii; i++) { + result = callbacks[i][0]; + callback = callbacks[i][3]; + try { + result.notify(isFunction(callback) ? callback(progress) : progress); + } catch (e) { + exceptionHandler(e); + } + } + }); + } + } + }; + + /** + * @ngdoc method + * @name $q#reject + * @kind function + * + * @description + * Creates a promise that is resolved as rejected with the specified `reason`. This api should be + * used to forward rejection in a chain of promises. If you are dealing with the last promise in + * a promise chain, you don't need to worry about it. + * + * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of + * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via + * a promise error callback and you want to forward the error to the promise derived from the + * current promise, you have to "rethrow" the error by returning a rejection constructed via + * `reject`. + * + * ```js + * promiseB = promiseA.then(function(result) { + * // success: do something and resolve promiseB + * // with the old or a new result + * return result; + * }, function(reason) { + * // error: handle the error if possible and + * // resolve promiseB with newPromiseOrValue, + * // otherwise forward the rejection to promiseB + * if (canHandle(reason)) { + * // handle the error and recover + * return newPromiseOrValue; + * } + * return $q.reject(reason); + * }); + * ``` + * + * @param {*} reason Constant, message, exception or an object representing the rejection reason. + * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`. + */ + var reject = function(reason) { + var result = new Deferred(); + result.reject(reason); + return result.promise; + }; + + var makePromise = function makePromise(value, resolved) { + var result = new Deferred(); + if (resolved) { + result.resolve(value); + } else { + result.reject(value); + } + return result.promise; + }; + + var handleCallback = function handleCallback(value, isResolved, callback) { + var callbackOutput = null; + try { + if (isFunction(callback)) callbackOutput = callback(); + } catch (e) { + return makePromise(e, false); + } + if (isPromiseLike(callbackOutput)) { + return callbackOutput.then(function() { + return makePromise(value, isResolved); + }, function(error) { + return makePromise(error, false); + }); + } else { + return makePromise(value, isResolved); + } + }; + + /** + * @ngdoc method + * @name $q#when + * @kind function + * + * @description + * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise. + * This is useful when you are dealing with an object that might or might not be a promise, or if + * the promise comes from a source that can't be trusted. + * + * @param {*} value Value or a promise + * @returns {Promise} Returns a promise of the passed value or promise + */ + + + var when = function(value, callback, errback, progressBack) { + var result = new Deferred(); + result.resolve(value); + return result.promise.then(callback, errback, progressBack); + }; + + /** + * @ngdoc method + * @name $q#all + * @kind function + * + * @description + * Combines multiple promises into a single promise that is resolved when all of the input + * promises are resolved. + * + * @param {Array.|Object.} promises An array or hash of promises. + * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values, + * each value corresponding to the promise at the same index/key in the `promises` array/hash. + * If any of the promises is resolved with a rejection, this resulting promise will be rejected + * with the same rejection value. + */ + + function all(promises) { + var deferred = new Deferred(), + counter = 0, + results = isArray(promises) ? [] : {}; + + forEach(promises, function(promise, key) { + counter++; + when(promise).then(function(value) { + if (results.hasOwnProperty(key)) return; + results[key] = value; + if (!(--counter)) deferred.resolve(results); + }, function(reason) { + if (results.hasOwnProperty(key)) return; + deferred.reject(reason); + }); + }); + + if (counter === 0) { + deferred.resolve(results); + } + + return deferred.promise; + } + + var $Q = function Q(resolver) { + if (!isFunction(resolver)) { + throw $qMinErr('norslvr', "Expected resolverFn, got '{0}'", resolver); + } + + if (!(this instanceof Q)) { + // More useful when $Q is the Promise itself. + return new Q(resolver); + } + + var deferred = new Deferred(); + + function resolveFn(value) { + deferred.resolve(value); + } + + function rejectFn(reason) { + deferred.reject(reason); + } + + resolver(resolveFn, rejectFn); + + return deferred.promise; + }; + + $Q.defer = defer; + $Q.reject = reject; + $Q.when = when; + $Q.all = all; + + return $Q; +} + +function $$RAFProvider() { //rAF + this.$get = ['$window', '$timeout', function($window, $timeout) { + var requestAnimationFrame = $window.requestAnimationFrame || + $window.webkitRequestAnimationFrame; + + var cancelAnimationFrame = $window.cancelAnimationFrame || + $window.webkitCancelAnimationFrame || + $window.webkitCancelRequestAnimationFrame; + + var rafSupported = !!requestAnimationFrame; + var rafFn = rafSupported + ? function(fn) { + var id = requestAnimationFrame(fn); + return function() { + cancelAnimationFrame(id); + }; + } + : function(fn) { + var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666 + return function() { + $timeout.cancel(timer); + }; + }; + + queueFn.supported = rafSupported; + + var cancelLastRAF; + var taskCount = 0; + var taskQueue = []; + return queueFn; + + function flush() { + for (var i = 0; i < taskQueue.length; i++) { + var task = taskQueue[i]; + if (task) { + taskQueue[i] = null; + task(); + } + } + taskCount = taskQueue.length = 0; + } + + function queueFn(asyncFn) { + var index = taskQueue.length; + + taskCount++; + taskQueue.push(asyncFn); + + if (index === 0) { + cancelLastRAF = rafFn(flush); + } + + return function cancelQueueFn() { + if (index >= 0) { + taskQueue[index] = null; + index = null; + + if (--taskCount === 0 && cancelLastRAF) { + cancelLastRAF(); + cancelLastRAF = null; + taskQueue.length = 0; + } + } + }; + } + }]; +} + +/** + * DESIGN NOTES + * + * The design decisions behind the scope are heavily favored for speed and memory consumption. + * + * The typical use of scope is to watch the expressions, which most of the time return the same + * value as last time so we optimize the operation. + * + * Closures construction is expensive in terms of speed as well as memory: + * - No closures, instead use prototypical inheritance for API + * - Internal state needs to be stored on scope directly, which means that private state is + * exposed as $$____ properties + * + * Loop operations are optimized by using while(count--) { ... } + * - this means that in order to keep the same order of execution as addition we have to add + * items to the array at the beginning (unshift) instead of at the end (push) + * + * Child scopes are created and removed often + * - Using an array would be slow since inserts in middle are expensive so we use linked list + * + * There are few watches then a lot of observers. This is why you don't want the observer to be + * implemented in the same way as watch. Watch requires return of initialization function which + * are expensive to construct. + */ + + +/** + * @ngdoc provider + * @name $rootScopeProvider + * @description + * + * Provider for the $rootScope service. + */ + +/** + * @ngdoc method + * @name $rootScopeProvider#digestTtl + * @description + * + * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and + * assuming that the model is unstable. + * + * The current default is 10 iterations. + * + * In complex applications it's possible that the dependencies between `$watch`s will result in + * several digest iterations. However if an application needs more than the default 10 digest + * iterations for its model to stabilize then you should investigate what is causing the model to + * continuously change during the digest. + * + * Increasing the TTL could have performance implications, so you should not change it without + * proper justification. + * + * @param {number} limit The number of digest iterations. + */ + + +/** + * @ngdoc service + * @name $rootScope + * @description + * + * Every application has a single root {@link ng.$rootScope.Scope scope}. + * All other scopes are descendant scopes of the root scope. Scopes provide separation + * between the model and the view, via a mechanism for watching the model for changes. + * They also provide an event emission/broadcast and subscription facility. See the + * {@link guide/scope developer guide on scopes}. + */ +function $RootScopeProvider() { + var TTL = 10; + var $rootScopeMinErr = minErr('$rootScope'); + var lastDirtyWatch = null; + var applyAsyncId = null; + + this.digestTtl = function(value) { + if (arguments.length) { + TTL = value; + } + return TTL; + }; + + function createChildScopeClass(parent) { + function ChildScope() { + this.$$watchers = this.$$nextSibling = + this.$$childHead = this.$$childTail = null; + this.$$listeners = {}; + this.$$listenerCount = {}; + this.$$watchersCount = 0; + this.$id = nextUid(); + this.$$ChildScope = null; + } + ChildScope.prototype = parent; + return ChildScope; + } + + this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser', + function($injector, $exceptionHandler, $parse, $browser) { + + function destroyChildScope($event) { + $event.currentScope.$$destroyed = true; + } + + /** + * @ngdoc type + * @name $rootScope.Scope + * + * @description + * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the + * {@link auto.$injector $injector}. Child scopes are created using the + * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when + * compiled HTML template is executed.) + * + * Here is a simple scope snippet to show how you can interact with the scope. + * ```html + * + * ``` + * + * # Inheritance + * A scope can inherit from a parent scope, as in this example: + * ```js + var parent = $rootScope; + var child = parent.$new(); + + parent.salutation = "Hello"; + expect(child.salutation).toEqual('Hello'); + + child.salutation = "Welcome"; + expect(child.salutation).toEqual('Welcome'); + expect(parent.salutation).toEqual('Hello'); + * ``` + * + * When interacting with `Scope` in tests, additional helper methods are available on the + * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional + * details. + * + * + * @param {Object.=} providers Map of service factory which need to be + * provided for the current scope. Defaults to {@link ng}. + * @param {Object.=} instanceCache Provides pre-instantiated services which should + * append/override services provided by `providers`. This is handy + * when unit-testing and having the need to override a default + * service. + * @returns {Object} Newly created scope. + * + */ + function Scope() { + this.$id = nextUid(); + this.$$phase = this.$parent = this.$$watchers = + this.$$nextSibling = this.$$prevSibling = + this.$$childHead = this.$$childTail = null; + this.$root = this; + this.$$destroyed = false; + this.$$listeners = {}; + this.$$listenerCount = {}; + this.$$watchersCount = 0; + this.$$isolateBindings = null; + } + + /** + * @ngdoc property + * @name $rootScope.Scope#$id + * + * @description + * Unique scope ID (monotonically increasing) useful for debugging. + */ + + /** + * @ngdoc property + * @name $rootScope.Scope#$parent + * + * @description + * Reference to the parent scope. + */ + + /** + * @ngdoc property + * @name $rootScope.Scope#$root + * + * @description + * Reference to the root scope. + */ + + Scope.prototype = { + constructor: Scope, + /** + * @ngdoc method + * @name $rootScope.Scope#$new + * @kind function + * + * @description + * Creates a new child {@link ng.$rootScope.Scope scope}. + * + * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event. + * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}. + * + * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is + * desired for the scope and its child scopes to be permanently detached from the parent and + * thus stop participating in model change detection and listener notification by invoking. + * + * @param {boolean} isolate If true, then the scope does not prototypically inherit from the + * parent scope. The scope is isolated, as it can not see parent scope properties. + * When creating widgets, it is useful for the widget to not accidentally read parent + * state. + * + * @param {Scope} [parent=this] The {@link ng.$rootScope.Scope `Scope`} that will be the `$parent` + * of the newly created scope. Defaults to `this` scope if not provided. + * This is used when creating a transclude scope to correctly place it + * in the scope hierarchy while maintaining the correct prototypical + * inheritance. + * + * @returns {Object} The newly created child scope. + * + */ + $new: function(isolate, parent) { + var child; + + parent = parent || this; + + if (isolate) { + child = new Scope(); + child.$root = this.$root; + } else { + // Only create a child scope class if somebody asks for one, + // but cache it to allow the VM to optimize lookups. + if (!this.$$ChildScope) { + this.$$ChildScope = createChildScopeClass(this); + } + child = new this.$$ChildScope(); + } + child.$parent = parent; + child.$$prevSibling = parent.$$childTail; + if (parent.$$childHead) { + parent.$$childTail.$$nextSibling = child; + parent.$$childTail = child; + } else { + parent.$$childHead = parent.$$childTail = child; + } + + // When the new scope is not isolated or we inherit from `this`, and + // the parent scope is destroyed, the property `$$destroyed` is inherited + // prototypically. In all other cases, this property needs to be set + // when the parent scope is destroyed. + // The listener needs to be added after the parent is set + if (isolate || parent != this) child.$on('$destroy', destroyChildScope); + + return child; + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$watch + * @kind function + * + * @description + * Registers a `listener` callback to be executed whenever the `watchExpression` changes. + * + * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest + * $digest()} and should return the value that will be watched. (Since + * {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the + * `watchExpression` can execute multiple times per + * {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.) + * - The `listener` is called only when the value from the current `watchExpression` and the + * previous call to `watchExpression` are not equal (with the exception of the initial run, + * see below). Inequality is determined according to reference inequality, + * [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators) + * via the `!==` Javascript operator, unless `objectEquality == true` + * (see next point) + * - When `objectEquality == true`, inequality of the `watchExpression` is determined + * according to the {@link angular.equals} function. To save the value of the object for + * later comparison, the {@link angular.copy} function is used. This therefore means that + * watching complex objects will have adverse memory and performance implications. + * - The watch `listener` may change the model, which may trigger other `listener`s to fire. + * This is achieved by rerunning the watchers until no changes are detected. The rerun + * iteration limit is 10 to prevent an infinite loop deadlock. + * + * + * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called, + * you can register a `watchExpression` function with no `listener`. (Since `watchExpression` + * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a + * change is detected, be prepared for multiple calls to your listener.) + * + * After a watcher is registered with the scope, the `listener` fn is called asynchronously + * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the + * watcher. In rare cases, this is undesirable because the listener is called when the result + * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you + * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the + * listener was called due to initialization. + * + * + * + * # Example + * ```js + // let's assume that scope was dependency injected as the $rootScope + var scope = $rootScope; + scope.name = 'misko'; + scope.counter = 0; + + expect(scope.counter).toEqual(0); + scope.$watch('name', function(newValue, oldValue) { + scope.counter = scope.counter + 1; + }); + expect(scope.counter).toEqual(0); + + scope.$digest(); + // the listener is always called during the first $digest loop after it was registered + expect(scope.counter).toEqual(1); + + scope.$digest(); + // but now it will not be called unless the value changes + expect(scope.counter).toEqual(1); + + scope.name = 'adam'; + scope.$digest(); + expect(scope.counter).toEqual(2); + + + + // Using a function as a watchExpression + var food; + scope.foodCounter = 0; + expect(scope.foodCounter).toEqual(0); + scope.$watch( + // This function returns the value being watched. It is called for each turn of the $digest loop + function() { return food; }, + // This is the change listener, called when the value returned from the above function changes + function(newValue, oldValue) { + if ( newValue !== oldValue ) { + // Only increment the counter if the value changed + scope.foodCounter = scope.foodCounter + 1; + } + } + ); + // No digest has been run so the counter will be zero + expect(scope.foodCounter).toEqual(0); + + // Run the digest but since food has not changed count will still be zero + scope.$digest(); + expect(scope.foodCounter).toEqual(0); + + // Update food and run digest. Now the counter will increment + food = 'cheeseburger'; + scope.$digest(); + expect(scope.foodCounter).toEqual(1); + + * ``` + * + * + * + * @param {(function()|string)} watchExpression Expression that is evaluated on each + * {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers + * a call to the `listener`. + * + * - `string`: Evaluated as {@link guide/expression expression} + * - `function(scope)`: called with current `scope` as a parameter. + * @param {function(newVal, oldVal, scope)} listener Callback called whenever the value + * of `watchExpression` changes. + * + * - `newVal` contains the current value of the `watchExpression` + * - `oldVal` contains the previous value of the `watchExpression` + * - `scope` refers to the current scope + * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of + * comparing for reference equality. + * @returns {function()} Returns a deregistration function for this listener. + */ + $watch: function(watchExp, listener, objectEquality, prettyPrintExpression) { + var get = $parse(watchExp); + + if (get.$$watchDelegate) { + return get.$$watchDelegate(this, listener, objectEquality, get, watchExp); + } + var scope = this, + array = scope.$$watchers, + watcher = { + fn: listener, + last: initWatchVal, + get: get, + exp: prettyPrintExpression || watchExp, + eq: !!objectEquality + }; + + lastDirtyWatch = null; + + if (!isFunction(listener)) { + watcher.fn = noop; + } + + if (!array) { + array = scope.$$watchers = []; + } + // we use unshift since we use a while loop in $digest for speed. + // the while loop reads in reverse order. + array.unshift(watcher); + incrementWatchersCount(this, 1); + + return function deregisterWatch() { + if (arrayRemove(array, watcher) >= 0) { + incrementWatchersCount(scope, -1); + } + lastDirtyWatch = null; + }; + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$watchGroup + * @kind function + * + * @description + * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`. + * If any one expression in the collection changes the `listener` is executed. + * + * - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every + * call to $digest() to see if any items changes. + * - The `listener` is called whenever any expression in the `watchExpressions` array changes. + * + * @param {Array.} watchExpressions Array of expressions that will be individually + * watched using {@link ng.$rootScope.Scope#$watch $watch()} + * + * @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any + * expression in `watchExpressions` changes + * The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching + * those of `watchExpression` + * and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching + * those of `watchExpression` + * The `scope` refers to the current scope. + * @returns {function()} Returns a de-registration function for all listeners. + */ + $watchGroup: function(watchExpressions, listener) { + var oldValues = new Array(watchExpressions.length); + var newValues = new Array(watchExpressions.length); + var deregisterFns = []; + var self = this; + var changeReactionScheduled = false; + var firstRun = true; + + if (!watchExpressions.length) { + // No expressions means we call the listener ASAP + var shouldCall = true; + self.$evalAsync(function() { + if (shouldCall) listener(newValues, newValues, self); + }); + return function deregisterWatchGroup() { + shouldCall = false; + }; + } + + if (watchExpressions.length === 1) { + // Special case size of one + return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) { + newValues[0] = value; + oldValues[0] = oldValue; + listener(newValues, (value === oldValue) ? newValues : oldValues, scope); + }); + } + + forEach(watchExpressions, function(expr, i) { + var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) { + newValues[i] = value; + oldValues[i] = oldValue; + if (!changeReactionScheduled) { + changeReactionScheduled = true; + self.$evalAsync(watchGroupAction); + } + }); + deregisterFns.push(unwatchFn); + }); + + function watchGroupAction() { + changeReactionScheduled = false; + + if (firstRun) { + firstRun = false; + listener(newValues, newValues, self); + } else { + listener(newValues, oldValues, self); + } + } + + return function deregisterWatchGroup() { + while (deregisterFns.length) { + deregisterFns.shift()(); + } + }; + }, + + + /** + * @ngdoc method + * @name $rootScope.Scope#$watchCollection + * @kind function + * + * @description + * Shallow watches the properties of an object and fires whenever any of the properties change + * (for arrays, this implies watching the array items; for object maps, this implies watching + * the properties). If a change is detected, the `listener` callback is fired. + * + * - The `obj` collection is observed via standard $watch operation and is examined on every + * call to $digest() to see if any items have been added, removed, or moved. + * - The `listener` is called whenever anything within the `obj` has changed. Examples include + * adding, removing, and moving items belonging to an object or array. + * + * + * # Example + * ```js + $scope.names = ['igor', 'matias', 'misko', 'james']; + $scope.dataCount = 4; + + $scope.$watchCollection('names', function(newNames, oldNames) { + $scope.dataCount = newNames.length; + }); + + expect($scope.dataCount).toEqual(4); + $scope.$digest(); + + //still at 4 ... no changes + expect($scope.dataCount).toEqual(4); + + $scope.names.pop(); + $scope.$digest(); + + //now there's been a change + expect($scope.dataCount).toEqual(3); + * ``` + * + * + * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The + * expression value should evaluate to an object or an array which is observed on each + * {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the + * collection will trigger a call to the `listener`. + * + * @param {function(newCollection, oldCollection, scope)} listener a callback function called + * when a change is detected. + * - The `newCollection` object is the newly modified data obtained from the `obj` expression + * - The `oldCollection` object is a copy of the former collection data. + * Due to performance considerations, the`oldCollection` value is computed only if the + * `listener` function declares two or more arguments. + * - The `scope` argument refers to the current scope. + * + * @returns {function()} Returns a de-registration function for this listener. When the + * de-registration function is executed, the internal watch operation is terminated. + */ + $watchCollection: function(obj, listener) { + $watchCollectionInterceptor.$stateful = true; + + var self = this; + // the current value, updated on each dirty-check run + var newValue; + // a shallow copy of the newValue from the last dirty-check run, + // updated to match newValue during dirty-check run + var oldValue; + // a shallow copy of the newValue from when the last change happened + var veryOldValue; + // only track veryOldValue if the listener is asking for it + var trackVeryOldValue = (listener.length > 1); + var changeDetected = 0; + var changeDetector = $parse(obj, $watchCollectionInterceptor); + var internalArray = []; + var internalObject = {}; + var initRun = true; + var oldLength = 0; + + function $watchCollectionInterceptor(_value) { + newValue = _value; + var newLength, key, bothNaN, newItem, oldItem; + + // If the new value is undefined, then return undefined as the watch may be a one-time watch + if (isUndefined(newValue)) return; + + if (!isObject(newValue)) { // if primitive + if (oldValue !== newValue) { + oldValue = newValue; + changeDetected++; + } + } else if (isArrayLike(newValue)) { + if (oldValue !== internalArray) { + // we are transitioning from something which was not an array into array. + oldValue = internalArray; + oldLength = oldValue.length = 0; + changeDetected++; + } + + newLength = newValue.length; + + if (oldLength !== newLength) { + // if lengths do not match we need to trigger change notification + changeDetected++; + oldValue.length = oldLength = newLength; + } + // copy the items to oldValue and look for changes. + for (var i = 0; i < newLength; i++) { + oldItem = oldValue[i]; + newItem = newValue[i]; + + bothNaN = (oldItem !== oldItem) && (newItem !== newItem); + if (!bothNaN && (oldItem !== newItem)) { + changeDetected++; + oldValue[i] = newItem; + } + } + } else { + if (oldValue !== internalObject) { + // we are transitioning from something which was not an object into object. + oldValue = internalObject = {}; + oldLength = 0; + changeDetected++; + } + // copy the items to oldValue and look for changes. + newLength = 0; + for (key in newValue) { + if (newValue.hasOwnProperty(key)) { + newLength++; + newItem = newValue[key]; + oldItem = oldValue[key]; + + if (key in oldValue) { + bothNaN = (oldItem !== oldItem) && (newItem !== newItem); + if (!bothNaN && (oldItem !== newItem)) { + changeDetected++; + oldValue[key] = newItem; + } + } else { + oldLength++; + oldValue[key] = newItem; + changeDetected++; + } + } + } + if (oldLength > newLength) { + // we used to have more keys, need to find them and destroy them. + changeDetected++; + for (key in oldValue) { + if (!newValue.hasOwnProperty(key)) { + oldLength--; + delete oldValue[key]; + } + } + } + } + return changeDetected; + } + + function $watchCollectionAction() { + if (initRun) { + initRun = false; + listener(newValue, newValue, self); + } else { + listener(newValue, veryOldValue, self); + } + + // make a copy for the next time a collection is changed + if (trackVeryOldValue) { + if (!isObject(newValue)) { + //primitive + veryOldValue = newValue; + } else if (isArrayLike(newValue)) { + veryOldValue = new Array(newValue.length); + for (var i = 0; i < newValue.length; i++) { + veryOldValue[i] = newValue[i]; + } + } else { // if object + veryOldValue = {}; + for (var key in newValue) { + if (hasOwnProperty.call(newValue, key)) { + veryOldValue[key] = newValue[key]; + } + } + } + } + } + + return this.$watch(changeDetector, $watchCollectionAction); + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$digest + * @kind function + * + * @description + * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and + * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change + * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} + * until no more listeners are firing. This means that it is possible to get into an infinite + * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of + * iterations exceeds 10. + * + * Usually, you don't call `$digest()` directly in + * {@link ng.directive:ngController controllers} or in + * {@link ng.$compileProvider#directive directives}. + * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within + * a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`. + * + * If you want to be notified whenever `$digest()` is called, + * you can register a `watchExpression` function with + * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`. + * + * In unit tests, you may need to call `$digest()` to simulate the scope life cycle. + * + * # Example + * ```js + var scope = ...; + scope.name = 'misko'; + scope.counter = 0; + + expect(scope.counter).toEqual(0); + scope.$watch('name', function(newValue, oldValue) { + scope.counter = scope.counter + 1; + }); + expect(scope.counter).toEqual(0); + + scope.$digest(); + // the listener is always called during the first $digest loop after it was registered + expect(scope.counter).toEqual(1); + + scope.$digest(); + // but now it will not be called unless the value changes + expect(scope.counter).toEqual(1); + + scope.name = 'adam'; + scope.$digest(); + expect(scope.counter).toEqual(2); + * ``` + * + */ + $digest: function() { + var watch, value, last, + watchers, + length, + dirty, ttl = TTL, + next, current, target = this, + watchLog = [], + logIdx, logMsg, asyncTask; + + beginPhase('$digest'); + // Check for changes to browser url that happened in sync before the call to $digest + $browser.$$checkUrlChange(); + + if (this === $rootScope && applyAsyncId !== null) { + // If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then + // cancel the scheduled $apply and flush the queue of expressions to be evaluated. + $browser.defer.cancel(applyAsyncId); + flushApplyAsync(); + } + + lastDirtyWatch = null; + + do { // "while dirty" loop + dirty = false; + current = target; + + while (asyncQueue.length) { + try { + asyncTask = asyncQueue.shift(); + asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals); + } catch (e) { + $exceptionHandler(e); + } + lastDirtyWatch = null; + } + + traverseScopesLoop: + do { // "traverse the scopes" loop + if ((watchers = current.$$watchers)) { + // process our watches + length = watchers.length; + while (length--) { + try { + watch = watchers[length]; + // Most common watches are on primitives, in which case we can short + // circuit it with === operator, only when === fails do we use .equals + if (watch) { + if ((value = watch.get(current)) !== (last = watch.last) && + !(watch.eq + ? equals(value, last) + : (typeof value === 'number' && typeof last === 'number' + && isNaN(value) && isNaN(last)))) { + dirty = true; + lastDirtyWatch = watch; + watch.last = watch.eq ? copy(value, null) : value; + watch.fn(value, ((last === initWatchVal) ? value : last), current); + if (ttl < 5) { + logIdx = 4 - ttl; + if (!watchLog[logIdx]) watchLog[logIdx] = []; + watchLog[logIdx].push({ + msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp, + newVal: value, + oldVal: last + }); + } + } else if (watch === lastDirtyWatch) { + // If the most recently dirty watcher is now clean, short circuit since the remaining watchers + // have already been tested. + dirty = false; + break traverseScopesLoop; + } + } + } catch (e) { + $exceptionHandler(e); + } + } + } + + // Insanity Warning: scope depth-first traversal + // yes, this code is a bit crazy, but it works and we have tests to prove it! + // this piece should be kept in sync with the traversal in $broadcast + if (!(next = ((current.$$watchersCount && current.$$childHead) || + (current !== target && current.$$nextSibling)))) { + while (current !== target && !(next = current.$$nextSibling)) { + current = current.$parent; + } + } + } while ((current = next)); + + // `break traverseScopesLoop;` takes us to here + + if ((dirty || asyncQueue.length) && !(ttl--)) { + clearPhase(); + throw $rootScopeMinErr('infdig', + '{0} $digest() iterations reached. Aborting!\n' + + 'Watchers fired in the last 5 iterations: {1}', + TTL, watchLog); + } + + } while (dirty || asyncQueue.length); + + clearPhase(); + + while (postDigestQueue.length) { + try { + postDigestQueue.shift()(); + } catch (e) { + $exceptionHandler(e); + } + } + }, + + + /** + * @ngdoc event + * @name $rootScope.Scope#$destroy + * @eventType broadcast on scope being destroyed + * + * @description + * Broadcasted when a scope and its children are being destroyed. + * + * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to + * clean up DOM bindings before an element is removed from the DOM. + */ + + /** + * @ngdoc method + * @name $rootScope.Scope#$destroy + * @kind function + * + * @description + * Removes the current scope (and all of its children) from the parent scope. Removal implies + * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer + * propagate to the current scope and its children. Removal also implies that the current + * scope is eligible for garbage collection. + * + * The `$destroy()` is usually used by directives such as + * {@link ng.directive:ngRepeat ngRepeat} for managing the + * unrolling of the loop. + * + * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope. + * Application code can register a `$destroy` event handler that will give it a chance to + * perform any necessary cleanup. + * + * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to + * clean up DOM bindings before an element is removed from the DOM. + */ + $destroy: function() { + // We can't destroy a scope that has been already destroyed. + if (this.$$destroyed) return; + var parent = this.$parent; + + this.$broadcast('$destroy'); + this.$$destroyed = true; + + if (this === $rootScope) { + //Remove handlers attached to window when $rootScope is removed + $browser.$$applicationDestroyed(); + } + + incrementWatchersCount(this, -this.$$watchersCount); + for (var eventName in this.$$listenerCount) { + decrementListenerCount(this, this.$$listenerCount[eventName], eventName); + } + + // sever all the references to parent scopes (after this cleanup, the current scope should + // not be retained by any of our references and should be eligible for garbage collection) + if (parent && parent.$$childHead == this) parent.$$childHead = this.$$nextSibling; + if (parent && parent.$$childTail == this) parent.$$childTail = this.$$prevSibling; + if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling; + if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling; + + // Disable listeners, watchers and apply/digest methods + this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop; + this.$on = this.$watch = this.$watchGroup = function() { return noop; }; + this.$$listeners = {}; + + // All of the code below is bogus code that works around V8's memory leak via optimized code + // and inline caches. + // + // see: + // - https://code.google.com/p/v8/issues/detail?id=2073#c26 + // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909 + // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451 + + this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead = + this.$$childTail = this.$root = this.$$watchers = null; + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$eval + * @kind function + * + * @description + * Executes the `expression` on the current scope and returns the result. Any exceptions in + * the expression are propagated (uncaught). This is useful when evaluating Angular + * expressions. + * + * # Example + * ```js + var scope = ng.$rootScope.Scope(); + scope.a = 1; + scope.b = 2; + + expect(scope.$eval('a+b')).toEqual(3); + expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3); + * ``` + * + * @param {(string|function())=} expression An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/expression expression}. + * - `function(scope)`: execute the function with the current `scope` parameter. + * + * @param {(object)=} locals Local variables object, useful for overriding values in scope. + * @returns {*} The result of evaluating the expression. + */ + $eval: function(expr, locals) { + return $parse(expr)(this, locals); + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$evalAsync + * @kind function + * + * @description + * Executes the expression on the current scope at a later point in time. + * + * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only + * that: + * + * - it will execute after the function that scheduled the evaluation (preferably before DOM + * rendering). + * - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after + * `expression` execution. + * + * Any exceptions from the execution of the expression are forwarded to the + * {@link ng.$exceptionHandler $exceptionHandler} service. + * + * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle + * will be scheduled. However, it is encouraged to always call code that changes the model + * from within an `$apply` call. That includes code evaluated via `$evalAsync`. + * + * @param {(string|function())=} expression An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/expression expression}. + * - `function(scope)`: execute the function with the current `scope` parameter. + * + * @param {(object)=} locals Local variables object, useful for overriding values in scope. + */ + $evalAsync: function(expr, locals) { + // if we are outside of an $digest loop and this is the first time we are scheduling async + // task also schedule async auto-flush + if (!$rootScope.$$phase && !asyncQueue.length) { + $browser.defer(function() { + if (asyncQueue.length) { + $rootScope.$digest(); + } + }); + } + + asyncQueue.push({scope: this, expression: expr, locals: locals}); + }, + + $$postDigest: function(fn) { + postDigestQueue.push(fn); + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$apply + * @kind function + * + * @description + * `$apply()` is used to execute an expression in angular from outside of the angular + * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries). + * Because we are calling into the angular framework we need to perform proper scope life + * cycle of {@link ng.$exceptionHandler exception handling}, + * {@link ng.$rootScope.Scope#$digest executing watches}. + * + * ## Life cycle + * + * # Pseudo-Code of `$apply()` + * ```js + function $apply(expr) { + try { + return $eval(expr); + } catch (e) { + $exceptionHandler(e); + } finally { + $root.$digest(); + } + } + * ``` + * + * + * Scope's `$apply()` method transitions through the following stages: + * + * 1. The {@link guide/expression expression} is executed using the + * {@link ng.$rootScope.Scope#$eval $eval()} method. + * 2. Any exceptions from the execution of the expression are forwarded to the + * {@link ng.$exceptionHandler $exceptionHandler} service. + * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the + * expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method. + * + * + * @param {(string|function())=} exp An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/expression expression}. + * - `function(scope)`: execute the function with current `scope` parameter. + * + * @returns {*} The result of evaluating the expression. + */ + $apply: function(expr) { + try { + beginPhase('$apply'); + return this.$eval(expr); + } catch (e) { + $exceptionHandler(e); + } finally { + clearPhase(); + try { + $rootScope.$digest(); + } catch (e) { + $exceptionHandler(e); + throw e; + } + } + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$applyAsync + * @kind function + * + * @description + * Schedule the invocation of $apply to occur at a later time. The actual time difference + * varies across browsers, but is typically around ~10 milliseconds. + * + * This can be used to queue up multiple expressions which need to be evaluated in the same + * digest. + * + * @param {(string|function())=} exp An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/expression expression}. + * - `function(scope)`: execute the function with current `scope` parameter. + */ + $applyAsync: function(expr) { + var scope = this; + expr && applyAsyncQueue.push($applyAsyncExpression); + scheduleApplyAsync(); + + function $applyAsyncExpression() { + scope.$eval(expr); + } + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$on + * @kind function + * + * @description + * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for + * discussion of event life cycle. + * + * The event listener function format is: `function(event, args...)`. The `event` object + * passed into the listener has the following attributes: + * + * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or + * `$broadcast`-ed. + * - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the + * event propagates through the scope hierarchy, this property is set to null. + * - `name` - `{string}`: name of the event. + * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel + * further event propagation (available only for events that were `$emit`-ed). + * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag + * to true. + * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called. + * + * @param {string} name Event name to listen on. + * @param {function(event, ...args)} listener Function to call when the event is emitted. + * @returns {function()} Returns a deregistration function for this listener. + */ + $on: function(name, listener) { + var namedListeners = this.$$listeners[name]; + if (!namedListeners) { + this.$$listeners[name] = namedListeners = []; + } + namedListeners.push(listener); + + var current = this; + do { + if (!current.$$listenerCount[name]) { + current.$$listenerCount[name] = 0; + } + current.$$listenerCount[name]++; + } while ((current = current.$parent)); + + var self = this; + return function() { + var indexOfListener = namedListeners.indexOf(listener); + if (indexOfListener !== -1) { + namedListeners[indexOfListener] = null; + decrementListenerCount(self, 1, name); + } + }; + }, + + + /** + * @ngdoc method + * @name $rootScope.Scope#$emit + * @kind function + * + * @description + * Dispatches an event `name` upwards through the scope hierarchy notifying the + * registered {@link ng.$rootScope.Scope#$on} listeners. + * + * The event life cycle starts at the scope on which `$emit` was called. All + * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get + * notified. Afterwards, the event traverses upwards toward the root scope and calls all + * registered listeners along the way. The event will stop propagating if one of the listeners + * cancels it. + * + * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed + * onto the {@link ng.$exceptionHandler $exceptionHandler} service. + * + * @param {string} name Event name to emit. + * @param {...*} args Optional one or more arguments which will be passed onto the event listeners. + * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}). + */ + $emit: function(name, args) { + var empty = [], + namedListeners, + scope = this, + stopPropagation = false, + event = { + name: name, + targetScope: scope, + stopPropagation: function() {stopPropagation = true;}, + preventDefault: function() { + event.defaultPrevented = true; + }, + defaultPrevented: false + }, + listenerArgs = concat([event], arguments, 1), + i, length; + + do { + namedListeners = scope.$$listeners[name] || empty; + event.currentScope = scope; + for (i = 0, length = namedListeners.length; i < length; i++) { + + // if listeners were deregistered, defragment the array + if (!namedListeners[i]) { + namedListeners.splice(i, 1); + i--; + length--; + continue; + } + try { + //allow all listeners attached to the current scope to run + namedListeners[i].apply(null, listenerArgs); + } catch (e) { + $exceptionHandler(e); + } + } + //if any listener on the current scope stops propagation, prevent bubbling + if (stopPropagation) { + event.currentScope = null; + return event; + } + //traverse upwards + scope = scope.$parent; + } while (scope); + + event.currentScope = null; + + return event; + }, + + + /** + * @ngdoc method + * @name $rootScope.Scope#$broadcast + * @kind function + * + * @description + * Dispatches an event `name` downwards to all child scopes (and their children) notifying the + * registered {@link ng.$rootScope.Scope#$on} listeners. + * + * The event life cycle starts at the scope on which `$broadcast` was called. All + * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get + * notified. Afterwards, the event propagates to all direct and indirect scopes of the current + * scope and calls all registered listeners along the way. The event cannot be canceled. + * + * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed + * onto the {@link ng.$exceptionHandler $exceptionHandler} service. + * + * @param {string} name Event name to broadcast. + * @param {...*} args Optional one or more arguments which will be passed onto the event listeners. + * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on} + */ + $broadcast: function(name, args) { + var target = this, + current = target, + next = target, + event = { + name: name, + targetScope: target, + preventDefault: function() { + event.defaultPrevented = true; + }, + defaultPrevented: false + }; + + if (!target.$$listenerCount[name]) return event; + + var listenerArgs = concat([event], arguments, 1), + listeners, i, length; + + //down while you can, then up and next sibling or up and next sibling until back at root + while ((current = next)) { + event.currentScope = current; + listeners = current.$$listeners[name] || []; + for (i = 0, length = listeners.length; i < length; i++) { + // if listeners were deregistered, defragment the array + if (!listeners[i]) { + listeners.splice(i, 1); + i--; + length--; + continue; + } + + try { + listeners[i].apply(null, listenerArgs); + } catch (e) { + $exceptionHandler(e); + } + } + + // Insanity Warning: scope depth-first traversal + // yes, this code is a bit crazy, but it works and we have tests to prove it! + // this piece should be kept in sync with the traversal in $digest + // (though it differs due to having the extra check for $$listenerCount) + if (!(next = ((current.$$listenerCount[name] && current.$$childHead) || + (current !== target && current.$$nextSibling)))) { + while (current !== target && !(next = current.$$nextSibling)) { + current = current.$parent; + } + } + } + + event.currentScope = null; + return event; + } + }; + + var $rootScope = new Scope(); + + //The internal queues. Expose them on the $rootScope for debugging/testing purposes. + var asyncQueue = $rootScope.$$asyncQueue = []; + var postDigestQueue = $rootScope.$$postDigestQueue = []; + var applyAsyncQueue = $rootScope.$$applyAsyncQueue = []; + + return $rootScope; + + + function beginPhase(phase) { + if ($rootScope.$$phase) { + throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase); + } + + $rootScope.$$phase = phase; + } + + function clearPhase() { + $rootScope.$$phase = null; + } + + function incrementWatchersCount(current, count) { + do { + current.$$watchersCount += count; + } while ((current = current.$parent)); + } + + function decrementListenerCount(current, count, name) { + do { + current.$$listenerCount[name] -= count; + + if (current.$$listenerCount[name] === 0) { + delete current.$$listenerCount[name]; + } + } while ((current = current.$parent)); + } + + /** + * function used as an initial value for watchers. + * because it's unique we can easily tell it apart from other values + */ + function initWatchVal() {} + + function flushApplyAsync() { + while (applyAsyncQueue.length) { + try { + applyAsyncQueue.shift()(); + } catch (e) { + $exceptionHandler(e); + } + } + applyAsyncId = null; + } + + function scheduleApplyAsync() { + if (applyAsyncId === null) { + applyAsyncId = $browser.defer(function() { + $rootScope.$apply(flushApplyAsync); + }); + } + } + }]; +} + +/** + * @description + * Private service to sanitize uris for links and images. Used by $compile and $sanitize. + */ +function $$SanitizeUriProvider() { + var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/, + imgSrcSanitizationWhitelist = /^\s*((https?|ftp|file|blob):|data:image\/)/; + + /** + * @description + * Retrieves or overrides the default regular expression that is used for whitelisting of safe + * urls during a[href] sanitization. + * + * The sanitization is a security measure aimed at prevent XSS attacks via html links. + * + * Any url about to be assigned to a[href] via data-binding is first normalized and turned into + * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist` + * regular expression. If a match is found, the original url is written into the dom. Otherwise, + * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * + * @param {RegExp=} regexp New regexp to whitelist urls with. + * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for + * chaining otherwise. + */ + this.aHrefSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + aHrefSanitizationWhitelist = regexp; + return this; + } + return aHrefSanitizationWhitelist; + }; + + + /** + * @description + * Retrieves or overrides the default regular expression that is used for whitelisting of safe + * urls during img[src] sanitization. + * + * The sanitization is a security measure aimed at prevent XSS attacks via html links. + * + * Any url about to be assigned to img[src] via data-binding is first normalized and turned into + * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist` + * regular expression. If a match is found, the original url is written into the dom. Otherwise, + * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * + * @param {RegExp=} regexp New regexp to whitelist urls with. + * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for + * chaining otherwise. + */ + this.imgSrcSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + imgSrcSanitizationWhitelist = regexp; + return this; + } + return imgSrcSanitizationWhitelist; + }; + + this.$get = function() { + return function sanitizeUri(uri, isImage) { + var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist; + var normalizedVal; + normalizedVal = urlResolve(uri).href; + if (normalizedVal !== '' && !normalizedVal.match(regex)) { + return 'unsafe:' + normalizedVal; + } + return uri; + }; + }; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +var $sceMinErr = minErr('$sce'); + +var SCE_CONTEXTS = { + HTML: 'html', + CSS: 'css', + URL: 'url', + // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a + // url. (e.g. ng-include, script src, templateUrl) + RESOURCE_URL: 'resourceUrl', + JS: 'js' +}; + +// Helper functions follow. + +function adjustMatcher(matcher) { + if (matcher === 'self') { + return matcher; + } else if (isString(matcher)) { + // Strings match exactly except for 2 wildcards - '*' and '**'. + // '*' matches any character except those from the set ':/.?&'. + // '**' matches any character (like .* in a RegExp). + // More than 2 *'s raises an error as it's ill defined. + if (matcher.indexOf('***') > -1) { + throw $sceMinErr('iwcard', + 'Illegal sequence *** in string matcher. String: {0}', matcher); + } + matcher = escapeForRegexp(matcher). + replace('\\*\\*', '.*'). + replace('\\*', '[^:/.?&;]*'); + return new RegExp('^' + matcher + '$'); + } else if (isRegExp(matcher)) { + // The only other type of matcher allowed is a Regexp. + // Match entire URL / disallow partial matches. + // Flags are reset (i.e. no global, ignoreCase or multiline) + return new RegExp('^' + matcher.source + '$'); + } else { + throw $sceMinErr('imatcher', + 'Matchers may only be "self", string patterns or RegExp objects'); + } +} + + +function adjustMatchers(matchers) { + var adjustedMatchers = []; + if (isDefined(matchers)) { + forEach(matchers, function(matcher) { + adjustedMatchers.push(adjustMatcher(matcher)); + }); + } + return adjustedMatchers; +} + + +/** + * @ngdoc service + * @name $sceDelegate + * @kind function + * + * @description + * + * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict + * Contextual Escaping (SCE)} services to AngularJS. + * + * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of + * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS. This is + * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to + * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things + * work because `$sce` delegates to `$sceDelegate` for these operations. + * + * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service. + * + * The default instance of `$sceDelegate` should work out of the box with little pain. While you + * can override it completely to change the behavior of `$sce`, the common case would + * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting + * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as + * templates. Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist + * $sceDelegateProvider.resourceUrlWhitelist} and {@link + * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist} + */ + +/** + * @ngdoc provider + * @name $sceDelegateProvider + * @description + * + * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate + * $sceDelegate} service. This allows one to get/set the whitelists and blacklists used to ensure + * that the URLs used for sourcing Angular templates are safe. Refer {@link + * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and + * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist} + * + * For the general details about this service in Angular, read the main page for {@link ng.$sce + * Strict Contextual Escaping (SCE)}. + * + * **Example**: Consider the following case. + * + * - your app is hosted at url `http://myapp.example.com/` + * - but some of your templates are hosted on other domains you control such as + * `http://srv01.assets.example.com/`,  `http://srv02.assets.example.com/`, etc. + * - and you have an open redirect at `http://myapp.example.com/clickThru?...`. + * + * Here is what a secure configuration for this scenario might look like: + * + * ``` + * angular.module('myApp', []).config(function($sceDelegateProvider) { + * $sceDelegateProvider.resourceUrlWhitelist([ + * // Allow same origin resource loads. + * 'self', + * // Allow loading from our assets domain. Notice the difference between * and **. + * 'http://srv*.assets.example.com/**' + * ]); + * + * // The blacklist overrides the whitelist so the open redirect here is blocked. + * $sceDelegateProvider.resourceUrlBlacklist([ + * 'http://myapp.example.com/clickThru**' + * ]); + * }); + * ``` + */ + +function $SceDelegateProvider() { + this.SCE_CONTEXTS = SCE_CONTEXTS; + + // Resource URLs can also be trusted by policy. + var resourceUrlWhitelist = ['self'], + resourceUrlBlacklist = []; + + /** + * @ngdoc method + * @name $sceDelegateProvider#resourceUrlWhitelist + * @kind function + * + * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value + * provided. This must be an array or null. A snapshot of this array is used so further + * changes to the array are ignored. + * + * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items + * allowed in this array. + * + * Note: **an empty whitelist array will block all URLs**! + * + * @return {Array} the currently set whitelist array. + * + * The **default value** when no whitelist has been explicitly set is `['self']` allowing only + * same origin resource requests. + * + * @description + * Sets/Gets the whitelist of trusted resource URLs. + */ + this.resourceUrlWhitelist = function(value) { + if (arguments.length) { + resourceUrlWhitelist = adjustMatchers(value); + } + return resourceUrlWhitelist; + }; + + /** + * @ngdoc method + * @name $sceDelegateProvider#resourceUrlBlacklist + * @kind function + * + * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value + * provided. This must be an array or null. A snapshot of this array is used so further + * changes to the array are ignored. + * + * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items + * allowed in this array. + * + * The typical usage for the blacklist is to **block + * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as + * these would otherwise be trusted but actually return content from the redirected domain. + * + * Finally, **the blacklist overrides the whitelist** and has the final say. + * + * @return {Array} the currently set blacklist array. + * + * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there + * is no blacklist.) + * + * @description + * Sets/Gets the blacklist of trusted resource URLs. + */ + + this.resourceUrlBlacklist = function(value) { + if (arguments.length) { + resourceUrlBlacklist = adjustMatchers(value); + } + return resourceUrlBlacklist; + }; + + this.$get = ['$injector', function($injector) { + + var htmlSanitizer = function htmlSanitizer(html) { + throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.'); + }; + + if ($injector.has('$sanitize')) { + htmlSanitizer = $injector.get('$sanitize'); + } + + + function matchUrl(matcher, parsedUrl) { + if (matcher === 'self') { + return urlIsSameOrigin(parsedUrl); + } else { + // definitely a regex. See adjustMatchers() + return !!matcher.exec(parsedUrl.href); + } + } + + function isResourceUrlAllowedByPolicy(url) { + var parsedUrl = urlResolve(url.toString()); + var i, n, allowed = false; + // Ensure that at least one item from the whitelist allows this url. + for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) { + if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) { + allowed = true; + break; + } + } + if (allowed) { + // Ensure that no item from the blacklist blocked this url. + for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) { + if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) { + allowed = false; + break; + } + } + } + return allowed; + } + + function generateHolderType(Base) { + var holderType = function TrustedValueHolderType(trustedValue) { + this.$$unwrapTrustedValue = function() { + return trustedValue; + }; + }; + if (Base) { + holderType.prototype = new Base(); + } + holderType.prototype.valueOf = function sceValueOf() { + return this.$$unwrapTrustedValue(); + }; + holderType.prototype.toString = function sceToString() { + return this.$$unwrapTrustedValue().toString(); + }; + return holderType; + } + + var trustedValueHolderBase = generateHolderType(), + byType = {}; + + byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]); + + /** + * @ngdoc method + * @name $sceDelegate#trustAs + * + * @description + * Returns an object that is trusted by angular for use in specified strict + * contextual escaping contexts (such as ng-bind-html, ng-include, any src + * attribute interpolation, any dom event binding attribute interpolation + * such as for onclick, etc.) that uses the provided value. + * See {@link ng.$sce $sce} for enabling strict contextual escaping. + * + * @param {string} type The kind of context in which this value is safe for use. e.g. url, + * resourceUrl, html, js and css. + * @param {*} value The value that that should be considered trusted/safe. + * @returns {*} A value that can be used to stand in for the provided `value` in places + * where Angular expects a $sce.trustAs() return value. + */ + function trustAs(type, trustedValue) { + var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null); + if (!Constructor) { + throw $sceMinErr('icontext', + 'Attempted to trust a value in invalid context. Context: {0}; Value: {1}', + type, trustedValue); + } + if (trustedValue === null || trustedValue === undefined || trustedValue === '') { + return trustedValue; + } + // All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting + // mutable objects, we ensure here that the value passed in is actually a string. + if (typeof trustedValue !== 'string') { + throw $sceMinErr('itype', + 'Attempted to trust a non-string value in a content requiring a string: Context: {0}', + type); + } + return new Constructor(trustedValue); + } + + /** + * @ngdoc method + * @name $sceDelegate#valueOf + * + * @description + * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs + * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link + * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. + * + * If the passed parameter is not a value that had been returned by {@link + * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is. + * + * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} + * call or anything else. + * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs + * `$sceDelegate.trustAs`} if `value` is the result of such a call. Otherwise, returns + * `value` unchanged. + */ + function valueOf(maybeTrusted) { + if (maybeTrusted instanceof trustedValueHolderBase) { + return maybeTrusted.$$unwrapTrustedValue(); + } else { + return maybeTrusted; + } + } + + /** + * @ngdoc method + * @name $sceDelegate#getTrusted + * + * @description + * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and + * returns the originally supplied value if the queried context type is a supertype of the + * created type. If this condition isn't satisfied, throws an exception. + * + * @param {string} type The kind of context in which this value is to be used. + * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs + * `$sceDelegate.trustAs`} call. + * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs + * `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception. + */ + function getTrusted(type, maybeTrusted) { + if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') { + return maybeTrusted; + } + var constructor = (byType.hasOwnProperty(type) ? byType[type] : null); + if (constructor && maybeTrusted instanceof constructor) { + return maybeTrusted.$$unwrapTrustedValue(); + } + // If we get here, then we may only take one of two actions. + // 1. sanitize the value for the requested type, or + // 2. throw an exception. + if (type === SCE_CONTEXTS.RESOURCE_URL) { + if (isResourceUrlAllowedByPolicy(maybeTrusted)) { + return maybeTrusted; + } else { + throw $sceMinErr('insecurl', + 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}', + maybeTrusted.toString()); + } + } else if (type === SCE_CONTEXTS.HTML) { + return htmlSanitizer(maybeTrusted); + } + throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.'); + } + + return { trustAs: trustAs, + getTrusted: getTrusted, + valueOf: valueOf }; + }]; +} + + +/** + * @ngdoc provider + * @name $sceProvider + * @description + * + * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service. + * - enable/disable Strict Contextual Escaping (SCE) in a module + * - override the default implementation with a custom delegate + * + * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}. + */ + +/* jshint maxlen: false*/ + +/** + * @ngdoc service + * @name $sce + * @kind function + * + * @description + * + * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS. + * + * # Strict Contextual Escaping + * + * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain + * contexts to result in a value that is marked as safe to use for that context. One example of + * such a context is binding arbitrary html controlled by the user via `ng-bind-html`. We refer + * to these contexts as privileged or SCE contexts. + * + * As of version 1.2, Angular ships with SCE enabled by default. + * + * Note: When enabled (the default), IE<11 in quirks mode is not supported. In this mode, IE<11 allow + * one to execute arbitrary javascript by the use of the expression() syntax. Refer + * to learn more about them. + * You can ensure your document is in standards mode and not quirks mode by adding `` + * to the top of your HTML document. + * + * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for + * security vulnerabilities such as XSS, clickjacking, etc. a lot easier. + * + * Here's an example of a binding in a privileged context: + * + * ``` + * + *
      + * ``` + * + * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE + * disabled, this application allows the user to render arbitrary HTML into the DIV. + * In a more realistic example, one may be rendering user comments, blog articles, etc. via + * bindings. (HTML is just one example of a context where rendering user controlled input creates + * security vulnerabilities.) + * + * For the case of HTML, you might use a library, either on the client side, or on the server side, + * to sanitize unsafe HTML before binding to the value and rendering it in the document. + * + * How would you ensure that every place that used these types of bindings was bound to a value that + * was sanitized by your library (or returned as safe for rendering by your server?) How can you + * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some + * properties/fields and forgot to update the binding to the sanitized value? + * + * To be secure by default, you want to ensure that any such bindings are disallowed unless you can + * determine that something explicitly says it's safe to use a value for binding in that + * context. You can then audit your code (a simple grep would do) to ensure that this is only done + * for those values that you can easily tell are safe - because they were received from your server, + * sanitized by your library, etc. You can organize your codebase to help with this - perhaps + * allowing only the files in a specific directory to do this. Ensuring that the internal API + * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task. + * + * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs} + * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to + * obtain values that will be accepted by SCE / privileged contexts. + * + * + * ## How does it work? + * + * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted + * $sce.getTrusted(context, value)} rather than to the value directly. Directives use {@link + * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the + * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals. + * + * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link + * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly + * simplified): + * + * ``` + * var ngBindHtmlDirective = ['$sce', function($sce) { + * return function(scope, element, attr) { + * scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) { + * element.html(value || ''); + * }); + * }; + * }]; + * ``` + * + * ## Impact on loading templates + * + * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as + * `templateUrl`'s specified by {@link guide/directive directives}. + * + * By default, Angular only loads templates from the same domain and protocol as the application + * document. This is done by calling {@link ng.$sce#getTrustedResourceUrl + * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or + * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist + * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value. + * + * *Please note*: + * The browser's + * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest) + * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/) + * policy apply in addition to this and may further restrict whether the template is successfully + * loaded. This means that without the right CORS policy, loading templates from a different domain + * won't work on all browsers. Also, loading templates from `file://` URL does not work on some + * browsers. + * + * ## This feels like too much overhead + * + * It's important to remember that SCE only applies to interpolation expressions. + * + * If your expressions are constant literals, they're automatically trusted and you don't need to + * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g. + * `
      `) just works. + * + * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them + * through {@link ng.$sce#getTrusted $sce.getTrusted}. SCE doesn't play a role here. + * + * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load + * templates in `ng-include` from your application's domain without having to even know about SCE. + * It blocks loading templates from other domains or loading templates over http from an https + * served document. You can change these by setting your own custom {@link + * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link + * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs. + * + * This significantly reduces the overhead. It is far easier to pay the small overhead and have an + * application that's secure and can be audited to verify that with much more ease than bolting + * security onto an application later. + * + * + * ## What trusted context types are supported? + * + * | Context | Notes | + * |---------------------|----------------| + * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. | + * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. | + * | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`
      Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. | + * | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. | + * + * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist}
      + * + * Each element in these arrays must be one of the following: + * + * - **'self'** + * - The special **string**, `'self'`, can be used to match against all URLs of the **same + * domain** as the application document using the **same protocol**. + * - **String** (except the special value `'self'`) + * - The string is matched against the full *normalized / absolute URL* of the resource + * being tested (substring matches are not good enough.) + * - There are exactly **two wildcard sequences** - `*` and `**`. All other characters + * match themselves. + * - `*`: matches zero or more occurrences of any character other than one of the following 6 + * characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'. It's a useful wildcard for use + * in a whitelist. + * - `**`: matches zero or more occurrences of *any* character. As such, it's not + * not appropriate to use in for a scheme, domain, etc. as it would match too much. (e.g. + * http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might + * not have been the intention.) Its usage at the very end of the path is ok. (e.g. + * http://foo.example.com/templates/**). + * - **RegExp** (*see caveat below*) + * - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax + * (and all the inevitable escaping) makes them *harder to maintain*. It's easy to + * accidentally introduce a bug when one updates a complex expression (imho, all regexes should + * have good test coverage.). For instance, the use of `.` in the regex is correct only in a + * small number of cases. A `.` character in the regex used when matching the scheme or a + * subdomain could be matched against a `:` or literal `.` that was likely not intended. It + * is highly recommended to use the string patterns and only fall back to regular expressions + * if they as a last resort. + * - The regular expression must be an instance of RegExp (i.e. not a string.) It is + * matched against the **entire** *normalized / absolute URL* of the resource being tested + * (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags + * present on the RegExp (such as multiline, global, ignoreCase) are ignored. + * - If you are generating your JavaScript from some other templating engine (not + * recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)), + * remember to escape your regular expression (and be aware that you might need more than + * one level of escaping depending on your templating engine and the way you interpolated + * the value.) Do make use of your platform's escaping mechanism as it might be good + * enough before coding your own. e.g. Ruby has + * [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape) + * and Python has [re.escape](http://docs.python.org/library/re.html#re.escape). + * Javascript lacks a similar built in function for escaping. Take a look at Google + * Closure library's [goog.string.regExpEscape(s)]( + * http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962). + * + * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example. + * + * ## Show me an example using SCE. + * + * + * + *
      + *

      + * User comments
      + * By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when + * $sanitize is available. If $sanitize isn't available, this results in an error instead of an + * exploit. + *
      + *
      + * {{userComment.name}}: + * + *
      + *
      + *
      + *
      + *
      + * + * + * angular.module('mySceApp', ['ngSanitize']) + * .controller('AppController', ['$http', '$templateCache', '$sce', + * function($http, $templateCache, $sce) { + * var self = this; + * $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) { + * self.userComments = userComments; + * }); + * self.explicitlyTrustedHtml = $sce.trustAsHtml( + * 'Hover over this text.'); + * }]); + * + * + * + * [ + * { "name": "Alice", + * "htmlComment": + * "Is anyone reading this?" + * }, + * { "name": "Bob", + * "htmlComment": "Yes! Am I the only other one?" + * } + * ] + * + * + * + * describe('SCE doc demo', function() { + * it('should sanitize untrusted values', function() { + * expect(element.all(by.css('.htmlComment')).first().getInnerHtml()) + * .toBe('Is anyone reading this?'); + * }); + * + * it('should NOT sanitize explicitly trusted values', function() { + * expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe( + * 'Hover over this text.'); + * }); + * }); + * + *
      + * + * + * + * ## Can I disable SCE completely? + * + * Yes, you can. However, this is strongly discouraged. SCE gives you a lot of security benefits + * for little coding overhead. It will be much harder to take an SCE disabled application and + * either secure it on your own or enable SCE at a later stage. It might make sense to disable SCE + * for cases where you have a lot of existing code that was written before SCE was introduced and + * you're migrating them a module at a time. + * + * That said, here's how you can completely disable SCE: + * + * ``` + * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) { + * // Completely disable SCE. For demonstration purposes only! + * // Do not use in new projects. + * $sceProvider.enabled(false); + * }); + * ``` + * + */ +/* jshint maxlen: 100 */ + +function $SceProvider() { + var enabled = true; + + /** + * @ngdoc method + * @name $sceProvider#enabled + * @kind function + * + * @param {boolean=} value If provided, then enables/disables SCE. + * @return {boolean} true if SCE is enabled, false otherwise. + * + * @description + * Enables/disables SCE and returns the current value. + */ + this.enabled = function(value) { + if (arguments.length) { + enabled = !!value; + } + return enabled; + }; + + + /* Design notes on the default implementation for SCE. + * + * The API contract for the SCE delegate + * ------------------------------------- + * The SCE delegate object must provide the following 3 methods: + * + * - trustAs(contextEnum, value) + * This method is used to tell the SCE service that the provided value is OK to use in the + * contexts specified by contextEnum. It must return an object that will be accepted by + * getTrusted() for a compatible contextEnum and return this value. + * + * - valueOf(value) + * For values that were not produced by trustAs(), return them as is. For values that were + * produced by trustAs(), return the corresponding input value to trustAs. Basically, if + * trustAs is wrapping the given values into some type, this operation unwraps it when given + * such a value. + * + * - getTrusted(contextEnum, value) + * This function should return the a value that is safe to use in the context specified by + * contextEnum or throw and exception otherwise. + * + * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be + * opaque or wrapped in some holder object. That happens to be an implementation detail. For + * instance, an implementation could maintain a registry of all trusted objects by context. In + * such a case, trustAs() would return the same object that was passed in. getTrusted() would + * return the same object passed in if it was found in the registry under a compatible context or + * throw an exception otherwise. An implementation might only wrap values some of the time based + * on some criteria. getTrusted() might return a value and not throw an exception for special + * constants or objects even if not wrapped. All such implementations fulfill this contract. + * + * + * A note on the inheritance model for SCE contexts + * ------------------------------------------------ + * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types. This + * is purely an implementation details. + * + * The contract is simply this: + * + * getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value) + * will also succeed. + * + * Inheritance happens to capture this in a natural way. In some future, we + * may not use inheritance anymore. That is OK because no code outside of + * sce.js and sceSpecs.js would need to be aware of this detail. + */ + + this.$get = ['$parse', '$sceDelegate', function( + $parse, $sceDelegate) { + // Prereq: Ensure that we're not running in IE<11 quirks mode. In that mode, IE < 11 allow + // the "expression(javascript expression)" syntax which is insecure. + if (enabled && msie < 8) { + throw $sceMinErr('iequirks', + 'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' + + 'mode. You can fix this by adding the text to the top of your HTML ' + + 'document. See http://docs.angularjs.org/api/ng.$sce for more information.'); + } + + var sce = shallowCopy(SCE_CONTEXTS); + + /** + * @ngdoc method + * @name $sce#isEnabled + * @kind function + * + * @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you + * have to do it at module config time on {@link ng.$sceProvider $sceProvider}. + * + * @description + * Returns a boolean indicating if SCE is enabled. + */ + sce.isEnabled = function() { + return enabled; + }; + sce.trustAs = $sceDelegate.trustAs; + sce.getTrusted = $sceDelegate.getTrusted; + sce.valueOf = $sceDelegate.valueOf; + + if (!enabled) { + sce.trustAs = sce.getTrusted = function(type, value) { return value; }; + sce.valueOf = identity; + } + + /** + * @ngdoc method + * @name $sce#parseAs + * + * @description + * Converts Angular {@link guide/expression expression} into a function. This is like {@link + * ng.$parse $parse} and is identical when the expression is a literal constant. Otherwise, it + * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*, + * *result*)} + * + * @param {string} type The kind of SCE context in which this result will be used. + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + sce.parseAs = function sceParseAs(type, expr) { + var parsed = $parse(expr); + if (parsed.literal && parsed.constant) { + return parsed; + } else { + return $parse(expr, function(value) { + return sce.getTrusted(type, value); + }); + } + }; + + /** + * @ngdoc method + * @name $sce#trustAs + * + * @description + * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. As such, + * returns an object that is trusted by angular for use in specified strict contextual + * escaping contexts (such as ng-bind-html, ng-include, any src attribute + * interpolation, any dom event binding attribute interpolation such as for onclick, etc.) + * that uses the provided value. See * {@link ng.$sce $sce} for enabling strict contextual + * escaping. + * + * @param {string} type The kind of context in which this value is safe for use. e.g. url, + * resourceUrl, html, js and css. + * @param {*} value The value that that should be considered trusted/safe. + * @returns {*} A value that can be used to stand in for the provided `value` in places + * where Angular expects a $sce.trustAs() return value. + */ + + /** + * @ngdoc method + * @name $sce#trustAsHtml + * + * @description + * Shorthand method. `$sce.trustAsHtml(value)` → + * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml + * $sce.getTrustedHtml(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the + * return value of {@link ng.$sce#trustAs $sce.trustAs}.) + */ + + /** + * @ngdoc method + * @name $sce#trustAsUrl + * + * @description + * Shorthand method. `$sce.trustAsUrl(value)` → + * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl + * $sce.getTrustedUrl(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the + * return value of {@link ng.$sce#trustAs $sce.trustAs}.) + */ + + /** + * @ngdoc method + * @name $sce#trustAsResourceUrl + * + * @description + * Shorthand method. `$sce.trustAsResourceUrl(value)` → + * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl + * $sce.getTrustedResourceUrl(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the return + * value of {@link ng.$sce#trustAs $sce.trustAs}.) + */ + + /** + * @ngdoc method + * @name $sce#trustAsJs + * + * @description + * Shorthand method. `$sce.trustAsJs(value)` → + * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs + * $sce.getTrustedJs(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the + * return value of {@link ng.$sce#trustAs $sce.trustAs}.) + */ + + /** + * @ngdoc method + * @name $sce#getTrusted + * + * @description + * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}. As such, + * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the + * originally supplied value if the queried context type is a supertype of the created type. + * If this condition isn't satisfied, throws an exception. + * + * @param {string} type The kind of context in which this value is to be used. + * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`} + * call. + * @returns {*} The value the was originally provided to + * {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context. + * Otherwise, throws an exception. + */ + + /** + * @ngdoc method + * @name $sce#getTrustedHtml + * + * @description + * Shorthand method. `$sce.getTrustedHtml(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)` + */ + + /** + * @ngdoc method + * @name $sce#getTrustedCss + * + * @description + * Shorthand method. `$sce.getTrustedCss(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)` + */ + + /** + * @ngdoc method + * @name $sce#getTrustedUrl + * + * @description + * Shorthand method. `$sce.getTrustedUrl(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)` + */ + + /** + * @ngdoc method + * @name $sce#getTrustedResourceUrl + * + * @description + * Shorthand method. `$sce.getTrustedResourceUrl(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`} + * + * @param {*} value The value to pass to `$sceDelegate.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)` + */ + + /** + * @ngdoc method + * @name $sce#getTrustedJs + * + * @description + * Shorthand method. `$sce.getTrustedJs(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)` + */ + + /** + * @ngdoc method + * @name $sce#parseAsHtml + * + * @description + * Shorthand method. `$sce.parseAsHtml(expression string)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + /** + * @ngdoc method + * @name $sce#parseAsCss + * + * @description + * Shorthand method. `$sce.parseAsCss(value)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + /** + * @ngdoc method + * @name $sce#parseAsUrl + * + * @description + * Shorthand method. `$sce.parseAsUrl(value)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + /** + * @ngdoc method + * @name $sce#parseAsResourceUrl + * + * @description + * Shorthand method. `$sce.parseAsResourceUrl(value)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + /** + * @ngdoc method + * @name $sce#parseAsJs + * + * @description + * Shorthand method. `$sce.parseAsJs(value)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + // Shorthand delegations. + var parse = sce.parseAs, + getTrusted = sce.getTrusted, + trustAs = sce.trustAs; + + forEach(SCE_CONTEXTS, function(enumValue, name) { + var lName = lowercase(name); + sce[camelCase("parse_as_" + lName)] = function(expr) { + return parse(enumValue, expr); + }; + sce[camelCase("get_trusted_" + lName)] = function(value) { + return getTrusted(enumValue, value); + }; + sce[camelCase("trust_as_" + lName)] = function(value) { + return trustAs(enumValue, value); + }; + }); + + return sce; + }]; +} + +/** + * !!! This is an undocumented "private" service !!! + * + * @name $sniffer + * @requires $window + * @requires $document + * + * @property {boolean} history Does the browser support html5 history api ? + * @property {boolean} transitions Does the browser support CSS transition events ? + * @property {boolean} animations Does the browser support CSS animation events ? + * + * @description + * This is very simple implementation of testing browser's features. + */ +function $SnifferProvider() { + this.$get = ['$window', '$document', function($window, $document) { + var eventSupport = {}, + android = + toInt((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]), + boxee = /Boxee/i.test(($window.navigator || {}).userAgent), + document = $document[0] || {}, + vendorPrefix, + vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/, + bodyStyle = document.body && document.body.style, + transitions = false, + animations = false, + match; + + if (bodyStyle) { + for (var prop in bodyStyle) { + if (match = vendorRegex.exec(prop)) { + vendorPrefix = match[0]; + vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1); + break; + } + } + + if (!vendorPrefix) { + vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit'; + } + + transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle)); + animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle)); + + if (android && (!transitions || !animations)) { + transitions = isString(bodyStyle.webkitTransition); + animations = isString(bodyStyle.webkitAnimation); + } + } + + + return { + // Android has history.pushState, but it does not update location correctly + // so let's not use the history API at all. + // http://code.google.com/p/android/issues/detail?id=17471 + // https://github.com/angular/angular.js/issues/904 + + // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has + // so let's not use the history API also + // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined + // jshint -W018 + history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee), + // jshint +W018 + hasEvent: function(event) { + // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have + // it. In particular the event is not fired when backspace or delete key are pressed or + // when cut operation is performed. + // IE10+ implements 'input' event but it erroneously fires under various situations, + // e.g. when placeholder changes, or a form is focused. + if (event === 'input' && msie <= 11) return false; + + if (isUndefined(eventSupport[event])) { + var divElm = document.createElement('div'); + eventSupport[event] = 'on' + event in divElm; + } + + return eventSupport[event]; + }, + csp: csp(), + vendorPrefix: vendorPrefix, + transitions: transitions, + animations: animations, + android: android + }; + }]; +} + +var $compileMinErr = minErr('$compile'); + +/** + * @ngdoc service + * @name $templateRequest + * + * @description + * The `$templateRequest` service downloads the provided template using `$http` and, upon success, + * stores the contents inside of `$templateCache`. If the HTTP request fails or the response data + * of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted + * by setting the 2nd parameter of the function to true). + * + * @param {string} tpl The HTTP request template URL + * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty + * + * @return {Promise} a promise for the HTTP response data of the given URL. + * + * @property {number} totalPendingRequests total amount of pending template requests being downloaded. + */ +function $TemplateRequestProvider() { + this.$get = ['$templateCache', '$http', '$q', function($templateCache, $http, $q) { + function handleRequestFn(tpl, ignoreRequestError) { + handleRequestFn.totalPendingRequests++; + + var transformResponse = $http.defaults && $http.defaults.transformResponse; + + if (isArray(transformResponse)) { + transformResponse = transformResponse.filter(function(transformer) { + return transformer !== defaultHttpResponseTransform; + }); + } else if (transformResponse === defaultHttpResponseTransform) { + transformResponse = null; + } + + var httpOptions = { + cache: $templateCache, + transformResponse: transformResponse + }; + + return $http.get(tpl, httpOptions) + ['finally'](function() { + handleRequestFn.totalPendingRequests--; + }) + .then(function(response) { + $templateCache.put(tpl, response.data); + return response.data; + }, handleError); + + function handleError(resp) { + if (!ignoreRequestError) { + throw $compileMinErr('tpload', 'Failed to load template: {0} (HTTP status: {1} {2})', + tpl, resp.status, resp.statusText); + } + return $q.reject(resp); + } + } + + handleRequestFn.totalPendingRequests = 0; + + return handleRequestFn; + }]; +} + +function $$TestabilityProvider() { + this.$get = ['$rootScope', '$browser', '$location', + function($rootScope, $browser, $location) { + + /** + * @name $testability + * + * @description + * The private $$testability service provides a collection of methods for use when debugging + * or by automated test and debugging tools. + */ + var testability = {}; + + /** + * @name $$testability#findBindings + * + * @description + * Returns an array of elements that are bound (via ng-bind or {{}}) + * to expressions matching the input. + * + * @param {Element} element The element root to search from. + * @param {string} expression The binding expression to match. + * @param {boolean} opt_exactMatch If true, only returns exact matches + * for the expression. Filters and whitespace are ignored. + */ + testability.findBindings = function(element, expression, opt_exactMatch) { + var bindings = element.getElementsByClassName('ng-binding'); + var matches = []; + forEach(bindings, function(binding) { + var dataBinding = angular.element(binding).data('$binding'); + if (dataBinding) { + forEach(dataBinding, function(bindingName) { + if (opt_exactMatch) { + var matcher = new RegExp('(^|\\s)' + escapeForRegexp(expression) + '(\\s|\\||$)'); + if (matcher.test(bindingName)) { + matches.push(binding); + } + } else { + if (bindingName.indexOf(expression) != -1) { + matches.push(binding); + } + } + }); + } + }); + return matches; + }; + + /** + * @name $$testability#findModels + * + * @description + * Returns an array of elements that are two-way found via ng-model to + * expressions matching the input. + * + * @param {Element} element The element root to search from. + * @param {string} expression The model expression to match. + * @param {boolean} opt_exactMatch If true, only returns exact matches + * for the expression. + */ + testability.findModels = function(element, expression, opt_exactMatch) { + var prefixes = ['ng-', 'data-ng-', 'ng\\:']; + for (var p = 0; p < prefixes.length; ++p) { + var attributeEquals = opt_exactMatch ? '=' : '*='; + var selector = '[' + prefixes[p] + 'model' + attributeEquals + '"' + expression + '"]'; + var elements = element.querySelectorAll(selector); + if (elements.length) { + return elements; + } + } + }; + + /** + * @name $$testability#getLocation + * + * @description + * Shortcut for getting the location in a browser agnostic way. Returns + * the path, search, and hash. (e.g. /path?a=b#hash) + */ + testability.getLocation = function() { + return $location.url(); + }; + + /** + * @name $$testability#setLocation + * + * @description + * Shortcut for navigating to a location without doing a full page reload. + * + * @param {string} url The location url (path, search and hash, + * e.g. /path?a=b#hash) to go to. + */ + testability.setLocation = function(url) { + if (url !== $location.url()) { + $location.url(url); + $rootScope.$digest(); + } + }; + + /** + * @name $$testability#whenStable + * + * @description + * Calls the callback when $timeout and $http requests are completed. + * + * @param {function} callback + */ + testability.whenStable = function(callback) { + $browser.notifyWhenNoOutstandingRequests(callback); + }; + + return testability; + }]; +} + +function $TimeoutProvider() { + this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler', + function($rootScope, $browser, $q, $$q, $exceptionHandler) { + + var deferreds = {}; + + + /** + * @ngdoc service + * @name $timeout + * + * @description + * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch + * block and delegates any exceptions to + * {@link ng.$exceptionHandler $exceptionHandler} service. + * + * The return value of calling `$timeout` is a promise, which will be resolved when + * the delay has passed and the timeout function, if provided, is executed. + * + * To cancel a timeout request, call `$timeout.cancel(promise)`. + * + * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to + * synchronously flush the queue of deferred functions. + * + * If you only want a promise that will be resolved after some specified delay + * then you can call `$timeout` without the `fn` function. + * + * @param {function()=} fn A function, whose execution should be delayed. + * @param {number=} [delay=0] Delay in milliseconds. + * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise + * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. + * @param {...*=} Pass additional parameters to the executed function. + * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this + * promise will be resolved with is the return value of the `fn` function. + * + */ + function timeout(fn, delay, invokeApply) { + if (!isFunction(fn)) { + invokeApply = delay; + delay = fn; + fn = noop; + } + + var args = sliceArgs(arguments, 3), + skipApply = (isDefined(invokeApply) && !invokeApply), + deferred = (skipApply ? $$q : $q).defer(), + promise = deferred.promise, + timeoutId; + + timeoutId = $browser.defer(function() { + try { + deferred.resolve(fn.apply(null, args)); + } catch (e) { + deferred.reject(e); + $exceptionHandler(e); + } + finally { + delete deferreds[promise.$$timeoutId]; + } + + if (!skipApply) $rootScope.$apply(); + }, delay); + + promise.$$timeoutId = timeoutId; + deferreds[timeoutId] = deferred; + + return promise; + } + + + /** + * @ngdoc method + * @name $timeout#cancel + * + * @description + * Cancels a task associated with the `promise`. As a result of this, the promise will be + * resolved with a rejection. + * + * @param {Promise=} promise Promise returned by the `$timeout` function. + * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully + * canceled. + */ + timeout.cancel = function(promise) { + if (promise && promise.$$timeoutId in deferreds) { + deferreds[promise.$$timeoutId].reject('canceled'); + delete deferreds[promise.$$timeoutId]; + return $browser.defer.cancel(promise.$$timeoutId); + } + return false; + }; + + return timeout; + }]; +} + +// NOTE: The usage of window and document instead of $window and $document here is +// deliberate. This service depends on the specific behavior of anchor nodes created by the +// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and +// cause us to break tests. In addition, when the browser resolves a URL for XHR, it +// doesn't know about mocked locations and resolves URLs to the real document - which is +// exactly the behavior needed here. There is little value is mocking these out for this +// service. +var urlParsingNode = document.createElement("a"); +var originUrl = urlResolve(window.location.href); + + +/** + * + * Implementation Notes for non-IE browsers + * ---------------------------------------- + * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM, + * results both in the normalizing and parsing of the URL. Normalizing means that a relative + * URL will be resolved into an absolute URL in the context of the application document. + * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related + * properties are all populated to reflect the normalized URL. This approach has wide + * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc. See + * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html + * + * Implementation Notes for IE + * --------------------------- + * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other + * browsers. However, the parsed components will not be set if the URL assigned did not specify + * them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We + * work around that by performing the parsing in a 2nd step by taking a previously normalized + * URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the + * properties such as protocol, hostname, port, etc. + * + * IE7 does not normalize the URL when assigned to an anchor node. (Apparently, it does, if one + * uses the inner HTML approach to assign the URL as part of an HTML snippet - + * http://stackoverflow.com/a/472729) However, setting img[src] does normalize the URL. + * Unfortunately, setting img[src] to something like "javascript:foo" on IE throws an exception. + * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that + * method and IE < 8 is unsupported. + * + * References: + * http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement + * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html + * http://url.spec.whatwg.org/#urlutils + * https://github.com/angular/angular.js/pull/2902 + * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/ + * + * @kind function + * @param {string} url The URL to be parsed. + * @description Normalizes and parses a URL. + * @returns {object} Returns the normalized URL as a dictionary. + * + * | member name | Description | + * |---------------|----------------| + * | href | A normalized version of the provided URL if it was not an absolute URL | + * | protocol | The protocol including the trailing colon | + * | host | The host and port (if the port is non-default) of the normalizedUrl | + * | search | The search params, minus the question mark | + * | hash | The hash string, minus the hash symbol + * | hostname | The hostname + * | port | The port, without ":" + * | pathname | The pathname, beginning with "/" + * + */ +function urlResolve(url) { + var href = url; + + if (msie) { + // Normalize before parse. Refer Implementation Notes on why this is + // done in two steps on IE. + urlParsingNode.setAttribute("href", href); + href = urlParsingNode.href; + } + + urlParsingNode.setAttribute('href', href); + + // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils + return { + href: urlParsingNode.href, + protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '', + host: urlParsingNode.host, + search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '', + hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '', + hostname: urlParsingNode.hostname, + port: urlParsingNode.port, + pathname: (urlParsingNode.pathname.charAt(0) === '/') + ? urlParsingNode.pathname + : '/' + urlParsingNode.pathname + }; +} + +/** + * Parse a request URL and determine whether this is a same-origin request as the application document. + * + * @param {string|object} requestUrl The url of the request as a string that will be resolved + * or a parsed URL object. + * @returns {boolean} Whether the request is for the same origin as the application document. + */ +function urlIsSameOrigin(requestUrl) { + var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl; + return (parsed.protocol === originUrl.protocol && + parsed.host === originUrl.host); +} + +/** + * @ngdoc service + * @name $window + * + * @description + * A reference to the browser's `window` object. While `window` + * is globally available in JavaScript, it causes testability problems, because + * it is a global variable. In angular we always refer to it through the + * `$window` service, so it may be overridden, removed or mocked for testing. + * + * Expressions, like the one defined for the `ngClick` directive in the example + * below, are evaluated with respect to the current scope. Therefore, there is + * no risk of inadvertently coding in a dependency on a global value in such an + * expression. + * + * @example + + + +
      + + +
      +
      + + it('should display the greeting in the input box', function() { + element(by.model('greeting')).sendKeys('Hello, E2E Tests'); + // If we click the button it will block the test runner + // element(':button').click(); + }); + +
      + */ +function $WindowProvider() { + this.$get = valueFn(window); +} + +/** + * @name $$cookieReader + * @requires $document + * + * @description + * This is a private service for reading cookies used by $http and ngCookies + * + * @return {Object} a key/value map of the current cookies + */ +function $$CookieReader($document) { + var rawDocument = $document[0] || {}; + var lastCookies = {}; + var lastCookieString = ''; + + function safeDecodeURIComponent(str) { + try { + return decodeURIComponent(str); + } catch (e) { + return str; + } + } + + return function() { + var cookieArray, cookie, i, index, name; + var currentCookieString = rawDocument.cookie || ''; + + if (currentCookieString !== lastCookieString) { + lastCookieString = currentCookieString; + cookieArray = lastCookieString.split('; '); + lastCookies = {}; + + for (i = 0; i < cookieArray.length; i++) { + cookie = cookieArray[i]; + index = cookie.indexOf('='); + if (index > 0) { //ignore nameless cookies + name = safeDecodeURIComponent(cookie.substring(0, index)); + // the first value that is seen for a cookie is the most + // specific one. values for the same cookie name that + // follow are for less specific paths. + if (lastCookies[name] === undefined) { + lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1)); + } + } + } + } + return lastCookies; + }; +} + +$$CookieReader.$inject = ['$document']; + +function $$CookieReaderProvider() { + this.$get = $$CookieReader; +} + +/* global currencyFilter: true, + dateFilter: true, + filterFilter: true, + jsonFilter: true, + limitToFilter: true, + lowercaseFilter: true, + numberFilter: true, + orderByFilter: true, + uppercaseFilter: true, + */ + +/** + * @ngdoc provider + * @name $filterProvider + * @description + * + * Filters are just functions which transform input to an output. However filters need to be + * Dependency Injected. To achieve this a filter definition consists of a factory function which is + * annotated with dependencies and is responsible for creating a filter function. + * + *
      + * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`. + * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace + * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores + * (`myapp_subsection_filterx`). + *
      + * + * ```js + * // Filter registration + * function MyModule($provide, $filterProvider) { + * // create a service to demonstrate injection (not always needed) + * $provide.value('greet', function(name){ + * return 'Hello ' + name + '!'; + * }); + * + * // register a filter factory which uses the + * // greet service to demonstrate DI. + * $filterProvider.register('greet', function(greet){ + * // return the filter function which uses the greet service + * // to generate salutation + * return function(text) { + * // filters need to be forgiving so check input validity + * return text && greet(text) || text; + * }; + * }); + * } + * ``` + * + * The filter function is registered with the `$injector` under the filter name suffix with + * `Filter`. + * + * ```js + * it('should be the same instance', inject( + * function($filterProvider) { + * $filterProvider.register('reverse', function(){ + * return ...; + * }); + * }, + * function($filter, reverseFilter) { + * expect($filter('reverse')).toBe(reverseFilter); + * }); + * ``` + * + * + * For more information about how angular filters work, and how to create your own filters, see + * {@link guide/filter Filters} in the Angular Developer Guide. + */ + +/** + * @ngdoc service + * @name $filter + * @kind function + * @description + * Filters are used for formatting data displayed to the user. + * + * The general syntax in templates is as follows: + * + * {{ expression [| filter_name[:parameter_value] ... ] }} + * + * @param {String} name Name of the filter function to retrieve + * @return {Function} the filter function + * @example + + +
      +

      {{ originalText }}

      +

      {{ filteredText }}

      +
      +
      + + + angular.module('filterExample', []) + .controller('MainCtrl', function($scope, $filter) { + $scope.originalText = 'hello'; + $scope.filteredText = $filter('uppercase')($scope.originalText); + }); + +
      + */ +$FilterProvider.$inject = ['$provide']; +function $FilterProvider($provide) { + var suffix = 'Filter'; + + /** + * @ngdoc method + * @name $filterProvider#register + * @param {string|Object} name Name of the filter function, or an object map of filters where + * the keys are the filter names and the values are the filter factories. + * + *
      + * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`. + * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace + * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores + * (`myapp_subsection_filterx`). + *
      + * @returns {Object} Registered filter instance, or if a map of filters was provided then a map + * of the registered filter instances. + */ + function register(name, factory) { + if (isObject(name)) { + var filters = {}; + forEach(name, function(filter, key) { + filters[key] = register(key, filter); + }); + return filters; + } else { + return $provide.factory(name + suffix, factory); + } + } + this.register = register; + + this.$get = ['$injector', function($injector) { + return function(name) { + return $injector.get(name + suffix); + }; + }]; + + //////////////////////////////////////// + + /* global + currencyFilter: false, + dateFilter: false, + filterFilter: false, + jsonFilter: false, + limitToFilter: false, + lowercaseFilter: false, + numberFilter: false, + orderByFilter: false, + uppercaseFilter: false, + */ + + register('currency', currencyFilter); + register('date', dateFilter); + register('filter', filterFilter); + register('json', jsonFilter); + register('limitTo', limitToFilter); + register('lowercase', lowercaseFilter); + register('number', numberFilter); + register('orderBy', orderByFilter); + register('uppercase', uppercaseFilter); +} + +/** + * @ngdoc filter + * @name filter + * @kind function + * + * @description + * Selects a subset of items from `array` and returns it as a new array. + * + * @param {Array} array The source array. + * @param {string|Object|function()} expression The predicate to be used for selecting items from + * `array`. + * + * Can be one of: + * + * - `string`: The string is used for matching against the contents of the `array`. All strings or + * objects with string properties in `array` that match this string will be returned. This also + * applies to nested object properties. + * The predicate can be negated by prefixing the string with `!`. + * + * - `Object`: A pattern object can be used to filter specific properties on objects contained + * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items + * which have property `name` containing "M" and property `phone` containing "1". A special + * property name `$` can be used (as in `{$:"text"}`) to accept a match against any + * property of the object or its nested object properties. That's equivalent to the simple + * substring match with a `string` as described above. The predicate can be negated by prefixing + * the string with `!`. + * For example `{name: "!M"}` predicate will return an array of items which have property `name` + * not containing "M". + * + * Note that a named property will match properties on the same level only, while the special + * `$` property will match properties on the same level or deeper. E.g. an array item like + * `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but + * **will** be matched by `{$: 'John'}`. + * + * - `function(value, index)`: A predicate function can be used to write arbitrary filters. The + * function is called for each element of `array`. The final result is an array of those + * elements that the predicate returned true for. + * + * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in + * determining if the expected value (from the filter expression) and actual value (from + * the object in the array) should be considered a match. + * + * Can be one of: + * + * - `function(actual, expected)`: + * The function will be given the object value and the predicate value to compare and + * should return true if both values should be considered equal. + * + * - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`. + * This is essentially strict comparison of expected and actual. + * + * - `false|undefined`: A short hand for a function which will look for a substring match in case + * insensitive way. + * + * Primitive values are converted to strings. Objects are not compared against primitives, + * unless they have a custom `toString` method (e.g. `Date` objects). + * + * @example + + +
      + + + + + + + + +
      NamePhone
      {{friend.name}}{{friend.phone}}
      +
      +
      +
      +
      +
      + + + + + + +
      NamePhone
      {{friendObj.name}}{{friendObj.phone}}
      +
      + + var expectFriendNames = function(expectedNames, key) { + element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) { + arr.forEach(function(wd, i) { + expect(wd.getText()).toMatch(expectedNames[i]); + }); + }); + }; + + it('should search across all fields when filtering with a string', function() { + var searchText = element(by.model('searchText')); + searchText.clear(); + searchText.sendKeys('m'); + expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend'); + + searchText.clear(); + searchText.sendKeys('76'); + expectFriendNames(['John', 'Julie'], 'friend'); + }); + + it('should search in specific fields when filtering with a predicate object', function() { + var searchAny = element(by.model('search.$')); + searchAny.clear(); + searchAny.sendKeys('i'); + expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj'); + }); + it('should use a equal comparison when comparator is true', function() { + var searchName = element(by.model('search.name')); + var strict = element(by.model('strict')); + searchName.clear(); + searchName.sendKeys('Julie'); + strict.click(); + expectFriendNames(['Julie'], 'friendObj'); + }); + +
      + */ +function filterFilter() { + return function(array, expression, comparator) { + if (!isArrayLike(array)) { + if (array == null) { + return array; + } else { + throw minErr('filter')('notarray', 'Expected array but received: {0}', array); + } + } + + var expressionType = getTypeForFilter(expression); + var predicateFn; + var matchAgainstAnyProp; + + switch (expressionType) { + case 'function': + predicateFn = expression; + break; + case 'boolean': + case 'null': + case 'number': + case 'string': + matchAgainstAnyProp = true; + //jshint -W086 + case 'object': + //jshint +W086 + predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp); + break; + default: + return array; + } + + return Array.prototype.filter.call(array, predicateFn); + }; +} + +function hasCustomToString(obj) { + return isFunction(obj.toString) && obj.toString !== Object.prototype.toString; +} + +// Helper functions for `filterFilter` +function createPredicateFn(expression, comparator, matchAgainstAnyProp) { + var shouldMatchPrimitives = isObject(expression) && ('$' in expression); + var predicateFn; + + if (comparator === true) { + comparator = equals; + } else if (!isFunction(comparator)) { + comparator = function(actual, expected) { + if (isUndefined(actual)) { + // No substring matching against `undefined` + return false; + } + if ((actual === null) || (expected === null)) { + // No substring matching against `null`; only match against `null` + return actual === expected; + } + if (isObject(expected) || (isObject(actual) && !hasCustomToString(actual))) { + // Should not compare primitives against objects, unless they have custom `toString` method + return false; + } + + actual = lowercase('' + actual); + expected = lowercase('' + expected); + return actual.indexOf(expected) !== -1; + }; + } + + predicateFn = function(item) { + if (shouldMatchPrimitives && !isObject(item)) { + return deepCompare(item, expression.$, comparator, false); + } + return deepCompare(item, expression, comparator, matchAgainstAnyProp); + }; + + return predicateFn; +} + +function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) { + var actualType = getTypeForFilter(actual); + var expectedType = getTypeForFilter(expected); + + if ((expectedType === 'string') && (expected.charAt(0) === '!')) { + return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp); + } else if (isArray(actual)) { + // In case `actual` is an array, consider it a match + // if ANY of it's items matches `expected` + return actual.some(function(item) { + return deepCompare(item, expected, comparator, matchAgainstAnyProp); + }); + } + + switch (actualType) { + case 'object': + var key; + if (matchAgainstAnyProp) { + for (key in actual) { + if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) { + return true; + } + } + return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false); + } else if (expectedType === 'object') { + for (key in expected) { + var expectedVal = expected[key]; + if (isFunction(expectedVal) || isUndefined(expectedVal)) { + continue; + } + + var matchAnyProperty = key === '$'; + var actualVal = matchAnyProperty ? actual : actual[key]; + if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) { + return false; + } + } + return true; + } else { + return comparator(actual, expected); + } + break; + case 'function': + return false; + default: + return comparator(actual, expected); + } +} + +// Used for easily differentiating between `null` and actual `object` +function getTypeForFilter(val) { + return (val === null) ? 'null' : typeof val; +} + +/** + * @ngdoc filter + * @name currency + * @kind function + * + * @description + * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default + * symbol for current locale is used. + * + * @param {number} amount Input to filter. + * @param {string=} symbol Currency symbol or identifier to be displayed. + * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale + * @returns {string} Formatted number. + * + * + * @example + + + +
      +
      + default currency symbol ($): {{amount | currency}}
      + custom currency identifier (USD$): {{amount | currency:"USD$"}} + no fractions (0): {{amount | currency:"USD$":0}} +
      +
      + + it('should init with 1234.56', function() { + expect(element(by.id('currency-default')).getText()).toBe('$1,234.56'); + expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56'); + expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235'); + }); + it('should update', function() { + if (browser.params.browser == 'safari') { + // Safari does not understand the minus key. See + // https://github.com/angular/protractor/issues/481 + return; + } + element(by.model('amount')).clear(); + element(by.model('amount')).sendKeys('-1234'); + expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)'); + expect(element(by.id('currency-custom')).getText()).toBe('(USD$1,234.00)'); + expect(element(by.id('currency-no-fractions')).getText()).toBe('(USD$1,234)'); + }); + +
      + */ +currencyFilter.$inject = ['$locale']; +function currencyFilter($locale) { + var formats = $locale.NUMBER_FORMATS; + return function(amount, currencySymbol, fractionSize) { + if (isUndefined(currencySymbol)) { + currencySymbol = formats.CURRENCY_SYM; + } + + if (isUndefined(fractionSize)) { + fractionSize = formats.PATTERNS[1].maxFrac; + } + + // if null or undefined pass it through + return (amount == null) + ? amount + : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize). + replace(/\u00A4/g, currencySymbol); + }; +} + +/** + * @ngdoc filter + * @name number + * @kind function + * + * @description + * Formats a number as text. + * + * If the input is not a number an empty string is returned. + * + * If the input is an infinite (Infinity/-Infinity) the Infinity symbol '∞' is returned. + * + * @param {number|string} number Number to format. + * @param {(number|string)=} fractionSize Number of decimal places to round the number to. + * If this is not provided then the fraction size is computed from the current locale's number + * formatting pattern. In the case of the default locale, it will be 3. + * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit. + * + * @example + + + +
      +
      + Default formatting: {{val | number}}
      + No fractions: {{val | number:0}}
      + Negative number: {{-val | number:4}} +
      +
      + + it('should format numbers', function() { + expect(element(by.id('number-default')).getText()).toBe('1,234.568'); + expect(element(by.binding('val | number:0')).getText()).toBe('1,235'); + expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679'); + }); + + it('should update', function() { + element(by.model('val')).clear(); + element(by.model('val')).sendKeys('3374.333'); + expect(element(by.id('number-default')).getText()).toBe('3,374.333'); + expect(element(by.binding('val | number:0')).getText()).toBe('3,374'); + expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330'); + }); + +
      + */ + + +numberFilter.$inject = ['$locale']; +function numberFilter($locale) { + var formats = $locale.NUMBER_FORMATS; + return function(number, fractionSize) { + + // if null or undefined pass it through + return (number == null) + ? number + : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP, + fractionSize); + }; +} + +var DECIMAL_SEP = '.'; +function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) { + if (isObject(number)) return ''; + + var isNegative = number < 0; + number = Math.abs(number); + + var isInfinity = number === Infinity; + if (!isInfinity && !isFinite(number)) return ''; + + var numStr = number + '', + formatedText = '', + hasExponent = false, + parts = []; + + if (isInfinity) formatedText = '\u221e'; + + if (!isInfinity && numStr.indexOf('e') !== -1) { + var match = numStr.match(/([\d\.]+)e(-?)(\d+)/); + if (match && match[2] == '-' && match[3] > fractionSize + 1) { + number = 0; + } else { + formatedText = numStr; + hasExponent = true; + } + } + + if (!isInfinity && !hasExponent) { + var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length; + + // determine fractionSize if it is not specified + if (isUndefined(fractionSize)) { + fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac); + } + + // safely round numbers in JS without hitting imprecisions of floating-point arithmetics + // inspired by: + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round + number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize); + + var fraction = ('' + number).split(DECIMAL_SEP); + var whole = fraction[0]; + fraction = fraction[1] || ''; + + var i, pos = 0, + lgroup = pattern.lgSize, + group = pattern.gSize; + + if (whole.length >= (lgroup + group)) { + pos = whole.length - lgroup; + for (i = 0; i < pos; i++) { + if ((pos - i) % group === 0 && i !== 0) { + formatedText += groupSep; + } + formatedText += whole.charAt(i); + } + } + + for (i = pos; i < whole.length; i++) { + if ((whole.length - i) % lgroup === 0 && i !== 0) { + formatedText += groupSep; + } + formatedText += whole.charAt(i); + } + + // format fraction part. + while (fraction.length < fractionSize) { + fraction += '0'; + } + + if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize); + } else { + if (fractionSize > 0 && number < 1) { + formatedText = number.toFixed(fractionSize); + number = parseFloat(formatedText); + } + } + + if (number === 0) { + isNegative = false; + } + + parts.push(isNegative ? pattern.negPre : pattern.posPre, + formatedText, + isNegative ? pattern.negSuf : pattern.posSuf); + return parts.join(''); +} + +function padNumber(num, digits, trim) { + var neg = ''; + if (num < 0) { + neg = '-'; + num = -num; + } + num = '' + num; + while (num.length < digits) num = '0' + num; + if (trim) { + num = num.substr(num.length - digits); + } + return neg + num; +} + + +function dateGetter(name, size, offset, trim) { + offset = offset || 0; + return function(date) { + var value = date['get' + name](); + if (offset > 0 || value > -offset) { + value += offset; + } + if (value === 0 && offset == -12) value = 12; + return padNumber(value, size, trim); + }; +} + +function dateStrGetter(name, shortForm) { + return function(date, formats) { + var value = date['get' + name](); + var get = uppercase(shortForm ? ('SHORT' + name) : name); + + return formats[get][value]; + }; +} + +function timeZoneGetter(date, formats, offset) { + var zone = -1 * offset; + var paddedZone = (zone >= 0) ? "+" : ""; + + paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) + + padNumber(Math.abs(zone % 60), 2); + + return paddedZone; +} + +function getFirstThursdayOfYear(year) { + // 0 = index of January + var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay(); + // 4 = index of Thursday (+1 to account for 1st = 5) + // 11 = index of *next* Thursday (+1 account for 1st = 12) + return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst); +} + +function getThursdayThisWeek(datetime) { + return new Date(datetime.getFullYear(), datetime.getMonth(), + // 4 = index of Thursday + datetime.getDate() + (4 - datetime.getDay())); +} + +function weekGetter(size) { + return function(date) { + var firstThurs = getFirstThursdayOfYear(date.getFullYear()), + thisThurs = getThursdayThisWeek(date); + + var diff = +thisThurs - +firstThurs, + result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week + + return padNumber(result, size); + }; +} + +function ampmGetter(date, formats) { + return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1]; +} + +function eraGetter(date, formats) { + return date.getFullYear() <= 0 ? formats.ERAS[0] : formats.ERAS[1]; +} + +function longEraGetter(date, formats) { + return date.getFullYear() <= 0 ? formats.ERANAMES[0] : formats.ERANAMES[1]; +} + +var DATE_FORMATS = { + yyyy: dateGetter('FullYear', 4), + yy: dateGetter('FullYear', 2, 0, true), + y: dateGetter('FullYear', 1), + MMMM: dateStrGetter('Month'), + MMM: dateStrGetter('Month', true), + MM: dateGetter('Month', 2, 1), + M: dateGetter('Month', 1, 1), + dd: dateGetter('Date', 2), + d: dateGetter('Date', 1), + HH: dateGetter('Hours', 2), + H: dateGetter('Hours', 1), + hh: dateGetter('Hours', 2, -12), + h: dateGetter('Hours', 1, -12), + mm: dateGetter('Minutes', 2), + m: dateGetter('Minutes', 1), + ss: dateGetter('Seconds', 2), + s: dateGetter('Seconds', 1), + // while ISO 8601 requires fractions to be prefixed with `.` or `,` + // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions + sss: dateGetter('Milliseconds', 3), + EEEE: dateStrGetter('Day'), + EEE: dateStrGetter('Day', true), + a: ampmGetter, + Z: timeZoneGetter, + ww: weekGetter(2), + w: weekGetter(1), + G: eraGetter, + GG: eraGetter, + GGG: eraGetter, + GGGG: longEraGetter +}; + +var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/, + NUMBER_STRING = /^\-?\d+$/; + +/** + * @ngdoc filter + * @name date + * @kind function + * + * @description + * Formats `date` to a string based on the requested `format`. + * + * `format` string can be composed of the following elements: + * + * * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010) + * * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10) + * * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199) + * * `'MMMM'`: Month in year (January-December) + * * `'MMM'`: Month in year (Jan-Dec) + * * `'MM'`: Month in year, padded (01-12) + * * `'M'`: Month in year (1-12) + * * `'dd'`: Day in month, padded (01-31) + * * `'d'`: Day in month (1-31) + * * `'EEEE'`: Day in Week,(Sunday-Saturday) + * * `'EEE'`: Day in Week, (Sun-Sat) + * * `'HH'`: Hour in day, padded (00-23) + * * `'H'`: Hour in day (0-23) + * * `'hh'`: Hour in AM/PM, padded (01-12) + * * `'h'`: Hour in AM/PM, (1-12) + * * `'mm'`: Minute in hour, padded (00-59) + * * `'m'`: Minute in hour (0-59) + * * `'ss'`: Second in minute, padded (00-59) + * * `'s'`: Second in minute (0-59) + * * `'sss'`: Millisecond in second, padded (000-999) + * * `'a'`: AM/PM marker + * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200) + * * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year + * * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year + * * `'G'`, `'GG'`, `'GGG'`: The abbreviated form of the era string (e.g. 'AD') + * * `'GGGG'`: The long form of the era string (e.g. 'Anno Domini') + * + * `format` string can also be one of the following predefined + * {@link guide/i18n localizable formats}: + * + * * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale + * (e.g. Sep 3, 2010 12:05:08 PM) + * * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 PM) + * * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US locale + * (e.g. Friday, September 3, 2010) + * * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010) + * * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010) + * * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10) + * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 PM) + * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 PM) + * + * `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g. + * `"h 'in the morning'"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence + * (e.g. `"h 'o''clock'"`). + * + * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or + * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its + * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is + * specified in the string input, the time is considered to be in the local timezone. + * @param {string=} format Formatting rules (see Description). If not specified, + * `mediumDate` is used. + * @param {string=} timezone Timezone to be used for formatting. It understands UTC/GMT and the + * continental US time zone abbreviations, but for general use, use a time zone offset, for + * example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian) + * If not specified, the timezone of the browser will be used. + * @returns {string} Formatted string or the input if input is not recognized as date/millis. + * + * @example + + + {{1288323623006 | date:'medium'}}: + {{1288323623006 | date:'medium'}}
      + {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}: + {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
      + {{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}: + {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
      + {{1288323623006 | date:"MM/dd/yyyy 'at' h:mma"}}: + {{'1288323623006' | date:"MM/dd/yyyy 'at' h:mma"}}
      +
      + + it('should format date', function() { + expect(element(by.binding("1288323623006 | date:'medium'")).getText()). + toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/); + expect(element(by.binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).getText()). + toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/); + expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()). + toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/); + expect(element(by.binding("'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"")).getText()). + toMatch(/10\/2\d\/2010 at \d{1,2}:\d{2}(AM|PM)/); + }); + +
      + */ +dateFilter.$inject = ['$locale']; +function dateFilter($locale) { + + + var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/; + // 1 2 3 4 5 6 7 8 9 10 11 + function jsonStringToDate(string) { + var match; + if (match = string.match(R_ISO8601_STR)) { + var date = new Date(0), + tzHour = 0, + tzMin = 0, + dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear, + timeSetter = match[8] ? date.setUTCHours : date.setHours; + + if (match[9]) { + tzHour = toInt(match[9] + match[10]); + tzMin = toInt(match[9] + match[11]); + } + dateSetter.call(date, toInt(match[1]), toInt(match[2]) - 1, toInt(match[3])); + var h = toInt(match[4] || 0) - tzHour; + var m = toInt(match[5] || 0) - tzMin; + var s = toInt(match[6] || 0); + var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000); + timeSetter.call(date, h, m, s, ms); + return date; + } + return string; + } + + + return function(date, format, timezone) { + var text = '', + parts = [], + fn, match; + + format = format || 'mediumDate'; + format = $locale.DATETIME_FORMATS[format] || format; + if (isString(date)) { + date = NUMBER_STRING.test(date) ? toInt(date) : jsonStringToDate(date); + } + + if (isNumber(date)) { + date = new Date(date); + } + + if (!isDate(date) || !isFinite(date.getTime())) { + return date; + } + + while (format) { + match = DATE_FORMATS_SPLIT.exec(format); + if (match) { + parts = concat(parts, match, 1); + format = parts.pop(); + } else { + parts.push(format); + format = null; + } + } + + var dateTimezoneOffset = date.getTimezoneOffset(); + if (timezone) { + dateTimezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset()); + date = convertTimezoneToLocal(date, timezone, true); + } + forEach(parts, function(value) { + fn = DATE_FORMATS[value]; + text += fn ? fn(date, $locale.DATETIME_FORMATS, dateTimezoneOffset) + : value.replace(/(^'|'$)/g, '').replace(/''/g, "'"); + }); + + return text; + }; +} + + +/** + * @ngdoc filter + * @name json + * @kind function + * + * @description + * Allows you to convert a JavaScript object into JSON string. + * + * This filter is mostly useful for debugging. When using the double curly {{value}} notation + * the binding is automatically converted to JSON. + * + * @param {*} object Any JavaScript object (including arrays and primitive types) to filter. + * @param {number=} spacing The number of spaces to use per indentation, defaults to 2. + * @returns {string} JSON string. + * + * + * @example + + +
      {{ {'name':'value'} | json }}
      +
      {{ {'name':'value'} | json:4 }}
      +
      + + it('should jsonify filtered objects', function() { + expect(element(by.id('default-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/); + expect(element(by.id('custom-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/); + }); + +
      + * + */ +function jsonFilter() { + return function(object, spacing) { + if (isUndefined(spacing)) { + spacing = 2; + } + return toJson(object, spacing); + }; +} + + +/** + * @ngdoc filter + * @name lowercase + * @kind function + * @description + * Converts string to lowercase. + * @see angular.lowercase + */ +var lowercaseFilter = valueFn(lowercase); + + +/** + * @ngdoc filter + * @name uppercase + * @kind function + * @description + * Converts string to uppercase. + * @see angular.uppercase + */ +var uppercaseFilter = valueFn(uppercase); + +/** + * @ngdoc filter + * @name limitTo + * @kind function + * + * @description + * Creates a new array or string containing only a specified number of elements. The elements + * are taken from either the beginning or the end of the source array, string or number, as specified by + * the value and sign (positive or negative) of `limit`. If a number is used as input, it is + * converted to a string. + * + * @param {Array|string|number} input Source array, string or number to be limited. + * @param {string|number} limit The length of the returned array or string. If the `limit` number + * is positive, `limit` number of items from the beginning of the source array/string are copied. + * If the number is negative, `limit` number of items from the end of the source array/string + * are copied. The `limit` will be trimmed if it exceeds `array.length`. If `limit` is undefined, + * the input will be returned unchanged. + * @param {(string|number)=} begin Index at which to begin limitation. As a negative index, `begin` + * indicates an offset from the end of `input`. Defaults to `0`. + * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array + * had less than `limit` elements. + * + * @example + + + +
      + +

      Output numbers: {{ numbers | limitTo:numLimit }}

      + +

      Output letters: {{ letters | limitTo:letterLimit }}

      + +

      Output long number: {{ longNumber | limitTo:longNumberLimit }}

      +
      +
      + + var numLimitInput = element(by.model('numLimit')); + var letterLimitInput = element(by.model('letterLimit')); + var longNumberLimitInput = element(by.model('longNumberLimit')); + var limitedNumbers = element(by.binding('numbers | limitTo:numLimit')); + var limitedLetters = element(by.binding('letters | limitTo:letterLimit')); + var limitedLongNumber = element(by.binding('longNumber | limitTo:longNumberLimit')); + + it('should limit the number array to first three items', function() { + expect(numLimitInput.getAttribute('value')).toBe('3'); + expect(letterLimitInput.getAttribute('value')).toBe('3'); + expect(longNumberLimitInput.getAttribute('value')).toBe('3'); + expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]'); + expect(limitedLetters.getText()).toEqual('Output letters: abc'); + expect(limitedLongNumber.getText()).toEqual('Output long number: 234'); + }); + + // There is a bug in safari and protractor that doesn't like the minus key + // it('should update the output when -3 is entered', function() { + // numLimitInput.clear(); + // numLimitInput.sendKeys('-3'); + // letterLimitInput.clear(); + // letterLimitInput.sendKeys('-3'); + // longNumberLimitInput.clear(); + // longNumberLimitInput.sendKeys('-3'); + // expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]'); + // expect(limitedLetters.getText()).toEqual('Output letters: ghi'); + // expect(limitedLongNumber.getText()).toEqual('Output long number: 342'); + // }); + + it('should not exceed the maximum size of input array', function() { + numLimitInput.clear(); + numLimitInput.sendKeys('100'); + letterLimitInput.clear(); + letterLimitInput.sendKeys('100'); + longNumberLimitInput.clear(); + longNumberLimitInput.sendKeys('100'); + expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]'); + expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi'); + expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342'); + }); + +
      +*/ +function limitToFilter() { + return function(input, limit, begin) { + if (Math.abs(Number(limit)) === Infinity) { + limit = Number(limit); + } else { + limit = toInt(limit); + } + if (isNaN(limit)) return input; + + if (isNumber(input)) input = input.toString(); + if (!isArray(input) && !isString(input)) return input; + + begin = (!begin || isNaN(begin)) ? 0 : toInt(begin); + begin = (begin < 0 && begin >= -input.length) ? input.length + begin : begin; + + if (limit >= 0) { + return input.slice(begin, begin + limit); + } else { + if (begin === 0) { + return input.slice(limit, input.length); + } else { + return input.slice(Math.max(0, begin + limit), begin); + } + } + }; +} + +/** + * @ngdoc filter + * @name orderBy + * @kind function + * + * @description + * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically + * for strings and numerically for numbers. Note: if you notice numbers are not being sorted + * correctly, make sure they are actually being saved as numbers and not strings. + * + * @param {Array} array The array to sort. + * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be + * used by the comparator to determine the order of elements. + * + * Can be one of: + * + * - `function`: Getter function. The result of this function will be sorted using the + * `<`, `===`, `>` operator. + * - `string`: An Angular expression. The result of this expression is used to compare elements + * (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by + * 3 first characters of a property called `name`). The result of a constant expression + * is interpreted as a property name to be used in comparisons (for example `"special name"` + * to sort object by the value of their `special name` property). An expression can be + * optionally prefixed with `+` or `-` to control ascending or descending sort order + * (for example, `+name` or `-name`). If no property is provided, (e.g. `'+'`) then the array + * element itself is used to compare where sorting. + * - `Array`: An array of function or string predicates. The first predicate in the array + * is used for sorting, but when two items are equivalent, the next predicate is used. + * + * If the predicate is missing or empty then it defaults to `'+'`. + * + * @param {boolean=} reverse Reverse the order of the array. + * @returns {Array} Sorted copy of the source array. + * + * + * @example + * The example below demonstrates a simple ngRepeat, where the data is sorted + * by age in descending order (predicate is set to `'-age'`). + * `reverse` is not set, which means it defaults to `false`. + + + +
      + + + + + + + + + + + +
      NamePhone NumberAge
      {{friend.name}}{{friend.phone}}{{friend.age}}
      +
      +
      +
      + * + * The predicate and reverse parameters can be controlled dynamically through scope properties, + * as shown in the next example. + * @example + + + +
      +
      Sorting predicate = {{predicate}}; reverse = {{reverse}}
      +
      + [ unsorted ] + + + + + + + + + + + +
      Name + (^)Phone NumberAge
      {{friend.name}}{{friend.phone}}{{friend.age}}
      +
      +
      +
      + * + * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the + * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the + * desired parameters. + * + * Example: + * + * @example + + +
      + + + + + + + + + + + +
      Name + (^)Phone NumberAge
      {{friend.name}}{{friend.phone}}{{friend.age}}
      +
      +
      + + + angular.module('orderByExample', []) + .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) { + var orderBy = $filter('orderBy'); + $scope.friends = [ + { name: 'John', phone: '555-1212', age: 10 }, + { name: 'Mary', phone: '555-9876', age: 19 }, + { name: 'Mike', phone: '555-4321', age: 21 }, + { name: 'Adam', phone: '555-5678', age: 35 }, + { name: 'Julie', phone: '555-8765', age: 29 } + ]; + $scope.order = function(predicate, reverse) { + $scope.friends = orderBy($scope.friends, predicate, reverse); + }; + $scope.order('-age',false); + }]); + +
      + */ +orderByFilter.$inject = ['$parse']; +function orderByFilter($parse) { + return function(array, sortPredicate, reverseOrder) { + if (!(isArrayLike(array))) return array; + sortPredicate = isArray(sortPredicate) ? sortPredicate : [sortPredicate]; + if (sortPredicate.length === 0) { sortPredicate = ['+']; } + sortPredicate = sortPredicate.map(function(predicate) { + var descending = false, get = predicate || identity; + if (isString(predicate)) { + if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) { + descending = predicate.charAt(0) == '-'; + predicate = predicate.substring(1); + } + if (predicate === '') { + // Effectively no predicate was passed so we compare identity + return reverseComparator(compare, descending); + } + get = $parse(predicate); + if (get.constant) { + var key = get(); + return reverseComparator(function(a, b) { + return compare(a[key], b[key]); + }, descending); + } + } + return reverseComparator(function(a, b) { + return compare(get(a),get(b)); + }, descending); + }); + return slice.call(array).sort(reverseComparator(comparator, reverseOrder)); + + function comparator(o1, o2) { + for (var i = 0; i < sortPredicate.length; i++) { + var comp = sortPredicate[i](o1, o2); + if (comp !== 0) return comp; + } + return 0; + } + function reverseComparator(comp, descending) { + return descending + ? function(a, b) {return comp(b,a);} + : comp; + } + + function isPrimitive(value) { + switch (typeof value) { + case 'number': /* falls through */ + case 'boolean': /* falls through */ + case 'string': + return true; + default: + return false; + } + } + + function objectToString(value) { + if (value === null) return 'null'; + if (typeof value.valueOf === 'function') { + value = value.valueOf(); + if (isPrimitive(value)) return value; + } + if (typeof value.toString === 'function') { + value = value.toString(); + if (isPrimitive(value)) return value; + } + return ''; + } + + function compare(v1, v2) { + var t1 = typeof v1; + var t2 = typeof v2; + if (t1 === t2 && t1 === "object") { + v1 = objectToString(v1); + v2 = objectToString(v2); + } + if (t1 === t2) { + if (t1 === "string") { + v1 = v1.toLowerCase(); + v2 = v2.toLowerCase(); + } + if (v1 === v2) return 0; + return v1 < v2 ? -1 : 1; + } else { + return t1 < t2 ? -1 : 1; + } + } + }; +} + +function ngDirective(directive) { + if (isFunction(directive)) { + directive = { + link: directive + }; + } + directive.restrict = directive.restrict || 'AC'; + return valueFn(directive); +} + +/** + * @ngdoc directive + * @name a + * @restrict E + * + * @description + * Modifies the default behavior of the html A tag so that the default action is prevented when + * the href attribute is empty. + * + * This change permits the easy creation of action links with the `ngClick` directive + * without changing the location or causing page reloads, e.g.: + * `Add Item` + */ +var htmlAnchorDirective = valueFn({ + restrict: 'E', + compile: function(element, attr) { + if (!attr.href && !attr.xlinkHref) { + return function(scope, element) { + // If the linked element is not an anchor tag anymore, do nothing + if (element[0].nodeName.toLowerCase() !== 'a') return; + + // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute. + var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ? + 'xlink:href' : 'href'; + element.on('click', function(event) { + // if we have no href url, then don't navigate anywhere. + if (!element.attr(href)) { + event.preventDefault(); + } + }); + }; + } + } +}); + +/** + * @ngdoc directive + * @name ngHref + * @restrict A + * @priority 99 + * + * @description + * Using Angular markup like `{{hash}}` in an href attribute will + * make the link go to the wrong URL if the user clicks it before + * Angular has a chance to replace the `{{hash}}` markup with its + * value. Until Angular replaces the markup the link will be broken + * and will most likely return a 404 error. The `ngHref` directive + * solves this problem. + * + * The wrong way to write it: + * ```html + * link1 + * ``` + * + * The correct way to write it: + * ```html + * link1 + * ``` + * + * @element A + * @param {template} ngHref any string which can contain `{{}}` markup. + * + * @example + * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes + * in links and their different behaviors: + + +
      + link 1 (link, don't reload)
      + link 2 (link, don't reload)
      + link 3 (link, reload!)
      + anchor (link, don't reload)
      + anchor (no link)
      + link (link, change location) +
      + + it('should execute ng-click but not reload when href without value', function() { + element(by.id('link-1')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('1'); + expect(element(by.id('link-1')).getAttribute('href')).toBe(''); + }); + + it('should execute ng-click but not reload when href empty string', function() { + element(by.id('link-2')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('2'); + expect(element(by.id('link-2')).getAttribute('href')).toBe(''); + }); + + it('should execute ng-click and change url when ng-href specified', function() { + expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\/123$/); + + element(by.id('link-3')).click(); + + // At this point, we navigate away from an Angular page, so we need + // to use browser.driver to get the base webdriver. + + browser.wait(function() { + return browser.driver.getCurrentUrl().then(function(url) { + return url.match(/\/123$/); + }); + }, 5000, 'page should navigate to /123'); + }); + + it('should execute ng-click but not reload when href empty string and name specified', function() { + element(by.id('link-4')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('4'); + expect(element(by.id('link-4')).getAttribute('href')).toBe(''); + }); + + it('should execute ng-click but not reload when no href but name specified', function() { + element(by.id('link-5')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('5'); + expect(element(by.id('link-5')).getAttribute('href')).toBe(null); + }); + + it('should only change url when only ng-href', function() { + element(by.model('value')).clear(); + element(by.model('value')).sendKeys('6'); + expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\/6$/); + + element(by.id('link-6')).click(); + + // At this point, we navigate away from an Angular page, so we need + // to use browser.driver to get the base webdriver. + browser.wait(function() { + return browser.driver.getCurrentUrl().then(function(url) { + return url.match(/\/6$/); + }); + }, 5000, 'page should navigate to /6'); + }); + +
      + */ + +/** + * @ngdoc directive + * @name ngSrc + * @restrict A + * @priority 99 + * + * @description + * Using Angular markup like `{{hash}}` in a `src` attribute doesn't + * work right: The browser will fetch from the URL with the literal + * text `{{hash}}` until Angular replaces the expression inside + * `{{hash}}`. The `ngSrc` directive solves this problem. + * + * The buggy way to write it: + * ```html + * Description + * ``` + * + * The correct way to write it: + * ```html + * Description + * ``` + * + * @element IMG + * @param {template} ngSrc any string which can contain `{{}}` markup. + */ + +/** + * @ngdoc directive + * @name ngSrcset + * @restrict A + * @priority 99 + * + * @description + * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't + * work right: The browser will fetch from the URL with the literal + * text `{{hash}}` until Angular replaces the expression inside + * `{{hash}}`. The `ngSrcset` directive solves this problem. + * + * The buggy way to write it: + * ```html + * Description + * ``` + * + * The correct way to write it: + * ```html + * Description + * ``` + * + * @element IMG + * @param {template} ngSrcset any string which can contain `{{}}` markup. + */ + +/** + * @ngdoc directive + * @name ngDisabled + * @restrict A + * @priority 100 + * + * @description + * + * This directive sets the `disabled` attribute on the element if the + * {@link guide/expression expression} inside `ngDisabled` evaluates to truthy. + * + * A special directive is necessary because we cannot use interpolation inside the `disabled` + * attribute. The following example would make the button enabled on Chrome/Firefox + * but not on older IEs: + * + * ```html + * + *
      + * + *
      + * ``` + * + * This is because the HTML specification does not require browsers to preserve the values of + * boolean attributes such as `disabled` (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * + * @example + + +
      + +
      + + it('should toggle button', function() { + expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy(); + element(by.model('checked')).click(); + expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy(); + }); + +
      + * + * @element INPUT + * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy, + * then the `disabled` attribute will be set on the element + */ + + +/** + * @ngdoc directive + * @name ngChecked + * @restrict A + * @priority 100 + * + * @description + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as checked. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngChecked` directive solves this problem for the `checked` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. + * @example + + +
      + +
      + + it('should check both checkBoxes', function() { + expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy(); + element(by.model('master')).click(); + expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy(); + }); + +
      + * + * @element INPUT + * @param {expression} ngChecked If the {@link guide/expression expression} is truthy, + * then special attribute "checked" will be set on the element + */ + + +/** + * @ngdoc directive + * @name ngReadonly + * @restrict A + * @priority 100 + * + * @description + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as readonly. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngReadonly` directive solves this problem for the `readonly` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. + * @example + + +
      + +
      + + it('should toggle readonly attr', function() { + expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeFalsy(); + element(by.model('checked')).click(); + expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeTruthy(); + }); + +
      + * + * @element INPUT + * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy, + * then special attribute "readonly" will be set on the element + */ + + +/** + * @ngdoc directive + * @name ngSelected + * @restrict A + * @priority 100 + * + * @description + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as selected. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngSelected` directive solves this problem for the `selected` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. + * + * @example + + +
      + +
      + + it('should select Greetings!', function() { + expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy(); + element(by.model('selected')).click(); + expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy(); + }); + +
      + * + * @element OPTION + * @param {expression} ngSelected If the {@link guide/expression expression} is truthy, + * then special attribute "selected" will be set on the element + */ + +/** + * @ngdoc directive + * @name ngOpen + * @restrict A + * @priority 100 + * + * @description + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as open. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngOpen` directive solves this problem for the `open` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. + * @example + + +
      +
      + Show/Hide me +
      +
      + + it('should toggle open', function() { + expect(element(by.id('details')).getAttribute('open')).toBeFalsy(); + element(by.model('open')).click(); + expect(element(by.id('details')).getAttribute('open')).toBeTruthy(); + }); + +
      + * + * @element DETAILS + * @param {expression} ngOpen If the {@link guide/expression expression} is truthy, + * then special attribute "open" will be set on the element + */ + +var ngAttributeAliasDirectives = {}; + +// boolean attrs are evaluated +forEach(BOOLEAN_ATTR, function(propName, attrName) { + // binding to multiple is not supported + if (propName == "multiple") return; + + function defaultLinkFn(scope, element, attr) { + scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) { + attr.$set(attrName, !!value); + }); + } + + var normalized = directiveNormalize('ng-' + attrName); + var linkFn = defaultLinkFn; + + if (propName === 'checked') { + linkFn = function(scope, element, attr) { + // ensuring ngChecked doesn't interfere with ngModel when both are set on the same input + if (attr.ngModel !== attr[normalized]) { + defaultLinkFn(scope, element, attr); + } + }; + } + + ngAttributeAliasDirectives[normalized] = function() { + return { + restrict: 'A', + priority: 100, + link: linkFn + }; + }; +}); + +// aliased input attrs are evaluated +forEach(ALIASED_ATTR, function(htmlAttr, ngAttr) { + ngAttributeAliasDirectives[ngAttr] = function() { + return { + priority: 100, + link: function(scope, element, attr) { + //special case ngPattern when a literal regular expression value + //is used as the expression (this way we don't have to watch anything). + if (ngAttr === "ngPattern" && attr.ngPattern.charAt(0) == "/") { + var match = attr.ngPattern.match(REGEX_STRING_REGEXP); + if (match) { + attr.$set("ngPattern", new RegExp(match[1], match[2])); + return; + } + } + + scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) { + attr.$set(ngAttr, value); + }); + } + }; + }; +}); + +// ng-src, ng-srcset, ng-href are interpolated +forEach(['src', 'srcset', 'href'], function(attrName) { + var normalized = directiveNormalize('ng-' + attrName); + ngAttributeAliasDirectives[normalized] = function() { + return { + priority: 99, // it needs to run after the attributes are interpolated + link: function(scope, element, attr) { + var propName = attrName, + name = attrName; + + if (attrName === 'href' && + toString.call(element.prop('href')) === '[object SVGAnimatedString]') { + name = 'xlinkHref'; + attr.$attr[name] = 'xlink:href'; + propName = null; + } + + attr.$observe(normalized, function(value) { + if (!value) { + if (attrName === 'href') { + attr.$set(name, null); + } + return; + } + + attr.$set(name, value); + + // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist + // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need + // to set the property as well to achieve the desired effect. + // we use attr[attrName] value since $set can sanitize the url. + if (msie && propName) element.prop(propName, attr[name]); + }); + } + }; + }; +}); + +/* global -nullFormCtrl, -SUBMITTED_CLASS, addSetValidityMethod: true + */ +var nullFormCtrl = { + $addControl: noop, + $$renameControl: nullFormRenameControl, + $removeControl: noop, + $setValidity: noop, + $setDirty: noop, + $setPristine: noop, + $setSubmitted: noop +}, +SUBMITTED_CLASS = 'ng-submitted'; + +function nullFormRenameControl(control, name) { + control.$name = name; +} + +/** + * @ngdoc type + * @name form.FormController + * + * @property {boolean} $pristine True if user has not interacted with the form yet. + * @property {boolean} $dirty True if user has already interacted with the form. + * @property {boolean} $valid True if all of the containing forms and controls are valid. + * @property {boolean} $invalid True if at least one containing control or form is invalid. + * @property {boolean} $submitted True if user has submitted the form even if its invalid. + * + * @property {Object} $error Is an object hash, containing references to controls or + * forms with failing validators, where: + * + * - keys are validation tokens (error names), + * - values are arrays of controls or forms that have a failing validator for given error name. + * + * Built-in validation tokens: + * + * - `email` + * - `max` + * - `maxlength` + * - `min` + * - `minlength` + * - `number` + * - `pattern` + * - `required` + * - `url` + * - `date` + * - `datetimelocal` + * - `time` + * - `week` + * - `month` + * + * @description + * `FormController` keeps track of all its controls and nested forms as well as the state of them, + * such as being valid/invalid or dirty/pristine. + * + * Each {@link ng.directive:form form} directive creates an instance + * of `FormController`. + * + */ +//asks for $scope to fool the BC controller module +FormController.$inject = ['$element', '$attrs', '$scope', '$animate', '$interpolate']; +function FormController(element, attrs, $scope, $animate, $interpolate) { + var form = this, + controls = []; + + var parentForm = form.$$parentForm = element.parent().controller('form') || nullFormCtrl; + + // init state + form.$error = {}; + form.$$success = {}; + form.$pending = undefined; + form.$name = $interpolate(attrs.name || attrs.ngForm || '')($scope); + form.$dirty = false; + form.$pristine = true; + form.$valid = true; + form.$invalid = false; + form.$submitted = false; + + parentForm.$addControl(form); + + /** + * @ngdoc method + * @name form.FormController#$rollbackViewValue + * + * @description + * Rollback all form controls pending updates to the `$modelValue`. + * + * Updates may be pending by a debounced event or because the input is waiting for a some future + * event defined in `ng-model-options`. This method is typically needed by the reset button of + * a form that uses `ng-model-options` to pend updates. + */ + form.$rollbackViewValue = function() { + forEach(controls, function(control) { + control.$rollbackViewValue(); + }); + }; + + /** + * @ngdoc method + * @name form.FormController#$commitViewValue + * + * @description + * Commit all form controls pending updates to the `$modelValue`. + * + * Updates may be pending by a debounced event or because the input is waiting for a some future + * event defined in `ng-model-options`. This method is rarely needed as `NgModelController` + * usually handles calling this in response to input events. + */ + form.$commitViewValue = function() { + forEach(controls, function(control) { + control.$commitViewValue(); + }); + }; + + /** + * @ngdoc method + * @name form.FormController#$addControl + * + * @description + * Register a control with the form. + * + * Input elements using ngModelController do this automatically when they are linked. + */ + form.$addControl = function(control) { + // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored + // and not added to the scope. Now we throw an error. + assertNotHasOwnProperty(control.$name, 'input'); + controls.push(control); + + if (control.$name) { + form[control.$name] = control; + } + }; + + // Private API: rename a form control + form.$$renameControl = function(control, newName) { + var oldName = control.$name; + + if (form[oldName] === control) { + delete form[oldName]; + } + form[newName] = control; + control.$name = newName; + }; + + /** + * @ngdoc method + * @name form.FormController#$removeControl + * + * @description + * Deregister a control from the form. + * + * Input elements using ngModelController do this automatically when they are destroyed. + */ + form.$removeControl = function(control) { + if (control.$name && form[control.$name] === control) { + delete form[control.$name]; + } + forEach(form.$pending, function(value, name) { + form.$setValidity(name, null, control); + }); + forEach(form.$error, function(value, name) { + form.$setValidity(name, null, control); + }); + forEach(form.$$success, function(value, name) { + form.$setValidity(name, null, control); + }); + + arrayRemove(controls, control); + }; + + + /** + * @ngdoc method + * @name form.FormController#$setValidity + * + * @description + * Sets the validity of a form control. + * + * This method will also propagate to parent forms. + */ + addSetValidityMethod({ + ctrl: this, + $element: element, + set: function(object, property, controller) { + var list = object[property]; + if (!list) { + object[property] = [controller]; + } else { + var index = list.indexOf(controller); + if (index === -1) { + list.push(controller); + } + } + }, + unset: function(object, property, controller) { + var list = object[property]; + if (!list) { + return; + } + arrayRemove(list, controller); + if (list.length === 0) { + delete object[property]; + } + }, + parentForm: parentForm, + $animate: $animate + }); + + /** + * @ngdoc method + * @name form.FormController#$setDirty + * + * @description + * Sets the form to a dirty state. + * + * This method can be called to add the 'ng-dirty' class and set the form to a dirty + * state (ng-dirty class). This method will also propagate to parent forms. + */ + form.$setDirty = function() { + $animate.removeClass(element, PRISTINE_CLASS); + $animate.addClass(element, DIRTY_CLASS); + form.$dirty = true; + form.$pristine = false; + parentForm.$setDirty(); + }; + + /** + * @ngdoc method + * @name form.FormController#$setPristine + * + * @description + * Sets the form to its pristine state. + * + * This method can be called to remove the 'ng-dirty' class and set the form to its pristine + * state (ng-pristine class). This method will also propagate to all the controls contained + * in this form. + * + * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after + * saving or resetting it. + */ + form.$setPristine = function() { + $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS); + form.$dirty = false; + form.$pristine = true; + form.$submitted = false; + forEach(controls, function(control) { + control.$setPristine(); + }); + }; + + /** + * @ngdoc method + * @name form.FormController#$setUntouched + * + * @description + * Sets the form to its untouched state. + * + * This method can be called to remove the 'ng-touched' class and set the form controls to their + * untouched state (ng-untouched class). + * + * Setting a form controls back to their untouched state is often useful when setting the form + * back to its pristine state. + */ + form.$setUntouched = function() { + forEach(controls, function(control) { + control.$setUntouched(); + }); + }; + + /** + * @ngdoc method + * @name form.FormController#$setSubmitted + * + * @description + * Sets the form to its submitted state. + */ + form.$setSubmitted = function() { + $animate.addClass(element, SUBMITTED_CLASS); + form.$submitted = true; + parentForm.$setSubmitted(); + }; +} + +/** + * @ngdoc directive + * @name ngForm + * @restrict EAC + * + * @description + * Nestable alias of {@link ng.directive:form `form`} directive. HTML + * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a + * sub-group of controls needs to be determined. + * + * Note: the purpose of `ngForm` is to group controls, + * but not to be a replacement for the `
      ` tag with all of its capabilities + * (e.g. posting to the server, ...). + * + * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into + * related scope, under this name. + * + */ + + /** + * @ngdoc directive + * @name form + * @restrict E + * + * @description + * Directive that instantiates + * {@link form.FormController FormController}. + * + * If the `name` attribute is specified, the form controller is published onto the current scope under + * this name. + * + * # Alias: {@link ng.directive:ngForm `ngForm`} + * + * In Angular, forms can be nested. This means that the outer form is valid when all of the child + * forms are valid as well. However, browsers do not allow nesting of `` elements, so + * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to + * `` but can be nested. This allows you to have nested forms, which is very useful when + * using Angular validation directives in forms that are dynamically generated using the + * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name` + * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an + * `ngForm` directive and nest these in an outer `form` element. + * + * + * # CSS classes + * - `ng-valid` is set if the form is valid. + * - `ng-invalid` is set if the form is invalid. + * - `ng-pristine` is set if the form is pristine. + * - `ng-dirty` is set if the form is dirty. + * - `ng-submitted` is set if the form was submitted. + * + * Keep in mind that ngAnimate can detect each of these classes when added and removed. + * + * + * # Submitting a form and preventing the default action + * + * Since the role of forms in client-side Angular applications is different than in classical + * roundtrip apps, it is desirable for the browser not to translate the form submission into a full + * page reload that sends the data to the server. Instead some javascript logic should be triggered + * to handle the form submission in an application-specific way. + * + * For this reason, Angular prevents the default action (form submission to the server) unless the + * `` element has an `action` attribute specified. + * + * You can use one of the following two ways to specify what javascript method should be called when + * a form is submitted: + * + * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element + * - {@link ng.directive:ngClick ngClick} directive on the first + * button or input field of type submit (input[type=submit]) + * + * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit} + * or {@link ng.directive:ngClick ngClick} directives. + * This is because of the following form submission rules in the HTML specification: + * + * - If a form has only one input field then hitting enter in this field triggers form submit + * (`ngSubmit`) + * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter + * doesn't trigger submit + * - if a form has one or more input fields and one or more buttons or input[type=submit] then + * hitting enter in any of the input fields will trigger the click handler on the *first* button or + * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`) + * + * Any pending `ngModelOptions` changes will take place immediately when an enclosing form is + * submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit` + * to have access to the updated model. + * + * ## Animation Hooks + * + * Animations in ngForm are triggered when any of the associated CSS classes are added and removed. + * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any + * other validations that are performed within the form. Animations in ngForm are similar to how + * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well + * as JS animations. + * + * The following example shows a simple way to utilize CSS transitions to style a form element + * that has been rendered as invalid after it has been validated: + * + *
      + * //be sure to include ngAnimate as a module to hook into more
      + * //advanced animations
      + * .my-form {
      + *   transition:0.5s linear all;
      + *   background: white;
      + * }
      + * .my-form.ng-invalid {
      + *   background: red;
      + *   color:white;
      + * }
      + * 
      + * + * @example + + + + + + userType: + Required!
      + userType = {{userType}}
      + myForm.input.$valid = {{myForm.input.$valid}}
      + myForm.input.$error = {{myForm.input.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      + +
      + + it('should initialize to model', function() { + var userType = element(by.binding('userType')); + var valid = element(by.binding('myForm.input.$valid')); + + expect(userType.getText()).toContain('guest'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + var userType = element(by.binding('userType')); + var valid = element(by.binding('myForm.input.$valid')); + var userInput = element(by.model('userType')); + + userInput.clear(); + userInput.sendKeys(''); + + expect(userType.getText()).toEqual('userType ='); + expect(valid.getText()).toContain('false'); + }); + +
      + * + * @param {string=} name Name of the form. If specified, the form controller will be published into + * related scope, under this name. + */ +var formDirectiveFactory = function(isNgForm) { + return ['$timeout', function($timeout) { + var formDirective = { + name: 'form', + restrict: isNgForm ? 'EAC' : 'E', + controller: FormController, + compile: function ngFormCompile(formElement, attr) { + // Setup initial state of the control + formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS); + + var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false); + + return { + pre: function ngFormPreLink(scope, formElement, attr, controller) { + // if `action` attr is not present on the form, prevent the default action (submission) + if (!('action' in attr)) { + // we can't use jq events because if a form is destroyed during submission the default + // action is not prevented. see #1238 + // + // IE 9 is not affected because it doesn't fire a submit event and try to do a full + // page reload if the form was destroyed by submission of the form via a click handler + // on a button in the form. Looks like an IE9 specific bug. + var handleFormSubmission = function(event) { + scope.$apply(function() { + controller.$commitViewValue(); + controller.$setSubmitted(); + }); + + event.preventDefault(); + }; + + addEventListenerFn(formElement[0], 'submit', handleFormSubmission); + + // unregister the preventDefault listener so that we don't not leak memory but in a + // way that will achieve the prevention of the default action. + formElement.on('$destroy', function() { + $timeout(function() { + removeEventListenerFn(formElement[0], 'submit', handleFormSubmission); + }, 0, false); + }); + } + + var parentFormCtrl = controller.$$parentForm; + + if (nameAttr) { + setter(scope, controller.$name, controller, controller.$name); + attr.$observe(nameAttr, function(newValue) { + if (controller.$name === newValue) return; + setter(scope, controller.$name, undefined, controller.$name); + parentFormCtrl.$$renameControl(controller, newValue); + setter(scope, controller.$name, controller, controller.$name); + }); + } + formElement.on('$destroy', function() { + parentFormCtrl.$removeControl(controller); + if (nameAttr) { + setter(scope, attr[nameAttr], undefined, controller.$name); + } + extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards + }); + } + }; + } + }; + + return formDirective; + }]; +}; + +var formDirective = formDirectiveFactory(); +var ngFormDirective = formDirectiveFactory(true); + +/* global VALID_CLASS: false, + INVALID_CLASS: false, + PRISTINE_CLASS: false, + DIRTY_CLASS: false, + UNTOUCHED_CLASS: false, + TOUCHED_CLASS: false, + $ngModelMinErr: false, +*/ + +// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231 +var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/; +var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/; +var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i; +var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/; +var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/; +var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; +var WEEK_REGEXP = /^(\d{4})-W(\d\d)$/; +var MONTH_REGEXP = /^(\d{4})-(\d\d)$/; +var TIME_REGEXP = /^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; + +var inputType = { + + /** + * @ngdoc input + * @name input[text] + * + * @description + * Standard HTML text input with angular data binding, inherited by most of the `input` elements. + * + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Adds `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match + * a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.
      + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input. + * This parameter is ignored for input[type=password] controls, which will never trim the + * input. + * + * @example + + + +
      + +
      + + Required! + + Single word only! +
      + text = {{example.text}}
      + myForm.input.$valid = {{myForm.input.$valid}}
      + myForm.input.$error = {{myForm.input.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      +
      +
      + + var text = element(by.binding('example.text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.text')); + + it('should initialize to model', function() { + expect(text.getText()).toContain('guest'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); + + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); + }); + + it('should be invalid if multi word', function() { + input.clear(); + input.sendKeys('hello world'); + + expect(valid.getText()).toContain('false'); + }); + +
      + */ + 'text': textInputType, + + /** + * @ngdoc input + * @name input[date] + * + * @description + * Input with date validation and transformation. In browsers that do not yet support + * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601 + * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many + * modern browsers do not yet support this input type, it is important to provide cues to users on the + * expected input format via a placeholder or label. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a + * valid ISO date string (yyyy-MM-dd). + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be + * a valid ISO date string (yyyy-MM-dd). + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
      + + +
      + + Required! + + Not a valid date! +
      + value = {{example.value | date: "yyyy-MM-dd"}}
      + myForm.input.$valid = {{myForm.input.$valid}}
      + myForm.input.$error = {{myForm.input.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      +
      +
      + + var value = element(by.binding('example.value | date: "yyyy-MM-dd"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.value')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (see https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('2013-10-22'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('2015-01-01'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
      + */ + 'date': createDateInputType('date', DATE_REGEXP, + createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']), + 'yyyy-MM-dd'), + + /** + * @ngdoc input + * @name input[datetime-local] + * + * @description + * Input with datetime validation and transformation. In browsers that do not yet support + * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a + * valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be + * a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
      + + +
      + + Required! + + Not a valid date! +
      + value = {{example.value | date: "yyyy-MM-ddTHH:mm:ss"}}
      + myForm.input.$valid = {{myForm.input.$valid}}
      + myForm.input.$error = {{myForm.input.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      +
      +
      + + var value = element(by.binding('example.value | date: "yyyy-MM-ddTHH:mm:ss"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.value')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('2010-12-28T14:57:00'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('2015-01-01T23:59:00'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
      + */ + 'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP, + createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']), + 'yyyy-MM-ddTHH:mm:ss.sss'), + + /** + * @ngdoc input + * @name input[time] + * + * @description + * Input with time validation and transformation. In browsers that do not yet support + * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a + * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a + * valid ISO time format (HH:mm:ss). + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be a + * valid ISO time format (HH:mm:ss). + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
      + + +
      + + Required! + + Not a valid date! +
      + value = {{example.value | date: "HH:mm:ss"}}
      + myForm.input.$valid = {{myForm.input.$valid}}
      + myForm.input.$error = {{myForm.input.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      +
      +
      + + var value = element(by.binding('example.value | date: "HH:mm:ss"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.value')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('14:57:00'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('23:59:00'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
      + */ + 'time': createDateInputType('time', TIME_REGEXP, + createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']), + 'HH:mm:ss.sss'), + + /** + * @ngdoc input + * @name input[week] + * + * @description + * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support + * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * week format (yyyy-W##), for example: `2013-W02`. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a + * valid ISO week format (yyyy-W##). + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be + * a valid ISO week format (yyyy-W##). + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
      + +
      + + Required! + + Not a valid date! +
      + value = {{example.value | date: "yyyy-Www"}}
      + myForm.input.$valid = {{myForm.input.$valid}}
      + myForm.input.$error = {{myForm.input.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      +
      +
      + + var value = element(by.binding('example.value | date: "yyyy-Www"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.value')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('2013-W01'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('2015-W01'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
      + */ + 'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'), + + /** + * @ngdoc input + * @name input[month] + * + * @description + * Input with month validation and transformation. In browsers that do not yet support + * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * month format (yyyy-MM), for example: `2009-01`. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * If the model is not set to the first of the month, the next view to model update will set it + * to the first of the month. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be + * a valid ISO month format (yyyy-MM). + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must + * be a valid ISO month format (yyyy-MM). + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
      + + +
      + + Required! + + Not a valid month! +
      + value = {{example.value | date: "yyyy-MM"}}
      + myForm.input.$valid = {{myForm.input.$valid}}
      + myForm.input.$error = {{myForm.input.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      +
      +
      + + var value = element(by.binding('example.value | date: "yyyy-MM"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.value')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('2013-10'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('2015-01'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
      + */ + 'month': createDateInputType('month', MONTH_REGEXP, + createDateParser(MONTH_REGEXP, ['yyyy', 'MM']), + 'yyyy-MM'), + + /** + * @ngdoc input + * @name input[number] + * + * @description + * Text input with number validation and transformation. Sets the `number` validation + * error if not a valid number. + * + *
      + * The model must always be of type `number` otherwise Angular will throw an error. + * Be aware that a string containing a number is not enough. See the {@link ngModel:numfmt} + * error docs for more information and an example of how to convert your model if necessary. + *
      + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match + * a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.
      + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
      + +
      + + Required! + + Not valid number! +
      + value = {{example.value}}
      + myForm.input.$valid = {{myForm.input.$valid}}
      + myForm.input.$error = {{myForm.input.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      +
      +
      + + var value = element(by.binding('example.value')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.value')); + + it('should initialize to model', function() { + expect(value.getText()).toContain('12'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('false'); + }); + + it('should be invalid if over max', function() { + input.clear(); + input.sendKeys('123'); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('false'); + }); + +
      + */ + 'number': numberInputType, + + + /** + * @ngdoc input + * @name input[url] + * + * @description + * Text input with URL validation. Sets the `url` validation error key if the content is not a + * valid URL. + * + *
      + * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex + * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify + * the built-in validators (see the {@link guide/forms Forms guide}) + *
      + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match + * a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.
      + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
      +
      + + var text = element(by.binding('url.text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('url.text')); + + it('should initialize to model', function() { + expect(text.getText()).toContain('http://google.com'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); + + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); + }); + + it('should be invalid if not url', function() { + input.clear(); + input.sendKeys('box'); + + expect(valid.getText()).toContain('false'); + }); + +
      + */ + 'url': urlInputType, + + + /** + * @ngdoc input + * @name input[email] + * + * @description + * Text input with email validation. Sets the `email` validation error key if not a valid email + * address. + * + *
      + * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex + * used in Chromium. If you need stricter validation (e.g. requiring a top-level domain), you can + * use `ng-pattern` or modify the built-in validators (see the {@link guide/forms Forms guide}) + *
      + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match + * a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.
      + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
      + +
      + + Required! + + Not valid email! +
      + text = {{email.text}}
      + myForm.input.$valid = {{myForm.input.$valid}}
      + myForm.input.$error = {{myForm.input.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      + myForm.$error.email = {{!!myForm.$error.email}}
      +
      +
      + + var text = element(by.binding('email.text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('email.text')); + + it('should initialize to model', function() { + expect(text.getText()).toContain('me@example.com'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); + }); + + it('should be invalid if not email', function() { + input.clear(); + input.sendKeys('xxx'); + + expect(valid.getText()).toContain('false'); + }); + +
      + */ + 'email': emailInputType, + + + /** + * @ngdoc input + * @name input[radio] + * + * @description + * HTML radio button. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string} value The value to which the expression should be set when selected. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * @param {string} ngValue Angular expression which sets the value to which the expression should + * be set when selected. + * + * @example + + + +
      +
      +
      +
      + color = {{color.name | json}}
      +
      + Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`. +
      + + it('should change state', function() { + var color = element(by.binding('color.name')); + + expect(color.getText()).toContain('blue'); + + element.all(by.model('color.name')).get(0).click(); + + expect(color.getText()).toContain('red'); + }); + +
      + */ + 'radio': radioInputType, + + + /** + * @ngdoc input + * @name input[checkbox] + * + * @description + * HTML checkbox. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {expression=} ngTrueValue The value to which the expression should be set when selected. + * @param {expression=} ngFalseValue The value to which the expression should be set when not selected. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
      +
      +
      + value1 = {{checkboxModel.value1}}
      + value2 = {{checkboxModel.value2}}
      +
      +
      + + it('should change state', function() { + var value1 = element(by.binding('checkboxModel.value1')); + var value2 = element(by.binding('checkboxModel.value2')); + + expect(value1.getText()).toContain('true'); + expect(value2.getText()).toContain('YES'); + + element(by.model('checkboxModel.value1')).click(); + element(by.model('checkboxModel.value2')).click(); + + expect(value1.getText()).toContain('false'); + expect(value2.getText()).toContain('NO'); + }); + +
      + */ + 'checkbox': checkboxInputType, + + 'hidden': noop, + 'button': noop, + 'submit': noop, + 'reset': noop, + 'file': noop +}; + +function stringBasedInputType(ctrl) { + ctrl.$formatters.push(function(value) { + return ctrl.$isEmpty(value) ? value : value.toString(); + }); +} + +function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + stringBasedInputType(ctrl); +} + +function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) { + var type = lowercase(element[0].type); + + // In composition mode, users are still inputing intermediate text buffer, + // hold the listener until composition is done. + // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent + if (!$sniffer.android) { + var composing = false; + + element.on('compositionstart', function(data) { + composing = true; + }); + + element.on('compositionend', function() { + composing = false; + listener(); + }); + } + + var listener = function(ev) { + if (timeout) { + $browser.defer.cancel(timeout); + timeout = null; + } + if (composing) return; + var value = element.val(), + event = ev && ev.type; + + // By default we will trim the value + // If the attribute ng-trim exists we will avoid trimming + // If input type is 'password', the value is never trimmed + if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) { + value = trim(value); + } + + // If a control is suffering from bad input (due to native validators), browsers discard its + // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the + // control's value is the same empty value twice in a row. + if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) { + ctrl.$setViewValue(value, event); + } + }; + + // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the + // input event on backspace, delete or cut + if ($sniffer.hasEvent('input')) { + element.on('input', listener); + } else { + var timeout; + + var deferListener = function(ev, input, origValue) { + if (!timeout) { + timeout = $browser.defer(function() { + timeout = null; + if (!input || input.value !== origValue) { + listener(ev); + } + }); + } + }; + + element.on('keydown', function(event) { + var key = event.keyCode; + + // ignore + // command modifiers arrows + if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return; + + deferListener(event, this, this.value); + }); + + // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it + if ($sniffer.hasEvent('paste')) { + element.on('paste cut', deferListener); + } + } + + // if user paste into input using mouse on older browser + // or form autocomplete on newer browser, we need "change" event to catch it + element.on('change', listener); + + ctrl.$render = function() { + element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue); + }; +} + +function weekParser(isoWeek, existingDate) { + if (isDate(isoWeek)) { + return isoWeek; + } + + if (isString(isoWeek)) { + WEEK_REGEXP.lastIndex = 0; + var parts = WEEK_REGEXP.exec(isoWeek); + if (parts) { + var year = +parts[1], + week = +parts[2], + hours = 0, + minutes = 0, + seconds = 0, + milliseconds = 0, + firstThurs = getFirstThursdayOfYear(year), + addDays = (week - 1) * 7; + + if (existingDate) { + hours = existingDate.getHours(); + minutes = existingDate.getMinutes(); + seconds = existingDate.getSeconds(); + milliseconds = existingDate.getMilliseconds(); + } + + return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds); + } + } + + return NaN; +} + +function createDateParser(regexp, mapping) { + return function(iso, date) { + var parts, map; + + if (isDate(iso)) { + return iso; + } + + if (isString(iso)) { + // When a date is JSON'ified to wraps itself inside of an extra + // set of double quotes. This makes the date parsing code unable + // to match the date string and parse it as a date. + if (iso.charAt(0) == '"' && iso.charAt(iso.length - 1) == '"') { + iso = iso.substring(1, iso.length - 1); + } + if (ISO_DATE_REGEXP.test(iso)) { + return new Date(iso); + } + regexp.lastIndex = 0; + parts = regexp.exec(iso); + + if (parts) { + parts.shift(); + if (date) { + map = { + yyyy: date.getFullYear(), + MM: date.getMonth() + 1, + dd: date.getDate(), + HH: date.getHours(), + mm: date.getMinutes(), + ss: date.getSeconds(), + sss: date.getMilliseconds() / 1000 + }; + } else { + map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 }; + } + + forEach(parts, function(part, index) { + if (index < mapping.length) { + map[mapping[index]] = +part; + } + }); + return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0); + } + } + + return NaN; + }; +} + +function createDateInputType(type, regexp, parseDate, format) { + return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) { + badInputChecker(scope, element, attr, ctrl); + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + var timezone = ctrl && ctrl.$options && ctrl.$options.timezone; + var previousDate; + + ctrl.$$parserName = type; + ctrl.$parsers.push(function(value) { + if (ctrl.$isEmpty(value)) return null; + if (regexp.test(value)) { + // Note: We cannot read ctrl.$modelValue, as there might be a different + // parser/formatter in the processing chain so that the model + // contains some different data format! + var parsedDate = parseDate(value, previousDate); + if (timezone) { + parsedDate = convertTimezoneToLocal(parsedDate, timezone); + } + return parsedDate; + } + return undefined; + }); + + ctrl.$formatters.push(function(value) { + if (value && !isDate(value)) { + throw $ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value); + } + if (isValidDate(value)) { + previousDate = value; + if (previousDate && timezone) { + previousDate = convertTimezoneToLocal(previousDate, timezone, true); + } + return $filter('date')(value, format, timezone); + } else { + previousDate = null; + return ''; + } + }); + + if (isDefined(attr.min) || attr.ngMin) { + var minVal; + ctrl.$validators.min = function(value) { + return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal; + }; + attr.$observe('min', function(val) { + minVal = parseObservedDateValue(val); + ctrl.$validate(); + }); + } + + if (isDefined(attr.max) || attr.ngMax) { + var maxVal; + ctrl.$validators.max = function(value) { + return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal; + }; + attr.$observe('max', function(val) { + maxVal = parseObservedDateValue(val); + ctrl.$validate(); + }); + } + + function isValidDate(value) { + // Invalid Date: getTime() returns NaN + return value && !(value.getTime && value.getTime() !== value.getTime()); + } + + function parseObservedDateValue(val) { + return isDefined(val) ? (isDate(val) ? val : parseDate(val)) : undefined; + } + }; +} + +function badInputChecker(scope, element, attr, ctrl) { + var node = element[0]; + var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity); + if (nativeValidation) { + ctrl.$parsers.push(function(value) { + var validity = element.prop(VALIDITY_STATE_PROPERTY) || {}; + // Detect bug in FF35 for input[email] (https://bugzilla.mozilla.org/show_bug.cgi?id=1064430): + // - also sets validity.badInput (should only be validity.typeMismatch). + // - see http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-(type=email) + // - can ignore this case as we can still read out the erroneous email... + return validity.badInput && !validity.typeMismatch ? undefined : value; + }); + } +} + +function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) { + badInputChecker(scope, element, attr, ctrl); + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + + ctrl.$$parserName = 'number'; + ctrl.$parsers.push(function(value) { + if (ctrl.$isEmpty(value)) return null; + if (NUMBER_REGEXP.test(value)) return parseFloat(value); + return undefined; + }); + + ctrl.$formatters.push(function(value) { + if (!ctrl.$isEmpty(value)) { + if (!isNumber(value)) { + throw $ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value); + } + value = value.toString(); + } + return value; + }); + + if (isDefined(attr.min) || attr.ngMin) { + var minVal; + ctrl.$validators.min = function(value) { + return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal; + }; + + attr.$observe('min', function(val) { + if (isDefined(val) && !isNumber(val)) { + val = parseFloat(val, 10); + } + minVal = isNumber(val) && !isNaN(val) ? val : undefined; + // TODO(matsko): implement validateLater to reduce number of validations + ctrl.$validate(); + }); + } + + if (isDefined(attr.max) || attr.ngMax) { + var maxVal; + ctrl.$validators.max = function(value) { + return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal; + }; + + attr.$observe('max', function(val) { + if (isDefined(val) && !isNumber(val)) { + val = parseFloat(val, 10); + } + maxVal = isNumber(val) && !isNaN(val) ? val : undefined; + // TODO(matsko): implement validateLater to reduce number of validations + ctrl.$validate(); + }); + } +} + +function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) { + // Note: no badInputChecker here by purpose as `url` is only a validation + // in browsers, i.e. we can always read out input.value even if it is not valid! + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + stringBasedInputType(ctrl); + + ctrl.$$parserName = 'url'; + ctrl.$validators.url = function(modelValue, viewValue) { + var value = modelValue || viewValue; + return ctrl.$isEmpty(value) || URL_REGEXP.test(value); + }; +} + +function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) { + // Note: no badInputChecker here by purpose as `url` is only a validation + // in browsers, i.e. we can always read out input.value even if it is not valid! + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + stringBasedInputType(ctrl); + + ctrl.$$parserName = 'email'; + ctrl.$validators.email = function(modelValue, viewValue) { + var value = modelValue || viewValue; + return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value); + }; +} + +function radioInputType(scope, element, attr, ctrl) { + // make the name unique, if not defined + if (isUndefined(attr.name)) { + element.attr('name', nextUid()); + } + + var listener = function(ev) { + if (element[0].checked) { + ctrl.$setViewValue(attr.value, ev && ev.type); + } + }; + + element.on('click', listener); + + ctrl.$render = function() { + var value = attr.value; + element[0].checked = (value == ctrl.$viewValue); + }; + + attr.$observe('value', ctrl.$render); +} + +function parseConstantExpr($parse, context, name, expression, fallback) { + var parseFn; + if (isDefined(expression)) { + parseFn = $parse(expression); + if (!parseFn.constant) { + throw minErr('ngModel')('constexpr', 'Expected constant expression for `{0}`, but saw ' + + '`{1}`.', name, expression); + } + return parseFn(context); + } + return fallback; +} + +function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) { + var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true); + var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false); + + var listener = function(ev) { + ctrl.$setViewValue(element[0].checked, ev && ev.type); + }; + + element.on('click', listener); + + ctrl.$render = function() { + element[0].checked = ctrl.$viewValue; + }; + + // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false` + // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert + // it to a boolean. + ctrl.$isEmpty = function(value) { + return value === false; + }; + + ctrl.$formatters.push(function(value) { + return equals(value, trueValue); + }); + + ctrl.$parsers.push(function(value) { + return value ? trueValue : falseValue; + }); +} + + +/** + * @ngdoc directive + * @name textarea + * @restrict E + * + * @description + * HTML textarea element control with angular data-binding. The data-binding and validation + * properties of this element are exactly the same as those of the + * {@link ng.directive:input input element}. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any + * length. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match + * a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.
      + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input. + */ + + +/** + * @ngdoc directive + * @name input + * @restrict E + * + * @description + * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding, + * input state control, and validation. + * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers. + * + *
      + * **Note:** Not every feature offered is available for all input types. + * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`. + *
      + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {boolean=} ngRequired Sets `required` attribute if set to true + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any + * length. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match + * a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.
      + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input. + * This parameter is ignored for input[type=password] controls, which will never trim the + * input. + * + * @example + + + +
      +
      + +
      + + Required! +
      + +
      + + Too short! + + Too long! +
      +
      +
      + user = {{user}}
      + myForm.userName.$valid = {{myForm.userName.$valid}}
      + myForm.userName.$error = {{myForm.userName.$error}}
      + myForm.lastName.$valid = {{myForm.lastName.$valid}}
      + myForm.lastName.$error = {{myForm.lastName.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      + myForm.$error.minlength = {{!!myForm.$error.minlength}}
      + myForm.$error.maxlength = {{!!myForm.$error.maxlength}}
      +
      +
      + + var user = element(by.exactBinding('user')); + var userNameValid = element(by.binding('myForm.userName.$valid')); + var lastNameValid = element(by.binding('myForm.lastName.$valid')); + var lastNameError = element(by.binding('myForm.lastName.$error')); + var formValid = element(by.binding('myForm.$valid')); + var userNameInput = element(by.model('user.name')); + var userLastInput = element(by.model('user.last')); + + it('should initialize to model', function() { + expect(user.getText()).toContain('{"name":"guest","last":"visitor"}'); + expect(userNameValid.getText()).toContain('true'); + expect(formValid.getText()).toContain('true'); + }); + + it('should be invalid if empty when required', function() { + userNameInput.clear(); + userNameInput.sendKeys(''); + + expect(user.getText()).toContain('{"last":"visitor"}'); + expect(userNameValid.getText()).toContain('false'); + expect(formValid.getText()).toContain('false'); + }); + + it('should be valid if empty when min length is set', function() { + userLastInput.clear(); + userLastInput.sendKeys(''); + + expect(user.getText()).toContain('{"name":"guest","last":""}'); + expect(lastNameValid.getText()).toContain('true'); + expect(formValid.getText()).toContain('true'); + }); + + it('should be invalid if less than required min length', function() { + userLastInput.clear(); + userLastInput.sendKeys('xx'); + + expect(user.getText()).toContain('{"name":"guest"}'); + expect(lastNameValid.getText()).toContain('false'); + expect(lastNameError.getText()).toContain('minlength'); + expect(formValid.getText()).toContain('false'); + }); + + it('should be invalid if longer than max length', function() { + userLastInput.clear(); + userLastInput.sendKeys('some ridiculously long name'); + + expect(user.getText()).toContain('{"name":"guest"}'); + expect(lastNameValid.getText()).toContain('false'); + expect(lastNameError.getText()).toContain('maxlength'); + expect(formValid.getText()).toContain('false'); + }); + +
      + */ +var inputDirective = ['$browser', '$sniffer', '$filter', '$parse', + function($browser, $sniffer, $filter, $parse) { + return { + restrict: 'E', + require: ['?ngModel'], + link: { + pre: function(scope, element, attr, ctrls) { + if (ctrls[0]) { + (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer, + $browser, $filter, $parse); + } + } + } + }; +}]; + + + +var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/; +/** + * @ngdoc directive + * @name ngValue + * + * @description + * Binds the given expression to the value of `
      + + it('should check ng-options', function() { + expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red'); + element.all(by.model('myColor')).first().click(); + element.all(by.css('select[ng-model="myColor"] option')).first().click(); + expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black'); + element(by.css('.nullable select[ng-model="myColor"]')).click(); + element.all(by.css('.nullable select[ng-model="myColor"] option')).first().click(); + expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null'); + }); + + + */ + +// jshint maxlen: false +// //00001111111111000000000002222222222000000000000000000000333333333300000000000000000000000004444444444400000000000005555555555555550000000006666666666666660000000777777777777777000000000000000888888888800000000000000000009999999999 +var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/; + // 1: value expression (valueFn) + // 2: label expression (displayFn) + // 3: group by expression (groupByFn) + // 4: disable when expression (disableWhenFn) + // 5: array item variable name + // 6: object item key variable name + // 7: object item value variable name + // 8: collection expression + // 9: track by expression +// jshint maxlen: 100 + + +var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) { + + function parseOptionsExpression(optionsExp, selectElement, scope) { + + var match = optionsExp.match(NG_OPTIONS_REGEXP); + if (!(match)) { + throw ngOptionsMinErr('iexp', + "Expected expression in form of " + + "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" + + " but got '{0}'. Element: {1}", + optionsExp, startingTag(selectElement)); + } + + // Extract the parts from the ngOptions expression + + // The variable name for the value of the item in the collection + var valueName = match[5] || match[7]; + // The variable name for the key of the item in the collection + var keyName = match[6]; + + // An expression that generates the viewValue for an option if there is a label expression + var selectAs = / as /.test(match[0]) && match[1]; + // An expression that is used to track the id of each object in the options collection + var trackBy = match[9]; + // An expression that generates the viewValue for an option if there is no label expression + var valueFn = $parse(match[2] ? match[1] : valueName); + var selectAsFn = selectAs && $parse(selectAs); + var viewValueFn = selectAsFn || valueFn; + var trackByFn = trackBy && $parse(trackBy); + + // Get the value by which we are going to track the option + // if we have a trackFn then use that (passing scope and locals) + // otherwise just hash the given viewValue + var getTrackByValueFn = trackBy ? + function(value, locals) { return trackByFn(scope, locals); } : + function getHashOfValue(value) { return hashKey(value); }; + var getTrackByValue = function(value, key) { + return getTrackByValueFn(value, getLocals(value, key)); + }; + + var displayFn = $parse(match[2] || match[1]); + var groupByFn = $parse(match[3] || ''); + var disableWhenFn = $parse(match[4] || ''); + var valuesFn = $parse(match[8]); + + var locals = {}; + var getLocals = keyName ? function(value, key) { + locals[keyName] = key; + locals[valueName] = value; + return locals; + } : function(value) { + locals[valueName] = value; + return locals; + }; + + + function Option(selectValue, viewValue, label, group, disabled) { + this.selectValue = selectValue; + this.viewValue = viewValue; + this.label = label; + this.group = group; + this.disabled = disabled; + } + + return { + trackBy: trackBy, + getTrackByValue: getTrackByValue, + getWatchables: $parse(valuesFn, function(values) { + // Create a collection of things that we would like to watch (watchedArray) + // so that they can all be watched using a single $watchCollection + // that only runs the handler once if anything changes + var watchedArray = []; + values = values || []; + + Object.keys(values).forEach(function getWatchable(key) { + var locals = getLocals(values[key], key); + var selectValue = getTrackByValueFn(values[key], locals); + watchedArray.push(selectValue); + + // Only need to watch the displayFn if there is a specific label expression + if (match[2] || match[1]) { + var label = displayFn(scope, locals); + watchedArray.push(label); + } + + // Only need to watch the disableWhenFn if there is a specific disable expression + if (match[4]) { + var disableWhen = disableWhenFn(scope, locals); + watchedArray.push(disableWhen); + } + }); + return watchedArray; + }), + + getOptions: function() { + + var optionItems = []; + var selectValueMap = {}; + + // The option values were already computed in the `getWatchables` fn, + // which must have been called to trigger `getOptions` + var optionValues = valuesFn(scope) || []; + var optionValuesKeys; + + + if (!keyName && isArrayLike(optionValues)) { + optionValuesKeys = optionValues; + } else { + // if object, extract keys, in enumeration order, unsorted + optionValuesKeys = []; + for (var itemKey in optionValues) { + if (optionValues.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') { + optionValuesKeys.push(itemKey); + } + } + } + + var optionValuesLength = optionValuesKeys.length; + + for (var index = 0; index < optionValuesLength; index++) { + var key = (optionValues === optionValuesKeys) ? index : optionValuesKeys[index]; + var value = optionValues[key]; + var locals = getLocals(value, key); + var viewValue = viewValueFn(scope, locals); + var selectValue = getTrackByValueFn(viewValue, locals); + var label = displayFn(scope, locals); + var group = groupByFn(scope, locals); + var disabled = disableWhenFn(scope, locals); + var optionItem = new Option(selectValue, viewValue, label, group, disabled); + + optionItems.push(optionItem); + selectValueMap[selectValue] = optionItem; + } + + return { + items: optionItems, + selectValueMap: selectValueMap, + getOptionFromViewValue: function(value) { + return selectValueMap[getTrackByValue(value)]; + }, + getViewValueFromOption: function(option) { + // If the viewValue could be an object that may be mutated by the application, + // we need to make a copy and not return the reference to the value on the option. + return trackBy ? angular.copy(option.viewValue) : option.viewValue; + } + }; + } + }; + } + + + // we can't just jqLite(' + * + * + * + * {{ model }} + * + * + * angular.module('nonStringSelect', []) + * .run(function($rootScope) { + * $rootScope.model = { id: 2 }; + * }) + * .directive('convertToNumber', function() { + * return { + * require: 'ngModel', + * link: function(scope, element, attrs, ngModel) { + * ngModel.$parsers.push(function(val) { + * return parseInt(val, 10); + * }); + * ngModel.$formatters.push(function(val) { + * return '' + val; + * }); + * } + * }; + * }); + * + * + * it('should initialize to model', function() { + * var select = element(by.css('select')); + * expect(element(by.model('model.id')).$('option:checked').getText()).toEqual('Two'); + * }); + * + * + * + */ +var selectDirective = function() { + + return { + restrict: 'E', + require: ['select', '?ngModel'], + controller: SelectController, + link: function(scope, element, attr, ctrls) { + + // if ngModel is not defined, we don't need to do anything + var ngModelCtrl = ctrls[1]; + if (!ngModelCtrl) return; + + var selectCtrl = ctrls[0]; + + selectCtrl.ngModelCtrl = ngModelCtrl; + + // We delegate rendering to the `writeValue` method, which can be changed + // if the select can have multiple selected values or if the options are being + // generated by `ngOptions` + ngModelCtrl.$render = function() { + selectCtrl.writeValue(ngModelCtrl.$viewValue); + }; + + // When the selected item(s) changes we delegate getting the value of the select control + // to the `readValue` method, which can be changed if the select can have multiple + // selected values or if the options are being generated by `ngOptions` + element.on('change', function() { + scope.$apply(function() { + ngModelCtrl.$setViewValue(selectCtrl.readValue()); + }); + }); + + // If the select allows multiple values then we need to modify how we read and write + // values from and to the control; also what it means for the value to be empty and + // we have to add an extra watch since ngModel doesn't work well with arrays - it + // doesn't trigger rendering if only an item in the array changes. + if (attr.multiple) { + + // Read value now needs to check each option to see if it is selected + selectCtrl.readValue = function readMultipleValue() { + var array = []; + forEach(element.find('option'), function(option) { + if (option.selected) { + array.push(option.value); + } + }); + return array; + }; + + // Write value now needs to set the selected property of each matching option + selectCtrl.writeValue = function writeMultipleValue(value) { + var items = new HashMap(value); + forEach(element.find('option'), function(option) { + option.selected = isDefined(items.get(option.value)); + }); + }; + + // we have to do it on each watch since ngModel watches reference, but + // we need to work of an array, so we need to see if anything was inserted/removed + var lastView, lastViewRef = NaN; + scope.$watch(function selectMultipleWatch() { + if (lastViewRef === ngModelCtrl.$viewValue && !equals(lastView, ngModelCtrl.$viewValue)) { + lastView = shallowCopy(ngModelCtrl.$viewValue); + ngModelCtrl.$render(); + } + lastViewRef = ngModelCtrl.$viewValue; + }); + + // If we are a multiple select then value is now a collection + // so the meaning of $isEmpty changes + ngModelCtrl.$isEmpty = function(value) { + return !value || value.length === 0; + }; + + } + } + }; +}; + + +// The option directive is purely designed to communicate the existence (or lack of) +// of dynamically created (and destroyed) option elements to their containing select +// directive via its controller. +var optionDirective = ['$interpolate', function($interpolate) { + + function chromeHack(optionElement) { + // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459 + // Adding an