Skip to content

Commit

Permalink
Merge pull request #3274 from wowsims/apl
Browse files Browse the repository at this point in the history
Implement path flattening in json exports to make them more readable
  • Loading branch information
jimmyt857 authored Jul 9, 2023
2 parents 4bcc966 + 7034d60 commit a6c6365
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 2 deletions.
18 changes: 16 additions & 2 deletions ui/core/components/exporters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { IndividualSimSettings } from '../proto/ui';
import { classNames, raceNames } from '../proto_utils/names';
import { UnitStat } from '../proto_utils/stats';
import { specNames } from '../proto_utils/utils';
import { downloadString } from '../utils';
import { downloadString, jsonStringifyWithFlattenedPaths } from '../utils';
import { BaseModal } from './base_modal';
import { IndividualWowheadGearPlannerImporter } from './importers';
import { RaidSimRequest } from '../proto/api';
Expand Down Expand Up @@ -97,7 +97,21 @@ export class IndividualJsonExporter<SpecType extends Spec> extends Exporter {
}

getData(): string {
return JSON.stringify(IndividualSimSettings.toJson(this.simUI.toProto()), null, 2);
return jsonStringifyWithFlattenedPaths(IndividualSimSettings.toJson(this.simUI.toProto()), 2, (value, path) => {
if (['stats', 'pseudoStats'].includes(path[path.length - 1])) {
return true;
}

if (['player', 'equipment', 'items'].every((v, i) => path[i] == v)) {
return path.length > 3;
}

if (path[0] == 'player' && path[1] == 'rotation' && ['prepullActions', 'priorityList'].includes(path[2])) {
return path[path.length - 2] == 'action';
}

return false;
});
}
}

Expand Down
35 changes: 35 additions & 0 deletions ui/core/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,4 +233,39 @@ export function randomString(len?: number): string {
str += randomStringChars[Math.floor(Math.random() * randomStringChars.length)];
}
return str;
}

// Allows replacement of stringified objects based on the key and path.
// If handler returns a string, that string is used. Otherwise, the normal JSON.stringify result is returned.
export function jsonStringifyCustom(value: any, indent: number, handler: (value: any, path: Array<string>) => string|undefined|void): string {
const indentStr = ' '.repeat(indent);
return jsonStringifyCustomHelper(value, indentStr, [], handler);
}
function jsonStringifyCustomHelper(value: any, indentStr: string, path: Array<string>, handler: (value: any, path: Array<string>) => string|undefined|void): string {
const handlerResult = handler(value, path);
if (handlerResult != null) {
return handlerResult;
}

if (!(value instanceof Object)) {
return JSON.stringify(value);
} else if (value instanceof Array) {
let str = '[\n';
const lines = value.map((e, i) => `${indentStr.repeat(path.length+1)}${jsonStringifyCustomHelper(e, indentStr, path.slice().concat([i + '']), handler)}${i == value.length - 1 ? '' : ','}\n`);
str += lines.join('');
str += indentStr.repeat(path.length) + ']';
return str;
} else { // Object
let str = '{\n';
const len = Object.keys(value).length;
const lines = Object.entries(value).map(([fieldKey, fieldValue], i) => `${indentStr.repeat(path.length+1)}"${fieldKey}": ${jsonStringifyCustomHelper(fieldValue, indentStr, path.slice().concat([fieldKey]), handler)}${i == len - 1 ? '' : ','}\n`);
str += lines.join('');
str += indentStr.repeat(path.length) + '}';
return str;
}
}

// Pretty-prints the value in JSON form, but does not prettify (flattens) sub-values where handler returns true.
export function jsonStringifyWithFlattenedPaths(value: any, indent: number, handler: (value: any, path: Array<string>) => boolean): string {
return jsonStringifyCustom(value, indent, (value, path) => handler(value, path) ? JSON.stringify(value) : undefined);
}

0 comments on commit a6c6365

Please sign in to comment.