Spaces:
Sleeping
Sleeping
File size: 4,351 Bytes
15f353f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | /**
* Pinia store for MCTS visualization state
*/
import { defineStore } from "pinia";
import { ref, computed } from "vue";
import type {
MCTSMoveData,
MCTSMoveStatistic,
MCTSStatisticType,
ColorScaleType
} from "@/types/mcts";
import type { Position } from "../../../inc/trigo/types";
export const useMCTSStore = defineStore("mcts", () => {
// ============================================================================
// State
// ============================================================================
// Game data
const gameHistory = ref<MCTSMoveData[]>([]);
const currentMoveIndex = ref<number>(0);
// Visualization settings
const selectedStatistic = ref<MCTSStatisticType>("N");
const colorScale = ref<ColorScaleType>("linear");
const topNFilter = ref<number>(10); // Show top N moves in tree/table
// Selection state
const selectedActionKey = ref<string | null>(null);
// ============================================================================
// Getters
// ============================================================================
const hasData = computed(() => gameHistory.value.length > 0);
const currentMoveData = computed((): MCTSMoveData | null => {
if (!hasData.value) return null;
return gameHistory.value[currentMoveIndex.value] || null;
});
const maxMoveIndex = computed(() => {
return Math.max(0, gameHistory.value.length - 1);
});
const currentStatistics = computed((): MCTSMoveStatistic[] => {
return currentMoveData.value?.statistics || [];
});
const topMoves = computed((): MCTSMoveStatistic[] => {
const stats = currentStatistics.value;
return stats
.slice()
.sort((a, b) => b.N - a.N)
.slice(0, topNFilter.value);
});
const totalVisits = computed((): number => {
return currentStatistics.value.reduce((sum, stat) => sum + stat.N, 0);
});
const selectedMove = computed((): MCTSMoveStatistic | null => {
if (!selectedActionKey.value) return null;
return (
currentStatistics.value.find(
(stat) => stat.actionKey === selectedActionKey.value
) || null
);
});
// ============================================================================
// Actions
// ============================================================================
function setGameHistory(history: MCTSMoveData[]) {
gameHistory.value = history;
currentMoveIndex.value = 0;
selectedActionKey.value = null;
}
function clearGameHistory() {
gameHistory.value = [];
currentMoveIndex.value = 0;
selectedActionKey.value = null;
}
function setCurrentMoveIndex(index: number) {
if (index < 0 || index > maxMoveIndex.value) return;
currentMoveIndex.value = index;
// Clear selection when moving to different move
selectedActionKey.value = null;
}
function nextMove() {
if (currentMoveIndex.value < maxMoveIndex.value) {
setCurrentMoveIndex(currentMoveIndex.value + 1);
}
}
function prevMove() {
if (currentMoveIndex.value > 0) {
setCurrentMoveIndex(currentMoveIndex.value - 1);
}
}
function firstMove() {
setCurrentMoveIndex(0);
}
function lastMove() {
setCurrentMoveIndex(maxMoveIndex.value);
}
function setSelectedStatistic(stat: MCTSStatisticType) {
selectedStatistic.value = stat;
}
function setColorScale(scale: ColorScaleType) {
colorScale.value = scale;
}
function setTopNFilter(n: number) {
topNFilter.value = Math.max(3, Math.min(50, n));
}
function selectAction(actionKey: string | null) {
selectedActionKey.value = actionKey;
}
function selectPosition(position: Position | null) {
if (!position) {
selectedActionKey.value = "pass";
return;
}
selectedActionKey.value = `${position.x},${position.y},${position.z}`;
}
// ============================================================================
// Return
// ============================================================================
return {
// State
gameHistory,
currentMoveIndex,
selectedStatistic,
colorScale,
topNFilter,
selectedActionKey,
// Getters
hasData,
currentMoveData,
maxMoveIndex,
currentStatistics,
topMoves,
totalVisits,
selectedMove,
// Actions
setGameHistory,
clearGameHistory,
setCurrentMoveIndex,
nextMove,
prevMove,
firstMove,
lastMove,
setSelectedStatistic,
setColorScale,
setTopNFilter,
selectAction,
selectPosition
};
});
|