volleyballsimtypes 0.0.416 → 0.0.418

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.
@@ -40,7 +40,9 @@ export type Match = Omit<DataProps<_Match>, 'sets' | 'homeTeam' | 'awayTeam' | '
40
40
  export type RallyEvent = DataProps<_RallyEvent> & {
41
41
  team?: Team;
42
42
  };
43
- export type Player = Omit<DataProps<_Player>, 'stats' | 'birthAge' | 'birthIteration' | 'declineProfile'> & Partial<Pick<DataProps<_Player>, 'birthAge' | 'birthIteration' | 'declineProfile'>> & {
43
+ export type Player = Omit<DataProps<_Player>, 'stats' | 'birthAge' | 'birthIteration' | 'declineProfile'> & {
44
+ -readonly [K in 'birthAge' | 'birthIteration' | 'declineProfile']?: DataProps<_Player>[K];
45
+ } & {
44
46
  stats?: PerformanceStats;
45
47
  teamId: string;
46
48
  jerseyNumber: number;
@@ -4,6 +4,7 @@ export * from './match-generator';
4
4
  export * from './match-rating';
5
5
  export * from './match-set';
6
6
  export * from './rally';
7
+ export * from './point-breakdown';
7
8
  export * from './court-position';
8
9
  export * from './match-team';
9
10
  export * from './vper';
@@ -20,6 +20,7 @@ __exportStar(require("./match-generator"), exports);
20
20
  __exportStar(require("./match-rating"), exports);
21
21
  __exportStar(require("./match-set"), exports);
22
22
  __exportStar(require("./rally"), exports);
23
+ __exportStar(require("./point-breakdown"), exports);
23
24
  __exportStar(require("./court-position"), exports);
24
25
  __exportStar(require("./match-team"), exports);
25
26
  __exportStar(require("./vper"), exports);
@@ -0,0 +1,30 @@
1
+ import { type Rally } from './rally';
2
+ export interface TeamBlockTally {
3
+ blockPoints: number;
4
+ blockSolo: number;
5
+ blockAssists: number;
6
+ }
7
+ export declare function tallyBlockPoints(rallies: Rally[], teamOf: (playerId: string) => string | null): Map<string, TeamBlockTally>;
8
+ export interface TeamPointBreakdown {
9
+ kills: number;
10
+ aces: number;
11
+ blockPoints: number;
12
+ opponentErrors: number;
13
+ }
14
+ export interface PointBreakdown {
15
+ home: TeamPointBreakdown;
16
+ away: TeamPointBreakdown;
17
+ }
18
+ export interface PointBreakdownInput {
19
+ rallies: Rally[];
20
+ homeTeamId: string;
21
+ awayTeamId: string;
22
+ teamOf: (playerId: string) => string | null;
23
+ homeKills: number;
24
+ awayKills: number;
25
+ homeAces: number;
26
+ awayAces: number;
27
+ homeTotalPoints: number;
28
+ awayTotalPoints: number;
29
+ }
30
+ export declare function computePointBreakdown(input: PointBreakdownInput): PointBreakdown;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tallyBlockPoints = tallyBlockPoints;
4
+ exports.computePointBreakdown = computePointBreakdown;
5
+ const event_1 = require("../event");
6
+ // A block scores a point in exactly ONE place in the sim (reception-simulator: a dig of a block fails
7
+ // and the block landed in-court, i.e. target >= 7). Each such rally is ONE block point regardless of how
8
+ // many blockers were on it; the box score records it as one `block_assists` per blocker (or one
9
+ // `block_solo`), which is why summing solo+assists over-counts block points. We rebuild the true count
10
+ // from the rallies. The blockSolo / blockAssists tallies must reconstruct box.block.solo and
11
+ // box.block.assists exactly (the correctness gate).
12
+ //
13
+ // `teamOf(playerId)` returns the team id of a player (or null if unknown). The scoring team is the
14
+ // blockers' team.
15
+ function tallyBlockPoints(rallies, teamOf) {
16
+ const out = new Map();
17
+ const tallyFor = (team) => {
18
+ let t = out.get(team);
19
+ if (t == null) {
20
+ t = { blockPoints: 0, blockSolo: 0, blockAssists: 0 };
21
+ out.set(team, t);
22
+ }
23
+ return t;
24
+ };
25
+ for (const rally of rallies) {
26
+ // Ignore substitutions / libero replacements (eventType < SERVE) when locating the terminal action.
27
+ const inPlay = rally.events.filter(e => e.eventType >= event_1.EventTypeEnum.SERVE);
28
+ const last = inPlay[inPlay.length - 1];
29
+ const prev = inPlay[inPlay.length - 2];
30
+ if (last == null || prev == null)
31
+ continue;
32
+ // Block point signature: the rally ends on a failed RECEPTION (dig) whose previous event is a BLOCK
33
+ // that landed in-court (target >= 7). target < 7 is a deflection -> the ATTACKER's kill, not a block.
34
+ if (last.eventType !== event_1.EventTypeEnum.RECEPTION || last.failure <= 0)
35
+ continue;
36
+ if (prev.eventType !== event_1.EventTypeEnum.BLOCK)
37
+ continue;
38
+ const block = prev;
39
+ if (block.target < 7)
40
+ continue;
41
+ const team = teamOf(block.blockers[0] ?? block.playerId);
42
+ if (team == null)
43
+ continue;
44
+ const t = tallyFor(team);
45
+ t.blockPoints++;
46
+ if (block.blockers.length < 2)
47
+ t.blockSolo++;
48
+ else
49
+ t.blockAssists += block.blockers.length;
50
+ }
51
+ return out;
52
+ }
53
+ // Kills/aces come straight from the box score; block points are derived from rallies; opponent errors
54
+ // are the remainder (>= 0 by construction). The four reconcile to the team's total points.
55
+ function computePointBreakdown(input) {
56
+ const tally = tallyBlockPoints(input.rallies, input.teamOf);
57
+ const homeBlocks = tally.get(input.homeTeamId)?.blockPoints ?? 0;
58
+ const awayBlocks = tally.get(input.awayTeamId)?.blockPoints ?? 0;
59
+ return {
60
+ home: {
61
+ kills: input.homeKills,
62
+ aces: input.homeAces,
63
+ blockPoints: homeBlocks,
64
+ opponentErrors: input.homeTotalPoints - input.homeKills - input.homeAces - homeBlocks
65
+ },
66
+ away: {
67
+ kills: input.awayKills,
68
+ aces: input.awayAces,
69
+ blockPoints: awayBlocks,
70
+ opponentErrors: input.awayTotalPoints - input.awayKills - input.awayAces - awayBlocks
71
+ }
72
+ };
73
+ }
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const globals_1 = require("@jest/globals");
4
+ const event_1 = require("../event");
5
+ const point_breakdown_1 = require("./point-breakdown");
6
+ // Minimal event/rally builders - the tally only reads eventType, failure, target, blockers, playerId.
7
+ const blockEvent = (playerId, target, blockers) => ({ eventType: event_1.EventTypeEnum.BLOCK, playerId, target, blockers, failure: 0, type: blockers.length, score: 0, activeTraits: [] });
8
+ const receptionEvent = (playerId, failure) => ({ eventType: event_1.EventTypeEnum.RECEPTION, playerId, failure, target: 0, type: 0, score: 0, activeTraits: [] });
9
+ const serveEvent = (playerId, failure) => ({ eventType: event_1.EventTypeEnum.SERVE, playerId, failure });
10
+ const spikeEvent = (playerId) => ({ eventType: event_1.EventTypeEnum.SPIKE, playerId, failure: 0 });
11
+ const rally = (events) => ({ id: 'r', order: 0, servingTeamId: 'HOME', events });
12
+ const teamOf = (id) => id.startsWith('h') ? 'HOME' : id.startsWith('a') ? 'AWAY' : null;
13
+ (0, globals_1.describe)('tallyBlockPoints', () => {
14
+ (0, globals_1.it)('counts an assisted block point once, recording each blocker as an assist', () => {
15
+ const t = (0, point_breakdown_1.tallyBlockPoints)([rally([blockEvent('h1', 8, ['h1', 'h2']), receptionEvent('a3', 1)])], teamOf);
16
+ (0, globals_1.expect)(t.get('HOME')).toEqual({ blockPoints: 1, blockSolo: 0, blockAssists: 2 });
17
+ });
18
+ (0, globals_1.it)('counts a solo block point', () => {
19
+ const t = (0, point_breakdown_1.tallyBlockPoints)([rally([blockEvent('h1', 9, ['h1']), receptionEvent('a3', 2)])], teamOf);
20
+ (0, globals_1.expect)(t.get('HOME')).toEqual({ blockPoints: 1, blockSolo: 1, blockAssists: 0 });
21
+ });
22
+ (0, globals_1.it)('does NOT count a deflection (target < 7) - that is the attacker\'s kill', () => {
23
+ const t = (0, point_breakdown_1.tallyBlockPoints)([rally([blockEvent('h1', 4, ['h1', 'h2']), receptionEvent('a3', 1)])], teamOf);
24
+ (0, globals_1.expect)(t.size).toBe(0);
25
+ });
26
+ (0, globals_1.it)('does NOT count an ace (reception fail after serve)', () => {
27
+ const t = (0, point_breakdown_1.tallyBlockPoints)([rally([serveEvent('h1', 0), receptionEvent('a3', 1)])], teamOf);
28
+ (0, globals_1.expect)(t.size).toBe(0);
29
+ });
30
+ (0, globals_1.it)('does NOT count a successful dig (reception failure 0)', () => {
31
+ const t = (0, point_breakdown_1.tallyBlockPoints)([rally([blockEvent('h1', 8, ['h1', 'h2']), receptionEvent('a3', 0), spikeEvent('a3')])], teamOf);
32
+ (0, globals_1.expect)(t.size).toBe(0);
33
+ });
34
+ (0, globals_1.it)('reconstructs box block.solo and block.assists across a mix (incl. a triple block)', () => {
35
+ const t = (0, point_breakdown_1.tallyBlockPoints)([
36
+ rally([blockEvent('h1', 8, ['h1', 'h2']), receptionEvent('a3', 1)]), // double: +2 assists
37
+ rally([blockEvent('h3', 8, ['h3', 'h4', 'h5']), receptionEvent('a1', 1)]), // triple: +3 assists
38
+ rally([blockEvent('h1', 9, ['h1']), receptionEvent('a2', 1)]), // solo: +1 solo
39
+ rally([blockEvent('a1', 8, ['a1', 'a2']), receptionEvent('h2', 1)]) // away double
40
+ ], teamOf);
41
+ (0, globals_1.expect)(t.get('HOME')).toEqual({ blockPoints: 3, blockSolo: 1, blockAssists: 5 });
42
+ (0, globals_1.expect)(t.get('AWAY')).toEqual({ blockPoints: 1, blockSolo: 0, blockAssists: 2 });
43
+ });
44
+ });
45
+ (0, globals_1.describe)('computePointBreakdown', () => {
46
+ (0, globals_1.it)('reproduces the prod bug scenario as a positive number (was -3)', () => {
47
+ // AWAY scored 99 (54 kills, 0 aces) and 28 block points (8 solo + 20 doubles). Old formula did
48
+ // 99 - 54 - (8 + 40) - 0 = -3; correct is 99 - 54 - 0 - 28 = 17.
49
+ const rallies = [];
50
+ for (let i = 0; i < 20; i++)
51
+ rallies.push(rally([blockEvent('a1', 8, ['a1', 'a2']), receptionEvent(`h${i}`, 1)]));
52
+ for (let i = 0; i < 8; i++)
53
+ rallies.push(rally([blockEvent('a3', 9, ['a3']), receptionEvent(`h${i + 20}`, 1)]));
54
+ const out = (0, point_breakdown_1.computePointBreakdown)({
55
+ rallies,
56
+ homeTeamId: 'HOME',
57
+ awayTeamId: 'AWAY',
58
+ teamOf,
59
+ homeKills: 51,
60
+ awayKills: 54,
61
+ homeAces: 3,
62
+ awayAces: 0,
63
+ homeTotalPoints: 108,
64
+ awayTotalPoints: 99
65
+ });
66
+ (0, globals_1.expect)(out.away.blockPoints).toBe(28);
67
+ (0, globals_1.expect)(out.away.opponentErrors).toBe(17);
68
+ (0, globals_1.expect)(out.away.opponentErrors).toBeGreaterThanOrEqual(0);
69
+ // The four categories reconcile to the team's total points.
70
+ (0, globals_1.expect)(out.away.kills + out.away.aces + out.away.blockPoints + out.away.opponentErrors).toBe(99);
71
+ (0, globals_1.expect)(out.home.kills + out.home.aces + out.home.blockPoints + out.home.opponentErrors).toBe(108);
72
+ });
73
+ });
@@ -40,7 +40,9 @@ export type Match = Omit<DataProps<_Match>, 'sets' | 'homeTeam' | 'awayTeam' | '
40
40
  export type RallyEvent = DataProps<_RallyEvent> & {
41
41
  team?: Team;
42
42
  };
43
- export type Player = Omit<DataProps<_Player>, 'stats' | 'birthAge' | 'birthIteration' | 'declineProfile'> & Partial<Pick<DataProps<_Player>, 'birthAge' | 'birthIteration' | 'declineProfile'>> & {
43
+ export type Player = Omit<DataProps<_Player>, 'stats' | 'birthAge' | 'birthIteration' | 'declineProfile'> & {
44
+ -readonly [K in 'birthAge' | 'birthIteration' | 'declineProfile']?: DataProps<_Player>[K];
45
+ } & {
44
46
  stats?: PerformanceStats;
45
47
  teamId: string;
46
48
  jerseyNumber: number;
@@ -4,6 +4,7 @@ export * from './match-generator';
4
4
  export * from './match-rating';
5
5
  export * from './match-set';
6
6
  export * from './rally';
7
+ export * from './point-breakdown';
7
8
  export * from './court-position';
8
9
  export * from './match-team';
9
10
  export * from './vper';
@@ -4,6 +4,7 @@ export * from './match-generator';
4
4
  export * from './match-rating';
5
5
  export * from './match-set';
6
6
  export * from './rally';
7
+ export * from './point-breakdown';
7
8
  export * from './court-position';
8
9
  export * from './match-team';
9
10
  export * from './vper';
@@ -0,0 +1,30 @@
1
+ import { type Rally } from './rally';
2
+ export interface TeamBlockTally {
3
+ blockPoints: number;
4
+ blockSolo: number;
5
+ blockAssists: number;
6
+ }
7
+ export declare function tallyBlockPoints(rallies: Rally[], teamOf: (playerId: string) => string | null): Map<string, TeamBlockTally>;
8
+ export interface TeamPointBreakdown {
9
+ kills: number;
10
+ aces: number;
11
+ blockPoints: number;
12
+ opponentErrors: number;
13
+ }
14
+ export interface PointBreakdown {
15
+ home: TeamPointBreakdown;
16
+ away: TeamPointBreakdown;
17
+ }
18
+ export interface PointBreakdownInput {
19
+ rallies: Rally[];
20
+ homeTeamId: string;
21
+ awayTeamId: string;
22
+ teamOf: (playerId: string) => string | null;
23
+ homeKills: number;
24
+ awayKills: number;
25
+ homeAces: number;
26
+ awayAces: number;
27
+ homeTotalPoints: number;
28
+ awayTotalPoints: number;
29
+ }
30
+ export declare function computePointBreakdown(input: PointBreakdownInput): PointBreakdown;
@@ -0,0 +1,69 @@
1
+ import { EventTypeEnum } from '../event';
2
+ // A block scores a point in exactly ONE place in the sim (reception-simulator: a dig of a block fails
3
+ // and the block landed in-court, i.e. target >= 7). Each such rally is ONE block point regardless of how
4
+ // many blockers were on it; the box score records it as one `block_assists` per blocker (or one
5
+ // `block_solo`), which is why summing solo+assists over-counts block points. We rebuild the true count
6
+ // from the rallies. The blockSolo / blockAssists tallies must reconstruct box.block.solo and
7
+ // box.block.assists exactly (the correctness gate).
8
+ //
9
+ // `teamOf(playerId)` returns the team id of a player (or null if unknown). The scoring team is the
10
+ // blockers' team.
11
+ export function tallyBlockPoints(rallies, teamOf) {
12
+ const out = new Map();
13
+ const tallyFor = (team) => {
14
+ let t = out.get(team);
15
+ if (t == null) {
16
+ t = { blockPoints: 0, blockSolo: 0, blockAssists: 0 };
17
+ out.set(team, t);
18
+ }
19
+ return t;
20
+ };
21
+ for (const rally of rallies) {
22
+ // Ignore substitutions / libero replacements (eventType < SERVE) when locating the terminal action.
23
+ const inPlay = rally.events.filter(e => e.eventType >= EventTypeEnum.SERVE);
24
+ const last = inPlay[inPlay.length - 1];
25
+ const prev = inPlay[inPlay.length - 2];
26
+ if (last == null || prev == null)
27
+ continue;
28
+ // Block point signature: the rally ends on a failed RECEPTION (dig) whose previous event is a BLOCK
29
+ // that landed in-court (target >= 7). target < 7 is a deflection -> the ATTACKER's kill, not a block.
30
+ if (last.eventType !== EventTypeEnum.RECEPTION || last.failure <= 0)
31
+ continue;
32
+ if (prev.eventType !== EventTypeEnum.BLOCK)
33
+ continue;
34
+ const block = prev;
35
+ if (block.target < 7)
36
+ continue;
37
+ const team = teamOf(block.blockers[0] ?? block.playerId);
38
+ if (team == null)
39
+ continue;
40
+ const t = tallyFor(team);
41
+ t.blockPoints++;
42
+ if (block.blockers.length < 2)
43
+ t.blockSolo++;
44
+ else
45
+ t.blockAssists += block.blockers.length;
46
+ }
47
+ return out;
48
+ }
49
+ // Kills/aces come straight from the box score; block points are derived from rallies; opponent errors
50
+ // are the remainder (>= 0 by construction). The four reconcile to the team's total points.
51
+ export function computePointBreakdown(input) {
52
+ const tally = tallyBlockPoints(input.rallies, input.teamOf);
53
+ const homeBlocks = tally.get(input.homeTeamId)?.blockPoints ?? 0;
54
+ const awayBlocks = tally.get(input.awayTeamId)?.blockPoints ?? 0;
55
+ return {
56
+ home: {
57
+ kills: input.homeKills,
58
+ aces: input.homeAces,
59
+ blockPoints: homeBlocks,
60
+ opponentErrors: input.homeTotalPoints - input.homeKills - input.homeAces - homeBlocks
61
+ },
62
+ away: {
63
+ kills: input.awayKills,
64
+ aces: input.awayAces,
65
+ blockPoints: awayBlocks,
66
+ opponentErrors: input.awayTotalPoints - input.awayKills - input.awayAces - awayBlocks
67
+ }
68
+ };
69
+ }
@@ -0,0 +1,71 @@
1
+ import { describe, expect, it } from '@jest/globals';
2
+ import { EventTypeEnum } from '../event';
3
+ import { computePointBreakdown, tallyBlockPoints } from './point-breakdown';
4
+ // Minimal event/rally builders - the tally only reads eventType, failure, target, blockers, playerId.
5
+ const blockEvent = (playerId, target, blockers) => ({ eventType: EventTypeEnum.BLOCK, playerId, target, blockers, failure: 0, type: blockers.length, score: 0, activeTraits: [] });
6
+ const receptionEvent = (playerId, failure) => ({ eventType: EventTypeEnum.RECEPTION, playerId, failure, target: 0, type: 0, score: 0, activeTraits: [] });
7
+ const serveEvent = (playerId, failure) => ({ eventType: EventTypeEnum.SERVE, playerId, failure });
8
+ const spikeEvent = (playerId) => ({ eventType: EventTypeEnum.SPIKE, playerId, failure: 0 });
9
+ const rally = (events) => ({ id: 'r', order: 0, servingTeamId: 'HOME', events });
10
+ const teamOf = (id) => id.startsWith('h') ? 'HOME' : id.startsWith('a') ? 'AWAY' : null;
11
+ describe('tallyBlockPoints', () => {
12
+ it('counts an assisted block point once, recording each blocker as an assist', () => {
13
+ const t = tallyBlockPoints([rally([blockEvent('h1', 8, ['h1', 'h2']), receptionEvent('a3', 1)])], teamOf);
14
+ expect(t.get('HOME')).toEqual({ blockPoints: 1, blockSolo: 0, blockAssists: 2 });
15
+ });
16
+ it('counts a solo block point', () => {
17
+ const t = tallyBlockPoints([rally([blockEvent('h1', 9, ['h1']), receptionEvent('a3', 2)])], teamOf);
18
+ expect(t.get('HOME')).toEqual({ blockPoints: 1, blockSolo: 1, blockAssists: 0 });
19
+ });
20
+ it('does NOT count a deflection (target < 7) - that is the attacker\'s kill', () => {
21
+ const t = tallyBlockPoints([rally([blockEvent('h1', 4, ['h1', 'h2']), receptionEvent('a3', 1)])], teamOf);
22
+ expect(t.size).toBe(0);
23
+ });
24
+ it('does NOT count an ace (reception fail after serve)', () => {
25
+ const t = tallyBlockPoints([rally([serveEvent('h1', 0), receptionEvent('a3', 1)])], teamOf);
26
+ expect(t.size).toBe(0);
27
+ });
28
+ it('does NOT count a successful dig (reception failure 0)', () => {
29
+ const t = tallyBlockPoints([rally([blockEvent('h1', 8, ['h1', 'h2']), receptionEvent('a3', 0), spikeEvent('a3')])], teamOf);
30
+ expect(t.size).toBe(0);
31
+ });
32
+ it('reconstructs box block.solo and block.assists across a mix (incl. a triple block)', () => {
33
+ const t = tallyBlockPoints([
34
+ rally([blockEvent('h1', 8, ['h1', 'h2']), receptionEvent('a3', 1)]), // double: +2 assists
35
+ rally([blockEvent('h3', 8, ['h3', 'h4', 'h5']), receptionEvent('a1', 1)]), // triple: +3 assists
36
+ rally([blockEvent('h1', 9, ['h1']), receptionEvent('a2', 1)]), // solo: +1 solo
37
+ rally([blockEvent('a1', 8, ['a1', 'a2']), receptionEvent('h2', 1)]) // away double
38
+ ], teamOf);
39
+ expect(t.get('HOME')).toEqual({ blockPoints: 3, blockSolo: 1, blockAssists: 5 });
40
+ expect(t.get('AWAY')).toEqual({ blockPoints: 1, blockSolo: 0, blockAssists: 2 });
41
+ });
42
+ });
43
+ describe('computePointBreakdown', () => {
44
+ it('reproduces the prod bug scenario as a positive number (was -3)', () => {
45
+ // AWAY scored 99 (54 kills, 0 aces) and 28 block points (8 solo + 20 doubles). Old formula did
46
+ // 99 - 54 - (8 + 40) - 0 = -3; correct is 99 - 54 - 0 - 28 = 17.
47
+ const rallies = [];
48
+ for (let i = 0; i < 20; i++)
49
+ rallies.push(rally([blockEvent('a1', 8, ['a1', 'a2']), receptionEvent(`h${i}`, 1)]));
50
+ for (let i = 0; i < 8; i++)
51
+ rallies.push(rally([blockEvent('a3', 9, ['a3']), receptionEvent(`h${i + 20}`, 1)]));
52
+ const out = computePointBreakdown({
53
+ rallies,
54
+ homeTeamId: 'HOME',
55
+ awayTeamId: 'AWAY',
56
+ teamOf,
57
+ homeKills: 51,
58
+ awayKills: 54,
59
+ homeAces: 3,
60
+ awayAces: 0,
61
+ homeTotalPoints: 108,
62
+ awayTotalPoints: 99
63
+ });
64
+ expect(out.away.blockPoints).toBe(28);
65
+ expect(out.away.opponentErrors).toBe(17);
66
+ expect(out.away.opponentErrors).toBeGreaterThanOrEqual(0);
67
+ // The four categories reconcile to the team's total points.
68
+ expect(out.away.kills + out.away.aces + out.away.blockPoints + out.away.opponentErrors).toBe(99);
69
+ expect(out.home.kills + out.home.aces + out.home.blockPoints + out.home.opponentErrors).toBe(108);
70
+ });
71
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "volleyballsimtypes",
3
- "version": "0.0.416",
3
+ "version": "0.0.418",
4
4
  "description": "vbsim types",
5
5
  "main": "./dist/cjs/src/index.js",
6
6
  "module": "./dist/esm/src/index.js",