890 lines
27 KiB
TypeScript
890 lines
27 KiB
TypeScript
import { createImageTemplate, DEFAULT_CONFIDENCE, type CategorizedTemplate } from '@/packages/domain/value-objects/ImageTemplate';
|
|
import type { ImageTemplate } from '@/packages/domain/value-objects/ImageTemplate';
|
|
|
|
/**
|
|
* Template definitions for iRacing UI elements.
|
|
*
|
|
* These templates replace CSS selectors with image-based matching for TOS-compliant
|
|
* OS-level automation. Templates reference images in resources/templates/iracing/
|
|
*
|
|
* Template images should be captured from the actual iRacing UI at standard resolution.
|
|
* Recommended: 1920x1080 or 2560x1440 with PNG format for lossless quality.
|
|
*/
|
|
|
|
/**
|
|
* Step template configuration containing all templates needed for a workflow step.
|
|
*/
|
|
export interface StepTemplates {
|
|
/** Templates to detect if we're on this step */
|
|
indicators: ImageTemplate[];
|
|
/** Button templates for navigation and actions */
|
|
buttons: Record<string, ImageTemplate>;
|
|
/** Field templates for form inputs */
|
|
fields?: Record<string, ImageTemplate>;
|
|
/** Modal-related templates if applicable */
|
|
modal?: {
|
|
indicator: ImageTemplate;
|
|
closeButton: ImageTemplate;
|
|
confirmButton?: ImageTemplate;
|
|
searchInput?: ImageTemplate;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Complete template map type for iRacing automation.
|
|
*/
|
|
export interface IRacingTemplateMapType {
|
|
/** Common templates used across multiple steps */
|
|
common: {
|
|
/** Logged-in state indicators */
|
|
loginIndicators: ImageTemplate[];
|
|
/** Logged-out state indicators */
|
|
logoutIndicators: ImageTemplate[];
|
|
/** Generic navigation buttons */
|
|
navigation: Record<string, ImageTemplate>;
|
|
/** Loading indicators */
|
|
loading: ImageTemplate[];
|
|
};
|
|
/** Step-specific templates */
|
|
steps: Record<number, StepTemplates>;
|
|
/** Base path for template images */
|
|
templateBasePath: string;
|
|
}
|
|
|
|
/**
|
|
* Template paths for iRacing UI elements.
|
|
* All paths are relative to resources/templates/iracing/
|
|
*/
|
|
const TEMPLATE_PATHS = {
|
|
common: {
|
|
login: 'common/login-indicator.png',
|
|
logout: 'common/logout-indicator.png',
|
|
userAvatar: 'common/user-avatar.png',
|
|
memberBadge: 'common/member-badge.png',
|
|
loginButton: 'common/login-button.png',
|
|
loadingSpinner: 'common/loading-spinner.png',
|
|
nextButton: 'common/next-button.png',
|
|
backButton: 'common/back-button.png',
|
|
checkoutButton: 'common/checkout-button.png',
|
|
closeModal: 'common/close-modal-button.png',
|
|
},
|
|
steps: {
|
|
1: {
|
|
loginForm: 'step01-login/login-form.png',
|
|
emailField: 'step01-login/email-field.png',
|
|
passwordField: 'step01-login/password-field.png',
|
|
submitButton: 'step01-login/submit-button.png',
|
|
},
|
|
2: {
|
|
hostedRacingTab: 'step02-hosted/hosted-racing-tab.png',
|
|
// Using 1x template - will be scaled by 2x for Retina displays
|
|
createRaceButton: 'step02-hosted/create-race-button.png',
|
|
sessionList: 'step02-hosted/session-list.png',
|
|
},
|
|
3: {
|
|
createRaceModal: 'step03-create/create-race-modal.png',
|
|
confirmButton: 'step03-create/confirm-button.png',
|
|
},
|
|
4: {
|
|
stepIndicator: 'step04-info/race-info-indicator.png',
|
|
sessionNameField: 'step04-info/session-name-field.png',
|
|
passwordField: 'step04-info/password-field.png',
|
|
descriptionField: 'step04-info/description-field.png',
|
|
nextButton: 'step04-info/next-button.png',
|
|
},
|
|
5: {
|
|
stepIndicator: 'step05-server/server-details-indicator.png',
|
|
regionDropdown: 'step05-server/region-dropdown.png',
|
|
startNowToggle: 'step05-server/start-now-toggle.png',
|
|
nextButton: 'step05-server/next-button.png',
|
|
},
|
|
6: {
|
|
stepIndicator: 'step06-admins/admins-indicator.png',
|
|
addAdminButton: 'step06-admins/add-admin-button.png',
|
|
adminModal: 'step06-admins/admin-modal.png',
|
|
searchField: 'step06-admins/search-field.png',
|
|
nextButton: 'step06-admins/next-button.png',
|
|
},
|
|
7: {
|
|
stepIndicator: 'step07-time/time-limits-indicator.png',
|
|
practiceField: 'step07-time/practice-field.png',
|
|
qualifyField: 'step07-time/qualify-field.png',
|
|
raceField: 'step07-time/race-field.png',
|
|
nextButton: 'step07-time/next-button.png',
|
|
},
|
|
8: {
|
|
stepIndicator: 'step08-cars/cars-indicator.png',
|
|
addCarButton: 'step08-cars/add-car-button.png',
|
|
carList: 'step08-cars/car-list.png',
|
|
nextButton: 'step08-cars/next-button.png',
|
|
},
|
|
9: {
|
|
carModal: 'step09-addcar/car-modal.png',
|
|
searchField: 'step09-addcar/search-field.png',
|
|
carGrid: 'step09-addcar/car-grid.png',
|
|
selectButton: 'step09-addcar/select-button.png',
|
|
closeButton: 'step09-addcar/close-button.png',
|
|
},
|
|
10: {
|
|
stepIndicator: 'step10-classes/car-classes-indicator.png',
|
|
classDropdown: 'step10-classes/class-dropdown.png',
|
|
nextButton: 'step10-classes/next-button.png',
|
|
},
|
|
11: {
|
|
stepIndicator: 'step11-track/track-indicator.png',
|
|
addTrackButton: 'step11-track/add-track-button.png',
|
|
trackList: 'step11-track/track-list.png',
|
|
nextButton: 'step11-track/next-button.png',
|
|
},
|
|
12: {
|
|
trackModal: 'step12-addtrack/track-modal.png',
|
|
searchField: 'step12-addtrack/search-field.png',
|
|
trackGrid: 'step12-addtrack/track-grid.png',
|
|
selectButton: 'step12-addtrack/select-button.png',
|
|
closeButton: 'step12-addtrack/close-button.png',
|
|
},
|
|
13: {
|
|
stepIndicator: 'step13-trackopts/track-options-indicator.png',
|
|
configDropdown: 'step13-trackopts/config-dropdown.png',
|
|
nextButton: 'step13-trackopts/next-button.png',
|
|
},
|
|
14: {
|
|
stepIndicator: 'step14-tod/time-of-day-indicator.png',
|
|
timeSlider: 'step14-tod/time-slider.png',
|
|
datePicker: 'step14-tod/date-picker.png',
|
|
nextButton: 'step14-tod/next-button.png',
|
|
},
|
|
15: {
|
|
stepIndicator: 'step15-weather/weather-indicator.png',
|
|
weatherDropdown: 'step15-weather/weather-dropdown.png',
|
|
temperatureField: 'step15-weather/temperature-field.png',
|
|
nextButton: 'step15-weather/next-button.png',
|
|
},
|
|
16: {
|
|
stepIndicator: 'step16-race/race-options-indicator.png',
|
|
maxDriversField: 'step16-race/max-drivers-field.png',
|
|
rollingStartToggle: 'step16-race/rolling-start-toggle.png',
|
|
nextButton: 'step16-race/next-button.png',
|
|
},
|
|
17: {
|
|
stepIndicator: 'step17-team/team-driving-indicator.png',
|
|
teamDrivingToggle: 'step17-team/team-driving-toggle.png',
|
|
nextButton: 'step17-team/next-button.png',
|
|
},
|
|
18: {
|
|
stepIndicator: 'step18-conditions/track-conditions-indicator.png',
|
|
trackStateDropdown: 'step18-conditions/track-state-dropdown.png',
|
|
marblesToggle: 'step18-conditions/marbles-toggle.png',
|
|
// NOTE: No checkout button template - automation stops here for safety
|
|
},
|
|
},
|
|
} as const;
|
|
|
|
/**
|
|
* Complete template map for iRacing hosted session automation.
|
|
* Templates are organized by common elements and workflow steps.
|
|
*/
|
|
export const IRacingTemplateMap: IRacingTemplateMapType = {
|
|
templateBasePath: 'resources/templates/iracing',
|
|
|
|
common: {
|
|
loginIndicators: [
|
|
createImageTemplate(
|
|
'login-user-avatar',
|
|
TEMPLATE_PATHS.common.userAvatar,
|
|
'User avatar indicating logged-in state',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
createImageTemplate(
|
|
'login-member-badge',
|
|
TEMPLATE_PATHS.common.memberBadge,
|
|
'Member badge indicating logged-in state',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
],
|
|
logoutIndicators: [
|
|
createImageTemplate(
|
|
'logout-login-button',
|
|
TEMPLATE_PATHS.common.loginButton,
|
|
'Login button indicating logged-out state',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
],
|
|
navigation: {
|
|
next: createImageTemplate(
|
|
'nav-next',
|
|
TEMPLATE_PATHS.common.nextButton,
|
|
'Next button for wizard navigation',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
back: createImageTemplate(
|
|
'nav-back',
|
|
TEMPLATE_PATHS.common.backButton,
|
|
'Back button for wizard navigation',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
checkout: createImageTemplate(
|
|
'nav-checkout',
|
|
TEMPLATE_PATHS.common.checkoutButton,
|
|
'Checkout/submit button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
closeModal: createImageTemplate(
|
|
'nav-close-modal',
|
|
TEMPLATE_PATHS.common.closeModal,
|
|
'Close modal button',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
},
|
|
loading: [
|
|
createImageTemplate(
|
|
'loading-spinner',
|
|
TEMPLATE_PATHS.common.loadingSpinner,
|
|
'Loading spinner indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.LOW }
|
|
),
|
|
],
|
|
},
|
|
|
|
steps: {
|
|
// Step 1: LOGIN (handled externally, templates for detection only)
|
|
1: {
|
|
indicators: [
|
|
createImageTemplate(
|
|
'step1-login-form',
|
|
TEMPLATE_PATHS.steps[1].loginForm,
|
|
'Login form indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
],
|
|
buttons: {
|
|
submit: createImageTemplate(
|
|
'step1-submit',
|
|
TEMPLATE_PATHS.steps[1].submitButton,
|
|
'Login submit button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
},
|
|
fields: {
|
|
email: createImageTemplate(
|
|
'step1-email',
|
|
TEMPLATE_PATHS.steps[1].emailField,
|
|
'Email input field',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
password: createImageTemplate(
|
|
'step1-password',
|
|
TEMPLATE_PATHS.steps[1].passwordField,
|
|
'Password input field',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
},
|
|
},
|
|
|
|
// Step 2: HOSTED_RACING
|
|
// NOTE: Using DEBUG confidence (0.5) temporarily to test template matching
|
|
// after fixing the Retina scaling issue (DISPLAY_SCALE_FACTOR=1)
|
|
2: {
|
|
indicators: [
|
|
createImageTemplate(
|
|
'step2-hosted-tab',
|
|
TEMPLATE_PATHS.steps[2].hostedRacingTab,
|
|
'Hosted racing tab indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.DEBUG }
|
|
),
|
|
],
|
|
buttons: {
|
|
createRace: createImageTemplate(
|
|
'step2-create-race',
|
|
TEMPLATE_PATHS.steps[2].createRaceButton,
|
|
'Create a Race button',
|
|
{ confidence: DEFAULT_CONFIDENCE.DEBUG }
|
|
),
|
|
},
|
|
},
|
|
|
|
// Step 3: CREATE_RACE
|
|
3: {
|
|
indicators: [
|
|
createImageTemplate(
|
|
'step3-modal',
|
|
TEMPLATE_PATHS.steps[3].createRaceModal,
|
|
'Create race modal indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
],
|
|
buttons: {
|
|
confirm: createImageTemplate(
|
|
'step3-confirm',
|
|
TEMPLATE_PATHS.steps[3].confirmButton,
|
|
'Confirm create race button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
},
|
|
},
|
|
|
|
// Step 4: RACE_INFORMATION
|
|
4: {
|
|
indicators: [
|
|
createImageTemplate(
|
|
'step4-indicator',
|
|
TEMPLATE_PATHS.steps[4].stepIndicator,
|
|
'Race information step indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
],
|
|
buttons: {
|
|
next: createImageTemplate(
|
|
'step4-next',
|
|
TEMPLATE_PATHS.steps[4].nextButton,
|
|
'Next to Server Details button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
},
|
|
fields: {
|
|
sessionName: createImageTemplate(
|
|
'step4-session-name',
|
|
TEMPLATE_PATHS.steps[4].sessionNameField,
|
|
'Session name input field',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
password: createImageTemplate(
|
|
'step4-password',
|
|
TEMPLATE_PATHS.steps[4].passwordField,
|
|
'Session password input field',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
description: createImageTemplate(
|
|
'step4-description',
|
|
TEMPLATE_PATHS.steps[4].descriptionField,
|
|
'Session description textarea',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
},
|
|
},
|
|
|
|
// Step 5: SERVER_DETAILS
|
|
5: {
|
|
indicators: [
|
|
createImageTemplate(
|
|
'step5-indicator',
|
|
TEMPLATE_PATHS.steps[5].stepIndicator,
|
|
'Server details step indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
],
|
|
buttons: {
|
|
next: createImageTemplate(
|
|
'step5-next',
|
|
TEMPLATE_PATHS.steps[5].nextButton,
|
|
'Next to Admins button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
},
|
|
fields: {
|
|
region: createImageTemplate(
|
|
'step5-region',
|
|
TEMPLATE_PATHS.steps[5].regionDropdown,
|
|
'Server region dropdown',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
startNow: createImageTemplate(
|
|
'step5-start-now',
|
|
TEMPLATE_PATHS.steps[5].startNowToggle,
|
|
'Start now toggle',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
},
|
|
},
|
|
|
|
// Step 6: SET_ADMINS (modal step)
|
|
6: {
|
|
indicators: [
|
|
createImageTemplate(
|
|
'step6-indicator',
|
|
TEMPLATE_PATHS.steps[6].stepIndicator,
|
|
'Admins step indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
],
|
|
buttons: {
|
|
addAdmin: createImageTemplate(
|
|
'step6-add-admin',
|
|
TEMPLATE_PATHS.steps[6].addAdminButton,
|
|
'Add admin button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
next: createImageTemplate(
|
|
'step6-next',
|
|
TEMPLATE_PATHS.steps[6].nextButton,
|
|
'Next to Time Limits button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
},
|
|
modal: {
|
|
indicator: createImageTemplate(
|
|
'step6-modal',
|
|
TEMPLATE_PATHS.steps[6].adminModal,
|
|
'Add admin modal indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
closeButton: createImageTemplate(
|
|
'step6-modal-close',
|
|
TEMPLATE_PATHS.common.closeModal,
|
|
'Close admin modal button',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
searchInput: createImageTemplate(
|
|
'step6-search',
|
|
TEMPLATE_PATHS.steps[6].searchField,
|
|
'Admin search field',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
},
|
|
},
|
|
|
|
// Step 7: TIME_LIMITS
|
|
7: {
|
|
indicators: [
|
|
createImageTemplate(
|
|
'step7-indicator',
|
|
TEMPLATE_PATHS.steps[7].stepIndicator,
|
|
'Time limits step indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
],
|
|
buttons: {
|
|
next: createImageTemplate(
|
|
'step7-next',
|
|
TEMPLATE_PATHS.steps[7].nextButton,
|
|
'Next to Cars button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
},
|
|
fields: {
|
|
practice: createImageTemplate(
|
|
'step7-practice',
|
|
TEMPLATE_PATHS.steps[7].practiceField,
|
|
'Practice length field',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
qualify: createImageTemplate(
|
|
'step7-qualify',
|
|
TEMPLATE_PATHS.steps[7].qualifyField,
|
|
'Qualify length field',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
race: createImageTemplate(
|
|
'step7-race',
|
|
TEMPLATE_PATHS.steps[7].raceField,
|
|
'Race length field',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
},
|
|
},
|
|
|
|
// Step 8: SET_CARS
|
|
8: {
|
|
indicators: [
|
|
createImageTemplate(
|
|
'step8-indicator',
|
|
TEMPLATE_PATHS.steps[8].stepIndicator,
|
|
'Cars step indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
],
|
|
buttons: {
|
|
addCar: createImageTemplate(
|
|
'step8-add-car',
|
|
TEMPLATE_PATHS.steps[8].addCarButton,
|
|
'Add car button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
next: createImageTemplate(
|
|
'step8-next',
|
|
TEMPLATE_PATHS.steps[8].nextButton,
|
|
'Next to Track button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
},
|
|
},
|
|
|
|
// Step 9: ADD_CAR (modal step)
|
|
9: {
|
|
indicators: [
|
|
createImageTemplate(
|
|
'step9-modal',
|
|
TEMPLATE_PATHS.steps[9].carModal,
|
|
'Add car modal indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
],
|
|
buttons: {
|
|
select: createImageTemplate(
|
|
'step9-select',
|
|
TEMPLATE_PATHS.steps[9].selectButton,
|
|
'Select car button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
},
|
|
modal: {
|
|
indicator: createImageTemplate(
|
|
'step9-modal-indicator',
|
|
TEMPLATE_PATHS.steps[9].carModal,
|
|
'Car selection modal',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
closeButton: createImageTemplate(
|
|
'step9-close',
|
|
TEMPLATE_PATHS.steps[9].closeButton,
|
|
'Close car modal button',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
searchInput: createImageTemplate(
|
|
'step9-search',
|
|
TEMPLATE_PATHS.steps[9].searchField,
|
|
'Car search field',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
},
|
|
},
|
|
|
|
// Step 10: SET_CAR_CLASSES
|
|
10: {
|
|
indicators: [
|
|
createImageTemplate(
|
|
'step10-indicator',
|
|
TEMPLATE_PATHS.steps[10].stepIndicator,
|
|
'Car classes step indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
],
|
|
buttons: {
|
|
next: createImageTemplate(
|
|
'step10-next',
|
|
TEMPLATE_PATHS.steps[10].nextButton,
|
|
'Next to Track button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
},
|
|
fields: {
|
|
class: createImageTemplate(
|
|
'step10-class',
|
|
TEMPLATE_PATHS.steps[10].classDropdown,
|
|
'Car class dropdown',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
},
|
|
},
|
|
|
|
// Step 11: SET_TRACK
|
|
11: {
|
|
indicators: [
|
|
createImageTemplate(
|
|
'step11-indicator',
|
|
TEMPLATE_PATHS.steps[11].stepIndicator,
|
|
'Track step indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
],
|
|
buttons: {
|
|
addTrack: createImageTemplate(
|
|
'step11-add-track',
|
|
TEMPLATE_PATHS.steps[11].addTrackButton,
|
|
'Add track button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
next: createImageTemplate(
|
|
'step11-next',
|
|
TEMPLATE_PATHS.steps[11].nextButton,
|
|
'Next to Track Options button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
},
|
|
},
|
|
|
|
// Step 12: ADD_TRACK (modal step)
|
|
12: {
|
|
indicators: [
|
|
createImageTemplate(
|
|
'step12-modal',
|
|
TEMPLATE_PATHS.steps[12].trackModal,
|
|
'Add track modal indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
],
|
|
buttons: {
|
|
select: createImageTemplate(
|
|
'step12-select',
|
|
TEMPLATE_PATHS.steps[12].selectButton,
|
|
'Select track button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
},
|
|
modal: {
|
|
indicator: createImageTemplate(
|
|
'step12-modal-indicator',
|
|
TEMPLATE_PATHS.steps[12].trackModal,
|
|
'Track selection modal',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
closeButton: createImageTemplate(
|
|
'step12-close',
|
|
TEMPLATE_PATHS.steps[12].closeButton,
|
|
'Close track modal button',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
searchInput: createImageTemplate(
|
|
'step12-search',
|
|
TEMPLATE_PATHS.steps[12].searchField,
|
|
'Track search field',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
},
|
|
},
|
|
|
|
// Step 13: TRACK_OPTIONS
|
|
13: {
|
|
indicators: [
|
|
createImageTemplate(
|
|
'step13-indicator',
|
|
TEMPLATE_PATHS.steps[13].stepIndicator,
|
|
'Track options step indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
],
|
|
buttons: {
|
|
next: createImageTemplate(
|
|
'step13-next',
|
|
TEMPLATE_PATHS.steps[13].nextButton,
|
|
'Next to Time of Day button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
},
|
|
fields: {
|
|
config: createImageTemplate(
|
|
'step13-config',
|
|
TEMPLATE_PATHS.steps[13].configDropdown,
|
|
'Track configuration dropdown',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
},
|
|
},
|
|
|
|
// Step 14: TIME_OF_DAY
|
|
14: {
|
|
indicators: [
|
|
createImageTemplate(
|
|
'step14-indicator',
|
|
TEMPLATE_PATHS.steps[14].stepIndicator,
|
|
'Time of day step indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
],
|
|
buttons: {
|
|
next: createImageTemplate(
|
|
'step14-next',
|
|
TEMPLATE_PATHS.steps[14].nextButton,
|
|
'Next to Weather button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
},
|
|
fields: {
|
|
time: createImageTemplate(
|
|
'step14-time',
|
|
TEMPLATE_PATHS.steps[14].timeSlider,
|
|
'Time of day slider',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
date: createImageTemplate(
|
|
'step14-date',
|
|
TEMPLATE_PATHS.steps[14].datePicker,
|
|
'Date picker',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
},
|
|
},
|
|
|
|
// Step 15: WEATHER
|
|
15: {
|
|
indicators: [
|
|
createImageTemplate(
|
|
'step15-indicator',
|
|
TEMPLATE_PATHS.steps[15].stepIndicator,
|
|
'Weather step indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
],
|
|
buttons: {
|
|
next: createImageTemplate(
|
|
'step15-next',
|
|
TEMPLATE_PATHS.steps[15].nextButton,
|
|
'Next to Race Options button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
},
|
|
fields: {
|
|
weather: createImageTemplate(
|
|
'step15-weather',
|
|
TEMPLATE_PATHS.steps[15].weatherDropdown,
|
|
'Weather type dropdown',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
temperature: createImageTemplate(
|
|
'step15-temperature',
|
|
TEMPLATE_PATHS.steps[15].temperatureField,
|
|
'Temperature field',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
},
|
|
},
|
|
|
|
// Step 16: RACE_OPTIONS
|
|
16: {
|
|
indicators: [
|
|
createImageTemplate(
|
|
'step16-indicator',
|
|
TEMPLATE_PATHS.steps[16].stepIndicator,
|
|
'Race options step indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
],
|
|
buttons: {
|
|
next: createImageTemplate(
|
|
'step16-next',
|
|
TEMPLATE_PATHS.steps[16].nextButton,
|
|
'Next to Track Conditions button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
},
|
|
fields: {
|
|
maxDrivers: createImageTemplate(
|
|
'step16-max-drivers',
|
|
TEMPLATE_PATHS.steps[16].maxDriversField,
|
|
'Maximum drivers field',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
rollingStart: createImageTemplate(
|
|
'step16-rolling-start',
|
|
TEMPLATE_PATHS.steps[16].rollingStartToggle,
|
|
'Rolling start toggle',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
},
|
|
},
|
|
|
|
// Step 17: TEAM_DRIVING
|
|
17: {
|
|
indicators: [
|
|
createImageTemplate(
|
|
'step17-indicator',
|
|
TEMPLATE_PATHS.steps[17].stepIndicator,
|
|
'Team driving step indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
],
|
|
buttons: {
|
|
next: createImageTemplate(
|
|
'step17-next',
|
|
TEMPLATE_PATHS.steps[17].nextButton,
|
|
'Next to Track Conditions button',
|
|
{ confidence: DEFAULT_CONFIDENCE.HIGH }
|
|
),
|
|
},
|
|
fields: {
|
|
teamDriving: createImageTemplate(
|
|
'step17-team-driving',
|
|
TEMPLATE_PATHS.steps[17].teamDrivingToggle,
|
|
'Team driving toggle',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
},
|
|
},
|
|
|
|
// Step 18: TRACK_CONDITIONS (final step - no checkout for safety)
|
|
18: {
|
|
indicators: [
|
|
createImageTemplate(
|
|
'step18-indicator',
|
|
TEMPLATE_PATHS.steps[18].stepIndicator,
|
|
'Track conditions step indicator',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
],
|
|
buttons: {
|
|
// NOTE: No checkout button - automation intentionally stops here
|
|
// User must manually review and submit
|
|
},
|
|
fields: {
|
|
trackState: createImageTemplate(
|
|
'step18-track-state',
|
|
TEMPLATE_PATHS.steps[18].trackStateDropdown,
|
|
'Track state dropdown',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
marbles: createImageTemplate(
|
|
'step18-marbles',
|
|
TEMPLATE_PATHS.steps[18].marblesToggle,
|
|
'Marbles toggle',
|
|
{ confidence: DEFAULT_CONFIDENCE.STANDARD }
|
|
),
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Get templates for a specific step.
|
|
*/
|
|
export function getStepTemplates(stepId: number): StepTemplates | undefined {
|
|
return IRacingTemplateMap.steps[stepId];
|
|
}
|
|
|
|
/**
|
|
* Check if a step is a modal step (requires opening a secondary dialog).
|
|
*/
|
|
export function isModalStep(stepId: number): boolean {
|
|
const templates = IRacingTemplateMap.steps[stepId];
|
|
return templates?.modal !== undefined;
|
|
}
|
|
|
|
/**
|
|
* Get the step name for logging/debugging.
|
|
*/
|
|
export function getStepName(stepId: number): string {
|
|
const stepNames: Record<number, string> = {
|
|
1: 'LOGIN',
|
|
2: 'HOSTED_RACING',
|
|
3: 'CREATE_RACE',
|
|
4: 'RACE_INFORMATION',
|
|
5: 'SERVER_DETAILS',
|
|
6: 'SET_ADMINS',
|
|
7: 'TIME_LIMITS',
|
|
8: 'SET_CARS',
|
|
9: 'ADD_CAR',
|
|
10: 'SET_CAR_CLASSES',
|
|
11: 'SET_TRACK',
|
|
12: 'ADD_TRACK',
|
|
13: 'TRACK_OPTIONS',
|
|
14: 'TIME_OF_DAY',
|
|
15: 'WEATHER',
|
|
16: 'RACE_OPTIONS',
|
|
17: 'TEAM_DRIVING',
|
|
18: 'TRACK_CONDITIONS',
|
|
};
|
|
return stepNames[stepId] || `UNKNOWN_STEP_${stepId}`;
|
|
}
|
|
|
|
/**
|
|
* Get all login indicator templates.
|
|
*/
|
|
export function getLoginIndicators(): ImageTemplate[] {
|
|
return IRacingTemplateMap.common.loginIndicators;
|
|
}
|
|
|
|
/**
|
|
* Get all logout indicator templates.
|
|
*/
|
|
export function getLogoutIndicators(): ImageTemplate[] {
|
|
return IRacingTemplateMap.common.logoutIndicators;
|
|
} |