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
9 changes: 7 additions & 2 deletions src/components/modals/GlobalSearchModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@ export const GlobalSearchModal: React.FC<Props> = ({ isOpen, onClose, onSelect }
const matchedLines: any[] = [];
const matchedStations: any[] = [];

Object.entries(railwayData).forEach(([lineKey, lineData]) => {
// ⚡ Bolt Optimization: Prevent creating a large array via Object.entries()
// on every keystroke by using a manual single-pass for...in loop.
for (const lineKey in railwayData) {
if (!Object.prototype.hasOwnProperty.call(railwayData, lineKey)) continue;
const lineData = railwayData[lineKey];

const displayName = lineKey.includes(':') ? lineKey.split(':').slice(1).join(':') : lineKey;

// Check line match
Expand Down Expand Up @@ -64,7 +69,7 @@ export const GlobalSearchModal: React.FC<Props> = ({ isOpen, onClose, onSelect }
});
}
});
});
}

// (the code up there already populated `matchedLines` and `matchedStations` so no need to do performSearch here)
return {
Expand Down
66 changes: 54 additions & 12 deletions src/components/modals/WalkTripEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,33 @@ 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];
});
let foundStart = false;
let foundEnd = false;

// ⚡ Bolt Optimization: Replace Object.values().forEach with a single-pass
// for...in loop and early break to prevent large temporary array allocations
for (const lineKey in railwayData) {
if (!Object.prototype.hasOwnProperty.call(railwayData, lineKey)) continue;
const line = railwayData[lineKey];

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

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

if (foundStart && foundEnd) break;
}

if (startCoords && endCoords) {
walkPath = generateBezierPath(startCoords as [number, number], endCoords as [number, number]);
Expand Down Expand Up @@ -127,12 +148,33 @@ export const WalkTripEditor: React.FC = () => {
// Resolving station names for read-only display
let startName = "未知起点";
let endName = "未知终点";
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 foundStartName = false;
let foundEndName = false;

// ⚡ Bolt Optimization: Replace Object.values().forEach with a single-pass
// for...in loop and early break to prevent large temporary array allocations
for (const lineKey in railwayData) {
if (!Object.prototype.hasOwnProperty.call(railwayData, lineKey)) continue;
const line = railwayData[lineKey];

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

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

if (foundStartName && foundEndName) break;
}

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

Expand Down
26 changes: 18 additions & 8 deletions src/pages/TripsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,21 @@ export const TripsPage: React.FC = () => {
folders: state.folders,
badgeSettings: state.badgeSettings
})));

// ⚡ Bolt Optimization: Build a single O(N) map of station IDs to names
// instead of repeatedly looping through all railway lines for every walk trip.
// This reduces the complexity from O(Trips * Lines * Stations) to O(1) per lookup.
const stationNameMap = useMemo(() => {
const map = new Map<string, string>();
for (const lineKey in railwayData) {
if (Object.prototype.hasOwnProperty.call(railwayData, lineKey)) {
railwayData[lineKey].stations.forEach(st => {
map.set(st.id, st.name_ja);
});
}
}
return map;
}, [railwayData]);
const setModalState = useStore(state => state.setModalState);
const startEditingTrip = useStore(state => state.startEditingTrip);
const removeTrip = useStore(state => state.removeTrip);
Expand Down Expand Up @@ -157,14 +172,9 @@ export const TripsPage: React.FC = () => {
const isWalk = t.isWalk;

if (isWalk) {
let startName = t.fromId || '';
let endName = t.toId || '';
Object.values(railwayData).forEach(line => {
const s = line.stations.find(st => st.id === t.fromId);
if (s) startName = s.name_ja;
const e = line.stations.find(st => st.id === t.toId);
if (e) endName = e.name_ja;
});
// ⚡ Bolt Optimization: O(1) hash map lookup replacing nested loops
const startName = stationNameMap.get(t.fromId) || t.fromId || '';
const endName = stationNameMap.get(t.toId) || t.toId || '';

const isTree = t.walkType === 'tree';
const cls = {
Expand Down