Skip to content

Commit

Permalink
Merge pull request #9 from NMSCD/dev
Browse files Browse the repository at this point in the history
Add station limit warning; add new endpoints to the beginning
  • Loading branch information
Lenni009 authored Jul 21, 2024
2 parents 9c32047 + 9152a2f commit 9c28e81
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 58 deletions.
8 changes: 4 additions & 4 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ import { computed } from 'vue';
import { endpointToGlyphs } from './common';
const endpointData = useEndpointDataStore();
const { json, filter, filterType } = storeToRefs(endpointData);
const { allEndpoints, filter, filterType } = storeToRefs(endpointData);
const renderJson = computed(() => {
if (filter.value || filterType.value) {
return json.value.filter(
return allEndpoints.value.filter(
(item) =>
(!filter.value ||
item.Name.toLowerCase().includes(filter.value.toLowerCase()) ||
endpointToGlyphs(item).includes(filter.value.toUpperCase())) &&
(!filterType.value || item.TeleporterType === filterType.value)
);
} else {
return json.value;
return allEndpoints.value;
}
});
</script>
Expand Down Expand Up @@ -50,7 +50,7 @@ const renderJson = computed(() => {
</div>
<div class="endpoint-list mt-5 mb-6">
<EndpointCard
v-for="endpoint in json"
v-for="endpoint in allEndpoints.toReversed()"
v-show="renderJson.includes(endpoint)"
:endpoint-json="endpoint"
:key="endpoint.Name"
Expand Down
37 changes: 26 additions & 11 deletions src/components/CopyButton.vue
Original file line number Diff line number Diff line change
@@ -1,31 +1,46 @@
<script setup lang="ts">
import { useEndpointDataStore } from '@/store/endpointData';
import type { TeleportEndpoint, TeleporterTypes } from '@/types/teleportEndpoint';
import { maxStations } from '@/variables/limits';
import { storeToRefs } from 'pinia';
import { ref } from 'vue';
import { computed, ref } from 'vue';
const endpointData = useEndpointDataStore();
const { json } = storeToRefs(endpointData);
const { json, addedEndpoints, typeCounter } = storeToRefs(endpointData);
const defaultText = 'Copy modified JSON';
const buttonText = ref(defaultText);
const copied = ref(false);
const isCopied = ref(false);
const buttonText = computed(() => (isCopied.value ? 'Copied!' : 'Copy modified JSON'));
function getExcessEndpoints(arr: TeleportEndpoint[], type: TeleporterTypes) {
const endpointCount = typeCounter.value[type] ?? 0;
const excessEndpoints = Math.max(endpointCount - maxStations, 0);
const endpoints = arr.filter((item) => item.TeleporterType === type);
const removeStations = endpoints.slice(0, excessEndpoints);
return removeStations;
}
function copyJson() {
const indent = 2;
const displayTime = 1500;
navigator.clipboard.writeText(JSON.stringify(json.value, null, indent));
buttonText.value = 'Copied!';
copied.value = true;
const excessStations = getExcessEndpoints(json.value, 'Spacestation');
const excessStationsFixPos = getExcessEndpoints(json.value, 'SpacestationFixPosition');
const filteredEndpoints = json.value.filter(
(item) => !excessStations.includes(item) && !excessStationsFixPos.includes(item)
);
const combinedEndpoints = [...filteredEndpoints, ...addedEndpoints.value];
navigator.clipboard.writeText(JSON.stringify(combinedEndpoints, null, indent));
isCopied.value = true;
setTimeout(() => {
buttonText.value = defaultText;
copied.value = false;
isCopied.value = false;
}, displayTime);
}
</script>

<template>
<button
:class="{ 'no-interaction': copied, 'is-outlined': !copied }"
:class="{ 'no-interaction': isCopied, 'is-outlined': !isCopied }"
class="button is-success"
@click="copyJson"
>
Expand Down
73 changes: 55 additions & 18 deletions src/components/EditEndpointDialogue.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,33 @@ import { addressToXYZ, createEndpoint, endpointToGlyphs } from '@/common';
import { useId } from '@/helpers/id';
import { useEndpointDataStore } from '@/store/endpointData';
import type { DialogProps } from '@/types/props';
import { teleporterTypesEnum, type TeleporterTypes } from '@/types/teleportEndpoint';
import { teleporterTypes, type TeleporterTypes } from '@/types/teleportEndpoint';
import { maxStations } from '@/variables/limits';
import { storeToRefs } from 'pinia';
import { computed, ref } from 'vue';
import { computed, ref, watch } from 'vue';
const props = withDefaults(defineProps<DialogProps>(), {
open: false,
endpointData: () => createEndpoint(),
});
const endpointData = useEndpointDataStore();
const { json } = storeToRefs(endpointData);
const { addedEndpoints, typeCounter } = storeToRefs(endpointData);
const newEndpointName = ref<string>(props.endpointData.Name);
const newEndpointAddress = ref<string>(endpointToGlyphs(props.endpointData));
const newEndpointGalaxy = ref<string>((props.endpointData.UniverseAddress.RealityIndex + 1).toString());
const newEndpointType = ref<TeleporterTypes>(props.endpointData.TeleporterType);
const stationEndpoints = teleporterTypes.filter((item) => item.startsWith('Spacestation'));
const isNewEndpoint = computed(() => !props.endpointData.Name);
const editButtonText = computed(() => (isNewEndpoint.value ? 'Add Endpoint' : 'Save Changes'));
function resetEndpointInputs() {
newEndpointName.value = props.endpointData.Name;
newEndpointAddress.value = endpointToGlyphs(props.endpointData);
newEndpointGalaxy.value = (props.endpointData.UniverseAddress.RealityIndex + 1).toString();
newEndpointType.value = props.endpointData.TeleporterType;
changeInitialEndpointType();
}
function addEndpoint() {
Expand All @@ -46,7 +51,7 @@ function addEndpoint() {
planet: PlanetIndex,
});
if (props.endpointData.Name) {
if (!isNewEndpoint.value) {
const locationData = addressToXYZ(newEndpointAddress.value);
if (!locationData) return;
const { VoxelX, VoxelY, VoxelZ, SolarSystemIndex, PlanetIndex } = locationData;
Expand All @@ -60,7 +65,9 @@ function addEndpoint() {
props.endpointData.UniverseAddress.RealityIndex = parseInt(newEndpointGalaxy.value) - 1;
props.endpointData.TeleporterType = newEndpointType.value;
} else {
json.value.unshift(endpoint);
// start of the array: oldest (bottom of list in game)
// end of the array: newest (top of list in game)
addedEndpoints.value.unshift(endpoint);
}
// reset to initial state
Expand All @@ -74,15 +81,37 @@ const ids = {
galaxyInput: 'galaxyInput' + uniqueId,
};
const editButtonText = computed(() => (props.endpointData.Name ? 'Save Changes' : 'Add Endpoint'));
const isOutOfSafeRange = computed(() => {
const systemIndex = newEndpointAddress.value.substring(1, 4);
const systemNumber = parseInt(systemIndex, 16);
const lastSafeIndex = 122;
const aboveSafeRange = systemNumber > lastSafeIndex;
return aboveSafeRange && endpointToGlyphs(props.endpointData) !== newEndpointAddress.value;
});
const isOverLimit = computed(() => {
const amountOfTypeEndpoints = typeCounter.value[newEndpointType.value] ?? 0;
// case 1: editing existing endpoint, but not changing type (total must be > max)
// case 2: editing existing endpoint, but changing type (total + 1 must be > max)
// case 3: adding new endpoint (total + 1 must be > max)
return (
(!isNewEndpoint.value && amountOfTypeEndpoints > maxStations) ||
((isNewEndpoint.value || props.endpointData.TeleporterType !== newEndpointType.value) &&
amountOfTypeEndpoints + 1 > maxStations)
);
});
const amountOverLimit = computed(() => Math.max((typeCounter.value[newEndpointType.value] ?? 0) - maxStations, 1));
function changeInitialEndpointType() {
if ((typeCounter.value.Spacestation ?? 0) + 1 > maxStations && isNewEndpoint.value) {
newEndpointType.value = 'SpacestationFixPosition';
} else {
newEndpointType.value = props.endpointData.TeleporterType;
}
}
watch(typeCounter, changeInitialEndpointType);
</script>

<template>
Expand Down Expand Up @@ -124,15 +153,23 @@ const isOutOfSafeRange = computed(() => {
type="text"
/>
<label>Type:</label>
<div class="select">
<select v-model="newEndpointType">
<option
v-for="endpointType in teleporterTypesEnum"
:value="endpointType"
>
{{ endpointType }}
</option>
</select>
<div>
<div class="select">
<select v-model="newEndpointType">
<option
v-for="endpointType in isNewEndpoint ? stationEndpoints : teleporterTypes"
:value="endpointType"
>
{{ endpointType }}
</option>
</select>
</div>
<p
v-if="isOverLimit"
class="warning mt-1 p-1"
>
Warning: Too many {{ newEndpointType }} endpoints. {{ amountOverLimit }} will be removed.
</p>
</div>
</form>

Expand Down
3 changes: 2 additions & 1 deletion src/components/EndpointCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ const props = defineProps<{
}>();
const endpointData = useEndpointDataStore();
const { json } = storeToRefs(endpointData);
const { json, addedEndpoints } = storeToRefs(endpointData);
const address = computed(() => endpointToGlyphs(props.endpointJson));
function removeEndpoint() {
json.value = json.value.filter((t) => t !== props.endpointJson);
addedEndpoints.value = addedEndpoints.value.filter((t) => t !== props.endpointJson);
}
</script>

Expand Down
9 changes: 3 additions & 6 deletions src/components/FilterInput.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
<script setup lang="ts">
import { useEndpointDataStore } from '@/store/endpointData';
import { teleporterTypesEnum } from '@/types/teleportEndpoint';
import { teleporterTypes } from '@/types/teleportEndpoint';
import { storeToRefs } from 'pinia';
import FilterInputWrapper from './FilterInputWrapper.vue';
const endpointData = useEndpointDataStore();
const { filter, filterType } = storeToRefs(endpointData);
// what the actual fuck is this, please explain what the hell this empty string property is
const teleporterFilterTypes = {
'': '',
...teleporterTypesEnum,
};
// These are the possible filters. You can either filter by all teleporter types, or by nothing.
const teleporterFilterTypes = ['', ...teleporterTypes];
</script>

<template>
Expand Down
15 changes: 15 additions & 0 deletions src/store/endpointData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { defineStore } from 'pinia';
interface State {
jsonInputString: string;
json: TeleportEndpoint[];
addedEndpoints: TeleportEndpoint[];
filter: string;
filterType: TeleporterTypes | '';
jsonError: boolean;
Expand All @@ -13,11 +14,25 @@ export const useEndpointDataStore = defineStore('endpointData', {
state: (): State => ({
jsonInputString: '',
json: [],
addedEndpoints: [],
filter: '',
filterType: '',
jsonError: false,
}),

getters: {
allEndpoints: (state) => [...state.json, ...state.addedEndpoints],
typeCounter() {
const counter: Partial<Record<TeleporterTypes, number>> = {};
for (const endpoint of this.allEndpoints) {
const type = endpoint.TeleporterType;
counter[type] ??= 0;
counter[type]++;
}
return counter;
},
},

actions: {
parseJson() {
try {
Expand Down
21 changes: 19 additions & 2 deletions src/style/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@
url('/NMS-Glyphs-Mono.ttf') format('truetype');
}

:root {
--link-hover: #363636;
}

@media (prefers-color-scheme: dark) {
:root {
--link-hover: #c9c9c9;
}
}

html {
scrollbar-gutter: stable;
}
Expand All @@ -22,6 +32,13 @@ html {
}
}

.select select {
width: 100%;
.select {
&,
select {
width: 100%;
}
}

a:hover {
color: var(--link-hover);
}
41 changes: 25 additions & 16 deletions src/types/teleportEndpoint.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
export const teleporterTypesEnum = {
Base: 'Base',
Spacestation: 'Spacestation',
Atlas: 'Atlas',
PlanetAwayFromShip: 'PlanetAwayFromShip',
ExternalBase: 'ExternalBase',
EmergencyGalaxyFix: 'EmergencyGalaxyFix',
OnNexus: 'OnNexus',
SpacestationFixPosition: 'SpacestationFixPosition',
Settlement: 'Settlement',
Freighter: 'Freighter',
Frigate: 'Frigate',
} as const;
export type TeleporterTypes =
| 'Base'
| 'Spacestation'
| 'Atlas'
| 'PlanetAwayFromShip'
| 'ExternalBase'
| 'EmergencyGalaxyFix'
| 'OnNexus'
| 'SpacestationFixPosition'
| 'Settlement'
| 'Freighter'
| 'Frigate';

type ObjectValues<T> = T[keyof T];

export type TeleporterTypes = ObjectValues<typeof teleporterTypesEnum>;
export const teleporterTypes: TeleporterTypes[] = [
'Atlas',
'Base',
'EmergencyGalaxyFix',
'ExternalBase',
'Freighter',
'Frigate',
'OnNexus',
'PlanetAwayFromShip',
'Settlement',
'Spacestation',
'SpacestationFixPosition',
];

export interface TeleportEndpoint {
UniverseAddress: {
Expand Down
1 change: 1 addition & 0 deletions src/variables/limits.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const maxStations = 70;

0 comments on commit 9c28e81

Please sign in to comment.