Skip to main content

Accessors

Overview

Accessors are path strings that specify the location of data values within nested JSON objects. They provide a simple dot-notation syntax for accessing deeply nested attributes without writing complex traversal code. Accessors are used throughout TODS for filtering, policy evaluation, and data extraction.

Key Concepts

Dot Notation: Use dots to traverse object properties (e.g., person.standardFamilyName)
Array Handling: Automatically extracts values from arrays
Type Safety: Works with any JSON-compatible data structure
Use Cases: Participant filtering, avoidance policies, scale item values

Basic Syntax

Simple Property Access

Access top-level properties:

// Participant object
const participant = {
participantId: 'player-123',
participantType: 'INDIVIDUAL',
person: {
standardFamilyName: 'Federer',
standardGivenName: 'Roger',
nationalityCode: 'SUI',
sex: 'MALE'
}
};

// Accessor for family name
const accessor = 'person.standardFamilyName';
// Returns: 'Federer'

// Accessor for nationality
const accessor2 = 'person.nationalityCode';
// Returns: 'SUI'

Nested Property Access

Traverse multiple levels:

const participant = {
participantId: 'player-123',
person: {
addresses: [{
city: 'Basel',
country: 'Switzerland'
}],
contacts: [{
type: 'email',
value: 'roger@example.com'
}]
}
};

// Accessor for nested data
const accessor = 'person.addresses.country';
// Returns: ['Switzerland'] (array because addresses is an array)

Array Property Access

Accessors automatically handle arrays:

// PAIR participant with individual participants
const participant = {
participantType: 'PAIR',
individualParticipants: [
{
person: {
standardFamilyName: 'Bryan',
nationalityCode: 'USA'
}
},
{
person: {
standardFamilyName: 'Bryan',
nationalityCode: 'USA'
}
}
]
};

// Accessor extracts from all array elements
const accessor = 'individualParticipants.person.nationalityCode';
// Returns: ['USA', 'USA']

Common Use Cases

Participant Filtering

Filter participants using accessor-based criteria:

// Get all female participants
const { participants } = tournamentEngine.getParticipants({
participantFilters: {
accessorValues: [
{
accessor: 'person.sex',
value: 'FEMALE'
}
]
}
});

// Get participants from specific country
const { participants: french } = tournamentEngine.getParticipants({
participantFilters: {
accessorValues: [
{
accessor: 'person.nationalityCode',
value: 'FRA'
}
]
}
});

// Multiple filters (AND logic)
const { participants: filtered } = tournamentEngine.getParticipants({
participantFilters: {
accessorValues: [
{ accessor: 'person.sex', value: 'MALE' },
{ accessor: 'person.nationalityCode', value: 'ESP' }
]
}
});

Scale Item Values

Extract numeric values from complex scale items:

// Complex NTRP scale item
const scaleItem = {
scaleType: 'RATING',
scaleValue: {
ntrpRating: 4.5,
ratingYear: '2024',
ustaRatingType: 'C',
district: 'SoCal'
},
scaleName: 'NTRP',
eventType: 'DOUBLES',
scaleDate: '2024-06-15'
};

// Use accessor to extract the numeric rating
const scaleAttributes = {
scaleType: 'RATING',
scaleName: 'NTRP',
eventType: 'DOUBLES',
accessor: 'ntrpRating' // Points to scaleValue.ntrpRating
};

const { scaleItem: retrieved } = tournamentEngine.getParticipantScaleItem({
participantId: 'player-123',
scaleAttributes
});
// The accessor extracts 4.5 from scaleValue for comparisons

See: Scale Items for detailed scale item documentation.

Avoidance Policies

Define matchUp avoidance based on participant attributes:

// Avoid matching participants from same country
const policyDefinitions = {
avoidance: {
policyName: 'Nationality Avoidance',
roundsToSeparate: 2, // Keep apart for 2 rounds
accessor: 'person.nationalityCode'
}
};

tournamentEngine.attachPolicies({ policyDefinitions });

// When generating draw, participants with matching nationalityCode
// will be placed to avoid early-round matchups
tournamentEngine.generateDrawDefinition({
eventId: 'singles-main',
policyDefinitions
});

See: Avoidance Policies for complete avoidance documentation.

Team/Pair Participant Filtering

Access properties of individual participants within teams or pairs:

// Get all pairs containing at least one USA player
const { participants } = tournamentEngine.getParticipants({
participantFilters: {
participantTypes: ['PAIR'],
accessorValues: [
{
accessor: 'individualParticipants.person.nationalityCode',
value: 'USA'
}
]
}
});

// Get teams with specific club affiliation
const { participants: teams } = tournamentEngine.getParticipants({
participantFilters: {
participantTypes: ['TEAM'],
accessorValues: [
{
accessor: 'teamParticipants.person.club',
value: 'Tennis Club America'
}
]
}
});

Advanced Patterns

Multiple Accessor Filters

Combine multiple accessor-based filters:

const { participants } = tournamentEngine.getParticipants({
participantFilters: {
accessorValues: [
{ accessor: 'person.sex', value: 'FEMALE' },
{ accessor: 'person.nationalityCode', value: 'GBR' },
{ accessor: 'person.birthDate', value: '2005' } // Birth year matching
]
}
});

// All conditions must match (AND logic)

Partial String Matching

Some filter contexts support partial matching:

// Filter by birth year from full date
const { participants } = tournamentEngine.getParticipants({
participantFilters: {
accessorValues: [
{
accessor: 'person.birthDate',
value: '2005' // Matches any birthDate containing '2005'
}
]
}
});

Array Value Extraction

When accessor path includes arrays, values are extracted from all elements:

// PAIR participant
const pair = {
participantType: 'PAIR',
individualParticipants: [
{
person: { nationalityCode: 'USA', standardFamilyName: 'Sock' }
},
{
person: { nationalityCode: 'AUS', standardFamilyName: 'Peers' }
}
]
};

// Accessor extracts both nationalities
const accessor = 'individualParticipants.person.nationalityCode';
// Returns: ['USA', 'AUS']

// Can match if ANY element matches the filter value

Accessor Validation

Valid Accessor Paths

// ✓ Simple property
'participantType'

// ✓ Nested property
'person.standardFamilyName'

// ✓ Deeply nested
'person.addresses.city'

// ✓ Through arrays
'individualParticipants.person.nationalityCode'

// ✓ Multiple levels with arrays
'teamParticipants.person.contacts.value'

Invalid Accessor Paths

// ✗ Empty string
''

// ✗ Starting with dot
'.person.name'

// ✗ Ending with dot
'person.name.'

// ✗ Double dots
'person..name'

// ✗ Array indices (not supported)
'individualParticipants[0].person.name'

Performance Considerations

Accessor Efficiency

Accessors are evaluated for each participant/item, so keep paths as short as necessary:

// ✓ Efficient - direct path
accessor: 'person.nationalityCode'

// ✓ Efficient - necessary depth
accessor: 'individualParticipants.person.nationalityCode'

// ⚠ Less efficient - unnecessary depth
accessor: 'person.details.info.data.nationality' // If flatter structure possible

Caching Considerations

When filtering large participant sets repeatedly:

// ✓ Good - filter once, reuse results
const { participants: females } = tournamentEngine.getParticipants({
participantFilters: {
accessorValues: [{ accessor: 'person.sex', value: 'FEMALE' }]
}
});

// Use 'females' array for subsequent operations

// ✗ Less efficient - filtering multiple times
// (If you need the same filtered set multiple times)

Practical Examples

Tournament Entry Filters

Filter participants for event entry:

// Get all junior female players
const { participants } = tournamentEngine.getParticipants({
participantFilters: {
accessorValues: [
{ accessor: 'person.sex', value: 'FEMALE' },
{ accessor: 'person.birthDate', value: '2006' } // U18 players
]
}
});

// Add them to junior girls event
tournamentEngine.addEventEntries({
eventId: 'girls-u18',
participantIds: participants.map(p => p.participantId)
});

Nationality-Based Draws

Create draws avoiding same-nation matchups:

// Set nationality avoidance policy
const policyDefinitions = {
avoidance: {
policyName: 'National Federation Avoidance',
roundsToSeparate: 3,
accessor: 'person.nationalityCode'
}
};

// Generate draw with avoidance
tournamentEngine.generateDrawDefinition({
eventId: 'singles-main',
drawSize: 32,
seedsCount: 8,
policyDefinitions
});

// Participants from same country will be separated for 3 rounds

Complex Scale Item Retrieval

Work with multi-attribute scale values:

// Set complex scale item
tournamentEngine.setParticipantScaleItem({
participantId: 'player-123',
scaleItem: {
scaleType: 'RATING',
scaleValue: {
combinedRating: 9.2,
singlesRating: 9.5,
doublesRating: 8.9,
lastUpdated: '2024-06-15'
},
scaleName: 'CustomRating',
eventType: 'SINGLES',
scaleDate: '2024-06-15'
}
});

// Retrieve using accessor to combined rating
const { scaleItem } = tournamentEngine.getParticipantScaleItem({
participantId: 'player-123',
scaleAttributes: {
scaleType: 'RATING',
scaleName: 'CustomRating',
eventType: 'SINGLES',
accessor: 'combinedRating'
}
});

console.log(scaleItem.scaleValue.combinedRating); // 9.2

Multi-Level Team Filtering

Filter team participants by individual member attributes:

// Get teams with at least one member from specific region
const { participants: regionalTeams } = tournamentEngine.getParticipants({
participantFilters: {
participantTypes: ['TEAM'],
accessorValues: [
{
accessor: 'teamParticipants.person.region',
value: 'Northern California'
}
]
}
});

// Teams where ANY member matches the region will be included

Live Editor Example

In the Live Editor below, the accessor "person.sex" is used to target FEMALE participants. Change the accessor value or uncomment the person.nationalityCode filter to see the results change.

Live Editor
Result
Loading...