poi-plugin-kai-planner 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +48 -0
  2. package/index.js +35 -0
  3. package/package.json +25 -0
  4. package/src/app/KaiPlannerApp.js +211 -0
  5. package/src/app/tabs/daily/DailyTab.js +439 -0
  6. package/src/app/tabs/debug/DebugTab.js +554 -0
  7. package/src/app/tabs/wishlist/CreatePlanForm.js +185 -0
  8. package/src/app/tabs/wishlist/WishlistTab.js +704 -0
  9. package/src/app/tabs/wishlist/components/MouseComboBox.js +185 -0
  10. package/src/app/tabs/wishlist/components/WishlistExpandedDetail.js +170 -0
  11. package/src/app/tabs/wishlist/components/WishlistTable.js +253 -0
  12. package/src/core/poi/secretaryName.js +64 -0
  13. package/src/data/indexes/buildArrangementIndex.js +103 -0
  14. package/src/data/loaders/loadStaticData.js +182 -0
  15. package/src/data/static/data_manifest.json +15 -0
  16. package/src/data/static/equip_base_cost.json +5000 -0
  17. package/src/data/static/equipment_upgrade_path.json +3555 -0
  18. package/src/data/static/improvement_arrangement.json +15677 -0
  19. package/src/data/static/improvement_consume_item.json +8933 -0
  20. package/src/data/static/improvement_consume_step.json +9284 -0
  21. package/src/data/static/improvement_upgrade_cost.json +4766 -0
  22. package/src/data/static/improvement_upgrade_target.json +2641 -0
  23. package/src/data/static/material.json +90 -0
  24. package/src/services/common/secretaryDisplay.js +42 -0
  25. package/src/services/daily/buildDailyViewModel.js +402 -0
  26. package/src/services/planner/buildUpgradePath.js +79 -0
  27. package/src/services/planner/calcImproveSteps.js +104 -0
  28. package/src/services/planner/calcRemainingPlan.js +169 -0
  29. package/src/services/planner/calcRoutePlan.js +85 -0
  30. package/src/services/planner/calcUpgradeStep.js +85 -0
  31. package/src/services/planner/detectCurrentPosition.js +57 -0
  32. package/src/services/planner/summarizeShortage.js +76 -0
  33. package/src/services/player/countPlayerEquipByMasterId.js +27 -0
  34. package/src/services/player/getEquipOwnerShip.js +66 -0
  35. package/src/services/player/getPlayerData.js +14 -0
  36. package/src/services/player/getPlayerItemCountByUseitemId.js +45 -0
  37. package/src/services/player/getReduxStateFromEnvWindow.js +12 -0
  38. package/src/services/player/resolveMaterialKeyToUseitemId.js +54 -0
  39. package/src/services/static/indexes/buildConsumeIndexes.js +28 -0
  40. package/src/services/static/indexes/buildPathIndexes.js +29 -0
  41. package/src/services/static/indexes/buildUpgradeIndexes.js +57 -0
  42. package/src/services/static/version/dataSourceConfig.js +25 -0
  43. package/src/services/static/version/dataUpdateManager.js +176 -0
  44. package/src/services/static/version/versionStore.js +205 -0
  45. package/src/services/utils/toInt.js +11 -0
  46. package/src/services/utils/tokyoTime.js +58 -0
  47. package/src/services/wishlist/buildWishlistViewModel.js +56 -0
  48. package/src/services/wishlist/dropdownInteraction.js +30 -0
  49. package/src/services/wishlist/wishlistActions.js +485 -0
  50. package/src/storage/userPlans/fileStore.js +106 -0
  51. package/src/storage/userPlans/localStorageStore.js +50 -0
  52. package/src/storage/userPlans/migrate.js +60 -0
  53. package/src/storage/userPlans/planStore.js +107 -0
  54. package/src/storage/userPlans/storeAdapter.js +77 -0
@@ -0,0 +1,106 @@
1
+ /* src/storage/userPlans/fileStore.js */
2
+
3
+ function getNodeModule(name) {
4
+ try {
5
+ if (typeof window !== "undefined" && typeof window.require === "function") {
6
+ return window.require(name);
7
+ }
8
+ } catch {}
9
+
10
+ try {
11
+ // eslint-disable-next-line global-require
12
+ return require(name);
13
+ } catch {
14
+ return null;
15
+ }
16
+ }
17
+
18
+ const fs = getNodeModule("fs");
19
+ const path = getNodeModule("path");
20
+
21
+ function isAvailable() {
22
+ return !!(fs && path);
23
+ }
24
+
25
+ function getPluginRoot() {
26
+ if (!isAvailable()) return null;
27
+ // current file: src/storage/userPlans/fileStore.js
28
+ return path.resolve(__dirname, "../../../");
29
+ }
30
+
31
+ function getStoreDir() {
32
+ const root = getPluginRoot();
33
+ if (!root) return null;
34
+ return path.join(root, "runtime_data", "userPlans");
35
+ }
36
+
37
+ function getStoreFilePath() {
38
+ const dir = getStoreDir();
39
+ if (!dir) return null;
40
+ return path.join(dir, "plans.v1.json");
41
+ }
42
+
43
+ function ensureStoreDir() {
44
+ if (!isAvailable()) return false;
45
+ const dir = getStoreDir();
46
+ if (!dir) return false;
47
+ try {
48
+ fs.mkdirSync(dir, { recursive: true });
49
+ return true;
50
+ } catch {
51
+ return false;
52
+ }
53
+ }
54
+
55
+ function exists() {
56
+ if (!isAvailable()) return false;
57
+ const fp = getStoreFilePath();
58
+ if (!fp) return false;
59
+ try {
60
+ return fs.existsSync(fp);
61
+ } catch {
62
+ return false;
63
+ }
64
+ }
65
+
66
+ function readRaw() {
67
+ if (!isAvailable()) return null;
68
+ const fp = getStoreFilePath();
69
+ if (!fp || !exists()) return null;
70
+ try {
71
+ const s = fs.readFileSync(fp, "utf8");
72
+ if (!s) return null;
73
+ return JSON.parse(s);
74
+ } catch {
75
+ return null;
76
+ }
77
+ }
78
+
79
+ function writeRaw(payload) {
80
+ if (!isAvailable()) return false;
81
+ if (!ensureStoreDir()) return false;
82
+
83
+ const fp = getStoreFilePath();
84
+ if (!fp) return false;
85
+ const tmp = `${fp}.tmp`;
86
+
87
+ try {
88
+ fs.writeFileSync(tmp, JSON.stringify(payload, null, 2), "utf8");
89
+ fs.renameSync(tmp, fp);
90
+ return true;
91
+ } catch {
92
+ try {
93
+ if (fs.existsSync(tmp)) fs.unlinkSync(tmp);
94
+ } catch {}
95
+ return false;
96
+ }
97
+ }
98
+
99
+ module.exports = {
100
+ isAvailable,
101
+ getStoreDir,
102
+ getStoreFilePath,
103
+ exists,
104
+ readRaw,
105
+ writeRaw,
106
+ };
@@ -0,0 +1,50 @@
1
+ /* src/storage/userPlans/localStorageStore.js */
2
+
3
+ const STORAGE_KEY = "kai_planner_user_plans_v1";
4
+
5
+ function canUseLocalStorage() {
6
+ try {
7
+ return typeof window !== "undefined" && window.localStorage != null;
8
+ } catch {
9
+ return false;
10
+ }
11
+ }
12
+
13
+ function readRaw() {
14
+ if (!canUseLocalStorage()) return null;
15
+ try {
16
+ const s = window.localStorage.getItem(STORAGE_KEY);
17
+ if (!s) return null;
18
+ return JSON.parse(s);
19
+ } catch {
20
+ return null;
21
+ }
22
+ }
23
+
24
+ function writeRaw(payload) {
25
+ if (!canUseLocalStorage()) return false;
26
+ try {
27
+ window.localStorage.setItem(STORAGE_KEY, JSON.stringify(payload));
28
+ return true;
29
+ } catch {
30
+ return false;
31
+ }
32
+ }
33
+
34
+ function clear() {
35
+ if (!canUseLocalStorage()) return false;
36
+ try {
37
+ window.localStorage.removeItem(STORAGE_KEY);
38
+ return true;
39
+ } catch {
40
+ return false;
41
+ }
42
+ }
43
+
44
+ module.exports = {
45
+ STORAGE_KEY,
46
+ canUseLocalStorage,
47
+ readRaw,
48
+ writeRaw,
49
+ clear,
50
+ };
@@ -0,0 +1,60 @@
1
+ /* src/storage/userPlans/migrate.js */
2
+
3
+ const CURRENT_VERSION = 1;
4
+
5
+ function asArray(x) {
6
+ return Array.isArray(x) ? x : [];
7
+ }
8
+
9
+ function normalizePlanV1(plan) {
10
+ if (!plan || typeof plan !== "object") return null;
11
+ const id = plan.id == null ? null : String(plan.id);
12
+ if (!id) return null;
13
+ const snapshot = plan.startSnapshot && typeof plan.startSnapshot === "object" ? plan.startSnapshot : null;
14
+
15
+ return {
16
+ id,
17
+ createdAt: plan.createdAt || new Date().toISOString(),
18
+ updatedAt: plan.updatedAt || new Date().toISOString(),
19
+ note: plan.note == null ? "" : String(plan.note),
20
+ startApiId: plan.startApiId == null ? "" : String(plan.startApiId),
21
+ targetEquipId: plan.targetEquipId == null ? "" : String(plan.targetEquipId),
22
+ targetLevel: plan.targetLevel == null ? "0" : String(plan.targetLevel),
23
+ priority: plan.priority == null ? "P0" : String(plan.priority),
24
+ startSnapshot: snapshot
25
+ ? {
26
+ equipId: snapshot.equipId == null ? "" : String(snapshot.equipId),
27
+ level: snapshot.level == null ? "0" : String(snapshot.level),
28
+ name: snapshot.name == null ? "" : String(snapshot.name),
29
+ }
30
+ : null,
31
+ snapshotSteps: asArray(plan.snapshotSteps),
32
+ lastComputedAt: plan.lastComputedAt || null,
33
+ lastResult: plan.lastResult || null,
34
+ };
35
+ }
36
+
37
+ function migrateStore(raw) {
38
+ const obj = raw && typeof raw === "object" ? raw : {};
39
+ const version = Number(obj.version) || 0;
40
+ let plans = [];
41
+
42
+ if (version <= 0) {
43
+ plans = asArray(obj.plans).map(normalizePlanV1).filter(Boolean);
44
+ return { version: CURRENT_VERSION, plans };
45
+ }
46
+
47
+ if (version === 1) {
48
+ plans = asArray(obj.plans).map(normalizePlanV1).filter(Boolean);
49
+ return { version: CURRENT_VERSION, plans };
50
+ }
51
+
52
+ // Forward-compat fallback: keep recognizable records.
53
+ plans = asArray(obj.plans).map(normalizePlanV1).filter(Boolean);
54
+ return { version: CURRENT_VERSION, plans };
55
+ }
56
+
57
+ module.exports = {
58
+ CURRENT_VERSION,
59
+ migrateStore,
60
+ };
@@ -0,0 +1,107 @@
1
+ /* src/storage/userPlans/planStore.js */
2
+
3
+ const { CURRENT_VERSION } = require("./migrate");
4
+ const { readStore, writeStore, getStorageInfo } = require("./storeAdapter");
5
+
6
+ function nowIso() {
7
+ return new Date().toISOString();
8
+ }
9
+
10
+ function loadPlans() {
11
+ return readStore().plans || [];
12
+ }
13
+
14
+ function savePlans(plans) {
15
+ writeStore({ version: CURRENT_VERSION, plans: Array.isArray(plans) ? plans : [] });
16
+ }
17
+
18
+ function makePlanId() {
19
+ return `plan_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
20
+ }
21
+
22
+ function createPlan({ startApiId, targetEquipId, targetLevel, priority, note, startSnapshot, snapshotSteps }) {
23
+ const store = readStore();
24
+ const plan = {
25
+ id: makePlanId(),
26
+ createdAt: nowIso(),
27
+ updatedAt: nowIso(),
28
+ note: note == null ? "" : String(note),
29
+ startApiId: startApiId == null ? "" : String(startApiId),
30
+ targetEquipId: targetEquipId == null ? "" : String(targetEquipId),
31
+ targetLevel: targetLevel == null ? "0" : String(targetLevel),
32
+ priority: priority == null ? "P0" : String(priority),
33
+ startSnapshot:
34
+ startSnapshot && typeof startSnapshot === "object"
35
+ ? {
36
+ equipId: startSnapshot.equipId == null ? "" : String(startSnapshot.equipId),
37
+ level: startSnapshot.level == null ? "0" : String(startSnapshot.level),
38
+ name: startSnapshot.name == null ? "" : String(startSnapshot.name),
39
+ }
40
+ : null,
41
+ snapshotSteps: Array.isArray(snapshotSteps) ? snapshotSteps : [],
42
+ lastComputedAt: null,
43
+ lastResult: null,
44
+ };
45
+ store.plans.unshift(plan);
46
+ writeStore(store);
47
+ return plan;
48
+ }
49
+
50
+ function updatePlan(planId, patch) {
51
+ const store = readStore();
52
+ const idx = store.plans.findIndex((p) => String(p.id) === String(planId));
53
+ if (idx < 0) return null;
54
+ store.plans[idx] = {
55
+ ...store.plans[idx],
56
+ ...patch,
57
+ updatedAt: nowIso(),
58
+ };
59
+ writeStore(store);
60
+ return store.plans[idx];
61
+ }
62
+
63
+ function deletePlan(planId) {
64
+ const store = readStore();
65
+ const before = store.plans.length;
66
+ store.plans = store.plans.filter((p) => String(p.id) !== String(planId));
67
+ writeStore(store);
68
+ return store.plans.length !== before;
69
+ }
70
+
71
+ function replacePlanStartApiId(planId, newApiId) {
72
+ return updatePlan(planId, { startApiId: String(newApiId || "") });
73
+ }
74
+
75
+ function updatePlanPriority(planId, priority) {
76
+ return updatePlan(planId, { priority: String(priority == null ? "P0" : priority) });
77
+ }
78
+
79
+ function updatePlanTargetLevel(planId, targetLevel, snapshotSteps) {
80
+ const patch = {
81
+ targetLevel: String(targetLevel == null ? "0" : targetLevel),
82
+ lastResult: null,
83
+ lastComputedAt: null,
84
+ };
85
+ if (Array.isArray(snapshotSteps)) patch.snapshotSteps = snapshotSteps;
86
+ return updatePlan(planId, patch);
87
+ }
88
+
89
+ function upsertLastResult(planId, result) {
90
+ return updatePlan(planId, {
91
+ lastResult: result || null,
92
+ lastComputedAt: nowIso(),
93
+ });
94
+ }
95
+
96
+ module.exports = {
97
+ loadPlans,
98
+ savePlans,
99
+ createPlan,
100
+ updatePlan,
101
+ deletePlan,
102
+ replacePlanStartApiId,
103
+ updatePlanPriority,
104
+ updatePlanTargetLevel,
105
+ upsertLastResult,
106
+ getStorageInfo,
107
+ };
@@ -0,0 +1,77 @@
1
+ /* src/storage/userPlans/storeAdapter.js */
2
+
3
+ const { CURRENT_VERSION, migrateStore } = require("./migrate");
4
+ const localStorageStore = require("./localStorageStore");
5
+ const fileStore = require("./fileStore");
6
+
7
+ function emptyStore() {
8
+ return { version: CURRENT_VERSION, plans: [] };
9
+ }
10
+
11
+ let initialized = false;
12
+
13
+ function readFromPreferredBackend() {
14
+ if (fileStore.isAvailable()) {
15
+ return fileStore.readRaw();
16
+ }
17
+ return localStorageStore.readRaw();
18
+ }
19
+
20
+ function writeToPreferredBackend(payload) {
21
+ if (fileStore.isAvailable()) {
22
+ return fileStore.writeRaw(payload);
23
+ }
24
+ return localStorageStore.writeRaw(payload);
25
+ }
26
+
27
+ function initMigrationIfNeeded() {
28
+ if (initialized) return;
29
+ initialized = true;
30
+
31
+ // one-time migration: localStorage -> fileStore
32
+ if (!fileStore.isAvailable()) return;
33
+ if (fileStore.exists()) return;
34
+
35
+ const oldRaw = localStorageStore.readRaw();
36
+ if (!oldRaw) return;
37
+
38
+ const migrated = migrateStore(oldRaw || emptyStore());
39
+ const ok = fileStore.writeRaw(migrated);
40
+ if (ok) {
41
+ localStorageStore.clear();
42
+ }
43
+ }
44
+
45
+ function readStore() {
46
+ initMigrationIfNeeded();
47
+ const raw = readFromPreferredBackend();
48
+ const migrated = migrateStore(raw || emptyStore());
49
+ writeToPreferredBackend(migrated);
50
+ return migrated;
51
+ }
52
+
53
+ function writeStore(store) {
54
+ initMigrationIfNeeded();
55
+ const payload = migrateStore(store || emptyStore());
56
+ writeToPreferredBackend(payload);
57
+ return payload;
58
+ }
59
+
60
+ function getStorageInfo() {
61
+ if (fileStore.isAvailable()) {
62
+ return {
63
+ backend: "file",
64
+ path: fileStore.getStoreFilePath(),
65
+ };
66
+ }
67
+ return {
68
+ backend: "localStorage",
69
+ key: localStorageStore.STORAGE_KEY,
70
+ };
71
+ }
72
+
73
+ module.exports = {
74
+ readStore,
75
+ writeStore,
76
+ getStorageInfo,
77
+ };