/** * Clinical Trial Matching Engine * * ╔═══════════════════════════════════════════════════════════════════════════════╗ * ║ CLINICAL TRIAL MATCHING - CONNECTING PATIENTS TO NOVEL THERAPIES ║ * ╠═══════════════════════════════════════════════════════════════════════════════╣ * ║ This module provides: ║ * ║ - Biomarker-to-trial mapping ║ * ║ - Eligibility criteria assessment ║ * ║ - Trial phase and mechanism matching ║ * ║ - Geographic and logistical feasibility ║ * ║ - Basket, umbrella, and platform trial navigation ║ * ╚═══════════════════════════════════════════════════════════════════════════════╝ */ // ═══════════════════════════════════════════════════════════════════════════════ // CLINICAL TRIAL DEFINITIONS // ═══════════════════════════════════════════════════════════════════════════════ export interface ClinicalTrial { nctId: string; title: string; phase: TrialPhase; status: TrialStatus; trialType: TrialType; sponsor: string; conditions: string[]; interventions: TrialIntervention[]; eligibilityCriteria: EligibilityCriteria; locations: TrialLocation[]; biomarkerRequirements: BiomarkerCriterion[]; primaryEndpoint: string; estimatedEnrollment: number; studyStartDate: string; estimatedCompletionDate: string; } export type TrialPhase = 'Early Phase 1' | 'Phase 1' | 'Phase 1/2' | 'Phase 2' | 'Phase 2/3' | 'Phase 3' | 'Phase 4'; export type TrialStatus = 'Recruiting' | 'Active, not recruiting' | 'Enrolling by invitation' | 'Not yet recruiting' | 'Completed' | 'Suspended' | 'Terminated' | 'Withdrawn'; export type TrialType = 'Interventional' | 'Basket' | 'Umbrella' | 'Platform' | 'Expanded Access'; export interface TrialIntervention { type: 'Drug' | 'Biological' | 'Device' | 'Radiation' | 'Procedure' | 'Combination'; name: string; mechanism: string; targetedPathway?: string; novelty: 'First-in-class' | 'Next-generation' | 'Combination' | 'New indication'; } export interface EligibilityCriteria { ageRange: { min: number; max: number }; gender: 'All' | 'Male' | 'Female'; performanceStatus: { scale: 'ECOG' | 'Karnofsky'; maxValue: number }; priorTherapyRequirements: PriorTherapyRequirement[]; organFunctionRequirements: OrganFunctionRequirement[]; exclusionCriteria: string[]; inclusionCriteria: string[]; } export interface PriorTherapyRequirement { requirement: 'Required' | 'Allowed' | 'Excluded'; therapyType: string; details: string; } export interface OrganFunctionRequirement { organ: string; parameter: string; requirement: string; } export interface TrialLocation { facility: string; city: string; state: string; country: string; status: 'Recruiting' | 'Not yet recruiting' | 'Completed'; contactName?: string; contactPhone?: string; contactEmail?: string; } export interface BiomarkerCriterion { biomarker: string; requirement: 'Required' | 'Preferred' | 'Excluded'; testMethod: string[]; details?: string; } // ═══════════════════════════════════════════════════════════════════════════════ // TRIAL MATCHING CRITERIA // ═══════════════════════════════════════════════════════════════════════════════ export interface PatientTrialProfile { cancerType: string; histology: string; stage: string; biomarkers: PatientBiomarker[]; priorTherapies: string[]; currentLine: number; age: number; performanceStatus: number; organFunction: OrganFunctionStatus; location: { country: string; state?: string; city?: string }; willingToTravel: boolean; maxTravelDistance?: number; // miles preferences: TrialPreferences; } export interface PatientBiomarker { name: string; status: 'Positive' | 'Negative' | 'Unknown'; value?: string | number; method?: string; } export interface OrganFunctionStatus { renalFunction: 'Normal' | 'Mild impairment' | 'Moderate impairment' | 'Severe impairment'; hepaticFunction: 'Normal' | 'Mild impairment' | 'Moderate impairment' | 'Severe impairment'; cardiacFunction: 'Normal' | 'Reduced' | 'Severely reduced'; bonemarrowFunction: 'Normal' | 'Reduced'; } export interface TrialPreferences { preferredPhases: TrialPhase[]; acceptPlaceboArm: boolean; preferLocalTrials: boolean; interestedMechanisms: string[]; } export interface TrialMatch { trial: ClinicalTrial; matchScore: number; matchDetails: MatchDetail[]; eligibilityStatus: 'Likely Eligible' | 'Possibly Eligible' | 'Likely Ineligible' | 'Need More Info'; barriers: string[]; nextSteps: string[]; } export interface MatchDetail { criterion: string; status: 'Met' | 'Not Met' | 'Partial' | 'Unknown'; explanation: string; } // ═══════════════════════════════════════════════════════════════════════════════ // TRIAL DATABASE (REPRESENTATIVE EXAMPLES) // ═══════════════════════════════════════════════════════════════════════════════ export const TRIAL_DATABASE: ClinicalTrial[] = [ // EGFR-mutant NSCLC Trials { nctId: 'NCT04816214', title: 'Amivantamab + Lazertinib vs Osimertinib in EGFR-Mutant NSCLC (MARIPOSA)', phase: 'Phase 3', status: 'Active, not recruiting', trialType: 'Interventional', sponsor: 'Janssen', conditions: ['NSCLC', 'EGFR-mutant'], interventions: [ { type: 'Combination', name: 'Amivantamab + Lazertinib', mechanism: 'EGFR-MET bispecific + EGFR TKI', novelty: 'Combination' } ], eligibilityCriteria: { ageRange: { min: 18, max: 99 }, gender: 'All', performanceStatus: { scale: 'ECOG', maxValue: 1 }, priorTherapyRequirements: [ { requirement: 'Excluded', therapyType: 'Prior EGFR TKI', details: 'No prior EGFR TKI for metastatic disease' } ], organFunctionRequirements: [ { organ: 'Renal', parameter: 'CrCl', requirement: '≥50 mL/min' }, { organ: 'Hepatic', parameter: 'AST/ALT', requirement: '≤3x ULN' } ], exclusionCriteria: ['Active brain metastases', 'Prior EGFR TKI', 'Interstitial lung disease'], inclusionCriteria: ['EGFR exon 19 del or L858R', 'Metastatic NSCLC', 'Treatment-naive'] }, locations: [ { facility: 'MD Anderson Cancer Center', city: 'Houston', state: 'TX', country: 'USA', status: 'Recruiting' }, { facility: 'Memorial Sloan Kettering', city: 'New York', state: 'NY', country: 'USA', status: 'Recruiting' } ], biomarkerRequirements: [ { biomarker: 'EGFR exon 19 del or L858R', requirement: 'Required', testMethod: ['NGS', 'PCR', 'ctDNA'] } ], primaryEndpoint: 'Progression-free survival', estimatedEnrollment: 1074, studyStartDate: '2021-05', estimatedCompletionDate: '2025-12' }, // HER2+ Breast Cancer Trials { nctId: 'NCT04784715', title: 'Trastuzumab Deruxtecan vs Physician Choice in HER2-low Breast Cancer (DESTINY-Breast06)', phase: 'Phase 3', status: 'Recruiting', trialType: 'Interventional', sponsor: 'Daiichi Sankyo', conditions: ['Breast Cancer', 'HER2-low'], interventions: [ { type: 'Biological', name: 'Trastuzumab Deruxtecan', mechanism: 'HER2-directed ADC', novelty: 'New indication' } ], eligibilityCriteria: { ageRange: { min: 18, max: 99 }, gender: 'All', performanceStatus: { scale: 'ECOG', maxValue: 1 }, priorTherapyRequirements: [ { requirement: 'Required', therapyType: 'Prior endocrine therapy', details: 'For HR+ patients' }, { requirement: 'Allowed', therapyType: 'Prior chemotherapy', details: '1-2 prior lines allowed' } ], organFunctionRequirements: [ { organ: 'Cardiac', parameter: 'LVEF', requirement: '≥50%' } ], exclusionCriteria: ['HER2-positive (IHC 3+)', 'History of ILD', 'Uncontrolled brain mets'], inclusionCriteria: ['HER2-low (IHC 1+ or 2+/FISH-)', 'HR+ or HR-', 'Metastatic breast cancer'] }, locations: [ { facility: 'Dana-Farber Cancer Institute', city: 'Boston', state: 'MA', country: 'USA', status: 'Recruiting' } ], biomarkerRequirements: [ { biomarker: 'HER2-low', requirement: 'Required', testMethod: ['IHC', 'FISH'] } ], primaryEndpoint: 'Progression-free survival', estimatedEnrollment: 850, studyStartDate: '2021-03', estimatedCompletionDate: '2026-06' }, // KRAS G12C Trials { nctId: 'NCT04685135', title: 'Sotorasib + Anti-EGFR in KRAS G12C CRC (CodeBreaK 300)', phase: 'Phase 3', status: 'Recruiting', trialType: 'Interventional', sponsor: 'Amgen', conditions: ['Colorectal Cancer', 'KRAS G12C'], interventions: [ { type: 'Combination', name: 'Sotorasib + Panitumumab', mechanism: 'KRAS G12C inhibitor + anti-EGFR', novelty: 'Combination' } ], eligibilityCriteria: { ageRange: { min: 18, max: 99 }, gender: 'All', performanceStatus: { scale: 'ECOG', maxValue: 1 }, priorTherapyRequirements: [ { requirement: 'Required', therapyType: 'Prior chemotherapy', details: '1-2 prior lines for metastatic disease' } ], organFunctionRequirements: [], exclusionCriteria: ['Prior KRAS G12C inhibitor', 'Symptomatic brain mets'], inclusionCriteria: ['KRAS G12C mutation', 'Metastatic CRC', 'Prior fluoropyrimidine, oxaliplatin, irinotecan'] }, locations: [ { facility: 'Multiple sites', city: 'Various', state: 'Various', country: 'USA', status: 'Recruiting' } ], biomarkerRequirements: [ { biomarker: 'KRAS G12C', requirement: 'Required', testMethod: ['NGS', 'PCR'] } ], primaryEndpoint: 'Overall survival', estimatedEnrollment: 160, studyStartDate: '2021-01', estimatedCompletionDate: '2025-06' }, // Basket Trial Example { nctId: 'NCT02465060', title: 'NCI-MATCH: Targeted Therapy Directed by Genetic Testing (Basket Trial)', phase: 'Phase 2', status: 'Active, not recruiting', trialType: 'Basket', sponsor: 'NCI', conditions: ['Solid Tumors', 'Lymphoma'], interventions: [ { type: 'Drug', name: 'Multiple targeted agents', mechanism: 'Various - based on molecular alteration', novelty: 'First-in-class' } ], eligibilityCriteria: { ageRange: { min: 18, max: 99 }, gender: 'All', performanceStatus: { scale: 'ECOG', maxValue: 1 }, priorTherapyRequirements: [ { requirement: 'Required', therapyType: 'Prior standard therapy', details: 'Progressed on standard options' } ], organFunctionRequirements: [], exclusionCriteria: ['Matched targeted therapy previously received'], inclusionCriteria: ['Actionable genomic alteration', 'No standard treatment options'] }, locations: [ { facility: 'ECOG-ACRIN Network Sites', city: 'Multiple', state: 'Multiple', country: 'USA', status: 'Recruiting' } ], biomarkerRequirements: [ { biomarker: 'Actionable mutation per NCI-MATCH arms', requirement: 'Required', testMethod: ['NGS'] } ], primaryEndpoint: 'Overall response rate', estimatedEnrollment: 6000, studyStartDate: '2015-08', estimatedCompletionDate: '2025-12' }, // Immunotherapy Combination { nctId: 'NCT03899610', title: 'Nivolumab + Relatlimab vs Nivolumab in Melanoma (RELATIVITY-047)', phase: 'Phase 3', status: 'Active, not recruiting', trialType: 'Interventional', sponsor: 'Bristol-Myers Squibb', conditions: ['Melanoma'], interventions: [ { type: 'Combination', name: 'Nivolumab + Relatlimab', mechanism: 'Anti-PD-1 + Anti-LAG-3', novelty: 'First-in-class' } ], eligibilityCriteria: { ageRange: { min: 18, max: 99 }, gender: 'All', performanceStatus: { scale: 'ECOG', maxValue: 1 }, priorTherapyRequirements: [ { requirement: 'Excluded', therapyType: 'Prior anti-PD-1/PD-L1', details: 'No prior checkpoint inhibitor' } ], organFunctionRequirements: [], exclusionCriteria: ['Active autoimmune disease', 'Prior immunotherapy'], inclusionCriteria: ['Unresectable or metastatic melanoma', 'Treatment-naive for metastatic disease'] }, locations: [ { facility: 'Multiple sites', city: 'Various', state: 'Various', country: 'USA', status: 'Recruiting' } ], biomarkerRequirements: [], primaryEndpoint: 'Progression-free survival', estimatedEnrollment: 714, studyStartDate: '2019-04', estimatedCompletionDate: '2024-12' }, // CAR-T Trial { nctId: 'NCT04503278', title: 'Cilta-cel vs Standard of Care in Multiple Myeloma (CARTITUDE-4)', phase: 'Phase 3', status: 'Active, not recruiting', trialType: 'Interventional', sponsor: 'Janssen', conditions: ['Multiple Myeloma'], interventions: [ { type: 'Biological', name: 'Ciltacabtagene autoleucel (Cilta-cel)', mechanism: 'BCMA-directed CAR-T', novelty: 'Next-generation' } ], eligibilityCriteria: { ageRange: { min: 18, max: 99 }, gender: 'All', performanceStatus: { scale: 'ECOG', maxValue: 1 }, priorTherapyRequirements: [ { requirement: 'Required', therapyType: 'Prior lenalidomide and PI', details: '1-3 prior lines including lenalidomide and a PI' } ], organFunctionRequirements: [ { organ: 'Cardiac', parameter: 'LVEF', requirement: '≥45%' }, { organ: 'Pulmonary', parameter: 'O2 sat', requirement: '≥92% on room air' } ], exclusionCriteria: ['Prior BCMA-targeted therapy', 'Active CNS involvement', 'Uncontrolled infection'], inclusionCriteria: ['Relapsed/refractory MM', 'Lenalidomide-refractory', '1-3 prior lines'] }, locations: [ { facility: 'Multiple academic centers', city: 'Various', state: 'Various', country: 'USA', status: 'Recruiting' } ], biomarkerRequirements: [], primaryEndpoint: 'Progression-free survival', estimatedEnrollment: 400, studyStartDate: '2020-06', estimatedCompletionDate: '2026-01' }, // Pediatric Trial { nctId: 'NCT03155620', title: 'Larotrectinib in Pediatric Solid Tumors with NTRK Fusion (SCOUT)', phase: 'Phase 1/2', status: 'Recruiting', trialType: 'Basket', sponsor: 'Bayer', conditions: ['Pediatric Solid Tumors', 'NTRK Fusion'], interventions: [ { type: 'Drug', name: 'Larotrectinib', mechanism: 'TRK inhibitor', novelty: 'First-in-class' } ], eligibilityCriteria: { ageRange: { min: 0, max: 21 }, gender: 'All', performanceStatus: { scale: 'Karnofsky', maxValue: 50 }, priorTherapyRequirements: [ { requirement: 'Allowed', therapyType: 'Prior therapy', details: 'No limit on prior therapies' } ], organFunctionRequirements: [], exclusionCriteria: ['Prior TRK inhibitor', 'Primary CNS tumor'], inclusionCriteria: ['NTRK gene fusion', 'Relapsed or refractory solid tumor', 'Age ≤21'] }, locations: [ { facility: "Children's Hospital of Philadelphia", city: 'Philadelphia', state: 'PA', country: 'USA', status: 'Recruiting' }, { facility: 'Texas Childrens Hospital', city: 'Houston', state: 'TX', country: 'USA', status: 'Recruiting' } ], biomarkerRequirements: [ { biomarker: 'NTRK1/2/3 fusion', requirement: 'Required', testMethod: ['NGS', 'FISH', 'IHC'] } ], primaryEndpoint: 'Overall response rate', estimatedEnrollment: 150, studyStartDate: '2017-07', estimatedCompletionDate: '2025-12' } ]; // ═══════════════════════════════════════════════════════════════════════════════ // TRIAL MATCHING ENGINE // ═══════════════════════════════════════════════════════════════════════════════ export class ClinicalTrialMatchingEngine { private trials: ClinicalTrial[] = TRIAL_DATABASE; findMatchingTrials(patient: PatientTrialProfile): TrialMatch[] { const matches: TrialMatch[] = []; for (const trial of this.trials) { if (trial.status === 'Withdrawn' || trial.status === 'Terminated') continue; const matchResult = this.evaluateTrialMatch(patient, trial); if (matchResult.matchScore > 0) { matches.push(matchResult); } } return matches.sort((a, b) => b.matchScore - a.matchScore); } private evaluateTrialMatch(patient: PatientTrialProfile, trial: ClinicalTrial): TrialMatch { const matchDetails: MatchDetail[] = []; const barriers: string[] = []; let score = 0; // Check cancer type match const cancerMatch = trial.conditions.some(c => c.toLowerCase().includes(patient.cancerType.toLowerCase()) || patient.cancerType.toLowerCase().includes(c.toLowerCase()) ); if (cancerMatch) { score += 30; matchDetails.push({ criterion: 'Cancer type', status: 'Met', explanation: 'Cancer type matches trial conditions' }); } else { matchDetails.push({ criterion: 'Cancer type', status: 'Not Met', explanation: 'Cancer type does not match' }); } // Check biomarker requirements for (const bioReq of trial.biomarkerRequirements) { const patientBiomarker = patient.biomarkers.find(b => b.name.toLowerCase().includes(bioReq.biomarker.toLowerCase()) || bioReq.biomarker.toLowerCase().includes(b.name.toLowerCase()) ); if (bioReq.requirement === 'Required') { if (patientBiomarker?.status === 'Positive') { score += 25; matchDetails.push({ criterion: `Biomarker: ${bioReq.biomarker}`, status: 'Met', explanation: 'Required biomarker is positive' }); } else if (patientBiomarker?.status === 'Negative') { score -= 50; barriers.push(`Required biomarker ${bioReq.biomarker} is negative`); matchDetails.push({ criterion: `Biomarker: ${bioReq.biomarker}`, status: 'Not Met', explanation: 'Required biomarker is negative' }); } else { matchDetails.push({ criterion: `Biomarker: ${bioReq.biomarker}`, status: 'Unknown', explanation: 'Biomarker status not tested' }); } } else if (bioReq.requirement === 'Excluded') { if (patientBiomarker?.status === 'Positive') { score -= 50; barriers.push(`Excluded biomarker ${bioReq.biomarker} is positive`); matchDetails.push({ criterion: `Biomarker: ${bioReq.biomarker}`, status: 'Not Met', explanation: 'Excluded biomarker is positive' }); } } } // Check age eligibility const ageElig = trial.eligibilityCriteria.ageRange; if (patient.age >= ageElig.min && patient.age <= ageElig.max) { score += 10; matchDetails.push({ criterion: 'Age', status: 'Met', explanation: `Age ${patient.age} within range ${ageElig.min}-${ageElig.max}` }); } else { barriers.push(`Age ${patient.age} outside eligible range ${ageElig.min}-${ageElig.max}`); matchDetails.push({ criterion: 'Age', status: 'Not Met', explanation: 'Age outside eligible range' }); } // Check performance status const psReq = trial.eligibilityCriteria.performanceStatus; if (patient.performanceStatus <= psReq.maxValue) { score += 10; matchDetails.push({ criterion: 'Performance status', status: 'Met', explanation: `PS ${patient.performanceStatus} meets requirement ≤${psReq.maxValue}` }); } else { barriers.push(`Performance status ${patient.performanceStatus} exceeds maximum ${psReq.maxValue}`); matchDetails.push({ criterion: 'Performance status', status: 'Not Met', explanation: 'Performance status too high' }); } // Check phase preference if (patient.preferences.preferredPhases.includes(trial.phase)) { score += 5; } // Check location const matchingLocation = trial.locations.find(loc => loc.country === patient.location.country && loc.status === 'Recruiting' ); if (matchingLocation) { score += 10; matchDetails.push({ criterion: 'Location', status: 'Met', explanation: `Trial available in ${matchingLocation.city}, ${matchingLocation.state}` }); } else if (patient.willingToTravel) { score += 5; matchDetails.push({ criterion: 'Location', status: 'Partial', explanation: 'Patient willing to travel' }); } else { barriers.push('No recruiting sites in patient location'); matchDetails.push({ criterion: 'Location', status: 'Not Met', explanation: 'No local sites; travel required' }); } // Determine eligibility status let eligibilityStatus: TrialMatch['eligibilityStatus']; if (barriers.length === 0 && score > 50) { eligibilityStatus = 'Likely Eligible'; } else if (barriers.length === 0) { eligibilityStatus = 'Need More Info'; } else if (barriers.some(b => b.includes('Required biomarker') || b.includes('Age'))) { eligibilityStatus = 'Likely Ineligible'; } else { eligibilityStatus = 'Possibly Eligible'; } // Generate next steps const nextSteps: string[] = []; if (eligibilityStatus === 'Likely Eligible' || eligibilityStatus === 'Possibly Eligible') { nextSteps.push('Discuss with oncologist'); nextSteps.push(`Contact trial site: ${trial.locations[0]?.facility || 'See ClinicalTrials.gov'}`); nextSteps.push(`Search ClinicalTrials.gov for NCT: ${trial.nctId}`); } if (matchDetails.some(m => m.status === 'Unknown')) { nextSteps.push('Complete biomarker testing'); } return { trial, matchScore: Math.max(0, score), matchDetails, eligibilityStatus, barriers, nextSteps }; } findTrialsByBiomarker(biomarker: string): ClinicalTrial[] { return this.trials.filter(trial => trial.biomarkerRequirements.some(b => b.biomarker.toLowerCase().includes(biomarker.toLowerCase()) ) ); } findTrialsByMechanism(mechanism: string): ClinicalTrial[] { return this.trials.filter(trial => trial.interventions.some(i => i.mechanism.toLowerCase().includes(mechanism.toLowerCase()) ) ); } findBasketTrials(): ClinicalTrial[] { return this.trials.filter(trial => trial.trialType === 'Basket'); } findPediatricTrials(): ClinicalTrial[] { return this.trials.filter(trial => trial.eligibilityCriteria.ageRange.min < 18 || trial.conditions.some(c => c.toLowerCase().includes('pediatric')) ); } getTrialById(nctId: string): ClinicalTrial | undefined { return this.trials.find(t => t.nctId === nctId); } generateTrialSearchStrategy(patient: PatientTrialProfile): { searchTerms: string[]; recommendedDatabases: string[]; searchTips: string[]; } { const searchTerms: string[] = [ patient.cancerType, patient.histology, ...patient.biomarkers.filter(b => b.status === 'Positive').map(b => b.name) ]; return { searchTerms, recommendedDatabases: [ 'ClinicalTrials.gov (clinicaltrials.gov)', 'NCI Cancer Clinical Trials (cancer.gov/clinicaltrials)', 'TrialMatch (lls.org/support/information-specialists)', 'EmergingMed Navigator (emergingmed.com)' ], searchTips: [ 'Use condition + biomarker for targeted searches', 'Filter by "Recruiting" status', 'Check Phase 1/2 trials for novel mechanisms', 'Consider basket trials if you have an actionable mutation', 'Contact trial coordinators directly for eligibility questions' ] }; } } // Export singleton export const clinicalTrialMatchingEngine = new ClinicalTrialMatchingEngine();