Compare commits
No commits in common. "ed6bf05a595c3e08ecab2402ed07333bece56bf2" and "4ed7c8062a87db93f444a4894df40cf1dc33510d" have entirely different histories.
ed6bf05a59
...
4ed7c8062a
@ -13,7 +13,6 @@
|
||||
"format": "prettier --write src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tauri-apps/plugin-fs": "~2",
|
||||
"file-saver": "^2.0.5",
|
||||
"fp-ts": "^2.16.9",
|
||||
"pinia": "^2.3.0",
|
||||
@ -25,7 +24,6 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.15",
|
||||
"@tauri-apps/cli": "^2.2.0",
|
||||
"@tsconfig/node22": "^22.0.0",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/node": "^22.10.2",
|
||||
|
||||
4
src-tauri/.gitignore
vendored
@ -1,4 +0,0 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
/gen/schemas
|
||||
4834
src-tauri/Cargo.lock
generated
@ -1,26 +0,0 @@
|
||||
[package]
|
||||
name = "app"
|
||||
version = "0.1.0"
|
||||
description = "A Tauri App"
|
||||
authors = ["you"]
|
||||
license = ""
|
||||
repository = ""
|
||||
edition = "2021"
|
||||
rust-version = "1.77.2"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
name = "app_lib"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.0.3", features = [] }
|
||||
|
||||
[dependencies]
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
log = "0.4"
|
||||
tauri = { version = "2.2.0", features = [] }
|
||||
tauri-plugin-log = "2.0.0-rc"
|
||||
tauri-plugin-fs = "2"
|
||||
@ -1,3 +0,0 @@
|
||||
fn main() {
|
||||
tauri_build::build()
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "default",
|
||||
"description": "enables the default permissions",
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"fs:default",
|
||||
{
|
||||
"identifier": "fs:scope",
|
||||
"allow": [{ "path": "$DOCUMENT/My Games/Path of Exile 2" }, { "path": "$DOCUMENT/My Games/Path of Exile 2/**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-write-text-file",
|
||||
"allow": [ { "path": "$DOCUMENT/My Games/Path of Exile 2/*" }]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 49 KiB |
@ -1,17 +0,0 @@
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_fs::init())
|
||||
.setup(|app| {
|
||||
if cfg!(debug_assertions) {
|
||||
app.handle().plugin(
|
||||
tauri_plugin_log::Builder::default()
|
||||
.level(log::LevelFilter::Info)
|
||||
.build(),
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
fn main() {
|
||||
app_lib::run();
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
{
|
||||
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
||||
"productName": "poe2-loot-filter-vue",
|
||||
"version": "0.1.0",
|
||||
"identifier": "com.tauri.dev",
|
||||
"build": {
|
||||
"frontendDist": "../dist",
|
||||
"devUrl": "http://localhost:5173",
|
||||
"beforeDevCommand": "bun dev",
|
||||
"beforeBuildCommand": "bun build"
|
||||
},
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "poe2-loot-filter-vue",
|
||||
"width": 800,
|
||||
"height": 600,
|
||||
"resizable": true,
|
||||
"fullscreen": false
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": null
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
]
|
||||
}
|
||||
}
|
||||
153
src/App.vue
@ -1,12 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import { Button, InputText, ButtonGroup, Dialog, Listbox, ConfirmPopup, Toast, Splitter, SplitterPanel, ScrollPanel, useToast } from 'primevue'
|
||||
import { Button, Dialog, ConfirmPopup, Toast, Splitter, SplitterPanel, ScrollPanel, useToast } from 'primevue'
|
||||
import TreeNav from './components/TreeNav.vue'
|
||||
import FilterDetail from './components/FilterDetail.vue'
|
||||
import Info from './components/Info.vue'
|
||||
import { computed, ref, toRaw, watch } from 'vue'
|
||||
import * as O from 'fp-ts/Option'
|
||||
import * as A from 'fp-ts/lib/Array';
|
||||
import { pipe } from 'fp-ts/function'
|
||||
import FileSaver from 'file-saver'
|
||||
import { generateFilterText, type Filter, type FilterConfig, type FilterNode } from './models'
|
||||
import { filterToTreeNode, treeNodeToFilter } from './services/filter'
|
||||
import { BaseDirectory, writeTextFile, lstat, readDir, readTextFile } from '@tauri-apps/plugin-fs';
|
||||
|
||||
const darkMode = ref(document.documentElement.classList.contains('dark'))
|
||||
|
||||
@ -22,9 +25,14 @@ watch(darkMode, (dark) => {
|
||||
localStorage.theme = dark ? 'dark' : 'light'
|
||||
})
|
||||
|
||||
const filterName = ref()
|
||||
|
||||
const nodes = ref([] as FilterNode[])
|
||||
let defaultFilters: Filter[] = []
|
||||
const nodes = ref(pipe(
|
||||
localStorage.getItem("filters"),
|
||||
O.fromNullable,
|
||||
O.map((value): Filter[] => JSON.parse(value)),
|
||||
O.getOrElse(() => defaultFilters),
|
||||
A.map(filterToTreeNode)
|
||||
))
|
||||
const selectedFilter = ref<FilterNode>()
|
||||
|
||||
function onDelete() {
|
||||
@ -38,123 +46,60 @@ function onDelete() {
|
||||
selectedFilter.value = undefined
|
||||
}
|
||||
|
||||
const POE2_FOLDER = 'My Games/Path of Exile 2'
|
||||
const PREFIX = 'Clearfell'
|
||||
const CONFIG_SUFFIX = "config.json"
|
||||
const FILTER_SUFFIX = 'filter'
|
||||
const BASE_DIR = BaseDirectory.Document
|
||||
const previewText = ref()
|
||||
|
||||
async function save(toastOnComplete?: boolean) {
|
||||
if (nodes.value && !!filterName.value) {
|
||||
function exportFilter() {
|
||||
let text = generateFilterText(toRaw(nodes.value).map(treeNodeToFilter))
|
||||
console.log(text)
|
||||
previewText.value = text
|
||||
exportDialogVisible.value = true;
|
||||
}
|
||||
|
||||
function download() {
|
||||
var blob = new Blob([previewText.value], { type: "text/plain;charset=utf-8" });
|
||||
FileSaver.saveAs(blob, "poe2.filter")
|
||||
}
|
||||
|
||||
const exportDialogVisible = ref(false);
|
||||
|
||||
function save() {
|
||||
if (nodes.value) {
|
||||
const filters = toRaw(nodes.value).map(treeNodeToFilter)
|
||||
|
||||
let text = generateFilterText(filters)
|
||||
await Promise.all([writeTextFile(`${POE2_FOLDER}/${PREFIX} ${filterName.value}.${CONFIG_SUFFIX}`, JSON.stringify({ filters }, null, 2), {
|
||||
baseDir: BASE_DIR,
|
||||
}), writeTextFile(`${POE2_FOLDER}/${PREFIX} ${filterName.value}.${FILTER_SUFFIX}`, text, {
|
||||
baseDir: BASE_DIR,
|
||||
})])
|
||||
if (toastOnComplete) {
|
||||
toast.add({ severity: 'success', summary: 'Success', detail: 'Content Saved', life: 3000 });
|
||||
}
|
||||
localStorage.setItem("filters", JSON.stringify(filters))
|
||||
}
|
||||
}
|
||||
|
||||
setInterval(save, 5000)
|
||||
|
||||
const CONFIG_PATTERN = `^${PREFIX} (.*)\\.config\\.json$`
|
||||
|
||||
const filterNames = ref([] as string[])
|
||||
|
||||
async function fetchFilterNames() {
|
||||
const ls = await readDir(POE2_FOLDER, {
|
||||
baseDir: BASE_DIR
|
||||
})
|
||||
filterNames.value = ls.map(f => {
|
||||
if (f.isFile) {
|
||||
let match = f.name.match(CONFIG_PATTERN)
|
||||
if (match) {
|
||||
return match[1]
|
||||
}
|
||||
}
|
||||
return null
|
||||
}).filter(f => f != null)
|
||||
}
|
||||
async function load() {
|
||||
await fetchFilterNames()
|
||||
loadDialogVisible.value = true
|
||||
}
|
||||
|
||||
async function saveAs() {
|
||||
await fetchFilterNames()
|
||||
saveDialogVisible.value = true
|
||||
}
|
||||
|
||||
const loadDialogVisible = ref(false)
|
||||
const saveDialogVisible = ref(false)
|
||||
|
||||
async function loadFilter() {
|
||||
const json = await readTextFile(`${POE2_FOLDER}/${PREFIX} ${loadName.value}.${CONFIG_SUFFIX}`, {
|
||||
baseDir: BASE_DIR,
|
||||
})
|
||||
const filters: Filter[] = JSON.parse(json).filters
|
||||
nodes.value = filters.map(f => filterToTreeNode(f))
|
||||
filterName.value = loadName.value
|
||||
loadDialogVisible.value = false
|
||||
loadName.value = undefined
|
||||
}
|
||||
async function saveFilter() {
|
||||
filterName.value = saveName.value
|
||||
await save(true)
|
||||
saveDialogVisible.value = false
|
||||
saveName.value = undefined
|
||||
}
|
||||
|
||||
const loadName = ref()
|
||||
const saveName = ref()
|
||||
|
||||
const overwrite = computed(() => filterNames.value.includes(saveName.value))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ConfirmPopup />
|
||||
<Toast />
|
||||
<Dialog v-model:visible="loadDialogVisible" modal header="Load Filter">
|
||||
<Listbox v-model="loadName" :options="filterNames" />
|
||||
<template #footer>
|
||||
<Button label="Cancel" severity="secondary" @click="loadDialogVisible = false" autofocus />
|
||||
<Button :disabled="!loadName" label="Load" severity="primary" @click="loadFilter" autofocus />
|
||||
</template>
|
||||
</Dialog>
|
||||
<Dialog v-model:visible="saveDialogVisible" modal header="Save Filter As">
|
||||
<div class="flex flex-col gap-2">
|
||||
<label>Existing Filters:</label>
|
||||
<Listbox v-model="saveName" :options="filterNames" />
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 mt-4">
|
||||
<label>Save Name:</label>
|
||||
<InputText type="text" v-model="saveName" />
|
||||
</div>
|
||||
<template #footer>
|
||||
<Button label="Cancel" severity="secondary" @click="saveDialogVisible = false" autofocus />
|
||||
<Button :disabled="!saveName" :label="overwrite ? 'Overwrite' : 'Save'"
|
||||
:severity="overwrite ? 'danger' : 'primary'" @click="saveFilter" autofocus />
|
||||
</template>
|
||||
</Dialog>
|
||||
<div class="flex flex-row gap-2 items-center flex-grow-0">
|
||||
<article class="prose dark:prose-invert p-4">
|
||||
<h1>Path of Exile 2 Loot Filter Config</h1>
|
||||
</article>
|
||||
<ButtonGroup>
|
||||
<Button :icon @click="darkMode = !darkMode" severity="secondary" variant="outlined" />
|
||||
<Button icon="pi pi-file-import" label="Load" severity="secondary" variant="outlined" @click="load" />
|
||||
<Button icon="pi pi-save" label="Save As" severity="secondary" variant="outlined" @click="saveAs" />
|
||||
<Button :disabled="!filterName" icon="pi pi-save" label="Save" severity="primary" @click="save(true)" />
|
||||
</ButtonGroup>
|
||||
</article><Button :icon @click="darkMode = !darkMode" severity="secondary" variant="outlined" rounded />
|
||||
<Button icon="pi pi-save" label="Save" severity="secondary" variant="outlined" rounded
|
||||
@click="save(); toast.add({ severity: 'success', summary: 'Success', detail: 'Content Saved', life: 3000 });" />
|
||||
<Button icon="pi pi-file-export" label="Export" severity="primary" @click="exportFilter" />
|
||||
<Dialog v-model:visible="exportDialogVisible" modal header="Preview Filter Text">
|
||||
<template #default>
|
||||
<ScrollPanel class="h-[50vh]">
|
||||
<pre>{{ previewText }}</pre>
|
||||
</ScrollPanel>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<Button type="button" label="Cancel" severity="secondary" @click="exportDialogVisible = false"></Button>
|
||||
<Button type="button" icon="pi pi-download" label="Download" @click="download"></Button>
|
||||
</template>
|
||||
</Dialog>
|
||||
<!-- <Button icon = "pi pi-save" severity="secondary" variant="outlined" rounded /> -->
|
||||
</div>
|
||||
<Splitter class="flex-1 min-h-0">
|
||||
<SplitterPanel class="flex flex-col">
|
||||
<TreeNav :filterName :nodes :selectedNode="selectedFilter" @nodeSelect="selectedFilter = $event"
|
||||
<TreeNav :nodes :selectedNode="selectedFilter" @nodeSelect="selectedFilter = $event"
|
||||
@nodeUnselect="selectedFilter = undefined" />
|
||||
</SplitterPanel>
|
||||
<SplitterPanel class="flex flex-col">
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { toDisplayLines, type Filter, type FilterNode, type FilterRule } from '@/models';
|
||||
import { toLines, type Filter, type FilterNode, type FilterRule } from '@/models';
|
||||
import { computed, ref, watchEffect } from 'vue'
|
||||
import { Button, ColorPicker, ScrollPanel, Tabs, Tab, TabPanels, TabList, TabPanel, ToggleButton, InputText, InputNumber, Select, ToggleSwitch, MultiSelect } from 'primevue'
|
||||
import { useConfirm } from "primevue/useconfirm";
|
||||
import { useToast } from "primevue/usetoast";
|
||||
import { CLASSES, COLORS, BASE_TYPES, RARITIES, SHAPES, OPERATORS, ARMOUR_TYPES } from '@/models/settings';
|
||||
|
||||
const confirm = useConfirm();
|
||||
const toast = useToast();
|
||||
@ -37,7 +36,55 @@ const props = defineProps<{
|
||||
node: FilterNode,
|
||||
onDelete: () => void
|
||||
}>()
|
||||
const OPERATORS = ['=', '==', '!=', '<', '<=', '>', '>='];
|
||||
|
||||
const COLORS = [
|
||||
'Red',
|
||||
'Green',
|
||||
'Blue',
|
||||
'Brown',
|
||||
'White',
|
||||
'Yellow',
|
||||
'Cyan',
|
||||
'Grey',
|
||||
'Orange',
|
||||
'Pink',
|
||||
'Purple'
|
||||
];
|
||||
|
||||
const SHAPES = [
|
||||
'Circle',
|
||||
'Diamond',
|
||||
'Hexagon',
|
||||
'Square',
|
||||
'Star',
|
||||
'Triangle',
|
||||
'Cross',
|
||||
'Moon',
|
||||
'Raindrop',
|
||||
'Kite',
|
||||
'Pentagon',
|
||||
'UpsideDownHouse'
|
||||
];
|
||||
|
||||
const RARITIES = ['Normal', 'Magic', 'Rare', 'Unique'];
|
||||
|
||||
const CLASSES = [
|
||||
'Currency', 'Stackable Currency', 'Jewel', 'Abyss Jewel', 'Divination Card',
|
||||
'Gem', 'Flask', 'Map', 'Map Fragment', 'Fishing Rods', 'Amulet', 'Ring',
|
||||
'Claw', 'Dagger', 'Wand', 'One Hand Sword', 'Thrusting One Hand Sword',
|
||||
'One Hand Axe', 'One Hand Mace', 'Sceptre', 'Rune Dagger', 'Bow', 'Staff',
|
||||
'Two Hand Sword', 'Two Hand Axe', 'Two Hand Mace', 'Warstaff', 'Body Armour',
|
||||
'Boots', 'Gloves', 'Helmet', 'Shield', 'Quiver'
|
||||
];
|
||||
|
||||
const BASE_TYPES = [
|
||||
'Exalted Orb', 'Mirror of Kalandra', 'Eternal Orb', 'Divine Orb',
|
||||
'Orb of Annulment', 'Chaos Orb', 'Vaal Orb', 'Regal Orb', 'Orb of Alchemy',
|
||||
'Orb of Fusing', 'Blessed Orb', 'Cartographer\'s Chisel', 'Orb of Scouring',
|
||||
'Jeweller\'s Orb', 'Chromatic Orb', 'Orb of Chance', 'Orb of Alteration',
|
||||
'Orb of Transmutation', 'Scroll of Wisdom', 'Portal Scroll'
|
||||
];
|
||||
|
||||
const filter = computed(() => props.node.data)
|
||||
|
||||
@ -109,7 +156,7 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
<ToggleButton class="w-24 flex-shrink-0" onIcon="pi pi-eye" offIcon="pi pi-eye-slash" v-if="filter.type === 'leaf'"
|
||||
v-model="filter.show" onLabel="Show" offLabel="Hide" />
|
||||
|
||||
<InputText class="w-full" type="text" :placeholder="toDisplayLines(filter).join(' ')" v-model="filter.name" />
|
||||
<InputText class="w-full" type="text" :placeholder="toLines(filter.rule).join(' ')" v-model="filter.name" />
|
||||
<Button class="flex-shrink-0" icon="pi pi-trash" severity="danger" v-on:click="confirmDelete" />
|
||||
</div>
|
||||
|
||||
@ -129,7 +176,7 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="pr-4 whitespace-nowrap">
|
||||
<td class="pr-4">
|
||||
Class
|
||||
</td>
|
||||
<td class="pr-4">
|
||||
@ -140,16 +187,16 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
</td>
|
||||
<td class="h-11">
|
||||
<MultiSelect v-if="ruleWithLookup[1].class != 'inherit' && filter.rule.class"
|
||||
v-model="filter.rule.class" display="chip" :options="CLASSES.slice()" filter
|
||||
placeholder="Select Classes" class="w-full" :maxSelectedLabels=3 fluid />
|
||||
v-model="filter.rule.class" display="chip" :options="CLASSES" filter placeholder="Select Classes"
|
||||
class="w-full" :maxSelectedLabels=3 fluid />
|
||||
|
||||
<MultiSelect disabled v-if="ruleWithLookup[1].class == 'inherit'"
|
||||
:model-value="ruleWithLookup[0].class" display="chip" :options="CLASSES.slice()" filter
|
||||
:model-value="ruleWithLookup[0].class" display="chip" :options="CLASSES" filter
|
||||
placeholder="Select Classes" class="w-full" :maxSelectedLabels=3 fluid />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="pr-4 whitespace-nowrap">
|
||||
<td class="pr-4">
|
||||
BaseType
|
||||
</td>
|
||||
<td class="pr-4">
|
||||
@ -160,29 +207,15 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
</td>
|
||||
<td class="h-11">
|
||||
<MultiSelect v-if="ruleWithLookup[1].base_type != 'inherit' && filter.rule.base_type"
|
||||
v-model="filter.rule.base_type" display="chip" :options="BASE_TYPES.slice()" filter
|
||||
v-model="filter.rule.base_type" display="chip" :options="BASE_TYPES" filter
|
||||
placeholder="Select Base Types" class="w-full" :maxSelectedLabels=3 fluid />
|
||||
<MultiSelect disabled v-if="ruleWithLookup[1].base_type == 'inherit'"
|
||||
:model-value="ruleWithLookup[0].base_type" display="chip" :options="BASE_TYPES.slice()" filter
|
||||
:model-value="ruleWithLookup[0].base_type" display="chip" :options="BASE_TYPES" filter
|
||||
placeholder="Select Base Types" class="w-full" :maxSelectedLabels=3 fluid />
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="filter.type === 'leaf'">
|
||||
<td class="pr-4 whitespace-nowrap">
|
||||
ArmourType
|
||||
</td>
|
||||
<td class="pr-4">
|
||||
<ToggleSwitch class="align-middle" :model-value="filter.leafRule.armour_type != undefined"
|
||||
@update:model-value="filter.leafRule.armour_type = $event ? [] : undefined" />
|
||||
</td>
|
||||
<td class="h-11">
|
||||
<MultiSelect v-if="filter.leafRule.armour_type" v-model="filter.leafRule.armour_type" display="chip"
|
||||
:options="ARMOUR_TYPES.slice()" filter placeholder="Select Base Types" class="w-full"
|
||||
:maxSelectedLabels=3 fluid />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="pr-4 whitespace-nowrap">
|
||||
<td class="pr-4">
|
||||
Rarity
|
||||
</td>
|
||||
<td class="pr-4">
|
||||
@ -193,17 +226,17 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
</td>
|
||||
<td class="h-11 flex gap-2">
|
||||
<Select v-if="ruleWithLookup[1].rarity != 'inherit' && filter.rule.rarity"
|
||||
v-model="filter.rule.rarity[0]" :options="OPERATORS.slice()" />
|
||||
v-model="filter.rule.rarity[0]" :options="OPERATORS" />
|
||||
<Select v-if="ruleWithLookup[1].rarity != 'inherit' && filter.rule.rarity"
|
||||
v-model="filter.rule.rarity[1]" :options="RARITIES.slice()" />
|
||||
v-model="filter.rule.rarity[1]" :options="RARITIES" />
|
||||
<Select disabled v-if="ruleWithLookup[1].rarity == 'inherit'"
|
||||
:model-value="ruleWithLookup[0].rarity![0]" :options="OPERATORS.slice()" />
|
||||
:model-value="ruleWithLookup[0].rarity![0]" :options="OPERATORS" />
|
||||
<Select disabled v-if="ruleWithLookup[1].rarity == 'inherit'"
|
||||
:model-value="ruleWithLookup[0].rarity![1]" :options="RARITIES.slice()" />
|
||||
:model-value="ruleWithLookup[0].rarity![1]" :options="RARITIES" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="pr-4 whitespace-nowrap">
|
||||
<td class="pr-4">
|
||||
Sockets
|
||||
</td>
|
||||
<td class="pr-4">
|
||||
@ -214,17 +247,17 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
</td>
|
||||
<td class="h-11 flex gap-2">
|
||||
<Select v-if="ruleWithLookup[1].sockets != 'inherit' && filter.rule.sockets"
|
||||
v-model="filter.rule.sockets[0]" :options="OPERATORS.slice()" />
|
||||
v-model="filter.rule.sockets[0]" :options="OPERATORS" />
|
||||
<InputNumber class="w-16" fluid v-if="ruleWithLookup[1].sockets != 'inherit' && filter.rule.sockets"
|
||||
v-model="filter.rule.sockets[1]" />
|
||||
<Select disabled v-if="ruleWithLookup[1].sockets == 'inherit'"
|
||||
:model-value="ruleWithLookup[0].sockets![0]" :options="OPERATORS.slice()" />
|
||||
:model-value="ruleWithLookup[0].sockets![0]" :options="OPERATORS" />
|
||||
<InputNumber disabled class="w-16" fluid v-if="ruleWithLookup[1].sockets == 'inherit'"
|
||||
:model-value="ruleWithLookup[0].sockets![1]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="pr-4 whitespace-nowrap">
|
||||
<td class="pr-4">
|
||||
Quality
|
||||
</td>
|
||||
<td class="pr-4">
|
||||
@ -235,17 +268,17 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
</td>
|
||||
<td class="h-11 flex gap-2">
|
||||
<Select v-if="ruleWithLookup[1].quality != 'inherit' && filter.rule.quality"
|
||||
v-model="filter.rule.quality[0]" :options="OPERATORS.slice()" />
|
||||
v-model="filter.rule.quality[0]" :options="OPERATORS" />
|
||||
<InputNumber class="w-16" fluid v-if="ruleWithLookup[1].quality != 'inherit' && filter.rule.quality"
|
||||
v-model="filter.rule.quality[1]" />
|
||||
<Select disabled v-if="ruleWithLookup[1].quality == 'inherit'"
|
||||
:model-value="ruleWithLookup[0].quality![0]" :options="OPERATORS.slice()" />
|
||||
:model-value="ruleWithLookup[0].quality![0]" :options="OPERATORS" />
|
||||
<InputNumber disabled class="w-16" fluid v-if="ruleWithLookup[1].quality == 'inherit'"
|
||||
:model-value="ruleWithLookup[0].quality![1]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="pr-4 whitespace-nowrap">
|
||||
<td class="pr-4">
|
||||
StackSize
|
||||
</td>
|
||||
<td class="pr-4">
|
||||
@ -256,18 +289,18 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
</td>
|
||||
<td class="h-11 flex gap-2">
|
||||
<Select v-if="ruleWithLookup[1].stack_size != 'inherit' && filter.rule.stack_size"
|
||||
v-model="filter.rule.stack_size[0]" :options="OPERATORS.slice()" />
|
||||
v-model="filter.rule.stack_size[0]" :options="OPERATORS" />
|
||||
<InputNumber class="w-16" fluid
|
||||
v-if="ruleWithLookup[1].stack_size != 'inherit' && filter.rule.stack_size"
|
||||
v-model="filter.rule.stack_size[1]" />
|
||||
<Select disabled v-if="ruleWithLookup[1].stack_size == 'inherit'"
|
||||
:model-value="ruleWithLookup[0].stack_size![0]" :options="OPERATORS.slice()" />
|
||||
:model-value="ruleWithLookup[0].stack_size![0]" :options="OPERATORS" />
|
||||
<InputNumber disabled class="w-16" fluid v-if="ruleWithLookup[1].stack_size == 'inherit'"
|
||||
:model-value="ruleWithLookup[0].stack_size![1]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="pr-4 whitespace-nowrap">
|
||||
<td class="pr-4">
|
||||
AreaLevel
|
||||
</td>
|
||||
<td class="pr-4">
|
||||
@ -278,18 +311,18 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
</td>
|
||||
<td class="h-11 flex gap-2">
|
||||
<Select v-if="ruleWithLookup[1].area_level != 'inherit' && filter.rule.area_level"
|
||||
v-model="filter.rule.area_level[0]" :options="OPERATORS.slice()" />
|
||||
v-model="filter.rule.area_level[0]" :options="OPERATORS" />
|
||||
<InputNumber class="w-16" fluid
|
||||
v-if="ruleWithLookup[1].area_level != 'inherit' && filter.rule.area_level"
|
||||
v-model="filter.rule.area_level[1]" />
|
||||
<Select disabled v-if="ruleWithLookup[1].area_level == 'inherit'"
|
||||
:model-value="ruleWithLookup[0].area_level![0]" :options="OPERATORS.slice()" />
|
||||
:model-value="ruleWithLookup[0].area_level![0]" :options="OPERATORS" />
|
||||
<InputNumber disabled class="w-16" fluid v-if="ruleWithLookup[1].area_level == 'inherit'"
|
||||
:model-value="ruleWithLookup[0].area_level![1]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="pr-4 whitespace-nowrap">
|
||||
<td class="pr-4">
|
||||
DropLevel
|
||||
</td>
|
||||
<td class="pr-4">
|
||||
@ -300,18 +333,18 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
</td>
|
||||
<td class="h-11 flex gap-2">
|
||||
<Select v-if="ruleWithLookup[1].drop_level != 'inherit' && filter.rule.drop_level"
|
||||
v-model="filter.rule.drop_level[0]" :options="OPERATORS.slice()" />
|
||||
v-model="filter.rule.drop_level[0]" :options="OPERATORS" />
|
||||
<InputNumber class="w-16" fluid
|
||||
v-if="ruleWithLookup[1].drop_level != 'inherit' && filter.rule.drop_level"
|
||||
v-model="filter.rule.drop_level[1]" />
|
||||
<Select disabled v-if="ruleWithLookup[1].drop_level == 'inherit'"
|
||||
:model-value="ruleWithLookup[0].drop_level![0]" :options="OPERATORS.slice()" />
|
||||
:model-value="ruleWithLookup[0].drop_level![0]" :options="OPERATORS" />
|
||||
<InputNumber disabled class="w-16" fluid v-if="ruleWithLookup[1].drop_level == 'inherit'"
|
||||
:model-value="ruleWithLookup[0].drop_level![1]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="pr-4 whitespace-nowrap">
|
||||
<td class="pr-4">
|
||||
ItemLevel
|
||||
</td>
|
||||
<td class="pr-4">
|
||||
@ -322,33 +355,18 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
</td>
|
||||
<td class="h-11 flex gap-2">
|
||||
<Select v-if="ruleWithLookup[1].item_level != 'inherit' && filter.rule.item_level"
|
||||
v-model="filter.rule.item_level[0]" :options="OPERATORS.slice()" />
|
||||
v-model="filter.rule.item_level[0]" :options="OPERATORS" />
|
||||
<InputNumber class="w-16" fluid
|
||||
v-if="ruleWithLookup[1].item_level != 'inherit' && filter.rule.item_level"
|
||||
v-model="filter.rule.item_level[1]" />
|
||||
<Select disabled v-if="ruleWithLookup[1].item_level == 'inherit'"
|
||||
:model-value="ruleWithLookup[0].item_level![0]" :options="OPERATORS.slice()" />
|
||||
:model-value="ruleWithLookup[0].item_level![0]" :options="OPERATORS" />
|
||||
<InputNumber disabled class="w-16" fluid v-if="ruleWithLookup[1].item_level == 'inherit'"
|
||||
:model-value="ruleWithLookup[0].item_level![1]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="filter.type === 'leaf'">
|
||||
<td class="pr-4 whitespace-nowrap">
|
||||
(Area - Drop)Level
|
||||
</td>
|
||||
<td class="pr-4">
|
||||
<ToggleSwitch class="align-middle" :model-value="filter.leafRule.area_minus_drop_level != undefined"
|
||||
@update:model-value="filter.leafRule.area_minus_drop_level = $event ? ['>', 0] : undefined" />
|
||||
</td>
|
||||
<td class="h-11 flex gap-2">
|
||||
<Select v-if="filter.leafRule.area_minus_drop_level"
|
||||
v-model="filter.leafRule.area_minus_drop_level[0]" :options="OPERATORS.slice()" />
|
||||
<InputNumber class="w-16" fluid v-if="filter.leafRule.area_minus_drop_level"
|
||||
v-model="filter.leafRule.area_minus_drop_level[1]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="pr-4 whitespace-nowrap">
|
||||
<td class="pr-4">
|
||||
WaystoneTier
|
||||
</td>
|
||||
<td class="pr-4">
|
||||
@ -359,12 +377,12 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
</td>
|
||||
<td class="h-11 flex gap-2">
|
||||
<Select v-if="ruleWithLookup[1].waystone_tier != 'inherit' && filter.rule.waystone_tier"
|
||||
v-model="filter.rule.waystone_tier[0]" :options="OPERATORS.slice()" />
|
||||
v-model="filter.rule.waystone_tier[0]" :options="OPERATORS" />
|
||||
<InputNumber class="w-16" fluid
|
||||
v-if="ruleWithLookup[1].waystone_tier != 'inherit' && filter.rule.waystone_tier"
|
||||
v-model="filter.rule.waystone_tier[1]" />
|
||||
<Select disabled v-if="ruleWithLookup[1].waystone_tier == 'inherit'"
|
||||
:model-value="ruleWithLookup[0].waystone_tier![0]" :options="OPERATORS.slice()" />
|
||||
:model-value="ruleWithLookup[0].waystone_tier![0]" :options="OPERATORS" />
|
||||
<InputNumber disabled class="w-16" fluid v-if="ruleWithLookup[1].waystone_tier == 'inherit'"
|
||||
:model-value="ruleWithLookup[0].waystone_tier![1]" />
|
||||
</td>
|
||||
@ -382,7 +400,7 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="pr-4 whitespace-nowrap">
|
||||
<td class="pr-4">
|
||||
SetFontSize
|
||||
</td>
|
||||
<td class="pr-4">
|
||||
@ -401,7 +419,7 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="pr-4 whitespace-nowrap">
|
||||
<td class="pr-4">
|
||||
SetTextColor
|
||||
</td>
|
||||
<td class="pr-4">
|
||||
@ -420,7 +438,7 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="pr-4 whitespace-nowrap">
|
||||
<td class="pr-4">
|
||||
SetBackgroundColor
|
||||
</td>
|
||||
<td class="pr-4">
|
||||
@ -439,7 +457,7 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="pr-4 whitespace-nowrap">
|
||||
<td class="pr-4">
|
||||
SetBorderColor
|
||||
</td>
|
||||
<td class="pr-4">
|
||||
@ -458,7 +476,7 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="pr-4 whitespace-nowrap">
|
||||
<td class="pr-4">
|
||||
PlayAlertSound
|
||||
</td>
|
||||
<td class="pr-4">
|
||||
@ -481,7 +499,7 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="pr-4 whitespace-nowrap">
|
||||
<td class="pr-4">
|
||||
MinimapIcon
|
||||
</td>
|
||||
<td class="pr-4">
|
||||
@ -495,19 +513,19 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
v-if="ruleWithLookup[1].minimap_icon != 'inherit' && filter.rule.minimap_icon"
|
||||
v-model="filter.rule.minimap_icon[0]" />
|
||||
<Select v-if="ruleWithLookup[1].minimap_icon != 'inherit' && filter.rule.minimap_icon"
|
||||
v-model="filter.rule.minimap_icon[1]" :options="COLORS.slice()" />
|
||||
v-model="filter.rule.minimap_icon[1]" :options="COLORS" />
|
||||
<Select v-if="ruleWithLookup[1].minimap_icon != 'inherit' && filter.rule.minimap_icon"
|
||||
v-model="filter.rule.minimap_icon[2]" :options="SHAPES.slice()" />
|
||||
v-model="filter.rule.minimap_icon[2]" :options="SHAPES" />
|
||||
<InputNumber class="w-16" fluid v-if="ruleWithLookup[1].minimap_icon == 'inherit'" disabled
|
||||
:model-value="ruleWithLookup[0].minimap_icon![0]" />
|
||||
<Select v-if="ruleWithLookup[1].minimap_icon == 'inherit'" disabled
|
||||
:model-value="ruleWithLookup[0].minimap_icon![1]" :options="COLORS.slice()" />
|
||||
:model-value="ruleWithLookup[0].minimap_icon![1]" :options="COLORS" />
|
||||
<Select v-if="ruleWithLookup[1].minimap_icon == 'inherit'" disabled
|
||||
:model-value="ruleWithLookup[0].minimap_icon![2]" :options="SHAPES.slice()" />
|
||||
:model-value="ruleWithLookup[0].minimap_icon![2]" :options="SHAPES" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="pr-4 whitespace-nowrap">
|
||||
<td class="pr-4">
|
||||
PlayEffect
|
||||
</td>
|
||||
<td class="pr-4">
|
||||
@ -518,9 +536,9 @@ function mergeLookup([childValue, childLookup]: any, [parentValue, parentLookup]
|
||||
</td>
|
||||
<td class="h-11 flex gap-2">
|
||||
<Select v-if="ruleWithLookup[1].play_effect != 'inherit' && filter.rule.play_effect"
|
||||
v-model="filter.rule.play_effect" :options="COLORS.slice()" />
|
||||
v-model="filter.rule.play_effect" :options="COLORS" />
|
||||
<Select v-if="ruleWithLookup[1].play_effect == 'inherit'" disabled
|
||||
:model-value="ruleWithLookup[0].play_effect" :options="COLORS.slice()" />
|
||||
:model-value="ruleWithLookup[0].play_effect" :options="COLORS" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { defaultGroup, defaultLeaf, toDisplayLines, type FilterNode } from '@/models';
|
||||
import { defaultGroup, defaultLeaf, toLines, type FilterNode } from '@/models';
|
||||
import { filterToTreeNode } from '@/services/filter';
|
||||
import { Button, Menu, Chip } from 'primevue';
|
||||
import { ref } from 'vue'
|
||||
@ -42,7 +42,7 @@ const toggle = (event: MouseEvent) => {
|
||||
<template>
|
||||
<div class="flex items-center w-full flex-1">
|
||||
<div class="flex-1 flex truncate">
|
||||
<Chip v-if="!node.data.name" class="text-xs py-1.5 px-2" v-for="line in toDisplayLines(node.data)">
|
||||
<Chip v-if="!node.data.name" class="text-xs py-1.5 px-2" v-for="line in toLines(node.data.rule)">
|
||||
<span class="truncate max-w-40">{{ line }}</span>
|
||||
</Chip>
|
||||
<label v-else>{{ node.data.name }}</label>
|
||||
|
||||
@ -10,7 +10,6 @@ import { filterToTreeNode } from '@/services/filter';
|
||||
const props = defineProps<{
|
||||
nodes: FilterNodeType[]
|
||||
selectedNode?: FilterNodeType
|
||||
filterName?: string
|
||||
}>()
|
||||
const emit = defineEmits(['nodeSelect', 'nodeUnselect'])
|
||||
const selectedKey = ref()
|
||||
@ -145,7 +144,7 @@ const expandedKeys
|
||||
<template>
|
||||
<div class="flex flex-shrink-0 p-4 items-center">
|
||||
<article class="prose dark:prose-invert flex-1">
|
||||
<h2>{{ filterName }}</h2>
|
||||
<h2>Rules:</h2>
|
||||
</article>
|
||||
<ButtonGroup>
|
||||
<Button class="flex-shrink-0" :disabled="selectedPosition == undefined || selectedPosition[0] <= 0"
|
||||
|
||||
@ -1,13 +1,5 @@
|
||||
import { show } from 'fp-ts'
|
||||
import * as uuid from 'uuid'
|
||||
import type {
|
||||
ARMOUR_TYPES,
|
||||
BASE_TYPES,
|
||||
CLASSES,
|
||||
COLORS,
|
||||
OPERATORS,
|
||||
RARITIES,
|
||||
SHAPES,
|
||||
} from './settings'
|
||||
|
||||
interface _Filter {
|
||||
id: string
|
||||
@ -24,7 +16,6 @@ export function defaultLeaf(): FilterLeaf {
|
||||
enabled: true,
|
||||
rule: {},
|
||||
show: true,
|
||||
leafRule: {},
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,7 +37,6 @@ export interface FilterConfig {
|
||||
export type FilterLeaf = _Filter & {
|
||||
type: 'leaf'
|
||||
show: boolean
|
||||
leafRule: LeafRule
|
||||
}
|
||||
|
||||
export type FilterGroup = _Filter & {
|
||||
@ -56,37 +46,39 @@ export type FilterGroup = _Filter & {
|
||||
|
||||
export type Filter = FilterLeaf | FilterGroup
|
||||
|
||||
export type ItemClass = any // Replace with actual type definition
|
||||
export type ItemBaseType = any // Replace with actual type definition
|
||||
export type Op = any // Replace with actual type definition
|
||||
export type Level = RangedNumber<1, 100> // Replace with actual type definition
|
||||
export type ItemRarity = string // Replace with actual type definition
|
||||
export type GameColor = any // Replace with actual type definition
|
||||
export type MinimapIconShape = any // Replace with actual type definition
|
||||
|
||||
export interface RangedNumber<T extends number, U extends number> {
|
||||
value: number
|
||||
min: T
|
||||
max: U
|
||||
}
|
||||
|
||||
export interface Color {
|
||||
r: number
|
||||
g: number
|
||||
b: number
|
||||
}
|
||||
|
||||
export type Class = (typeof CLASSES)[number]
|
||||
export type BaseType = (typeof BASE_TYPES)[number]
|
||||
export type ArmourType = (typeof ARMOUR_TYPES)[number]
|
||||
export type Op = (typeof OPERATORS)[number]
|
||||
export type Rarity = (typeof RARITIES)[number]
|
||||
export type GameColor = (typeof COLORS)[number]
|
||||
export type Shape = (typeof SHAPES)[number]
|
||||
|
||||
export interface LeafRule {
|
||||
armour_type?: ArmourType[] // special addition
|
||||
area_minus_drop_level?: [Op, number] // special addition
|
||||
}
|
||||
|
||||
export interface FilterRule {
|
||||
class?: Class[] //
|
||||
base_type?: BaseType[] //
|
||||
area_level?: [Op, number] //
|
||||
drop_level?: [Op, number] //
|
||||
item_level?: [Op, number] //
|
||||
rarity?: [Op, Rarity] //
|
||||
sockets?: [Op, number] //
|
||||
quality?: [Op, number] //
|
||||
stack_size?: [Op, number] //
|
||||
class?: string[] //
|
||||
base_type?: string[] //
|
||||
area_level?: [string, number] //
|
||||
drop_level?: [string, number] //
|
||||
item_level?: [string, number] //
|
||||
rarity?: [string, string] //
|
||||
sockets?: [string, number] //
|
||||
quality?: [string, number] //
|
||||
stack_size?: [string, number] //
|
||||
|
||||
// waystones
|
||||
waystone_tier?: [Op, number] //
|
||||
waystone_tier?: [string, number] //
|
||||
|
||||
// effects
|
||||
set_font_size?: number //
|
||||
@ -94,8 +86,8 @@ export interface FilterRule {
|
||||
set_border_color?: Color //
|
||||
set_background_color?: Color //
|
||||
play_alert_sound?: [number, number] //
|
||||
play_effect?: GameColor //
|
||||
minimap_icon?: [number, GameColor, Shape] //
|
||||
play_effect?: string //
|
||||
minimap_icon?: [number, string, string] //
|
||||
}
|
||||
|
||||
export interface FilterNode {
|
||||
@ -105,22 +97,7 @@ export interface FilterNode {
|
||||
children?: FilterNode[]
|
||||
}
|
||||
|
||||
export function toDisplayLines(filter: Filter) {
|
||||
let r: string[] = toLines(filter.rule)
|
||||
if (filter.type === 'leaf') {
|
||||
if (filter.leafRule.armour_type) {
|
||||
r.push(`ArmourType ${filter.leafRule.armour_type.map((c) => `"${c}"`).join(' ')}`)
|
||||
}
|
||||
if (filter.leafRule.area_minus_drop_level) {
|
||||
r.push(
|
||||
`Area-DropLevel ${filter.leafRule.area_minus_drop_level[0]} ${filter.leafRule.area_minus_drop_level[1]}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
export function toLines(rule: FilterRuleRaw): string[] {
|
||||
export function toLines(rule: FilterRule): string[] {
|
||||
let r: string[] = []
|
||||
if (rule.class && rule.class.length > 0) {
|
||||
r.push(`Class ${rule.class.map((c) => `"${c}"`).join(' ')}`)
|
||||
@ -128,15 +105,6 @@ export function toLines(rule: FilterRuleRaw): string[] {
|
||||
if (rule.base_type && rule.base_type.length > 0) {
|
||||
r.push(`BaseType ${rule.base_type.map((c) => `"${c}"`).join(' ')}`)
|
||||
}
|
||||
if (rule.base_armour) {
|
||||
r.push(`BaseArmour ${rule.base_armour[0]} ${rule.base_armour[1]}`)
|
||||
}
|
||||
if (rule.base_evasion) {
|
||||
r.push(`BaseEvasion ${rule.base_evasion[0]} ${rule.base_evasion[1]}`)
|
||||
}
|
||||
if (rule.base_energy_shield) {
|
||||
r.push(`BaseEnergyShield ${rule.base_energy_shield[0]} ${rule.base_energy_shield[1]}`)
|
||||
}
|
||||
if (rule.rarity) {
|
||||
r.push(`Rarity ${rule.rarity[0]} ${rule.rarity[1]}`)
|
||||
}
|
||||
@ -206,7 +174,7 @@ export function generateFilterText(filters: Filter[]): string {
|
||||
.join('\n\n')
|
||||
}
|
||||
|
||||
function flatten(filters: Filter[]): { show: boolean; rule: FilterRuleRaw }[] {
|
||||
function flatten(filters: Filter[]): Omit<FilterLeaf, 'id' | 'name' | 'type' | 'enabled'>[] {
|
||||
return filters.flatMap((f) => {
|
||||
if (!f.enabled) {
|
||||
return []
|
||||
@ -226,85 +194,7 @@ function flatten(filters: Filter[]): { show: boolean; rule: FilterRuleRaw }[] {
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return expandLeaf(f).map((r) => ({ show: f.show, rule: r }))
|
||||
return [{ show: f.show, rule: f.rule }]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
type FilterRuleRaw = FilterRule & {
|
||||
base_armour?: [Op, number]
|
||||
base_evasion?: [Op, number]
|
||||
base_energy_shield?: [Op, number]
|
||||
}
|
||||
|
||||
function expandLeaf(leaf: FilterLeaf): FilterRuleRaw[] {
|
||||
let result = [leaf.rule]
|
||||
if (leaf.leafRule.area_minus_drop_level) {
|
||||
result = []
|
||||
for (let area_level = 1; area_level <= 100; area_level++) {
|
||||
let rule = { ...leaf.rule }
|
||||
let op: Op
|
||||
switch (leaf.leafRule.area_minus_drop_level[0]) {
|
||||
case '<':
|
||||
op = '>'
|
||||
break
|
||||
case '<=':
|
||||
op = '>='
|
||||
break
|
||||
case '>':
|
||||
op = '<'
|
||||
break
|
||||
case '>=':
|
||||
op = '<='
|
||||
break
|
||||
default:
|
||||
op = leaf.leafRule.area_minus_drop_level[0]
|
||||
}
|
||||
rule.area_level = ['==', area_level]
|
||||
rule.drop_level = [op, Math.max(0, area_level - leaf.leafRule.area_minus_drop_level[1])]
|
||||
result.push(rule)
|
||||
}
|
||||
}
|
||||
|
||||
if (leaf.leafRule.armour_type) {
|
||||
result = result.flatMap((r) => {
|
||||
return leaf.leafRule.armour_type!.map((t) => {
|
||||
let rule: FilterRuleRaw = { ...r }
|
||||
switch (t) {
|
||||
case 'Armour':
|
||||
rule.base_armour = ['>', 0]
|
||||
rule.base_evasion = ['<=', 0]
|
||||
rule.base_energy_shield = ['<=', 0]
|
||||
break
|
||||
case 'Evasion':
|
||||
rule.base_armour = ['<=', 0]
|
||||
rule.base_evasion = ['>', 0]
|
||||
rule.base_energy_shield = ['<=', 0]
|
||||
break
|
||||
case 'EnergyShield':
|
||||
rule.base_armour = ['<=', 0]
|
||||
rule.base_evasion = ['<=', 0]
|
||||
rule.base_energy_shield = ['>', 0]
|
||||
break
|
||||
case 'Armour + Evasion':
|
||||
rule.base_armour = ['>', 0]
|
||||
rule.base_evasion = ['>', 0]
|
||||
rule.base_energy_shield = ['<=', 0]
|
||||
break
|
||||
case 'Armour + EnergyShield':
|
||||
rule.base_armour = ['>', 0]
|
||||
rule.base_evasion = ['<=', 0]
|
||||
rule.base_energy_shield = ['>', 0]
|
||||
break
|
||||
case 'Evasion + EnergyShield':
|
||||
rule.base_armour = ['<=', 0]
|
||||
rule.base_evasion = ['>', 0]
|
||||
rule.base_energy_shield = ['>', 0]
|
||||
break
|
||||
}
|
||||
return rule
|
||||
})
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@ -1,97 +0,0 @@
|
||||
export const OPERATORS = ['=', '==', '!=', '<', '<=', '>', '>='] as const
|
||||
|
||||
export const COLORS = [
|
||||
'Red',
|
||||
'Green',
|
||||
'Blue',
|
||||
'Brown',
|
||||
'White',
|
||||
'Yellow',
|
||||
'Cyan',
|
||||
'Grey',
|
||||
'Orange',
|
||||
'Pink',
|
||||
'Purple',
|
||||
] as const
|
||||
|
||||
export const SHAPES = [
|
||||
'Circle',
|
||||
'Diamond',
|
||||
'Hexagon',
|
||||
'Square',
|
||||
'Star',
|
||||
'Triangle',
|
||||
'Cross',
|
||||
'Moon',
|
||||
'Raindrop',
|
||||
'Kite',
|
||||
'Pentagon',
|
||||
'UpsideDownHouse',
|
||||
] as const
|
||||
|
||||
export const RARITIES = ['Normal', 'Magic', 'Rare', 'Unique'] as const
|
||||
|
||||
export const CLASSES = [
|
||||
'Currency',
|
||||
'Stackable Currency',
|
||||
'Jewel',
|
||||
'Abyss Jewel',
|
||||
'Divination Card',
|
||||
'Gem',
|
||||
'Flask',
|
||||
'Map',
|
||||
'Map Fragment',
|
||||
'Fishing Rods',
|
||||
'Amulet',
|
||||
'Ring',
|
||||
'Claw',
|
||||
'Dagger',
|
||||
'Wand',
|
||||
'One Hand Sword',
|
||||
'One Hand Axe',
|
||||
'One Hand Mace',
|
||||
'Sceptre',
|
||||
'Bow',
|
||||
'Staff',
|
||||
'Two Hand Sword',
|
||||
'Two Hand Axe',
|
||||
'Two Hand Mace',
|
||||
'Body Armour',
|
||||
'Boots',
|
||||
'Gloves',
|
||||
'Helmet',
|
||||
'Shield',
|
||||
'Quiver',
|
||||
] as const
|
||||
|
||||
export const BASE_TYPES = [
|
||||
'Exalted Orb',
|
||||
'Mirror of Kalandra',
|
||||
'Eternal Orb',
|
||||
'Divine Orb',
|
||||
'Orb of Annulment',
|
||||
'Chaos Orb',
|
||||
'Vaal Orb',
|
||||
'Regal Orb',
|
||||
'Orb of Alchemy',
|
||||
'Orb of Fusing',
|
||||
'Blessed Orb',
|
||||
"Cartographer's Chisel",
|
||||
'Orb of Scouring',
|
||||
"Jeweller's Orb",
|
||||
'Chromatic Orb',
|
||||
'Orb of Chance',
|
||||
'Orb of Alteration',
|
||||
'Orb of Transmutation',
|
||||
'Scroll of Wisdom',
|
||||
'Portal Scroll',
|
||||
] as const
|
||||
|
||||
export const ARMOUR_TYPES = [
|
||||
'Armour',
|
||||
'Evasion',
|
||||
'EnergyShield',
|
||||
'Armour + Evasion',
|
||||
'Armour + EnergyShield',
|
||||
'Evasion + EnergyShield',
|
||||
] as const
|
||||
@ -3,32 +3,16 @@ import { fileURLToPath, URL } from 'node:url'
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueDevTools from 'vite-plugin-vue-devtools'
|
||||
const host = process.env.TAURI_DEV_HOST
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
// prevent vite from obscuring rust errors
|
||||
clearScreen: false,
|
||||
server: {
|
||||
// Tauri expects a fixed port, fail if that port is not available
|
||||
strictPort: true,
|
||||
// if the host Tauri is expecting is set, use it
|
||||
host: host || false,
|
||||
port: 5173,
|
||||
},
|
||||
// Env variables starting with the item of `envPrefix` will be exposed in tauri's source code through `import.meta.env`.
|
||||
envPrefix: ['VITE_', 'TAURI_ENV_*'],
|
||||
build: {
|
||||
// Tauri uses Chromium on Windows and WebKit on macOS and Linux
|
||||
target: process.env.TAURI_ENV_PLATFORM == 'windows' ? 'chrome105' : 'safari13',
|
||||
// don't minify for debug builds
|
||||
minify: !process.env.TAURI_ENV_DEBUG ? 'esbuild' : false,
|
||||
// produce sourcemaps for debug builds
|
||||
sourcemap: !!process.env.TAURI_ENV_DEBUG,
|
||||
},
|
||||
plugins: [vue(), vueDevTools()],
|
||||
plugins: [
|
||||
vue(),
|
||||
vueDevTools(),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||