cant log out lol
This commit is contained in:
parent
a75a1d774f
commit
ef6bbaf009
25
package-lock.json
generated
25
package-lock.json
generated
@ -11,6 +11,7 @@
|
|||||||
"@handsontable/vue3": "^12.0.1",
|
"@handsontable/vue3": "^12.0.1",
|
||||||
"@types/numbro": "^1.9.3",
|
"@types/numbro": "^1.9.3",
|
||||||
"@types/qs": "^6.9.7",
|
"@types/qs": "^6.9.7",
|
||||||
|
"@types/uuid": "^8.3.4",
|
||||||
"@vueuse/core": "^8.7.5",
|
"@vueuse/core": "^8.7.5",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
"handsontable": "^12.0.1",
|
"handsontable": "^12.0.1",
|
||||||
@ -18,6 +19,7 @@
|
|||||||
"pinia": "^2.0.14",
|
"pinia": "^2.0.14",
|
||||||
"qs": "^6.10.5",
|
"qs": "^6.10.5",
|
||||||
"typescript-cookie": "^1.0.3",
|
"typescript-cookie": "^1.0.3",
|
||||||
|
"uuid": "^8.3.2",
|
||||||
"vue": "^3.2.25",
|
"vue": "^3.2.25",
|
||||||
"vue3-cookies": "^1.0.6"
|
"vue3-cookies": "^1.0.6"
|
||||||
},
|
},
|
||||||
@ -70,6 +72,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
|
||||||
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw=="
|
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/uuid": {
|
||||||
|
"version": "8.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
|
||||||
|
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw=="
|
||||||
|
},
|
||||||
"node_modules/@types/web-bluetooth": {
|
"node_modules/@types/web-bluetooth": {
|
||||||
"version": "0.0.14",
|
"version": "0.0.14",
|
||||||
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz",
|
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz",
|
||||||
@ -1195,6 +1202,14 @@
|
|||||||
"node": ">= 0.4.0"
|
"node": ">= 0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "2.9.12",
|
"version": "2.9.12",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-2.9.12.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-2.9.12.tgz",
|
||||||
@ -1301,6 +1316,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
|
||||||
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw=="
|
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw=="
|
||||||
},
|
},
|
||||||
|
"@types/uuid": {
|
||||||
|
"version": "8.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
|
||||||
|
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw=="
|
||||||
|
},
|
||||||
"@types/web-bluetooth": {
|
"@types/web-bluetooth": {
|
||||||
"version": "0.0.14",
|
"version": "0.0.14",
|
||||||
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz",
|
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz",
|
||||||
@ -2000,6 +2020,11 @@
|
|||||||
"integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==",
|
"integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||||
|
},
|
||||||
"vite": {
|
"vite": {
|
||||||
"version": "2.9.12",
|
"version": "2.9.12",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-2.9.12.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-2.9.12.tgz",
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
"@handsontable/vue3": "^12.0.1",
|
"@handsontable/vue3": "^12.0.1",
|
||||||
"@types/numbro": "^1.9.3",
|
"@types/numbro": "^1.9.3",
|
||||||
"@types/qs": "^6.9.7",
|
"@types/qs": "^6.9.7",
|
||||||
|
"@types/uuid": "^8.3.4",
|
||||||
"@vueuse/core": "^8.7.5",
|
"@vueuse/core": "^8.7.5",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
"handsontable": "^12.0.1",
|
"handsontable": "^12.0.1",
|
||||||
@ -18,6 +19,7 @@
|
|||||||
"pinia": "^2.0.14",
|
"pinia": "^2.0.14",
|
||||||
"qs": "^6.10.5",
|
"qs": "^6.10.5",
|
||||||
"typescript-cookie": "^1.0.3",
|
"typescript-cookie": "^1.0.3",
|
||||||
|
"uuid": "^8.3.2",
|
||||||
"vue": "^3.2.25",
|
"vue": "^3.2.25",
|
||||||
"vue3-cookies": "^1.0.6"
|
"vue3-cookies": "^1.0.6"
|
||||||
},
|
},
|
||||||
|
@ -13,19 +13,22 @@ const props = defineProps(['character'])
|
|||||||
const name = ref(props.character.split("/").pop())
|
const name = ref(props.character.split("/").pop())
|
||||||
const job = ref("")
|
const job = ref("")
|
||||||
const galders = ref(0)
|
const galders = ref(0)
|
||||||
const {invs, activeTable} = useStoreRef()
|
const {invs, activeTable, chars} = useStoreRef()
|
||||||
|
|
||||||
watch(invs.value,()=>{
|
watch(invs.value,()=>{
|
||||||
const currentInv = invs.value.get(props.character)
|
const currentInv = invs.value.get(props.character)
|
||||||
if(currentInv){
|
if(currentInv){
|
||||||
if(currentInv.wallet){
|
name.value = currentInv.name!
|
||||||
name.value = currentInv.name!
|
galders.value = currentInv.galders!
|
||||||
job.value = currentInv.wallet?.job_img!
|
|
||||||
galders.value = currentInv.wallet?.galders!
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},{deep:true})
|
},{deep:true})
|
||||||
|
|
||||||
|
const currentChar = chars.value.get(props.character)
|
||||||
|
if(currentChar){
|
||||||
|
name.value = currentChar.name!
|
||||||
|
job.value = JobNumberToString(currentChar.current_job)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const selectCharacter = () => {
|
const selectCharacter = () => {
|
||||||
activeTable.value = props.character
|
activeTable.value = props.character
|
||||||
@ -38,6 +41,7 @@ import log from 'loglevel';
|
|||||||
import { defineComponent, computed, PropType, defineProps, defineEmits, ref, watch, onMounted} from 'vue';
|
import { defineComponent, computed, PropType, defineProps, defineEmits, ref, watch, onMounted} from 'vue';
|
||||||
import { getLTOState, LTOApi, LTOApiv0 } from '../lib/lifeto';
|
import { getLTOState, LTOApi, LTOApiv0 } from '../lib/lifeto';
|
||||||
import { LoginHelper, Session } from '../lib/session';
|
import { LoginHelper, Session } from '../lib/session';
|
||||||
|
import { JobNumberToString } from '../lib/trickster';
|
||||||
import { storage } from '../session_storage';
|
import { storage } from '../session_storage';
|
||||||
import { useStore, useStoreRef } from '../state/state';
|
import { useStore, useStoreRef } from '../state/state';
|
||||||
</script>
|
</script>
|
||||||
|
@ -7,19 +7,21 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import CharacterCard from './CharacterCard.vue';
|
import CharacterCard from './CharacterCard.vue';
|
||||||
|
|
||||||
const { accounts, invs, activeTable } = useStoreRef()
|
const { chars, accounts, invs, activeTable } = useStoreRef()
|
||||||
|
|
||||||
const characters = ref([] as string[])
|
const characters = ref([] as string[])
|
||||||
watch(invs, () => {
|
watch(chars, () => {
|
||||||
characters.value = [...new Set([...characters.value, ...invs.value.keys()])]
|
characters.value = [...new Set([...characters.value, ...invs.value.keys()])]
|
||||||
}, { deep: true })
|
}, { deep: true })
|
||||||
|
|
||||||
const session = storage.GetSession()
|
const session = storage.GetSession()
|
||||||
const api:LTOApi = getLTOState(LTOApiv0, session, useStoreRef())
|
const api:LTOApi = getLTOState(LTOApiv0, session, useStoreRef())
|
||||||
|
|
||||||
api.GetAccounts().then(xs => {
|
api.GetAccounts().then(xs => {
|
||||||
xs.forEach(x => {
|
xs.forEach(x => {
|
||||||
characters.value.push(x)
|
characters.value.push(...x.characters.map(x=>x.path))
|
||||||
})
|
})
|
||||||
|
characters.value = [...new Set([...characters.value])]
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(()=>{
|
onMounted(()=>{
|
||||||
|
75
src/lib/columns/column.ts
Normal file
75
src/lib/columns/column.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import Handsontable from "handsontable"
|
||||||
|
import numbro from 'numbro';
|
||||||
|
import { textRenderer } from "handsontable/renderers"
|
||||||
|
import { TricksterItem } from "../trickster"
|
||||||
|
import Core from "handsontable/core";
|
||||||
|
|
||||||
|
export const BasicColumns = [
|
||||||
|
"Image","Name","Count",
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export const DetailsColumns = [
|
||||||
|
"Desc","Use",
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export const MoveColumns = [
|
||||||
|
"MoveCount","Move",
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export const TagColumns = [
|
||||||
|
"All","Equip","Drill","Card","Quest","Consume", "Compound"
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export const EquipmentColumns = [
|
||||||
|
"MinLvl","Slots","RefineNumber","RefineState",
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export const StatsColumns = [
|
||||||
|
"AP","GunAP","AC","DX","MP","MA","MD","WT","DA","LK","HP","DP","HV",
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export const HackColumns = [
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export const ColumnNames = [
|
||||||
|
...BasicColumns,
|
||||||
|
...MoveColumns,
|
||||||
|
...DetailsColumns,
|
||||||
|
...EquipmentColumns,
|
||||||
|
...StatsColumns,
|
||||||
|
...TagColumns,
|
||||||
|
...HackColumns,
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export type ColumnName = typeof ColumnNames[number]
|
||||||
|
|
||||||
|
const c = (a:ColumnName | ColumnInfo):ColumnName => {
|
||||||
|
switch(typeof a) {
|
||||||
|
case "string":
|
||||||
|
return a
|
||||||
|
case "object":
|
||||||
|
return a.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const LazyColumn = c;
|
||||||
|
|
||||||
|
export const ColumnSorter = (a:ColumnName | ColumnInfo, b: ColumnName | ColumnInfo):number => {
|
||||||
|
let n1 = ColumnNames.indexOf(c(a))
|
||||||
|
let n2 = ColumnNames.indexOf(c(b))
|
||||||
|
if(n1 == n2) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return n1 > n2 ? 1 : -1
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ColumnInfo {
|
||||||
|
name: ColumnName
|
||||||
|
displayName:string
|
||||||
|
|
||||||
|
options?:(s:string[])=>string[]
|
||||||
|
renderer?:any
|
||||||
|
filtering?:boolean
|
||||||
|
writable?:boolean
|
||||||
|
getter(item:TricksterItem):(string | number)
|
||||||
|
}
|
||||||
|
|
452
src/lib/columns/column_impl.ts
Normal file
452
src/lib/columns/column_impl.ts
Normal file
@ -0,0 +1,452 @@
|
|||||||
|
import Handsontable from "handsontable"
|
||||||
|
import Core from "handsontable/core"
|
||||||
|
import { textRenderer } from "handsontable/renderers"
|
||||||
|
import numbro from "numbro"
|
||||||
|
import { TricksterItem } from "../trickster"
|
||||||
|
import {ColumnName, ColumnInfo} from "./column"
|
||||||
|
|
||||||
|
export const ColumnByNames = (...n:ColumnName[]) => {
|
||||||
|
return n.map(ColumnByName)
|
||||||
|
}
|
||||||
|
export const ColumnByName = (n:ColumnName) => {
|
||||||
|
return Columns[n]
|
||||||
|
}
|
||||||
|
export const test = <T extends ColumnInfo>(n:(new ()=>T)):[string,T] => {
|
||||||
|
let nn = new n()
|
||||||
|
return [nn.name, nn]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Image implements ColumnInfo {
|
||||||
|
name:ColumnName = 'Image'
|
||||||
|
displayName = " "
|
||||||
|
renderer = coverRenderer
|
||||||
|
getter(item:TricksterItem):(string|number) {
|
||||||
|
return item.image ? item.image : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function coverRenderer(instance:any, td:any, row:any, col:any, prop:any, value:any, cellProperties:any) {
|
||||||
|
const stringifiedValue = Handsontable.helper.stringify(value);
|
||||||
|
if (stringifiedValue.startsWith('http')) {
|
||||||
|
const img:any = document.createElement('IMG');
|
||||||
|
img.src = value;
|
||||||
|
Handsontable.dom.addEvent(img, 'mousedown', event =>{
|
||||||
|
event!.preventDefault();
|
||||||
|
});
|
||||||
|
Handsontable.dom.empty(td);
|
||||||
|
td.appendChild(img);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Name implements ColumnInfo {
|
||||||
|
name:ColumnName = "Name"
|
||||||
|
displayName = "Name"
|
||||||
|
filtering = true
|
||||||
|
renderer = nameRenderer
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.item_name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function nameRenderer(instance:any, td:any, row:any, col:any, prop:any, value:any, cellProperties:any) {
|
||||||
|
const stringifiedValue = Handsontable.helper.stringify(value);
|
||||||
|
let showText = stringifiedValue;
|
||||||
|
const div= document.createElement('div');
|
||||||
|
div.innerHTML = showText
|
||||||
|
div.title = showText
|
||||||
|
div.style.maxWidth = "20ch"
|
||||||
|
div.style.textOverflow = "ellipsis"
|
||||||
|
div.style.overflow= "hidden"
|
||||||
|
div.style.whiteSpace= "nowrap"
|
||||||
|
Handsontable.dom.addEvent(div, 'mousedown', event =>{
|
||||||
|
event!.preventDefault();
|
||||||
|
});
|
||||||
|
Handsontable.dom.empty(td);
|
||||||
|
td.appendChild(div);
|
||||||
|
td.classList.add("htLeft")
|
||||||
|
}
|
||||||
|
|
||||||
|
class Count implements ColumnInfo {
|
||||||
|
name:ColumnName = "Count"
|
||||||
|
displayName = "Count"
|
||||||
|
renderer = "numeric"
|
||||||
|
filtering = true
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.item_count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Move implements ColumnInfo {
|
||||||
|
name:ColumnName = "Move"
|
||||||
|
displayName = "Target"
|
||||||
|
writable = true
|
||||||
|
options = getMoveTargets
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return "---------------------------------------------"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMoveTargets = (invs: string[]):string[] => {
|
||||||
|
let out:string[] = [];
|
||||||
|
for(const k of invs){
|
||||||
|
out.push(k)
|
||||||
|
}
|
||||||
|
out.push("")
|
||||||
|
out.push("")
|
||||||
|
out.push("!TRASH")
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
class MoveCount implements ColumnInfo {
|
||||||
|
name:ColumnName = "MoveCount"
|
||||||
|
displayName = "Move #"
|
||||||
|
renderer = moveCountRenderer
|
||||||
|
writable = true
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveCountRenderer(instance:Core, td:any, row:number, col:number, prop:any, value:any, cellProperties:any) {
|
||||||
|
let newValue = value;
|
||||||
|
|
||||||
|
if (Handsontable.helper.isNumeric(newValue)) {
|
||||||
|
const numericFormat = cellProperties.numericFormat;
|
||||||
|
const cellCulture = numericFormat && numericFormat.culture || '-';
|
||||||
|
const cellFormatPattern = numericFormat && numericFormat.pattern;
|
||||||
|
const className = cellProperties.className || '';
|
||||||
|
const classArr = className.length ? className.split(' ') : [];
|
||||||
|
if (typeof cellCulture !== 'undefined' && !numbro.languages()[cellCulture]) {
|
||||||
|
const shortTag:any = cellCulture.replace('-', '');
|
||||||
|
const langData = (numbro as any)[shortTag];
|
||||||
|
|
||||||
|
if (langData) {
|
||||||
|
numbro.registerLanguage(langData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const totalCount = Number(instance.getCell(row,col-1)?.innerHTML)
|
||||||
|
numbro.setLanguage(cellCulture);
|
||||||
|
const num = numbro(newValue)
|
||||||
|
if(totalCount < num.value()) {
|
||||||
|
const newNum = numbro(totalCount)
|
||||||
|
newValue = newNum.format(cellFormatPattern || '0');
|
||||||
|
}else {
|
||||||
|
newValue = num.format(cellFormatPattern || '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classArr.indexOf('htLeft') < 0 && classArr.indexOf('htCenter') < 0 &&
|
||||||
|
classArr.indexOf('htRight') < 0 && classArr.indexOf('htJustify') < 0) {
|
||||||
|
classArr.push('htRight');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classArr.indexOf('htNumeric') < 0) {
|
||||||
|
classArr.push('htNumeric');
|
||||||
|
}
|
||||||
|
cellProperties.className = classArr.join(' ');
|
||||||
|
|
||||||
|
td.dir = 'ltr';
|
||||||
|
newValue = newValue + "x"
|
||||||
|
}else {
|
||||||
|
newValue = ""
|
||||||
|
}
|
||||||
|
textRenderer(instance, td, row, col, prop, newValue, cellProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Equip implements ColumnInfo {
|
||||||
|
name:ColumnName = "Equip"
|
||||||
|
displayName = "equip"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.is_equip ? 1 : 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Drill implements ColumnInfo {
|
||||||
|
name:ColumnName = "Drill"
|
||||||
|
displayName = "drill"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.is_drill ? 1 : 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class All implements ColumnInfo {
|
||||||
|
name:ColumnName = "All"
|
||||||
|
displayName = "swap"
|
||||||
|
getter(_:TricksterItem):(string|number){
|
||||||
|
return -10000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Card implements ColumnInfo {
|
||||||
|
name:ColumnName = "Card"
|
||||||
|
displayName = "card"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return cardFilter(item) ? 1 : 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const cardFilter= (item:TricksterItem): boolean => {
|
||||||
|
return (item.item_name.endsWith(" Card") || item.item_name.startsWith("Star Card"))
|
||||||
|
}
|
||||||
|
class Compound implements ColumnInfo {
|
||||||
|
name:ColumnName = "Compound"
|
||||||
|
displayName = "comp"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return compFilter(item) ? 1 : 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const compFilter= (item:TricksterItem): boolean => {
|
||||||
|
return (item.item_desc.toLowerCase().includes("compound item"))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Quest implements ColumnInfo {
|
||||||
|
name:ColumnName = "Quest"
|
||||||
|
displayName = "quest"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return questFilter(item) ? 1 : 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const questFilter= (item:TricksterItem): boolean => {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
class Consume implements ColumnInfo {
|
||||||
|
name:ColumnName = "Consume"
|
||||||
|
displayName = "eat"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return consumeFilter(item) ? 1 : 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const consumeFilter= (item:TricksterItem): boolean => {
|
||||||
|
const tl = item.item_use.toLowerCase()
|
||||||
|
return tl.includes("recover") || tl.includes("restores")
|
||||||
|
}
|
||||||
|
|
||||||
|
class AP implements ColumnInfo {
|
||||||
|
name:ColumnName = "AP"
|
||||||
|
displayName = "AP"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.stats ? item.stats["AP"] : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GunAP implements ColumnInfo {
|
||||||
|
name:ColumnName = "GunAP"
|
||||||
|
displayName = "Gun AP"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.stats ? item.stats["Gun AP"] : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AC implements ColumnInfo {
|
||||||
|
name:ColumnName = "AC"
|
||||||
|
displayName = "AC"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.stats ? item.stats["AC"] : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DX implements ColumnInfo {
|
||||||
|
name:ColumnName = "DX"
|
||||||
|
displayName = "DX"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.stats ? item.stats["DX"] : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MP implements ColumnInfo {
|
||||||
|
name:ColumnName = "MP"
|
||||||
|
displayName = "MP"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.stats ? item.stats["MP"] : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MA implements ColumnInfo {
|
||||||
|
name:ColumnName = "MA"
|
||||||
|
displayName = "MA"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.stats ? item.stats["MA"] : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MD implements ColumnInfo {
|
||||||
|
name:ColumnName = "MD"
|
||||||
|
displayName = "MD"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.stats ? item.stats["MD"] : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WT implements ColumnInfo {
|
||||||
|
name:ColumnName = "WT"
|
||||||
|
displayName = "WT"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.stats ? item.stats["WT"] : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DA implements ColumnInfo {
|
||||||
|
name:ColumnName = "DA"
|
||||||
|
displayName = "DA"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.stats ? item.stats["DA"] : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LK implements ColumnInfo {
|
||||||
|
name:ColumnName = "LK"
|
||||||
|
displayName = "LK"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.stats ? item.stats["LK"] : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HP implements ColumnInfo {
|
||||||
|
name:ColumnName = "HP"
|
||||||
|
displayName = "HP"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.stats ? item.stats["HP"] : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DP implements ColumnInfo {
|
||||||
|
name:ColumnName = "DP"
|
||||||
|
displayName = "DP"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.stats ? item.stats["DP"] : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class HV implements ColumnInfo {
|
||||||
|
name:ColumnName = "HV"
|
||||||
|
displayName = "HV"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.stats ? item.stats["HV"] : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MinLvl implements ColumnInfo {
|
||||||
|
name:ColumnName = "MinLvl"
|
||||||
|
displayName = "lvl"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
//TODO:
|
||||||
|
return item.item_min_level? item.item_min_level:""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Slots implements ColumnInfo {
|
||||||
|
name:ColumnName = "Slots"
|
||||||
|
displayName = "slots"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
//TODO:
|
||||||
|
return item.item_slots ? item.item_slots : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RefineNumber implements ColumnInfo {
|
||||||
|
name:ColumnName = "RefineNumber"
|
||||||
|
displayName = "refine"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.refine_level ? item.refine_level : 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RefineState implements ColumnInfo {
|
||||||
|
name:ColumnName = "RefineState"
|
||||||
|
displayName = "bork"
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.refine_state ? item.refine_state : 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Desc implements ColumnInfo {
|
||||||
|
name:ColumnName = "Desc"
|
||||||
|
displayName = "desc"
|
||||||
|
renderer = descRenderer
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.item_desc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function descRenderer(instance:any, td:any, row:any, col:any, prop:any, value:any, cellProperties:any) {
|
||||||
|
const stringifiedValue = Handsontable.helper.stringify(value);
|
||||||
|
let showText = stringifiedValue;
|
||||||
|
const div= document.createElement('div');
|
||||||
|
div.innerHTML = showText
|
||||||
|
div.title = showText
|
||||||
|
div.style.maxWidth = "30ch"
|
||||||
|
div.style.textOverflow = "ellipsis"
|
||||||
|
div.style.overflow= "hidden"
|
||||||
|
div.style.whiteSpace= "nowrap"
|
||||||
|
Handsontable.dom.addEvent(div, 'mousedown', event =>{
|
||||||
|
event!.preventDefault();
|
||||||
|
});
|
||||||
|
Handsontable.dom.empty(td);
|
||||||
|
td.appendChild(div);
|
||||||
|
td.classList.add("htLeft")
|
||||||
|
}
|
||||||
|
|
||||||
|
class Use implements ColumnInfo {
|
||||||
|
name:ColumnName = "Use"
|
||||||
|
displayName = "use"
|
||||||
|
renderer= useRenderer;
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.item_use
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function useRenderer(instance:any, td:any, row:any, col:any, prop:any, value:any, cellProperties:any) {
|
||||||
|
const stringifiedValue = Handsontable.helper.stringify(value);
|
||||||
|
let showText = stringifiedValue;
|
||||||
|
const div= document.createElement('div');
|
||||||
|
div.title = showText
|
||||||
|
div.innerHTML = showText
|
||||||
|
div.style.maxWidth = "30ch"
|
||||||
|
div.style.textOverflow = "ellipsis"
|
||||||
|
div.style.overflow= "hidden"
|
||||||
|
div.style.whiteSpace= "nowrap"
|
||||||
|
Handsontable.dom.addEvent(div, 'mousedown', event =>{
|
||||||
|
event!.preventDefault();
|
||||||
|
});
|
||||||
|
Handsontable.dom.empty(td);
|
||||||
|
td.appendChild(div);
|
||||||
|
td.classList.add("htLeft")
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Columns:{[Property in ColumnName]:ColumnInfo}= {
|
||||||
|
Use: new Use(),
|
||||||
|
Desc: new Desc(),
|
||||||
|
Image: new Image(),
|
||||||
|
Name: new Name(),
|
||||||
|
Count: new Count(),
|
||||||
|
Move: new Move(),
|
||||||
|
MoveCount: new MoveCount(),
|
||||||
|
Equip: new Equip(),
|
||||||
|
Drill: new Drill(),
|
||||||
|
Card: new Card(),
|
||||||
|
Quest: new Quest(),
|
||||||
|
Consume: new Consume(),
|
||||||
|
AP: new AP(),
|
||||||
|
GunAP: new GunAP(),
|
||||||
|
AC: new AC(),
|
||||||
|
DX: new DX(),
|
||||||
|
MP: new MP(),
|
||||||
|
MA: new MA(),
|
||||||
|
MD: new MD(),
|
||||||
|
WT: new WT(),
|
||||||
|
DA: new DA(),
|
||||||
|
LK: new LK(),
|
||||||
|
HP: new HP(),
|
||||||
|
DP: new DP(),
|
||||||
|
HV: new HV(),
|
||||||
|
MinLvl: new MinLvl(),
|
||||||
|
Slots: new Slots(),
|
||||||
|
RefineNumber: new RefineNumber(),
|
||||||
|
RefineState: new RefineState(),
|
||||||
|
All: new All(),
|
||||||
|
Compound: new Compound(),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
3
src/lib/columns/index.ts
Normal file
3
src/lib/columns/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from "./column"
|
||||||
|
export * from "./column_impl"
|
||||||
|
|
@ -1,149 +0,0 @@
|
|||||||
import { Axios, AxiosResponse } from "axios"
|
|
||||||
import log from "loglevel"
|
|
||||||
import { RefStore } from "../state/state"
|
|
||||||
import { Session } from "./session"
|
|
||||||
import { dummyChar, TricksterInventory, TricksterItem, TricksterWallet } from "./trickster"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export interface LTOApi {
|
|
||||||
GetAccount:(name:string) =>Promise<[TricksterInventory, Array<string>]>
|
|
||||||
GetInventory:(path:string)=>Promise<TricksterInventory>
|
|
||||||
GetAccounts:() =>Promise<Array<string>>
|
|
||||||
GetLoggedin: ()=>Promise<boolean>
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SessionBinding {
|
|
||||||
new(s:Session):LTOApi
|
|
||||||
}
|
|
||||||
export const getLTOState = <A extends LTOApi>(c: new (s:Session) => A,s:Session, r:RefStore): LTOApi => {
|
|
||||||
return new StatefulLTOApi(new c(s),r);
|
|
||||||
}
|
|
||||||
|
|
||||||
export class StatefulLTOApi implements LTOApi {
|
|
||||||
u: LTOApi
|
|
||||||
r: RefStore
|
|
||||||
constructor(s:LTOApi, r:RefStore){
|
|
||||||
this.u = s
|
|
||||||
this.r=r
|
|
||||||
}
|
|
||||||
GetAccount = async (name:string):Promise<[TricksterInventory, Array<string>]> =>{
|
|
||||||
const account = await this.u.GetAccount(name)
|
|
||||||
this.r.invs.value.set(account[0].path,account[0])
|
|
||||||
account[1].forEach((s)=>{
|
|
||||||
const d = dummyChar(s)
|
|
||||||
this.r.invs.value.set(d.path,d)
|
|
||||||
})
|
|
||||||
this.r.dirty.value = this.r.dirty.value + 1
|
|
||||||
return account
|
|
||||||
}
|
|
||||||
GetInventory = async (path:string):Promise<TricksterInventory>=>{
|
|
||||||
if(!path.includes("/")) {
|
|
||||||
const a = await this.GetAccount(path)
|
|
||||||
return a[0]
|
|
||||||
}
|
|
||||||
const inv = await this.u.GetInventory(path)
|
|
||||||
this.r.invs.value.set(inv.path,inv)
|
|
||||||
this.r.dirty.value = this.r.dirty.value + 1
|
|
||||||
return inv
|
|
||||||
}
|
|
||||||
GetAccounts = async ():Promise<Array<string>> =>{
|
|
||||||
return this.u.GetAccounts()
|
|
||||||
}
|
|
||||||
GetLoggedin= async ():Promise<boolean>=>{
|
|
||||||
return this.u.GetLoggedin()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class LTOApiv0 implements LTOApi {
|
|
||||||
s: Session
|
|
||||||
|
|
||||||
constructor(s:Session) {
|
|
||||||
this.s = s
|
|
||||||
}
|
|
||||||
|
|
||||||
GetAccount = async (account: string):Promise<[TricksterInventory, Array<string>]> => {
|
|
||||||
return this.s.authed_request("GET", `item-manager/items/account/${account}`,undefined).then(async (ans:AxiosResponse)=>{
|
|
||||||
const o = ans.data
|
|
||||||
log.debug("GetAccount", o)
|
|
||||||
let out:string[] = []
|
|
||||||
Object.entries(o.characters).forEach((x:[string,any])=>{
|
|
||||||
out.push(`${account}/${x[1].name}`)
|
|
||||||
})
|
|
||||||
return [{
|
|
||||||
name: account,
|
|
||||||
id:account,
|
|
||||||
wallet: {
|
|
||||||
galders: 0,
|
|
||||||
state: 0,
|
|
||||||
job_img: "bank",
|
|
||||||
},
|
|
||||||
path: account,
|
|
||||||
items:(Object.entries(o.items) as any).map(([k, v]: [string, TricksterItem]):TricksterItem=>{
|
|
||||||
v.unique_id = Number(k)
|
|
||||||
return v
|
|
||||||
}),
|
|
||||||
},out]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
GetInventory = async (char_path: string):Promise<TricksterInventory> =>{
|
|
||||||
if(char_path.startsWith(":")) {
|
|
||||||
char_path = char_path.replace(":","")
|
|
||||||
}
|
|
||||||
return this.s.authed_request("GET", `item-manager/items/account/${char_path}`,undefined).then((ans:AxiosResponse)=>{
|
|
||||||
const o = ans.data
|
|
||||||
log.debug("GetInventory", o)
|
|
||||||
let name = ""
|
|
||||||
let id = ""
|
|
||||||
let wallet:TricksterWallet = {galders:0,state:0,job_img:""}
|
|
||||||
if(char_path.includes("/")) {
|
|
||||||
let [char, val] = Object.entries(o.characters)[0] as [string,any]
|
|
||||||
name = val.name
|
|
||||||
id = char
|
|
||||||
wallet = {
|
|
||||||
galders:val.galders as number,
|
|
||||||
state:val.state as number,
|
|
||||||
job_img: val.job_img as string
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
name = char_path
|
|
||||||
id = char_path
|
|
||||||
wallet = {
|
|
||||||
galders: 0,
|
|
||||||
state: 0,
|
|
||||||
job_img: "bank",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let out = {
|
|
||||||
name,
|
|
||||||
id,
|
|
||||||
wallet,
|
|
||||||
path: char_path,
|
|
||||||
items:(Object.entries(o.items) as any).map(([k, v]: [string, TricksterItem]):TricksterItem=>{
|
|
||||||
v.unique_id = Number(k)
|
|
||||||
return v
|
|
||||||
}),
|
|
||||||
} as TricksterInventory
|
|
||||||
return out
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
GetAccounts = async ():Promise<string[]> => {
|
|
||||||
return this.s.authed_request("POST", "accounts/list",undefined).then((ans:AxiosResponse)=>{
|
|
||||||
log.debug("GetAccounts", ans.data)
|
|
||||||
return ans.data.map((x:any)=>x.name)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
GetLoggedin = async ():Promise<boolean> => {
|
|
||||||
return this.s.authed_request("POST", "accounts/list",undefined).then((ans:AxiosResponse)=>{
|
|
||||||
if(ans.status == 401) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if(ans.status == 200) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
40
src/lib/lifeto/api.ts
Normal file
40
src/lib/lifeto/api.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { trace } from "loglevel"
|
||||||
|
import { TricksterAccount, TricksterInventory } from "../trickster"
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
|
|
||||||
|
export interface LTOApi {
|
||||||
|
GetInventory:(path:string)=>Promise<TricksterInventory>
|
||||||
|
GetAccounts:() =>Promise<Array<TricksterAccount>>
|
||||||
|
GetLoggedin: ()=>Promise<boolean>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TxnStates = ["PENDING","INFLIGHT","WAITING","ERROR","SUCCESS"] as const
|
||||||
|
export type TxnState = typeof TxnStates[number]
|
||||||
|
|
||||||
|
export interface TxnDetails {
|
||||||
|
item_uid: string | "galders"
|
||||||
|
count:number
|
||||||
|
origin:string
|
||||||
|
target:string
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class BankReceipt {
|
||||||
|
action_id: string
|
||||||
|
details:TxnDetails
|
||||||
|
created:Date
|
||||||
|
|
||||||
|
constructor(details:TxnDetails) {
|
||||||
|
this.details = details
|
||||||
|
this.created = new Date()
|
||||||
|
this.action_id = uuidv4();
|
||||||
|
}
|
||||||
|
abstract state():Promise<TxnState>
|
||||||
|
abstract status():string
|
||||||
|
abstract progress():[number, number]
|
||||||
|
abstract error():string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BankApi {
|
||||||
|
SendTxn: (txn:TxnDetails) => Promise<BankReceipt>
|
||||||
|
}
|
3
src/lib/lifeto/index.ts
Normal file
3
src/lib/lifeto/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from "./lifeto"
|
||||||
|
export * from "./api"
|
||||||
|
export * from "./stateful"
|
78
src/lib/lifeto/lifeto.ts
Normal file
78
src/lib/lifeto/lifeto.ts
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import { Axios, AxiosResponse } from "axios"
|
||||||
|
import { zhCN } from "handsontable/i18n"
|
||||||
|
import log from "loglevel"
|
||||||
|
import { RefStore } from "../../state/state"
|
||||||
|
import { Session } from "../session"
|
||||||
|
import { dummyChar, TricksterAccount, TricksterInventory, TricksterItem, TricksterWallet } from "../trickster"
|
||||||
|
import { LTOApi } from "./api"
|
||||||
|
|
||||||
|
export class LTOApiv0 implements LTOApi {
|
||||||
|
s: Session
|
||||||
|
constructor(s:Session) {
|
||||||
|
this.s = s
|
||||||
|
}
|
||||||
|
GetInventory = async (char_path: string):Promise<TricksterInventory> =>{
|
||||||
|
if(char_path.startsWith(":")) {
|
||||||
|
char_path = char_path.replace(":","")
|
||||||
|
}
|
||||||
|
return this.s.authed_request("GET", `item-manager/items/account/${char_path}`,undefined).then((ans:AxiosResponse)=>{
|
||||||
|
const o = ans.data
|
||||||
|
log.debug("GetInventory", o)
|
||||||
|
let name = "bank"
|
||||||
|
let id = 0
|
||||||
|
let galders = 0
|
||||||
|
if(char_path.includes("/")) {
|
||||||
|
let [char, val] = Object.entries(o.characters)[0] as [string,any]
|
||||||
|
name = val.name
|
||||||
|
id = Number(char)
|
||||||
|
galders = val.galders as number
|
||||||
|
}else {
|
||||||
|
id = o.id
|
||||||
|
name = o.name
|
||||||
|
galders = o.galders
|
||||||
|
}
|
||||||
|
let out = {
|
||||||
|
name,
|
||||||
|
id,
|
||||||
|
path: char_path,
|
||||||
|
galders,
|
||||||
|
items:(Object.entries(o.items) as any).map(([k, v]: [string, TricksterItem]):TricksterItem=>{
|
||||||
|
v.unique_id = Number(k)
|
||||||
|
return v
|
||||||
|
}),
|
||||||
|
} as TricksterInventory
|
||||||
|
return out
|
||||||
|
})
|
||||||
|
}
|
||||||
|
GetAccounts = async ():Promise<TricksterAccount[]> => {
|
||||||
|
return this.s.authed_request("GET", "characters/list",undefined).then((ans:AxiosResponse)=>{
|
||||||
|
log.debug("GetAccounts", ans.data)
|
||||||
|
return ans.data.map((x:any)=>{
|
||||||
|
return {
|
||||||
|
name: x.name,
|
||||||
|
characters: [{id: x.id, path:x.name, name: x.name+'/bank', class:-8, base_job: -8, current_job: -8},...Object.values(x.characters).map((z:any)=>{
|
||||||
|
return {
|
||||||
|
id: z.id,
|
||||||
|
name: z.name,
|
||||||
|
path: x.name+"/"+z.name,
|
||||||
|
class: z.class,
|
||||||
|
base_job: z.base_job,
|
||||||
|
current_job: z.current_job,
|
||||||
|
}
|
||||||
|
})],
|
||||||
|
} as TricksterAccount
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
GetLoggedin = async ():Promise<boolean> => {
|
||||||
|
return this.s.authed_request("POST", "accounts/list",undefined).then((ans:AxiosResponse)=>{
|
||||||
|
if(ans.status == 401) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if(ans.status == 200) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
39
src/lib/lifeto/stateful.ts
Normal file
39
src/lib/lifeto/stateful.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { RefStore } from "../../state/state";
|
||||||
|
import { Session } from "../session";
|
||||||
|
import { TricksterAccount, TricksterInventory } from "../trickster";
|
||||||
|
import { LTOApi } from "./api";
|
||||||
|
|
||||||
|
export interface SessionBinding {
|
||||||
|
new(s:Session):LTOApi
|
||||||
|
}
|
||||||
|
export const getLTOState = <A extends LTOApi>(c: new (s:Session) => A,s:Session, r:RefStore): LTOApi => {
|
||||||
|
return new StatefulLTOApi(new c(s),r);
|
||||||
|
}
|
||||||
|
|
||||||
|
export class StatefulLTOApi implements LTOApi {
|
||||||
|
u: LTOApi
|
||||||
|
r: RefStore
|
||||||
|
constructor(s:LTOApi, r:RefStore){
|
||||||
|
this.u = s
|
||||||
|
this.r=r
|
||||||
|
}
|
||||||
|
GetInventory = async (path:string):Promise<TricksterInventory>=>{
|
||||||
|
const inv = await this.u.GetInventory(path)
|
||||||
|
this.r.invs.value.set(inv.path,inv)
|
||||||
|
this.r.dirty.value = this.r.dirty.value + 1
|
||||||
|
return inv
|
||||||
|
}
|
||||||
|
GetAccounts = async ():Promise<TricksterAccount[]> => {
|
||||||
|
const xs = await this.u.GetAccounts()
|
||||||
|
xs.forEach((x)=>{
|
||||||
|
x.characters.forEach((ch)=>{
|
||||||
|
this.r.chars.value.set(ch.path,ch)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return xs
|
||||||
|
}
|
||||||
|
GetLoggedin= async ():Promise<boolean>=>{
|
||||||
|
return this.u.GetLoggedin()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,30 +8,30 @@ import { RefStore } from "../state/state";
|
|||||||
|
|
||||||
export const BasicColumns = [
|
export const BasicColumns = [
|
||||||
"Image","Name","Count",
|
"Image","Name","Count",
|
||||||
]
|
] as const
|
||||||
|
|
||||||
export const DetailsColumns = [
|
export const DetailsColumns = [
|
||||||
"Desc","Use",
|
"Desc","Use",
|
||||||
]
|
] as const
|
||||||
|
|
||||||
export const MoveColumns = [
|
export const MoveColumns = [
|
||||||
"MoveCount","Move",
|
"MoveCount","Move",
|
||||||
]
|
] as const
|
||||||
|
|
||||||
export const TagColumns = [
|
export const TagColumns = [
|
||||||
"All","Equip","Drill","Card","Quest","Consume", "Compound"
|
"All","Equip","Drill","Card","Quest","Consume", "Compound"
|
||||||
]
|
] as const
|
||||||
|
|
||||||
export const HackColumns = [
|
|
||||||
]
|
|
||||||
|
|
||||||
export const EquipmentColumns = [
|
export const EquipmentColumns = [
|
||||||
"MinLvl","Slots","RefineNumber","RefineState",
|
"MinLvl","Slots","RefineNumber","RefineState",
|
||||||
]
|
] as const
|
||||||
|
|
||||||
export const StatsColumns = [
|
export const StatsColumns = [
|
||||||
"AP","GunAP","AC","DX","MP","MA","MD","WT","DA","LK","HP","DP","HV",
|
"AP","GunAP","AC","DX","MP","MA","MD","WT","DA","LK","HP","DP","HV",
|
||||||
]
|
] as const
|
||||||
|
|
||||||
|
export const HackColumns = [
|
||||||
|
] as const
|
||||||
|
|
||||||
export const ColumnNames = [
|
export const ColumnNames = [
|
||||||
...BasicColumns,
|
...BasicColumns,
|
||||||
@ -40,7 +40,8 @@ export const ColumnNames = [
|
|||||||
...EquipmentColumns,
|
...EquipmentColumns,
|
||||||
...StatsColumns,
|
...StatsColumns,
|
||||||
...TagColumns,
|
...TagColumns,
|
||||||
]
|
...HackColumns,
|
||||||
|
] as const
|
||||||
|
|
||||||
export type ColumnName = typeof ColumnNames[number]
|
export type ColumnName = typeof ColumnNames[number]
|
||||||
|
|
||||||
@ -472,11 +473,6 @@ function useRenderer(instance:any, td:any, row:any, col:any, prop:any, value:any
|
|||||||
td.appendChild(div);
|
td.appendChild(div);
|
||||||
td.classList.add("htLeft")
|
td.classList.add("htLeft")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const ColumnByNames = (...n:ColumnName[]) => {
|
export const ColumnByNames = (...n:ColumnName[]) => {
|
||||||
return n.map(ColumnByName)
|
return n.map(ColumnByName)
|
||||||
}
|
}
|
||||||
@ -484,6 +480,10 @@ export const ColumnByNames = (...n:ColumnName[]) => {
|
|||||||
export const ColumnByName = (n:ColumnName) => {
|
export const ColumnByName = (n:ColumnName) => {
|
||||||
return Columns[n]
|
return Columns[n]
|
||||||
}
|
}
|
||||||
|
export const test = <T extends ColumnInfo>(n:(new ()=>T)):[string,T] => {
|
||||||
|
let nn = new n()
|
||||||
|
return [nn.name, nn]
|
||||||
|
}
|
||||||
|
|
||||||
export const Columns:{[Property in ColumnName]:ColumnInfo}= {
|
export const Columns:{[Property in ColumnName]:ColumnInfo}= {
|
||||||
Use: new Use(),
|
Use: new Use(),
|
@ -14,7 +14,7 @@
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
import { ColumnSet } from "./table"
|
import { ColumnSet } from "./table"
|
||||||
import { dummyChar, TricksterInventory } from "./trickster"
|
import { TricksterCharacter, TricksterInventory } from "./trickster"
|
||||||
|
|
||||||
export const ARRAY_SEPERATOR = ","
|
export const ARRAY_SEPERATOR = ","
|
||||||
|
|
||||||
@ -45,9 +45,9 @@ export const StoreStrSet = {
|
|||||||
|
|
||||||
export const StoreColSet = {
|
export const StoreColSet = {
|
||||||
Murder: (s:ColumnSet):string=>Array.from(s.s.values()).join(as),
|
Murder: (s:ColumnSet):string=>Array.from(s.s.values()).join(as),
|
||||||
Revive: (s:string):ColumnSet=>new ColumnSet(s.split(as))
|
Revive: (s:string):ColumnSet=>new ColumnSet(s.split(as) as any)
|
||||||
}
|
}
|
||||||
export const StoreInvs = {
|
export const StoreChars = {
|
||||||
Murder: (s:Map<string,TricksterInventory>):string=>Array.from(s.keys()).join(as),
|
Murder: (s:Map<string,TricksterCharacter>):string=>JSON.stringify(Object.entries(s)),
|
||||||
Revive: (s:string):Map<string,TricksterInventory>=>new Map(s.split(as).map((x)=>[x, dummyChar(x)])),
|
Revive: (s:string):Map<string,TricksterCharacter>=>new Map(JSON.parse(s)),
|
||||||
}
|
}
|
||||||
|
@ -114,30 +114,18 @@ export class InventoryTable {
|
|||||||
getTableRows():any[][] {
|
getTableRows():any[][] {
|
||||||
return Object.values(this.inv.items)
|
return Object.values(this.inv.items)
|
||||||
.filter((item):boolean=>{
|
.filter((item):boolean=>{
|
||||||
let found = false
|
let found = true
|
||||||
if(this.o.tags.has("All")) {
|
let hasAll = this.o.tags.has("All")
|
||||||
found = true
|
|
||||||
}
|
|
||||||
if(this.o.tags.s.size > 0) {
|
if(this.o.tags.s.size > 0) {
|
||||||
|
found = hasAll
|
||||||
for(const tag of this.o.tags.values()) {
|
for(const tag of this.o.tags.values()) {
|
||||||
if(tag.name =="All") {
|
if(tag.name =="All") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
let chk = tag.getter(item)
|
if(tag.getter(item) === 1) {
|
||||||
if(this.o.tags.has("All")) {
|
return !hasAll
|
||||||
if(chk === 1) {
|
|
||||||
found = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
if(chk === 1) {
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else {
|
|
||||||
found = true
|
|
||||||
}
|
}
|
||||||
return found
|
return found
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
import sampleAyshe from "./sample/ayshe.json"
|
|
||||||
|
|
||||||
|
|
||||||
export interface ItemExpireTime {
|
export interface ItemExpireTime {
|
||||||
text: string
|
text: string
|
||||||
us: string
|
us: string
|
||||||
@ -25,39 +22,41 @@ export interface TricksterItem {
|
|||||||
stats?: {[key: string]:any}
|
stats?: {[key: string]:any}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TricksterWallet {
|
export interface TricksterAccount {
|
||||||
galders:number
|
name:string
|
||||||
state:number
|
characters: TricksterCharacter[]
|
||||||
job_img:string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TricksterInventory {
|
export interface Identifier {
|
||||||
path:string
|
id: number
|
||||||
name:string
|
name: string
|
||||||
id:string
|
path: string
|
||||||
wallet?:TricksterWallet
|
}
|
||||||
|
|
||||||
|
export interface TricksterCharacter extends Identifier {
|
||||||
|
class: number
|
||||||
|
base_job: number
|
||||||
|
current_job: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TricksterInventory extends Identifier{
|
||||||
|
galders?:number
|
||||||
items:{[key:string]:TricksterItem}
|
items:{[key:string]:TricksterItem}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const dummyChar = (s:string):TricksterInventory => {
|
|
||||||
return {
|
const jobMap:{[key:number]:string} = {
|
||||||
path: s,
|
31: "diva",
|
||||||
name: s.split("/").pop()!,
|
29: "scientist",
|
||||||
id: s,
|
11: "sheep",
|
||||||
items:{}
|
}
|
||||||
|
|
||||||
|
export const JobNumberToString = (n:number):string=> {
|
||||||
|
if(n == -8) {
|
||||||
|
return "bank"
|
||||||
}
|
}
|
||||||
}
|
if(jobMap[n] != undefined) {
|
||||||
|
return jobMap[n]
|
||||||
|
}
|
||||||
|
return n.toString()
|
||||||
export const SampleData:{[key:string]:TricksterInventory} = {
|
|
||||||
aysheBoyfriend: {
|
|
||||||
name: sampleAyshe.characters[100047311].name,
|
|
||||||
items: sampleAyshe.items,
|
|
||||||
wallet: {
|
|
||||||
galders: sampleAyshe.characters[100047311].galders,
|
|
||||||
job_img: sampleAyshe.characters[100047311].job_img,
|
|
||||||
state: sampleAyshe.characters[100047311].state
|
|
||||||
}
|
|
||||||
} as any
|
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,14 @@
|
|||||||
id="loginButton"
|
id="loginButton"
|
||||||
v-on:click="login()"
|
v-on:click="login()"
|
||||||
>Login</button>
|
>Login</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
id="logoutButton"
|
||||||
|
v-on:click="logout()"
|
||||||
|
>Logout</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@ -38,6 +45,7 @@ const login = () => {
|
|||||||
.then((session)=>{
|
.then((session)=>{
|
||||||
console.log(session, "adding to storage")
|
console.log(session, "adding to storage")
|
||||||
storage.AddSession(session)
|
storage.AddSession(session)
|
||||||
|
window.location.reload()
|
||||||
}).catch((e)=>{
|
}).catch((e)=>{
|
||||||
if(e.code == "ERR_BAD_REQUEST") {
|
if(e.code == "ERR_BAD_REQUEST") {
|
||||||
alert("invalid username/password")
|
alert("invalid username/password")
|
||||||
@ -48,6 +56,12 @@ const login = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const logout = () => {
|
||||||
|
storage.RemoveSession()
|
||||||
|
localStorage.clear()
|
||||||
|
window.location.reload()
|
||||||
|
}
|
||||||
|
|
||||||
const s = storage.GetSession()
|
const s = storage.GetSession()
|
||||||
const api = new LTOApiv0(s)
|
const api = new LTOApiv0(s)
|
||||||
if (s != undefined) {
|
if (s != undefined) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { getCookie, setCookie} from 'typescript-cookie'
|
import { Cookies, getCookie, removeCookie, setCookie} from 'typescript-cookie'
|
||||||
import { Session, TokenSession } from './lib/session'
|
import { Session, TokenSession } from './lib/session'
|
||||||
|
|
||||||
|
|
||||||
@ -20,9 +20,9 @@ export class Storage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RemoveSession() {
|
RemoveSession() {
|
||||||
setCookie(nameCookie("user"),"")
|
removeCookie(nameCookie("user"))
|
||||||
setCookie(nameCookie("xsrf"),"")
|
removeCookie(nameCookie("xsrf"))
|
||||||
setCookie(nameCookie("csrf"),"")
|
removeCookie(nameCookie("csrf"))
|
||||||
}
|
}
|
||||||
AddSession(s:Session) {
|
AddSession(s:Session) {
|
||||||
setCookie(nameCookie("user"),s.user)
|
setCookie(nameCookie("user"),s.user)
|
||||||
@ -32,3 +32,5 @@ export class Storage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const storage = new Storage()
|
export const storage = new Storage()
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,9 +2,9 @@ import { defineStore, storeToRefs } from 'pinia'
|
|||||||
import { getCookie, setCookie } from 'typescript-cookie'
|
import { getCookie, setCookie } from 'typescript-cookie'
|
||||||
import { useCookies } from 'vue3-cookies'
|
import { useCookies } from 'vue3-cookies'
|
||||||
import { BasicColumns, ColumnInfo, ColumnName, Columns, DetailsColumns, MoveColumns } from '../lib/columns'
|
import { BasicColumns, ColumnInfo, ColumnName, Columns, DetailsColumns, MoveColumns } from '../lib/columns'
|
||||||
import { Reviver, StoreColSet, StoreInvs, StoreStr, StoreStrSet } from '../lib/storage'
|
import { Reviver, StoreChars, StoreColSet, StoreInvs, StoreStr, StoreStrSet } from '../lib/storage'
|
||||||
import { ColumnSet } from '../lib/table'
|
import { ColumnSet } from '../lib/table'
|
||||||
import { TricksterInventory } from '../lib/trickster'
|
import { TricksterCharacter, TricksterInventory } from '../lib/trickster'
|
||||||
import { nameCookie} from '../session_storage'
|
import { nameCookie} from '../session_storage'
|
||||||
|
|
||||||
const _defaultColumn:(ColumnInfo| ColumnName)[] = [
|
const _defaultColumn:(ColumnInfo| ColumnName)[] = [
|
||||||
@ -16,6 +16,7 @@ export const useStore = defineStore('state', {
|
|||||||
state: ()=> {
|
state: ()=> {
|
||||||
let store = {
|
let store = {
|
||||||
invs: new Map() as Map<string,TricksterInventory>,
|
invs: new Map() as Map<string,TricksterInventory>,
|
||||||
|
chars: new Map() as Map<string,TricksterCharacter>,
|
||||||
accounts: new Set() as Set<string>,
|
accounts: new Set() as Set<string>,
|
||||||
activeTable: "none",
|
activeTable: "none",
|
||||||
screen: "default",
|
screen: "default",
|
||||||
@ -23,20 +24,13 @@ export const useStore = defineStore('state', {
|
|||||||
tags: new ColumnSet(),
|
tags: new ColumnSet(),
|
||||||
dirty: 0,
|
dirty: 0,
|
||||||
}
|
}
|
||||||
for(const [k, v] of Object.entries(StoreReviver)){
|
loadStore();
|
||||||
const coke = getCookie(nameCookie("last_"+k))
|
|
||||||
if(coke){
|
|
||||||
if((store[k as keyof StoreProps]) != undefined){
|
|
||||||
(store[k as keyof StoreProps] as any) = v.Revive(coke)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return store
|
return store
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export const StoreReviver = {
|
export const StoreReviver = {
|
||||||
invs: StoreInvs,
|
chars: StoreChars,
|
||||||
accounts: StoreStrSet,
|
accounts: StoreStrSet,
|
||||||
activeTable: StoreStr,
|
activeTable: StoreStr,
|
||||||
screen: StoreStr,
|
screen: StoreStr,
|
||||||
@ -46,6 +40,7 @@ export const StoreReviver = {
|
|||||||
|
|
||||||
export interface StoreProps {
|
export interface StoreProps {
|
||||||
invs: Map<string,TricksterInventory>
|
invs: Map<string,TricksterInventory>
|
||||||
|
chars: Map<string, TricksterCharacter>
|
||||||
accounts: Set<string>
|
accounts: Set<string>
|
||||||
activeTable: string
|
activeTable: string
|
||||||
screen: string
|
screen: string
|
||||||
@ -56,25 +51,24 @@ export interface StoreProps {
|
|||||||
export const loadStore = ()=> {
|
export const loadStore = ()=> {
|
||||||
let store = useStoreRef()
|
let store = useStoreRef()
|
||||||
for(const [k, v] of Object.entries(StoreReviver)){
|
for(const [k, v] of Object.entries(StoreReviver)){
|
||||||
const coke = getCookie(nameCookie("last_"+k))
|
const coke = localStorage.getItem(nameCookie("last_"+k))
|
||||||
if(coke){
|
if(coke){
|
||||||
if((store[k as keyof StoreProps]) != undefined){
|
if((store[k as keyof RefStore]) != undefined){
|
||||||
store[k as keyof StoreProps].value = v.Revive(coke)
|
store[k as keyof RefStore].value = v.Revive(coke) as any
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const saveStore = ()=> {
|
export const saveStore = ()=> {
|
||||||
let store = useStoreRef()
|
let store = useStoreRef()
|
||||||
for(const [k, v] of Object.entries(StoreReviver)){
|
for(const [k, v] of Object.entries(StoreReviver)){
|
||||||
let coke;
|
let coke;
|
||||||
|
|
||||||
if((store[k as keyof StoreProps]) != undefined){
|
if((store[k as keyof RefStore]) != undefined){
|
||||||
coke = v.Murder(store[k as keyof StoreProps].value as any)
|
coke = v.Murder(store[k as keyof RefStore].value as any)
|
||||||
}
|
}
|
||||||
if(coke){
|
if(coke){
|
||||||
setCookie(nameCookie("last_"+k),coke)
|
localStorage.setItem(nameCookie("last_"+k),coke)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user