some kinda fuge state...
This commit is contained in:
@@ -15,12 +15,13 @@ app.get('/', (req, res) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
app.post('/api/serverstats/gamestats', jsonParser, async (req, res) => {
|
app.post('/api/serverstats/gamestats', jsonParser, async (req, res) => {
|
||||||
|
const monthId = req.body.monthId
|
||||||
let startSeconds = 0
|
let startSeconds = 0
|
||||||
let endSeconds = Number.MAX_SAFE_INTEGER
|
let endSeconds = Number.MAX_SAFE_INTEGER
|
||||||
|
|
||||||
if (req.body.monthId != -1) {
|
if (monthId != -1) {
|
||||||
const month = req.body.monthId % 12
|
const month = monthId % 12
|
||||||
const year = Math.floor(req.body.monthId / 12) + 2023
|
const year = Math.floor(monthId / 12) + 2023
|
||||||
|
|
||||||
const startDate = new Date(year, month, 1)
|
const startDate = new Date(year, month, 1)
|
||||||
const endDate = new Date(year, month + 1, -1)
|
const endDate = new Date(year, month + 1, -1)
|
||||||
@@ -35,6 +36,8 @@ app.post('/api/serverstats/gamestats', jsonParser, async (req, res) => {
|
|||||||
'SUM(CASE WHEN status = "Complete" THEN 1 ELSE 0 END) as Complete, ' +
|
'SUM(CASE WHEN status = "Complete" THEN 1 ELSE 0 END) as Complete, ' +
|
||||||
'SUM(CASE WHEN status = "Postponed" THEN 1 ELSE 0 END) as Postponed, ' +
|
'SUM(CASE WHEN status = "Postponed" THEN 1 ELSE 0 END) as Postponed, ' +
|
||||||
'SUM(CASE WHEN status = "Pending" THEN 1 ELSE 0 END) as Pending, ' +
|
'SUM(CASE WHEN status = "Pending" THEN 1 ELSE 0 END) as Pending, ' +
|
||||||
|
'SUM(payoutEB) as TotalEB, ' +
|
||||||
|
'SUM(payoutIP) as TotalIP, ' +
|
||||||
'SUM(payoutEB) / SUM(CASE WHEN status = "Complete" THEN 1 ELSE 0 END) as AverageEB, ' +
|
'SUM(payoutEB) / SUM(CASE WHEN status = "Complete" THEN 1 ELSE 0 END) as AverageEB, ' +
|
||||||
'SUM(payoutIP) / SUM(CASE WHEN status = "Complete" THEN 1 ELSE 0 END) as AverageIP ' +
|
'SUM(payoutIP) / SUM(CASE WHEN status = "Complete" THEN 1 ELSE 0 END) as AverageIP ' +
|
||||||
'FROM Games WHERE postdate BETWEEN :startSeconds AND :endSeconds',
|
'FROM Games WHERE postdate BETWEEN :startSeconds AND :endSeconds',
|
||||||
@@ -46,7 +49,90 @@ app.post('/api/serverstats/gamestats', jsonParser, async (req, res) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
res.json(serverGameStats[0])
|
res.send(serverGameStats[0])
|
||||||
|
})
|
||||||
|
|
||||||
|
app.post('/api/serverstats/rolestats', jsonParser, async (req, res) => {
|
||||||
|
const monthId = req.body.monthId
|
||||||
|
|
||||||
|
let startSeconds = 0
|
||||||
|
let endSeconds = Number.MAX_SAFE_INTEGER
|
||||||
|
|
||||||
|
if (monthId != -1) {
|
||||||
|
const month = monthId % 12
|
||||||
|
const year = Math.floor(monthId / 12) + 2023
|
||||||
|
|
||||||
|
const startDate = new Date(year, month, 1)
|
||||||
|
const endDate = new Date(year, month + 1, -1)
|
||||||
|
|
||||||
|
startSeconds = startDate.getTime() / 1000
|
||||||
|
endSeconds = endDate.getTime() / 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
const games = await Game.findAll({
|
||||||
|
include: [
|
||||||
|
{ model: Character, as: 'characterPickedForGame' },
|
||||||
|
{ model: Character, as: 'characterAppliedForGame' }
|
||||||
|
],
|
||||||
|
where: { postdate: { [Op.between]: [startSeconds, endSeconds] } }
|
||||||
|
})
|
||||||
|
|
||||||
|
// count active roles
|
||||||
|
let activeCharacters = new Map()
|
||||||
|
let pickedCharacterCount = new Map()
|
||||||
|
let appedCharacterCount = new Map()
|
||||||
|
|
||||||
|
games.forEach((game, gameNum) => {
|
||||||
|
const picks = game.dataValues.characterPickedForGame
|
||||||
|
const appls = game.dataValues.characterAppliedForGame
|
||||||
|
|
||||||
|
picks.forEach((character, characterNum) => {
|
||||||
|
const role = character.dataValues.role
|
||||||
|
// Count role application
|
||||||
|
pickedCharacterCount.set(
|
||||||
|
role, (pickedCharacterCount.get(role) || 0) + 1
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
appls.forEach((character, characterNum) => {
|
||||||
|
const role = character.dataValues.role
|
||||||
|
const charId = character.dataValues.id
|
||||||
|
// Add apllied characters to active list
|
||||||
|
if (!activeCharacters.has(role)) {
|
||||||
|
activeCharacters.set(role, new Set())
|
||||||
|
}
|
||||||
|
activeCharacters.get(role).add(charId)
|
||||||
|
// Count role application
|
||||||
|
appedCharacterCount.set(
|
||||||
|
role, (appedCharacterCount.get(role) || 0) + 1
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const roleNames = [
|
||||||
|
'Fixer',
|
||||||
|
'Tech',
|
||||||
|
'Medtech',
|
||||||
|
'Media',
|
||||||
|
'Netrunner',
|
||||||
|
'Solo',
|
||||||
|
'Nomad',
|
||||||
|
'Exec',
|
||||||
|
'Lawman',
|
||||||
|
'Rocker'
|
||||||
|
]
|
||||||
|
|
||||||
|
const result = {}
|
||||||
|
|
||||||
|
roleNames.forEach((roleName) => {
|
||||||
|
result[roleName] = {
|
||||||
|
apps: appedCharacterCount.get(roleName) || 0,
|
||||||
|
picks: pickedCharacterCount.get(roleName) || 0,
|
||||||
|
active: activeCharacters.has(roleName) ?activeCharacters.get(roleName).size : 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
res.send(result)
|
||||||
})
|
})
|
||||||
|
|
||||||
app.get('/api/character/:characterId', async (req, res) => {
|
app.get('/api/character/:characterId', async (req, res) => {
|
||||||
@@ -72,7 +158,7 @@ app.post('/api/character', jsonParser, async (req, res) => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
res.setHeader('Content-Type', 'application/json')
|
res.setHeader('Content-Type', 'application/json')
|
||||||
res.json({ characterData, pageCount })
|
res.send({ characterData, pageCount })
|
||||||
})
|
})
|
||||||
|
|
||||||
app.get('/api/game/:gameId', async (req, res) => {
|
app.get('/api/game/:gameId', async (req, res) => {
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ watch(route, (newValue, oldValue) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
let debounce = null
|
let debounce = null
|
||||||
watch(filtervalue, (oldFilter, newFilter) => {
|
watch(filtervalue, (newFilter, oldFilter) => {
|
||||||
debounce = clearTimeout(debounce)
|
debounce = clearTimeout(debounce)
|
||||||
debounce = setTimeout(() => {
|
debounce = setTimeout(() => {
|
||||||
loadData()
|
loadData()
|
||||||
|
|||||||
@@ -2,36 +2,46 @@
|
|||||||
<div class="d-flex flex-column">
|
<div class="d-flex flex-column">
|
||||||
<v-select class="date-selector" v-model="dateSelect" variant="underlined" :items="dateItems">
|
<v-select class="date-selector" v-model="dateSelect" variant="underlined" :items="dateItems">
|
||||||
</v-select>
|
</v-select>
|
||||||
<!-- <v-select class="graph-selector" v-model="graphSelect" variant="underlined" :items="graphItems">
|
<div class="stat-bar d-flex flex-row justify-space-around">
|
||||||
</v-select> -->
|
|
||||||
<div class="d-flex flex-row justify-space-around">
|
|
||||||
<div class="d-flex flex-column">
|
<div class="d-flex flex-column">
|
||||||
<v-label>Completed Games</v-label>
|
<v-label class="title">Completed Games</v-label>
|
||||||
<v-label>{{ gameStats.Complete }}</v-label>
|
<v-label>{{ gameStats.Complete }}</v-label>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex flex-column">
|
<div class="d-flex flex-column">
|
||||||
<v-label>Postponed Games</v-label>
|
<v-label class="title">Postponed Games</v-label>
|
||||||
<v-label>{{ gameStats.Postponed }}</v-label>
|
<v-label>{{ gameStats.Postponed }}</v-label>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex flex-column">
|
<div class="d-flex flex-column">
|
||||||
<v-label>Average EB</v-label>
|
<v-label class="title">Total / Average EB</v-label>
|
||||||
<v-label>{{ Math.floor(gameStats.AverageEB) }}</v-label>
|
<v-label
|
||||||
|
>{{ Math.floor(gameStats.TotalEB) }} / {{ Math.floor(gameStats.AverageEB) }}</v-label
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex flex-column">
|
<div class="d-flex flex-column">
|
||||||
<v-label>Average IP</v-label>
|
<v-label class="title">Total / Average IP</v-label>
|
||||||
<v-label>{{ Math.floor(gameStats.AverageIP) }}</v-label>
|
<v-label
|
||||||
|
>{{ Math.floor(gameStats.TotalIP) }} / {{ Math.floor(gameStats.AverageIP) }}</v-label
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex flex-column">
|
<div class="role-table d-flex flex-column">
|
||||||
<v-table>
|
<v-table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="text-left">Role</th>
|
<th class="text-left">Role</th>
|
||||||
|
<th class="text-center">Characters</th>
|
||||||
|
<th class="text-center">App Count</th>
|
||||||
|
<th class="text-center">Games Played</th>
|
||||||
|
<th class="text-center">% Games With Role</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr v-for="roleStat, roleName in roleStats">
|
||||||
<td>Solo</td>
|
<td>{{ roleName }}</td>
|
||||||
|
<td class="text-center">{{ roleStat.active }}</td>
|
||||||
|
<td class="text-center">{{ roleStat.apps }}</td>
|
||||||
|
<td class="text-center">{{ roleStat.picks }}</td>
|
||||||
|
<td class="text-center">{{ Math.floor((roleStat.picks / gameStats.Complete) * 100)}}%</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</v-table>
|
</v-table>
|
||||||
@@ -48,36 +58,51 @@
|
|||||||
margin-left: 15px;
|
margin-left: 15px;
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
}
|
}
|
||||||
|
.stat-bar {
|
||||||
|
padding: 10px;
|
||||||
|
margin-left: 15px;
|
||||||
|
margin-right: 15px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
.title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.role-table {
|
||||||
|
margin-left: 15px;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, ref } from 'vue'
|
import { onMounted, watch, ref } from 'vue'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
const dateSelect = ref('All Time')
|
const dateSelect = ref(-1)
|
||||||
|
|
||||||
const dateItems = ['All Time', 'May 2024']
|
const dateItems = [
|
||||||
|
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
|
||||||
|
]
|
||||||
|
|
||||||
const graphSelect = ref('All Time')
|
const gameStats = ref({})
|
||||||
|
|
||||||
const graphItems = ['All Time', 'May 2024']
|
const roleStats = ref({})
|
||||||
|
|
||||||
const gameStats = ref({
|
|
||||||
TotalGames: 0,
|
|
||||||
Complete: 0,
|
|
||||||
Postponed: 0,
|
|
||||||
Pending: 0,
|
|
||||||
AverageEB: 0,
|
|
||||||
AverageIP: 0
|
|
||||||
})
|
|
||||||
|
|
||||||
async function loadData() {
|
async function loadData() {
|
||||||
const response = await axios.post('/api/serverstats/gamestats', {
|
const gameStatsResponse = await axios.post('/api/serverstats/gamestats', {
|
||||||
monthId: -1
|
monthId: dateSelect.value
|
||||||
})
|
})
|
||||||
gameStats.value = response.data
|
gameStats.value = gameStatsResponse.data
|
||||||
|
|
||||||
|
const roleStatsResponse = await axios.post('/api/serverstats/rolestats', {
|
||||||
|
monthId: dateSelect.value
|
||||||
|
})
|
||||||
|
roleStats.value = roleStatsResponse.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(dateSelect, async (newValue, oldValue) => {
|
||||||
|
loadData()
|
||||||
|
})
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
loadData()
|
loadData()
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user