From e88760fecb9a523c945144ee5d63763870644127 Mon Sep 17 00:00:00 2001 From: Zhao Xin <7176466@qq.com> Date: Wed, 14 Sep 2022 17:34:39 +0800 Subject: [PATCH] gitpush --- demo/clients.js | 37 + demo/dbclickrotate/favicon.ico | Bin 0 -> 167710 bytes demo/dbclickrotate/index.html | 22 + demo/dbclickrotate/main.js | 2 + demo/dbclickrotate/style.css | 38 + demo/demo1/favicon.ico | Bin 0 -> 167710 bytes demo/demo1/index.html | 46 + demo/demo1/index.js | 37 + demo/demo1/style.css | 60 + demo/dragdrop/favicon.ico | Bin 0 -> 167710 bytes demo/dragdrop/index.html | 19 + demo/dragdrop/main.js | 16 + demo/dragdrop/style.css | 29 + demo/onshipgrid/favicon.ico | Bin 0 -> 167710 bytes demo/onshipgrid/index.html | 44 + demo/onshipgrid/main.js | 130 + demo/onshipgrid/style.css | 106 + demo/public/bs.css | 35 + demo/public/bs.html | 27 + demo/public/bs.js | 15 + demo/public/client.js | 28 + demo/public/favicon.ico | Bin 0 -> 167710 bytes demo/public/index.html | 20 + demo/public/style.css | 13 + demo/public2/favicon.ico | Bin 0 -> 167710 bytes demo/public2/index.html | 37 + demo/public2/main.js | 159 + demo/public2/play.html | 61 + demo/public2/style.css | 150 + demo/ship.js | 37 + 参考项目/846px-Battleships_Paper_Game.svg.png | Bin 0 -> 66805 bytes 参考项目/BattleShip/README.md | 98 + 参考项目/BattleShip/app.js | 113 + 参考项目/BattleShip/board.js | 94 + 参考项目/BattleShip/bundle.js | 31257 ++++++++++++++++ 参考项目/BattleShip/player.js | 30 + 参考项目/BattleShip/ship.js | 38 + 参考项目/battleboat/README.md | 10 + 参考项目/battleboat/battleboat.js | 1371 + 参考项目/battleboat/img/cross-icon.png | Bin 0 -> 187 bytes 参考项目/battleboat/img/cross-icon.svg | 8 + 参考项目/battleboat/img/crosshair.png | Bin 0 -> 639 bytes 参考项目/battleboat/img/favicon.png | Bin 0 -> 3890 bytes 参考项目/battleboat/index.html | 88 + 参考项目/battleboat/styles.css | 398 + 参考项目/bs/index.html | 37 + 参考项目/bs/script.js | 751 + 参考项目/bs/style.css | 350 + .../military-boats-collection_1284-37419.jpg | Bin 0 -> 81849 bytes 49 files changed, 35811 insertions(+) create mode 100644 demo/clients.js create mode 100644 demo/dbclickrotate/favicon.ico create mode 100644 demo/dbclickrotate/index.html create mode 100644 demo/dbclickrotate/main.js create mode 100644 demo/dbclickrotate/style.css create mode 100644 demo/demo1/favicon.ico create mode 100644 demo/demo1/index.html create mode 100644 demo/demo1/index.js create mode 100644 demo/demo1/style.css create mode 100644 demo/dragdrop/favicon.ico create mode 100644 demo/dragdrop/index.html create mode 100644 demo/dragdrop/main.js create mode 100644 demo/dragdrop/style.css create mode 100644 demo/onshipgrid/favicon.ico create mode 100644 demo/onshipgrid/index.html create mode 100644 demo/onshipgrid/main.js create mode 100644 demo/onshipgrid/style.css create mode 100644 demo/public/bs.css create mode 100644 demo/public/bs.html create mode 100644 demo/public/bs.js create mode 100644 demo/public/client.js create mode 100644 demo/public/favicon.ico create mode 100644 demo/public/index.html create mode 100644 demo/public/style.css create mode 100644 demo/public2/favicon.ico create mode 100644 demo/public2/index.html create mode 100644 demo/public2/main.js create mode 100644 demo/public2/play.html create mode 100644 demo/public2/style.css create mode 100644 demo/ship.js create mode 100644 参考项目/846px-Battleships_Paper_Game.svg.png create mode 100644 参考项目/BattleShip/README.md create mode 100644 参考项目/BattleShip/app.js create mode 100644 参考项目/BattleShip/board.js create mode 100644 参考项目/BattleShip/bundle.js create mode 100644 参考项目/BattleShip/player.js create mode 100644 参考项目/BattleShip/ship.js create mode 100644 参考项目/battleboat/README.md create mode 100644 参考项目/battleboat/battleboat.js create mode 100644 参考项目/battleboat/img/cross-icon.png create mode 100644 参考项目/battleboat/img/cross-icon.svg create mode 100644 参考项目/battleboat/img/crosshair.png create mode 100644 参考项目/battleboat/img/favicon.png create mode 100644 参考项目/battleboat/index.html create mode 100644 参考项目/battleboat/styles.css create mode 100644 参考项目/bs/index.html create mode 100644 参考项目/bs/script.js create mode 100644 参考项目/bs/style.css create mode 100644 参考项目/military-boats-collection_1284-37419.jpg diff --git a/demo/clients.js b/demo/clients.js new file mode 100644 index 0000000..829cdab --- /dev/null +++ b/demo/clients.js @@ -0,0 +1,37 @@ +class Client { + constructor(client) { + this.client = client + this.status = 'await' + this.name = 'anonymous' + this.client.emit('id', client.id) + } +} + +class Clients { + + constructor(io) { + this.io = io + this.clients = {} + } + + debuglog() { + console.log('client total:', this.length) + } + + add(client) { + this.clients[client.id] = new Client(client) + this.debuglog() + } + + del(client) { + delete this.clients[client.id] + this.debuglog() + } + + get length() { + return Object.entries(this.clients).length + } + +} + +module.exports = Clients diff --git a/demo/dbclickrotate/favicon.ico b/demo/dbclickrotate/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..ddaaf830f874db98c8dedf90228d2200c53c9661 GIT binary patch literal 167710 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 Jh^ten{s)n4^eO-V literal 0 HcmV?d00001 diff --git a/demo/dbclickrotate/index.html b/demo/dbclickrotate/index.html new file mode 100644 index 0000000..b2da5e7 --- /dev/null +++ b/demo/dbclickrotate/index.html @@ -0,0 +1,22 @@ + + + + + + + rotate + + + + +
+ + + + + +
+ + + + diff --git a/demo/dbclickrotate/main.js b/demo/dbclickrotate/main.js new file mode 100644 index 0000000..339459a --- /dev/null +++ b/demo/dbclickrotate/main.js @@ -0,0 +1,2 @@ +const ship = document.querySelector('.ship') +ship.addEventListener('dblclick', e => e.target.parentNode.classList.toggle("vertical")) diff --git a/demo/dbclickrotate/style.css b/demo/dbclickrotate/style.css new file mode 100644 index 0000000..6f478b8 --- /dev/null +++ b/demo/dbclickrotate/style.css @@ -0,0 +1,38 @@ +body { + height: 100vh; + display: flex; + align-items: center; + justify-content: center; +} + +.ship { + display: flex; + flex-wrap: wrap; + flex-direction: row; +} + +.ship.vertical { + flex-direction: column; +} + +.ship span { + width: 40px; + height: 40px; + background-color: orange; +} + +.ship .head { + border-radius: 20px 0 0 20px; +} + +.ship .tail { + border-radius: 0 10px 10px 0; +} + +.ship.vertical .head { + border-radius: 20px 20px 0 0; +} + +.ship.vertical .tail { + border-radius: 0 0 10px 10px; +} diff --git a/demo/demo1/favicon.ico b/demo/demo1/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..ddaaf830f874db98c8dedf90228d2200c53c9661 GIT binary patch literal 167710 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 Jh^ten{s)n4^eO-V literal 0 HcmV?d00001 diff --git a/demo/demo1/index.html b/demo/demo1/index.html new file mode 100644 index 0000000..52250d1 --- /dev/null +++ b/demo/demo1/index.html @@ -0,0 +1,46 @@ + + + + + + + Battleship + + + + + +

Battleship

+ + +
+
+ + + + + +
+
+ + + + +
+
+ + + +
+
+ + + +
+
+ + +
+ + + diff --git a/demo/demo1/index.js b/demo/demo1/index.js new file mode 100644 index 0000000..e84ceff --- /dev/null +++ b/demo/demo1/index.js @@ -0,0 +1,37 @@ +// elements in dom +const playerNameInput = document.getElementById('playerNameInput') +const playerGrid = document.getElementById('playerGrid') + +const player = { + name: localStorage.getItem('playerName') || '', +} + +// init +playerNameInput.value = player.name +for (let i = 0; i < 100; i++) { + const cell = document.createElement('span') + cell.classList.add('cell') + playerGrid.appendChild(cell) +} + +function start() { + const playerName = playerNameInput.value.trim() + if (playerName === '') { + alert('Please enter your name!') + playerNameInput.value = player.name || '' + playerNameInput.focus() + } else { + player.name = playerName + localStorage.setItem('playerName', playerName) + console.info(`player ${playerName} is starting a game`) + } +} + +for (let ship of document.querySelectorAll('.ship')) { + ship.addEventListener('click', (e) => { + e.preventDefault() + console.log(e) + e.target.classList.toggle("v") + }) +} + diff --git a/demo/demo1/style.css b/demo/demo1/style.css new file mode 100644 index 0000000..172fb74 --- /dev/null +++ b/demo/demo1/style.css @@ -0,0 +1,60 @@ +* { + margin: 0px; + padding: 0px; + box-sizing: border-box; +} + +.grid { + width: 430px; + height: 430px; + padding: 5px; + margin: 5px; + background-color: darkslategray; + display: flex; + flex-wrap: wrap; +} + +.grid span { + width: 40px; + height: 40px; + margin: 1px; + background-color: darkcyan; +} + +.ship { + width: 210px; + height: 42px; + display: flex; + flex-wrap: wrap; +} + +.ship.v { + width: 42px; + height: 210px; +} + +.ship span { + width: 40px; + height: 40px; + margin: 1px; +} + +.carrier span { + background-color: wheat; +} + +.battleship span { + background-color: darkslateblue; +} + +.destroyer span { + background-color: grey; +} + +.submarine span { + background-color: darkslategray; +} + +.patrolboat span { + background-color: darkgoldenrod; +} diff --git a/demo/dragdrop/favicon.ico b/demo/dragdrop/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..ddaaf830f874db98c8dedf90228d2200c53c9661 GIT binary patch literal 167710 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 Jh^ten{s)n4^eO-V literal 0 HcmV?d00001 diff --git a/demo/dragdrop/index.html b/demo/dragdrop/index.html new file mode 100644 index 0000000..bfbd1c0 --- /dev/null +++ b/demo/dragdrop/index.html @@ -0,0 +1,19 @@ + + + + + + + dragdrop + + + + +
+ +
+
+ + + + diff --git a/demo/dragdrop/main.js b/demo/dragdrop/main.js new file mode 100644 index 0000000..4c06fa8 --- /dev/null +++ b/demo/dragdrop/main.js @@ -0,0 +1,16 @@ +const one = document.getElementById('one') +const tow = document.getElementById('tow') +const box = document.getElementById('box') + +let item = undefined +box.addEventListener('drag', e => item = e.target) + +one.addEventListener('dragover', e => e.preventDefault()) +two.addEventListener('dragover', e => e.preventDefault()) +one.addEventListener('drop', drop) +two.addEventListener('drop', drop) + +function drop(e) { + e.target.appendChild(item) + item = undefined +} diff --git a/demo/dragdrop/style.css b/demo/dragdrop/style.css new file mode 100644 index 0000000..6583b04 --- /dev/null +++ b/demo/dragdrop/style.css @@ -0,0 +1,29 @@ + body { + height: 100vh; + display: flex; + align-items: center; + justify-content: center; + } + + div { + width: 100px; + height: 100px; + display: flex; + align-items: center; + justify-content: center; + margin: 0 10px; + } + + span { + width: 50px; + height: 50px; + } + + #one, + #two { + background-color: beige; + } + + #box { + background-color: chartreuse; + } diff --git a/demo/onshipgrid/favicon.ico b/demo/onshipgrid/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..ddaaf830f874db98c8dedf90228d2200c53c9661 GIT binary patch literal 167710 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 Jh^ten{s)n4^eO-V literal 0 HcmV?d00001 diff --git a/demo/onshipgrid/index.html b/demo/onshipgrid/index.html new file mode 100644 index 0000000..47dba1b --- /dev/null +++ b/demo/onshipgrid/index.html @@ -0,0 +1,44 @@ + + + + + + + grid + + + + +
+
+ + + + + +
+
+ + + + +
+
+ + + +
+
+ + + +
+
+ + +
+ + + + + diff --git a/demo/onshipgrid/main.js b/demo/onshipgrid/main.js new file mode 100644 index 0000000..8d11b71 --- /dev/null +++ b/demo/onshipgrid/main.js @@ -0,0 +1,130 @@ +const grid = document.querySelector('.grid') +const ships = document.querySelectorAll('.ship') +const carrier = document.querySelector('.carrier') // 航空母舰 +const battleship = document.querySelector('.battleship') // 战列舰 +const cruiser = document.querySelector('.cruiser') // 巡洋舰 +const submarine = document.querySelector('.submarine') // 潜艇 +const destroyer = document.querySelector('.destroyer') // 驱逐舰 +const testButton = document.querySelector('#testButton') + +let playing = false +let dragingItem = null + +function mod(n, w) { + const x = n % w + const y = (n - x) / w + return { x, y } +} + +function checkIfCollision(ox, oy, currentShip) { + for (let ship of ships) { + if (ship != currentShip) { + const cell = ship.parentNode + const index = parseInt(cell.id.slice(5)) + let { x, y } = mod(index, 10) + const vertical = ship.classList.contains('vertical') + const length = ship.children.length + if (vertical) { + const tail = y + length + for (; y < tail; y++) { + if (ox === x && oy === y) return true + } + } else { + const tail = x + length + for (; x < tail; x++) { + if (ox === x && oy === y) return true + } + } + } + } + return false +} + +function shipRotate(e) { + if (playing) return + const currentShip = e.target.parentNode + const length = currentShip.children.length + const cell = currentShip.parentNode + const index = parseInt(cell.id.slice(5)) + let { x, y } = mod(index, 10) + const vertical = currentShip.classList.contains('vertical') + // TODO 检查碰撞 + if (vertical) { + // 判断转为横向时是否碰撞 + const tail = x + length - 1 + if (tail >= 10) return // 船尾越界 + for (x = x + 1; x <= tail; x++) { + if (checkIfCollision(x, y, currentShip)) return + } + } else { + // 判断转为竖向时是否碰撞 + const tail = y + length - 1 + if (tail >= 10) return // 船尾越界 + for (y = y + 1; y <= tail; y++) { + if (checkIfCollision(x, y, currentShip)) return + } + } + + currentShip.classList.toggle('vertical') +} + +function shipMove(ship, x, y) { + const index = 10 * y + x + const vertical = ship.classList.contains('vertical') + // TODO 检查碰撞 + if (vertical) { } else { } + const cell = document.getElementById(`cell-${index}`) + cell.appendChild(ship) +} + +for (let ship of ships) ship.addEventListener('dblclick', shipRotate) + +testButton.addEventListener('click', e => { + playing = !playing + e.target.innerHTML = playing ? 'playing' : 'planning' +}) + +document.addEventListener('dragstart', e => { + if (playing || e.target.classList && !e.target.classList.contains('ship')) { + e.preventDefault() + return + } + dragingItem = e.target + // document.body.append(dragingItem) +}) +document.addEventListener('dragover', e => { + e.preventDefault() + dragingItem.style.display = 'none' + // document.body.append(dragingItem); + // dragingItem.style.position = 'absolute' + // dragingItem.style.left = e.pageX + 'px' + // dragingItem.style.top = e.pageY + 'px' +}) +function toggleCellHightlight(e) { if (e.target.classList && e.target.classList.contains('cell')) e.target.classList.toggle('hot') } +document.addEventListener('dragenter', toggleCellHightlight) +document.addEventListener('dragleave', toggleCellHightlight) +document.addEventListener('drop', e => { + e.preventDefault() + if (e.target.classList.contains('cell')) { + e.target.classList.remove('hot') + e.target.appendChild(dragingItem) + } + dragingItem.style.display = 'flex' + // dragingItem.style.position = 'relative' + // dragingItem.style.left = '0px' + // dragingItem.style.top = '0px' + dragingItem = null +}) + +// Init the game +for (let i = 0; i < 100; i++) { + const cell = document.createElement('span') + cell.id = `cell-${i}` + cell.classList.add('cell') + grid.appendChild(cell) +} +shipMove(carrier, 0, 0) +shipMove(battleship, 0, 1) +shipMove(cruiser, 0, 2) +shipMove(submarine, 0, 3) +shipMove(destroyer, 0, 4) diff --git a/demo/onshipgrid/style.css b/demo/onshipgrid/style.css new file mode 100644 index 0000000..e5beddc --- /dev/null +++ b/demo/onshipgrid/style.css @@ -0,0 +1,106 @@ +body { + height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.grid { + width: 420px; + height: 420px; + padding: 5px; + margin: 5px; + display: flex; + flex-wrap: wrap; + background-color: darkturquoise; +} + +.grid span { + width: 40px; + height: 40px; + margin: 1px; + background-color: #eee; + position: relative; +} + +.grid span.hot { + background-color: darkturquoise; +} + +.ship { + display: flex; + flex-wrap: wrap; + flex-direction: row; + z-index: 10; + position: relative; + margin: -1px; +} + +.ship.vertical { + flex-direction: column; +} + +.carrier { + width: 210px; + height: 40px; +} + +.carrier.vertical { + width: 40px; + height: 210px; +} + +.battleship { + width: 168px; + height: 40px; +} + +.battleship.vertical { + width: 40px; + height: 168px; +} + +.cruiser, +.submarine { + width: 126px; + height: 40px; +} + +.cruiser.vertical, +.submarine.vertical { + width: 40px; + height: 126px; +} + +.destroyer { + width: 84px; + height: 40px; +} + +.destroyer.vertical { + width: 40px; + height: 84px; +} + +.ship span { + width: 40px; + height: 40px; + background-color: darkcyan; +} + +.ship .head { + border-radius: 20px 0 0 20px; +} + +.ship .tail { + border-radius: 0 10px 10px 0; +} + +.ship.vertical .head { + border-radius: 20px 20px 0 0; +} + +.ship.vertical .tail { + border-radius: 0 0 10px 10px; +} diff --git a/demo/public/bs.css b/demo/public/bs.css new file mode 100644 index 0000000..a54bc78 --- /dev/null +++ b/demo/public/bs.css @@ -0,0 +1,35 @@ +* { + margin: 0px; + padding: 0px; + box-sizing: border-box; +} + +body { + width: 100vw; + height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +#sea { + display: flex; +} + +.player-grid { + width: 430px; + height: 430px; + padding: 5px; + margin: 5px; + background-color: darkslategray; + display: flex; + flex-wrap: wrap; +} + +.player-grid .cell { + width: 40px; + height: 40px; + margin: 1px; + background-color: darkcyan; +} diff --git a/demo/public/bs.html b/demo/public/bs.html new file mode 100644 index 0000000..663bfae --- /dev/null +++ b/demo/public/bs.html @@ -0,0 +1,27 @@ + + + + + + + Battleship + + + + + + +

Battleship

+
+
+

Plyer 1

+
+
+
+

Plyer 2

+
+
+
+ + + diff --git a/demo/public/bs.js b/demo/public/bs.js new file mode 100644 index 0000000..d6b0aa5 --- /dev/null +++ b/demo/public/bs.js @@ -0,0 +1,15 @@ +(function () { + const client = { id: "", io: io() } + client.io.on('id', id => client.id = id) + + const player1Grid = document.getElementById('player1-grid') + const player2Grid = document.getElementById('player2-grid') + for (let i = 0; i < 100; i++) { + const div1 = document.createElement('div') + div1.classList.add('cell') + player1Grid.appendChild(div1) + const div2 = document.createElement('div') + div2.classList.add('cell') + player2Grid.appendChild(div2) + } +})() diff --git a/demo/public/client.js b/demo/public/client.js new file mode 100644 index 0000000..b3324bb --- /dev/null +++ b/demo/public/client.js @@ -0,0 +1,28 @@ +const canvas = document.getElementById('canvas') +const ctx = canvas.getContext('2d') +const ColorBackgroud = '#000' +const CanvasWidth = 1000, CanvasHeight = 500 +const client = { id: "", io: io() } + +client.io.on('id', id => client.id = id) + +canvas.width = CanvasWidth +canvas.height = CanvasHeight +ctx.fillstyle = ColorBackgroud +ctx.fillRect(0, 0, CanvasWidth, CanvasHeight) + +document.addEventListener('click', event => { + console.log(event) + switch (event.key) { + case 'ArrowUp': + break + case 'ArrowDown': + break + case 'ArrowLeft': + break + case 'ArrowRight': + break + default: + break + } +}) diff --git a/demo/public/favicon.ico b/demo/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..ddaaf830f874db98c8dedf90228d2200c53c9661 GIT binary patch literal 167710 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 Jh^ten{s)n4^eO-V literal 0 HcmV?d00001 diff --git a/demo/public/index.html b/demo/public/index.html new file mode 100644 index 0000000..33a4345 --- /dev/null +++ b/demo/public/index.html @@ -0,0 +1,20 @@ + + + + + + + Battleship War + + + + + + +
+

Battleship War

+ +
+ + + diff --git a/demo/public/style.css b/demo/public/style.css new file mode 100644 index 0000000..e27e7d4 --- /dev/null +++ b/demo/public/style.css @@ -0,0 +1,13 @@ +* { + margin: 0px; + padding: 0px; + box-sizing: border-box; +} + +body { + width: 100vw; + height: 100vh; + display: flex; + align-items: center; + justify-content: center; +} diff --git a/demo/public2/favicon.ico b/demo/public2/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..ddaaf830f874db98c8dedf90228d2200c53c9661 GIT binary patch literal 167710 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 Jh^ten{s)n4^eO-V literal 0 HcmV?d00001 diff --git a/demo/public2/index.html b/demo/public2/index.html new file mode 100644 index 0000000..3d9df52 --- /dev/null +++ b/demo/public2/index.html @@ -0,0 +1,37 @@ + + + + + + + Battleships + + + + +
+

Battleships

+
+ + +
+
+ + + + diff --git a/demo/public2/main.js b/demo/public2/main.js new file mode 100644 index 0000000..6679b97 --- /dev/null +++ b/demo/public2/main.js @@ -0,0 +1,159 @@ +document.addEventListener('DOMContentLoaded', () => { + const client = io() + const queryString = window.location.search + const urlParams = new URLSearchParams(queryString) + const playerName = document.querySelector('#playerName') + playerName.innerHTML = urlParams.get('name') + client.emit('name', playerName.innerHTML) + + // Init the game + const playerGrid = document.querySelector('#playerGrid') + for (let i = 0; i < 100; i++) { + const cell = document.createElement('span') + cell.id = `playerCell${i}` + cell.classList.add('cell') + cell.dataset.index = i + cell.dataset.x = i % 10 + cell.dataset.y = (i - cell.dataset.x) / 10 + cell.classList.add('cell') + playerGrid.appendChild(cell) + } + + const enemyGrid = document.querySelector('#enemyGrid') + for (let i = 0; i < 100; i++) { + const cell = document.createElement('span') + cell.id = `enemyCell${i}` + cell.classList.add('cell') + cell.dataset.index = i + cell.dataset.x = i % 10 + cell.dataset.y = (i - cell.dataset.x) / 10 + cell.classList.add('cell') + enemyGrid.appendChild(cell) + } + + const ships = document.querySelectorAll('.ship') + const carrier = document.querySelector('.carrier') // 航空母舰 + const battleship = document.querySelector('.battleship') // 战列舰 + const cruiser = document.querySelector('.cruiser') // 巡洋舰 + const submarine = document.querySelector('.submarine') // 潜艇 + const destroyer = document.querySelector('.destroyer') // 驱逐舰 + + let playing = false + let dragingItem = null + + + function mod(n, w) { + const x = n % w + const y = (n - x) / w + return { x, y } + } + + function checkIfCollision(ox, oy, currentShip) { + for (let ship of ships) { + if (ship != currentShip) { + const cell = ship.parentNode + const index = parseInt(cell.dataset.index) + let { x, y } = mod(index, 10) + const vertical = ship.classList.contains('vertical') + const length = ship.children.length + if (vertical) { + const tail = y + length + for (; y < tail; y++) { + if (ox === x && oy === y) return true + } + } else { + const tail = x + length + for (; x < tail; x++) { + if (ox === x && oy === y) return true + } + } + } + } + return false + } + + function shipRotate(e) { + if (playing) return + const currentShip = e.target.parentNode + const length = currentShip.children.length + const cell = currentShip.parentNode + const index = parseInt(cell.dataset.index) + let { x, y } = mod(index, 10) + const vertical = currentShip.classList.contains('vertical') + // TODO 检查碰撞 + if (vertical) { + // 判断转为横向时是否碰撞 + const tail = x + length - 1 + if (tail >= 10) return // 船尾越界 + for (x = x + 1; x <= tail; x++) { + if (checkIfCollision(x, y, currentShip)) return + } + } else { + // 判断转为竖向时是否碰撞 + const tail = y + length - 1 + if (tail >= 10) return // 船尾越界 + for (y = y + 1; y <= tail; y++) { + if (checkIfCollision(x, y, currentShip)) return + } + } + + currentShip.classList.toggle('vertical') + } + + function shipMove(ship, x, y) { + const index = 10 * y + x + const cell = document.getElementById(`playerCell${index}`) + const length = ship.children.length + const vertical = ship.classList.contains('vertical') + // TODO 检查碰撞 + if (vertical) { + // 判断转为竖向时是否碰撞 + const tail = y + length - 1 + if (tail >= 10) return // 船尾越界 + for (let i = y + 1; i <= tail; i++) { + if (checkIfCollision(x, i, ship)) return + } + } else { + // 判断转为横向时是否碰撞 + const tail = x + length - 1 + if (tail >= 10) return // 船尾越界 + for (let i = x + 1; i <= tail; i++) { + if (checkIfCollision(i, y, ship)) return + } + } + cell.appendChild(ship) + } + + for (let ship of ships) ship.addEventListener('dblclick', shipRotate) + + document.addEventListener('dragstart', e => { + if (playing || e.target.classList && !e.target.classList.contains('ship')) { + e.preventDefault() + return + } + dragingItem = e.target + }) + document.addEventListener('dragover', e => { + e.preventDefault() + dragingItem.style.display = 'none' + }) + function toggleCellHightlight(e) { if (e.target.classList && e.target.classList.contains('cell')) e.target.classList.toggle('hot') } + document.addEventListener('dragenter', toggleCellHightlight) + document.addEventListener('dragleave', toggleCellHightlight) + document.addEventListener('drop', e => { + e.preventDefault() + if (e.target.classList.contains('cell')) { + e.target.classList.remove('hot') + e.target.appendChild(dragingItem) + } + dragingItem.style.display = 'flex' + dragingItem = null + }) + + shipMove(carrier, 1, 1) + shipMove(battleship, 1, 2) + shipMove(cruiser, 1, 3) + shipMove(submarine, 1, 4) + shipMove(destroyer, 1, 5) + +}) diff --git a/demo/public2/play.html b/demo/public2/play.html new file mode 100644 index 0000000..7b15fd9 --- /dev/null +++ b/demo/public2/play.html @@ -0,0 +1,61 @@ + + + + + + + Battleships + + + + +
+
+
+
+ You: ... + Status: Planning + Score: 0 +
+
+
+
+
+ Enemy: ... + Status: ... + Score: 0 +
+
+
+
+
+ + + + + +
+
+ + + + +
+
+ + + +
+
+ + + +
+
+ + +
+
+ + + diff --git a/demo/public2/style.css b/demo/public2/style.css new file mode 100644 index 0000000..562b686 --- /dev/null +++ b/demo/public2/style.css @@ -0,0 +1,150 @@ +* { + margin: 0px; + padding: 0px; + box-sizing: border-box; +} + +body { + width: 100vw; + height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +body, +input, +select, +button { + font-family: monospace; + font-size: 20px; +} + +input, +button { + border: 1px solid #333; + padding: 10px; + border-radius: 0px; +} + +button { + cursor: pointer; +} + +.text-center { + text-align: center; +} + +.container { + display: flex; +} + +.row { + flex-direction: row; + margin: 1rem 0; + justify-content: space-between; +} + +.column { + flex-direction: column; + margin: 0 1rem; +} + +.grid { + width: 430px; + height: 430px; + padding: 5px; + display: flex; + flex-wrap: wrap; + background-color: #003768; +} + +.grid span { + width: 40px; + height: 40px; + margin: 1px; + background-color: #3987c9; + position: relative; +} + +.grid span.hot { + background-color: #7fffd4; +} + +.ship { + display: flex; + flex-wrap: wrap; + flex-direction: row; + z-index: 10; + position: relative; + margin: -1px; +} + +.ship.vertical { + flex-direction: column; +} + +.carrier { + width: 210px; + height: 40px; +} + +.carrier.vertical { + width: 40px; + height: 210px; +} + +.battleship { + width: 168px; + height: 40px; +} + +.battleship.vertical { + width: 40px; + height: 168px; +} + +.cruiser, +.submarine { + width: 126px; + height: 40px; +} + +.cruiser.vertical, +.submarine.vertical { + width: 40px; + height: 126px; +} + +.destroyer { + width: 84px; + height: 40px; +} + +.destroyer.vertical { + width: 40px; + height: 84px; +} + +.ship span { + width: 40px; + height: 40px; + background-color: lightblue; +} + +.ship .head { + border-radius: 20px 0 0 20px; +} + +.ship .tail { + border-radius: 0 10px 10px 0; +} + +.ship.vertical .head { + border-radius: 20px 20px 0 0; +} + +.ship.vertical .tail { + border-radius: 0 0 10px 10px; +} diff --git a/demo/ship.js b/demo/ship.js new file mode 100644 index 0000000..91c9dda --- /dev/null +++ b/demo/ship.js @@ -0,0 +1,37 @@ +class Ship { + constructor(name, length) { + this.name = name + this.length = length + } +} + +class Carrier extends Ship { + constructor() { + super('Carrier', 5) + } +} + +class Battleship extends Ship { + constructor() { + super('Battleship', 4) + } +} + +class Destroyer extends Ship { + constructor() { + super('Destroyer', 3) + } +} + +class Submarine extends Ship { + constructor() { + super('Submarine', 3) + } +} +class Patrolboat extends Ship { + constructor() { + super('Patrolboat', 2) + } +} + +module.exports = { Carrier, Battleship, Destroyer, Submarine, Patrolboat } diff --git a/参考项目/846px-Battleships_Paper_Game.svg.png b/参考项目/846px-Battleships_Paper_Game.svg.png new file mode 100644 index 0000000000000000000000000000000000000000..e1a6e1b31b024f90d2c52ff153e5f22d3e6945d5 GIT binary patch literal 66805 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

xNNykA#z>GvdibFS40jmQjzLqt3R~?ozCdJ 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 literal 0 HcmV?d00001 diff --git a/参考项目/BattleShip/README.md b/参考项目/BattleShip/README.md new file mode 100644 index 0000000..faf2c98 --- /dev/null +++ b/参考项目/BattleShip/README.md @@ -0,0 +1,98 @@ +# Battleships! + +A backend implementation Battleship using JavaScript. + +## Setup + +You will need to have the `prompt-sync` module for synchronous prompting of user input: + +`npm install --save prompt-sync` + +Clone the repo, navigate to the directory, and run: + + `node app.js` + + Simple as that! For placing ships, enter coordinates in the form `[x,y]`, for attacking ships, use `[y,x]` + +## Design + +Battleships uses an object-oriented approach to game design: + +### Classes + +**Player** +Has a `name`, `board`, and collection of `ships`. Giving each player a board allows us to abstract the board logic to its own class, and define a set of functions that will work regardless of the state of the current player's board. + +Player has one instance method on its prototype – `lost()` which makes use of ES6's `Array.prototype.every()` function to check if all ships in the collection are sunk. + +**Ship** +Ships have a `name`, `length`, and `numHits`. The ship uses 4 static methods to create instances of itself: + +``` +Ship.aircraftCarrier = function() { + return new Ship(5, "aircraft carrier") +}; +``` + +This allows the `Player` class to have ships like so: + + +``` +Player.prototype.createShips = function() { + return ( + { + aircraftCarrier: Ship.aircraftCarrier(), + battleship: Ship.battleship(), + submarine: Ship.submarine(), + patrolBoat: Ship.patrolBoat() + + } + ) +}; +``` +Ships have a `hit()` method, which increments `numHits` and checks its `sunk()` method. + +**Board** +The board manages the placement of ships, checking if an attack hits or misses, and creation of the obfuscated board. + +Ships are represented on the board as letters. For example, aircraft carriers are represented by the letter 'a'. The board iterates over its cells and uses a switch statement to handle a successful hit: + +``` +if (target != 'x' && target != '~') { + console.log("It's a hit!"); + switch (target) { + case 'a': + player.ships.aircraftCarrier.hit(); + break; + case 'b': + player.ships.battleship.hit(); + break; + case 's': + player.ships.submarine.hit(); + break; + case 'p': + player.ships.patrolBoat.hit(); + break; + } +``` + +`obfuscateBoard()` is used to display the 'upper' board of the player, which is essentially (for now) a record of successful hits. During a given players turn, they will see their opponents obfuscated board. Board obfuscation is accomplished by making a deep copy of the board and replacing anything other than an 'x' (a hit) with '~' + +``` +Board.prototype.obfuscateBoard = function() { + let deepCopy = JSON.parse(JSON.stringify(this.cells)); + deepCopy.forEach( (row, i) => { + row.forEach( (el, j) => { + if (el !== 'x' && el !== '~') { + deepCopy[i][j] = '~'; + } + }); + }); + return deepCopy; +} +``` + +**app** +The game driver, app.js, is not actually a class. It is a collection of functions mainly used to set up the game and maintain the rules with validation of coordinates, checking if the game is over, etc. It instantiates two players and then calls `gameSetup()` once for each player followed by `playGame()` + +Validation is tricky. There are many ways for a user to give bad input. `validCoords()` stops four behaviors: placing ships diagonally, placing ships out of bounds, placing ships on top of one another, placing ships in a space that is too small or large for the given ship. diff --git a/参考项目/BattleShip/app.js b/参考项目/BattleShip/app.js new file mode 100644 index 0000000..cde886b --- /dev/null +++ b/参考项目/BattleShip/app.js @@ -0,0 +1,113 @@ +const Player = require('./player.js') +const Board = require('./board.js') +const readline = require('readline') +var prompt = require('prompt-sync')({ + autocomplete: null, +}) + +var player1 = new Player("Player 1") +var player2 = new Player("Player 2") +var currentPlayer = player1 + +function gameSetup(player) { + console.log(`${player.name}, time to place your ships.`) + for (var el in player.ships) { + getInput(player.ships[el], player.ships[el].name, player) + } +} + +function getInput(ship, shipName, player) { + var letter = shipName[0] + var pair1 = prompt(`Place your ${shipName}, start position `) + var pair2 = prompt(`Place your ${shipName}, end position `) + while (!validCoords(pair1, pair2, player, ship)) { + var pair1 = prompt(`Place your ${shipName}, start position `) + var pair2 = prompt(`Place your ${shipName}, end position `) + } + player.board.placeShip(ship, [pair1, pair2], letter) +} + +function validCoords(p1, p2, player, ship) { + var x1 = parseInt(p1[1]) + var y1 = parseInt(p1[3]) + var x2 = parseInt(p2[1]) + var y2 = parseInt(p2[3]) + + // Ensure coordinates in bounds. + if (x1 < 0 || x2 < 0 || y1 < 0 || y2 < 0) { + console.log("Coordinates out of bounds") + return false + } + + if (x1 > 6 || x2 > 6 || y1 > 6 || y2 > 6) { + console.log("Coordinates out of bounds") + return false + } + + // If both x coords are the same, then the y coords must be different, IE, no diagonal ships. + if (!(((x1 != x2) && (y1 === y2)) || ((x1 === x2) && (y1 != y2)))) { + console.log("Ships cannot be placed diagonally.") + return false + + } + + // Ensure space isn't already populated + if (x1 != x2) { + var len = Math.abs(x1 - y1) + + for (var i = x1; i < x2; i++) { + if (player.board.cells[y1][i] != '~') { + console.log("A ship already exists there.") + return false + } + } + + // Ensure the distance between the two coordinates is big enough to fit the whole ship. + if (Math.abs(x1 - x2) != ship.length) { + console.log("Space is too small or too large to fit ship.") + return false + } + + } else { + var len = Math.abs(y1 - y2) + + for (var i = y1; i < y2; i++) { + if (player.board.cells[i][x1] != '~') { + console.log("A ship alredy exists there.") + return false + } + } + + if (Math.abs(y1 - y2) != ship.length) { + console.log("Space is too small or too large to fit ship.") + return false + } + + } + return true +} + +function getAttackCoords() { + return prompt('Enter attack target in the form [y,x] ') +} + +function oppositePlayer() { + var other = (currentPlayer === player1 ? player2 : player1) + return other +} + +function playGame() { + while (!currentPlayer.lost()) { + console.log(`${currentPlayer.name}, it's your turn!`) + console.log("Your opponent's board:") + console.log(oppositePlayer().board.obfuscateBoard()) + var attackCoords = getAttackCoords() + oppositePlayer().board.hit(attackCoords, oppositePlayer()) + currentPlayer = oppositePlayer() + } + console.log(`${currentPlayer.name} loses!`) +} + +gameSetup(player1) +gameSetup(player2) +playGame() diff --git a/参考项目/BattleShip/board.js b/参考项目/BattleShip/board.js new file mode 100644 index 0000000..051a467 --- /dev/null +++ b/参考项目/BattleShip/board.js @@ -0,0 +1,94 @@ +"use strict" + +function Board(name) { + this.cells = this.makeBoard(7, 7) + this.name = name + this.placeShip = this.placeShip.bind(this) + this.obfuscateBoard = this.obfuscateBoard.bind(this) + this.setDefault = this.setDefault.bind(this) + this.setDefault() +} + +Board.prototype.makeBoard = function (length) { + let arr = new Array(length || 0), + i = length + if (arguments.length > 1) { + let args = Array.prototype.slice.call(arguments, 1) + while (i--) arr[length - 1 - i] = this.makeBoard.apply(this, args) + } + return arr +} + +Board.prototype.placeShip = function (ship, coordindates, shipSym) { + let x1 = parseInt(coordindates[0][1]) + let y1 = parseInt(coordindates[0][3]) + let x2 = parseInt(coordindates[1][1]) + let y2 = parseInt(coordindates[1][3]) + + // Check if ship extends vertically or horizontally. + if (x1 != x2) { + let len = Math.abs(x1 - x2) + for (let i = x1; i < x2; i++) { + this.cells[y1][i] = shipSym + } + } else { + let len = Math.abs(y1 - y2) + for (let i = y1; i < y2; i++) { + this.cells[i][x1] = shipSym + } + } + console.log(this.cells) +} + +// 5 possible outcomes: hit, miss, repeat hit, sunk, victory. +Board.prototype.hit = function (coordindates, player) { + let x1 = parseInt(coordindates[1]) + let y1 = parseInt(coordindates[3]) + let target = this.cells[x1][y1] + + if (target != 'x' && target != '~') { + console.log("It's a hit!") + switch (target) { + case 'a': + player.ships.aircraftCarrier.hit() + break + case 'b': + player.ships.battleship.hit() + break + case 's': + player.ships.submarine.hit() + break + case 'p': + player.ships.patrolBoat.hit() + break + } + // Mark cell so we know that part of the ship has been hit. + this.cells[x1][y1] = 'x' + } else if (target === 'x') { + console.log("You already attacked that spot!") + } else { + console.log("Missfire!") + } +} + +// Fill the board with water tiles. +Board.prototype.setDefault = function () { + this.cells.forEach(row => { + row.fill('~') + }) +} + +// Display board only showing spots where the player has successfully hit the opponent. +Board.prototype.obfuscateBoard = function () { + let deepCopy = JSON.parse(JSON.stringify(this.cells)) + deepCopy.forEach((row, i) => { + row.forEach((el, j) => { + if (el !== 'x' && el !== '~') { + deepCopy[i][j] = '~' + } + }) + }) + return deepCopy +} + +module.exports = Board diff --git a/参考项目/BattleShip/bundle.js b/参考项目/BattleShip/bundle.js new file mode 100644 index 0000000..35247f3 --- /dev/null +++ b/参考项目/BattleShip/bundle.js @@ -0,0 +1,31257 @@ +/******/ (function (modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {} + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if (installedModules[moduleId]) +/******/ return installedModules[moduleId].exports + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false + /******/ +} + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__) + +/******/ // Flag the module as loaded +/******/ module.loaded = true + +/******/ // Return the exports of the module +/******/ return module.exports + /******/ +} + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = "" + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0) + /******/ +}) +/************************************************************************/ +/******/([ +/* 0 */ +/***/ function (module, exports, __webpack_require__) { + + const Player = __webpack_require__(1) + const Board = __webpack_require__(3) + const readline = __webpack_require__(4) + + var prompt = __webpack_require__(14) + + var player1 = new Player("Player 1") + var player2 = new Player("Player 2") + console.log("Player1, time to place your ships!") + console.log("Player1, time to place your Aircraft Carrier!") + prompt.start() + prompt.get(['pair1', 'pair2'], function (err, result) { + player1.board.placeShip(player1.ships.aircraftCarrier, [result.pair1, result.pair2]) + }) + + console.log("Player1, time to place your BattleShip!") + console.log("Player1, time to place your Submarine!") + console.log("Player1, time to place your Patrol Boat!") + + + + // console.log(p.name); + // console.log(p.ships); + // console.log(p.board.cells) + + /***/ +}, +/* 1 */ +/***/ function (module, exports, __webpack_require__) { + + const Ship = __webpack_require__(2) + const Board = __webpack_require__(3) + + function Player(name) { + this.name = name + this.board = new Board(this.name) + this.ships = this.createShips() + } + + Player.prototype.createShips = function () { + return ( + { + aircraftCarrier: Ship.aircraftCarrier(), + battleship: Ship.battleship(), + submarine: Ship.submarine(), + patrolBoat: Ship.patrolBoat() + } + ) + } + + module.exports = Player + + /***/ +}, +/* 2 */ +/***/ function (module, exports) { + + + function Ship(length, type) { + this.length = length + this.name = type + this.numHits = 0 + this.placed = false + } + + Ship.aircraftCarrier = function () { + return new Ship(5, "aircraft carrier") + } + + Ship.submarine = function () { + return new Ship(4, "submarine") + } + + Ship.battleship = function () { + return new Ship(3, "battleship") + } + + Ship.patrolBoat = function () { + return new Ship(2, "patrol boat") + } + + Ship.prototype.hit = function () { + this.numHits += 1 + } + + Ship.prototype.placed = function () { + return this.placed + } + + Ship.prototype.sunk = function () { + if (this.numHits === this.length) { + return true + } else { + return false + } + } + + + module.exports = Ship + + + /***/ +}, +/* 3 */ +/***/ function (module, exports) { + + "use strict" + + function Board(name) { + this.cells = this.makeBoard(7, 7) + this.name = name + } + + Board.prototype.makeBoard = function (length) { + let arr = new Array(length || 0), + i = length + if (arguments.length > 1) { + let args = Array.prototype.slice.call(arguments, 1) + while (i--) arr[length - 1 - i] = this.makeBoard.apply(this, args) + } + return arr + } + + Board.prototype.placeShip = function (ship, coordindates) { + + } + + + module.exports = Board + + /***/ +}, +/* 4 */ +/***/ function (module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function (Buffer) { + var fs = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"fs\""); e.code = 'MODULE_NOT_FOUND'; throw e }())), + EventEmitter = __webpack_require__(9).EventEmitter, + util = __webpack_require__(10) + + var readLine = module.exports = function (file, opts) { + if (!(this instanceof readLine)) return new readLine(file, opts) + + EventEmitter.call(this) + opts = opts || {} + opts.maxLineLength = opts.maxLineLength || 4096 // 4K + opts.retainBuffer = !!opts.retainBuffer //do not convert to String prior to invoking emit 'line' event + var self = this, + lineBuffer = new Buffer(opts.maxLineLength), + lineLength = 0, + lineCount = 0, + byteCount = 0, + emit = function (lineCount, byteCount) { + try { + var line = lineBuffer.slice(0, lineLength) + self.emit('line', opts.retainBuffer ? line : line.toString(), lineCount, byteCount) + } catch (err) { + self.emit('error', err) + } finally { + lineLength = 0 // Empty buffer. + } + } + this.input = ('string' === typeof file) ? fs.createReadStream(file, opts) : file + this.input.on('open', function (fd) { + self.emit('open', fd) + }) + .on('data', function (data) { + for (var i = 0; i < data.length; i++) { + if (data[i] == 10 || data[i] == 13) { // Newline char was found. + if (data[i] == 10) { + lineCount++ + emit(lineCount, byteCount) + } + } else { + lineBuffer[lineLength] = data[i] // Buffer new line data. + lineLength++ + } + byteCount++ + } + }) + .on('error', function (err) { + self.emit('error', err) + }) + .on('end', function () { + // Emit last line if anything left over since EOF won't trigger it. + if (lineLength) { + lineCount++ + emit(lineCount, byteCount) + } + self.emit('end') + }) + .on('close', function () { + self.emit('close') + }) + } + util.inherits(readLine, EventEmitter) + + /* WEBPACK VAR INJECTION */ +}.call(exports, __webpack_require__(5).Buffer)) + + /***/ +}, +/* 5 */ +/***/ function (module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function (Buffer, global) {/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ + /* eslint-disable no-proto */ + + 'use strict' + + var base64 = __webpack_require__(6) + var ieee754 = __webpack_require__(7) + var isArray = __webpack_require__(8) + + exports.Buffer = Buffer + exports.SlowBuffer = SlowBuffer + exports.INSPECT_MAX_BYTES = 50 + Buffer.poolSize = 8192 // not used by this implementation + + var rootParent = {} + + /** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Use Object implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * Due to various browser bugs, sometimes the Object implementation will be used even + * when the browser supports typed arrays. + * + * Note: + * + * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, + * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. + * + * - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property + * on objects. + * + * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. + * + * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of + * incorrect length in some situations. + + * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they + * get the Object implementation, which is slower but behaves correctly. + */ + Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined + ? global.TYPED_ARRAY_SUPPORT + : typedArraySupport() + + function typedArraySupport() { + function Bar() { } + try { + var arr = new Uint8Array(1) + arr.foo = function () { return 42 } + arr.constructor = Bar + return arr.foo() === 42 && // typed array instances can be augmented + arr.constructor === Bar && // constructor can be set + typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` + arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` + } catch (e) { + return false + } + } + + function kMaxLength() { + return Buffer.TYPED_ARRAY_SUPPORT + ? 0x7fffffff + : 0x3fffffff + } + + /** + * Class: Buffer + * ============= + * + * The Buffer constructor returns instances of `Uint8Array` that are augmented + * with function properties for all the node `Buffer` API functions. We use + * `Uint8Array` so that square bracket notation works as expected -- it returns + * a single octet. + * + * By augmenting the instances, we can avoid modifying the `Uint8Array` + * prototype. + */ + function Buffer(arg) { + if (!(this instanceof Buffer)) { + // Avoid going through an ArgumentsAdaptorTrampoline in the common case. + if (arguments.length > 1) return new Buffer(arg, arguments[1]) + return new Buffer(arg) + } + + if (!Buffer.TYPED_ARRAY_SUPPORT) { + this.length = 0 + this.parent = undefined + } + + // Common case. + if (typeof arg === 'number') { + return fromNumber(this, arg) + } + + // Slightly less common case. + if (typeof arg === 'string') { + return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8') + } + + // Unusual. + return fromObject(this, arg) + } + + function fromNumber(that, length) { + that = allocate(that, length < 0 ? 0 : checked(length) | 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) { + for (var i = 0; i < length; i++) { + that[i] = 0 + } + } + return that + } + + function fromString(that, string, encoding) { + if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8' + + // Assumption: byteLength() return value is always < kMaxLength. + var length = byteLength(string, encoding) | 0 + that = allocate(that, length) + + that.write(string, encoding) + return that + } + + function fromObject(that, object) { + if (Buffer.isBuffer(object)) return fromBuffer(that, object) + + if (isArray(object)) return fromArray(that, object) + + if (object == null) { + throw new TypeError('must start with number, buffer, array or string') + } + + if (typeof ArrayBuffer !== 'undefined') { + if (object.buffer instanceof ArrayBuffer) { + return fromTypedArray(that, object) + } + if (object instanceof ArrayBuffer) { + return fromArrayBuffer(that, object) + } + } + + if (object.length) return fromArrayLike(that, object) + + return fromJsonObject(that, object) + } + + function fromBuffer(that, buffer) { + var length = checked(buffer.length) | 0 + that = allocate(that, length) + buffer.copy(that, 0, 0, length) + return that + } + + function fromArray(that, array) { + var length = checked(array.length) | 0 + that = allocate(that, length) + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that + } + + // Duplicate of fromArray() to keep fromArray() monomorphic. + function fromTypedArray(that, array) { + var length = checked(array.length) | 0 + that = allocate(that, length) + // Truncating the elements is probably not what people expect from typed + // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior + // of the old Buffer constructor. + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that + } + + function fromArrayBuffer(that, array) { + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Return an augmented `Uint8Array` instance, for best performance + array.byteLength + that = Buffer._augment(new Uint8Array(array)) + } else { + // Fallback: Return an object instance of the Buffer class + that = fromTypedArray(that, new Uint8Array(array)) + } + return that + } + + function fromArrayLike(that, array) { + var length = checked(array.length) | 0 + that = allocate(that, length) + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that + } + + // Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object. + // Returns a zero-length buffer for inputs that don't conform to the spec. + function fromJsonObject(that, object) { + var array + var length = 0 + + if (object.type === 'Buffer' && isArray(object.data)) { + array = object.data + length = checked(array.length) | 0 + } + that = allocate(that, length) + + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that + } + + if (Buffer.TYPED_ARRAY_SUPPORT) { + Buffer.prototype.__proto__ = Uint8Array.prototype + Buffer.__proto__ = Uint8Array + } else { + // pre-set for values that may exist in the future + Buffer.prototype.length = undefined + Buffer.prototype.parent = undefined + } + + function allocate(that, length) { + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Return an augmented `Uint8Array` instance, for best performance + that = Buffer._augment(new Uint8Array(length)) + that.__proto__ = Buffer.prototype + } else { + // Fallback: Return an object instance of the Buffer class + that.length = length + that._isBuffer = true + } + + var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1 + if (fromPool) that.parent = rootParent + + return that + } + + function checked(length) { + // Note: cannot use `length < kMaxLength` here because that fails when + // length is NaN (which is otherwise coerced to zero.) + if (length >= kMaxLength()) { + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + kMaxLength().toString(16) + ' bytes') + } + return length | 0 + } + + function SlowBuffer(subject, encoding) { + if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding) + + var buf = new Buffer(subject, encoding) + delete buf.parent + return buf + } + + Buffer.isBuffer = function isBuffer(b) { + return !!(b != null && b._isBuffer) + } + + Buffer.compare = function compare(a, b) { + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + throw new TypeError('Arguments must be Buffers') + } + + if (a === b) return 0 + + var x = a.length + var y = b.length + + var i = 0 + var len = Math.min(x, y) + while (i < len) { + if (a[i] !== b[i]) break + + ++i + } + + if (i !== len) { + x = a[i] + y = b[i] + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 + } + + Buffer.isEncoding = function isEncoding(encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'binary': + case 'base64': + case 'raw': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } + } + + Buffer.concat = function concat(list, length) { + if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.') + + if (list.length === 0) { + return new Buffer(0) + } + + var i + if (length === undefined) { + length = 0 + for (i = 0; i < list.length; i++) { + length += list[i].length + } + } + + var buf = new Buffer(length) + var pos = 0 + for (i = 0; i < list.length; i++) { + var item = list[i] + item.copy(buf, pos) + pos += item.length + } + return buf + } + + function byteLength(string, encoding) { + if (typeof string !== 'string') string = '' + string + + var len = string.length + if (len === 0) return 0 + + // Use a for loop to avoid recursion + var loweredCase = false + for (; ;) { + switch (encoding) { + case 'ascii': + case 'binary': + // Deprecated + case 'raw': + case 'raws': + return len + case 'utf8': + case 'utf-8': + return utf8ToBytes(string).length + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return len * 2 + case 'hex': + return len >>> 1 + case 'base64': + return base64ToBytes(string).length + default: + if (loweredCase) return utf8ToBytes(string).length // assume utf8 + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } + } + Buffer.byteLength = byteLength + + function slowToString(encoding, start, end) { + var loweredCase = false + + start = start | 0 + end = end === undefined || end === Infinity ? this.length : end | 0 + + if (!encoding) encoding = 'utf8' + if (start < 0) start = 0 + if (end > this.length) end = this.length + if (end <= start) return '' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'binary': + return binarySlice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } + } + } + + Buffer.prototype.toString = function toString() { + var length = this.length | 0 + if (length === 0) return '' + if (arguments.length === 0) return utf8Slice(this, 0, length) + return slowToString.apply(this, arguments) + } + + Buffer.prototype.equals = function equals(b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return true + return Buffer.compare(this, b) === 0 + } + + Buffer.prototype.inspect = function inspect() { + var str = '' + var max = exports.INSPECT_MAX_BYTES + if (this.length > 0) { + str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') + if (this.length > max) str += ' ... ' + } + return '' + } + + Buffer.prototype.compare = function compare(b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return 0 + return Buffer.compare(this, b) + } + + Buffer.prototype.indexOf = function indexOf(val, byteOffset) { + if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff + else if (byteOffset < -0x80000000) byteOffset = -0x80000000 + byteOffset >>= 0 + + if (this.length === 0) return -1 + if (byteOffset >= this.length) return -1 + + // Negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0) + + if (typeof val === 'string') { + if (val.length === 0) return -1 // special case: looking for empty string always fails + return String.prototype.indexOf.call(this, val, byteOffset) + } + if (Buffer.isBuffer(val)) { + return arrayIndexOf(this, val, byteOffset) + } + if (typeof val === 'number') { + if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') { + return Uint8Array.prototype.indexOf.call(this, val, byteOffset) + } + return arrayIndexOf(this, [val], byteOffset) + } + + function arrayIndexOf(arr, val, byteOffset) { + var foundIndex = -1 + for (var i = 0; byteOffset + i < arr.length; i++) { + if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) { + if (foundIndex === -1) foundIndex = i + if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex + } else { + foundIndex = -1 + } + } + return -1 + } + + throw new TypeError('val must be string, number or Buffer') + } + + // `get` is deprecated + Buffer.prototype.get = function get(offset) { + console.log('.get() is deprecated. Access using array indexes instead.') + return this.readUInt8(offset) + } + + // `set` is deprecated + Buffer.prototype.set = function set(v, offset) { + console.log('.set() is deprecated. Access using array indexes instead.') + return this.writeUInt8(v, offset) + } + + function hexWrite(buf, string, offset, length) { + offset = Number(offset) || 0 + var remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + // must be an even number of digits + var strLen = string.length + if (strLen % 2 !== 0) throw new Error('Invalid hex string') + + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; i++) { + var parsed = parseInt(string.substr(i * 2, 2), 16) + if (isNaN(parsed)) throw new Error('Invalid hex string') + buf[offset + i] = parsed + } + return i + } + + function utf8Write(buf, string, offset, length) { + return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) + } + + function asciiWrite(buf, string, offset, length) { + return blitBuffer(asciiToBytes(string), buf, offset, length) + } + + function binaryWrite(buf, string, offset, length) { + return asciiWrite(buf, string, offset, length) + } + + function base64Write(buf, string, offset, length) { + return blitBuffer(base64ToBytes(string), buf, offset, length) + } + + function ucs2Write(buf, string, offset, length) { + return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) + } + + Buffer.prototype.write = function write(string, offset, length, encoding) { + // Buffer#write(string) + if (offset === undefined) { + encoding = 'utf8' + length = this.length + offset = 0 + // Buffer#write(string, encoding) + } else if (length === undefined && typeof offset === 'string') { + encoding = offset + length = this.length + offset = 0 + // Buffer#write(string, offset[, length][, encoding]) + } else if (isFinite(offset)) { + offset = offset | 0 + if (isFinite(length)) { + length = length | 0 + if (encoding === undefined) encoding = 'utf8' + } else { + encoding = length + length = undefined + } + // legacy write(string, encoding, offset, length) - remove in v0.13 + } else { + var swap = encoding + encoding = offset + offset = length | 0 + length = swap + } + + var remaining = this.length - offset + if (length === undefined || length > remaining) length = remaining + + if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { + throw new RangeError('attempt to write outside buffer bounds') + } + + if (!encoding) encoding = 'utf8' + + var loweredCase = false + for (; ;) { + switch (encoding) { + case 'hex': + return hexWrite(this, string, offset, length) + + case 'utf8': + case 'utf-8': + return utf8Write(this, string, offset, length) + + case 'ascii': + return asciiWrite(this, string, offset, length) + + case 'binary': + return binaryWrite(this, string, offset, length) + + case 'base64': + // Warning: maxLength not taken into account in base64Write + return base64Write(this, string, offset, length) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return ucs2Write(this, string, offset, length) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } + } + + Buffer.prototype.toJSON = function toJSON() { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } + } + + function base64Slice(buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } + } + + function utf8Slice(buf, start, end) { + end = Math.min(buf.length, end) + var res = [] + + var i = start + while (i < end) { + var firstByte = buf[i] + var codePoint = null + var bytesPerSequence = (firstByte > 0xEF) ? 4 + : (firstByte > 0xDF) ? 3 + : (firstByte > 0xBF) ? 2 + : 1 + + if (i + bytesPerSequence <= end) { + var secondByte, thirdByte, fourthByte, tempCodePoint + + switch (bytesPerSequence) { + case 1: + if (firstByte < 0x80) { + codePoint = firstByte + } + break + case 2: + secondByte = buf[i + 1] + if ((secondByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) + if (tempCodePoint > 0x7F) { + codePoint = tempCodePoint + } + } + break + case 3: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) + if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { + codePoint = tempCodePoint + } + } + break + case 4: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + fourthByte = buf[i + 3] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) + if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { + codePoint = tempCodePoint + } + } + } + } + + if (codePoint === null) { + // we did not generate a valid codePoint so insert a + // replacement char (U+FFFD) and advance only 1 byte + codePoint = 0xFFFD + bytesPerSequence = 1 + } else if (codePoint > 0xFFFF) { + // encode to utf16 (surrogate pair dance) + codePoint -= 0x10000 + res.push(codePoint >>> 10 & 0x3FF | 0xD800) + codePoint = 0xDC00 | codePoint & 0x3FF + } + + res.push(codePoint) + i += bytesPerSequence + } + + return decodeCodePointsArray(res) + } + + // Based on http://stackoverflow.com/a/22747272/680742, the browser with + // the lowest limit is Chrome, with 0x10000 args. + // We go 1 magnitude less, for safety + var MAX_ARGUMENTS_LENGTH = 0x1000 + + function decodeCodePointsArray(codePoints) { + var len = codePoints.length + if (len <= MAX_ARGUMENTS_LENGTH) { + return String.fromCharCode.apply(String, codePoints) // avoid extra slice() + } + + // Decode in chunks to avoid "call stack size exceeded". + var res = '' + var i = 0 + while (i < len) { + res += String.fromCharCode.apply( + String, + codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) + ) + } + return res + } + + function asciiSlice(buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; i++) { + ret += String.fromCharCode(buf[i] & 0x7F) + } + return ret + } + + function binarySlice(buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; i++) { + ret += String.fromCharCode(buf[i]) + } + return ret + } + + function hexSlice(buf, start, end) { + var len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + var out = '' + for (var i = start; i < end; i++) { + out += toHex(buf[i]) + } + return out + } + + function utf16leSlice(buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) + } + return res + } + + Buffer.prototype.slice = function slice(start, end) { + var len = this.length + start = ~~start + end = end === undefined ? len : ~~end + + if (start < 0) { + start += len + if (start < 0) start = 0 + } else if (start > len) { + start = len + } + + if (end < 0) { + end += len + if (end < 0) end = 0 + } else if (end > len) { + end = len + } + + if (end < start) end = start + + var newBuf + if (Buffer.TYPED_ARRAY_SUPPORT) { + newBuf = Buffer._augment(this.subarray(start, end)) + } else { + var sliceLen = end - start + newBuf = new Buffer(sliceLen, undefined) + for (var i = 0; i < sliceLen; i++) { + newBuf[i] = this[i + start] + } + } + + if (newBuf.length) newBuf.parent = this.parent || this + + return newBuf + } + + /* + * Need to make sure that buffer isn't trying to write out of bounds. + */ + function checkOffset(offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') + if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') + } + + Buffer.prototype.readUIntLE = function readUIntLE(offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + + return val + } + + Buffer.prototype.readUIntBE = function readUIntBE(offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) { + checkOffset(offset, byteLength, this.length) + } + + var val = this[offset + --byteLength] + var mul = 1 + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul + } + + return val + } + + Buffer.prototype.readUInt8 = function readUInt8(offset, noAssert) { + if (!noAssert) checkOffset(offset, 1, this.length) + return this[offset] + } + + Buffer.prototype.readUInt16LE = function readUInt16LE(offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) + } + + Buffer.prototype.readUInt16BE = function readUInt16BE(offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] + } + + Buffer.prototype.readUInt32LE = function readUInt32LE(offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) + } + + Buffer.prototype.readUInt32BE = function readUInt32BE(offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) + } + + Buffer.prototype.readIntLE = function readIntLE(offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val + } + + Buffer.prototype.readIntBE = function readIntBE(offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var i = byteLength + var mul = 1 + var val = this[offset + --i] + while (i > 0 && (mul *= 0x100)) { + val += this[offset + --i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val + } + + Buffer.prototype.readInt8 = function readInt8(offset, noAssert) { + if (!noAssert) checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) return (this[offset]) + return ((0xff - this[offset] + 1) * -1) + } + + Buffer.prototype.readInt16LE = function readInt16LE(offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val + } + + Buffer.prototype.readInt16BE = function readInt16BE(offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val + } + + Buffer.prototype.readInt32LE = function readInt32LE(offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) + } + + Buffer.prototype.readInt32BE = function readInt32BE(offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) + } + + Buffer.prototype.readFloatLE = function readFloatLE(offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) + } + + Buffer.prototype.readFloatBE = function readFloatBE(offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) + } + + Buffer.prototype.readDoubleLE = function readDoubleLE(offset, noAssert) { + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) + } + + Buffer.prototype.readDoubleBE = function readDoubleBE(offset, noAssert) { + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) + } + + function checkInt(buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance') + if (value > max || value < min) throw new RangeError('value is out of bounds') + if (offset + ext > buf.length) throw new RangeError('index out of range') + } + + Buffer.prototype.writeUIntLE = function writeUIntLE(value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0) + + var mul = 1 + var i = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength + } + + Buffer.prototype.writeUIntBE = function writeUIntBE(value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0) + + var i = byteLength - 1 + var mul = 1 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength + } + + Buffer.prototype.writeUInt8 = function writeUInt8(value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + this[offset] = (value & 0xff) + return offset + 1 + } + + function objectWriteUInt16(buf, value, offset, littleEndian) { + if (value < 0) value = 0xffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) { + buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> + (littleEndian ? i : 1 - i) * 8 + } + } + + Buffer.prototype.writeUInt16LE = function writeUInt16LE(value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + } else { + objectWriteUInt16(this, value, offset, true) + } + return offset + 2 + } + + Buffer.prototype.writeUInt16BE = function writeUInt16BE(value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + } else { + objectWriteUInt16(this, value, offset, false) + } + return offset + 2 + } + + function objectWriteUInt32(buf, value, offset, littleEndian) { + if (value < 0) value = 0xffffffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) { + buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff + } + } + + Buffer.prototype.writeUInt32LE = function writeUInt32LE(value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = (value & 0xff) + } else { + objectWriteUInt32(this, value, offset, true) + } + return offset + 4 + } + + Buffer.prototype.writeUInt32BE = function writeUInt32BE(value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + } else { + objectWriteUInt32(this, value, offset, false) + } + return offset + 4 + } + + Buffer.prototype.writeIntLE = function writeIntLE(value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) { + var limit = Math.pow(2, 8 * byteLength - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = 0 + var mul = 1 + var sub = value < 0 ? 1 : 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength + } + + Buffer.prototype.writeIntBE = function writeIntBE(value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) { + var limit = Math.pow(2, 8 * byteLength - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = byteLength - 1 + var mul = 1 + var sub = value < 0 ? 1 : 0 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength + } + + Buffer.prototype.writeInt8 = function writeInt8(value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + if (value < 0) value = 0xff + value + 1 + this[offset] = (value & 0xff) + return offset + 1 + } + + Buffer.prototype.writeInt16LE = function writeInt16LE(value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + } else { + objectWriteUInt16(this, value, offset, true) + } + return offset + 2 + } + + Buffer.prototype.writeInt16BE = function writeInt16BE(value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + } else { + objectWriteUInt16(this, value, offset, false) + } + return offset + 2 + } + + Buffer.prototype.writeInt32LE = function writeInt32LE(value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + } else { + objectWriteUInt32(this, value, offset, true) + } + return offset + 4 + } + + Buffer.prototype.writeInt32BE = function writeInt32BE(value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + } else { + objectWriteUInt32(this, value, offset, false) + } + return offset + 4 + } + + function checkIEEE754(buf, value, offset, ext, max, min) { + if (value > max || value < min) throw new RangeError('value is out of bounds') + if (offset + ext > buf.length) throw new RangeError('index out of range') + if (offset < 0) throw new RangeError('index out of range') + } + + function writeFloat(buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + } + ieee754.write(buf, value, offset, littleEndian, 23, 4) + return offset + 4 + } + + Buffer.prototype.writeFloatLE = function writeFloatLE(value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) + } + + Buffer.prototype.writeFloatBE = function writeFloatBE(value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) + } + + function writeDouble(buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) + } + ieee754.write(buf, value, offset, littleEndian, 52, 8) + return offset + 8 + } + + Buffer.prototype.writeDoubleLE = function writeDoubleLE(value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) + } + + Buffer.prototype.writeDoubleBE = function writeDoubleBE(value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) + } + + // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) + Buffer.prototype.copy = function copy(target, targetStart, start, end) { + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (targetStart >= target.length) targetStart = target.length + if (!targetStart) targetStart = 0 + if (end > 0 && end < start) end = start + + // Copy 0 bytes; we're done + if (end === start) return 0 + if (target.length === 0 || this.length === 0) return 0 + + // Fatal error conditions + if (targetStart < 0) { + throw new RangeError('targetStart out of bounds') + } + if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') + if (end < 0) throw new RangeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) end = this.length + if (target.length - targetStart < end - start) { + end = target.length - targetStart + start + } + + var len = end - start + var i + + if (this === target && start < targetStart && targetStart < end) { + // descending copy from end + for (i = len - 1; i >= 0; i--) { + target[i + targetStart] = this[i + start] + } + } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { + // ascending copy from start + for (i = 0; i < len; i++) { + target[i + targetStart] = this[i + start] + } + } else { + target._set(this.subarray(start, start + len), targetStart) + } + + return len + } + + // fill(value, start=0, end=buffer.length) + Buffer.prototype.fill = function fill(value, start, end) { + if (!value) value = 0 + if (!start) start = 0 + if (!end) end = this.length + + if (end < start) throw new RangeError('end < start') + + // Fill 0 bytes; we're done + if (end === start) return + if (this.length === 0) return + + if (start < 0 || start >= this.length) throw new RangeError('start out of bounds') + if (end < 0 || end > this.length) throw new RangeError('end out of bounds') + + var i + if (typeof value === 'number') { + for (i = start; i < end; i++) { + this[i] = value + } + } else { + var bytes = utf8ToBytes(value.toString()) + var len = bytes.length + for (i = start; i < end; i++) { + this[i] = bytes[i % len] + } + } + + return this + } + + /** + * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. + * Added in Node 0.12. Only available in browsers that support ArrayBuffer. + */ + Buffer.prototype.toArrayBuffer = function toArrayBuffer() { + if (typeof Uint8Array !== 'undefined') { + if (Buffer.TYPED_ARRAY_SUPPORT) { + return (new Buffer(this)).buffer + } else { + var buf = new Uint8Array(this.length) + for (var i = 0, len = buf.length; i < len; i += 1) { + buf[i] = this[i] + } + return buf.buffer + } + } else { + throw new TypeError('Buffer.toArrayBuffer not supported in this browser') + } + } + + // HELPER FUNCTIONS + // ================ + + var BP = Buffer.prototype + + /** + * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods + */ + Buffer._augment = function _augment(arr) { + arr.constructor = Buffer + arr._isBuffer = true + + // save reference to original Uint8Array set method before overwriting + arr._set = arr.set + + // deprecated + arr.get = BP.get + arr.set = BP.set + + arr.write = BP.write + arr.toString = BP.toString + arr.toLocaleString = BP.toString + arr.toJSON = BP.toJSON + arr.equals = BP.equals + arr.compare = BP.compare + arr.indexOf = BP.indexOf + arr.copy = BP.copy + arr.slice = BP.slice + arr.readUIntLE = BP.readUIntLE + arr.readUIntBE = BP.readUIntBE + arr.readUInt8 = BP.readUInt8 + arr.readUInt16LE = BP.readUInt16LE + arr.readUInt16BE = BP.readUInt16BE + arr.readUInt32LE = BP.readUInt32LE + arr.readUInt32BE = BP.readUInt32BE + arr.readIntLE = BP.readIntLE + arr.readIntBE = BP.readIntBE + arr.readInt8 = BP.readInt8 + arr.readInt16LE = BP.readInt16LE + arr.readInt16BE = BP.readInt16BE + arr.readInt32LE = BP.readInt32LE + arr.readInt32BE = BP.readInt32BE + arr.readFloatLE = BP.readFloatLE + arr.readFloatBE = BP.readFloatBE + arr.readDoubleLE = BP.readDoubleLE + arr.readDoubleBE = BP.readDoubleBE + arr.writeUInt8 = BP.writeUInt8 + arr.writeUIntLE = BP.writeUIntLE + arr.writeUIntBE = BP.writeUIntBE + arr.writeUInt16LE = BP.writeUInt16LE + arr.writeUInt16BE = BP.writeUInt16BE + arr.writeUInt32LE = BP.writeUInt32LE + arr.writeUInt32BE = BP.writeUInt32BE + arr.writeIntLE = BP.writeIntLE + arr.writeIntBE = BP.writeIntBE + arr.writeInt8 = BP.writeInt8 + arr.writeInt16LE = BP.writeInt16LE + arr.writeInt16BE = BP.writeInt16BE + arr.writeInt32LE = BP.writeInt32LE + arr.writeInt32BE = BP.writeInt32BE + arr.writeFloatLE = BP.writeFloatLE + arr.writeFloatBE = BP.writeFloatBE + arr.writeDoubleLE = BP.writeDoubleLE + arr.writeDoubleBE = BP.writeDoubleBE + arr.fill = BP.fill + arr.inspect = BP.inspect + arr.toArrayBuffer = BP.toArrayBuffer + + return arr + } + + var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g + + function base64clean(str) { + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = stringtrim(str).replace(INVALID_BASE64_RE, '') + // Node converts strings with length < 2 to '' + if (str.length < 2) return '' + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '=' + } + return str + } + + function stringtrim(str) { + if (str.trim) return str.trim() + return str.replace(/^\s+|\s+$/g, '') + } + + function toHex(n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) + } + + function utf8ToBytes(string, units) { + units = units || Infinity + var codePoint + var length = string.length + var leadSurrogate = null + var bytes = [] + + for (var i = 0; i < length; i++) { + codePoint = string.charCodeAt(i) + + // is surrogate component + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (!leadSurrogate) { + // no lead yet + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } + + // valid lead + leadSurrogate = codePoint + + continue + } + + // 2 leads in a row + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + leadSurrogate = codePoint + continue + } + + // valid surrogate pair + codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + } + + leadSurrogate = null + + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break + bytes.push(codePoint) + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break + bytes.push( + codePoint >> 0x6 | 0xC0, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break + bytes.push( + codePoint >> 0xC | 0xE0, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x110000) { + if ((units -= 4) < 0) break + bytes.push( + codePoint >> 0x12 | 0xF0, + codePoint >> 0xC & 0x3F | 0x80, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else { + throw new Error('Invalid code point') + } + } + + return bytes + } + + function asciiToBytes(str) { + var byteArray = [] + for (var i = 0; i < str.length; i++) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray + } + + function utf16leToBytes(str, units) { + var c, hi, lo + var byteArray = [] + for (var i = 0; i < str.length; i++) { + if ((units -= 2) < 0) break + + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } + + return byteArray + } + + function base64ToBytes(str) { + return base64.toByteArray(base64clean(str)) + } + + function blitBuffer(src, dst, offset, length) { + for (var i = 0; i < length; i++) { + if ((i + offset >= dst.length) || (i >= src.length)) break + dst[i + offset] = src[i] + } + return i + } + + /* WEBPACK VAR INJECTION */ +}.call(exports, __webpack_require__(5).Buffer, (function () { return this }()))) + + /***/ +}, +/* 6 */ +/***/ function (module, exports, __webpack_require__) { + + var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + + ; (function (exports) { + 'use strict' + + var Arr = (typeof Uint8Array !== 'undefined') + ? Uint8Array + : Array + + var PLUS = '+'.charCodeAt(0) + var SLASH = '/'.charCodeAt(0) + var NUMBER = '0'.charCodeAt(0) + var LOWER = 'a'.charCodeAt(0) + var UPPER = 'A'.charCodeAt(0) + var PLUS_URL_SAFE = '-'.charCodeAt(0) + var SLASH_URL_SAFE = '_'.charCodeAt(0) + + function decode(elt) { + var code = elt.charCodeAt(0) + if (code === PLUS || + code === PLUS_URL_SAFE) + return 62 // '+' + if (code === SLASH || + code === SLASH_URL_SAFE) + return 63 // '/' + if (code < NUMBER) + return -1 //no match + if (code < NUMBER + 10) + return code - NUMBER + 26 + 26 + if (code < UPPER + 26) + return code - UPPER + if (code < LOWER + 26) + return code - LOWER + 26 + } + + function b64ToByteArray(b64) { + var i, j, l, tmp, placeHolders, arr + + if (b64.length % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // the number of equal signs (place holders) + // if there are two placeholders, than the two characters before it + // represent one byte + // if there is only one, then the three characters before it represent 2 bytes + // this is just a cheap hack to not do indexOf twice + var len = b64.length + placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0 + + // base64 is 4/3 + up to two characters of the original data + arr = new Arr(b64.length * 3 / 4 - placeHolders) + + // if there are placeholders, only get up to the last complete 4 chars + l = placeHolders > 0 ? b64.length - 4 : b64.length + + var L = 0 + + function push(v) { + arr[L++] = v + } + + for (i = 0, j = 0; i < l; i += 4, j += 3) { + tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) + push((tmp & 0xFF0000) >> 16) + push((tmp & 0xFF00) >> 8) + push(tmp & 0xFF) + } + + if (placeHolders === 2) { + tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) + push(tmp & 0xFF) + } else if (placeHolders === 1) { + tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) + push((tmp >> 8) & 0xFF) + push(tmp & 0xFF) + } + + return arr + } + + function uint8ToBase64(uint8) { + var i, + extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes + output = "", + temp, length + + function encode(num) { + return lookup.charAt(num) + } + + function tripletToBase64(num) { + return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) + } + + // go through the array every three bytes, we'll deal with trailing stuff later + for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { + temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) + output += tripletToBase64(temp) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + switch (extraBytes) { + case 1: + temp = uint8[uint8.length - 1] + output += encode(temp >> 2) + output += encode((temp << 4) & 0x3F) + output += '==' + break + case 2: + temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) + output += encode(temp >> 10) + output += encode((temp >> 4) & 0x3F) + output += encode((temp << 2) & 0x3F) + output += '=' + break + } + + return output + } + + exports.toByteArray = b64ToByteArray + exports.fromByteArray = uint8ToBase64 + }(false ? (this.base64js = {}) : exports)) + + + /***/ +}, +/* 7 */ +/***/ function (module, exports) { + + exports.read = function (buffer, offset, isLE, mLen, nBytes) { + var e, m + var eLen = nBytes * 8 - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var nBits = -7 + var i = isLE ? (nBytes - 1) : 0 + var d = isLE ? -1 : 1 + var s = buffer[offset + i] + + i += d + + e = s & ((1 << (-nBits)) - 1) + s >>= (-nBits) + nBits += eLen + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) { } + + m = e & ((1 << (-nBits)) - 1) + e >>= (-nBits) + nBits += mLen + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) { } + + if (e === 0) { + e = 1 - eBias + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity) + } else { + m = m + Math.pow(2, mLen) + e = e - eBias + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen) + } + + exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c + var eLen = nBytes * 8 - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) + var i = isLE ? 0 : (nBytes - 1) + var d = isLE ? 1 : -1 + var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 + + value = Math.abs(value) + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0 + e = eMax + } else { + e = Math.floor(Math.log(value) / Math.LN2) + if (value * (c = Math.pow(2, -e)) < 1) { + e-- + c *= 2 + } + if (e + eBias >= 1) { + value += rt / c + } else { + value += rt * Math.pow(2, 1 - eBias) + } + if (value * c >= 2) { + e++ + c /= 2 + } + + if (e + eBias >= eMax) { + m = 0 + e = eMax + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen) + e = e + eBias + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) + e = 0 + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) { } + + e = (e << mLen) | m + eLen += mLen + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) { } + + buffer[offset + i - d] |= s * 128 + } + + + /***/ +}, +/* 8 */ +/***/ function (module, exports) { + + var toString = {}.toString + + module.exports = Array.isArray || function (arr) { + return toString.call(arr) == '[object Array]' + } + + + /***/ +}, +/* 9 */ +/***/ function (module, exports) { + + // Copyright Joyent, Inc. and other Node contributors. + // + // 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. + + function EventEmitter() { + this._events = this._events || {} + this._maxListeners = this._maxListeners || undefined + } + module.exports = EventEmitter + + // Backwards-compat with node 0.10.x + EventEmitter.EventEmitter = EventEmitter + + EventEmitter.prototype._events = undefined + EventEmitter.prototype._maxListeners = undefined + + // By default EventEmitters will print a warning if more than 10 listeners are + // added to it. This is a useful default which helps finding memory leaks. + EventEmitter.defaultMaxListeners = 10 + + // Obviously not all Emitters should be limited to 10. This function allows + // that to be increased. Set to zero for unlimited. + EventEmitter.prototype.setMaxListeners = function (n) { + if (!isNumber(n) || n < 0 || isNaN(n)) + throw TypeError('n must be a positive number') + this._maxListeners = n + return this + } + + EventEmitter.prototype.emit = function (type) { + var er, handler, len, args, i, listeners + + if (!this._events) + this._events = {} + + // If there is no 'error' event listener then throw. + if (type === 'error') { + if (!this._events.error || + (isObject(this._events.error) && !this._events.error.length)) { + er = arguments[1] + if (er instanceof Error) { + throw er // Unhandled 'error' event + } else { + // At least give some kind of context to the user + var err = new Error('Uncaught, unspecified "error" event. (' + er + ')') + err.context = er + throw err + } + } + } + + handler = this._events[type] + + if (isUndefined(handler)) + return false + + if (isFunction(handler)) { + switch (arguments.length) { + // fast cases + case 1: + handler.call(this) + break + case 2: + handler.call(this, arguments[1]) + break + case 3: + handler.call(this, arguments[1], arguments[2]) + break + // slower + default: + args = Array.prototype.slice.call(arguments, 1) + handler.apply(this, args) + } + } else if (isObject(handler)) { + args = Array.prototype.slice.call(arguments, 1) + listeners = handler.slice() + len = listeners.length + for (i = 0; i < len; i++) + listeners[i].apply(this, args) + } + + return true + } + + EventEmitter.prototype.addListener = function (type, listener) { + var m + + if (!isFunction(listener)) + throw TypeError('listener must be a function') + + if (!this._events) + this._events = {} + + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (this._events.newListener) + this.emit('newListener', type, + isFunction(listener.listener) ? + listener.listener : listener) + + if (!this._events[type]) + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener + else if (isObject(this._events[type])) + // If we've already got an array, just append. + this._events[type].push(listener) + else + // Adding the second element, need to change to array. + this._events[type] = [this._events[type], listener] + + // Check for listener leak + if (isObject(this._events[type]) && !this._events[type].warned) { + if (!isUndefined(this._maxListeners)) { + m = this._maxListeners + } else { + m = EventEmitter.defaultMaxListeners + } + + if (m && m > 0 && this._events[type].length > m) { + this._events[type].warned = true + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length) + if (typeof console.trace === 'function') { + // not supported in IE 10 + console.trace() + } + } + } + + return this + } + + EventEmitter.prototype.on = EventEmitter.prototype.addListener + + EventEmitter.prototype.once = function (type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function') + + var fired = false + + function g() { + this.removeListener(type, g) + + if (!fired) { + fired = true + listener.apply(this, arguments) + } + } + + g.listener = listener + this.on(type, g) + + return this + } + + // emits a 'removeListener' event iff the listener was removed + EventEmitter.prototype.removeListener = function (type, listener) { + var list, position, length, i + + if (!isFunction(listener)) + throw TypeError('listener must be a function') + + if (!this._events || !this._events[type]) + return this + + list = this._events[type] + length = list.length + position = -1 + + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type] + if (this._events.removeListener) + this.emit('removeListener', type, listener) + + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i + break + } + } + + if (position < 0) + return this + + if (list.length === 1) { + list.length = 0 + delete this._events[type] + } else { + list.splice(position, 1) + } + + if (this._events.removeListener) + this.emit('removeListener', type, listener) + } + + return this + } + + EventEmitter.prototype.removeAllListeners = function (type) { + var key, listeners + + if (!this._events) + return this + + // not listening for removeListener, no need to emit + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {} + else if (this._events[type]) + delete this._events[type] + return this + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue + this.removeAllListeners(key) + } + this.removeAllListeners('removeListener') + this._events = {} + return this + } + + listeners = this._events[type] + + if (isFunction(listeners)) { + this.removeListener(type, listeners) + } else if (listeners) { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]) + } + delete this._events[type] + + return this + } + + EventEmitter.prototype.listeners = function (type) { + var ret + if (!this._events || !this._events[type]) + ret = [] + else if (isFunction(this._events[type])) + ret = [this._events[type]] + else + ret = this._events[type].slice() + return ret + } + + EventEmitter.prototype.listenerCount = function (type) { + if (this._events) { + var evlistener = this._events[type] + + if (isFunction(evlistener)) + return 1 + else if (evlistener) + return evlistener.length + } + return 0 + } + + EventEmitter.listenerCount = function (emitter, type) { + return emitter.listenerCount(type) + } + + function isFunction(arg) { + return typeof arg === 'function' + } + + function isNumber(arg) { + return typeof arg === 'number' + } + + function isObject(arg) { + return typeof arg === 'object' && arg !== null + } + + function isUndefined(arg) { + return arg === void 0 + } + + + /***/ +}, +/* 10 */ +/***/ function (module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function (global, process) {// Copyright Joyent, Inc. and other Node contributors. + // + // 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. + + var formatRegExp = /%[sdj%]/g + exports.format = function (f) { + if (!isString(f)) { + var objects = [] + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])) + } + return objects.join(' ') + } + + var i = 1 + var args = arguments + var len = args.length + var str = String(f).replace(formatRegExp, function (x) { + if (x === '%%') return '%' + if (i >= len) return x + switch (x) { + case '%s': return String(args[i++]) + case '%d': return Number(args[i++]) + case '%j': + try { + return JSON.stringify(args[i++]) + } catch (_) { + return '[Circular]' + } + default: + return x + } + }) + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x + } else { + str += ' ' + inspect(x) + } + } + return str + } + + + // Mark that a method should not be used. + // Returns a modified function which warns once by default. + // If --no-deprecation is set, then it is a no-op. + exports.deprecate = function (fn, msg) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(global.process)) { + return function () { + return exports.deprecate(fn, msg).apply(this, arguments) + } + } + + if (process.noDeprecation === true) { + return fn + } + + var warned = false + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg) + } else if (process.traceDeprecation) { + console.trace(msg) + } else { + console.error(msg) + } + warned = true + } + return fn.apply(this, arguments) + } + + return deprecated + } + + + var debugs = {} + var debugEnviron + exports.debuglog = function (set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || '' + set = set.toUpperCase() + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + var pid = process.pid + debugs[set] = function () { + var msg = exports.format.apply(exports, arguments) + console.error('%s %d: %s', set, pid, msg) + } + } else { + debugs[set] = function () { } + } + } + return debugs[set] + } + + + /** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ + /* legacy: obj, showHidden, depth, colors*/ + function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + } + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2] + if (arguments.length >= 4) ctx.colors = arguments[3] + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts) + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false + if (isUndefined(ctx.depth)) ctx.depth = 2 + if (isUndefined(ctx.colors)) ctx.colors = false + if (isUndefined(ctx.customInspect)) ctx.customInspect = true + if (ctx.colors) ctx.stylize = stylizeWithColor + return formatValue(ctx, obj, ctx.depth) + } + exports.inspect = inspect + + + // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics + inspect.colors = { + 'bold': [1, 22], + 'italic': [3, 23], + 'underline': [4, 24], + 'inverse': [7, 27], + 'white': [37, 39], + 'grey': [90, 39], + 'black': [30, 39], + 'blue': [34, 39], + 'cyan': [36, 39], + 'green': [32, 39], + 'magenta': [35, 39], + 'red': [31, 39], + 'yellow': [33, 39] + } + + // Don't use 'blue' not visible on cmd.exe + inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' + } + + + function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType] + + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm' + } else { + return str + } + } + + + function stylizeNoColor(str, styleType) { + return str + } + + + function arrayToHash(array) { + var hash = {} + + array.forEach(function (val, idx) { + hash[val] = true + }) + + return hash + } + + + function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes, ctx) + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes) + } + return ret + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value) + if (primitive) { + return primitive + } + + // Look up the keys of the object. + var keys = Object.keys(value) + var visibleKeys = arrayToHash(keys) + + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value) + } + + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if (isError(value) + && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { + return formatError(value) + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : '' + return ctx.stylize('[Function' + name + ']', 'special') + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp') + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date') + } + if (isError(value)) { + return formatError(value) + } + } + + var base = '', array = false, braces = ['{', '}'] + + // Make Array say that they are Array + if (isArray(value)) { + array = true + braces = ['[', ']'] + } + + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : '' + base = ' [Function' + n + ']' + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value) + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value) + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value) + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1] + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp') + } else { + return ctx.stylize('[Object]', 'special') + } + } + + ctx.seen.push(value) + + var output + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys) + } else { + output = keys.map(function (key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) + }) + } + + ctx.seen.pop() + + return reduceToSingleString(output, base, braces) + } + + + function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined') + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\'' + return ctx.stylize(simple, 'string') + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number') + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean') + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null') + } + + + function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']' + } + + + function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = [] + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)) + } else { + output.push('') + } + } + keys.forEach(function (key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)) + } + }) + return output + } + + + function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] } + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special') + } else { + str = ctx.stylize('[Getter]', 'special') + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special') + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']' + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null) + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1) + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function (line) { + return ' ' + line + }).join('\n').substr(2) + } else { + str = '\n' + str.split('\n').map(function (line) { + return ' ' + line + }).join('\n') + } + } + } else { + str = ctx.stylize('[Circular]', 'special') + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str + } + name = JSON.stringify('' + key) + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2) + name = ctx.stylize(name, 'name') + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'") + name = ctx.stylize(name, 'string') + } + } + + return name + ': ' + str + } + + + function reduceToSingleString(output, base, braces) { + var numLinesEst = 0 + var length = output.reduce(function (prev, cur) { + numLinesEst++ + if (cur.indexOf('\n') >= 0) numLinesEst++ + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1 + }, 0) + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1] + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1] + } + + + // NOTE: These type checking functions intentionally don't use `instanceof` + // because it is fragile and can be easily faked with `Object.create()`. + function isArray(ar) { + return Array.isArray(ar) + } + exports.isArray = isArray + + function isBoolean(arg) { + return typeof arg === 'boolean' + } + exports.isBoolean = isBoolean + + function isNull(arg) { + return arg === null + } + exports.isNull = isNull + + function isNullOrUndefined(arg) { + return arg == null + } + exports.isNullOrUndefined = isNullOrUndefined + + function isNumber(arg) { + return typeof arg === 'number' + } + exports.isNumber = isNumber + + function isString(arg) { + return typeof arg === 'string' + } + exports.isString = isString + + function isSymbol(arg) { + return typeof arg === 'symbol' + } + exports.isSymbol = isSymbol + + function isUndefined(arg) { + return arg === void 0 + } + exports.isUndefined = isUndefined + + function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]' + } + exports.isRegExp = isRegExp + + function isObject(arg) { + return typeof arg === 'object' && arg !== null + } + exports.isObject = isObject + + function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]' + } + exports.isDate = isDate + + function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error) + } + exports.isError = isError + + function isFunction(arg) { + return typeof arg === 'function' + } + exports.isFunction = isFunction + + function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined' + } + exports.isPrimitive = isPrimitive + + exports.isBuffer = __webpack_require__(12) + + function objectToString(o) { + return Object.prototype.toString.call(o) + } + + + function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10) + } + + + var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec'] + + // 26 Feb 16:19:34 + function timestamp() { + var d = new Date() + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':') + return [d.getDate(), months[d.getMonth()], time].join(' ') + } + + + // log is just a thin wrapper to console.log that prepends a timestamp + exports.log = function () { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)) + } + + + /** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ + exports.inherits = __webpack_require__(13) + + exports._extend = function (origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin + + var keys = Object.keys(add) + var i = keys.length + while (i--) { + origin[keys[i]] = add[keys[i]] + } + return origin + } + + function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop) + } + + /* WEBPACK VAR INJECTION */ +}.call(exports, (function () { return this }()), __webpack_require__(11))) + + /***/ +}, +/* 11 */ +/***/ function (module, exports) { + + // shim for using process in browser + var process = module.exports = {} + + // cached from whatever global is present so that test runners that stub it + // don't break things. But we need to wrap it in a try catch in case it is + // wrapped in strict mode code which doesn't define any globals. It's inside a + // function because try/catches deoptimize in certain engines. + + var cachedSetTimeout + var cachedClearTimeout; + + (function () { + try { + cachedSetTimeout = setTimeout + } catch (e) { + cachedSetTimeout = function () { + throw new Error('setTimeout is not defined') + } + } + try { + cachedClearTimeout = clearTimeout + } catch (e) { + cachedClearTimeout = function () { + throw new Error('clearTimeout is not defined') + } + } + }()) + function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0) + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0) + } catch (e) { + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0) + } catch (e) { + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0) + } + } + + + } + function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker) + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker) + } catch (e) { + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker) + } catch (e) { + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker) + } + } + + + + } + var queue = [] + var draining = false + var currentQueue + var queueIndex = -1 + + function cleanUpNextTick() { + if (!draining || !currentQueue) { + return + } + draining = false + if (currentQueue.length) { + queue = currentQueue.concat(queue) + } else { + queueIndex = -1 + } + if (queue.length) { + drainQueue() + } + } + + function drainQueue() { + if (draining) { + return + } + var timeout = runTimeout(cleanUpNextTick) + draining = true + + var len = queue.length + while (len) { + currentQueue = queue + queue = [] + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run() + } + } + queueIndex = -1 + len = queue.length + } + currentQueue = null + draining = false + runClearTimeout(timeout) + } + + process.nextTick = function (fun) { + var args = new Array(arguments.length - 1) + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i] + } + } + queue.push(new Item(fun, args)) + if (queue.length === 1 && !draining) { + runTimeout(drainQueue) + } + } + + // v8 likes predictible objects + function Item(fun, array) { + this.fun = fun + this.array = array + } + Item.prototype.run = function () { + this.fun.apply(null, this.array) + } + process.title = 'browser' + process.browser = true + process.env = {} + process.argv = [] + process.version = '' // empty string to avoid regexp issues + process.versions = {} + + function noop() { } + + process.on = noop + process.addListener = noop + process.once = noop + process.off = noop + process.removeListener = noop + process.removeAllListeners = noop + process.emit = noop + + process.binding = function (name) { + throw new Error('process.binding is not supported') + } + + process.cwd = function () { return '/' } + process.chdir = function (dir) { + throw new Error('process.chdir is not supported') + } + process.umask = function () { return 0 } + + + /***/ +}, +/* 12 */ +/***/ function (module, exports) { + + module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function' + } + + /***/ +}, +/* 13 */ +/***/ function (module, exports) { + + if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }) + } + } else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () { } + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } + } + + + /***/ +}, +/* 14 */ +/***/ function (module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function (module, process) {/* + * prompt.js: Simple prompt for prompting information from the command line + * + * (C) 2010, Nodejitsu Inc. + * + */ + + var events = __webpack_require__(9), + readline = __webpack_require__(4), + utile = __webpack_require__(16), + async = utile.async, + read = __webpack_require__(53), + validate = __webpack_require__(72).validate, + winston = __webpack_require__(73), + colors = __webpack_require__(147) + + // + // Monkey-punch readline.Interface to work-around + // https://github.com/joyent/node/issues/3860 + // + readline.Interface.prototype.setPrompt = function (prompt, length) { + this._prompt = prompt + if (length) { + this._promptLength = length + } else { + var lines = prompt.split(/[\r\n]/) + var lastLine = lines[lines.length - 1] + this._promptLength = lastLine.replace(/\u001b\[(\d+(;\d+)*)?m/g, '').length + } + } + + // + // Expose version using `pkginfo` + // + __webpack_require__(160)(module, 'version') + + var stdin, stdout, history = [] + var prompt = module.exports = Object.create(events.EventEmitter.prototype) + var logger = prompt.logger = new winston.Logger({ + transports: [new (winston.transports.Console)()] + }) + + prompt.started = false + prompt.paused = false + prompt.stopped = true + prompt.allowEmpty = false + prompt.message = 'prompt' + prompt.delimiter = ': ' + prompt.colors = true + + // + // Create an empty object for the properties + // known to `prompt` + // + prompt.properties = {} + + // + // Setup the default winston logger to use + // the `cli` levels and colors. + // + logger.cli() + + // + // ### function start (options) + // #### @options {Object} **Optional** Options to consume by prompt + // Starts the prompt by listening to the appropriate events on `options.stdin` + // and `options.stdout`. If no streams are supplied, then `process.stdin` + // and `process.stdout` are used, respectively. + // + prompt.start = function (options) { + if (prompt.started) { + return + } + + options = options || {} + stdin = options.stdin || process.stdin + stdout = options.stdout || process.stdout + + // + // By default: Remember the last `10` prompt property / + // answer pairs and don't allow empty responses globally. + // + prompt.memory = options.memory || 10 + prompt.allowEmpty = options.allowEmpty || false + prompt.message = options.message || prompt.message + prompt.delimiter = options.delimiter || prompt.delimiter + prompt.colors = options.colors || prompt.colors + + if (process.platform !== 'win32') { + // windows falls apart trying to deal with SIGINT + process.on('SIGINT', function () { + stdout.write('\n') + process.exit(1) + }) + } + + prompt.emit('start') + prompt.started = true + prompt.stopped = false + return prompt + } + + // + // ### function pause () + // Pauses input coming in from stdin + // + prompt.pause = function () { + if (!prompt.started || prompt.stopped || prompt.paused) { + return + } + + stdin.pause() + prompt.emit('pause') + prompt.paused = true + return prompt + } + + // + // ### function stop () + // Stops input coming in from stdin + // + prompt.stop = function () { + if (prompt.stopped || !prompt.started) { + return + } + + stdin.destroy() + prompt.emit('stop') + prompt.stopped = true + prompt.started = false + prompt.paused = false + return prompt + } + + // + // ### function resume () + // Resumes input coming in from stdin + // + prompt.resume = function () { + if (!prompt.started || !prompt.paused) { + return + } + + stdin.resume() + prompt.emit('resume') + prompt.paused = false + return prompt + } + + // + // ### function history (search) + // #### @search {Number|string} Index or property name to find. + // Returns the `property:value` pair from within the prompts + // `history` array. + // + prompt.history = function (search) { + if (typeof search === 'number') { + return history[search] || {} + } + + var names = history.map(function (pair) { + return typeof pair.property === 'string' + ? pair.property + : pair.property.name + }) + + if (!~names.indexOf(search)) { + return null + } + + return history.filter(function (pair) { + return typeof pair.property === 'string' + ? pair.property === search + : pair.property.name === search + })[0] + } + + // + // ### function get (schema, callback) + // #### @schema {Array|Object|string} Set of variables to get input for. + // #### @callback {function} Continuation to pass control to when complete. + // Gets input from the user via stdin for the specified message(s) `msg`. + // + prompt.get = function (schema, callback) { + // + // Transforms a full JSON-schema into an array describing path and sub-schemas. + // Used for iteration purposes. + // + function untangle(schema, path) { + var results = [] + path = path || [] + + if (schema.properties) { + // + // Iterate over the properties in the schema and use recursion + // to process sub-properties. + // + Object.keys(schema.properties).forEach(function (key) { + var obj = {} + obj[key] = schema.properties[key] + + // + // Concat a sub-untangling to the results. + // + results = results.concat(untangle(obj[key], path.concat(key))) + }) + + // Return the results. + return results + } + + // + // This is a schema "leaf". + // + return { + path: path, + schema: schema + } + } + + // + // Iterate over the values in the schema, represented as + // a legit single-property object subschemas. Accepts `schema` + // of the forms: + // + // 'prop-name' + // + // ['string-name', { path: ['or-well-formed-subschema'], properties: ... }] + // + // { path: ['or-well-formed-subschema'], properties: ... ] } + // + // { properties: { 'schema-with-no-path' } } + // + // And transforms them all into + // + // { path: ['path', 'to', 'property'], properties: { path: { to: ...} } } + // + function iterate(schema, get, done) { + var iterator = [], + result = {} + + if (typeof schema === 'string') { + // + // We can iterate over a single string. + // + iterator.push({ + path: [schema], + schema: prompt.properties[schema.toLowerCase()] || {} + }) + } + else if (Array.isArray(schema)) { + // + // An array of strings and/or single-prop schema and/or no-prop schema. + // + iterator = schema.map(function (element) { + if (typeof element === 'string') { + return { + path: [element], + schema: prompt.properties[element.toLowerCase()] || {} + } + } + else if (element.properties) { + return { + path: [Object.keys(element.properties)[0]], + schema: element.properties[Object.keys(element.properties)[0]] + } + } + else if (element.path && element.schema) { + return element + } + else { + return { + path: [element.name || 'question'], + schema: element + } + } + }) + } + else if (schema.properties) { + // + // Or a complete schema `untangle` it for use. + // + iterator = untangle(schema) + } + else { + // + // Or a partial schema and path. + // TODO: Evaluate need for this option. + // + iterator = [{ + schema: schema.schema ? schema.schema : schema, + path: schema.path || [schema.name || 'question'] + }] + } + + // + // Now, iterate and assemble the result. + // + async.forEachSeries(iterator, function (branch, next) { + get(branch, function assembler(err, line) { + if (err) { + return next(err) + } + + function build(path, line) { + var obj = {} + if (path.length) { + obj[path[0]] = build(path.slice(1), line) + return obj + } + + return line + } + + function attach(obj, attr) { + var keys + if (typeof attr !== 'object' || attr instanceof Array) { + return attr + } + + keys = Object.keys(attr) + if (keys.length) { + if (!obj[keys[0]]) { + obj[keys[0]] = {} + } + obj[keys[0]] = attach(obj[keys[0]], attr[keys[0]]) + } + + return obj + } + + result = attach(result, build(branch.path, line)) + next() + }) + }, function (err) { + return err ? done(err) : done(null, result) + }) + } + + iterate(schema, function get(target, next) { + prompt.getInput(target, function (err, line) { + return err ? next(err) : next(null, line) + }) + }, callback) + + return prompt + } + + // + // ### function confirm (msg, callback) + // #### @msg {Array|Object|string} set of message to confirm + // #### @callback {function} Continuation to pass control to when complete. + // Confirms a single or series of messages by prompting the user for a Y/N response. + // Returns `true` if ALL messages are answered in the affirmative, otherwise `false` + // + // `msg` can be a string, or object (or array of strings/objects). + // An object may have the following properties: + // + // { + // description: 'yes/no' // message to prompt user + // pattern: /^[yntf]{1}/i // optional - regex defining acceptable responses + // yes: /^[yt]{1}/i // optional - regex defining `affirmative` responses + // message: 'yes/no' // optional - message to display for invalid responses + // } + // + prompt.confirm = function (/* msg, options, callback */) { + var args = Array.prototype.slice.call(arguments), + msg = args.shift(), + callback = args.pop(), + opts = args.shift(), + vars = !Array.isArray(msg) ? [msg] : msg, + RX_Y = /^[yt]{1}/i, + RX_YN = /^[yntf]{1}/i + + function confirm(target, next) { + var yes = target.yes || RX_Y, + options = utile.mixin({ + description: typeof target === 'string' ? target : target.description || 'yes/no', + pattern: target.pattern || RX_YN, + name: 'confirm', + message: target.message || 'yes/no' + }, opts || {}) + + + prompt.get([options], function (err, result) { + next(err ? false : yes.test(result[options.name])) + }) + } + + async.rejectSeries(vars, confirm, function (result) { + callback(null, result.length === 0) + }) + } + + + // Variables needed outside of getInput for multiline arrays. + var tmp = [] + + + // ### function getInput (prop, callback) + // #### @prop {Object|string} Variable to get input for. + // #### @callback {function} Continuation to pass control to when complete. + // Gets input from the user via stdin for the specified message `msg`. + // + prompt.getInput = function (prop, callback) { + var schema = prop.schema || prop, + propName = prop.path && prop.path.join(':') || prop, + storedSchema = prompt.properties[propName.toLowerCase()], + delim = prompt.delimiter, + defaultLine, + against, + hidden, + length, + valid, + name, + raw, + msg + + // + // If there is a stored schema for `propName` in `propmpt.properties` + // then use it. + // + if (schema instanceof Object && !Object.keys(schema).length && + typeof storedSchema !== 'undefined') { + schema = storedSchema + } + + // + // Build a proper validation schema if we just have a string + // and no `storedSchema`. + // + if (typeof prop === 'string' && !storedSchema) { + schema = {} + } + + schema = convert(schema) + defaultLine = schema.default + name = prop.description || schema.description || propName + raw = prompt.colors + ? [colors.grey(name), colors.grey(delim)] + : [name, delim] + + if (prompt.message) + raw.unshift(prompt.message, delim) + + prop = { + schema: schema, + path: propName.split(':') + } + + // + // If the schema has no `properties` value then set + // it to an object containing the current schema + // for `propName`. + // + if (!schema.properties) { + schema = (function () { + var obj = { properties: {} } + obj.properties[propName] = schema + return obj + })() + } + + // + // Handle overrides here. + // TODO: Make overrides nestable + // + if (prompt.override && prompt.override[propName]) { + if (prompt._performValidation(name, prop, prompt.override, schema, -1, callback)) { + return callback(null, prompt.override[propName]) + } + + delete prompt.override[propName] + } + + // + // Check if we should skip this prompt + // + if (typeof prop.schema.ask === 'function' && + !prop.schema.ask()) { + return callback(null, prop.schema.default || '') + } + + var type = (schema.properties && schema.properties[propName] && + schema.properties[propName].type || '').toLowerCase().trim(), + wait = type === 'array' + + if (type === 'array') { + length = prop.schema.maxItems + if (length) { + msg = (tmp.length + 1).toString() + '/' + length.toString() + } + else { + msg = (tmp.length + 1).toString() + } + msg += delim + raw.push(prompt.colors ? msg.grey : msg) + } + + // + // Calculate the raw length and colorize the prompt + // + length = raw.join('').length + raw[0] = raw[0] + msg = raw.join('') + + if (schema.help) { + schema.help.forEach(function (line) { + logger.help(line) + }) + } + + // + // Emit a "prompting" event + // + prompt.emit('prompt', prop) + + // + // If there is no default line, set it to an empty string + // + if (typeof defaultLine === 'undefined') { + defaultLine = '' + } + + // + // set to string for readline ( will not accept Numbers ) + // + defaultLine = defaultLine.toString() + + // + // Make the actual read + // + read({ + prompt: msg, + silent: prop.schema && prop.schema.hidden, + replace: prop.schema && prop.schema.replace, + default: defaultLine, + input: stdin, + output: stdout + }, function (err, line) { + if (err && wait === false) { + return callback(err) + } + + var against = {}, + numericInput, + isValid + + if (line !== '') { + + if (schema.properties[propName]) { + var type = (schema.properties[propName].type || '').toLowerCase().trim() || undefined + + // + // If type is some sort of numeric create a Number object to pass to revalidator + // + if (type === 'number' || type === 'integer') { + line = Number(line) + } + + // + // Attempt to parse input as a boolean if the schema expects a boolean + // + if (type == 'boolean') { + if (line.toLowerCase() === "true" || line.toLowerCase() === 't') { + line = true + } else if (line.toLowerCase() === "false" || line.toLowerCase() === 'f') { + line = false + } + } + + // + // If the type is an array, wait for the end. Fixes #54 + // + if (type == 'array') { + var length = prop.schema.maxItems + if (err) { + if (err.message == 'canceled') { + wait = false + stdout.write('\n') + } + } + else { + if (length) { + if (tmp.length + 1 < length) { + isValid = false + wait = true + } + else { + isValid = true + wait = false + } + } + else { + isValid = false + wait = true + } + tmp.push(line) + } + line = tmp + } + } + + against[propName] = line + } + + if (prop && prop.schema.before) { + line = prop.schema.before(line) + } + + // Validate + if (isValid === undefined) isValid = prompt._performValidation(name, prop, against, schema, line, callback) + + if (!isValid) { + return prompt.getInput(prop, callback) + } + + // + // Log the resulting line, append this `property:value` + // pair to the history for `prompt` and respond to + // the callback. + // + logger.input(line.yellow) + prompt._remember(propName, line) + callback(null, line) + + // Make sure `tmp` is emptied + tmp = [] + }) + } + + // + // ### function performValidation (name, prop, against, schema, line, callback) + // #### @name {Object} Variable name + // #### @prop {Object|string} Variable to get input for. + // #### @against {Object} Input + // #### @schema {Object} Validation schema + // #### @line {String|Boolean} Input line + // #### @callback {function} Continuation to pass control to when complete. + // Perfoms user input validation, print errors if needed and returns value according to validation + // + prompt._performValidation = function (name, prop, against, schema, line, callback) { + var numericInput, valid, msg + try { + valid = validate(against, schema) + } + catch (err) { + return (line !== -1) ? callback(err) : false + } + + if (!valid.valid) { + if (prop.schema.message) { + logger.error(prop.schema.message) + } else { + msg = line !== -1 ? 'Invalid input for ' : 'Invalid command-line input for ' + + if (prompt.colors) { + logger.error(msg + name.grey) + } + else { + logger.error(msg + name) + } + } + + prompt.emit('invalid', prop, line) + } + + return valid.valid + } + + // + // ### function addProperties (obj, properties, callback) + // #### @obj {Object} Object to add properties to + // #### @properties {Array} List of properties to get values for + // #### @callback {function} Continuation to pass control to when complete. + // Prompts the user for values each of the `properties` if `obj` does not already + // have a value for the property. Responds with the modified object. + // + prompt.addProperties = function (obj, properties, callback) { + properties = properties.filter(function (prop) { + return typeof obj[prop] === 'undefined' + }) + + if (properties.length === 0) { + return callback(obj) + } + + prompt.get(properties, function (err, results) { + if (err) { + return callback(err) + } + else if (!results) { + return callback(null, obj) + } + + function putNested(obj, path, value) { + var last = obj, key + + while (path.length > 1) { + key = path.shift() + if (!last[key]) { + last[key] = {} + } + + last = last[key] + } + + last[path.shift()] = value + } + + Object.keys(results).forEach(function (key) { + putNested(obj, key.split('.'), results[key]) + }) + + callback(null, obj) + }) + + return prompt + } + + // + // ### @private function _remember (property, value) + // #### @property {Object|string} Property that the value is in response to. + // #### @value {string} User input captured by `prompt`. + // Prepends the `property:value` pair into the private `history` Array + // for `prompt` so that it can be accessed later. + // + prompt._remember = function (property, value) { + history.unshift({ + property: property, + value: value + }) + + // + // If the length of the `history` Array + // has exceeded the specified length to remember, + // `prompt.memory`, truncate it. + // + if (history.length > prompt.memory) { + history.splice(prompt.memory, history.length - prompt.memory) + } + } + + // + // ### @private function convert (schema) + // #### @schema {Object} Schema for a property + // Converts the schema into new format if it is in old format + // + function convert(schema) { + var newProps = Object.keys(validate.messages), + newSchema = false, + key + + newProps = newProps.concat(['description', 'dependencies']) + + for (key in schema) { + if (newProps.indexOf(key) > 0) { + newSchema = true + break + } + } + + if (!newSchema || schema.validator || schema.warning || typeof schema.empty !== 'undefined') { + schema.description = schema.message + schema.message = schema.warning + + if (typeof schema.validator === 'function') { + schema.conform = schema.validator + } else { + schema.pattern = schema.validator + } + + if (typeof schema.empty !== 'undefined') { + schema.required = !(schema.empty) + } + + delete schema.warning + delete schema.validator + delete schema.empty + } + + return schema + } + + /* WEBPACK VAR INJECTION */ +}.call(exports, __webpack_require__(15)(module), __webpack_require__(11))) + + /***/ +}, +/* 15 */ +/***/ function (module, exports) { + + module.exports = function (module) { + if (!module.webpackPolyfill) { + module.deprecate = function () { } + module.paths = [] + // module.parent = undefined by default + module.children = [] + module.webpackPolyfill = 1 + } + return module + } + + + /***/ +}, +/* 16 */ +/***/ function (module, exports, __webpack_require__) { + + /* + * index.js: Top-level include for the `utile` module. + * + * (C) 2011, Charlie Robbins & the Contributors + * MIT LICENSE + * + */ + + var fs = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"fs\""); e.code = 'MODULE_NOT_FOUND'; throw e }())), + path = __webpack_require__(17), + util = __webpack_require__(10) + + var utile = module.exports + + // + // Extend the `utile` object with all methods from the + // core node `util` methods. + // + Object.keys(util).forEach(function (key) { + utile[key] = util[key] + }) + + Object.defineProperties(utile, { + + // + // ### function async + // Simple wrapper to `require('async')`. + // + 'async': { + get: function () { + return utile.async = __webpack_require__(18) + } + }, + + // + // ### function inflect + // Simple wrapper to `require('i')`. + // + 'inflect': { + get: function () { + return utile.inflect = __webpack_require__(20)() + } + }, + + // + // ### function mkdirp + // Simple wrapper to `require('mkdirp')` + // + 'mkdirp': { + get: function () { + return utile.mkdirp = __webpack_require__(26) + } + }, + + // + // ### function deepEqual + // Simple wrapper to `require('deep-equal')` + // Remark: deepEqual is 4x faster then using assert.deepEqual + // see: https://gist.github.com/2790507 + // + 'deepEqual': { + get: function () { + return utile.deepEqual = __webpack_require__(27) + } + }, + + // + // ### function rimraf + // Simple wrapper to `require('rimraf')` + // + 'rimraf': { + get: function () { + return utile.rimraf = __webpack_require__(30) + } + }, + + // + // ### function cpr + // Simple wrapper to `require('ncp').ncp` + // + 'cpr': { + get: function () { + return utile.cpr = __webpack_require__(47).ncp + } + }, + + // + // ### @file {Object} + // Lazy-loaded `file` module + // + 'file': { + get: function () { + return utile.file = __webpack_require__(48) + } + }, + + // + // ### @args {Object} + // Lazy-loaded `args` module + // + 'args': { + get: function () { + return utile.args = __webpack_require__(49) + } + }, + + // + // ### @base64 {Object} + // Lazy-loaded `base64` object + // + 'base64': { + get: function () { + return utile.base64 = __webpack_require__(50) + } + }, + + // + // ### @format {Object} + // Lazy-loaded `format` object + // + 'format': { + get: function () { + return utile.format = __webpack_require__(51) + } + } + + }) + + + // + // ### function rargs(_args) + // #### _args {Arguments} Original function arguments + // + // Top-level method will accept a javascript "arguments" object + // (the actual keyword "arguments" inside any scope) and return + // back an Array. + // + utile.rargs = function (_args, slice) { + if (!slice) { + slice = 0 + } + + var len = (_args || []).length, + args = new Array(len - slice), + i + + // + // Convert the raw `_args` to a proper Array. + // + for (i = slice; i < len; i++) { + args[i - slice] = _args[i] + } + + return args + } + + // + // ### function each (obj, iterator) + // #### @obj {Object} Object to iterate over + // #### @iterator {function} Continuation to use on each key. `function (value, key, object)` + // Iterate over the keys of an object. + // + utile.each = function (obj, iterator) { + Object.keys(obj).forEach(function (key) { + iterator(obj[key], key, obj) + }) + } + + // + // ### function find (o) + // + // + utile.find = function (obj, pred) { + var value, key + + for (key in obj) { + value = obj[key] + if (pred(value, key)) { + return value + } + } + } + + // + // ### function pad (str, len, chr) + // ### @str {String} String to pad + // ### @len {Number} Number of chars to pad str with + // ### @chr {String} Optional replacement character, defaults to empty space + // Appends chr to str until it reaches a length of len + // + utile.pad = function pad(str, len, chr) { + var s + if (!chr) { + chr = ' ' + } + str = str || '' + s = str + if (str.length < len) { + for (var i = 0; i < (len - str.length); i++) { + s += chr + } + } + return s + } + + // + // ### function path (obj, path, value) + // ### @obj {Object} Object to insert value into + // ### @path {Array} List of nested keys to insert value at + // Retreives a value from given Object, `obj`, located at the + // nested keys, `path`. + // + utile.path = function (obj, path) { + var key, i + + for (i in path) { + if (typeof obj === 'undefined') { + return undefined + } + + key = path[i] + obj = obj[key] + } + + return obj + } + + // + // ### function createPath (obj, path, value) + // ### @obj {Object} Object to insert value into + // ### @path {Array} List of nested keys to insert value at + // ### @value {*} Value to insert into the object. + // Inserts the `value` into the given Object, `obj`, creating + // any keys in `path` along the way if necessary. + // + utile.createPath = function (obj, path, value) { + var key, i + + for (i in path) { + key = path[i] + if (!obj[key]) { + obj[key] = ((+i + 1 === path.length) ? value : {}) + } + + obj = obj[key] + } + } + + // + // ### function mixin (target [source0, source1, ...]) + // Copies enumerable properties from `source0 ... sourceN` + // onto `target` and returns the resulting object. + // + utile.mixin = function (target) { + utile.rargs(arguments, 1).forEach(function (o) { + Object.getOwnPropertyNames(o).forEach(function (attr) { + var getter = Object.getOwnPropertyDescriptor(o, attr).get, + setter = Object.getOwnPropertyDescriptor(o, attr).set + + if (!getter && !setter) { + target[attr] = o[attr] + } + else { + Object.defineProperty(target, attr, { + get: getter, + set: setter + }) + } + }) + }) + + return target + } + + + // + // ### function capitalize (str) + // #### @str {string} String to capitalize + // Capitalizes the specified `str`. + // + utile.capitalize = utile.inflect.camelize + + // + // ### function escapeRegExp (str) + // #### @str {string} String to be escaped + // Escape string for use in Javascript regex + // + utile.escapeRegExp = function (str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&") + } + + // + // ### function randomString (length) + // #### @length {integer} The number of bits for the random base64 string returned to contain + // randomString returns a pseude-random ASCII string (subset) + // the return value is a string of length ⌈bits/6⌉ of characters + // from the base64 alphabet. + // + utile.randomString = function (length) { + var chars, rand, i, ret, mod, bits + + chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-' + ret = '' + // standard 4 + mod = 4 + // default is 16 + bits = length * mod || 64 + + // in v8, Math.random() yields 32 pseudo-random bits (in spidermonkey it gives 53) + while (bits > 0) { + // 32-bit integer + rand = Math.floor(Math.random() * 0x100000000) + //we use the top bits + for (i = 26; i > 0 && bits > 0; i -= mod, bits -= mod) { + ret += chars[0x3F & rand >>> i] + } + } + + return ret + } + + // + // ### function filter (object, test) + // #### @obj {Object} Object to iterate over + // #### @pred {function} Predicate applied to each property. `function (value, key, object)` + // Returns an object with properties from `obj` which satisfy + // the predicate `pred` + // + utile.filter = function (obj, pred) { + var copy + if (Array.isArray(obj)) { + copy = [] + utile.each(obj, function (val, key) { + if (pred(val, key, obj)) { + copy.push(val) + } + }) + } + else { + copy = {} + utile.each(obj, function (val, key) { + if (pred(val, key, obj)) { + copy[key] = val + } + }) + } + return copy + } + + // + // ### function requireDir (directory) + // #### @directory {string} Directory to require + // Requires all files and directories from `directory`, returning an object + // with keys being filenames (without trailing `.js`) and respective values + // being return values of `require(filename)`. + // + utile.requireDir = function (directory) { + var result = {}, + files = fs.readdirSync(directory) + + files.forEach(function (file) { + if (file.substr(-3) === '.js') { + file = file.substr(0, file.length - 3) + } + result[file] = __webpack_require__(52)(path.resolve(directory, file)) + }) + return result + } + + // + // ### function requireDirLazy (directory) + // #### @directory {string} Directory to require + // Lazily requires all files and directories from `directory`, returning an + // object with keys being filenames (without trailing `.js`) and respective + // values (getters) being return values of `require(filename)`. + // + utile.requireDirLazy = function (directory) { + var result = {}, + files = fs.readdirSync(directory) + + files.forEach(function (file) { + if (file.substr(-3) === '.js') { + file = file.substr(0, file.length - 3) + } + Object.defineProperty(result, file, { + get: function () { + return result[file] = __webpack_require__(52)(path.resolve(directory, file)) + } + }) + }) + + return result + } + + // + // ### function clone (object, filter) + // #### @object {Object} Object to clone + // #### @filter {Function} Filter to be used + // Shallow clones the specified object. + // + utile.clone = function (object, filter) { + return Object.keys(object).reduce(filter ? function (obj, k) { + if (filter(k)) obj[k] = object[k] + return obj + } : function (obj, k) { + obj[k] = object[k] + return obj + }, {}) + } + + // + // ### function camelToUnderscore (obj) + // #### @obj {Object} Object to convert keys on. + // Converts all keys of the type `keyName` to `key_name` on the + // specified `obj`. + // + utile.camelToUnderscore = function (obj) { + if (typeof obj !== 'object' || obj === null) { + return obj + } + + if (Array.isArray(obj)) { + obj.forEach(utile.camelToUnderscore) + return obj + } + + Object.keys(obj).forEach(function (key) { + var k = utile.inflect.underscore(key) + if (k !== key) { + obj[k] = obj[key] + delete obj[key] + key = k + } + utile.camelToUnderscore(obj[key]) + }) + + return obj + } + + // + // ### function underscoreToCamel (obj) + // #### @obj {Object} Object to convert keys on. + // Converts all keys of the type `key_name` to `keyName` on the + // specified `obj`. + // + utile.underscoreToCamel = function (obj) { + if (typeof obj !== 'object' || obj === null) { + return obj + } + + if (Array.isArray(obj)) { + obj.forEach(utile.underscoreToCamel) + return obj + } + + Object.keys(obj).forEach(function (key) { + var k = utile.inflect.camelize(key, false) + if (k !== key) { + obj[k] = obj[key] + delete obj[key] + key = k + } + utile.underscoreToCamel(obj[key]) + }) + + return obj + } + + + /***/ +}, +/* 17 */ +/***/ function (module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function (process) {// Copyright Joyent, Inc. and other Node contributors. + // + // 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. + + // resolves . and .. elements in a path array with directory names there + // must be no slashes, empty elements, or device names (c:\) in the array + // (so also no leading and trailing slashes - it does not distinguish + // relative and absolute paths) + function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0 + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i] + if (last === '.') { + parts.splice(i, 1) + } else if (last === '..') { + parts.splice(i, 1) + up++ + } else if (up) { + parts.splice(i, 1) + up-- + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..') + } + } + + return parts + } + + // Split a filename into [root, dir, basename, ext], unix version + // 'root' is just a slash, or nothing. + var splitPathRe = + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/ + var splitPath = function (filename) { + return splitPathRe.exec(filename).slice(1) + } + + // path.resolve([from ...], to) + // posix version + exports.resolve = function () { + var resolvedPath = '', + resolvedAbsolute = false + + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : process.cwd() + + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings') + } else if (!path) { + continue + } + + resolvedPath = path + '/' + resolvedPath + resolvedAbsolute = path.charAt(0) === '/' + } + + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + + // Normalize the path + resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function (p) { + return !!p + }), !resolvedAbsolute).join('/') + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.' + } + + // path.normalize(path) + // posix version + exports.normalize = function (path) { + var isAbsolute = exports.isAbsolute(path), + trailingSlash = substr(path, -1) === '/' + + // Normalize the path + path = normalizeArray(filter(path.split('/'), function (p) { + return !!p + }), !isAbsolute).join('/') + + if (!path && !isAbsolute) { + path = '.' + } + if (path && trailingSlash) { + path += '/' + } + + return (isAbsolute ? '/' : '') + path + } + + // posix version + exports.isAbsolute = function (path) { + return path.charAt(0) === '/' + } + + // posix version + exports.join = function () { + var paths = Array.prototype.slice.call(arguments, 0) + return exports.normalize(filter(paths, function (p, index) { + if (typeof p !== 'string') { + throw new TypeError('Arguments to path.join must be strings') + } + return p + }).join('/')) + } + + + // path.relative(from, to) + // posix version + exports.relative = function (from, to) { + from = exports.resolve(from).substr(1) + to = exports.resolve(to).substr(1) + + function trim(arr) { + var start = 0 + for (; start < arr.length; start++) { + if (arr[start] !== '') break + } + + var end = arr.length - 1 + for (; end >= 0; end--) { + if (arr[end] !== '') break + } + + if (start > end) return [] + return arr.slice(start, end - start + 1) + } + + var fromParts = trim(from.split('/')) + var toParts = trim(to.split('/')) + + var length = Math.min(fromParts.length, toParts.length) + var samePartsLength = length + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i + break + } + } + + var outputParts = [] + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..') + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)) + + return outputParts.join('/') + } + + exports.sep = '/' + exports.delimiter = ':' + + exports.dirname = function (path) { + var result = splitPath(path), + root = result[0], + dir = result[1] + + if (!root && !dir) { + // No dirname whatsoever + return '.' + } + + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1) + } + + return root + dir + } + + + exports.basename = function (path, ext) { + var f = splitPath(path)[2] + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length) + } + return f + } + + + exports.extname = function (path) { + return splitPath(path)[3] + } + + function filter(xs, f) { + if (xs.filter) return xs.filter(f) + var res = [] + for (var i = 0; i < xs.length; i++) { + if (f(xs[i], i, xs)) res.push(xs[i]) + } + return res + } + + // String.prototype.substr - negative index don't work in IE8 + var substr = 'ab'.substr(-1) === 'b' + ? function (str, start, len) { return str.substr(start, len) } + : function (str, start, len) { + if (start < 0) start = str.length + start + return str.substr(start, len) + } + + + /* WEBPACK VAR INJECTION */ +}.call(exports, __webpack_require__(11))) + + /***/ +}, +/* 18 */ +/***/ function (module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function (process, setImmediate) {/*! + * async + * https://github.com/caolan/async + * + * Copyright 2010-2014 Caolan McMahon + * Released under the MIT license + */ + /*jshint onevar: false, indent:4 */ + /*global setImmediate: false, setTimeout: false, console: false */ + (function () { + + var async = {} + + // global on the server, window in the browser + var root, previous_async + + root = this + if (root != null) { + previous_async = root.async + } + + async.noConflict = function () { + root.async = previous_async + return async + } + + function only_once(fn) { + var called = false + return function () { + if (called) throw new Error("Callback was already called.") + called = true + fn.apply(root, arguments) + } + } + + //// cross-browser compatiblity functions //// + + var _toString = Object.prototype.toString + + var _isArray = Array.isArray || function (obj) { + return _toString.call(obj) === '[object Array]' + } + + var _each = function (arr, iterator) { + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr) + } + } + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator) + } + var results = [] + _each(arr, function (x, i, a) { + results.push(iterator(x, i, a)) + }) + return results + } + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo) + } + _each(arr, function (x, i, a) { + memo = iterator(memo, x, i, a) + }) + return memo + } + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj) + } + var keys = [] + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k) + } + } + return keys + } + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + if (typeof setImmediate === 'function') { + async.nextTick = function (fn) { + // not a direct alias for IE10 compatibility + setImmediate(fn) + } + async.setImmediate = async.nextTick + } + else { + async.nextTick = function (fn) { + setTimeout(fn, 0) + } + async.setImmediate = async.nextTick + } + } + else { + async.nextTick = process.nextTick + if (typeof setImmediate !== 'undefined') { + async.setImmediate = function (fn) { + // not a direct alias for IE10 compatibility + setImmediate(fn) + } + } + else { + async.setImmediate = async.nextTick + } + } + + async.each = function (arr, iterator, callback) { + callback = callback || function () { } + if (!arr.length) { + return callback() + } + var completed = 0 + _each(arr, function (x) { + iterator(x, only_once(done)) + }) + function done(err) { + if (err) { + callback(err) + callback = function () { } + } + else { + completed += 1 + if (completed >= arr.length) { + callback() + } + } + } + } + async.forEach = async.each + + async.eachSeries = function (arr, iterator, callback) { + callback = callback || function () { } + if (!arr.length) { + return callback() + } + var completed = 0 + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err) + callback = function () { } + } + else { + completed += 1 + if (completed >= arr.length) { + callback() + } + else { + iterate() + } + } + }) + } + iterate() + } + async.forEachSeries = async.eachSeries + + async.eachLimit = function (arr, limit, iterator, callback) { + var fn = _eachLimit(limit) + fn.apply(null, [arr, iterator, callback]) + } + async.forEachLimit = async.eachLimit + + var _eachLimit = function (limit) { + + return function (arr, iterator, callback) { + callback = callback || function () { } + if (!arr.length || limit <= 0) { + return callback() + } + var completed = 0 + var started = 0 + var running = 0; + + (function replenish() { + if (completed >= arr.length) { + return callback() + } + + while (running < limit && started < arr.length) { + started += 1 + running += 1 + iterator(arr[started - 1], function (err) { + if (err) { + callback(err) + callback = function () { } + } + else { + completed += 1 + running -= 1 + if (completed >= arr.length) { + callback() + } + else { + replenish() + } + } + }) + } + })() + } + } + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments) + return fn.apply(null, [async.each].concat(args)) + } + } + var doParallelLimit = function (limit, fn) { + return function () { + var args = Array.prototype.slice.call(arguments) + return fn.apply(null, [_eachLimit(limit)].concat(args)) + } + } + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments) + return fn.apply(null, [async.eachSeries].concat(args)) + } + } + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + arr = _map(arr, function (x, i) { + return { index: i, value: x } + }) + if (!callback) { + eachfn(arr, function (x, callback) { + iterator(x.value, function (err) { + callback(err) + }) + }) + } else { + var results = [] + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v + callback(err) + }) + }, function (err) { + callback(err, results) + }) + } + } + async.map = doParallel(_asyncMap) + async.mapSeries = doSeries(_asyncMap) + async.mapLimit = function (arr, limit, iterator, callback) { + return _mapLimit(limit)(arr, iterator, callback) + } + + var _mapLimit = function (limit) { + return doParallelLimit(limit, _asyncMap) + } + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.eachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v + callback(err) + }) + }, function (err) { + callback(err, memo) + }) + } + // inject alias + async.inject = async.reduce + // foldl alias + async.foldl = async.reduce + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x + }).reverse() + async.reduce(reversed, memo, iterator, callback) + } + // foldr alias + async.foldr = async.reduceRight + + var _filter = function (eachfn, arr, iterator, callback) { + var results = [] + arr = _map(arr, function (x, i) { + return { index: i, value: x } + }) + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x) + } + callback() + }) + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index + }), function (x) { + return x.value + })) + }) + } + async.filter = doParallel(_filter) + async.filterSeries = doSeries(_filter) + // select alias + async.select = async.filter + async.selectSeries = async.filterSeries + + var _reject = function (eachfn, arr, iterator, callback) { + var results = [] + arr = _map(arr, function (x, i) { + return { index: i, value: x } + }) + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x) + } + callback() + }) + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index + }), function (x) { + return x.value + })) + }) + } + async.reject = doParallel(_reject) + async.rejectSeries = doSeries(_reject) + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x) + main_callback = function () { } + } + else { + callback() + } + }) + }, function (err) { + main_callback() + }) + } + async.detect = doParallel(_detect) + async.detectSeries = doSeries(_detect) + + async.some = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true) + main_callback = function () { } + } + callback() + }) + }, function (err) { + main_callback(false) + }) + } + // any alias + async.any = async.some + + async.every = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false) + main_callback = function () { } + } + callback() + }) + }, function (err) { + main_callback(true) + }) + } + // all alias + async.all = async.every + + async.sortBy = function (arr, iterator, callback) { + async.map(arr, function (x, callback) { + iterator(x, function (err, criteria) { + if (err) { + callback(err) + } + else { + callback(null, { value: x, criteria: criteria }) + } + }) + }, function (err, results) { + if (err) { + return callback(err) + } + else { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria + return a < b ? -1 : a > b ? 1 : 0 + } + callback(null, _map(results.sort(fn), function (x) { + return x.value + })) + } + }) + } + + async.auto = function (tasks, callback) { + callback = callback || function () { } + var keys = _keys(tasks) + var remainingTasks = keys.length + if (!remainingTasks) { + return callback() + } + + var results = {} + + var listeners = [] + var addListener = function (fn) { + listeners.unshift(fn) + } + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1) + return + } + } + } + var taskComplete = function () { + remainingTasks-- + _each(listeners.slice(0), function (fn) { + fn() + }) + } + + addListener(function () { + if (!remainingTasks) { + var theCallback = callback + // prevent final callback from calling itself if it errors + callback = function () { } + + theCallback(null, results) + } + }) + + _each(keys, function (k) { + var task = _isArray(tasks[k]) ? tasks[k] : [tasks[k]] + var taskCallback = function (err) { + var args = Array.prototype.slice.call(arguments, 1) + if (args.length <= 1) { + args = args[0] + } + if (err) { + var safeResults = {} + _each(_keys(results), function (rkey) { + safeResults[rkey] = results[rkey] + }) + safeResults[k] = args + callback(err, safeResults) + // stop subsequent errors hitting callback multiple times + callback = function () { } + } + else { + results[k] = args + async.setImmediate(taskComplete) + } + } + var requires = task.slice(0, Math.abs(task.length - 1)) || [] + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)) + }, true) && !results.hasOwnProperty(k) + } + if (ready()) { + task[task.length - 1](taskCallback, results) + } + else { + var listener = function () { + if (ready()) { + removeListener(listener) + task[task.length - 1](taskCallback, results) + } + } + addListener(listener) + } + }) + } + + async.retry = function (times, task, callback) { + var DEFAULT_TIMES = 5 + var attempts = [] + // Use defaults if times not passed + if (typeof times === 'function') { + callback = task + task = times + times = DEFAULT_TIMES + } + // Make sure times is a number + times = parseInt(times, 10) || DEFAULT_TIMES + var wrappedTask = function (wrappedCallback, wrappedResults) { + var retryAttempt = function (task, finalAttempt) { + return function (seriesCallback) { + task(function (err, result) { + seriesCallback(!err || finalAttempt, { err: err, result: result }) + }, wrappedResults) + } + } + while (times) { + attempts.push(retryAttempt(task, !(times -= 1))) + } + async.series(attempts, function (done, data) { + data = data[data.length - 1]; + (wrappedCallback || callback)(data.err, data.result) + }) + } + // If a callback is passed, run this as a controll flow + return callback ? wrappedTask() : wrappedTask + } + + async.waterfall = function (tasks, callback) { + callback = callback || function () { } + if (!_isArray(tasks)) { + var err = new Error('First argument to waterfall must be an array of functions') + return callback(err) + } + if (!tasks.length) { + return callback() + } + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback.apply(null, arguments) + callback = function () { } + } + else { + var args = Array.prototype.slice.call(arguments, 1) + var next = iterator.next() + if (next) { + args.push(wrapIterator(next)) + } + else { + args.push(callback) + } + async.setImmediate(function () { + iterator.apply(null, args) + }) + } + } + } + wrapIterator(async.iterator(tasks))() + } + + var _parallel = function (eachfn, tasks, callback) { + callback = callback || function () { } + if (_isArray(tasks)) { + eachfn.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1) + if (args.length <= 1) { + args = args[0] + } + callback.call(null, err, args) + }) + } + }, callback) + } + else { + var results = {} + eachfn.each(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1) + if (args.length <= 1) { + args = args[0] + } + results[k] = args + callback(err) + }) + }, function (err) { + callback(err, results) + }) + } + } + + async.parallel = function (tasks, callback) { + _parallel({ map: async.map, each: async.each }, tasks, callback) + } + + async.parallelLimit = function (tasks, limit, callback) { + _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback) + } + + async.series = function (tasks, callback) { + callback = callback || function () { } + if (_isArray(tasks)) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1) + if (args.length <= 1) { + args = args[0] + } + callback.call(null, err, args) + }) + } + }, callback) + } + else { + var results = {} + async.eachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1) + if (args.length <= 1) { + args = args[0] + } + results[k] = args + callback(err) + }) + }, function (err) { + callback(err, results) + }) + } + } + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments) + } + return fn.next() + } + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1) : null + } + return fn + } + return makeCallback(0) + } + + async.apply = function (fn) { + var args = Array.prototype.slice.call(arguments, 1) + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ) + } + } + + var _concat = function (eachfn, arr, fn, callback) { + var r = [] + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []) + cb(err) + }) + }, function (err) { + callback(err, r) + }) + } + async.concat = doParallel(_concat) + async.concatSeries = doSeries(_concat) + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err) + } + async.whilst(test, iterator, callback) + }) + } + else { + callback() + } + } + + async.doWhilst = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err) + } + var args = Array.prototype.slice.call(arguments, 1) + if (test.apply(null, args)) { + async.doWhilst(iterator, test, callback) + } + else { + callback() + } + }) + } + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err) + } + async.until(test, iterator, callback) + }) + } + else { + callback() + } + } + + async.doUntil = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err) + } + var args = Array.prototype.slice.call(arguments, 1) + if (!test.apply(null, args)) { + async.doUntil(iterator, test, callback) + } + else { + callback() + } + }) + } + + async.queue = function (worker, concurrency) { + if (concurrency === undefined) { + concurrency = 1 + } + function _insert(q, data, pos, callback) { + if (!q.started) { + q.started = true + } + if (!_isArray(data)) { + data = [data] + } + if (data.length == 0) { + // call drain immediately if there are no tasks + return async.setImmediate(function () { + if (q.drain) { + q.drain() + } + }) + } + _each(data, function (task) { + var item = { + data: task, + callback: typeof callback === 'function' ? callback : null + } + + if (pos) { + q.tasks.unshift(item) + } else { + q.tasks.push(item) + } + + if (q.saturated && q.tasks.length === q.concurrency) { + q.saturated() + } + async.setImmediate(q.process) + }) + } + + var workers = 0 + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + started: false, + paused: false, + push: function (data, callback) { + _insert(q, data, false, callback) + }, + kill: function () { + q.drain = null + q.tasks = [] + }, + unshift: function (data, callback) { + _insert(q, data, true, callback) + }, + process: function () { + if (!q.paused && workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift() + if (q.empty && q.tasks.length === 0) { + q.empty() + } + workers += 1 + var next = function () { + workers -= 1 + if (task.callback) { + task.callback.apply(task, arguments) + } + if (q.drain && q.tasks.length + workers === 0) { + q.drain() + } + q.process() + } + var cb = only_once(next) + worker(task.data, cb) + } + }, + length: function () { + return q.tasks.length + }, + running: function () { + return workers + }, + idle: function () { + return q.tasks.length + workers === 0 + }, + pause: function () { + if (q.paused === true) { return } + q.paused = true + }, + resume: function () { + if (q.paused === false) { return } + q.paused = false + // Need to call q.process once per concurrent + // worker to preserve full concurrency after pause + for (var w = 1; w <= q.concurrency; w++) { + async.setImmediate(q.process) + } + } + } + return q + } + + async.priorityQueue = function (worker, concurrency) { + + function _compareTasks(a, b) { + return a.priority - b.priority + }; + + function _binarySearch(sequence, item, compare) { + var beg = -1, + end = sequence.length - 1 + while (beg < end) { + var mid = beg + ((end - beg + 1) >>> 1) + if (compare(item, sequence[mid]) >= 0) { + beg = mid + } else { + end = mid - 1 + } + } + return beg + } + + function _insert(q, data, priority, callback) { + if (!q.started) { + q.started = true + } + if (!_isArray(data)) { + data = [data] + } + if (data.length == 0) { + // call drain immediately if there are no tasks + return async.setImmediate(function () { + if (q.drain) { + q.drain() + } + }) + } + _each(data, function (task) { + var item = { + data: task, + priority: priority, + callback: typeof callback === 'function' ? callback : null + } + + q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item) + + if (q.saturated && q.tasks.length === q.concurrency) { + q.saturated() + } + async.setImmediate(q.process) + }) + } + + // Start with a normal queue + var q = async.queue(worker, concurrency) + + // Override push to accept second parameter representing priority + q.push = function (data, priority, callback) { + _insert(q, data, priority, callback) + } + + // Remove unshift function + delete q.unshift + + return q + } + + async.cargo = function (worker, payload) { + var working = false, + tasks = [] + + var cargo = { + tasks: tasks, + payload: payload, + saturated: null, + empty: null, + drain: null, + drained: true, + push: function (data, callback) { + if (!_isArray(data)) { + data = [data] + } + _each(data, function (task) { + tasks.push({ + data: task, + callback: typeof callback === 'function' ? callback : null + }) + cargo.drained = false + if (cargo.saturated && tasks.length === payload) { + cargo.saturated() + } + }) + async.setImmediate(cargo.process) + }, + process: function process() { + if (working) return + if (tasks.length === 0) { + if (cargo.drain && !cargo.drained) cargo.drain() + cargo.drained = true + return + } + + var ts = typeof payload === 'number' + ? tasks.splice(0, payload) + : tasks.splice(0, tasks.length) + + var ds = _map(ts, function (task) { + return task.data + }) + + if (cargo.empty) cargo.empty() + working = true + worker(ds, function () { + working = false + + var args = arguments + _each(ts, function (data) { + if (data.callback) { + data.callback.apply(null, args) + } + }) + + process() + }) + }, + length: function () { + return tasks.length + }, + running: function () { + return working + } + } + return cargo + } + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1) + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1) + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err) + } + } + else if (console[name]) { + _each(args, function (x) { + console[name](x) + }) + } + } + }])) + } + } + async.log = _console_fn('log') + async.dir = _console_fn('dir') + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + + async.memoize = function (fn, hasher) { + var memo = {} + var queues = {} + hasher = hasher || function (x) { + return x + } + var memoized = function () { + var args = Array.prototype.slice.call(arguments) + var callback = args.pop() + var key = hasher.apply(null, args) + if (key in memo) { + async.nextTick(function () { + callback.apply(null, memo[key]) + }) + } + else if (key in queues) { + queues[key].push(callback) + } + else { + queues[key] = [callback] + fn.apply(null, args.concat([function () { + memo[key] = arguments + var q = queues[key] + delete queues[key] + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments) + } + }])) + } + } + memoized.memo = memo + memoized.unmemoized = fn + return memoized + } + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments) + } + } + + async.times = function (count, iterator, callback) { + var counter = [] + for (var i = 0; i < count; i++) { + counter.push(i) + } + return async.map(counter, iterator, callback) + } + + async.timesSeries = function (count, iterator, callback) { + var counter = [] + for (var i = 0; i < count; i++) { + counter.push(i) + } + return async.mapSeries(counter, iterator, callback) + } + + async.seq = function (/* functions... */) { + var fns = arguments + return function () { + var that = this + var args = Array.prototype.slice.call(arguments) + var callback = args.pop() + async.reduce(fns, args, function (newargs, fn, cb) { + fn.apply(that, newargs.concat([function () { + var err = arguments[0] + var nextargs = Array.prototype.slice.call(arguments, 1) + cb(err, nextargs) + }])) + }, + function (err, results) { + callback.apply(that, [err].concat(results)) + }) + } + } + + async.compose = function (/* functions... */) { + return async.seq.apply(null, Array.prototype.reverse.call(arguments)) + } + + var _applyEach = function (eachfn, fns /*args...*/) { + var go = function () { + var that = this + var args = Array.prototype.slice.call(arguments) + var callback = args.pop() + return eachfn(fns, function (fn, cb) { + fn.apply(that, args.concat([cb])) + }, + callback) + } + if (arguments.length > 2) { + var args = Array.prototype.slice.call(arguments, 2) + return go.apply(this, args) + } + else { + return go + } + } + async.applyEach = doParallel(_applyEach) + async.applyEachSeries = doSeries(_applyEach) + + async.forever = function (fn, callback) { + function next(err) { + if (err) { + if (callback) { + return callback(err) + } + throw err + } + fn(next) + } + next() + } + + // Node.js + if (typeof module !== 'undefined' && module.exports) { + module.exports = async + } + // AMD / RequireJS + else if (true) { + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function () { + return async + }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)) + } + // included directly via + + + + + + + + diff --git a/参考项目/battleboat/styles.css b/参考项目/battleboat/styles.css new file mode 100644 index 0000000..3a368ec --- /dev/null +++ b/参考项目/battleboat/styles.css @@ -0,0 +1,398 @@ +@import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700); + +html, +body { + width: 100%; + padding: 0; + margin: 0; + background-color: #ddd; + min-width: 860px; +} + +h1, +h2, +h3, +h4, +h5, +h6, +p, +li, +span { + font-family: 'Open Sans', Helvetica, Arial, sans-serif; + color: #222222; +} + +a { + color: #222222; + font-weight: bold; +} + +a:hover { + text-decoration: none; +} + +div { + padding: 0; + margin: 0; +} + +button { + font-family: 'Open Sans', Helvetica, Arial, sans-serif; + font-size: 1.2em; + color: #EEEEEE; + background-color: #25567B; + border: none; + margin: 1em auto 0 auto; + padding: 10px; + border-radius: 5px; +} + +button:hover { + cursor: pointer; + background-color: #ffffff; +} + +button:active { + background-color: #99C2E1; +} + +#start-game, +#place-randomly, +#restart-game { + position: relative; + color: #FFFFFF; + background-color: #FF9200; +} + +#start-game:hover, +#place-randomly:hover, +#restart-game:hover { + background-color: #FFB655; +} + +#start-game:active, +#place-randomly:active, +#restart-game:active { + background-color: #FFCE8E; +} + +#prefetch1 { + background: url('../img/cross-icon.svg'); +} + +#prefetch2 { + background: url('../img/cross-icon.png'); +} + +#prefetch3 { + background: url('../img/crosshair.png'); +} + +.prefetch { + background-repeat: no-repeat; + background-position: -9999px -9999px; +} + +.tagline { + margin-bottom: 2em; +} + +.instructions { + width: auto; + display: inline-block; + text-align: left; + margin: 0 auto 3em auto; +} + +.container { + width: 870px; + text-align: center; + margin: 20px auto 100px auto; +} + +.game-container { + position: relative; +} + +#roster-sidebar, +#stats-sidebar, +#restart-sidebar { + width: 150px; + padding: 20px; + margin: 0; + background-color: #EEEEEE; + position: absolute; + top: 4.5em; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + +#roster-sidebar, +#restart-sidebar { + left: -200px; +} + +#stats-sidebar { + right: -200px; +} + +#roster-sidebar h2, +#stats-sidebar h2, +#restart-sidebar h2 { + margin: 0 0 1em 0; + text-align: center; +} + +.fleet-roster { + position: relative; + margin: 0; + padding: 0; + list-style: none; +} + +.fleet-roster, +button { + opacity: 1; + -webkit-transition: opacity 0.5s ease-out; + -o-transition: opacity 0.5s ease-out; + transition: opacity 0.5s ease-out; +} + +.fleet-roster li { + margin: 0.5em 0; +} + +.fleet-roster li:hover { + color: #aaa; + cursor: pointer; +} + +.fleet-roster .placing { + font-weight: bold; +} + +.fleet-roster .placed { + visibility: hidden; + font-weight: bold; + opacity: 0; + -webkit-transition: all 0.2s ease-in; + -o-transition: all 0.2s ease-in; + transition: all 0.2s ease-in; +} + +.invisible { + opacity: 0; + -webkit-transition: opacity 0.5s ease-in; + -o-transition: opacity 0.5s ease-in; + transition: opacity 0.5s ease-in; + z-index: -20; +} + +.hidden { + display: none; +} + +.grid-container { + width: 430px; + display: inline-block; +} + +.grid-container h2 { + width: 430px; + display: inline-block; +} + +.grid { + position: relative; + vertical-align: top; + padding: 5px; + height: 420px; + width: 420px; + background-color: #25567B; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + +.grid-container:last-child { + margin-left: 10px; +} + +.no-js { + width: 300px; + height: 300px; + margin: 100px auto; + display: inline-block; + color: #EEEEEE; + font-size: 2em; +} + +.grid-cell { + vertical-align: top; + /*clears the vertical space between rows*/ + height: 40px; + width: 40px; + display: inline-block; + background-color: #99C2E1; + margin: 1px; + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; +} + +.grid-cell:hover { + cursor: pointer; + /* Fallback for IE */ + background-color: #66A3D2; +} + +.human-player .grid-cell:hover { + background-color: #99C2E1; +} + +.computer-player .grid-cell:hover, +.computer-player:hover { + cursor: url('../img/crosshair.png') 16 16, crosshair; +} + +.grid-ship, +.human-player .grid-ship:hover { + background-color: #808080; +} + +.grid-miss, +.grid-miss:hover, +.human-player .grid-miss:hover { + background-color: #FFFFFF; + background-image: url('../img/cross-icon.png'); + /* Fallback */ + background-image: url('../img/cross-icon.svg'); + background-position: center; + background-repeat: no-repeat; +} + +.grid-hit, +.grid-hit:hover, +.human-player .grid-hit:hover { + background-color: #F60018; + background-image: url('../img/cross-icon.png'); + /* Fallback */ + background-image: url('../img/cross-icon.svg'); + background-position: center; + background-repeat: no-repeat; +} + +.grid-sunk, +.grid-sunk:hover, +.human-player .grid-sunk:hover { + background-color: #222222; +} + +.highlight { + overflow: visible; + /* Bugfix for IE */ +} + +.highlight:before { + content: "\2193"; + font-weight: bold; + font-size: 75px; + color: #FF9200; + text-shadow: 0 0 5px #FF9200; + position: absolute; + width: 100px; + height: 100px; + top: -100px; + left: 50%; + margin-left: -50px; + -webkit-animation: highlight 1.5s infinite; + -o-animation: highlight 1.5s infinite; + animation: highlight 1.5s infinite; +} + +.current-step { + font-weight: bold; +} + +@media(max-width: 1300px) { + .container { + width: 440px; + } + + .grid-container:last-child { + margin-left: 0; + } +} + + +@-webkit-keyframes highlight { + 0% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 50% { + -webkit-transform: translateY(-20px); + transform: translateY(-20px); + } + + 100% { + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@-moz-keyframes highlight { + 0% { + transform: translateY(0); + } + + 50% { + transform: translateY(-20px); + } + + 100% { + transform: translateY(0); + } +} + +@-o-keyframes highlight { + 0% { + -o-transform: translateY(0); + transform: translateY(0); + } + + 50% { + -o-transform: translateY(-20px); + transform: translateY(-20px); + } + + 100% { + -o-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes highlight { + 0% { + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + transform: translateY(0); + } + + 50% { + -webkit-transform: translateY(-20px); + -ms-transform: translateY(-20px); + -o-transform: translateY(-20px); + transform: translateY(-20px); + } + + 100% { + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + transform: translateY(0); + } +} diff --git a/参考项目/bs/index.html b/参考项目/bs/index.html new file mode 100644 index 0000000..d0b2650 --- /dev/null +++ b/参考项目/bs/index.html @@ -0,0 +1,37 @@ + + + + + BattleShip + + + + + + +

+
+
+
+
    +
    +
    +
      +
      +
      +
      +
      +
      +
      +
      One-Player
      +
      Two-Player
      +
      Options
      +
      +
      +
      +
      +
      +
      + + + diff --git a/参考项目/bs/script.js b/参考项目/bs/script.js new file mode 100644 index 0000000..752033e --- /dev/null +++ b/参考项目/bs/script.js @@ -0,0 +1,751 @@ +// Variables +var playerFleet, cpuFleet +var attemptedHits = [] + +// Object Constructors +function Fleet(name) { + this.name = name + this.shipDetails = [{ "name": "carrier", "length": 5 }, + { "name": "battleship", "length": 4 }, + { "name": "cruiser", "length": 3 }, + { "name": "destroyer", "length": 3 }, + { "name": "frigate", "length": 2 }] + this.numOfShips = this.shipDetails.length + this.ships = [] + this.currentShipSize = 0 + this.currentShip = 0 + this.initShips = function () { + for (var i = 0; i < this.numOfShips; i++) { + this.ships[i] = new Ship(this.shipDetails[i].name) + this.ships[i].length = this.shipDetails[i].length + } + } + this.removeShip = function (pos) { + this.numOfShips-- + $(".text").text(output.sunk(this.name, this.ships[pos].name)) + if (this == playerFleet) bot.sizeOfShipSunk = this.ships[pos].length + this.ships.splice(pos, 1) + if (this.ships.length == 0) { + $(".text").text(output.lost(this.name)) + } + return true + } + this.shipHit = function (ship_name) { + $(".text").text(output.hit(this.name)) + return true + } + this.checkIfHit = function (point) { + for (var i = 0; i < this.numOfShips; i++) { + if (this.ships[i].checkLocation(point)) { + this.ships[i].getRidOf(this.ships[i].hitPoints.indexOf(point)) + if (this.ships[i].hitPoints == 0) return this.removeShip(i) + else return this.shipHit(this.ships[i].name) + } + } + return false + } +} + +function Ship(name) { + this.name = name + this.length = 0 + this.hitPoints = [] + this.populateHorzHits = function (start) { + for (var i = 0; i < this.length; i++, start++) { + this.hitPoints[i] = start + } + } + this.populateVertHits = function (start) { + for (var i = 0; i < this.length; i++, start += 10) { + this.hitPoints[i] = start + } + } + this.checkLocation = function (loc) { + for (var i = 0; i < this.length; i++) { + if (this.hitPoints[i] == loc) return true + } + return false + } + this.getRidOf = function (pos) { + this.hitPoints.splice(pos, 1) + } +} + +// Console obj +var output = { + "welcome": " > Welcome to BattleShip. Use the menu above to get started.", + "not": " > This option is not currently available.", + "player1": " > Would you like to place your own ships or have the computer randomly do it for you?", + "self": " > Use the mouse and the Horizontal and Vertial buttons to place your ships on the bottom grid.", + "overlap": " > You can not overlap ships. Please try again.", + "start": " > Use the mouse to fire on the top grid. Good Luck!", + placed: function (name) { return " > Your " + name + " been placed." }, + hit: function (name, type) { return " > " + name + "'s ship was hit." }, + miss: function (name) { return " > " + name + " missed!" }, + sunk: function (user, type) { return " > " + user + "'s " + type + " was sunk!" }, + lost: function (name) { return " > " + name + " has lost his fleet!! Game Over." }, +} + +// Objects for playing the game and bot for playing the computer +var topBoard = { + allHits: [], + highlight: function (square) { + $(square).addClass("target").off("mouseleave").on("mouseleave", function () { + $(this).removeClass("target") + }) + + $(square).off("click").on("click", function () { + if (!($(this).hasClass("used"))) { + $(this).removeClass("target").addClass("used") + var num = parseInt($(this).attr("class").slice(15)) + var bool = cpuFleet.checkIfHit(num) + if (false == bool) { + $(".text").text(output.miss("You")) + $(this).children().addClass("miss") + } else $(this).children().addClass("hit") + $(".top").find(".points").off("mouseenter").off("mouseover").off("mouseleave").off("click") + // Check if it's the end of the game + if (cpuFleet.ships.length == 0) { + $(".top").find(".points").off("mouseenter").off("mouseover").off("mouseleave").off("click") + + } else setTimeout(bot.select, 800) + } // end of if + }) + }, +} + +var bottomBoard = { + currentHits: [], + checkAttempt: function (hit) { + if (playerFleet.checkIfHit(hit)) { + // Insert hit into an array for book keeping + bottomBoard.currentHits.push(hit) + if (this.currentHits.length > 1) bot.prev_hit = true + // display hit on the grid + $(".bottom").find("." + hit).children().addClass("hit") + if (bottomBoard.hasShipBeenSunk()) { + // clear flags + bot.hunting = bot.prev_hit = false + if (bot.sizeOfShipSunk == bottomBoard.currentHits.length) { + bot.num_misses = bot.back_count = bot.nextMove.length = bottomBoard.currentHits.length = bot.sizeOfShipSunk = bot.currrent = 0 + } else { + bot.special = bot.case1 = true + } + // check for special cases + if (bot.specialHits.length > 0) bot.special = true + // check for end of game. + } + return true + } else { + $(".bottom").find("." + hit).children().addClass("miss") + bot.current = bottomBoard.currentHits[0] + bot.prev_hit = false + if (bottomBoard.currentHits.length > 1) { + bot.back = true + bot.num_misses++ + } + if (bot.case2) { + bot.special = true + bot.case2 = false + } + return false + } + }, + + hasShipBeenSunk: function () { + if (bot.sizeOfShipSunk > 0) return true + else return false + } +} + + +var bot = { + back: false, + hunting: false, + prev_hit: false, + first_hit: false, + special: false, + case1: false, + case2: false, + num_misses: 0, + back_count: 0, + randPool: [], + nextMove: [], + attempted: [], + specialHits: [], + direction: "", + current: 0, + numAttemptsAfterHit: 0, + sizeOfShipSunk: 0, + randomGen: function (size) { + return Math.floor(Math.random() * size) + }, + select: function () { + if (bot.hunting) { + bot.battleLogic() + } else if (bot.special) { + bot.specialCase() + } else { + // grab a random number from the pool and increase attempts + bot.current = bot.randPool[bot.randomGen(bot.randPool.length)] + bot.attempted.push(bot.current) + bot.first_hit = true + // remove current guess from the random pool and check if hit + bot.removeGuess(bot.randPool.indexOf(bot.current)) + bot.hunting = bottomBoard.checkAttempt(bot.current) + } + setTimeout(highlightBoard(), 50) + }, + + removeGuess: function (index) { + bot.randPool.splice(index, 1) + }, + + battleLogic: function () { + if (bot.first_hit) { + bot.createMoves() + bot.first_hit = false + } + + if (bot.num_misses > 1) { + bot.specialCase() + } else if (bot.back) { + bot.back = false + bot.backy() + bot.deployHit(bot.current) + } else if (bot.prev_hit) { + bot.continueHits() + bot.deployHit(bot.current) + console.log(bot.prev_hit) + } else { + bot.direction = bot.nextMove.pop() + console.log(bot.direction + " " + bot.current) + bot.getNumericalDirection(bot.direction) + bot.prev_hit = bot.deployHit(bot.current) + console.log(bot.prev_hit) + } + }, + + deployHit: function (hit) { + if (bot.special) { + bot.specialCase() + } else { + bot.attempted.push(hit) + bot.removeGuess(bot.randPool.indexOf(hit)) + return bottomBoard.checkAttempt(hit) + } + }, + + createMoves: function () { + if (bot.current == 1) { + bot.getRandomMoves(["right", "down"]) + } + else if (bot.current == 10) { + bot.getRandomMoves(["left", "down"]) + } + else if (bot.current == 91) { + bot.getRandomMoves(["up", "right"]) + } + else if (bot.current == 100) { + bot.getRandomMoves(["left", "up"]) + } + else if (!(bot.current % 10)) { + bot.getRandomMoves(["up", "down", "left"]) + } + else if (bot.current < 10) { + bot.getRandomMoves(["right", "down", "left"]) + } + else if (bot.current % 10 == 1) { + bot.getRandomMoves(["up", "right", "down"]) + } + else if (bot.current > 91) { + bot.getRandomMoves(["up", "right", "left"]) + } + else { + bot.getRandomMoves(["up", "right", "down", "left"]) + } + }, + + getRandomMoves: function (possibleMoves) { + while (possibleMoves.length != 0) { + // pick a random direction + var dir = bot.randomGen(possibleMoves.length) + // Go Up + if (possibleMoves[dir] == "up") { + if (bot.randPool.some(function (x) { return x == bot.current - 10 })) { + bot.nextMove.push("up") + } + } + // Go right + if (possibleMoves[dir] == "right") { + if (bot.randPool.some(function (x) { return x == bot.current + 1 })) { + bot.nextMove.push("right") + } + } + // Go down + if (possibleMoves[dir] == "down") { + if (bot.randPool.some(function (x) { return x == bot.current + 10 })) { + bot.nextMove.push("down") + } + } + // Go left + if (possibleMoves[dir] == "left") { + if (bot.randPool.some(function (x) { return x == bot.current - 1 })) { + bot.nextMove.push("left") + } + } + possibleMoves.splice(dir, 1) + } + }, + + getNumericalDirection: function (dir) { + if (dir == "up") bot.current -= 10 + if (dir == "right") bot.current += 1 + if (dir == "down") bot.current += 10 + if (dir == "left") bot.current -= 1 + console.log(bot.current + " attempted " + bot.attempted) + // check if already used + if (bot.attempted.some(function (x) { return x == bot.current }) && bot.specialHits.length == 0) { + bot.current = bottomBoard.currentHits[0] + if (bot.back_count > 1) bot.special = true + else bot.backy() + } + return false + }, + + continueHits: function () { + console.log("cont " + bot.direction) + if (bot.direction == "up") { + if (bot.checkLocation("up")) { + bot.direction = "down" + return bot.getNumericalDirection(bot.direction) + } else return bot.getNumericalDirection(bot.direction) + } + if (bot.direction == "right") { + if (bot.checkLocation("right")) { + bot.direction = "left" + return bot.getNumericalDirection(bot.direction) + } else return bot.getNumericalDirection(bot.direction) + } + if (bot.direction == "down") { + if (bot.checkLocation("down")) { + bot.direction = "up" + return bot.getNumericalDirection(bot.direction) + } else return bot.getNumericalDirection(bot.direction) + } + if (bot.direction == "left") { + if (bot.checkLocation("left")) { + bot.direction = "right" + return bot.getNumericalDirection(bot.direction) + } else return bot.getNumericalDirection(bot.direction) + } + }, + + backy: function () { + bot.back_count++ + if (bot.direction == "up") { + bot.direction = "down" + return bot.continueHits() + } + if (bot.direction == "right") { + bot.direction = "left" + return bot.continueHits() + } + if (bot.direction == "down") { + bot.direction = "up" + return bot.continueHits() + } + if (bot.direction == "left") { + bot.direction = "right" + return bot.continueHits() + } + }, + + checkLocation: function (dir) { + if (dir == "up") { + if (bot.current < 11) return true + } + if (dir == "right") { + if (bot.current % 10 == 0) return true + } + if (dir == "down") { + if (bot.current > 90) return true + } + if (dir == "left") { + if (bot.current % 10 == 1) return true + } + return false + }, + + specialCase: function () { + bot.num_misses = bot.back_count = bot.nextMove.length = 0 + if (bot.case1) { + bot.prev_hit = true + if (bot.getNewCurrent(bot.direction)) { + bottomBoard.currentHits.length = 0 + bottomBoard.currentHits.push(bot.current) + bot.first_hit = true + bot.prev_hit = false + } + bot.special = bot.case1 = bot.back = false + bot.hunting = true + bot.sizeOfShipSunk = 0 + bot.battleLogic() + } else { + if (bot.specialHits.length == 0) { + for (var i = 0; i < bottomBoard.currentHits.length; i++) { + bot.specialHits.push(bottomBoard.currentHits[i]) + } + bottomBoard.currentHits.length = 0 + } + bot.current = bot.specialHits.pop() + bottomBoard.currentHits.push(bot.current) + bot.special = bot.back = bot.prev_hit = false + bot.first_hit = bot.hunting = true + bot.battleLogic() + } + }, + + getNewCurrent: function (direction) { + var difference = bottomBoard.currentHits.length - bot.sizeOfShipSunk + if (bot.direction == "up") { + bot.direction = "down" + if (difference > 1) { + bot.current += 10 * (bottomBoard.currentHits.length - 1) + var temp = bot.current + (10 * (difference - 1)) + bottomBoard.currentHits.length = 0 + for (var i = 0; i < difference; i++) { + bottomBoard.currentHits.push(temp) + temp += 10 + } + bot.case2 = true + return false + } + bot.current += 10 * bot.sizeOfShipSunk + return true + } + if (bot.direction == "right") { + bot.direction = "left" + if (difference > 1) { + bot.current -= bottomBoard.currentHits.length - 1 + var temp = bot.current + (difference - 1) + bottomBoard.currentHits.length = 0 + for (var i = 0; i < difference; i++) { + bottomBoard.currentHits.push(temp) + temp -= 1 + } + bot.case2 = true + return false + } + bot.current -= bot.sizeOfShipSunk + return true + } + if (bot.direction == "down") { + bot.direction = "up" + if (difference > 1) { + bot.current -= 10 * (bottomBoard.currentHits.length - 1) + var temp = bot.current - (10 * (difference - 1)) + bottomBoard.currentHits.length = 0 + for (var i = 0; i < difference; i++) { + bottomBoard.currentHits.push(temp) + temp -= 10 + } + bot.case2 = true + return false + } + bot.current -= 10 * bot.sizeOfShipSunk + return true + } + if (bot.direction == "left") { + bot.direction = "right" + if (difference > 1) { + bot.current += bottomBoard.currentHits.length - 1 + var temp = bot.current - (difference - 1) + bottomBoard.currentHits.length = 0 + for (var i = 0; i < difference; i++) { + bottomBoard.currentHits.push(temp) + temp += 1 + } + bot.case2 = true + return false + } + bot.current += bot.sizeOfShipSunk + return true + } + } +} + +// Create the games grids and layout +$(document).ready(function () { + for (var i = 1; i <= 100; i++) { + // The number and letter designators + if (i < 11) { + $(".top").prepend("" + Math.abs(i - 11) + "") + $(".bottom").prepend("" + Math.abs(i - 11) + "") + $(".grid").append("
    • ") + } else { + $(".grid").append("
    • ") + } + if (i == 11) { + $(".top").prepend("" + Math.abs(i - 11) + "") + $(".bottom").prepend("" + Math.abs(i - 11) + "") + } + if (i > 90) { + $(".top").append("" + + String.fromCharCode(97 + (i - 91)).toUpperCase() + "") + $(".bottom").append("" + + String.fromCharCode(97 + (i - 91)).toUpperCase() + "") + } + } + $(".text").text(output.welcome) +}) + +// Start the game setup +$(document).ready(function () { + $(".one").on("click", function () { + $(".text").text(output.player1) + gameSetup(this) + }) + $(".multi").on("click", function (e) { + e.preventDefault() + if (!$("div").hasClass("error")) { + $(".text").text(output.not) + $(this).addClass("error") + } + }) + $(".options").on("click", function (e) { + e.preventDefault() + if (!$("div").hasClass("error")) { + $(".text").text(output.not) + $(this).addClass("error") + } + }) +}) + +function gameSetup(t) { + $(t).off() && $(".two").off() + $(".one").addClass("self").removeClass("one").text("Place My Own") + $(".multi").addClass("random").removeClass("multi").text("Random") + + $(".self").off("click").on("click", function () { + $(".text").text(output.self) + selfSetup(playerFleet) + }) + $(".random").off("click").on("click", function () { + playerFleet = new Fleet("Player 1") + playerFleet.initShips() + randomSetup(playerFleet) + }) +} + + +function selfSetup() { + $(".self").addClass("horz").removeClass("self").text("Horizontal") + $(".random").addClass("vert").removeClass("random").text("Vertical") + + // initialize the fleet + playerFleet = new Fleet("Player 1") + playerFleet.initShips() + // light up the players ship board for placement + placeShip(playerFleet.ships[playerFleet.currentShip], playerFleet) +} + +function randomSetup(fleet) { + // Decide if the ship will be placed vertically or horizontally + // if 0 then ship will be places horizontally if 1 vertically + // setShip(location, ship, "vert", fleet, "self"); + if (fleet.currentShip >= fleet.numOfShips) return // regard against undefined length + + var orien = Math.floor((Math.random() * 10) + 1) + var length = fleet.ships[fleet.currentShip].length + + if (orien < 6) { + // create a random number betwee 1 and 6 + var shipOffset = 11 - fleet.ships[fleet.currentShip].length + var horiz = Math.floor((Math.random() * shipOffset) + 1) + var vert = Math.floor(Math.random() * 9) + var randNum = parseInt(String(vert) + String(horiz)) + if (fleet == cpuFleet) checkOverlap(randNum, length, "horz", fleet) + else setShip(randNum, fleet.ships[fleet.currentShip], "horz", fleet, "random") + } else { + var shipOffset = 110 - (fleet.ships[fleet.currentShip].length * 10) + var randNum = Math.floor((Math.random() * shipOffset) + 1) + + if (fleet == cpuFleet) checkOverlap(randNum, length, "vert", fleet) + else setShip(randNum, fleet.ships[fleet.currentShip], "vert", fleet, "random") + } +} + +function createCpuFleet() { + // create a random ship placement for the cpu's fleet + cpuFleet = new Fleet("CPU") + cpuFleet.initShips() + randomSetup(cpuFleet) +} + + +function placeShip(ship, fleet) { + // check orientation of ship and highlight accordingly + var orientation = "horz" + $(".vert").off("click").on("click", function () { + orientation = "vert" + }) + $(".horz").off("click").on("click", function () { + orientation = "horz" + }) + // when the user enters the grid have the ships lenght highlighted with the + // ships length. + $(".bottom").find(".points").off("mouseenter").on("mouseenter", function () { + var num = $(this).attr('class').slice(15) + // + if (orientation == "horz") displayShipHorz(parseInt(num), ship, this, fleet) + else displayShipVert(parseInt(num), ship, this, fleet) + }) +} + + +function displayShipHorz(location, ship, point, fleet) { + var endPoint = location + ship.length - 2 + if (!(endPoint % 10 >= 0 && endPoint % 10 < ship.length - 1)) { + for (var i = location; i < (location + ship.length); i++) { + $(".bottom ." + i).addClass("highlight") + } + $(point).off("click").on("click", function () { + setShip(location, ship, "horz", fleet, "self") + }) + } + $(point).off("mouseleave").on("mouseleave", function () { + removeShipHorz(location, ship.length) + }) +} + +function displayShipVert(location, ship, point, fleet) { + var endPoint = (ship.length * 10) - 10 + var inc = 0 + if (location + endPoint <= 100) { + for (var i = location; i < (location + ship.length); i++) { + $(".bottom ." + (location + inc)).addClass("highlight") + inc = inc + 10 + } + $(point).off("click").on("click", function () { + setShip(location, ship, "vert", fleet, "self") + }) + } + $(point).off("mouseleave").on("mouseleave", function () { + removeShipVert(location, ship.length) + }) +} + +function removeShipHorz(location, length) { + for (var i = location; i < location + length; i++) { + $(".bottom ." + i).removeClass("highlight") + } +} + +function removeShipVert(location, length) { + var inc = 0 + for (var i = location; i < location + length; i++) { + $(".bottom ." + (location + inc)).removeClass("highlight") + inc = inc + 10 + } +} + +function setShip(location, ship, orientation, genericFleet, type) { + if (!(checkOverlap(location, ship.length, orientation, genericFleet))) { + if (orientation == "horz") { + genericFleet.ships[genericFleet.currentShip].populateHorzHits(location) + $(".text").text(output.placed(genericFleet.ships[genericFleet.currentShip].name + " has")) + for (var i = location; i < (location + ship.length); i++) { + $(".bottom ." + i).addClass(genericFleet.ships[genericFleet.currentShip].name) + $(".bottom ." + i).children().removeClass("hole") + } + if (++genericFleet.currentShip == genericFleet.numOfShips) { + $(".text").text(output.placed("ships have")) + $(".bottom").find(".points").off("mouseenter") + // clear the call stack + setTimeout(createCpuFleet, 100) + } else { + if (type == "random") randomSetup(genericFleet) + else placeShip(genericFleet.ships[genericFleet.currentShip], genericFleet) + } + + } else { + var inc = 0 + genericFleet.ships[genericFleet.currentShip].populateVertHits(location) + $(".text").text(output.placed(genericFleet.ships[genericFleet.currentShip].name + " has")) + for (var i = location; i < (location + ship.length); i++) { + $(".bottom ." + (location + inc)).addClass(genericFleet.ships[genericFleet.currentShip].name) + $(".bottom ." + (location + inc)).children().removeClass("hole") + inc = inc + 10 + } + if (++genericFleet.currentShip == genericFleet.numOfShips) { + $(".text").text(output.placed("ships have")) + $(".bottom").find(".points").off("mouseenter") + // clear the call stack + setTimeout(createCpuFleet, 100) + } else { + if (type == "random") randomSetup(genericFleet) + else placeShip(genericFleet.ships[genericFleet.currentShip], genericFleet) + } + } + } else { + if (type == "random") randomSetup(genericFleet) + else $(".text").text(output.overlap) + } +} // end of setShip() + +function checkOverlap(location, length, orientation, genFleet) { + var loc = location + if (orientation == "horz") { + var end = location + length + for (; location < end; location++) { + for (var i = 0; i < genFleet.currentShip; i++) { + if (genFleet.ships[i].checkLocation(location)) { + if (genFleet == cpuFleet) randomSetup(genFleet) + else return true + } + } // end of for loop + } // end of for loop + } else { + var end = location + (10 * length) + for (; location < end; location += 10) { + for (var i = 0; i < genFleet.currentShip; i++) { + if (genFleet.ships[i].checkLocation(location)) { + if (genFleet == cpuFleet) randomSetup(genFleet) + else return true + } + } + } + } // end of if/else + if (genFleet == cpuFleet && genFleet.currentShip < genFleet.numOfShips) { + if (orientation == "horz") genFleet.ships[genFleet.currentShip++].populateHorzHits(loc) + else genFleet.ships[genFleet.currentShip++].populateVertHits(loc) + if (genFleet.currentShip == genFleet.numOfShips) { + // clear the call stack + setTimeout(startGame, 500) + } else randomSetup(genFleet) + } + return false +} // end of checkOverlap() + + +function startGame() { + $(".layout").fadeOut("fast", function () { + $(".console").css({ "margin-top": "31px" }) + }) + $(".text").text(output.start) + // Generate all possible hits for Player 1 + for (var i = 0; i < 100; i++) bot.randPool[i] = i + 1 + highlightBoard() +} + +function highlightBoard() { + if (playerFleet.ships.length == 0) { + $(".top").find(".points").off("mouseenter").off("mouseleave").off("click") + } else { + $(".top").find(".points").off("mouseenter mouseover").on("mouseenter mouseover", function () { + // only allow target highlight on none attempts + if (!($(this).hasClass("used"))) topBoard.highlight(this) + }) + } +} diff --git a/参考项目/bs/style.css b/参考项目/bs/style.css new file mode 100644 index 0000000..cc7bd11 --- /dev/null +++ b/参考项目/bs/style.css @@ -0,0 +1,350 @@ +@import url(https://fonts.googleapis.com/css?family=Roboto:400,700); + +* { + margin: 0; + padding: 0; +} + +html { + width: 100%; + height: 100%; +} + +#main { + width: 700px; + height: 800px; + margin: auto; + +} + +.board { + position: absolute; + width: 380px; + height: 740px; + margin: 25px auto; + border: 2px solid #73B1B7; + border-radius: 10px; +} + +.displays { + position: relative; + margin: 25px; +} + +.top { + width: 330px; + height: 330px; + background: #008B8B; + border-left: 1px solid #8DEEEE; + border-bottom: 1px solid #8DEEEE; + +} + +.bottom { + width: 330px; + height: 330px; + margin-top: 25px; + background: #008B8B; + border-left: 1px solid #8DEEEE; + border-bottom: 1px solid #8DEEEE; +} + +.grid { + position: absolute; + width: 300px; + height: 300px; + background: rgba(0, 0, 0, 0); + margin-left: 30px; + font-size: 0; +} + +.aTops { + width: 29px; + height: 29px; + border-top: 1px solid #8DEEEE; + border-right: 1px solid #8DEEEE; + display: table-cell; + vertical-align: middle; + + font-weight: bold; + color: white; + text-align: center; +} + +.aLeft { + position: relative; + width: 29px; + height: 29px; + border-top: 1px solid #8DEEEE; + border-right: 1px solid #8DEEEE; + display: block; + line-height: 29px; + + font-weight: bold; + color: white; + text-align: center; +} + +.points { + position: relative; + width: 29px; + height: 29px; + border-top: 1px solid #8DEEEE; + border-right: 1px solid #8DEEEE; + display: inline-block; + + +} + +.highlight { + background: rgba(144, 144, 144, 0.9); +} + +.hidezero { + color: #008B8B; +} + +.hole { + position: relative; + width: 10px; + height: 10px; + margin: 9px; + border: 1px solid #8DEEEE; + border-radius: 50%; + display: table; +} + + +.panel { + float: right; + width: 275px; + height: 740px; + margin-top: 25px; +} + +.topPanel { + width: 275px; + height: 350px; + border: 2px solid #73B1B7; + border-radius: 10px; + display: inline-block; +} + +.bottomPanel {} + +.console { + position: relative; + width: 275px; + height: 350px; + margin-top: 36px; + display: block; + + background: rgba(144, 144, 144, 0.6); + border: 2px solid #73B1B7; + border-radius: 10px; + + color: green; +} + +.text { + position: relative; + width: 250px; + height: 375px; + margin: 12px; + display: inline-block; +} + +.buttons { + position: relative; + display: block; + width: 150px; + height: 40px; + + margin: 50px auto; + border: 2px solid #cccccc; + border-radius: 5px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + + text-align: center; + line-height: 40px; + + cursor: pointer; +} + +.buttons:hover { + background: rgba(169, 169, 169, 0.3); +} + +.target { + background: rgba(250, 10, 10, 0.7); +} + +.carrier { + background: rgba(36, 36, 36, 1); +} + +.battleship { + background: rgba(49, 49, 49, 0.9); +} + +.cruiser { + background: rgba(64, 64, 64, 0.9); +} + +.destroyer { + background: rgba(81, 81, 81, 0.7); +} + +.frigate { + background: rgba(100, 100, 100, 0.7); +} + +.one {} + +.self {} + +.random {} + +.error {} + +.turn {} + +.hit { + position: relative; + margin: 1.5px; + width: 15px; + height: 15px; + top: 5px; + left: 5px; + + + background: rgb(220, 10, 10); + border: 1px solid red; + border-radius: 100%; + overflow: hidden; + + display: table; + + animation-name: expand; + animation-duration: 0.5s; + animation-iteration-count: 1; + animation-timing-function: linear; + animation-fill-mode: none; + + -webkit-animation-name: expand; + -webkit-animation-duration: 0.5s; + -webkit-animation-iteration-count: 1; + -webkit-animation-timing-function: linear; + -webkit-animation-fill-mode: none; + + -moz-animation-name: expand; + -moz-animation-duration: 0.5s; + -moz-animation-iteration-count: 1; + -moz-animation-timing-function: linear; + -moz-animation-fill-mode: none; +} + +.miss { + position: relative; + margin: 1.5px; + width: 15px; + height: 15px; + top: 5px; + left: 5px; + + background: rgb(250, 250, 250); + border: 1px solid white; + border-radius: 100%; + overflow: hidden; + + display: table; + + animation: expand; + animation-duration: 0.5s; + animation-iteration-count: 1; + animation-timing-function: linear; + animation-fill-mode: none; + + -webkit-animation: expand; + -webkit-animation-duration: 0.5s; + -webkit-animation-iteration-count: 1; + -webkit-animation-timing-function: linear; + -webkit-animation-fill-mode: none; + + -moz-animation: expand; + -moz-animation-duration: 0.5s; + -moz-animation-iteration-count: 1; + -moz-animation-timing-function: linear; + -moz-animation-fill-mode: none; + +} + +@keyframes expand { + 0% { + width: 0px; + height: 0px; + top: 12.5px; + left: 12.5px; + } + + 50% { + width: 25px; + height: 25px; + top: 0px; + left: 0px; + } + + 100% { + width: 15px; + height: 15px; + top: 5px; + left: 5px; + } +} + +@-webkit-keyframes expand { + 0% { + width: 0px; + height: 0px; + top: 12.5px; + left: 12.5px; + } + + 50% { + width: 25px; + height: 25px; + top: 0px; + left: 0px; + } + + 100% { + width: 15px; + height: 15px; + top: 5px; + left: 5px; + } +} + +@-moz-keyframes expand { + 0% { + width: 0px; + height: 0px; + top: 12.5px; + left: 12.5px; + } + + 50% { + width: 25px; + height: 25px; + top: 0px; + left: 0px; + } + + 100% { + width: 15px; + height: 15px; + top: 5px; + left: 5px; + } +} diff --git a/参考项目/military-boats-collection_1284-37419.jpg b/参考项目/military-boats-collection_1284-37419.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6599240bdb1539950ec8d9967b50872e6bab4609 GIT binary patch literal 81849 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