Skip to content

Commit

Permalink
Merge pull request #52 from TNO/comparison-improvement
Browse files Browse the repository at this point in the history
Comparison improvement
  • Loading branch information
lunalixxi authored Sep 27, 2023
2 parents 6eec10e + 789ecd5 commit 2af5f14
Show file tree
Hide file tree
Showing 11 changed files with 74 additions and 49 deletions.
10 changes: 10 additions & 0 deletions docs/developer-documentation/types/LogEntryCharMaps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Name

```TS
interface LogEntryCharMaps {
firstCharIndexMap;
lastCharIndexMap;
}
```

This type is used to represent an object containing two JavaScript [`Map`(s)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map). These maps store the first and last char indices of each log entry. These indices are used for the Segment Annotation and Structure Matching features and Search (with Regular Expressions).
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"@mui/material": "^5.14.0",
"framer-motion": "^10.15.1",
"lodash": "^4.17.21",
"react-fast-compare": "^3.2.2",
"react-resize-detector": "^8.0.4"
}
}
31 changes: 17 additions & 14 deletions src/viewer/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import LogFile from "./LogFile";
import LogView from "./log/LogView";
import MinimapView from "./minimap/MinimapView";
import Tooltip from "@mui/material/Tooltip";
import { LogViewState, StructureMatchId, RowProperty, Segment } from "./types";
import { LogViewState, StructureMatchId, RowProperty, Segment, LogEntryCharMaps } from "./types";
import {
LOG_HEADER_HEIGHT,
MINIMAP_COLUMN_WIDTH,
Expand All @@ -18,7 +18,7 @@ import {
VSCodeOption,
} from "@vscode/webview-ui-toolkit/react";
import {
useJsonObjectToTextRangesMap,
useGetCharIndicesForLogEntries,
useStructureRegularExpressionSearch,
} from "./hooks/useStructureRegularExpressionManager";
import { getRegularExpressionMatches, returnSearchIndices } from "./hooks/useLogSearchManager";
Expand All @@ -30,7 +30,7 @@ import Rule from "./rules/Rule";
import MinimapHeader from "./minimap/MinimapHeader";
import SelectColDialog from "./log/SelectColDialog";

interface Props {}
interface Props { }
interface State {
logFile: LogFile;
logViewState: LogViewState | undefined;
Expand All @@ -49,7 +49,7 @@ interface State {

// Structure related
logFileAsString: string;
logEntryRanges: number[][];
logEntryCharIndexMaps: LogEntryCharMaps;
selectedLogRows: string[][];
// selectedRowsTypes: RowType[];
rowProperties: RowProperty[];
Expand Down Expand Up @@ -105,7 +105,7 @@ export default class App extends React.Component<Props, State> {
caseSearch: false,
selectedLogRows: [],
rowProperties: [],
logEntryRanges: [],
logEntryCharIndexMaps: { firstCharIndexMap: null, lastCharIndexMap: null },
showStructureDialog: false,
structureMatches: [],
structureMatchesLogRows: [],
Expand All @@ -118,6 +118,9 @@ export default class App extends React.Component<Props, State> {

this.onMessage = this.onMessage.bind(this);
window.addEventListener("message", this.onMessage);
document.addEventListener("contextmenu", (event) => {
event.preventDefault();
});
this.vscode.postMessage({ type: "readFile" });
}

Expand All @@ -133,15 +136,15 @@ export default class App extends React.Component<Props, State> {
const rules = message.rules.map((r) => Rule.fromJSON(r)).filter((r) => r);
const lines = JSON.parse(message.text);
const logFileText = JSON.stringify(lines, null, 2);
const textRanges = useJsonObjectToTextRangesMap(logFileText);
const logEntryCharIndexMaps = useGetCharIndicesForLogEntries(logFileText);
const logFile = LogFile.create(lines, rules);
const newRowsProps = logFile.rows.map(() =>
constructNewRowProperty(true, true, SelectedRowType.None),
);
this.setState({
logFile,
logFileAsString: logFileText,
logEntryRanges: textRanges,
logEntryCharIndexMaps: logEntryCharIndexMaps,
rules,
rowProperties: newRowsProps,
});
Expand Down Expand Up @@ -181,11 +184,11 @@ export default class App extends React.Component<Props, State> {
return constructNewRowProperty(true, true, SelectedRowType.None);
else return constructNewRowProperty(false, false, SelectedRowType.None);
});
const textRanges = useJsonObjectToTextRangesMap(logFileText);
const logEntryCharIndexMaps = useGetCharIndicesForLogEntries(logFileText);
this.setState({
logFile,
logFileAsString: logFileText,
logEntryRanges: textRanges,
logEntryCharIndexMaps: logEntryCharIndexMaps,
rules,
rowProperties: newRowsProps,
});
Expand Down Expand Up @@ -319,13 +322,13 @@ export default class App extends React.Component<Props, State> {

handleStructureMatching(expression: string) {
const rowProperties = this.clearSelectedRowsTypes();
const { logFileAsString, logEntryRanges } = this.state;
const { logFileAsString, logEntryCharIndexMaps } = this.state;
let { currentStructureMatch, currentStructureMatchIndex } = this.state;

const structureMatches = useStructureRegularExpressionSearch(
expression,
logFileAsString,
logEntryRanges,
logEntryCharIndexMaps,
);
let structureMatchesLogRows: number[] = [];

Expand Down Expand Up @@ -378,18 +381,18 @@ export default class App extends React.Component<Props, State> {
}

handleSegmentation(entryExpression: string, exitExpression: string) {
const { logFileAsString, logEntryRanges } = this.state;
const { logFileAsString, logEntryCharIndexMaps } = this.state;
const { collapsibleRows } = this.state;

const entryMatches = getRegularExpressionMatches(
entryExpression,
logFileAsString,
logEntryRanges,
logEntryCharIndexMaps,
);
const exitMatches = getRegularExpressionMatches(
exitExpression,
logFileAsString,
logEntryRanges,
logEntryCharIndexMaps,
);

const stack: number[] = [];
Expand Down
3 changes: 2 additions & 1 deletion src/viewer/contextMenu/contextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,13 @@ export default class ContextMenu extends React.PureComponent<Props, State> {

handleContextMenu = (e) => {
e.preventDefault();
const path = e.composedPath();

this.setState({
xPos: e.pageX,
yPos: e.pageY,
showMenu: true,
anchorDivId: e.path[0].id,
anchorDivId: path[0].id,
});
};

Expand Down
19 changes: 8 additions & 11 deletions src/viewer/hooks/useLogSearchManager.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { LogEntryCharRanges } from "../types";

export const escapeSpecialChars = (text: string): string => {
let safeText = "";

Expand Down Expand Up @@ -135,29 +137,24 @@ export const returnSearchIndices = (
export const getRegularExpressionMatches = (
expression: string,
logFileAsString: string,
logEntryRanges: number[][],
logEntryCharRanges: LogEntryCharRanges,
): number[] => {
const searchIndices: number[] = [];
const resultingMatches: number[] = [];
const flags = "gs";
const query = new RegExp(expression, flags);
let result;
let currentIndex = 0;

while ((result = query.exec(logFileAsString)) !== null) {
searchIndices.push(result.index);
}

if (searchIndices.length > 0) {
for (let i = 0; i < logEntryRanges.length; i++) {
if (searchIndices[currentIndex] >= logEntryRanges[i][0]) {
if (searchIndices[currentIndex] <= logEntryRanges[i][1]) {
currentIndex += 1;
if (i != resultingMatches[-1]) resultingMatches.push(i);
if (currentIndex === searchIndices.length) break;
}
}
}
searchIndices.forEach((searchIndex) => {
const indexOfMatchedEntry = logEntryCharRanges.firstCharIndexMap.get(searchIndex);
resultingMatches.push(indexOfMatchedEntry);
});
}

return resultingMatches;
};
42 changes: 22 additions & 20 deletions src/viewer/hooks/useStructureRegularExpressionManager.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CellContents, Header, StructureEntry, Wildcard } from "../types";
import { CellContents, Header, LogEntryCharMaps, StructureEntry, Wildcard } from "../types";
import { StructureHeaderColumnType, StructureLinkDistance } from "../constants";
import { isSubstitutionFirstForWildcard } from "./useWildcardManager";

Expand Down Expand Up @@ -182,29 +182,33 @@ export const useStructureQueryConstructor = (
return regularExp;
};

export const useJsonObjectToTextRangesMap = (logFileAsString: string): number[][] => {
export const useGetCharIndicesForLogEntries = (logFileAsString: string): LogEntryCharMaps => {
const perfStart = performance.now();
const textRanges: number[][] = [];
const jsonObjectsRegExp = new RegExp(regExpjsonObject, flags);
const firstCharIndexMap = new Map();
const lastCharIndexMap = new Map();
let logEntryIndex = 0;

let result = jsonObjectsRegExp.exec(logFileAsString);

if (result !== null) {
do {
textRanges.push([result.index, jsonObjectsRegExp.lastIndex]);
firstCharIndexMap.set(result.index, logEntryIndex);
lastCharIndexMap.set(jsonObjectsRegExp.lastIndex, logEntryIndex);
logEntryIndex++;
} while ((result = jsonObjectsRegExp.exec(logFileAsString)) !== null);
}

const perfEnd = performance.now();
console.log(`Execution time (mapLogFileTextIndicesToObject()): ${perfEnd - perfStart} ms`);

return textRanges;
return { firstCharIndexMap: firstCharIndexMap, lastCharIndexMap: lastCharIndexMap };
};

export const useStructureRegularExpressionSearch = (
expression: string,
logFileAsString: string,
logEntryRanges: number[][],
logEntryCharIndexMaps: LogEntryCharMaps,
): number[][] => {
console.log("Starting Structure Matching");
const perfStart = performance.now();
Expand All @@ -213,35 +217,33 @@ export const useStructureRegularExpressionSearch = (
const structureQuery = new RegExp(expression, flags);
let result;


while ((result = structureQuery.exec(logFileAsString)) !== null) {
textRanges.push([result.index, structureQuery.lastIndex]);
}

const perfEnd = performance.now();
console.log(`Execution time (useStructureRegularExpressionSearch()): ${perfEnd - perfStart} ms`);
console.log(`Execution time (regular expression run): ${perfEnd - perfStart} ms`);

const transStart = performance.now();

textRanges.forEach((matchRanges) => {
const indexesOfEntriesInMatch: number[] = [];
let startingIndexOfMatch = 0;
let endingIndexOfMatch = -1;

for (let i = 0; i < logEntryRanges.length; i++) {
if (matchRanges[0] === logEntryRanges[i][0]) {
startingIndexOfMatch = i;
}
const indexOfFirstObjectInMatch = logEntryCharIndexMaps.firstCharIndexMap.get(matchRanges[0]);
const indexOfLastObjectInMatch = logEntryCharIndexMaps.lastCharIndexMap.get(matchRanges[1]);

if (matchRanges[1] === logEntryRanges[i][1]) {
endingIndexOfMatch = i;
break;
if(indexOfFirstObjectInMatch && indexOfLastObjectInMatch) {
for (let i = indexOfFirstObjectInMatch; i <= indexOfLastObjectInMatch; i++) {
indexesOfEntriesInMatch.push(i);
}
}

for (let o = startingIndexOfMatch; o <= endingIndexOfMatch; o++) {
indexesOfEntriesInMatch.push(o);
}

resultingMatches.push(indexesOfEntriesInMatch);
});

const transEnd = performance.now();
console.log(`Execution time (translation from char indices to logFile.rows indices): ${transEnd - transStart} ms`);

return resultingMatches;
};
2 changes: 1 addition & 1 deletion src/viewer/hooks/useStyleManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const getLogViewRowStyle = (rowIndex: number, leftPadding: number): React.CSSPro
height: LOG_ROW_HEIGHT,
overflow: "hidden",
top: rowIndex * LOG_ROW_HEIGHT,
userSelect: "none",
userSelect: "text",
borderRadius: "5px",
};

Expand Down
2 changes: 1 addition & 1 deletion src/viewer/structures/StructureDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
removeWildcardFromCellContent,
} from "../hooks/useWildcardManager";
import { structureDialogBackdropStyle, structureDialogDialogStyle } from "../hooks/useStyleManager";
import isEqual from "lodash/isEqual";
import isEqual from "react-fast-compare";
import cloneDeep from "lodash/cloneDeep";
import ContextMenu from "../contextMenu/contextMenu";
import { styled } from "@mui/material/styles";
Expand Down
2 changes: 1 addition & 1 deletion src/viewer/structures/StructureTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
getStructureTableLinkStyle,
} from "../hooks/useStyleManager";
import { getReactElementsFromCellContents } from "../hooks/useWildcardManager";
import isEqual from "lodash/isEqual";
import isEqual from "react-fast-compare";

interface Props {
headerColumns: Header[];
Expand Down
5 changes: 5 additions & 0 deletions src/viewer/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,8 @@ export interface Segment {
end: number;
level: number;
}

export interface LogEntryCharMaps {
firstCharIndexMap: Map<number, number>;
lastCharIndexMap: Map<number, number>;
}

0 comments on commit 2af5f14

Please sign in to comment.