Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
## 2026-03-31 - [Optimized Iteration over large collections]
**Learning:** Found an opportunity to replace chained array methods like flatMap, map, reduce, and Object.values/keys with single-pass manual 'for' and 'for...in' loops when processing arrays and objects to avoid allocating large temporary data structures. Used ES6 Maps/Sets where efficient counting/deduplication was needed.
**Action:** Apply this pattern to other performance sensitive areas where objects and arrays map over large datasets, and ensure that iteration checks 'Object.prototype.hasOwnProperty.call()' when utilizing 'for...in'. Note: This project lacks a package.json at the root so standard npm/pnpm lint tools might not be readily available.
## 2026-04-14 - [Selective Object Iteration Optimization]
**Learning:** When iterating over large data structures like `railwayData` to find specific items, prioritize loops that support early exits (e.g., `for...in` with `break`) over `Object.values().forEach()` to prevent unnecessary iterations once the target is found. Avoid globally replacing `Object` methods with `for...in` just to save temporary allocations, as this is an unmeasurable micro-optimization in React UI components.
**Action:** Use early break patterns when searching large data sets. Ensure optimizations solve actual bottlenecks, and add clear explanatory comments for these performance improvements.

## 2024-04-15 - [Avoid O(N log N) Sorting on Massive Geographical Collections]
**Learning:** In spatial queries like `findNearbyStations` where we scan `railwayData` containing thousands of stations to find the top K nearest points, allocating all elements to an array and running `Array.prototype.sort()` results in massive temporary object allocation and $O(N \log N)$ execution time (taking ~8.5ms in benchmarks).
Expand Down
58 changes: 46 additions & 12 deletions src/components/modals/WalkTripEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,24 @@ export const WalkTripEditor: React.FC = () => {
// Find coordinates for the Bezier curve
let startCoords = null;
let endCoords = null;
Object.values(railwayData).forEach(line => {
const s = line.stations.find(st => st.id === form.fromId);
if (s) startCoords = [s.lng, s.lat];
const e = line.stations.find(st => st.id === form.toId);
if (e) endCoords = [e.lng, e.lat];
});
// ⚡ Bolt Optimization: Use for...in with early break to avoid iterating over all lines
// once both start and end coordinates are found, and avoid creating temporary Object.values arrays.
for (const lineKey in railwayData) {
if (!Object.prototype.hasOwnProperty.call(railwayData, lineKey)) continue;
const line = railwayData[lineKey];

if (!startCoords) {
const s = line.stations.find(st => st.id === form.fromId);
if (s) startCoords = [s.lng, s.lat];
}

if (!endCoords) {
const e = line.stations.find(st => st.id === form.toId);
if (e) endCoords = [e.lng, e.lat];
}

if (startCoords && endCoords) break;
}

if (startCoords && endCoords) {
walkPath = generateBezierPath(startCoords as [number, number], endCoords as [number, number]);
Expand Down Expand Up @@ -130,12 +142,34 @@ export const WalkTripEditor: React.FC = () => {
// Resolving station names for read-only display
let startName = t('walk.unknownStart', "未知起点");
let endName = t('walk.unknownEnd', "未知终点");
Object.values(railwayData).forEach(line => {
const s = line.stations.find(st => st.id === form.fromId);
if (s) startName = s.name_ja;
const e = line.stations.find(st => st.id === form.toId);
if (e) endName = e.name_ja;
});

let startFound = false;
let endFound = false;

// ⚡ Bolt Optimization: Use for...in with early break to avoid iterating over all lines
// once both start and end station names are resolved, and avoid creating temporary Object.values arrays.
for (const lineKey in railwayData) {
if (!Object.prototype.hasOwnProperty.call(railwayData, lineKey)) continue;
const line = railwayData[lineKey];

if (!startFound) {
const s = line.stations.find(st => st.id === form.fromId);
if (s) {
startName = s.name_ja;
startFound = true;
}
}

if (!endFound) {
const e = line.stations.find(st => st.id === form.toId);
if (e) {
endName = e.name_ja;
endFound = true;
}
}

if (startFound && endFound) break;
}

const isTree = form.walkType === 'tree';

Expand Down