Add filtering on graph
This commit is contained in:
parent
dee0c26260
commit
3b1c3d7eb3
@ -1,3 +1,5 @@
|
||||
from collections import defaultdict
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request
|
||||
from fastapi.responses import HTMLResponse
|
||||
from sqlalchemy import and_, or_, func
|
||||
@ -9,7 +11,7 @@ from ..templates import jinja_templates
|
||||
from ..sql import crud, schemas
|
||||
from ..sql.database import get_db
|
||||
|
||||
from .players import list_players
|
||||
from .players import read_player, list_players
|
||||
from .games import _render_game_participants
|
||||
|
||||
api_router = APIRouter(prefix="/deck", tags=["deck"])
|
||||
@ -23,6 +25,19 @@ html_router = APIRouter(
|
||||
########
|
||||
|
||||
|
||||
@api_router.get("/by_player")
|
||||
def decks_by_player(db=Depends(get_db)):
|
||||
decks = crud.get_decks(db, skip=0, limit=-1)
|
||||
# TODO - could probably do this directly in-db with some fancy use of `group_concat`
|
||||
return_value = defaultdict(list)
|
||||
for deck in decks:
|
||||
# TODO - if we cared about latency, could cache this
|
||||
return_value[read_player(deck.owner_id, db).name].append(
|
||||
{"id": deck.id, "name": deck.name}
|
||||
)
|
||||
return return_value
|
||||
|
||||
|
||||
@api_router.post("/", response_model=schemas.Deck, status_code=201)
|
||||
def create_deck(deck: schemas.DeckCreate, db: Session = Depends(get_db)):
|
||||
db_player = crud.get_player_by_id(db, deck.owner_id)
|
||||
|
@ -1,4 +1,5 @@
|
||||
from collections import defaultdict
|
||||
from datetime import datetime, MINYEAR
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, Depends, Request
|
||||
@ -17,7 +18,11 @@ html_router = APIRouter(
|
||||
|
||||
|
||||
@api_router.get("/graph")
|
||||
def stats_graph_api(deck_ids: Optional[str] = None, db=Depends(get_db)):
|
||||
def stats_graph_api(
|
||||
deck_ids: Optional[str] = None,
|
||||
normalize_final_datapoint: bool = False,
|
||||
db=Depends(get_db),
|
||||
):
|
||||
# TODO - parallelize? (Probably not worth it :P )
|
||||
|
||||
# SO Answer on row_number: https://stackoverflow.com/a/38160409/1040915
|
||||
@ -44,12 +49,26 @@ def stats_graph_api(deck_ids: Optional[str] = None, db=Depends(get_db)):
|
||||
results = query.all()
|
||||
|
||||
data_grouped_by_deck = defaultdict(list)
|
||||
latest_date_so_far = datetime(MINYEAR, 1, 1, 0, 0, 0, 0)
|
||||
for result in results:
|
||||
# TODO - how to index results by name instead of tuple-number
|
||||
date = result[2]
|
||||
latest_date_so_far = max(latest_date_so_far, date)
|
||||
data_grouped_by_deck[result[0]].append(
|
||||
{"score": result[1], "date": result[2].strftime("%Y-%m-%d")}
|
||||
{"score": result[1], "date": date.strftime("%Y-%m-%d")}
|
||||
)
|
||||
|
||||
if normalize_final_datapoint:
|
||||
# Add a fake final datapoint to the series for any decks that weren't played in the latest game, so that lines
|
||||
# continue all the way to the end of the graph
|
||||
latest_date_formatted = latest_date_so_far.strftime("%Y-%m-%d")
|
||||
print(f"DEBUG = {latest_date_formatted=}")
|
||||
for games in data_grouped_by_deck.values():
|
||||
if games[-1]["date"] != latest_date_formatted:
|
||||
games.append(
|
||||
{"score": games[-1]["score"], "date": latest_date_formatted}
|
||||
)
|
||||
|
||||
return {
|
||||
"datasets": [
|
||||
{"label": key, "data": data_grouped_by_deck[key]}
|
||||
|
5
app/static/css/graph.css
Normal file
5
app/static/css/graph.css
Normal file
@ -0,0 +1,5 @@
|
||||
#options div {
|
||||
float: left;
|
||||
margin: 2px;
|
||||
background-color: lightblue;
|
||||
}
|
@ -1,9 +1,35 @@
|
||||
function updateGraphWithFilter() {
|
||||
filterString = $('#options input[type=checkbox]:checked').map((idx, elem) => {
|
||||
console.log('Adding ' + elem.id + ' to return string')
|
||||
return elem.id
|
||||
}).get().join(',')
|
||||
console.log(filterString);
|
||||
fetch('/api/stats/graph?deck_ids=' + filterString)
|
||||
.then(response => response.json())
|
||||
.then(response => {
|
||||
window.chart.data.datasets = response.datasets
|
||||
window.chart.update()
|
||||
})
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#filter_button').click(updateGraphWithFilter)
|
||||
|
||||
fetch('/api/deck/by_player')
|
||||
.then(response => response.json())
|
||||
.then(response => {
|
||||
console.log(response);
|
||||
for (playerName in response) {
|
||||
buildPlayerDecksDiv($('#options'), playerName, response[playerName])
|
||||
}
|
||||
})
|
||||
|
||||
fetch('/api/stats/graph')
|
||||
.then(response => response.json())
|
||||
.then(response => {
|
||||
console.log(response.datasets);
|
||||
new Chart(
|
||||
window.chart = new Chart(
|
||||
document.getElementById('graph_canvas'),
|
||||
{
|
||||
type: 'line',
|
||||
@ -27,3 +53,14 @@ $(document).ready(function() {
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function buildPlayerDecksDiv(parentDiv, playerName, playerDecks) {
|
||||
div = $('<div>',
|
||||
id='player_div_for_' + playerName
|
||||
)
|
||||
div.append('<p>' + playerName + '</p>')
|
||||
for (deck of playerDecks) {
|
||||
div.append('<input type="checkbox" id="' + deck["id"] + '" name="' + deck["name"] + '" value="' + deck["name"] + '"><label for="' + deck["name"] + '">' + deck["name"] + '</label><br/>')
|
||||
}
|
||||
div.appendTo(parentDiv)
|
||||
}
|
||||
|
@ -8,8 +8,14 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/moment@2.27.0"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment@0.1.1"></script>
|
||||
<script src="/static/js/stats/graph.js"></script>
|
||||
<link rel="stylesheet" href="/static/css/graph.css"/>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="wrapper" style="width:95%;margin-left:10px;"><canvas id="graph_canvas"></canvas></div>
|
||||
|
||||
<div id="options">
|
||||
<h2>Filter</h2>
|
||||
<button id="filter_button">Go!</button><br/>
|
||||
</div>
|
||||
{% endblock %}
|
Loading…
x
Reference in New Issue
Block a user