From e80a54eb715f101777a4664a95c9b02c7393615e Mon Sep 17 00:00:00 2001 From: Neshura Date: Fri, 2 Jun 2023 01:06:04 +0200 Subject: [PATCH] Add Species Pie Chart --- app/api/species/route.ts | 87 ++++++++++++++++++++++++++++++++ app/page.tsx | 4 +- components/charts/pops.tsx | 100 +++++++++++++++++++++++++++++++++++++ types/stellaris.ts | 15 ++++++ 4 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 app/api/species/route.ts create mode 100644 components/charts/pops.tsx diff --git a/app/api/species/route.ts b/app/api/species/route.ts new file mode 100644 index 0000000..143d7a3 --- /dev/null +++ b/app/api/species/route.ts @@ -0,0 +1,87 @@ +import { google } from 'googleapis'; +import { NextResponse } from 'next/server'; + +export async function GET() { + const target = ['https://www.googleapis.com/auth/spreadsheets.readonly']; + const jwt = new google.auth.JWT( + process.env.API_EMAIL, + undefined, + (process.env.API_KEY || '').replace(/\\n/g, '\n'), + target + ); + + const sheets = google.sheets({ version: 'v4', auth: jwt }); + const response = await sheets.spreadsheets.get({ + spreadsheetId: process.env.SPREADSHEET_ID, + ranges: [ + 'Overview!B22:R22', + 'Overview!B23:S23', + 'Overview!B24:R24', + 'Overview!B25:S25', + 'Overview!B26:S26', + 'Overview!B27:Q27', + 'Overview!B28:Q28', + 'Overview!B29:Q29', + 'Overview!B30:P30', + 'Overview!B31:P31', + 'Overview!B32:P32', + 'Overview!B33:P33', + 'Overview!B34:O34', + ], + includeGridData: true, + }); + + const sheetsData = response.data.sheets; + if (sheetsData?.length) { + + const rows = sheetsData[0].data; + const merges = sheetsData[0].merges; + if (rows?.length) { + let rowLenghts = new Array; + if (rows[0].rowData?.length) { + rowLenghts = rows[0].rowData; + } + let speciesArray = new Array; + + for (let i = 0; i < rows.length; i++) { + let sRows = rows[i].rowData; + if (sRows?.length) { + let data = sRows[0].values; + if (data?.length) { + speciesArray[i] = 0; + for (let j = 0; j < data.length; j++) { + switch (data[j].userEnteredValue?.stringValue) { + case ("Taken"): { + speciesArray[i] = speciesArray[i] + 2; + break; + } + case ("A"): + case ("B"): + case ("-"): { + speciesArray[i] = speciesArray[i] + 1; + break; + } + } + } + + if (merges?.length) { + merges.forEach(merge => { + if (merge.startRowIndex && merge.startRowIndex - 21 == i) { + speciesArray[i] = speciesArray[i] + 2; + } + }); + } + } + else { + speciesArray[i] = 0; + } + } + } + + return NextResponse.json({ speciesArray }); + } + } + else { + return NextResponse.json({ status: 500 }) + } +} \ No newline at end of file diff --git a/app/page.tsx b/app/page.tsx index 92209fd..4687db0 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -3,17 +3,19 @@ import { useState } from 'react'; import {RadarChart} from '../components/charts/radar' import {EmpireStats} from '../components/tables/empires' import { Checkbox } from '@nextui-org/react'; +import { PopChart } from '@/components/charts/pops'; export default function Home() { const [weighted, setWeighted] = useState(true); return (
-
+
setWeighted(!weighted)}>Weighted Ethics
+
diff --git a/components/charts/pops.tsx b/components/charts/pops.tsx new file mode 100644 index 0000000..5ce7d8a --- /dev/null +++ b/components/charts/pops.tsx @@ -0,0 +1,100 @@ +'use client'; + +import useSWR from "swr"; +import { Chart as ChartJS, registerables } from 'chart.js'; +import { Pie } from "react-chartjs-2"; +import ChartDataLabels from 'chartjs-plugin-datalabels'; +import { Species } from '../../types/stellaris'; + +const fetcher = async (url:any) => await fetch(url).then((res) => res.json()); + +export const PopChart = () => { + const {data: tmpData} = useSWR('/api/species',fetcher); + + let data; + if (tmpData) { + let sData: Array = tmpData.speciesArray + data = { + labels: sData.map((_elem, idx) => { + return Species[idx]; + }), + datasets: [{ + label: 'Portrait Picks', + data: sData, + backgroundColor: [ + 'rgb(255, 200, 200)', + 'rgb(88, 47, 0)', + 'rgb(255, 205, 86)', + 'rgb(255, 255, 255)', + 'rgb(228, 120, 25)', + 'rgb(0, 247, 255)', + 'rgb(252, 1, 197)', + 'rgb(120, 205, 120)', + 'rgb(255, 60, 60)', + 'rgb(120, 60, 120)', + 'rgb(54, 162, 235)', + 'rgb(0, 255, 60)', + 'rgb(120, 120, 120)' + ], + hoverOffset: 4 + }] + }; + } + else { + data = { + labels: [], + datasets: [{ + data: [], + fill: true, + backgroundColor: '#254A6FAA', + borderColor: '#356A9F', + radius: 3 + }] + }; + } + + + const config = { + type: 'PIE', + data: data, + options: { + plugins: { + tooltip: { + callbacks: { + label: function(ctx: any) { + let sum = 0; + ctx.dataset.data.map((elem: number) => { + sum = sum + Number(elem) + }); + return (ctx.dataset.data[ctx.dataIndex]*100/sum).toFixed(1) + "% | " + ctx.dataset.data[ctx.dataIndex] + " / " + sum + } + } + }, + legend: { + display: true + }, + datalabels: { + formatter: (value: any, context: any) => { + if (value > 0) { + return Species[context.dataIndex]; + } + else { + return ""; + } + }, + anchor: 'center', + align: 'end', + color: 'black' + }, + }, + }, + }; + + ChartJS.register( ...registerables, ChartDataLabels ) + + return ( +
+ +
+ ); +} \ No newline at end of file diff --git a/types/stellaris.ts b/types/stellaris.ts index 8030106..8f10bcd 100644 --- a/types/stellaris.ts +++ b/types/stellaris.ts @@ -108,3 +108,18 @@ export enum Scale { fanatic = 2 } +export enum Species { + Humanoid = 0, + Mammalian = 1, + Reptilian = 2, + Avian = 3, + Arthropod = 4, + Molluscoid = 5, + Fungoid = 6, + Plantoid = 7, + Lithoid = 8, + Necroid = 9, + Aquatic = 10, + Toxoid = 11, + Machine = 12 +}