adds first steps for the arcade game stroke fighter
|
|
@ -0,0 +1,12 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
|
||||
Kaboom based Game Engine for Rowing Games
|
||||
*/
|
||||
|
||||
import kaboom from 'kaboom'
|
||||
|
||||
export function createGameEngine (options) {
|
||||
return kaboom(options)
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
|
||||
Initializer for the Rowing Games
|
||||
*/
|
||||
|
||||
import { createGameEngine } from './GameEngine.js'
|
||||
import StrokeFighterBattleScene from './StrokeFighterBattleScene.js'
|
||||
|
||||
/**
|
||||
* creates and initializes the rowing games
|
||||
* @param {Element} canvasElement
|
||||
* @param {number} clientWidth
|
||||
* @param {number} clientHeight
|
||||
*/
|
||||
export function createRowingGames (canvasElement, clientWidth, clientHeight) {
|
||||
const k = createGameEngine({
|
||||
debug: true,
|
||||
global: false,
|
||||
canvas: canvasElement,
|
||||
crisp: true,
|
||||
width: clientWidth,
|
||||
height: clientHeight
|
||||
})
|
||||
// for now show debug infos all the time
|
||||
k.debug.inspect = true
|
||||
|
||||
// todo: once there are multiple games, asset loadingshould be moved to the individual games
|
||||
const assets = '/assets'
|
||||
const sprites = ['enemyBlack1', 'enemyBlue2', 'enemyGreen3', 'enemyRed4', 'enemyRed5', 'playerShip2_orange',
|
||||
'spaceShips_004', 'spaceShips_006', 'spaceShips_007', 'spaceShips_009', 'star1', 'star2', 'ufoGreen',
|
||||
'laserRed01', 'laserRed09']
|
||||
|
||||
for (const sprite of sprites) {
|
||||
k.loadSprite(sprite, `${assets}/sprites/${sprite}.png`)
|
||||
}
|
||||
k.loadSound('hit', `${assets}/sounds/explosionCrunch_000.ogg`)
|
||||
k.loadSound('shoot', `${assets}/sounds/laserSmall_001.ogg`)
|
||||
|
||||
k.scene('strokeFighterBattle', () => { StrokeFighterBattleScene(k) })
|
||||
|
||||
k.go('strokeFighterBattle')
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
|
||||
Creates a scrolling space background
|
||||
*/
|
||||
|
||||
const STAR_SPEED = 20
|
||||
const STAR_SPRITE_NAMES = ['star1', 'star2']
|
||||
const STAR_NUM = 10
|
||||
|
||||
export default function addSpaceBackground (k) {
|
||||
k.add([
|
||||
k.rect(k.width() + 50, k.height() + 50),
|
||||
k.pos(-25, -25),
|
||||
k.color(0, 0, 0),
|
||||
k.layer('background')
|
||||
])
|
||||
|
||||
for (let i = 0; i < STAR_NUM; i++) {
|
||||
addStar(false)
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a star at a random position
|
||||
* @param {boolean} respawn defines whether this is an initial star or a respawn
|
||||
*/
|
||||
function addStar (respawn) {
|
||||
const spriteName = k.choose(STAR_SPRITE_NAMES)
|
||||
const position = k.rand(k.vec2(0, respawn ? -50 : 0), k.vec2(k.width(), respawn ? 0 : k.height()))
|
||||
|
||||
const starColor = k.rand(120, 200)
|
||||
k.add([
|
||||
k.sprite(spriteName),
|
||||
k.scale(k.rand(0.2, 0.7)),
|
||||
k.color(starColor, starColor, starColor),
|
||||
k.layer('background'),
|
||||
k.pos(position),
|
||||
'star',
|
||||
{ speed: k.rand(STAR_SPEED * 0.5, STAR_SPEED * 1.5) }
|
||||
])
|
||||
}
|
||||
|
||||
k.onUpdate('star', (component) => {
|
||||
component.move(0, component.speed)
|
||||
if (component.pos.y - component.height > k.height()) {
|
||||
k.destroy(component)
|
||||
addStar(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
|
||||
Implements the Battle Actions of the Stroke Fighter Game
|
||||
*/
|
||||
|
||||
import addSpaceBackground from './SpaceBackground.js'
|
||||
|
||||
const ENEMY_SPRITE_NAMES = ['enemyBlack1', 'enemyBlue2', 'enemyGreen3', 'enemyRed4', 'enemyRed5',
|
||||
'spaceShips_004', 'spaceShips_006', 'spaceShips_007', 'spaceShips_009', 'ufoGreen']
|
||||
|
||||
export default function StrokeFighterBattleScene (k) {
|
||||
const BULLET_SPEED = 1200
|
||||
const ENEMY_SPEED = 60
|
||||
const PLAYER_SPEED = 480
|
||||
const ENEMY_HEALTH = 4
|
||||
const SPRITE_WIDTH = 90
|
||||
|
||||
k.layers([
|
||||
'background',
|
||||
'game',
|
||||
'ui'
|
||||
], 'game')
|
||||
|
||||
addSpaceBackground(k)
|
||||
|
||||
function grow (rate) {
|
||||
return {
|
||||
update () {
|
||||
const n = rate * k.dt()
|
||||
this.scale.x += n
|
||||
this.scale.y += n
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const player = k.add([
|
||||
k.sprite('playerShip2_orange'),
|
||||
k.area(),
|
||||
k.pos(k.width() / 2, k.height() - 64),
|
||||
k.origin('center')
|
||||
])
|
||||
|
||||
function moveLeft () {
|
||||
player.move(-PLAYER_SPEED, 0)
|
||||
if (player.pos.x < 0) {
|
||||
player.pos.x = k.width()
|
||||
}
|
||||
}
|
||||
|
||||
function moveRight () {
|
||||
player.move(PLAYER_SPEED, 0)
|
||||
if (player.pos.x > k.width()) {
|
||||
player.pos.x = 0
|
||||
}
|
||||
}
|
||||
|
||||
player.onCollide('enemy', (e) => {
|
||||
k.destroy(e)
|
||||
k.shake(4)
|
||||
k.play('hit', {
|
||||
detune: -1200,
|
||||
volume: 0.3,
|
||||
speed: k.rand(0.5, 2)
|
||||
})
|
||||
})
|
||||
|
||||
player.onUpdate(() => {
|
||||
const tolerance = 10
|
||||
const closestEnemy = k.get('enemy').reduce((prev, enemy) => { return enemy?.pos.y > prev?.pos.y ? enemy : prev }, { pos: { y: 0 } })
|
||||
if (closestEnemy?.pos?.x) {
|
||||
if (closestEnemy.pos.x > player.pos.x + tolerance) {
|
||||
moveRight()
|
||||
} else if (closestEnemy.pos.x < player.pos.x - tolerance) {
|
||||
moveLeft()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function addLaserHit (p, n) {
|
||||
for (let i = 0; i < n; i++) {
|
||||
k.wait(k.rand(n * 0.1), () => {
|
||||
for (let i = 0; i < 2; i++) {
|
||||
k.add([
|
||||
k.sprite('laserRed09'),
|
||||
k.pos(p.sub(0, 10)),
|
||||
k.scale(k.vec2(0.5)),
|
||||
k.lifespan(0.1),
|
||||
grow(k.rand(0.5, 2)),
|
||||
k.origin('center')
|
||||
])
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function spawnBullet (p) {
|
||||
k.add([
|
||||
k.sprite('laserRed01'),
|
||||
k.area(),
|
||||
k.pos(p),
|
||||
k.origin('center'),
|
||||
k.move(k.UP, BULLET_SPEED),
|
||||
k.cleanup(),
|
||||
'bullet'
|
||||
])
|
||||
}
|
||||
|
||||
// todo: this should be triggered by a finished rowing drive phase
|
||||
k.onKeyPress('space', () => {
|
||||
spawnBullet(player.pos.sub(16, 15))
|
||||
spawnBullet(player.pos.add(16, -15))
|
||||
k.play('shoot', {
|
||||
volume: 0.3,
|
||||
detune: k.rand(-1200, 1200)
|
||||
})
|
||||
})
|
||||
|
||||
function spawnEnemy () {
|
||||
const name = k.choose(ENEMY_SPRITE_NAMES)
|
||||
k.add([
|
||||
k.sprite(name),
|
||||
k.area(),
|
||||
k.pos(k.rand(0 + SPRITE_WIDTH / 2, k.width() - SPRITE_WIDTH / 2), 0),
|
||||
k.health(ENEMY_HEALTH),
|
||||
k.origin('bot'),
|
||||
'enemy',
|
||||
{ speed: k.rand(ENEMY_SPEED * 0.5, ENEMY_SPEED * 1.5) }
|
||||
])
|
||||
k.wait(3, spawnEnemy)
|
||||
}
|
||||
|
||||
k.on('death', 'enemy', (e) => {
|
||||
k.destroy(e)
|
||||
k.shake(2)
|
||||
})
|
||||
|
||||
k.on('hurt', 'enemy', (e) => {
|
||||
k.shake(1)
|
||||
k.play('hit', {
|
||||
detune: k.rand(-1200, 1200),
|
||||
volume: 0.1,
|
||||
speed: k.rand(0.2, 2)
|
||||
})
|
||||
})
|
||||
|
||||
const timer = k.add([
|
||||
k.text(0),
|
||||
k.pos(12, 32),
|
||||
k.fixed(),
|
||||
k.layer('ui'),
|
||||
{ time: 0 }
|
||||
])
|
||||
|
||||
timer.onUpdate(() => {
|
||||
timer.time += k.dt()
|
||||
timer.text = timer.time.toFixed(2)
|
||||
})
|
||||
|
||||
k.onCollide('bullet', 'enemy', (b, e) => {
|
||||
k.destroy(b)
|
||||
e.hurt(1)
|
||||
addLaserHit(b.pos, 1)
|
||||
})
|
||||
|
||||
k.onUpdate('enemy', (sprite) => {
|
||||
sprite.move(0, sprite.speed)
|
||||
if (sprite.pos.y - sprite.height > k.height()) {
|
||||
k.destroy(sprite)
|
||||
}
|
||||
})
|
||||
spawnEnemy()
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 735 B |
|
After Width: | Height: | Size: 752 B |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 312 B |
|
After Width: | Height: | Size: 345 B |
|
After Width: | Height: | Size: 3.0 KiB |
|
|
@ -25,10 +25,10 @@ export class DashboardMetric extends AppElement {
|
|||
|
||||
render () {
|
||||
// 416 is the max width value of the battery bar in the SVG graphic
|
||||
const batteryWidth = this.batteryLevel * 416 / 100
|
||||
const batteryWidth = parseInt(this.batteryLevel) * 416 / 100
|
||||
|
||||
// if battery level is low, highlight the battery icon
|
||||
const iconClass = this.batteryLevel > 25 ? 'icon' : 'icon low-battery'
|
||||
const iconClass = parseInt(this.batteryLevel) > 25 ? 'icon' : 'icon low-battery'
|
||||
|
||||
return svg`
|
||||
<svg aria-hidden="true" focusable="false" class="${iconClass}" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512">
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { AppElement, html, css } from './AppElement.js'
|
||||
import { customElement, state } from 'lit/decorators.js'
|
||||
import { icon_undo, icon_expand, icon_compress, icon_poweroff, icon_bluetooth, icon_upload } from '../lib/icons.js'
|
||||
import { icon_undo, icon_expand, icon_compress, icon_poweroff, icon_bluetooth, icon_upload, icon_gamepad } from '../lib/icons.js'
|
||||
import './AppDialog.js'
|
||||
|
||||
@customElement('dashboard-actions')
|
||||
|
|
@ -65,6 +65,7 @@ export class DashboardActions extends AppElement {
|
|||
return html`
|
||||
<button @click=${this.reset}>${icon_undo}</button>
|
||||
${this.renderOptionalButtons()}
|
||||
<button @click=${this.openRowingGames}>${icon_gamepad}</button>
|
||||
<button @click=${this.switchPeripheralMode}>${icon_bluetooth}</button>
|
||||
<div class="peripheral-mode">${this.peripheralMode()}</div>
|
||||
${this.dialog ? this.dialog : ''}
|
||||
|
|
@ -129,6 +130,10 @@ export class DashboardActions extends AppElement {
|
|||
this.sendEvent('triggerAction', { command: 'reset' })
|
||||
}
|
||||
|
||||
openRowingGames () {
|
||||
this.sendEvent('triggerAction', { command: 'openRowingGames' })
|
||||
}
|
||||
|
||||
switchPeripheralMode () {
|
||||
this.sendEvent('triggerAction', { command: 'switchPeripheralMode' })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
|
||||
Wrapper for the Open Rowing Monitor rowing games
|
||||
*/
|
||||
|
||||
import { AppElement, html, css } from './AppElement.js'
|
||||
import { customElement } from 'lit/decorators.js'
|
||||
import { createRowingGames } from '../arcade/RowingGames.js'
|
||||
|
||||
@customElement('game-component')
|
||||
export class GameComponent extends AppElement {
|
||||
static styles = css`
|
||||
:host {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
#arcade {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
`
|
||||
render () {
|
||||
return html`<canvas id="arcade"></canvas>`
|
||||
}
|
||||
|
||||
firstUpdated () {
|
||||
const canvas = this.renderRoot.querySelector('#arcade')
|
||||
createRowingGames(canvas, canvas.clientWidth, canvas.clientHeight)
|
||||
}
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@
|
|||
--theme-font-color: #f5f5f5;
|
||||
--theme-warning-color: #ff0000;
|
||||
--theme-border-radius: 3px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
|
|
@ -34,6 +35,7 @@
|
|||
font-family: var(--theme-font-family);
|
||||
user-select: none;
|
||||
overscroll-behavior: contain;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@media (orientation: portrait) {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { customElement, state } from 'lit/decorators.js'
|
|||
import { APP_STATE } from './store/appState.js'
|
||||
import { createApp } from './lib/app.js'
|
||||
import './components/PerformanceDashboard.js'
|
||||
import './components/GameComponent.js'
|
||||
|
||||
@customElement('web-app')
|
||||
export class App extends LitElement {
|
||||
|
|
@ -55,9 +56,12 @@ export class App extends LitElement {
|
|||
return JSON.parse(JSON.stringify(this.appState))
|
||||
}
|
||||
|
||||
// once we have multiple views, then we would rather reference some kind of router here
|
||||
// instead of embedding the performance-dashboard directly
|
||||
// currently just toggle between games and dashboard, if this gets more complex we might use a router here...
|
||||
render () {
|
||||
return this.appState?.activeRoute === 'DASHBOARD' ? this.renderDashboard() : this.renderRowingGames()
|
||||
}
|
||||
|
||||
renderDashboard () {
|
||||
return html`
|
||||
<performance-dashboard
|
||||
.appState=${this.appState}
|
||||
|
|
@ -66,6 +70,12 @@ export class App extends LitElement {
|
|||
`
|
||||
}
|
||||
|
||||
renderRowingGames () {
|
||||
return html`
|
||||
<game-component></game-component>
|
||||
`
|
||||
}
|
||||
|
||||
// there is no need to put this initialization component into a shadow root
|
||||
createRenderRoot () {
|
||||
return this
|
||||
|
|
|
|||
|
|
@ -128,6 +128,10 @@ export function createApp (app) {
|
|||
if (socket)socket.send(JSON.stringify({ command: 'switchPeripheralMode' }))
|
||||
break
|
||||
}
|
||||
case 'openRowingGames': {
|
||||
app.updateState({ ...app.getState(), activeRoute: 'ROWINGGAMES' })
|
||||
break
|
||||
}
|
||||
case 'reset': {
|
||||
resetFields()
|
||||
if (socket)socket.send(JSON.stringify({ command: 'reset' }))
|
||||
|
|
|
|||
|
|
@ -25,3 +25,4 @@ export const icon_expand = svg`<svg aria-hidden="true" focusable="false" class="
|
|||
export const icon_compress = svg`<svg aria-hidden="true" focusable="false" class="icon" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M436 192H312c-13.3 0-24-10.7-24-24V44c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v84h84c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12zm-276-24V44c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v84H12c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h124c13.3 0 24-10.7 24-24zm0 300V344c0-13.3-10.7-24-24-24H12c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h84v84c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm192 0v-84h84c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12H312c-13.3 0-24 10.7-24 24v124c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12z"></path></svg>`
|
||||
export const icon_bluetooth = svg`<svg aria-hidden="true" focusable="false" class="icon" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M292.6 171.1L249.7 214l-.3-86 43.2 43.1m-43.2 219.8l43.1-43.1-42.9-42.9-.2 86zM416 259.4C416 465 344.1 512 230.9 512S32 465 32 259.4 115.4 0 228.6 0 416 53.9 416 259.4zm-158.5 0l79.4-88.6L211.8 36.5v176.9L138 139.6l-27 26.9 92.7 93-92.7 93 26.9 26.9 73.8-73.8 2.3 170 127.4-127.5-83.9-88.7z"></path></svg>`
|
||||
export const icon_upload = svg`<svg aria-hidden="true" focusable="false" class="icon" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M537.6 226.6c4.1-10.7 6.4-22.4 6.4-34.6 0-53-43-96-96-96-19.7 0-38.1 6-53.3 16.2C367 64.2 315.3 32 256 32c-88.4 0-160 71.6-160 160 0 2.7.1 5.4.2 8.1C40.2 219.8 0 273.2 0 336c0 79.5 64.5 144 144 144h368c70.7 0 128-57.3 128-128 0-61.9-44-113.6-102.4-125.4zM393.4 288H328v112c0 8.8-7.2 16-16 16h-48c-8.8 0-16-7.2-16-16V288h-65.4c-14.3 0-21.4-17.2-11.3-27.3l105.4-105.4c6.2-6.2 16.4-6.2 22.6 0l105.4 105.4c10.1 10.1 2.9 27.3-11.3 27.3z"></path></svg>`
|
||||
export const icon_gamepad = svg`<svg aria-hidden="true" focusable="false" class="icon" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M448 64H192C85.96 64 0 149.1 0 256s85.96 192 192 192h256c106 0 192-85.96 192-192S554 64 448 64zM247.1 280h-32v32c0 13.2-10.78 24-23.98 24c-13.2 0-24.02-10.8-24.02-24v-32L136 279.1C122.8 279.1 111.1 269.2 111.1 256c0-13.2 10.85-24.01 24.05-24.01L167.1 232v-32c0-13.2 10.82-24 24.02-24c13.2 0 23.98 10.8 23.98 24v32h32c13.2 0 24.02 10.8 24.02 24C271.1 269.2 261.2 280 247.1 280zM431.1 344c-22.12 0-39.1-17.87-39.1-39.1s17.87-40 39.1-40s39.1 17.88 39.1 40S454.1 344 431.1 344zM495.1 248c-22.12 0-39.1-17.87-39.1-39.1s17.87-40 39.1-40c22.12 0 39.1 17.88 39.1 40S518.1 248 495.1 248z"/></svg>`
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
export const APP_STATE = {
|
||||
// currently can be STANDALONE (Mobile Home Screen App), KIOSK (Raspberry Pi deployment) or '' (default)
|
||||
appMode: '',
|
||||
// currently can be DASHBOARD or 'ROWINGGAMES' (default)
|
||||
activeRoute: 'DASHBOARD',
|
||||
// contains all the rowing metrics that are delivered from the backend
|
||||
metrics: {},
|
||||
config: {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
"ant-plus": "0.1.24",
|
||||
"finalhandler": "1.1.2",
|
||||
"form-data": "4.0.0",
|
||||
"kaboom": "2000.2.7",
|
||||
"lit": "2.1.3",
|
||||
"loglevel": "1.8.0",
|
||||
"nosleep.js": "0.12.0",
|
||||
|
|
@ -3372,9 +3373,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001311",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001311.tgz",
|
||||
"integrity": "sha512-mleTFtFKfykEeW34EyfhGIFjGCqzhh38Y0LhdQ9aWF+HorZTtdgKV/1hEE0NlFkG2ubvisPV6l400tlbPys98A==",
|
||||
"version": "1.0.30001312",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz",
|
||||
"integrity": "sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
|
|
@ -6640,6 +6641,11 @@
|
|||
"integrity": "sha512-TCa7ZdxCeq6q3Rgms2JCRHTCfWAETPZ8SzYUbkYF6KR3I03sN29DaOIC+xyWboIcMvjAsD5iG2u/RWzHD8XpgQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/kaboom": {
|
||||
"version": "2000.2.7",
|
||||
"resolved": "https://registry.npmjs.org/kaboom/-/kaboom-2000.2.7.tgz",
|
||||
"integrity": "sha512-CiEsmVdmufedNNvppMrVwVGYmao+WRsjE7M/TU4lFGYwUNwBPBVxORmsKvUmuvchw0cR+Dwcj1vAL+K8P06qGA=="
|
||||
},
|
||||
"node_modules/keyv": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.1.1.tgz",
|
||||
|
|
@ -7051,9 +7057,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz",
|
||||
"integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==",
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.1.tgz",
|
||||
"integrity": "sha512-reLxBcKUPNBnc/sVtAbxgRVFSegoGeLaSjmphNhcwcolhYLRgtJscn5mRl6YRZNQv40Y7P6JM2YhSIsbL9OB5A==",
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
|
|
@ -13733,9 +13739,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001311",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001311.tgz",
|
||||
"integrity": "sha512-mleTFtFKfykEeW34EyfhGIFjGCqzhh38Y0LhdQ9aWF+HorZTtdgKV/1hEE0NlFkG2ubvisPV6l400tlbPys98A==",
|
||||
"version": "1.0.30001312",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz",
|
||||
"integrity": "sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==",
|
||||
"dev": true
|
||||
},
|
||||
"caseless": {
|
||||
|
|
@ -16197,6 +16203,11 @@
|
|||
"integrity": "sha512-TCa7ZdxCeq6q3Rgms2JCRHTCfWAETPZ8SzYUbkYF6KR3I03sN29DaOIC+xyWboIcMvjAsD5iG2u/RWzHD8XpgQ==",
|
||||
"dev": true
|
||||
},
|
||||
"kaboom": {
|
||||
"version": "2000.2.7",
|
||||
"resolved": "https://registry.npmjs.org/kaboom/-/kaboom-2000.2.7.tgz",
|
||||
"integrity": "sha512-CiEsmVdmufedNNvppMrVwVGYmao+WRsjE7M/TU4lFGYwUNwBPBVxORmsKvUmuvchw0cR+Dwcj1vAL+K8P06qGA=="
|
||||
},
|
||||
"keyv": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.1.1.tgz",
|
||||
|
|
@ -16518,9 +16529,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz",
|
||||
"integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==",
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.1.tgz",
|
||||
"integrity": "sha512-reLxBcKUPNBnc/sVtAbxgRVFSegoGeLaSjmphNhcwcolhYLRgtJscn5mRl6YRZNQv40Y7P6JM2YhSIsbL9OB5A==",
|
||||
"devOptional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
"ant-plus": "0.1.24",
|
||||
"finalhandler": "1.1.2",
|
||||
"form-data": "4.0.0",
|
||||
"kaboom": "2000.2.7",
|
||||
"lit": "2.1.3",
|
||||
"loglevel": "1.8.0",
|
||||
"nosleep.js": "0.12.0",
|
||||
|
|
|
|||