Skip to content

Commit

Permalink
Merge pull request #1 from NMSCD/dev
Browse files Browse the repository at this point in the history
Functioning app
  • Loading branch information
Lenni009 authored Feb 24, 2024
2 parents f33300b + 7225f34 commit 5300be0
Show file tree
Hide file tree
Showing 12 changed files with 301 additions and 17 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Building-Charts

This website shows you how many parts all your build take up, how many you have left, and which bases take up the most parts.
4 changes: 2 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
content="width=device-width, initial-scale=1"
name="viewport"
/>
<title>app-template</title>
<title>Building Charts</title>
<script
src="./src/main.ts"
type="module"
></script>
</head>

<body>
<div id="app"></div>
<div id="app" class="container"></div>
</body>
</html>
55 changes: 44 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "app-template",
"name": "building-charts",
"private": true,
"version": "0.0.0",
"type": "module",
Expand All @@ -19,7 +19,10 @@
},
"dependencies": {
"@vitejs/plugin-vue": "^5.0.2",
"bulma": "^0.9.4",
"chart.js": "^4.4.1",
"pinia": "^2.1.7",
"vue-chartjs": "^5.3.0",
"vue-tsc": "^1.8.27"
}
}
68 changes: 66 additions & 2 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,71 @@
<script setup lang="ts">
console.log('Hello Eisvana!');
import { computed, ref } from 'vue';
import BaseList from './components/BaseList.vue';
import type { Base } from '@/types/Base';
import PartChart from './components/PartChart.vue';
const isJsonInvalid = ref(false);
const baseJson = ref<Base[]>([]);
const totalBases = computed(() => baseJson.value.length);
const totalPartsUsed = computed(() => {
const objectCounts = baseJson.value.map((base) => base.Objects.length);
return objectCounts.reduce((prev, cur) => prev + cur, 0);
});
function parseOnInput(e: Event) {
if (!(e.target instanceof HTMLTextAreaElement)) return;
parseJson(e.target.value);
}
function parseJson(rawJson: string) {
try {
const parsedJson: Base[] = JSON.parse(rawJson);
isJsonInvalid.value = false;
const sortedJson = parsedJson.toSorted((a, b) => b.Objects.length - a.Objects.length);
baseJson.value = sortedJson;
} catch (error) {
isJsonInvalid.value = true;
console.warn(error);
}
}
</script>

<template>
<div>Hello Eisvana!</div>
<nav class="my-4 is-size-5">
<a
href=".."
title="Other pages"
>&larr; View other pages</a
>
</nav>
<h1 class="title is-3 has-text-centered">Building Charts</h1>
<div class="is-flex is-flex-direction-column">
<label
class="label"
for="json-input"
>Enter your PersistentPlayerBases JSON section here:</label
>
<textarea
class="textarea"
id="json-input"
@input="parseOnInput"
></textarea>
</div>
<p v-if="isJsonInvalid">
Something went wrong. Please make sure you copied the whole PersistentPlayerBases JSON section.
</p>
<div
v-if="baseJson.length"
class="my-4"
>
<p>Total Number of Bases: {{ totalBases }}</p>
<p>Total Parts Used: {{ totalPartsUsed }}</p>
<BaseList :bases="baseJson" />
<PartChart
:bases="baseJson"
:total-parts="totalPartsUsed"
/>
</div>
</template>
26 changes: 26 additions & 0 deletions src/components/BaseItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script setup lang="ts">
import type { Base } from '@/types/Base';
import { computed } from 'vue';
const props = defineProps<{
base: Base;
}>();
const uploadLimit = 3000;
const isNotUploadable = computed(() => props.base.Objects.length >= uploadLimit);
</script>

<template>
<div class="card p-4">
<div>Name: {{ base.Name }}</div>
<div>
Parts:
<span
:class="{ 'has-text-danger': isNotUploadable }"
:title="isNotUploadable ? 'Cannot be uploaded' : undefined"
>{{ base.Objects.length }}</span
>
</div>
</div>
</template>
23 changes: 23 additions & 0 deletions src/components/BaseList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script setup lang="ts">
import type { Base } from '@/types/Base';
import BaseItem from './BaseItem.vue';
defineProps<{
bases: Base[];
}>();
</script>

<template>
<div class="base-list is-flex is-flex-wrap-wrap my-3">
<BaseItem
v-for="base in bases"
:base
/>
</div>
</template>

<style scoped lang="scss">
.base-list {
gap: 0.5rem;
}
</style>
79 changes: 79 additions & 0 deletions src/components/PartChart.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<script setup lang="ts">
import type { Base } from '@/types/Base';
import { computed, reactive } from 'vue';
import { Pie } from 'vue-chartjs';
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js';
ChartJS.register(ArcElement, Tooltip, Legend);
const props = defineProps<{
bases: Base[];
totalParts: number;
}>();
// min and max are both included
function getRndInteger(min: number, max: number) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
const minColourValue = 50;
const maxColourValue = 255;
function getRandomColour() {
const rgb = Array.from({ length: 3 }).map(() => getRndInteger(minColourValue, maxColourValue));
const hexCode = rgb.map((colour) => colour.toString(16)).join('');
return `#${hexCode}`;
}
const maxObjects = 16000;
const labels = computed(() => props.bases.map((base) => base.Name));
const objectCounts = computed(() => props.bases.map((base) => base.Objects.length));
const colours = computed(() => props.bases.map(getRandomColour));
const baseObjectsLeft = computed(() => maxObjects - props.totalParts);
const objectCountsWithBuffer = computed(() => [...objectCounts.value, baseObjectsLeft.value]);
const labelsWithBuffer = computed(() => [...labels.value, 'Unused']);
const coloursWithBuffer = computed(() => [...colours.value, '#333333']);
const baseData = reactive({
labels,
objectCounts,
colours,
labelsWithBuffer,
objectCountsWithBuffer,
coloursWithBuffer,
});
const data = computed(() => ({
labels: baseData.labelsWithBuffer,
datasets: [
{
backgroundColor: baseData.colours,
data: baseData.objectCounts,
},
{
backgroundColor: baseData.coloursWithBuffer,
data: baseData.objectCountsWithBuffer,
},
],
}));
const options = {
maintainAspectRatio: true,
};
</script>

<template>
<Pie
:data
:options
class="chart mx-auto"
/>
</template>

<style scoped lang="scss">
.chart {
width: min(100%, 800px);
}
</style>
1 change: 1 addition & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'bulma';
import '@/styles/styles.scss';
import App from './App.vue';
import { createApp } from 'vue';
Expand Down
Loading

0 comments on commit 5300be0

Please sign in to comment.