microboard-temp 0.5.75 → 0.5.77
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.
- package/dist/cjs/browser.js +116 -99
- package/dist/cjs/index.js +116 -99
- package/dist/cjs/node.js +116 -99
- package/dist/esm/browser.js +116 -99
- package/dist/esm/index.js +116 -99
- package/dist/esm/node.js +116 -99
- package/dist/types/Settings.d.ts +1 -0
- package/package.json +1 -1
package/dist/esm/browser.js
CHANGED
|
@@ -6909,7 +6909,8 @@ var conf = {
|
|
|
6909
6909
|
DECK_VERTICAL_OFFSET: 2,
|
|
6910
6910
|
CARD_DIMENSIONS: { width: 250, height: 400 },
|
|
6911
6911
|
DEFAULT_GAME_ITEM_DIMENSIONS: { width: 200, height: 200 },
|
|
6912
|
-
MAX_CARD_SIZE: 500
|
|
6912
|
+
MAX_CARD_SIZE: 500,
|
|
6913
|
+
CONNECTOR_ITEM_OFFSET: 20
|
|
6913
6914
|
};
|
|
6914
6915
|
initDefaultI18N();
|
|
6915
6916
|
|
|
@@ -36514,7 +36515,6 @@ function radiansBetweenPoints(point1, point22) {
|
|
|
36514
36515
|
}
|
|
36515
36516
|
|
|
36516
36517
|
// src/Items/Connector/getLine/findOrthogonalPath.ts
|
|
36517
|
-
var ITEM_OFFSET = 1;
|
|
36518
36518
|
function getDirection(from, to) {
|
|
36519
36519
|
if (!to) {
|
|
36520
36520
|
return null;
|
|
@@ -36555,9 +36555,9 @@ function getNeighbors(node2, grid, obstacles) {
|
|
|
36555
36555
|
{ x: node2.xGrid, y: node2.yGrid + 1 }
|
|
36556
36556
|
];
|
|
36557
36557
|
for (const pos of potentialNeighbors) {
|
|
36558
|
-
if (pos.x >= 0 && pos.x < grid.length && pos.y >= 0) {
|
|
36558
|
+
if (pos.x >= 0 && pos.x < grid.length && pos.y >= 0 && grid[pos.x] && grid[pos.x][pos.y]) {
|
|
36559
36559
|
const newPoint = grid[pos.x][pos.y];
|
|
36560
|
-
if (newPoint && !obstacles.some((obstacle) => obstacle.isAlmostInside(newPoint,
|
|
36560
|
+
if (newPoint && !obstacles.some((obstacle) => obstacle.isAlmostInside(newPoint, conf.CONNECTOR_ITEM_OFFSET - 1))) {
|
|
36561
36561
|
neighbors.push({
|
|
36562
36562
|
point: newPoint,
|
|
36563
36563
|
costSoFar: 0,
|
|
@@ -36585,16 +36585,20 @@ function findCenterLine(grid, start, end, middle) {
|
|
|
36585
36585
|
}
|
|
36586
36586
|
if (width > height) {
|
|
36587
36587
|
const centerIdx = grid.findIndex((row2) => row2[0].x === middlePoint.x || Math.abs(row2[0].x - middlePoint.x) < 0.01);
|
|
36588
|
-
|
|
36589
|
-
|
|
36590
|
-
|
|
36588
|
+
if (centerIdx !== -1) {
|
|
36589
|
+
for (let y = 0;y < grid[0].length; y++) {
|
|
36590
|
+
if (grid[centerIdx][y] && grid[centerIdx][y].x >= min2.x - 0.01 && grid[centerIdx][y].x <= max2.x + 0.01 && grid[centerIdx][y].y >= min2.y - 0.01 && grid[centerIdx][y].y <= max2.y + 0.01) {
|
|
36591
|
+
centerLine.push(grid[centerIdx][y]);
|
|
36592
|
+
}
|
|
36591
36593
|
}
|
|
36592
36594
|
}
|
|
36593
36595
|
} else {
|
|
36594
36596
|
const centerIdx = grid[0].findIndex((point5) => point5.y === middlePoint.y || Math.abs(point5.y - middlePoint.y) < 0.01);
|
|
36595
|
-
|
|
36596
|
-
|
|
36597
|
-
|
|
36597
|
+
if (centerIdx !== -1) {
|
|
36598
|
+
for (let x = 0;x < grid.length; x++) {
|
|
36599
|
+
if (grid[x][centerIdx] && grid[x][centerIdx].x >= min2.x - 0.01 && grid[x][centerIdx].x <= max2.x + 0.01 && grid[x][centerIdx].y >= min2.y - 0.01 && grid[x][centerIdx].y <= max2.y + 0.01) {
|
|
36600
|
+
centerLine.push(grid[x][centerIdx]);
|
|
36601
|
+
}
|
|
36598
36602
|
}
|
|
36599
36603
|
}
|
|
36600
36604
|
}
|
|
@@ -36605,69 +36609,24 @@ function createGrid(start, end, toVisitPoints = []) {
|
|
|
36605
36609
|
const endDir = getPointerDirection(end);
|
|
36606
36610
|
const revertMapDir = { top: 0, bottom: 1, right: 2, left: 3 };
|
|
36607
36611
|
const offsetMap = {
|
|
36608
|
-
top: { x: 0, y: -
|
|
36609
|
-
bottom: { x: 0, y:
|
|
36610
|
-
right: { x:
|
|
36611
|
-
left: { x: -
|
|
36612
|
+
top: { x: 0, y: -conf.CONNECTOR_ITEM_OFFSET },
|
|
36613
|
+
bottom: { x: 0, y: conf.CONNECTOR_ITEM_OFFSET },
|
|
36614
|
+
right: { x: conf.CONNECTOR_ITEM_OFFSET, y: 0 },
|
|
36615
|
+
left: { x: -conf.CONNECTOR_ITEM_OFFSET, y: 0 }
|
|
36612
36616
|
};
|
|
36613
36617
|
const horizontalLines = [];
|
|
36614
36618
|
const verticalLines = [];
|
|
36615
|
-
if (start.pointType !== "Board") {
|
|
36616
|
-
const itemMbr = start.item.getMbr();
|
|
36617
|
-
verticalLines.push(itemMbr.left - ITEM_OFFSET, itemMbr.left, itemMbr.right, itemMbr.right + ITEM_OFFSET);
|
|
36618
|
-
horizontalLines.push(itemMbr.top - ITEM_OFFSET, itemMbr.top, itemMbr.bottom, itemMbr.bottom + ITEM_OFFSET);
|
|
36619
|
-
}
|
|
36620
|
-
if (end.pointType !== "Board") {
|
|
36621
|
-
const itemMbr = end.item.getMbr();
|
|
36622
|
-
verticalLines.push(itemMbr.left - ITEM_OFFSET, itemMbr.left, itemMbr.right, itemMbr.right + ITEM_OFFSET);
|
|
36623
|
-
horizontalLines.push(itemMbr.top - ITEM_OFFSET, itemMbr.top, itemMbr.bottom, itemMbr.bottom + ITEM_OFFSET);
|
|
36624
|
-
}
|
|
36625
|
-
const tempStart = start;
|
|
36626
|
-
const tempEnd = end;
|
|
36627
|
-
const middle = new Point((tempStart.x + tempEnd.x) / 2, (tempStart.y + tempEnd.y) / 2);
|
|
36628
|
-
horizontalLines.push(middle.y, tempStart.y, tempEnd.y);
|
|
36629
|
-
verticalLines.push(middle.x, tempStart.x, tempEnd.x);
|
|
36630
|
-
toVisitPoints.forEach((p3) => {
|
|
36631
|
-
horizontalLines.push(p3.y);
|
|
36632
|
-
verticalLines.push(p3.x);
|
|
36633
|
-
});
|
|
36634
|
-
const uniqueHorizontalLines = Array.from(new Set(horizontalLines)).sort((a2, b) => a2 - b);
|
|
36635
|
-
const uniqueVerticalLines = Array.from(new Set(verticalLines)).sort((a2, b) => a2 - b);
|
|
36636
36619
|
let newStart;
|
|
36637
36620
|
let newEnd;
|
|
36638
36621
|
const processPoint = (point5, dir2) => {
|
|
36639
36622
|
const itemMbr = point5.item.getMbr();
|
|
36640
|
-
const
|
|
36623
|
+
const mbrFloored = new Mbr(Math.floor(itemMbr.left), Math.floor(itemMbr.top), Math.floor(itemMbr.right), Math.floor(itemMbr.bottom));
|
|
36624
|
+
const pointOnMbr = mbrFloored.getLines()[revertMapDir[dir2]].getNearestPointOnLineSegment(point5);
|
|
36641
36625
|
const newPoint = Object.create(Object.getPrototypeOf(point5), Object.getOwnPropertyDescriptors(point5));
|
|
36642
|
-
|
|
36643
|
-
|
|
36644
|
-
|
|
36645
|
-
|
|
36646
|
-
newPoint.y = uniqueHorizontalLines[nextYIndex];
|
|
36647
|
-
newPoint.x = pointOnMbr.x;
|
|
36648
|
-
}
|
|
36649
|
-
} else if (dir2 === "bottom") {
|
|
36650
|
-
const currentYIndex = uniqueHorizontalLines.findIndex((y) => Math.abs(y - pointOnMbr.y) < 0.01);
|
|
36651
|
-
const nextYIndex = currentYIndex + 1;
|
|
36652
|
-
if (nextYIndex < uniqueHorizontalLines.length) {
|
|
36653
|
-
newPoint.y = uniqueHorizontalLines[nextYIndex];
|
|
36654
|
-
newPoint.x = pointOnMbr.x;
|
|
36655
|
-
}
|
|
36656
|
-
} else if (dir2 === "left") {
|
|
36657
|
-
const currentXIndex = uniqueVerticalLines.findIndex((x) => Math.abs(x - pointOnMbr.x) < 0.01);
|
|
36658
|
-
const nextXIndex = currentXIndex - 1;
|
|
36659
|
-
if (nextXIndex >= 0) {
|
|
36660
|
-
newPoint.x = uniqueVerticalLines[nextXIndex];
|
|
36661
|
-
newPoint.y = pointOnMbr.y;
|
|
36662
|
-
}
|
|
36663
|
-
} else if (dir2 === "right") {
|
|
36664
|
-
const currentXIndex = uniqueVerticalLines.findIndex((x) => Math.abs(x - pointOnMbr.x) < 0.01);
|
|
36665
|
-
const nextXIndex = currentXIndex + 1;
|
|
36666
|
-
if (nextXIndex < uniqueVerticalLines.length) {
|
|
36667
|
-
newPoint.x = uniqueVerticalLines[nextXIndex];
|
|
36668
|
-
newPoint.y = pointOnMbr.y;
|
|
36669
|
-
}
|
|
36670
|
-
}
|
|
36626
|
+
newPoint.x = pointOnMbr.x + offsetMap[dir2].x;
|
|
36627
|
+
newPoint.y = pointOnMbr.y + offsetMap[dir2].y;
|
|
36628
|
+
verticalLines.push(mbrFloored.left - conf.CONNECTOR_ITEM_OFFSET, mbrFloored.left, pointOnMbr.x, mbrFloored.right, mbrFloored.right + conf.CONNECTOR_ITEM_OFFSET);
|
|
36629
|
+
horizontalLines.push(mbrFloored.top - conf.CONNECTOR_ITEM_OFFSET, mbrFloored.top, pointOnMbr.y, mbrFloored.bottom, mbrFloored.bottom + conf.CONNECTOR_ITEM_OFFSET);
|
|
36671
36630
|
return newPoint;
|
|
36672
36631
|
};
|
|
36673
36632
|
if (start.pointType !== "Board" && startDir) {
|
|
@@ -36676,6 +36635,17 @@ function createGrid(start, end, toVisitPoints = []) {
|
|
|
36676
36635
|
if (end.pointType !== "Board" && endDir) {
|
|
36677
36636
|
newEnd = processPoint(end, endDir);
|
|
36678
36637
|
}
|
|
36638
|
+
const finalStart = newStart || start;
|
|
36639
|
+
const finalEnd = newEnd || end;
|
|
36640
|
+
const middle = new Point((finalStart.x + finalEnd.x) / 2, (finalStart.y + finalEnd.y) / 2);
|
|
36641
|
+
horizontalLines.push(middle.y, finalStart.y, finalEnd.y);
|
|
36642
|
+
verticalLines.push(middle.x, finalStart.x, finalEnd.x);
|
|
36643
|
+
toVisitPoints.forEach((p3) => {
|
|
36644
|
+
horizontalLines.push(p3.y);
|
|
36645
|
+
verticalLines.push(p3.x);
|
|
36646
|
+
});
|
|
36647
|
+
const uniqueHorizontalLines = Array.from(new Set(horizontalLines)).sort((a2, b) => a2 - b);
|
|
36648
|
+
const uniqueVerticalLines = Array.from(new Set(verticalLines)).sort((a2, b) => a2 - b);
|
|
36679
36649
|
const grid = uniqueVerticalLines.map((x) => uniqueHorizontalLines.map((y) => new Point(x, y)));
|
|
36680
36650
|
return {
|
|
36681
36651
|
grid,
|
|
@@ -36684,18 +36654,27 @@ function createGrid(start, end, toVisitPoints = []) {
|
|
|
36684
36654
|
middlePoint: middle
|
|
36685
36655
|
};
|
|
36686
36656
|
}
|
|
36687
|
-
function findPath(start, end, grid, obstacles, newStart, newEnd) {
|
|
36688
|
-
const
|
|
36689
|
-
|
|
36690
|
-
|
|
36691
|
-
|
|
36657
|
+
function findPath(start, end, grid, obstacles, existingPath, newStart, newEnd) {
|
|
36658
|
+
const startRowIndex = grid.findIndex((row2) => row2.some((point5) => point5.barelyEqual(start)));
|
|
36659
|
+
if (startRowIndex === -1) {
|
|
36660
|
+
throw new Error("Start point not found in the grid row");
|
|
36661
|
+
}
|
|
36662
|
+
const startPointIndex = grid[startRowIndex].findIndex((point5) => point5.barelyEqual(start));
|
|
36663
|
+
if (startPointIndex === -1) {
|
|
36664
|
+
throw new Error("Start point not found in the grid column");
|
|
36665
|
+
}
|
|
36666
|
+
const endRowIndex = grid.findIndex((row2) => row2.some((point5) => point5.barelyEqual(end)));
|
|
36667
|
+
if (endRowIndex === -1) {
|
|
36668
|
+
throw new Error("End point not found in the grid row");
|
|
36669
|
+
}
|
|
36670
|
+
const endPointIndex = grid[endRowIndex].findIndex((point5) => point5.barelyEqual(end));
|
|
36671
|
+
if (endPointIndex === -1) {
|
|
36672
|
+
throw new Error("End point not found in the grid column");
|
|
36692
36673
|
}
|
|
36693
|
-
const startPointIdx = grid[startIdx].findIndex((point5) => point5.barelyEqual(start));
|
|
36694
|
-
const endPointIdx = grid[endIdx].findIndex((point5) => point5.barelyEqual(end));
|
|
36695
36674
|
const endNode = {
|
|
36696
36675
|
point: end,
|
|
36697
|
-
xGrid:
|
|
36698
|
-
yGrid:
|
|
36676
|
+
xGrid: endRowIndex,
|
|
36677
|
+
yGrid: endPointIndex,
|
|
36699
36678
|
costSoFar: 0,
|
|
36700
36679
|
heuristic: 0,
|
|
36701
36680
|
toFinish: 0
|
|
@@ -36703,53 +36682,72 @@ function findPath(start, end, grid, obstacles, newStart, newEnd) {
|
|
|
36703
36682
|
const startNode = {
|
|
36704
36683
|
point: start,
|
|
36705
36684
|
costSoFar: 0,
|
|
36706
|
-
heuristic: heuristic({ point: start, xGrid:
|
|
36707
|
-
toFinish: heuristic({ point: start, xGrid:
|
|
36708
|
-
xGrid:
|
|
36709
|
-
yGrid:
|
|
36685
|
+
heuristic: heuristic({ point: start, xGrid: startRowIndex, yGrid: startPointIndex }, endNode),
|
|
36686
|
+
toFinish: heuristic({ point: start, xGrid: startRowIndex, yGrid: startPointIndex }, endNode),
|
|
36687
|
+
xGrid: startRowIndex,
|
|
36688
|
+
yGrid: startPointIndex
|
|
36710
36689
|
};
|
|
36711
36690
|
const openSet = [startNode];
|
|
36712
36691
|
const closedSet = new Set;
|
|
36713
36692
|
while (openSet.length > 0) {
|
|
36714
36693
|
openSet.sort((aa, bb) => aa.toFinish - bb.toFinish);
|
|
36715
36694
|
const current = openSet.shift();
|
|
36695
|
+
const currentKey = `${current.point.x},${current.point.y}`;
|
|
36716
36696
|
if (current.point.barelyEqual(end)) {
|
|
36717
36697
|
const path2 = reconstructPath(current);
|
|
36718
36698
|
return path2;
|
|
36719
36699
|
}
|
|
36720
|
-
closedSet.add(
|
|
36700
|
+
closedSet.add(currentKey);
|
|
36721
36701
|
const neighbors = getNeighbors(current, grid, obstacles);
|
|
36722
36702
|
for (const neighbor of neighbors) {
|
|
36723
|
-
|
|
36703
|
+
const neighborKey = `${neighbor.point.x},${neighbor.point.y}`;
|
|
36704
|
+
if (closedSet.has(neighborKey) || existingPath.has(neighborKey) && !neighbor.point.barelyEqual(end)) {
|
|
36724
36705
|
continue;
|
|
36725
36706
|
}
|
|
36726
36707
|
const extraCost = isChangingDirection(current, neighbor, newStart, newEnd);
|
|
36727
|
-
const
|
|
36728
|
-
|
|
36729
|
-
|
|
36730
|
-
|
|
36731
|
-
|
|
36732
|
-
|
|
36708
|
+
const pathOverlapCost = existingPath.has(neighborKey) ? 1000 : 0;
|
|
36709
|
+
const tentativeCost = current.costSoFar + 1 + pathOverlapCost;
|
|
36710
|
+
let existingNodeInOpenSet = openSet.find((node2) => node2.point.barelyEqual(neighbor.point));
|
|
36711
|
+
if (!existingNodeInOpenSet || tentativeCost < existingNodeInOpenSet.costSoFar) {
|
|
36712
|
+
if (existingNodeInOpenSet) {
|
|
36713
|
+
existingNodeInOpenSet.costSoFar = tentativeCost + extraCost;
|
|
36714
|
+
existingNodeInOpenSet.heuristic = heuristic(neighbor, endNode);
|
|
36715
|
+
existingNodeInOpenSet.toFinish = existingNodeInOpenSet.costSoFar + existingNodeInOpenSet.heuristic;
|
|
36716
|
+
existingNodeInOpenSet.parent = current;
|
|
36717
|
+
} else {
|
|
36718
|
+
neighbor.costSoFar = tentativeCost + extraCost;
|
|
36719
|
+
neighbor.heuristic = heuristic(neighbor, endNode);
|
|
36720
|
+
neighbor.toFinish = neighbor.costSoFar + neighbor.heuristic;
|
|
36721
|
+
openSet.push(neighbor);
|
|
36722
|
+
}
|
|
36733
36723
|
}
|
|
36734
36724
|
}
|
|
36735
36725
|
}
|
|
36736
36726
|
return;
|
|
36737
36727
|
}
|
|
36738
36728
|
function findPathPoints(points, grid, obstacles, newStart, newEnd) {
|
|
36739
|
-
const
|
|
36729
|
+
const finalPath = [];
|
|
36730
|
+
const existingPathSegments = new Set;
|
|
36731
|
+
if (points.length > 0) {
|
|
36732
|
+
finalPath.push(points[0]);
|
|
36733
|
+
const startKey = `${points[0].x},${points[0].y}`;
|
|
36734
|
+
existingPathSegments.add(startKey);
|
|
36735
|
+
}
|
|
36740
36736
|
for (let i = 0;i < points.length - 1; i += 1) {
|
|
36741
|
-
const segmentPath = findPath(points[i], points[i + 1], grid, obstacles, newStart, newEnd);
|
|
36742
|
-
if (segmentPath) {
|
|
36743
|
-
|
|
36737
|
+
const segmentPath = findPath(points[i], points[i + 1], grid, obstacles, existingPathSegments, newStart, newEnd);
|
|
36738
|
+
if (segmentPath && segmentPath.length > 0) {
|
|
36739
|
+
for (let j = 1;j < segmentPath.length; j++) {
|
|
36740
|
+
const point5 = segmentPath[j];
|
|
36741
|
+
const key = `${point5.x},${point5.y}`;
|
|
36742
|
+
finalPath.push(point5);
|
|
36743
|
+
existingPathSegments.add(key);
|
|
36744
|
+
}
|
|
36744
36745
|
} else {
|
|
36745
36746
|
points.splice(i + 1, 1);
|
|
36746
36747
|
i--;
|
|
36747
36748
|
}
|
|
36748
36749
|
}
|
|
36749
|
-
|
|
36750
|
-
pathPoints.push(points[points.length - 1]);
|
|
36751
|
-
}
|
|
36752
|
-
return pathPoints;
|
|
36750
|
+
return finalPath;
|
|
36753
36751
|
}
|
|
36754
36752
|
function reducePoints(points) {
|
|
36755
36753
|
const uniquePoints = new Map;
|
|
@@ -36760,6 +36758,12 @@ function reducePoints(points) {
|
|
|
36760
36758
|
if (uniquePoints.has(key)) {
|
|
36761
36759
|
const loopStartIndex = uniquePoints.get(key);
|
|
36762
36760
|
result.splice(loopStartIndex + 1);
|
|
36761
|
+
const removedPoints = points.slice(loopStartIndex + 1, i + 1);
|
|
36762
|
+
removedPoints.forEach((p3) => {
|
|
36763
|
+
uniquePoints.delete(`${p3.x},${p3.y}`);
|
|
36764
|
+
});
|
|
36765
|
+
uniquePoints.set(key, result.length);
|
|
36766
|
+
result.push(point5);
|
|
36763
36767
|
} else {
|
|
36764
36768
|
uniquePoints.set(key, result.length);
|
|
36765
36769
|
result.push(point5);
|
|
@@ -36769,19 +36773,32 @@ function reducePoints(points) {
|
|
|
36769
36773
|
}
|
|
36770
36774
|
function getLines(pathPoints) {
|
|
36771
36775
|
const lines = [];
|
|
36776
|
+
if (pathPoints.length < 2) {
|
|
36777
|
+
return [];
|
|
36778
|
+
}
|
|
36772
36779
|
const reducedPoints = reducePoints(pathPoints);
|
|
36780
|
+
if (reducedPoints.length < 2) {
|
|
36781
|
+
return [];
|
|
36782
|
+
}
|
|
36773
36783
|
let startPoint = reducedPoints[0];
|
|
36774
|
-
for (let i = 1;i < reducedPoints.length
|
|
36784
|
+
for (let i = 1;i < reducedPoints.length; i += 1) {
|
|
36775
36785
|
const prevPoint = reducedPoints[i - 1];
|
|
36776
36786
|
const currPoint = reducedPoints[i];
|
|
36777
|
-
const nextPoint = reducedPoints[i + 1];
|
|
36778
|
-
if (prevPoint.x !== nextPoint.x && prevPoint.y !== nextPoint.y) {
|
|
36787
|
+
const nextPoint = i + 1 < reducedPoints.length ? reducedPoints[i + 1] : null;
|
|
36788
|
+
if (!nextPoint || prevPoint.x !== nextPoint.x && prevPoint.y !== nextPoint.y) {
|
|
36779
36789
|
lines.push(new Line(startPoint, currPoint));
|
|
36780
36790
|
startPoint = currPoint;
|
|
36781
36791
|
}
|
|
36782
36792
|
}
|
|
36783
|
-
if (lines.length >
|
|
36784
|
-
lines.push(new Line(
|
|
36793
|
+
if (lines.length === 0 && reducedPoints.length > 1) {
|
|
36794
|
+
lines.push(new Line(reducedPoints[0], reducedPoints[reducedPoints.length - 1]));
|
|
36795
|
+
} else if (lines.length > 0) {
|
|
36796
|
+
const lastLine = lines[lines.length - 1];
|
|
36797
|
+
const lastPointInLines = lastLine.getEndPoint();
|
|
36798
|
+
const lastPointInReduced = reducedPoints[reducedPoints.length - 1];
|
|
36799
|
+
if (!lastPointInLines.barelyEqual(lastPointInReduced)) {
|
|
36800
|
+
lines.push(new Line(lastPointInLines, lastPointInReduced));
|
|
36801
|
+
}
|
|
36785
36802
|
}
|
|
36786
36803
|
return lines;
|
|
36787
36804
|
}
|