Admin: Full Access
Live Demo — Real Federal API Data

FormularyEdge
AI-Powered Formulary Decision Support

Class reviews in minutes, not days. Real-time safety data from FAERS, head-to-head comparisons, and P&T committee-ready analytics powered by live federal APIs.

0 Drug Classes
0 Drugs Compared
0 Federal APIs
0 AEs Cross-Referenced

Select a Therapeutic Class

Compare Drugs

Safety Heatmap by Drug Class

Quick Drug Monograph

Generate a P&T committee summary card for any drug. Combines data from 5 federal APIs into a single view.

Pro Features

Included in FormularyEdge Pro ($299/mo)
P&T Monograph Generator
Full AMCP-format drug monograph from 7 federal APIs. Classification, approval history, indications, boxed warnings, top 15 AEs with demographics, active trials, recall history, formulation count, and editable committee recommendation. Saves 6-12 hours per drug.
Pro Feature
Tier Placement Scorecard
Rank every drug in a class by a composite "formulary attractiveness" score built from safety (FAERS), evidence (clinical trials), availability (NDC formulations), and risk (recall history). Auto-generates tier recommendations that mirror real P&T committee logic.
Pro Feature
Export AMCP Dossier
Generate a complete AMCP-format dossier with drug classification, clinical evidence summary, full safety profile from FAERS, pharmacoeconomic framework, and appendices. Print-ready layout and CSV data export.
Pro Feature
Formulary Recommendation Engine
Deterministic 5-dimension scoring engine: Safety (inverse AE rate weighted by seriousness), Evidence (clinical trials weighted by phase), Availability (NDC formulation count), Risk (inverse recall count), Market Maturity (years since FDA approval). Generates tier recommendations with visual radar chart and full score breakdown.
Pro Feature

How FormularyEdge Works

Automating the data layer so P&T committees can focus on clinical judgment, not data gathering.

The Problem

P&T committees review 20-50 drugs per meeting. Each drug requires safety profile compilation, class-wide comparative analysis, and tier recommendations.

3+ days per review

Our Solution

FormularyEdge queries 6 federal APIs simultaneously, cross-references adverse event data, clinical trials, recalls, and formulations in real time.

15 minutes

The Result

Committee-ready class reviews with safety heatmaps, head-to-head comparisons, recall flags, and monograph summaries generated from live data.

97% time saved

Data Pipeline

openFDA FAERS
openFDA Labels
openFDA NDC
FormularyEdge
Analysis Engine
Class Reviews
Safety Heatmaps
Monographs
+ NLM RxNorm/RxClass + ClinicalTrials.gov v2 + DailyMed SPL

Who Uses FormularyEdge

Formulary Analysts

Complete class reviews in 15 minutes instead of 3 days. Pre-built safety comparisons for every drug under review.

P&T Committees

Get pre-built safety comparisons, recall alerts, and class-wide heatmaps for every drug on the meeting agenda.

Health Plans

Benchmark tier placement against CMS Part D market data. Identify formulary gaps and optimization opportunities.

Pharmacovigilance Teams

Monitor class-wide safety signals with cross-drug heatmaps. Early detection of emerging AE patterns.

Free vs Pro

Feature Free Demo Pro ($299/mo)
Drug Class Reviews
Head-to-Head Comparisons
Safety Heatmaps
Quick Monographs
AMCP-Format Monograph Generator
CMS Part D Tier Benchmarking
Class-Wide Trend Analysis
PDF/DOCX/XLSX Export
AI Tier Recommendations
Custom Drug Lists
API Access
Dedicated Support

Ready for Full Formulary Intelligence?

Unlock class reviews, P&T monographs, CMS benchmarking, and AI-powered recommendations with FormularyEdge Pro.

'); w.document.write('

' + capitalize(drugName) + ' - P&T Committee Monograph

'); w.document.write('

Generated by FormularyEdge | ' + new Date().toLocaleDateString() + ' | Data sources: openFDA, RxClass, ClinicalTrials.gov

'); w.document.write(content.innerHTML.replace(/class="[^"]*"/g, '').replace(/style="[^"]*"/g, '').replace(/onclick="[^"]*"/g, '')); w.document.write(' '); w.document.close(); }; /* ================================================================ PRO FEATURE 2: TIER PLACEMENT SCORECARD ================================================================ */ window.runProCMS = function() { var classId = document.getElementById('pro-cms-select').value; if (!classId) return; var el = document.getElementById('pro-cms-results'); showLoading(el, 'Building tier scorecard for ' + (CLASS_NAMES[classId] || classId) + '...', ['RxClass', 'openFDA FAERS', 'openFDA NDC', 'ClinicalTrials.gov', 'openFDA Enforcement', 'openFDA Drugs@FDA']); getClassMembers(classId).then(function(members) { if (!members.length) { showError(el, 'No drugs found.'); return; } var promises = members.map(function(drug) { return Promise.all([ getDrugAECount(drug.name), getDrugSeriousAEPct(drug.name), getDrugTrials(drug.name), getDrugNDCCount(drug.name), getDrugRecalls(drug.name), getDrugApprovalYear(drug.name) ]).then(function(r) { return { name: drug.name, aeTotal: r[0], seriousAE: r[1], trials: r[2], ndcCount: r[3], recalls: r[4], approvalYear: r[5] }; }); }); return Promise.all(promises); }).then(function(drugs) { if (!drugs) return; renderProCMS(drugs, CLASS_NAMES[classId] || classId); }).catch(function(err) { showError(el, 'Scorecard failed: ' + err.message); }); }; function renderProCMS(drugs, className) { var el = document.getElementById('pro-cms-results'); var maxAE = Math.max.apply(null, drugs.map(function(d){return d.aeTotal}).concat([1])); var maxTrials = Math.max.apply(null, drugs.map(function(d){return d.trials}).concat([1])); var maxNDC = Math.max.apply(null, drugs.map(function(d){return d.ndcCount}).concat([1])); var maxRecalls = Math.max.apply(null, drugs.map(function(d){return d.recalls}).concat([1])); drugs.forEach(function(d) { d.safetyScore = maxAE > 0 ? Math.round((1 - d.aeTotal / maxAE) * 100) : 50; d.seriousPenalty = d.aeTotal > 0 ? Math.round((d.seriousAE / d.aeTotal) * 30) : 0; d.safetyScore = Math.max(5, d.safetyScore - d.seriousPenalty); d.evidenceScore = maxTrials > 0 ? Math.round((d.trials / maxTrials) * 100) : 10; d.availScore = maxNDC > 0 ? Math.round((d.ndcCount / maxNDC) * 100) : 10; d.riskScore = maxRecalls > 0 ? Math.round((1 - d.recalls / (maxRecalls + 1)) * 100) : 95; d.overall = Math.round(d.safetyScore * 0.35 + d.evidenceScore * 0.25 + d.availScore * 0.20 + d.riskScore * 0.20); }); drugs.sort(function(a, b) { return b.overall - a.overall; }); var html = '

' + className + ' Tier Scorecard' + srcTip('Composite score: Safety 35% (inverse AE count with seriousness penalty), Evidence 25% (clinical trials), Availability 20% (NDC formulations), Risk 20% (inverse recalls). All from live federal APIs.') + '

'; html += '
'; html += ''; html += ''; drugs.forEach(function(d, i) { var tierNum = i < Math.ceil(drugs.length * 0.3) ? 1 : i < Math.ceil(drugs.length * 0.6) ? 2 : i < Math.ceil(drugs.length * 0.85) ? 3 : 4; var tierLabel = tierNum === 1 ? 'Preferred' : tierNum === 2 ? 'Preferred Alt' : tierNum === 3 ? 'Non-Preferred' : 'Specialty'; var tierClass = 'tier-rec-' + tierNum; var barColor = d.overall >= 70 ? 'var(--green-400)' : d.overall >= 45 ? 'var(--amber-400)' : 'var(--red-400)'; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; }); html += '
RankDrugSafetyEvidenceAvailabilityRiskOverallTier Rec
#' + (i + 1) + '' + capitalize(d.name) + '' + d.safetyScore + '' + d.evidenceScore + '' + d.availScore + '' + d.riskScore + '
' + d.overall + '
T' + tierNum + ' ' + tierLabel + '
'; html += dataAbout('Formulary attractiveness scorecard for each drug in the class. Scores are normalized to the class maximum. Tier recommendations are automatically generated based on rank position.','Safety: openFDA FAERS (inverse AE count with seriousness weighting). Evidence: ClinicalTrials.gov (recruiting trial count). Availability: openFDA NDC (formulation count). Risk: openFDA Enforcement (inverse recall count).','Scores are relative within this class and recalculate each time. They do not account for cost, patient preference, or clinical guidelines. Tier recommendations are algorithmic suggestions, not clinical guidance.'); el.innerHTML = html; } /* ================================================================ PRO FEATURE 3: CLASS-WIDE TREND ANALYSIS Fetches FAERS count=receivedate for each drug, aggregates by year. ================================================================ */ function getDrugAETrend(drugName) { var url = 'https://api.fda.gov/drug/event.json?search=patient.drug.medicinalproduct:"' + encodeURIComponent(drugName) + '"&count=receivedate'; return fetchJSON(url).then(function(data) { return (data.results) ? data.results : []; }).catch(function() { return []; }); } window.runProTrends = function() { var classId = document.getElementById('pro-trends-select').value; if (!classId) return; var el = document.getElementById('pro-trends-results'); showLoading(el, 'Fetching AE reporting trends for every drug in ' + (CLASS_NAMES[classId] || classId) + '...', ['RxClass', 'openFDA FAERS receivedate']); getClassMembers(classId).then(function(members) { if (!members.length) { showError(el, 'No drugs found.'); return; } var promises = members.map(function(drug) { return getDrugAETrend(drug.name).then(function(trend) { return { name: drug.name, trend: trend }; }); }); return Promise.all(promises); }).then(function(drugs) { if (!drugs) return; renderProTrends(drugs, CLASS_NAMES[classId] || classId); }).catch(function(err) { showError(el, 'Trend analysis failed: ' + err.message); }); }; function renderProTrends(drugs, className) { var el = document.getElementById('pro-trends-results'); // Aggregate daily data into years (last 8 years) var currentYear = new Date().getFullYear(); var startYear = currentYear - 7; var years = []; for (var y = startYear; y <= currentYear; y++) years.push(y); var drugYearly = drugs.map(function(d) { var yearly = {}; years.forEach(function(y) { yearly[y] = 0; }); d.trend.forEach(function(pt) { var yr = parseInt(String(pt.time).substring(0, 4)); if (yr >= startYear && yr <= currentYear) yearly[yr] += pt.count; }); // YoY change for most recent complete year var recentYear = currentYear - 1; var prevYear = currentYear - 2; var yoyPct = yearly[prevYear] > 0 ? ((yearly[recentYear] - yearly[prevYear]) / yearly[prevYear] * 100).toFixed(1) : 0; return { name: d.name, yearly: yearly, yoy: parseFloat(yoyPct) }; }); // Find global max for chart scaling var globalMax = 1; drugYearly.forEach(function(d) { years.forEach(function(y) { if (d.yearly[y] > globalMax) globalMax = d.yearly[y]; }); }); // Build SVG line chart var svgW = 800, svgH = 350, padL = 60, padR = 20, padT = 20, padB = 40; var chartW = svgW - padL - padR; var chartH = svgH - padT - padB; var svg = ''; // Grid lines for (var g = 0; g <= 4; g++) { var gy = padT + (chartH / 4) * g; var gVal = Math.round(globalMax * (1 - g / 4)); svg += ''; svg += '' + (gVal >= 1000 ? Math.round(gVal/1000) + 'K' : gVal) + ''; } // X-axis labels years.forEach(function(y, i) { var x = padL + (chartW / (years.length - 1)) * i; svg += '' + y + ''; }); // Drug lines drugYearly.forEach(function(d, di) { var color = DRUG_COLORS[di % DRUG_COLORS.length]; var points = []; years.forEach(function(y, i) { var x = padL + (chartW / (years.length - 1)) * i; var yPos = padT + chartH - (globalMax > 0 ? (d.yearly[y] / globalMax) * chartH : 0); points.push(x + ',' + yPos); }); svg += ''; // Dots years.forEach(function(y, i) { var x = padL + (chartW / (years.length - 1)) * i; var yPos = padT + chartH - (globalMax > 0 ? (d.yearly[y] / globalMax) * chartH : 0); svg += '' + capitalize(d.name) + ' ' + y + ': ' + fmt(d.yearly[y]) + ' reports'; }); }); svg += ''; var html = '

' + className + ' AE Reporting Trends (' + startYear + '-' + currentYear + ')' + srcTip('Source: openFDA FAERS drug/event.json count=receivedate. Daily data aggregated to yearly totals.') + '

'; html += '
' + svg + '
'; // Legend html += '
'; drugYearly.forEach(function(d, di) { html += '
' + capitalize(d.name) + '
'; }); html += '
'; // Summary cards with trend arrows html += '

Year-over-Year Signal Detection

'; html += '
'; drugYearly.sort(function(a, b) { return b.yoy - a.yoy; }); drugYearly.forEach(function(d, di) { var arrow = d.yoy > 30 ? '' : d.yoy < -10 ? '' : ''; var pctColor = d.yoy > 30 ? 'color:var(--red-400)' : d.yoy < -10 ? 'color:var(--green-400)' : 'color:var(--navy-400)'; var flag = d.yoy > 30 ? ' SIGNAL' : ''; html += '
' + arrow + '
' + capitalize(d.name) + flag + '
'; html += '
' + (d.yoy > 0 ? '+' : '') + d.yoy + '% YoY
'; }); html += '
'; html += dataAbout('Yearly FAERS adverse event report counts for each drug in the class, with year-over-year change detection. Drugs with >30% YoY increase are flagged as potential safety signals.','openFDA FAERS drug/event.json with count=receivedate, aggregated from daily to yearly.','Report volume does not equal risk. Increases may reflect growing prescribing volume, media attention, or reporting campaigns rather than new safety issues. YoY calculations use the two most recent complete calendar years.'); el.innerHTML = html; } /* ================================================================ PRO FEATURE 4: EXPORT AMCP DOSSIER ================================================================ */ var lastDossierData = null; window.runProExport = function() { var drugName = (document.getElementById('pro-export-drug').value || '').trim().toLowerCase(); if (!drugName) return; var el = document.getElementById('pro-export-results'); showLoading(el, 'Compiling AMCP dossier for ' + capitalize(drugName) + '...', ['openFDA Labels', 'openFDA FAERS', 'openFDA Drugs@FDA', 'RxClass', 'ClinicalTrials.gov', 'openFDA Enforcement', 'openFDA NDC']); Promise.all([ getDrugLabel(drugName), getDrugTopAEs(drugName, 15), getDrugAECount(drugName), getDrugSeriousAEPct(drugName), getDrugMOA(drugName), getDrugTrials(drugName), getDrugNDCCount(drugName), getDrugRecallDetails(drugName), getDrugApprovalYear(drugName), getDrugDemographics(drugName) ]).then(function(res) { lastDossierData = { drugName: drugName, label: res[0], topAEs: res[1], totalAE: res[2], seriousAE: res[3], classes: res[4], trials: res[5], ndcCount: res[6], recallDetails: res[7], approvalYear: res[8], demographics: res[9] }; renderProExport(lastDossierData); }).catch(function(err) { showError(el, 'Dossier generation failed: ' + err.message); }); }; function renderProExport(d) { var el = document.getElementById('pro-export-results'); var label = d.label; var brandName = (label && label.openfda && label.openfda.brand_name) ? label.openfda.brand_name.slice(0,3).join(', ') : 'N/A'; var mfr = (label && label.openfda && label.openfda.manufacturer_name) ? label.openfda.manufacturer_name[0] : 'N/A'; var pharmClass = (label && label.openfda && label.openfda.pharm_class_epc) ? label.openfda.pharm_class_epc.join(', ') : 'N/A'; var indications = (label && label.indications_and_usage && label.indications_and_usage[0]) ? label.indications_and_usage[0].substring(0,600) : 'Not available'; var seriousPct = d.totalAE > 0 ? ((d.seriousAE / d.totalAE) * 100).toFixed(1) : '0'; var html = '

AMCP Dossier: ' + capitalize(d.drugName) + '

'; html += '
'; html += '

Section 1: Drug Classification & Identification

'; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; html += '
Generic Name' + capitalize(d.drugName) + '
Brand Name(s)' + escHtml(brandName) + '
Manufacturer' + escHtml(mfr) + '
Pharmacologic Class' + escHtml(pharmClass) + '
ATC Classification' + (d.classes.length ? escHtml(d.classes.join(', ')) : 'N/A') + '
FDA Approval Year' + (d.approvalYear || 'N/A') + '
Dosage Forms (NDC)' + fmt(d.ndcCount) + ' registered formulations
'; html += '

Section 2: Clinical Evidence Summary

'; html += '

Indications: ' + escHtml(indications) + '

'; html += '

Active Clinical Trials: ' + d.trials + ' currently recruiting (ClinicalTrials.gov)

'; html += '

Section 3: Safety Profile (FAERS)

'; html += '

Total AE Reports: ' + fmt(d.totalAE) + ' | Serious: ' + fmt(d.seriousAE) + ' (' + seriousPct + '%)

'; html += ''; d.topAEs.forEach(function(ae, i) { html += ''; }); html += '
RankAdverse Event (MedDRA PT)Report Count
' + (i+1) + '' + capitalize(ae.term) + '' + fmt(ae.count) + '
'; html += '

Section 4: Pharmacoeconomic Summary

'; html += '

Cost-effectiveness analysis framework: Formulary analysts should evaluate acquisition cost per unit, average wholesale price (AWP), and total cost of care including monitoring requirements. This section should be populated with institution-specific pricing data.

'; html += ''; html += ''; html += ''; html += ''; html += '
Generic Availability' + (d.approvalYear && d.approvalYear < 2010 ? 'Yes (patent likely expired)' : d.approvalYear && d.approvalYear < 2020 ? 'Possible' : 'Likely branded only') + '
Formulation Count' + fmt(d.ndcCount) + ' (higher = more competitive market)
Recall History' + d.recallDetails.length + ' enforcement actions
'; html += '

Section 5: Recall & Safety Appendix

'; if (d.recallDetails.length > 0) { html += ''; d.recallDetails.forEach(function(r) { html += ''; }); html += '
DateClassFirmReason
' + (r.recall_initiation_date||'N/A') + '' + (r.classification||'N/A') + '' + escHtml(r.recalling_firm||'N/A') + '' + escHtml((r.reason_for_recall||'N/A').substring(0,150)) + '
'; } else { html += '

No FDA recall/enforcement actions found.

'; } html += '
'; // Export buttons html += '
'; html += ''; html += ''; html += '
'; el.innerHTML = html; } window.printDossier = function(drugName) { var content = document.getElementById('dossier-content'); if (!content) return; var w = window.open('', '_blank'); '); w.document.write('

AMCP Format Dossier

' + capitalize(drugName) + '

Prepared by FormularyEdge | ' + new Date().toLocaleDateString() + ' | Data: openFDA, RxClass, ClinicalTrials.gov

'); w.document.write(content.innerHTML.replace(/class="[^"]*"/g, '').replace(/style="[^"]*"/g, '')); w.document.write(' '); w.document.close(); }; window.exportDossierCSV = function() { if (!lastDossierData) return; var d = lastDossierData; var rows = [['Field', 'Value']]; rows.push(['Drug Name', capitalize(d.drugName)]); rows.push(['Approval Year', d.approvalYear || 'N/A']); rows.push(['NDC Count', d.ndcCount]); rows.push(['Active Trials', d.trials]); rows.push(['Total AE Reports', d.totalAE]); rows.push(['Serious AE Reports', d.seriousAE]); rows.push(['Recalls', d.recallDetails.length]); rows.push(['ATC Classes', d.classes.join('; ')]); rows.push([]); rows.push(['Rank', 'Adverse Event', 'Count']); d.topAEs.forEach(function(ae, i) { rows.push([i+1, ae.term, ae.count]); }); rows.push([]); rows.push(['Recall Date', 'Classification', 'Firm', 'Reason']); d.recallDetails.forEach(function(r) { rows.push([r.recall_initiation_date||'', r.classification||'', r.recalling_firm||'', (r.reason_for_recall||'').replace(/,/g, ';')]); }); var csv = rows.map(function(r) { return r.join(','); }).join('\n'); var blob = new Blob([csv], { type: 'text/csv' }); var a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = capitalize(d.drugName) + '_AMCP_Dossier.csv'; a.click(); }; /* ================================================================ PRO FEATURE 5: FORMULARY RECOMMENDATION ENGINE Deterministic 5-dimension scoring with radar chart. ================================================================ */ window.runProRecommend = function() { var classId = document.getElementById('pro-rec-select').value; if (!classId) return; var el = document.getElementById('pro-rec-results'); showLoading(el, 'Computing recommendation scores for ' + (CLASS_NAMES[classId] || classId) + '...', ['RxClass', 'openFDA FAERS', 'ClinicalTrials.gov', 'openFDA NDC', 'openFDA Enforcement', 'openFDA Drugs@FDA']); getClassMembers(classId).then(function(members) { if (!members.length) { showError(el, 'No drugs found.'); return; } var promises = members.map(function(drug) { return Promise.all([ getDrugAECount(drug.name), getDrugSeriousAEPct(drug.name), getDrugTrials(drug.name), getDrugNDCCount(drug.name), getDrugRecalls(drug.name), getDrugApprovalYear(drug.name) ]).then(function(r) { return { name: drug.name, aeTotal: r[0], seriousAE: r[1], trials: r[2], ndcCount: r[3], recalls: r[4], approvalYear: r[5] }; }); }); return Promise.all(promises); }).then(function(drugs) { if (!drugs) return; renderProRecommend(drugs, CLASS_NAMES[classId] || classId); }).catch(function(err) { showError(el, 'Recommendation engine failed: ' + err.message); }); }; function renderProRecommend(drugs, className) { var el = document.getElementById('pro-rec-results'); var currentYear = new Date().getFullYear(); var maxAE = Math.max.apply(null, drugs.map(function(d){return d.aeTotal}).concat([1])); var maxTrials = Math.max.apply(null, drugs.map(function(d){return d.trials}).concat([1])); var maxNDC = Math.max.apply(null, drugs.map(function(d){return d.ndcCount}).concat([1])); var maxRecalls = Math.max.apply(null, drugs.map(function(d){return d.recalls}).concat([1])); var maxAge = Math.max.apply(null, drugs.map(function(d){return d.approvalYear ? currentYear - d.approvalYear : 0}).concat([1])); drugs.forEach(function(d) { // Safety: inverse AE weighted by seriousness var aeNorm = maxAE > 0 ? d.aeTotal / maxAE : 0; var seriousRatio = d.aeTotal > 0 ? d.seriousAE / d.aeTotal : 0; d.dim_safety = Math.round(Math.max(5, (1 - aeNorm * (1 + seriousRatio * 0.5)) * 100)); // Evidence: trial count (Phase 3/4 would be weighted more but API doesn't reliably filter) d.dim_evidence = maxTrials > 0 ? Math.round(Math.max(5, (d.trials / maxTrials) * 100)) : 10; // Availability: NDC count d.dim_availability = maxNDC > 0 ? Math.round(Math.max(5, (d.ndcCount / maxNDC) * 100)) : 10; // Risk: inverse recalls d.dim_risk = Math.round(Math.max(5, (1 - d.recalls / (maxRecalls + 1)) * 100)); // Market Maturity: years since approval var age = d.approvalYear ? currentYear - d.approvalYear : 0; d.dim_maturity = maxAge > 0 ? Math.round(Math.max(5, (age / maxAge) * 100)) : 10; // Weighted composite d.composite = Math.round(d.dim_safety * 0.30 + d.dim_evidence * 0.20 + d.dim_availability * 0.15 + d.dim_risk * 0.20 + d.dim_maturity * 0.15); }); drugs.sort(function(a, b) { return b.composite - a.composite; }); var preferred = drugs[0]; var altPreferred = drugs.length > 1 ? drugs[1] : null; var html = ''; // Recommendation verdict html += '
'; html += '
Recommended Preferred Agent: ' + capitalize(preferred.name) + '
'; html += '
Based on safety, evidence, availability, risk, and market maturity scores, ' + capitalize(preferred.name) + ' is the recommended preferred agent for the ' + className + ' class.' + (altPreferred ? ' ' + capitalize(altPreferred.name) + ' is recommended as the non-preferred alternative.' : '') + '
'; // Score cards for top pick html += '
'; var dims = [ { label: 'Safety', val: preferred.dim_safety, color: 'var(--green-400)' }, { label: 'Evidence', val: preferred.dim_evidence, color: 'var(--blue-400)' }, { label: 'Availability', val: preferred.dim_availability, color: 'var(--purple-400)' }, { label: 'Risk', val: preferred.dim_risk, color: 'var(--amber-400)' }, { label: 'Maturity', val: preferred.dim_maturity, color: 'var(--teal-400)' } ]; dims.forEach(function(dim) { html += '
' + dim.val + '
' + dim.label + '
'; }); html += '
'; // Radar chart for top 3 var topDrugs = drugs.slice(0, Math.min(3, drugs.length)); html += '
' + buildRecRadarSVG(topDrugs) + '
'; html += '
'; var rColors = ['var(--teal-400)', 'var(--blue-400)', 'var(--purple-400)']; topDrugs.forEach(function(d, i) { html += '
' + capitalize(d.name) + ' (Score: ' + d.composite + ')
'; }); html += '
'; // Full ranking breakdown html += '

Full Class Ranking

'; html += '
'; drugs.forEach(function(d, i) { var barColor = i === 0 ? 'var(--green-400)' : i === 1 ? 'var(--blue-400)' : i < drugs.length * 0.6 ? 'var(--amber-400)' : 'var(--red-400)'; var tierLabel = i === 0 ? 'Preferred' : i === 1 ? 'Alt Preferred' : i < Math.ceil(drugs.length * 0.6) ? 'Non-Preferred' : 'Specialty/Restrict'; html += '
'; html += '
#' + (i+1) + '
'; html += '
' + capitalize(d.name) + '
'; html += '
'; html += '
' + d.composite + '
'; html += '' + tierLabel + ''; html += '
'; }); html += '
'; html += '
'; html += dataAbout('5-dimension formulary recommendation scoring: Safety (30% weight, inverse AE count with seriousness penalty), Evidence (20%, active trial count), Availability (15%, NDC formulation count), Risk (20%, inverse recall count), Market Maturity (15%, years since FDA approval). Drugs are ranked by weighted composite score.','openFDA FAERS, openFDA NDC, openFDA Enforcement, openFDA Drugs@FDA, ClinicalTrials.gov, NLM RxClass. All data fetched in real time.','This is a decision-support tool, not clinical guidance. Scores are relative within the class and do not account for cost, clinical guidelines, patient population, or institutional preferences. The recommendation engine uses a deterministic algorithm with no AI/LLM component.'); el.innerHTML = html; } function buildRecRadarSVG(drugs) { var colorHex = ['#2dd4bf','#60a5fa','#c084fc']; var colorFill = ['rgba(45,212,191,0.15)','rgba(96,165,250,0.15)','rgba(192,132,252,0.15)']; var dimLabels = ['Safety','Evidence','Availability','Risk','Maturity']; var cx = 200, cy = 200, r = 150; var angleStep = (2 * Math.PI) / 5; var startAngle = -Math.PI / 2; function ptAt(idx, val) { var a = startAngle + idx * angleStep; var v = Math.max(0.05, val / 100); return { x: cx + r * v * Math.cos(a), y: cy + r * v * Math.sin(a) }; } var svg = ''; // Grid [0.25,0.5,0.75,1.0].forEach(function(ring) { var pts = []; for (var i = 0; i < 5; i++) { var p = ptAt(i, ring * 100); pts.push(p.x+','+p.y); } svg += ''; }); for (var i = 0; i < 5; i++) { var p = ptAt(i, 100); svg += ''; } // Drug polygons drugs.forEach(function(d, di) { var vals = [d.dim_safety, d.dim_evidence, d.dim_availability, d.dim_risk, d.dim_maturity]; var pts = []; for (var i = 0; i < 5; i++) { var p = ptAt(i, vals[i]); pts.push(p.x+','+p.y); } svg += ''; for (var j = 0; j < 5; j++) { var p2 = ptAt(j, vals[j]); svg += ''+capitalize(d.name)+' '+dimLabels[j]+': '+vals[j]+''; } }); // Labels var offsets = [{x:0,y:-18},{x:20,y:0},{x:12,y:18},{x:-12,y:18},{x:-20,y:0}]; for (var k = 0; k < 5; k++) { var p = ptAt(k, 115); svg += ''+dimLabels[k]+''; } svg += ''; return svg; } /* ================================================================ AUTO-LOAD: Statins (C10AA) on page load ================================================================ */ window.addEventListener('load', function() { // Animate hero stat counters setTimeout(animateCounters, 400); // Auto-load Statins class review setTimeout(function() { var sel = document.getElementById('class-select'); sel.value = 'C10AA'; // Highlight the Statins quick-switch button var btns = document.querySelectorAll('#quick-switch-class .quick-switch-btn'); if (btns.length > 0) btns[0].classList.add('active'); runClassReview(); }, 600); }); })();