feat: implement BarChart for MVP

This commit is contained in:
julius 2025-02-24 16:51:50 +01:00
parent 978aafc204
commit 5fef47f692
Signed by: julius
GPG Key ID: C80A63E6A5FD7092
4 changed files with 40 additions and 6 deletions

View File

@ -6,8 +6,9 @@ from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from sqlmodel import Session, func, select from sqlmodel import Session, func, select
from sqlmodel.sql.expression import SelectOfScalar from sqlmodel.sql.expression import SelectOfScalar
from db import Chemistry, Player, engine from db import Chemistry, MVPRanking, Player, engine
import networkx as nx import networkx as nx
import numpy as np
import matplotlib import matplotlib
matplotlib.use("agg") matplotlib.use("agg")
@ -18,6 +19,7 @@ analysis_router = APIRouter(prefix="/analysis")
C = Chemistry C = Chemistry
R = MVPRanking
P = Player P = Player
@ -192,9 +194,31 @@ async def render_sociogram(params: Params):
return {"image": encoded_image} return {"image": encoded_image}
def mvp():
ranks = dict()
with Session(engine) as session:
subquery = (
select(R.user, func.max(R.time).label("latest"))
.where(R.time > datetime(2025, 2, 8))
.group_by(R.user)
.subquery()
)
statement2 = select(R).join(
subquery, (R.user == subquery.c.user) & (R.time == subquery.c.latest)
)
for r in session.exec(statement2):
for i, p in enumerate(r.mvps):
ranks[p] = ranks.get(p, []) + [i + 1]
return [
{"name": p, "rank": f"{np.mean(v):.02f}", "std": f"{np.std(v):.02f}"}
for p, v in ranks.items()
]
analysis_router.add_api_route("/json", endpoint=sociogram_json, methods=["GET"]) analysis_router.add_api_route("/json", endpoint=sociogram_json, methods=["GET"])
analysis_router.add_api_route("/graph_json", endpoint=graph_json, methods=["GET"]) analysis_router.add_api_route("/graph_json", endpoint=graph_json, methods=["GET"])
analysis_router.add_api_route("/image", endpoint=render_sociogram, methods=["POST"]) analysis_router.add_api_route("/image", endpoint=render_sociogram, methods=["POST"])
analysis_router.add_api_route("/mvp", endpoint=mvp, methods=["GET"])
if __name__ == "__main__": if __name__ == "__main__":
with Session(engine) as session: with Session(engine) as session:

View File

@ -10,16 +10,16 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"react": "^18.3.1", "react": "18.3.1",
"react-dom": "^18.3.1", "react-dom": "18.3.1",
"react-sortablejs": "^6.1.4", "react-sortablejs": "^6.1.4",
"reagraph": "^4.21.2", "reagraph": "^4.21.2",
"sortablejs": "^1.15.6" "sortablejs": "^1.15.6"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.17.0", "@eslint/js": "^9.17.0",
"@types/react": "^18.3.18", "@types/react": "18.3.18",
"@types/react-dom": "^18.3.5", "@types/react-dom": "18.3.5",
"@types/sortablejs": "^1.15.8", "@types/sortablejs": "^1.15.8",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
"eslint": "^9.17.0", "eslint": "^9.17.0",

View File

@ -42,7 +42,7 @@ interface DeferredProps {
} }
let timeoutID: number | null = null; let timeoutID: NodeJS.Timeout | null = null;
export default function Analysis() { export default function Analysis() {
const [image, setImage] = useState(""); const [image, setImage] = useState("");
const [params, setParams] = useState<Params>({ const [params, setParams] = useState<Params>({

View File

@ -6,6 +6,7 @@ import Rankings from "./Rankings";
import { BrowserRouter, Routes, Route } from "react-router"; import { BrowserRouter, Routes, Route } from "react-router";
import { SessionProvider } from "./Session"; import { SessionProvider } from "./Session";
import { GraphComponent } from "./Network"; import { GraphComponent } from "./Network";
import MVPChart from "./MVPChart";
function App() { function App() {
return ( return (
@ -13,16 +14,25 @@ function App() {
<Header /> <Header />
<Routes> <Routes>
<Route index element={<Rankings />} /> <Route index element={<Rankings />} />
<Route path="/network" element={ <Route path="/network" element={
<SessionProvider> <SessionProvider>
<GraphComponent /> <GraphComponent />
</SessionProvider> </SessionProvider>
} /> } />
<Route path="/analysis" element={ <Route path="/analysis" element={
<SessionProvider> <SessionProvider>
<Analysis /> <Analysis />
</SessionProvider> </SessionProvider>
} /> } />
<Route path="/mvp" element={
<SessionProvider>
<MVPChart />
</SessionProvider>
} />
</Routes> </Routes>
<Footer /> <Footer />
</BrowserRouter> </BrowserRouter>