174 lines
5.4 KiB
TypeScript
174 lines
5.4 KiB
TypeScript
import type { TurnObj } from "@/defs";
|
|
import { clone, isString, range } from "lodash";
|
|
import { ref, type Ref } from "vue";
|
|
import { unwrap } from "./unwrap";
|
|
|
|
type TurnObjWithTime = TurnObj & {
|
|
time: string;
|
|
year?: number;
|
|
month?: number;
|
|
tooltip?: string;
|
|
style?: Record<string, string>;
|
|
};
|
|
|
|
export const getEmptyTurn = (maxTurn: number): TurnObjWithTime[] => Array.from<TurnObjWithTime>({
|
|
length: maxTurn,
|
|
}).fill({
|
|
arg: {},
|
|
brief: "",
|
|
action: "",
|
|
year: undefined,
|
|
month: undefined,
|
|
time: "",
|
|
});
|
|
|
|
export class QueryActionHelper {
|
|
public readonly reservedCommandList: Ref<TurnObjWithTime[]>;
|
|
public readonly selectedTurnList: Ref<Set<number>>;
|
|
public readonly prevSelectedTurnList: Ref<Set<number>>;
|
|
|
|
constructor(
|
|
protected maxTurn: number,
|
|
) {
|
|
this.reservedCommandList = ref(getEmptyTurn(maxTurn));
|
|
this.selectedTurnList = ref(new Set());
|
|
this.prevSelectedTurnList = ref(new Set([0]));
|
|
}
|
|
|
|
toggleTurn(...reqTurnList: number[] | string[]) {
|
|
for (let turnIdx of reqTurnList) {
|
|
if (isString(turnIdx)) {
|
|
turnIdx = parseInt(turnIdx);
|
|
}
|
|
if (this.selectedTurnList.value.has(turnIdx)) {
|
|
this.selectedTurnList.value.delete(turnIdx);
|
|
} else {
|
|
this.selectedTurnList.value.add(turnIdx);
|
|
}
|
|
}
|
|
}
|
|
|
|
selectTurn(...reqTurnList: number[] | string[]) {
|
|
this.selectedTurnList.value.clear();
|
|
for (const turnIdx of reqTurnList) {
|
|
if (isString(turnIdx)) {
|
|
this.selectedTurnList.value.add(parseInt(turnIdx));
|
|
} else {
|
|
this.selectedTurnList.value.add(turnIdx);
|
|
}
|
|
}
|
|
}
|
|
|
|
selectStep(begin: number, step: number) {
|
|
this.selectedTurnList.value.clear();
|
|
for (const idx of range(0, this.maxTurn)) {
|
|
if ((idx - begin) % step == 0) {
|
|
this.selectedTurnList.value.add(idx);
|
|
}
|
|
}
|
|
}
|
|
|
|
selectAll() {
|
|
for (let i = 0; i < this.maxTurn; i++) {
|
|
this.selectedTurnList.value.add(i);
|
|
}
|
|
}
|
|
|
|
getSelectedTurnList(useSort = true): number[] {
|
|
let result: number[];
|
|
if (this.selectedTurnList.value.size) {
|
|
result = Array.from(this.selectedTurnList.value);
|
|
}
|
|
else if (this.prevSelectedTurnList.value.size) {
|
|
result = Array.from(this.prevSelectedTurnList.value);
|
|
}
|
|
else {
|
|
return [0];
|
|
}
|
|
|
|
if (useSort) {
|
|
return result.sort((a, b) => a - b);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
releaseSelectedTurnList() {
|
|
if (this.selectedTurnList.value.size > 0) {
|
|
this.prevSelectedTurnList.value.clear();
|
|
for (const v of this.selectedTurnList.value) {
|
|
this.prevSelectedTurnList.value.add(v);
|
|
}
|
|
this.selectedTurnList.value.clear();
|
|
}
|
|
}
|
|
|
|
extractQueryActions(): [number[], TurnObj][] {
|
|
const reqTurnList = this.getSelectedTurnList();
|
|
const selectedMinTurnIdx = unwrap(Math.min(...reqTurnList));
|
|
|
|
const buffer = new Map<string, [number[], TurnObj]>();
|
|
for (const rawTurnIdx of reqTurnList) {
|
|
const turnIdx = rawTurnIdx - selectedMinTurnIdx;
|
|
const rawAction = this.reservedCommandList.value[rawTurnIdx]
|
|
const actionStr = JSON.stringify([rawAction.action, rawAction.arg]);
|
|
if (buffer.has(actionStr)) {
|
|
const items = unwrap(buffer.get(actionStr));
|
|
items[0].push(turnIdx);
|
|
}
|
|
else {
|
|
buffer.set(actionStr, [[turnIdx], {
|
|
action: rawAction.action,
|
|
arg: clone(rawAction.arg),
|
|
brief: rawAction.brief
|
|
}])
|
|
}
|
|
}
|
|
return Array.from(buffer.values());
|
|
}
|
|
|
|
amplifyQueryActions(rawActions: [number[], TurnObj][], reqTurnList: number[]): [number[], TurnObj][] {
|
|
if (reqTurnList.length < 1) {
|
|
return [];
|
|
}
|
|
|
|
let minQueryIdx = this.maxTurn;
|
|
let maxQueryIdx = 0;
|
|
for (const [turnList] of rawActions) {
|
|
for (const turnIdx of turnList) {
|
|
minQueryIdx = Math.min(minQueryIdx, turnIdx);
|
|
maxQueryIdx = Math.max(maxQueryIdx, turnIdx);
|
|
}
|
|
}
|
|
const queryLength = maxQueryIdx - minQueryIdx + 1;
|
|
|
|
const queryTurnList: number[] = [reqTurnList[0]];
|
|
for (const reqTurnIdx of reqTurnList) {
|
|
const last = queryTurnList[queryTurnList.length - 1];
|
|
if (reqTurnIdx < last + queryLength) {
|
|
continue;
|
|
}
|
|
queryTurnList.push(reqTurnIdx);
|
|
}
|
|
|
|
const actions: [number[], TurnObj][] = [];
|
|
for (const [baseTurnList, action] of rawActions) {
|
|
const subTurnList: number[] = [];
|
|
for (const baseTurnIdx of baseTurnList) {
|
|
for (const queryTurnIdx of queryTurnList) {
|
|
const targetTurn = baseTurnIdx + queryTurnIdx;
|
|
if (targetTurn >= this.maxTurn) {
|
|
continue;
|
|
}
|
|
subTurnList.push(baseTurnIdx + queryTurnIdx);
|
|
}
|
|
}
|
|
if (subTurnList.length == 0) {
|
|
continue;
|
|
}
|
|
actions.push([subTurnList, action]);
|
|
}
|
|
|
|
return actions;
|
|
}
|
|
}
|