From d95cdd1c9bc34ea3917fd73bb04812eaedf986cb Mon Sep 17 00:00:00 2001 From: lee00678 Date: Wed, 24 Jul 2024 12:51:11 -0700 Subject: [PATCH] Core | Test: Add random seed generator --- package-lock.json | 13 +++++ package.json | 3 ++ .../area/baseline-area/index.tsx | 4 +- .../xy-components/area/basic-area/index.tsx | 4 +- .../src/examples/xy-components/area/index.tsx | 6 +-- .../axis/axis-rotation/index.tsx | 8 +-- .../xy-components/brush/basic-brush/index.tsx | 4 +- .../stacked-vs-non-stacked/index.tsx | 4 +- packages/dev/src/utils/data.ts | 49 +++++++------------ 9 files changed, 48 insertions(+), 47 deletions(-) diff --git a/package-lock.json b/package-lock.json index 969ee529a..7277c1066 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,9 @@ "packages/vue", "packages/shared" ], + "dependencies": { + "seedrandom": "^3.0.5" + }, "devDependencies": { "@commitlint/cli": "^19.3.0", "@commitlint/config-conventional": "^19.2.2", @@ -21653,6 +21656,11 @@ "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", "dev": true }, + "node_modules/seedrandom": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" + }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -42082,6 +42090,11 @@ "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", "dev": true }, + "seedrandom": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" + }, "select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", diff --git a/package.json b/package.json index bc298218e..7d91ce548 100644 --- a/package.json +++ b/package.json @@ -67,5 +67,8 @@ }, "lint-staged": { "*.{js,ts,jsx,tsx,svelte}": "eslint --quiet --cache --fix" + }, + "dependencies": { + "seedrandom": "^3.0.5" } } diff --git a/packages/dev/src/examples/xy-components/area/baseline-area/index.tsx b/packages/dev/src/examples/xy-components/area/baseline-area/index.tsx index bf0f7c003..015c90cf9 100644 --- a/packages/dev/src/examples/xy-components/area/baseline-area/index.tsx +++ b/packages/dev/src/examples/xy-components/area/baseline-area/index.tsx @@ -1,13 +1,13 @@ import React from 'react' import { VisXYContainer, VisArea, VisAxis, VisCrosshair } from '@unovis/react' -import { XYDataRecord, generateXYDataRecords, generateXYTestDataRecords } from '@src/utils/data' +import { XYDataRecord, generateXYDataRecords } from '@src/utils/data' export const title = 'Area Chart with Baseline' export const subTitle = 'Generated Data' export const component = (): JSX.Element => { - const data = generateXYTestDataRecords(20) + const data = generateXYDataRecords(20) const accessors = [ (d: XYDataRecord) => d.y, (d: XYDataRecord) => d.y1, diff --git a/packages/dev/src/examples/xy-components/area/basic-area/index.tsx b/packages/dev/src/examples/xy-components/area/basic-area/index.tsx index b8e75a04f..095a2d282 100644 --- a/packages/dev/src/examples/xy-components/area/basic-area/index.tsx +++ b/packages/dev/src/examples/xy-components/area/basic-area/index.tsx @@ -1,7 +1,7 @@ import React, { useRef } from 'react' import { VisXYContainer, VisArea, VisAxis, VisTooltip, VisCrosshair } from '@unovis/react' -import { XYDataRecord, generateXYDataRecords, generateXYTestDataRecords } from '@src/utils/data' +import { XYDataRecord, generateXYDataRecords } from '@src/utils/data' export const title = 'Basic Area Chart' export const subTitle = 'Generated Data' @@ -14,7 +14,7 @@ export const component = (): JSX.Element => { ] return ( - data={generateXYTestDataRecords(15)} margin={{ top: 5, left: 5 }}> + data={generateXYDataRecords(15)} margin={{ top: 5, left: 5 }}> d.x} y={accessors} /> `${x}ms`}/> `${y}bps`}/> diff --git a/packages/dev/src/examples/xy-components/area/index.tsx b/packages/dev/src/examples/xy-components/area/index.tsx index eb49e6758..1718d202d 100644 --- a/packages/dev/src/examples/xy-components/area/index.tsx +++ b/packages/dev/src/examples/xy-components/area/index.tsx @@ -1,14 +1,14 @@ import React from 'react' import { VisXYContainer, VisArea } from '@unovis/react' import { TransitionComponentProps } from '@src/components/TransitionComponent' -import { generateXYDataRecords, XYDataRecord, generateXYTestDataRecords } from '@src/utils/data' +import { generateXYDataRecords, XYDataRecord } from '@src/utils/data' export const transitionComponent: TransitionComponentProps = { - data: generateXYTestDataRecords, + data: generateXYDataRecords, dataSeries: { noData: () => [], singleDataElement: d => [d[0]], - fewElements: () => generateXYTestDataRecords(3), + fewElements: () => generateXYDataRecords(3), singleLayer: d => d.map(d => ({ x: d.x, y: d.y })), }, component: (props) => ( diff --git a/packages/dev/src/examples/xy-components/axis/axis-rotation/index.tsx b/packages/dev/src/examples/xy-components/axis/axis-rotation/index.tsx index baca507e3..be340cd19 100644 --- a/packages/dev/src/examples/xy-components/axis/axis-rotation/index.tsx +++ b/packages/dev/src/examples/xy-components/axis/axis-rotation/index.tsx @@ -1,6 +1,6 @@ import React, { useRef } from 'react' import { VisXYContainer, VisAxis, VisLine, VisGroupedBar } from '@unovis/react' -import { XYDataRecord, generateXYDataRecords, generateXYTestDataRecords } from '@src/utils/data' +import { XYDataRecord, generateXYDataRecords } from '@src/utils/data' import { Scale } from '@unovis/ts' export const title = 'Axis with Ticks Rotation' @@ -16,7 +16,7 @@ export const component = (): JSX.Element => { ] return ( <> - data={generateXYTestDataRecords(15)} + data={generateXYDataRecords(15)} xScale={Scale.scaleTime()} margin={{ top: 5, left: 5, bottom: 40, right: 5 }}> d.x} y={accessors}/> @@ -35,7 +35,7 @@ export const component = (): JSX.Element => { /> - data={generateXYTestDataRecords(15)} + data={generateXYDataRecords(15)} xScale={Scale.scaleTime()} margin={{ top: 35, left: 65, bottom: 5, right: 5 }}> d.x} y={accessors}/> @@ -55,7 +55,7 @@ export const component = (): JSX.Element => { /> - ariaLabel='A simple example of a Grouped Bar chart' data={generateXYTestDataRecords(15)} margin={{ top: 5, left: 5 }} xDomain={[1, 10]}> + ariaLabel='A simple example of a Grouped Bar chart' data={generateXYDataRecords(15)} margin={{ top: 5, left: 5 }} xDomain={[1, 10]}> d.x} y={accessors} /> { (d: XYDataRecord) => d.y2, ] - const data = useMemo(() => generateXYTestDataRecords(25), []) + const data = useMemo(() => generateXYDataRecords(25), []) useEffect(() => { setTimeout(() => { setSelectedRange([data[0].x, data[10].x]) diff --git a/packages/dev/src/examples/xy-components/crosshair/stacked-vs-non-stacked/index.tsx b/packages/dev/src/examples/xy-components/crosshair/stacked-vs-non-stacked/index.tsx index f561cb152..c32ae030a 100644 --- a/packages/dev/src/examples/xy-components/crosshair/stacked-vs-non-stacked/index.tsx +++ b/packages/dev/src/examples/xy-components/crosshair/stacked-vs-non-stacked/index.tsx @@ -1,6 +1,6 @@ import React from 'react' import { VisXYContainer, VisArea, VisCrosshair, VisGroupedBar, VisLine, VisScatter, VisStackedBar } from '@unovis/react' -import { generateXYDataRecords, XYDataRecord, generateXYTestDataRecords } from '@src/utils/data' +import { generateXYDataRecords, XYDataRecord } from '@src/utils/data' import s from './styles.module.css' @@ -8,7 +8,7 @@ export const title = 'Stacked vs Non-Stacked' export const subTitle = 'XY component comparison' export const component = (): JSX.Element => { - const data = generateXYTestDataRecords(10) + const data = generateXYDataRecords(10) const x = (d: XYDataRecord): number => d.x const y = (d: XYDataRecord): number | undefined => d.y const yStacked = [ diff --git a/packages/dev/src/utils/data.ts b/packages/dev/src/utils/data.ts index e61c924dc..e58344b43 100644 --- a/packages/dev/src/utils/data.ts +++ b/packages/dev/src/utils/data.ts @@ -1,5 +1,8 @@ import { GenericDataRecord } from '@unovis/ts' import { sample } from './array' +/* eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/naming-convention */ +const SeedRandom = require('seedrandom') +const rng = new SeedRandom('hello.') export type XYDataRecord = { x: number; @@ -42,54 +45,36 @@ export type NestedDatum = GenericDataRecord & { export function generateXYDataRecords (n = 10): XYDataRecord[] { return Array(n).fill(0).map((_, i) => ({ x: i, - y: 5 + 5 * Math.random(), - y1: 1 + 3 * Math.random(), - y2: 2 * Math.random(), + y: 5 + 5 * rng(), + y1: 1 + 3 * rng(), + y2: 2 * rng(), })) } -const randomArray = [0.03, 0.73, 0.46, 0.88, 0.34, 0.63, 0.12, 0.56, 0.67, 0.22, 0.08, 0.92, 0.72, 0.71, 0.04, 0.03, 0.69, 0.18, 0.14, 0.78, 0.45] - -export function generateXYTestDataRecords (n = 10): XYDataRecord[] { - let idx = -1 - return Array(n).fill(0).map((_, i) => { - if (i >= 20) { - idx = idx % 20 - } - idx++ - return { - x: i, - y: 5 + 5 * randomArray[idx], - y1: 1 + 3 * randomArray[idx], - y2: 2 * randomArray[idx], - } - }) -} - export function generateStackedDataRecords (n = 10, count = 6): StackedDataRecord[] { return Array(n).fill(0).map((_, i) => ({ x: i, - ys: Array(count).fill(0).map((_, i) => (i * count / 3) + (count * Math.random())), + ys: Array(count).fill(0).map((_, i) => (i * count / 3) + (count * rng())), })) } export function generateTimeSeries (n = 10, types = n, lengthMultiplier = 1): TimeDataRecord[] { const groups = Array(types).fill(0).map((_, i) => String.fromCharCode(i + 65)) return Array(n).fill(0).map((_, i: number) => ({ - timestamp: Date.now() + i * 1000 * 60 * 60 * 24 + (Math.random() - 0.5) * 5 * 1000 * 60 * 60 * 24, + timestamp: Date.now() + i * 1000 * 60 * 60 * 24 + (rng() - 0.5) * 5 * 1000 * 60 * 60 * 24, value: i / 10 + Math.sin(i / 5) + Math.cos(i / 3), - length: Math.round(lengthMultiplier * 1000 * 60 * 60 * 24) * (0.2 + Math.random()), + length: Math.round(lengthMultiplier * 1000 * 60 * 60 * 24) * (0.2 + rng()), type: groups[i % groups.length], })) } export function generateNodeLinkData (n = 10, numNeighbourLinks = () => 1): NodeLinkData { - const nodes = Array(n).fill(0).map((_, i) => ({ i, id: (i + 1).toString(), value: 100 * Math.random() })) + const nodes = Array(n).fill(0).map((_, i) => ({ i, id: (i + 1).toString(), value: 100 * rng() })) const options = [...nodes].slice(1) const links = nodes.reduce((arr, n) => { if (options.length) { - const num = Math.max(1, Math.random() * options.length) + const num = Math.max(1, rng() * options.length) for (let i = 0; i < num; i++) { const targetId = options.shift()?.id for (let k = 0; k < numNeighbourLinks(); k++) { @@ -97,7 +82,7 @@ export function generateNodeLinkData (n = 10, numNeighbourLinks = () => 1): Node id: `${n.id}-${targetId}`, source: n.id, target: targetId, - value: Math.random(), + value: rng(), } arr.push(link) } @@ -113,14 +98,14 @@ export function generatePrecalculatedNodeLinkData (n = 10, numNeighbourLinks = ( const nodes = Array(n).fill(0).map((_, i) => ({ i, id: (i + 1).toString(), - value: 100 * Math.random(), + value: 100 * rng(), x: 50 * i, y: 50 * i, })) const options = [...nodes].slice(1) const links = nodes.reduce((arr, n) => { if (options.length) { - const num = Math.max(1, Math.random() * options.length) + const num = Math.max(1, rng() * options.length) for (let i = 0; i < num; i++) { const targetId = options.shift()?.id for (let k = 0; k < numNeighbourLinks(); k++) { @@ -128,7 +113,7 @@ export function generatePrecalculatedNodeLinkData (n = 10, numNeighbourLinks = ( id: `${n.id}-${targetId}`, source: n.id, target: targetId, - value: Math.random(), + value: rng(), } arr.push(link) } @@ -157,7 +142,7 @@ export function generateHierarchyData (n: number, levels: Record const nodes = Array(n).fill(0).map((_, i) => { const obj: NodeDatum = { id: i.toString(), label: `N${i}` } Object.keys(levels).forEach(key => { - obj[key] = `${key}${Math.floor(Math.random() * levels[key])}` + obj[key] = `${key}${Math.floor(rng() * levels[key])}` }) return obj }) @@ -166,7 +151,7 @@ export function generateHierarchyData (n: number, levels: Record links: Array(n / 2).fill(0).map(() => ({ source: sample(nodes), target: sample(nodes), - value: Math.random(), + value: rng(), })), } }