diff --git a/QUESTION_REFERENCE_REVIEWS.md b/QUESTION_REFERENCE_REVIEWS.md new file mode 100644 index 0000000..44664aa --- /dev/null +++ b/QUESTION_REFERENCE_REVIEWS.md @@ -0,0 +1,1353 @@ +# Question Reference Reviews + +This ledger records verification references for questions when the Questions API +schema cannot store question-level source metadata. See the verification policy +in `README.md`. + +## step3-biostatistics-diagnostic-threshold-sensitivity-specificity-3976 + +- Source: [Appendix: Test Performance Metrics](https://www.ncbi.nlm.nih.gov/sites/books/NBK98249/pdf/Bookshelf_NBK98249.pdf) +- Publisher: National Center for Biotechnology Information +- Supports: Raising the positive cutoff of a continuous test decreases + sensitivity and increases specificity. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-cardiovascular-new-hypertension-3101 + +- Source: [Hypertension in Adults: Screening](https://www.uspreventiveservicestaskforce.org/uspstf/recommendation/hypertension-in-adults-screening) +- Publisher: U.S. Preventive Services Task Force +- Supports: Adults should be screened with office blood pressure measurement, + but a positive screen should be confirmed with validated ambulatory or home + blood pressure monitoring before treatment is started. +- Source: [Home Blood Pressure Monitoring](https://www.heart.org/en/health-topics/high-blood-pressure/understanding-blood-pressure-readings/monitoring-your-blood-pressure-at-home) +- Publisher: American Heart Association +- Supports: Home monitoring can confirm a hypertension diagnosis; repeated + measurements over time are more informative than one elevated reading. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-infectious-bacterial-meningitis-3001 + +- Source: [WHO guidelines on meningitis diagnosis, treatment and care](https://www.who.int/publications/i/item/9789240108042) +- Publisher: World Health Organization +- Supports: Acute community-acquired bacterial meningitis requires prompt + intravenous antibiotic treatment. Ceftriaxone or cefotaxime is first-line, + with vancomycin added where resistant pneumococci are a concern; adjunctive + dexamethasone should be given with the first antibiotic dose in non-epidemic + settings. +- Source: [CDC Public Health Image Library: Streptococcus pneumoniae](https://wwwn.cdc.gov/phil/Details.aspx?pid=21340) +- Publisher: Centers for Disease Control and Prevention +- Supports: Streptococcus pneumoniae appears as gram-positive, lancet-shaped + diplococci on Gram stain. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-pulmonary-endobronchial-obstruction-5714 + +- Source: [Pediatric Bronchoscopy Guidelines](https://archbronconeumol.org/en-pediatric-bronchoscopy-guidelines-articulo-S1579212911000231) +- Publisher: Archivos de Bronconeumologia +- Supports: Persistent or recurrent localized pulmonary opacities can reflect an + unrecognized endobronchial foreign body and warrant airway evaluation. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-obgyn-antiphospholipid-syndrome-5862 + +- Source: [The 2023 ACR/EULAR Antiphospholipid Syndrome Classification Criteria](https://acrjournals.onlinelibrary.wiley.com/doi/10.1002/art.42624) +- Publisher: American College of Rheumatology and EULAR +- Supports: Venous thrombosis and obstetric morbidity are clinical APS domains; + anticardiolipin antibodies are among the qualifying laboratory antibodies. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-cardiology-vasospastic-angina-3827 + +- Source: [2023 AHA/ACC Guideline for the Management of Patients With Chronic Coronary Disease](https://www.ahajournals.org/doi/10.1161/CIR.0000000000001168) +- Publisher: American Heart Association and American College of Cardiology +- Supports: Nitrate-responsive rest angina, especially between night and early + morning, supports suspected vasospastic angina; definitive diagnosis also + requires transient ischemic ECG changes or documented coronary spasm. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-biostatistics-odds-ratio-confidence-interval-417 + +- Source: [Analyzing and Interpreting Data](https://www.cdc.gov/field-epi-manual/php/chapters/analyze-interpret-data.html) +- Publisher: Centers for Disease Control and Prevention +- Supports: Case-control studies use odds ratios, and the null hypothesis is not + rejected when a 95% confidence interval includes the null association value + of 1. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-pediatrics-congenital-cmv-638 + +- Source: [Clinical Overview of CMV and Congenital CMV](https://www.cdc.gov/cytomegalovirus/hcp/clinical-overview/index.html) +- Publisher: Centers for Disease Control and Prevention +- Supports: Congenital CMV is confirmed by PCR testing of saliva, urine, or blood + within the first 2-3 weeks of life; urine testing confirms a positive saliva + screen and distinguishes congenital from postnatal infection. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-epidemiology-dose-response-causality-431 + +- Source: [Analyzing and Interpreting Data](https://www.cdc.gov/field-epi-manual/php/chapters/analyze-interpret-data.html) +- Publisher: Centers for Disease Control and Prevention +- Supports: Increasing outcome risk with increasing exposure is a dose-response + relationship, and evidence of this gradient adds weight to causal inference. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-neurology-papilledema-neuroimaging-438 + +- Source: [ACR Appropriateness Criteria: Headache](https://acsearch.acr.org/list/TopicNarrativePdf?topicId=140) +- Publisher: American College of Radiology +- Supports: Papilledema is a red flag for intracranial hypertension, and + noncontrast head CT can promptly evaluate secondary causes such as mass, + edema, or hydrocephalus before lumbar puncture. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-pediatrics-abusive-head-trauma-ct-447 + +- Source: [Abusive Head Trauma in Infants and Children: Technical Report](https://publications.aap.org/pediatrics/article/155/3/e2024070457/201049/Abusive-Head-Trauma-in-Infants-and-Children) +- Publisher: American Academy of Pediatrics +- Supports: Head CT is the acute imaging modality of choice for cranial and + intracranial injury in children with neurologic symptoms and concern for + abuse; children age 2 years or younger also require a skeletal survey. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-ethics-decision-making-capacity-521 + +- Source: [Decisions for Adult Patients Who Lack Capacity](https://code-medical-ethics.ama-assn.org/ethics-opinions/decisions-adult-patients-who-lack-capacity) +- Publisher: American Medical Association +- Supports: When an adult lacks decision-making capacity, physicians should + identify and work with the surrogate designated through a durable power of + attorney for health care; ethics consultation is reserved for absent, + disputed, or inappropriate surrogate decision-making. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-biostatistics-screening-snout-412 + +- Source: [Diagnostic Testing Accuracy: Sensitivity, Specificity, Predictive Values and Likelihood Ratios](https://www.ncbi.nlm.nih.gov/sites/books/NBK557491/) +- Publisher: National Center for Biotechnology Information +- Supports: Sensitivity is the true-positive proportion, high sensitivity + minimizes false negatives, and negative likelihood ratios provide a fuller + measure of how strongly a negative result lowers disease probability. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-biostatistics-test-characteristics-486 + +- Source: [Performance Measures: Assessment of Cancer Screening](https://www.ncbi.nlm.nih.gov/books/NBK550207/) +- Publisher: National Center for Biotechnology Information +- Supports: Sensitivity, specificity, PPV, and NPV derive from the diagnostic + 2x2 table, and PPV can remain low for a rare disease despite high sensitivity + and specificity. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-preventive-care-smoking-cessation-593 + +- Source: [Tobacco Smoking Cessation in Adults: Interventions](https://www.uspreventiveservicestaskforce.org/uspstf/recommendation/tobacco-use-in-adults-and-pregnant-women-counseling-and-interventions) +- Publisher: U.S. Preventive Services Task Force +- Supports: Clinicians should ask adults about tobacco use, advise cessation, + and provide behavioral interventions and FDA-approved pharmacotherapy to + nonpregnant adults who smoke. +- Source: [Colorectal Cancer Screening](https://www.uspreventiveservicestaskforce.org/uspstf/recommendation/colorectal-cancer-screening) +- Publisher: U.S. Preventive Services Task Force +- Supports: Average-risk colorectal cancer screening begins at age 45. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-pediatrics-kawasaki-coronary-aneurysm-701 + +- Source: [Update on Diagnosis and Management of Kawasaki Disease](https://professional.heart.org/en/science-news/update-on-diagnosis-and-management-of-kawasaki-disease/top-things-to-know) +- Publisher: American Heart Association +- Supports: Kawasaki disease can cause coronary artery dilation and aneurysms; + coronary Z-score assessment and ongoing cardiac imaging guide risk assessment + and follow-up. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-heartfailure-aldosterone-antagonist-884 + +- Source: [2022 AHA/ACC/HFSA Guideline for the Management of Heart Failure](https://www.ahajournals.org/doi/10.1161/CIR.0000000000001063) +- Publisher: American Heart Association, American College of Cardiology, and + Heart Failure Society of America +- Supports: An MRA is recommended to reduce morbidity and mortality in + symptomatic HFrEF when eGFR is greater than 30 mL/min/1.73 m2 and potassium + is below 5.0 mEq/L. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-gastroenterology-peptic-ulcer-prognosis-905 + +- Source: [ACG Guideline on Treatment of Helicobacter pylori](https://gi.org/journals-publications/ebgi/schoenfeld_sep2024/) +- Publisher: American College of Gastroenterology +- Supports: H. pylori infection should be treated and eradication confirmed at + least 4 weeks after antibiotic therapy, with PPIs held before testing. +- Source: [The Role of Endoscopy in Peptic Ulcer Disease](https://www.asge.org/docs/default-source/education/practice_guidelines/doc-the-role-of-endoscopy-in-the-management-of-patientswith-peptic-ulcer-disease.pdf) +- Publisher: American Society for Gastrointestinal Endoscopy +- Supports: Surveillance endoscopy for a gastric ulcer is individualized based + on clinical and endoscopic circumstances rather than universally required. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-infectious-disease-antibiotic-stewardship-viral-uri-962 + +- Source: [Outpatient Clinical Care for Adults: Antibiotic Prescribing](https://www.cdc.gov/antibiotic-use/hcp/clinical-care/adult-outpatient.html) +- Publisher: Centers for Disease Control and Prevention +- Supports: Antibiotics are not recommended for nonspecific viral upper + respiratory infections, and outpatient evaluation should distinguish + syndromes requiring antibacterial treatment from self-limited viral illness. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-musculoskeletal-occult-hip-fracture-mri-1007 + +- Source: [ACR Appropriateness Criteria: Acute Hip Pain](https://acsearch.acr.org/docs/3082587/narrative) +- Publisher: American College of Radiology +- Supports: When traumatic hip fracture is suspected despite negative or + indeterminate radiographs, MRI without contrast and CT without contrast are + appropriate next imaging studies. +- Source: [NICE Hip Fracture Management](https://www.nice.org.uk/guidance/cg124/chapter/recommendations) +- Publisher: National Institute for Health and Care Excellence +- Supports: Offer MRI for suspected occult hip fracture after negative x-rays; + consider CT when MRI is unavailable within 24 hours or contraindicated. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-pediatrics-jia-sports-participation-1134 + +- Source: [Exercise and Arthritis](https://rheumatology.org/exercise-and-arthritis) +- Publisher: American College of Rheumatology +- Supports: Exercise is recommended for juvenile idiopathic arthritis and can + be individualized with physical or occupational therapy when modification is + needed. +- Source: [2021 ACR JIA Guideline: Nonpharmacologic Therapies](https://pmc.ncbi.nlm.nih.gov/articles/PMC10231687/) +- Publisher: American College of Rheumatology +- Supports: Physical and occupational therapy are conditionally recommended in + JIA but are supportive interventions rather than universal prerequisites for + activity. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-psychiatry-acute-mania-antipsychotic-1208 + +- Source: [VA/DoD Clinical Practice Guideline for Management of Bipolar Disorder](https://www.healthquality.va.gov/guidelines/MH/bd/VA-DoD-CPG-BD-Full-CPGFinal508.pdf) +- Publisher: U.S. Department of Veterans Affairs and Department of Defense +- Supports: Quetiapine is an evidence-based monotherapy option for acute mania. +- Source: [NICE Bipolar Disorder Recommendations](https://www.nice.org.uk/guidance/cg185/chapter/recommendations) +- Publisher: National Institute for Health and Care Excellence +- Supports: An antipsychotic such as quetiapine should be offered for mania when + the patient is not already taking an antipsychotic or mood stabilizer. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-dermatology-acne-comedonal-initial-1209 + +- Source: [Acne Clinical Guideline](https://www.aad.org/member/clinical-quality/guidelines/acne) +- Publisher: American Academy of Dermatology +- Supports: Current acne guidelines recommend topical retinoids as an effective + topical therapy and recommend limiting systemic antibiotic use. +- Source: [Acne: Diagnosis and Treatment](https://www.aad.org/public/diseases/acne/derm-treat/treat) +- Publisher: American Academy of Dermatology +- Supports: Topical retinoids, including adapalene, clear pores and treat + blackheads and whiteheads, supporting their use for isolated comedonal acne. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-infectious-bat-rabies-pep-1847 + +- Source: [Preventing Rabies from Bats](https://www.cdc.gov/rabies/prevention/bats.html) +- Publisher: Centers for Disease Control and Prevention +- Supports: Bat bites can be difficult to detect; public health or animal + control should coordinate safe capture and rabies testing of a bat found in + a home. +- Source: [Human Rabies Prevention: ACIP Recommendations](https://www.cdc.gov/mmwr/preview/mmwrhtml/rr57e507a1.htm) +- Publisher: Centers for Disease Control and Prevention +- Supports: A bat found with an unattended child can constitute a potential + exposure, but prophylaxis is unnecessary when the captured bat tests + negative. The 10-day observation rule applies to dogs, cats, and ferrets. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-geriatrics-unintentional-weight-loss-social-isolation-2314 + +- Source: [Choosing Wisely](https://www.healthinaging.org/choosing-wisely) +- Publisher: American Geriatrics Society, Health in Aging Foundation +- Supports: For anorexia or cachexia in older adults, clinicians should optimize + social supports, provide appealing food and feeding assistance, and address + contributing medications rather than routinely prescribing appetite + stimulants or supplements. +- Source: [Unintentional Weight Loss in Older Adults](https://www.aafp.org/afp/2021/0700/p34) +- Publisher: American Academy of Family Physicians +- Supports: Clinically significant weight loss requires an initial evaluation; + social isolation can reduce intake, and treatment should address social + support and the eating environment. Mirtazapine lacks evidence when used + solely for weight loss and can cause adverse effects in older adults. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-cardiovascular-atrial-fibrillation-stroke-prevention-5172 + +- Source: [2023 ACC/AHA/ACCP/HRS Guideline for Atrial Fibrillation](https://www.heart.org/-/media/Files/Professional/Quality-Improvement/Get-With-the-Guidelines/Get-With-The-Guidelines-AFIB/AFib-Month/joglaretal20232023accahaaccphrsguidelineforthediagnosisandmanagementofatrialfibrillation.pdf) +- Publisher: American College of Cardiology, American Heart Association, + American College of Chest Physicians, and Heart Rhythm Society +- Supports: Anticoagulation is recommended for men with atrial fibrillation and + CHA2DS2-VASc score of at least 2; direct oral anticoagulants are preferred in + the absence of moderate-to-severe rheumatic mitral stenosis or a mechanical + valve, and aspirin is not an acceptable substitute for anticoagulation. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-obgyn-abortion-complications-counseling-6815 + +- Source: [Abortion Care](https://www.acog.org/womens-health/faqs/induced-abortion) +- Publisher: American College of Obstetricians and Gynecologists +- Supports: First-trimester abortion is safe and effective; vaginal bleeding + and cramping are expected, major complications are rare, and abortion does + not increase infertility risk. +- Source: [Abortion Care](https://www.rcog.org.uk/for-the-public/browse-our-patient-information/abortion-care/) +- Publisher: Royal College of Obstetricians and Gynaecologists +- Supports: Bleeding and abdominal cramping occur with both medical and + procedural abortion, and patients should receive anticipatory guidance about + expected bleeding and warning symptoms. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-pediatrics-sports-clearance-innocent-murmur-1427 + +- Source: [Heart Murmurs in Children: Evaluation and Management](https://www.aafp.org/afp/2022/0300/p250) +- Publisher: American Academy of Family Physicians +- Supports: In a child older than 2 years, disappearance of a murmur with + standing strongly supports an innocent murmur; sports clearance is + appropriate when history and examination are otherwise benign. +- Source: [The Preparticipation Sports Evaluation](https://www.aafp.org/afp/2015/0901/p371) +- Publisher: American Academy of Family Physicians +- Supports: Athletes with well-controlled asthma can participate safely and + should have a rescue inhaler available; routine pulmonary function testing is + not required solely for clearance in an asymptomatic athlete with established + controlled asthma. +- Source: [Heart Murmurs](https://www.heart.org/en/health-topics/heart-murmurs) +- Publisher: American Heart Association +- Supports: Children with innocent murmurs do not require activity limitation. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-immunization-mmr-transient-arthralgia-615 + +- Source: [MMR Vaccine Safety](https://www.cdc.gov/vaccine-safety/vaccines/mmr.html) +- Publisher: Centers for Disease Control and Prevention +- Supports: Joint pain or stiffness occurs in up to one-quarter of susceptible + postpubertal females, generally begins 1 to 3 weeks after MMR vaccination, + is usually mild, lasts about 2 days, and rarely recurs. +- Source: [Pink Book, Chapter 20: Rubella](https://www.cdc.gov/pinkbook/hcp/table-of-contents/chapter-20-rubella.html) +- Publisher: Centers for Disease Control and Prevention +- Supports: Arthralgia after MMR vaccination is associated with the rubella + component and occurs much more often in adult women than in children or men. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-integumentary-contaminated-laceration-delayed-closure-2841 + +- Source: [Clinical Guidance for Wound Management to Prevent Tetanus](https://www.cdc.gov/tetanus/hcp/clinical-guidance/index.html) +- Publisher: Centers for Disease Control and Prevention +- Supports: A soil-contaminated wound is a dirty wound; a patient with unknown + tetanus vaccination history should receive a tetanus-containing vaccine and + tetanus immune globulin in addition to wound cleaning and debridement. +- Source: [Skin Lacerations](https://www.msdmanuals.com/professional/injuries-poisoning/lacerations-and-abrasions/skin-lacerations) +- Publisher: MSD Manual Professional Edition +- Supports: Delayed primary closure is appropriate for significantly + contaminated wounds, particularly those containing organic debris; initial + care includes thorough exploration, debridement, and loose moist-gauze + packing followed by reassessment for closure. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-tetanus-prophylaxis-001 + +- Source: [Clinical Guidance for Wound Management to Prevent Tetanus](https://www.cdc.gov/tetanus/hcp/clinical-guidance/index.html) +- Publisher: Centers for Disease Control and Prevention +- Supports: Puncture wounds and wounds containing soil are dirty or major + wounds. Patients with unknown vaccination history require a tetanus + toxoid-containing vaccine, and those with dirty or major wounds also require + tetanus immune globulin for immediate passive protection. +- Source: [Pink Book, Chapter 21: Tetanus](https://www.cdc.gov/pinkbook/hcp/table-of-contents/chapter-21-tetanus.html) +- Publisher: Centers for Disease Control and Prevention +- Supports: Patients with non-clean wounds and unknown or fewer than three + prior tetanus vaccine doses should receive both vaccine and tetanus immune + globulin; Tdap is preferred when prior Tdap history is unknown. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-derm-alopecia-areata-001 + +- Source: [Alopecia Areata: Diagnosis and Treatment](https://www.aad.org/public/diseases/hair-loss/types/alopecia/treatment) +- Publisher: American Academy of Dermatology +- Supports: Intralesional corticosteroid injections are considered the most + effective treatment for adults with a few patches of alopecia areata; hair + regrowth is often seen within approximately 3 months when treatment works. +- Source: [Alopecia Areata: Signs and Symptoms](https://www.aad.org/public/diseases/hair-loss/types/alopecia/symptoms) +- Publisher: American Academy of Dermatology +- Supports: Alopecia areata commonly presents with sudden round or oval smooth + patches of nonscarring hair loss without scalp irritation. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-cardiology-pci-restenosis-001 + +- Source: [SCAI Expert Consensus Statement on Management of In-Stent Restenosis and Stent Thrombosis](https://www.scai.org/publications/clinical-documents/scai-expert-consensus-statement-management-stent-restenosis-and) +- Publisher: Society for Cardiovascular Angiography and Interventions +- Supports: In-stent restenosis and stent thrombosis are distinct post-PCI + complications with different mechanisms and management considerations. +- Source: [Antiplatelet Strategies in Percutaneous Coronary Interventions](https://www.acc.org/-/media/Non-Clinical/Files-PDFs-Excel-MS-Word-etc/Membership/Coronary-Interventions-Handbook/Chapter-4_Antiplatelet-Strategies.pdf) +- Publisher: American College of Cardiology +- Supports: Dual antiplatelet therapy with aspirin and a P2Y12 inhibitor is a + cornerstone of peri-procedural and post-stent therapy to reduce stent + thrombosis. +- Source: [2021 ACC/AHA/SCAI Revascularization Guideline: Key Perspectives](https://www.acc.org/latest-in-cardiology/ten-points-to-remember/2021/12/08/21/19/2021-guideline-for-revascularization-gl-revasc) +- Publisher: American College of Cardiology +- Supports: Antiplatelet therapy after PCI is selected and continued according + to ischemic and bleeding risk; drug-eluting stents are standard contemporary + PCI devices. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-gi-barrett-gerd-001 + +- Source: [Barrett's Esophagus](https://gi.org/topics/barretts-esophagus/) +- Publisher: American College of Gastroenterology +- Supports: Most patients with Barrett esophagus receive proton pump inhibitor + therapy; antireflux surgery is used for GERD indications rather than as a + cancer-prevention treatment, and nondysplastic Barrett esophagus is managed + with surveillance rather than eradication therapy. +- Source: [Acid Reflux/GERD](https://gi.org/topics/acid-reflux/) +- Publisher: American College of Gastroenterology +- Supports: Proton pump inhibitors and lifestyle measures are effective GERD + therapy; objective reflux testing is particularly useful when symptoms are + not controlled or antireflux surgery is being considered. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-gi-cdiff-complication-001 + +- Source: [C. diff: Facts for Clinicians](https://www.cdc.gov/c-diff/hcp/clinical-overview/) +- Publisher: Centers for Disease Control and Prevention +- Supports: Recognized severe complications of C. difficile infection include + toxic megacolon, colonic perforation, sepsis, and death. +- Source: [SHEA/IDSA Clinical Practice Guideline for C. difficile Infection](https://www.idsociety.org/practice-guideline/clostridium-difficile/) +- Publisher: Infectious Diseases Society of America and Society for Healthcare + Epidemiology of America +- Supports: Fulminant C. difficile infection may be characterized by + hypotension or shock, ileus, or megacolon; megacolon and perforation may + require urgent surgical management. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-rheumatology-cppd-acute-treatment-734 + +- Source: [Calcium Pyrophosphate Deposition](https://rheumatology.org/patients/calcium-pyrophosphate-deposition-cppd) +- Publisher: American College of Rheumatology +- Supports: Acute CPP crystal arthritis may be treated with joint aspiration + and glucocorticoid injection or systemic anti-inflammatory therapy including + NSAIDs, oral glucocorticoids, or colchicine. +- Source: [Calcium Pyrophosphate Deposition Disease](https://www.msdmanuals.com/professional/musculoskeletal-and-connective-tissue-disorders/crystal-induced-arthritides/calcium-pyrophosphate-deposition-disease) +- Publisher: MSD Manual Professional Edition +- Supports: Colchicine is an accepted treatment for acute CPP arthritis flares; + NSAIDs and glucocorticoids are alternatives selected according to the number + of affected joints and patient-specific contraindications. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-infectious-tuberculosis-screening-conversion-237 + +- Source: [Clinical Testing Guidance for Tuberculosis: Tuberculin Skin Test](https://www.cdc.gov/tb/hcp/testing-diagnosis/tuberculin-skin-test.html) +- Publisher: Centers for Disease Control and Prevention +- Supports: A positive tuberculin skin test requires evaluation for TB disease; + the result must be interpreted according to exposure and progression risk. +- Source: [ATS/CDC/IDSA Diagnosis of Tuberculosis Guideline](https://www.idsociety.org/practice-guideline/diagnosis-of-tb-in-adults-and-children/) +- Publisher: American Thoracic Society, Centers for Disease Control and + Prevention, and Infectious Diseases Society of America +- Supports: Active TB is excluded by symptom assessment and chest radiography; + respiratory sampling follows when symptoms or radiographic abnormalities + suggest pulmonary disease. Confirmatory testing is mainly advised for an + unexpected positive result in a person unlikely to be infected. +- Source: [CDC Contact Investigation Recommendations](https://www.cdc.gov/mmwr/preview/mmwrhtml/rr5415a1.htm) +- Publisher: Centers for Disease Control and Prevention and National + Tuberculosis Controllers Association +- Supports: TST conversion is conventionally defined by an increase of at least + 10 mm within 2 years. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-gastro-sbp-saag-241 + +- Source: [Recognition and Management of Spontaneous Bacterial Peritonitis](https://www.hepatitisc.uw.edu/go/management-cirrhosis-related-complications/spontaneous-bacterial-peritonitis-recognition-management/core-concept/all/) +- Publisher: University of Washington Hepatitis C Online +- Supports: Ascitic fluid PMN count of at least 250 cells/mm3 warrants prompt + empiric antibiotics; community-acquired SBP is treated with intravenous + cefotaxime or a similar third-generation cephalosporin, whereas nosocomial + infection may require broader therapy. +- Source: [AASLD: Why Timing Matters, Paracentesis on Admission](https://www.aasld.org/liver-fellow-network/core-series/why-series/why-timing-matters-paracentesis-admission-cirrhosis) +- Publisher: American Association for the Study of Liver Diseases +- Supports: In a patient with cirrhosis and ascites, an ascitic PMN count of at + least 250 cells/uL carries a high likelihood of SBP and should prompt + antibiotic treatment without waiting for culture results. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-cardiovascular-thiazide-followup-251 + +- Source: [2025 High Blood Pressure Guideline: Top Things to Know](https://professional.heart.org/en/science-news/2025-high-blood-pressure-guideline/top-things-to-know) +- Publisher: American Heart Association and American College of Cardiology +- Supports: Stage 2 hypertension is preferably treated with two first-line + agents; home blood pressure monitoring and frequent follow-up are important + while therapy is being adjusted, and a potassium-rich DASH-style diet is + recommended when clinically appropriate. +- Source: [Chlorthalidone Prescribing Information](https://dailymed.nlm.nih.gov/dailymed/drugInfo.cfm?setid=36ef8d83-45f2-4873-b7cb-1be096d14d18) +- Publisher: U.S. National Library of Medicine DailyMed +- Supports: Chlorthalidone can cause dose-related potassium reduction; + electrolytes should be checked periodically, dose titration should follow a + suitable therapeutic trial, and elderly patients should generally begin at + the low end of the dose range. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-psych-acute-psychosis-261 + +- Source: [Adult Psychiatric Emergencies](https://www.acep.org/siteassets/new-pdfs/policy-statements/adult-psychiatric-emergencies.pdf) +- Publisher: American College of Emergency Physicians +- Supports: Psychosis and homicidal or violent behavior are psychiatric + emergencies requiring risk stratification, acute treatment, and a safe + disposition rather than routine outpatient follow-up. +- Source: [Crisis Services: Meeting Needs, Saving Lives](https://988crisissystemshelp.samhsa.gov/sites/default/files/2024-01/crisis-services-meeting-needs-saving-lives-compendium.pdf) +- Publisher: Substance Abuse and Mental Health Services Administration +- Supports: Acute psychiatric symptoms may require inpatient stabilization; + risk of injury to others is a common civil-commitment criterion, although + specific involuntary-hold procedures vary by jurisdiction. +- Source: [What Is Schizophrenia?](https://www.samhsa.gov/mental-health/what-is-mental-health/conditions/schizophrenia) +- Publisher: Substance Abuse and Mental Health Services Administration +- Supports: Hospitalization may be needed during a severe schizophrenia + episode to ensure safety and stabilization. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-pulmonary-copd-niv-271 + +- Source: [GOLD 2026 Report](https://goldcopd.org/wp-content/uploads/2026/01/GOLD-REPORT-2026-v1.3-8Dec2025_WMV2.pdf) +- Publisher: Global Initiative for Chronic Obstructive Lung Disease +- Supports: NIV is the initial ventilatory mode for hospitalized COPD + exacerbations with acute respiratory failure and is indicated with + respiratory acidosis, including PaCO2 at least 45 mm Hg and pH at or below + 7.35; it reduces intubation, complications, and mortality. +- Source: [ERS/ATS Guideline on NIV for Acute Respiratory Failure](https://publications.ersnet.org/content/erj/50/2/1602426.full) +- Publisher: European Respiratory Society and American Thoracic Society +- Supports: Bilevel NIV is strongly recommended for acute or acute-on-chronic + respiratory acidosis due to COPD exacerbation, particularly at pH 7.25 to + 7.35 when the patient is not immediately deteriorating and can be closely + monitored with rapid access to intubation. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-supportive-care-acupuncture-cinv-2801 + +- Source: [Acupuncture PDQ, Health Professional Version](https://www.cancer.gov/about-cancer/treatment/cam/hp/acupuncture-pdq) +- Publisher: National Cancer Institute +- Supports: Among cancer-related symptoms studied, acupuncture has its most + convincing evidence for chemotherapy-induced nausea and vomiting; it may be + used as an adjunct to standard antiemetic therapy, although study quality and + effects on specific nausea and vomiting outcomes vary. +- Source: [Nausea and Vomiting Related to Cancer Treatment PDQ](https://www.cancer.gov/about-cancer/treatment/side-effects/nausea/nausea-hp-pdq) +- Publisher: National Cancer Institute +- Supports: Persistent CINV can cause dehydration and nutritional depletion; + management requires optimized pharmacologic antiemetics, dietary support, + and selected nonpharmacologic adjuncts such as acupuncture or acupressure. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-pulmonary-silicosis-progressive-fibrosis-2901 + +- Source: [Engineered Stone and Silicosis](https://www.cdc.gov/niosh/bulletin/2026/engineered-stone-cos.html) +- Publisher: National Institute for Occupational Safety and Health +- Supports: Engineered stone typically contains very high crystalline silica + content, and respirable exposure during fabrication can cause irreversible + occupational silicosis. +- Source: [Outbreak of Silicosis Among Engineered Stone Countertop Workers](https://www.cdc.gov/niosh/bulletin/2019/silicosis-countertop.html) +- Publisher: National Institute for Occupational Safety and Health +- Supports: Silicosis is progressive, debilitating, incurable, and sometimes + fatal; high-level engineered-stone exposure can produce severe disease. +- Source: [Severe Silicosis in Engineered Stone Fabrication Workers](https://www.cdc.gov/mmwr/volumes/68/wr/mm6838a1.htm) +- Publisher: Centers for Disease Control and Prevention +- Supports: Progressive massive fibrosis is the most advanced form of + silicosis and can cause continued lung-function decline requiring lung + transplantation evaluation; silicosis also increases tuberculosis risk. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-neurology-tia-secondary-prevention-3201 + +- Source: [2026 Guideline for the Early Management of Patients With Acute Ischemic Stroke](https://professional.heart.org/en/science-news/2026-guideline-for-the-early-management-of-patients-with-acute-ischemic-stroke/top-things-to-know) +- Publisher: American Heart Association/American Stroke Association +- Supports: Eligible patients with disabling acute ischemic stroke deficits + should receive rapid intravenous thrombolysis within 4.5 hours regardless of + NIHSS score, whereas dual antiplatelet therapy is preferred for selected + nondisabling events. +- Source: [2021 Guideline for Prevention of Stroke in Patients With Stroke and TIA](https://professional.heart.org/en/science-news/2021-guideline-for-the-prevention-of-stroke-in-patients-with-stroke-and-transient-ischemic-attack/top-things-to-know) +- Publisher: American Heart Association/American Stroke Association +- Supports: Short-term dual antiplatelet therapy is recommended only for + selected patients, including early-arriving minor ischemic stroke and + high-risk transient ischemic attack; occult atrial-fibrillation monitoring + is also appropriate when no other cause is identified. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-neuro-acute-dystonia-337 + +- Source: [Reglan injection prescribing information](https://www.accessdata.fda.gov/drugsatfda_docs/label/2026/017862s64lbl.pdf) +- Publisher: U.S. Food and Drug Administration +- Supports: Metoclopramide can cause acute dystonic reactions within the first + 24-48 hours, including torticollis, trismus, and oculogyric crisis; + diphenhydramine or benztropine can treat the reaction, and metoclopramide + should be discontinued when extrapyramidal symptoms develop. +- Source: [Treatment of acute adverse effects of antipsychotics](https://www.merckmanuals.com/professional/psychiatric-disorders/schizophrenia-and-related-disorders/antipsychotic-medications) +- Publisher: Merck Manual Professional Edition +- Supports: Acute dystonic reactions such as oculogyric crisis and torticollis + are treated with intravenous or intramuscular diphenhydramine or benztropine. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-endocrine-diabetic-nephropathy-401 + +- Source: [Chronic Kidney Disease and Risk Management: Standards of Care in Diabetes - 2026](https://diabetesjournals.org/care/article/49/Supplement_1/S246/163914/11-Chronic-Kidney-Disease-and-Risk-Management) +- Publisher: American Diabetes Association +- Supports: In nonpregnant people with diabetes and hypertension, an ACE + inhibitor or ARB is recommended when UACR is 30-299 mg/g and is strongly + recommended with UACR at least 300 mg/g and/or eGFR below 60. Evidence does + not establish kidney-outcome benefit for moderately increased albuminuria + without hypertension, and abnormal UACR should be confirmed because of + biological variability. +- Source: [ADA-KDIGO consensus report on diabetes management in CKD](https://diabetesjournals.org/care/article/45/12/3075/147614/Diabetes-Management-in-Chronic-Kidney-Disease-A) +- Publisher: American Diabetes Association and Kidney Disease: Improving Global Outcomes +- Supports: ACE inhibitor or ARB therapy is recommended and titrated to the + highest tolerated dose in patients with diabetes, hypertension, and + albuminuria. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-genitourinary-chronic-bacterial-prostatitis-302 + +- Source: [EAU Guidelines on Urological Infections: Bacterial Prostatitis](https://uroweb.org/guidelines/urological-infections/chapter/the-guideline?s=04) +- Publisher: European Association of Urology +- Supports: Chronic bacterial prostatitis should receive culture-guided + antimicrobial treatment; fluoroquinolones are recommended first-line for + susceptible typical gram-negative pathogens and are generally given for + 4-6 weeks because of their prostatic penetration. +- Source: [Fluoroquinolone safety reminder](https://www.gov.uk/drug-safety-update/fluoroquinolone-antibiotics-reminder-of-the-risk-of-disabling-and-potentially-long-lasting-or-irreversible-side-effects) +- Publisher: UK Medicines and Healthcare products Regulatory Agency +- Supports: Fluoroquinolones can cause disabling, prolonged, or irreversible + adverse effects and require patient counseling and prompt discontinuation if + serious tendon, muscle, joint, peripheral nerve, or central nervous system + symptoms develop. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-em-criticalcare-hypothermia-403 + +- Source: [AHA Special Circumstances of Resuscitation](https://cpr.heart.org/en/resuscitation-science/cpr-and-ecc-guidelines/adult-and-pediatric-special-circumstances-of-resuscitation) +- Publisher: American Heart Association +- Supports: Full resuscitation and rewarming should continue in life-threatening + environmental hypothermia without an obviously lethal injury. Prognosis for + extracorporeal rewarming should use the validated HOPE score, which includes + age, sex, asphyxia, CPR duration, serum potassium, and core temperature; + isolated clinical or laboratory findings should not determine futility. +- Source: [2025 Special Circumstances Guidelines](https://www.resus.org.uk/professional-library/2025-resuscitation-guidelines/special-circumstances-guidelines) +- Publisher: Resuscitation Council UK +- Supports: In-hospital prognostication for successful rewarming after + hypothermic cardiac arrest should be based on the HOPE score. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-obgyn-hellp-urgent-delivery-404 + +- Source: [Preeclampsia and High Blood Pressure During Pregnancy](https://www.acog.org/womens-health/faqs/preeclampsia-and-high-blood-pressure-during-pregnancy) +- Publisher: American College of Obstetricians and Gynecologists +- Supports: HELLP syndrome is a medical emergency. Preeclampsia with severe + features at or beyond 34 weeks should be managed in the hospital with + maternal stabilization, seizure prophylaxis and blood-pressure treatment as + indicated, followed by delivery once stable. +- Source: [ACOG overview: 7 Things to Know About Preeclampsia](https://www.acog.org/womens-health/experts-and-stories/the-latest/7-things-to-know-about-preeclampsia) +- Publisher: American College of Obstetricians and Gynecologists +- Supports: HELLP requires immediate delivery; severe preeclampsia at or after + 34 weeks generally warrants delivery, with antihypertensive medication and + magnesium sulfate used during stabilization. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-endocrine-primary-aldosteronism-medical-therapy-506 + +- Source: [Primary Aldosteronism: Endocrine Society Clinical Practice Guideline](https://www.endocrine.org/clinical-practice-guidelines/primary-aldosteronism-2) +- Publisher: Endocrine Society +- Supports: Primary aldosteronism should receive aldosterone-specific therapy. + Lifelong mineralocorticoid receptor antagonist treatment is appropriate for + bilateral disease, unknown lateralization, patients who decline surgery, or + those who are not surgical candidates; spironolactone is suggested because + of cost and availability, with potassium, renal function, renin, and blood + pressure monitored during titration. +- Source: [Primary Aldosteronism guideline full text](https://academic.oup.com/jcem/article/110/9/2453/8196671) +- Publisher: Journal of Clinical Endocrinology & Metabolism +- Supports: CT imaging cannot reliably determine functional lateralization. + Patients who desire and are candidates for adrenalectomy generally require + CT plus adrenal venous sampling before choosing surgical therapy. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-infectious-mrsa-pneumonia-linezolid-707 + +- Source: [ATS/IDSA Community-Acquired Pneumonia Guideline Executive Summary](https://www.idsociety.org/globalassets/idsa/practice-guidelines/community-acquired-pneumonia-in-adults/executive_summary.pdf) +- Publisher: American Thoracic Society and Infectious Diseases Society of America +- Supports: Recommended MRSA-active treatment options for hospitalized adults + with community-acquired pneumonia include vancomycin or linezolid. +- Source: [ATS/IDSA HAP/VAP Guideline](https://www.idsociety.org/practice-guideline/hap_vap/) +- Publisher: American Thoracic Society and Infectious Diseases Society of America +- Supports: Confirmed MRSA pneumonia should be treated with vancomycin or + linezolid; patient-specific factors such as renal function, blood counts, + serotonergic medications, and cost can guide selection. +- Source: [Daptomycin prescribing information](https://www.accessdata.fda.gov/drugsatfda_docs/label/2024/217630s000lbl.pdf) +- Publisher: U.S. Food and Drug Administration +- Supports: Daptomycin is not indicated for treatment of pneumonia. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-endocrine-new-diabetes-lipid-screen-842 + +- Source: [Cardiovascular Disease and Risk Management: Standards of Care in Diabetes - 2026](https://diabetesjournals.org/care/article/49/Supplement_1/S216/163933/10-Cardiovascular-Disease-and-Risk-Management) +- Publisher: American Diabetes Association +- Supports: Adults with diabetes aged 40-75 years without ASCVD should receive + at least moderate-intensity statin therapy. A lipid profile establishes the + baseline needed to assess LDL reduction, identify severe dyslipidemia, and + monitor response and adherence after therapy begins. +- Source: [Comprehensive Medical Evaluation: Standards of Care in Diabetes - 2026](https://diabetesjournals.org/care/article/49/Supplement_1/S61/163931/4-Comprehensive-Medical-Evaluation-and-Assessment) +- Publisher: American Diabetes Association +- Supports: Adults with type 2 diabetes should also be assessed for metabolic + liver fibrosis risk with FIB-4, which uses age, AST, ALT, and platelet count; + therefore hepatic enzymes and CBC components should not be presented as + categorically unnecessary distractors in an initial diabetes evaluation. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-neuro-missed-antiseizure-dose-316 + +- Source: [Levetiracetam Medication Guide](https://www.dailymed.nlm.nih.gov/dailymed/medguide.cfm?setid=0f60b9fb-5305-4488-99b7-a01a693994b4) +- Publisher: U.S. National Library of Medicine DailyMed +- Supports: A missed levetiracetam dose should be taken when remembered unless + it is almost time for the next dose; in that case, the missed dose should be + skipped and the next dose taken at the regular time without doubling. +- Source: [How and when to take levetiracetam](https://www.nhs.uk/medicines/levetiracetam/how-and-when-to-take-levetiracetam/) +- Publisher: National Health Service +- Supports: For twice-daily levetiracetam, if fewer than 8 hours remain before + the next dose, skip the missed dose and take the next dose normally; never + take an extra dose to compensate. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-ethics-shared-decision-oncology-481 + +- Source: [Surgery to Reduce the Risk of Breast Cancer](https://www.cancer.gov/types/breast/causes-risk-factors/prevention/preventive-breast-surgery) +- Publisher: National Cancer Institute +- Supports: Contralateral risk-reducing mastectomy lowers contralateral cancer + incidence but is generally discouraged for average-risk patients because + contralateral risk is low, complications may increase, and available evidence + does not show reduced mortality; benefits and harms should be individualized + and discussed. +- Source: [Mastectomy: Single vs. Double Mastectomy](https://www.cancer.gov/types/breast/treatment/surgery/mastectomy) +- Publisher: National Cancer Institute +- Supports: Patients without a high-risk mutation or strong family history do + not generally live longer after double rather than single mastectomy, but + concerns about recurrence, surveillance, symmetry, body image, reconstruction, + risks, and patient preferences should be discussed in shared decision-making. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-neuro-ischemic-stroke-supportive-bp-615 + +- Source: [2026 Guideline for the Early Management of Patients With Acute Ischemic Stroke](https://professional.heart.org/en/science-news/2026-guideline-for-the-early-management-of-patients-with-acute-ischemic-stroke) +- Publisher: American Heart Association/American Stroke Association +- Supports: Current acute ischemic stroke guidance emphasizes rapid assessment for + intravenous thrombolysis and endovascular thrombectomy, including expanded + thrombectomy eligibility, and warns against intensive blood pressure lowering + around reperfusion treatment. +- Source: [2025 Guideline for the Prevention, Detection, Evaluation, and Management of High Blood Pressure in Adults](https://www.ahajournals.org/doi/10.1161/HYP.0000000000000249) +- Publisher: American Heart Association/American College of Cardiology +- Supports: In acute ischemic stroke, blood pressure treatment depends on + reperfusion status, a pressure above 220/120 mm Hg, or another comorbid + indication; rapid reduction can be detrimental because ischemic tissue depends + on systemic perfusion pressure. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-urogynecology-stress-incontinence-pessary-612 + +- Source: [Urinary Incontinence](https://www.acog.org/womens-health/faqs/urinary-incontinence) +- Publisher: American College of Obstetricians and Gynecologists +- Supports: Stress urinary incontinence causes leakage with coughing, laughing, + walking, running, or exercise; a fitted pessary can support the vaginal walls, + bladder, and urethra and provide symptom relief without surgery. +- Source: [Pelvic Support Problems](https://www.acog.org/womens-health/faqs/pelvic-support-problems) +- Publisher: American College of Obstetricians and Gynecologists +- Supports: Anterior vaginal wall prolapse results from weakened pelvic support; + pessaries can be used for short- or long-term support and many patients obtain + immediate relief, while pelvic floor exercises may also improve incontinence. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-cardiology-preop-ecg-incidental-552 + +- Source: [2024 Guideline for Perioperative Cardiovascular Management for Noncardiac Surgery](https://professional.heart.org/en/-/media/PHD-Files-2/Science-News/2/2024/2024-Guideline-for-Perioperative-Cardiovascular-Management-slide-set.pdf) +- Publisher: American Heart Association/American College of Cardiology +- Supports: Routine resting ECG is not recommended for asymptomatic patients + undergoing low-risk surgery; further evaluation is reasonable for new ECG + abnormalities, not an unchanged chronic finding. +- Source: [2024 AHA/ACC Perioperative Cardiovascular Management Guideline: Key Points](https://www.acc.org/latest-in-cardiology/ten-points-to-remember/2024/09/23/04/15/2024-aha-acc-perioperative-guideline-gl) +- Publisher: American College of Cardiology +- Supports: Patients with good functional capacity, low predicted perioperative + risk, or a planned low-risk procedure should not undergo routine preoperative + stress testing. +- Media: Original ECG schematic created for this question; no third-party image + was uploaded. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-psychiatry-late-life-depression-mirtazapine-714 + +- Source: [VA/DoD Clinical Practice Guideline: Management of Major Depressive Disorder](https://www.healthquality.va.gov/guidelines/MH/mdd/) +- Publisher: U.S. Department of Veterans Affairs and Department of Defense +- Supports: Major depressive disorder should be treated with evidence-based + pharmacotherapy and/or psychotherapy selected according to clinical features, + patient preferences, comorbidities, and adverse-effect profiles. +- Source: [Mirtazapine Prescribing Information](https://dailymed.nlm.nih.gov/dailymed/drugInfo.cfm?setid=98ad1917-a094-44f5-a28f-a64a8cfcd887) +- Publisher: U.S. National Library of Medicine DailyMed +- Supports: Mirtazapine is indicated for major depressive disorder; common + effects include somnolence, increased appetite, weight gain, and dizziness, + which informs individualized use and monitoring in an older patient with + insomnia and clinically significant weight loss. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-bone-health-osteoporosis-bisphosphonate-815 + +- Source: [Pharmacological Management of Osteoporosis in Postmenopausal Women](https://www.endocrine.org/clinical-practice-guidelines/osteoporosis-in-postmenopausal-women) +- Publisher: Endocrine Society +- Supports: Bisphosphonates are recommended as initial therapy for postmenopausal + women at high fracture risk; raloxifene is limited to women at low DVT risk, + menopausal hormone therapy is limited to selected younger women at low DVT + risk, and calcitonin is reserved for patients unable to use preferred agents. +- Source: [Raloxifene Prescribing Information](https://www.accessdata.fda.gov/drugsatfda_docs/review/2018/090842Orig1s000.pdf) +- Publisher: U.S. Food and Drug Administration +- Supports: Raloxifene is contraindicated in women with an active or past history + of venous thromboembolism, including deep venous thrombosis and pulmonary + embolism. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-endocrine-dka-dextrose-potassium-916 + +- Source: [Hyperglycemic Crises in Adults With Diabetes: A Consensus Report](https://diabetesjournals.org/care/article/47/8/1257/156808/Hyperglycemic-Crises-in-Adults-With-Diabetes-A) +- Publisher: American Diabetes Association and European Association for the Study of Diabetes +- Supports: When glucose falls below 250 mg/dL during DKA treatment, add 5%-10% + dextrose and reduce but continue intravenous insulin until ketonemia resolves; + add potassium when serum potassium falls below 5.0 mmol/L to maintain 4-5 + mmol/L, and reserve bicarbonate for severe acidosis with pH below 7.0. +- Source: [Hyperglycemic Crises in Adults With Diabetes: Full Consensus Report](https://pmc.ncbi.nlm.nih.gov/articles/PMC11272983/) +- Publisher: Diabetes Care via PubMed Central +- Supports: DKA resolution requires beta-hydroxybutyrate below 0.6 mmol/L plus + venous pH at least 7.3 or bicarbonate at least 18 mmol/L; glucose normalization + alone is not sufficient to stop insulin. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-substance-use-alcohol-blackout-counseling-917 + +- Source: [Interrupted Memories: Alcohol-Induced Blackouts](https://www.niaaa.nih.gov/publications/brochures-and-fact-sheets/interrupted-memories-alcohol-induced-blackouts) +- Publisher: National Institute on Alcohol Abuse and Alcoholism +- Supports: During an alcohol-induced blackout a person remains awake but cannot + consolidate new memories; even one blackout is concerning, predicts increased + risk of alcohol-related harms, and should prompt discussion and assessment of + drinking behavior. +- Source: [Screening, Brief Intervention, and Referral to Treatment](https://www.samhsa.gov/substance-use/treatment/sbirt) +- Publisher: Substance Abuse and Mental Health Services Administration +- Supports: Emergency departments are appropriate settings for validated + substance-use screening, brief intervention for at-risk use, and referral for + additional assessment or treatment when indicated. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-gastroenterology-splenic-infarction-post-sclerotherapy-918 + +- Source: [Splenic Abscess: A Possible Complication of Endoscopic Variceal Sclerotherapy](https://pubmed.ncbi.nlm.nih.gov/8340143/) +- Publisher: PubMed-indexed case report +- Supports: Splenic abscess is a reported rare complication of endoscopic + variceal sclerotherapy, potentially related to bacteremia or retrograde portal + venous thrombosis after the procedure. +- Source: [AAST Acute Care Surgery Curriculum: Splenic Abscess](https://www.aast.org/Assets/732276a6-7a75-44d8-99c8-a364158e7833/638578976049130000/e15-splenic-abscess-pdf) +- Publisher: American Association for the Surgery of Trauma +- Supports: CT establishes the diagnosis; initial treatment includes hospital + admission and broad-spectrum antibiotics, with definitive source control by + percutaneous drainage or splenectomy selected according to anatomy and clinical + status. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-gynecology-pessary-vaginitis-919 + +- Source: [Vaginal Pessary Use and Management for Pelvic Organ Prolapse](https://www.augs.org/clinical-patient-resources/clinical-guidance-documents/) +- Publisher: American Urogynecologic Society and Society of Urologic Nurses and Associates +- Supports: AUGS identifies its joint clinical consensus statement as current + guidance for pessary use, surveillance, and management of pessary-related + complications. +- Source: [Updates in Pessary Care for Pelvic Organ Prolapse: A Narrative Review](https://pmc.ncbi.nlm.nih.gov/articles/PMC12028327/) +- Publisher: Journal of Clinical Medicine via PubMed Central +- Supports: Pessary-associated discharge is common and does not necessarily + indicate infection; pessary-related epithelial changes are classified by + direct examination, and management may include cleaning, temporary removal, + vaginal assessment, and treatment directed by the observed complication. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-pulmonary-copd-exacerbation-bronchodilator-920 + +- Source: [Global Initiative for Chronic Obstructive Lung Disease 2026 Report](https://goldcopd.org/wp-content/uploads/2026/01/GOLD-REPORT-2026-v1.3-8Dec2025_WMV2.pdf) +- Publisher: Global Initiative for Chronic Obstructive Lung Disease +- Supports: Short-acting inhaled beta2-agonists, with or without short-acting + anticholinergics, are the initial bronchodilators for an acute COPD + exacerbation. Systemic corticosteroids improve recovery, and antibiotics are + indicated when increased sputum purulence accompanies other cardinal symptoms + or mechanical ventilation is required. +- Source: [Chronic Obstructive Pulmonary Disease in Over 16s: Diagnosis and Management](https://www.nice.org.uk/guidance/ng115/chapter/recommendations) +- Publisher: National Institute for Health and Care Excellence +- Supports: Acute exacerbation management includes increased short-acting + bronchodilator therapy, controlled oxygen when needed, systemic corticosteroids + for significant breathlessness, and antibiotics when sputum changes suggest a + bacterial trigger. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-obgyn-tuboovarian-abscess-641 + +- Source: [Pelvic Inflammatory Disease: STI Treatment Guidelines](https://www.cdc.gov/std/treatment-guidelines/pid.htm) +- Publisher: Centers for Disease Control and Prevention +- Supports: Tubo-ovarian abscess is an indication for hospitalization and more + than 24 hours of inpatient observation. Recommended parenteral therapy includes + ceftriaxone, doxycycline, and metronidazole, with continued anaerobic coverage + when an abscess is present. +- Source: [Pelvic Inflammatory Disease](https://www.acog.org/womens-health/faqs/pelvic-inflammatory-disease) +- Publisher: American College of Obstetricians and Gynecologists +- Supports: PID can produce a tubo-ovarian abscess; antibiotics are the usual + initial treatment, while selected abscesses may require a procedure or surgery. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-musculoskeletal-scoliosis-screen-422 + +- Source: [Adolescent Idiopathic Scoliosis: Screening](https://www.uspreventiveservicestaskforce.org/uspstf/index.php/recommendation/adolescent-idiopathic-scoliosis-screening) +- Publisher: U.S. Preventive Services Task Force +- Supports: The forward bend test is commonly used to evaluate adolescents for + scoliosis, a scoliometer can quantify trunk rotation, and an angle of 5-7 + degrees commonly prompts radiography. The USPSTF concludes that evidence is + insufficient to determine the benefits and harms of universal screening. +- Source: [Scoliosis](https://www.srs.org/Patients/Conditions/Scoliosis) +- Publisher: Scoliosis Research Society +- Supports: The Adams forward bend test reveals asymmetric rib or lumbar + prominence and is the most frequently used clinical screening maneuver for + scoliosis. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-ethics-geriatric-cataract-capacity-923 + +- Source: [Decisions for Adult Patients Who Lack Capacity](https://code-medical-ethics.ama-assn.org/ethics-opinions/decisions-adult-patients-who-lack-capacity) +- Publisher: American Medical Association Code of Medical Ethics +- Supports: Patients should participate in decisions according to their + decision-making capacity; a surrogate exercises authority when the patient + lacks capacity for the decision, not merely because a cognitive disorder is + present. +- Source: [Cataract Surgery](https://www.nei.nih.gov/eye-health-information/eye-conditions-and-diseases/cataracts/cataract-surgery) +- Publisher: National Eye Institute +- Supports: Cataract surgery is considered when vision loss interferes with + everyday activities such as reading; it is common, generally outpatient, and + improves vision in most patients, although individualized risks must be + discussed. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-obstetrics-initial-prenatal-blood-type-1024 + +- Source: [Routine Tests During Pregnancy](https://www.acog.org/womens-health/faqs/routine-tests-during-pregnancy) +- Publisher: American College of Obstetricians and Gynecologists +- Supports: Initial prenatal laboratory testing includes maternal blood type and + Rh status; early identification of Rh-negative patients and alloantibodies + guides prophylaxis and monitoring. +- Source: [Screening for Fetal Chromosomal Abnormalities](https://www.acog.org/clinical/clinical-guidance/practice-advisory/articles/2026/01/screening-for-fetal-chromosomal-abnormalities) +- Publisher: American College of Obstetricians and Gynecologists +- Supports: Cell-free DNA is the most sensitive and specific screening test for + common fetal aneuploidies and should be made available to all obstetric + patients after counseling, regardless of baseline risk. +- Source: [Oocyte or Embryo Donation to Women of Advanced Reproductive Age](https://integration.asrm.org/globalassets/_asrm/practice-guidance/ethics-opinions/pdf/oocyte_or_embryo_donation_to_women_of_advanced_maternal_age_an_ethics_commitee_opinion.pdf) +- Publisher: American Society for Reproductive Medicine Ethics Committee +- Supports: In donor-oocyte pregnancies, the incidence of age-related genetic + abnormalities in offspring relates primarily to the age of the oocyte donor + rather than the gestational carrier. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-urology-testicular-torsion-811 + +- Source: [AUA Medical Student Curriculum: The Acute Scrotum](https://www.auanet.org/documents/education/Acute-Scrotum.pdf) +- Publisher: American Urological Association +- Supports: Definitive treatment of testicular torsion is immediate scrotal + exploration. The affected testis is detorsed and fixed if viable, and the + contralateral testis undergoes orchiopexy because the bell-clapper deformity is + assumed to be bilateral. +- Source: [Acute Scrotal Pain Clinical Pathway](https://www.hopkinsmedicine.org/-/media/files/allchildrens/clinical-pathways/acute-scrotal-pain-clinical-pathway-12_8_2022.pdf) +- Publisher: Johns Hopkins All Children's Hospital +- Supports: Sudden severe pain with a high-riding or transverse testis and absent + cremasteric reflex can establish torsion clinically and should prompt immediate + surgical consultation; Doppler ultrasonography is used for equivocal cases. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-pediatrics-hsp-prognosis-517 + +- Source: [IPNA Clinical Practice Recommendations for Children With IgA Nephropathy and IgA Vasculitis Nephritis](https://pmc.ncbi.nlm.nih.gov/articles/PMC11666671/) +- Publisher: International Pediatric Nephrology Association +- Supports: Mild IgA vasculitis nephritis with normal blood pressure and kidney + function can recover without treatment. Persistent proteinuria, particularly + substantial proteinuria at 1 year, is associated with worse long-term kidney + prognosis; children with renal involvement require prolonged monitoring. +- Source: [National Recommendations for the Management of Children and Young People With IgA Vasculitis](https://pmc.ncbi.nlm.nih.gov/articles/PMC11671997/) +- Publisher: UK Kidney Association-aligned multidisciplinary guideline group +- Supports: All children with IgA vasculitis require surveillance for nephritis; + persistent moderate or severe proteinuria, acute kidney injury, and nephrotic + syndrome identify more severe renal disease requiring additional evaluation. +- Accessed: 2026-07-12 +- Reviewer: Codex + +## step3-pediatrics-asthma-environmental-control-388 + +- Source: [Global Strategy for Asthma Management and Prevention, 2025](https://ginasthma.org/wp-content/uploads/2025/07/GINA-2025-Strategy-Report_25_05_25-WMS-2.pdf) +- Publisher: Global Initiative for Asthma +- Supports: Parents and caregivers of children with asthma should be advised not + to smoke or vape and not to permit smoking or vaping in rooms or vehicles used + by their children; cessation support should be provided. +- Source: [Asthma and Secondhand Smoke](https://www.cdc.gov/tobacco/campaign/tips/diseases/secondhand-smoke-asthma.html) +- Publisher: Centers for Disease Control and Prevention +- Supports: Tobacco smoke is a common asthma trigger; families should not smoke + or allow smoking in the home or car, and opening a window does not protect a + child from secondhand smoke. +- Source: [Secondhand Tobacco Smoke and Indoor Air Quality](https://www.epa.gov/indoor-air-quality-iaq/secondhand-tobacco-smoke-and-indoor-air-quality) +- Publisher: U.S. Environmental Protection Agency +- Supports: Secondhand smoke causes more frequent and severe asthma attacks in + children, has no safe exposure level, and cannot be eliminated by ventilation + or air cleaning. +- Accessed: 2026-07-13 +- Reviewer: Codex + +## step3-infectious-facial-cellulitis-cefazolin-929 + +- Source: [Clinical Guidance for Group A Streptococcal Cellulitis](https://www.cdc.gov/group-a-strep/hcp/clinical-guidance/cellulitis.html) +- Publisher: Centers for Disease Control and Prevention +- Supports: Nonpurulent cellulitis should receive an antibiotic active against + streptococci; intravenous options for systemic infection include cefazolin. +- Source: [Practice Guidelines for Skin and Soft Tissue Infections](https://www.idsociety.org/practice-guideline/skin-and-soft-tissue-infections/) +- Publisher: Infectious Diseases Society of America +- Supports: Moderate nonpurulent cellulitis requires systemic antibiotics; + cefazolin covers streptococci and MSSA, while MRSA coverage is reserved for + defined risk factors or severe infection. +- Accessed: 2026-07-13 +- Reviewer: Codex + +## step3-hematology-hemophilia-hemarthrosis-928 + +- Source: [WFH Guidelines for the Management of Hemophilia, 3rd Edition: Prophylaxis](https://www1.wfh.org/publications/files/pdf-1907.pdf) +- Publisher: World Federation of Hemophilia +- Supports: Children with severe hemophilia should receive early, regular + prophylaxis; long-term prophylaxis reduces hemarthrosis, slows hemophilic + arthropathy, and improves joint outcomes compared with episodic treatment. +- Source: [About Hemophilia](https://www.cdc.gov/hemophilia/about/index.html) +- Publisher: Centers for Disease Control and Prevention +- Supports: Joint bleeding is a common manifestation of hemophilia and can cause + chronic joint disease and pain; regular prophylaxis can prevent most bleeding + episodes. +- Source: [Testing for Inhibitors and Hemophilia](https://www.cdc.gov/hemophilia/testing/testing-for-inhibitors-and-hemophilia.html) +- Publisher: Centers for Disease Control and Prevention +- Supports: Factor VIII inhibitors are a separate serious treatment complication + that can render replacement factor ineffective and warrant regular testing. +- Accessed: 2026-07-13 +- Reviewer: Codex + +## step3-cardiovascular-aaa-surveillance-930 + +- Source: [2022 ACC/AHA Aortic Disease Guideline: Key Perspectives](https://www.acc.org/Latest-in-Cardiology/ten-points-to-remember/2022/11/01/12/21/2022-Guideline-on-Aortic-Disease-2-gl-ad) +- Publisher: American College of Cardiology / American Heart Association +- Supports: Men with an AAA measuring 4.0-4.9 cm should undergo annual + surveillance; repair is recommended at 5.5 cm or for aneurysm-related symptoms. +- Source: [Patients with Abdominal Aortic Aneurysm](https://vascular.org/node/87) +- Publisher: Society for Vascular Surgery +- Supports: AAA measuring 4.0-4.9 cm should receive surveillance imaging at + 12-month intervals; vascular-surgery referral is recommended at diagnosis. +- Accessed: 2026-07-13 +- Reviewer: Codex + +## step3-gastrointestinal-bowel-obstruction-imaging-731 + +- Source: [ACR Appropriateness Criteria: Suspected Small-Bowel Obstruction](https://acsearch.acr.org/docs/69476/Narrative/) +- Publisher: American College of Radiology +- Supports: CT abdomen and pelvis with intravenous contrast is preferred for + acute suspected obstruction because it identifies the level, cause, bowel + perfusion, and complications; oral contrast is unnecessary in high-grade SBO. +- Source: [ASGE Guideline on Colonic Volvulus and Acute Colonic Pseudo-Obstruction](https://www.asge.org/docs/default-source/guidelines/american-society-for-gastrointestinal-endoscopy-guideline-on-the-role-of-endoscopy-in-the-management-of-acute-colonic-pseudo-obstruction-and-colonic-volvulus-2020-february-gie.pdf) +- Publisher: American Society for Gastrointestinal Endoscopy +- Supports: Cross-sectional CT distinguishes volvulus, pseudo-obstruction, and + other mechanical obstruction and has replaced plain radiography as the + preferred diagnostic study for suspected sigmoid or cecal volvulus. +- Accessed: 2026-07-13 +- Reviewer: Codex + +## step3-preventive-cervical-screening-sexual-orientation-932 + +- Source: [Screening for Cervical Cancer](https://www.acog.org/clinical/clinical-guidance/committee-statement/articles/2026/07/screening-for-cervical-cancer) +- Publisher: American College of Obstetricians and Gynecologists +- Supports: Under the 2026 ACOG/WPSI guidance, average-risk patients age 21-29 + years should receive cervical cytology alone every 3 years. +- Source: [Women Who Have Sex with Women](https://www.cdc.gov/std/treatment-guidelines/wsw.htm) +- Publisher: Centers for Disease Control and Prevention +- Supports: HPV can be transmitted between female partners, and routine cervical + cancer screening should be offered regardless of sexual orientation or practices. +- Source: [HPV Infection and Vaccination](https://www.acog.org/womens-health/faqs/hpv-vaccination) +- Publisher: American College of Obstetricians and Gynecologists +- Supports: HPV vaccination does not protect against all HPV types and does not + remove the need for age-appropriate cervical cancer screening. +- Accessed: 2026-07-13 +- Reviewer: Codex + +## step3-cardiovascular-risk-smoking-841 + +- Source: [Tobacco Smoking Cessation in Adults: Interventions](https://www.uspreventiveservicestaskforce.org/uspstf/recommendation/tobacco-use-in-adults-and-pregnant-women-counseling-and-interventions) +- Publisher: U.S. Preventive Services Task Force +- Supports: Adults who smoke should receive behavioral interventions and + FDA-approved pharmacotherapy; the net benefit of cessation treatment is substantial. +- Source: [Smoking and Cardiovascular Disease](https://www.cdc.gov/tobacco/patient-care/care-settings/pdfs/cdc-osh-hcp-cardio-factsheet-508.pdf) +- Publisher: Centers for Disease Control and Prevention +- Supports: Smoking cessation improves cardiovascular health, with coronary + heart disease risk falling sharply within 1-2 years after cessation. +- Source: [Aspirin Use to Prevent Cardiovascular Disease](https://www.uspreventiveservicestaskforce.org/uspstf/recommendation/aspirin-to-prevent-cardiovascular-disease-preventive-medication) +- Publisher: U.S. Preventive Services Task Force +- Supports: For adults age 40-59 years with elevated cardiovascular risk, + aspirin initiation is individualized because the average net benefit is small. +- Source: [Vitamin and Multivitamin Supplementation to Prevent CVD and Cancer](https://www.uspreventiveservicestaskforce.org/uspstf/recommendation/vitamin-supplementation-to-prevent-cvd-and-cancer-preventive-medication) +- Publisher: U.S. Preventive Services Task Force +- Supports: Evidence is insufficient to recommend multivitamins for preventing + cardiovascular disease, and trials have not shown cardiovascular mortality benefit. +- Accessed: 2026-07-13 +- Reviewer: Codex + +## step3-cardiovascular-exercise-hdl-614 + +- Source: [Physical Activity as First-Line Treatment for Elevated Blood Pressure or Cholesterol](https://professional.heart.org/en/science-news/physical-activity-as-a-critical-component-of-first-line-treatment-for-elevated-bp-or-cholesterol/top-things-to-know) +- Publisher: American Heart Association +- Supports: At least 150 minutes of moderate aerobic activity weekly raises HDL + by about 1-2 mg/dL, lowers LDL by 3-6 mg/dL and triglycerides by 4-12 mg/dL, + and lowers systolic and diastolic blood pressure by roughly 3-4 mm Hg. +- Source: [Physical Activity Guidelines for Americans, 2nd Edition](https://health.gov/sites/default/files/2019-09/Physical_Activity_Guidelines_2nd_edition.pdf) +- Publisher: U.S. Department of Health and Human Services +- Supports: Regular activity improves blood pressure and lipid profiles, and + substantial cardiovascular benefit occurs at 150 minutes of moderate activity weekly. +- Accessed: 2026-07-13 +- Reviewer: Codex + +## step3-musculoskeletal-lateral-ankle-sprain-935 + +- Source: [Lateral Ankle Ligament Sprains Clinical Practice Guideline](https://www.orthopt.org/uploads/content_files/files/jospt.2021.0302.pdf) +- Publisher: Academy of Orthopaedic Physical Therapy / Journal of Orthopaedic & Sports Physical Therapy +- Supports: Acute lateral ankle sprains should receive external support and + progressive weight bearing; intermittent ice may be used with therapeutic exercise. +- Source: [ACR Appropriateness Criteria: Acute Trauma to the Ankle](https://acsearch.acr.org/docs/69436/Narrative/) +- Publisher: American College of Radiology +- Supports: Ankle radiography is usually not appropriate when Ottawa ankle rules + are negative, with no relevant bony tenderness and preserved four-step ambulation. +- Source: [Sprained Ankle](https://orthoinfo.aaos.org/en/diseases--conditions/sprained-ankle/) +- Publisher: American Academy of Orthopaedic Surgeons +- Supports: Mild sprains are treated conservatively with early weight bearing, + removable support when needed, and early functional rehabilitation. +- Accessed: 2026-07-13 +- Reviewer: Codex + +## step3-obstetrics-prenatal-cocaine-exposure-674 + +- Source: [Cocaine](https://www.ncbi.nlm.nih.gov/books/NBK582649/) +- Publisher: MotherToBaby / Organization of Teratology Information Specialists +- Supports: Late prenatal cocaine exposure can be followed by irritability, + tremors, stiffness, poor feeding, sleep disturbance, and hyperactivity; exposure + also increases risks of low birth weight, prematurity, and placental abruption. +- Source: [Neonatal Drug Withdrawal](https://publications.aap.org/pediatrics/article/129/2/e540/32573/Neonatal-Drug-Withdrawal) +- Publisher: American Academy of Pediatrics +- Supports: Cocaine-exposed neonates can have irritability, hyperactivity, + tremors, and feeding abnormalities, but a distinct stimulant abstinence + syndrome is not clearly defined and findings may reflect residual drug effect. +- Source: [Management of Stillbirth](https://www.acog.org/clinical/clinical-guidance/obstetric-care-consensus/articles/2020/03/management-of-stillbirth) +- Publisher: American College of Obstetricians and Gynecologists +- Supports: Maternal cocaine and tobacco use are important contributors to + placental abruption and stillbirth risk. +- Accessed: 2026-07-13 +- Reviewer: Codex + +## step3-fetal-alcohol-earlyintervention-037 + +- Source: [Treatment of Fetal Alcohol Spectrum Disorders](https://www.cdc.gov/fasd/treatment/index.html) +- Publisher: Centers for Disease Control and Prevention +- Supports: Early intervention can improve development; infants and toddlers + with fetal alcohol syndrome commonly qualify immediately without waiting for + an established developmental delay. +- Source: [IDEA Regulation 34 CFR 303.21: Infant or Toddler with a Disability](https://sites.ed.gov/idea/regs/c/a/303.21) +- Publisher: U.S. Department of Education +- Supports: Part C eligibility includes diagnosed conditions with a high + probability of developmental delay and specifically names fetal alcohol syndrome. +- Source: [IDEA Part C Early Intervention Program](https://www.ed.gov/grants-and-programs/formula-grants/formula-grants-special-populations/idea-early-intervention-program-infants-and-toddlers-disabilities-part-c) +- Publisher: U.S. Department of Education +- Supports: Part C provides coordinated, multidisciplinary, family-centered + services for eligible children from birth through age 2 years. +- Accessed: 2026-07-13 +- Reviewer: Codex + +## step3-congenital-hypothyroidism-adoptedinfant-038 + +- Source: [Congenital Hypothyroidism: Screening and Management](https://publications.aap.org/pediatrics/article/151/1/e2022060419/190311/Congenital-Hypothyroidism-Screening-and-Management) +- Publisher: American Academy of Pediatrics +- Supports: Confirmed congenital hypothyroidism requires prompt levothyroxine; + treatment timing is critical for neurodevelopment, and imaging must never delay therapy. +- Source: [Congenital Hypothyroidism](https://www.thyroid.org/congenital-hypothyroidism/) +- Publisher: American Thyroid Association +- Supports: Low free T4 with elevated TSH confirms primary congenital + hypothyroidism; levothyroxine is standard treatment with frequent biochemical + monitoring and pediatric endocrine follow-up. +- Accessed: 2026-07-13 +- Reviewer: Codex + +## step3-delirium-collateral-history-039 + +- Source: [Delirium: prevention, diagnosis and management](https://www.nice.org.uk/guidance/cg103/chapter/Recommendations) +- Publisher: National Institute for Health and Care Excellence +- Supports: Recent changes or fluctuations suggesting delirium may be reported + by a relative or carer; identified cases require formal delirium assessment and + evaluation and management of contributing causes. +- Source: [Dementia: assessment, management and support](https://www.nice.org.uk/guidance/ng97/chapter/Recommendations) +- Publisher: National Institute for Health and Care Excellence +- Supports: Initial cognitive assessment includes history from the patient and, + when possible, someone who knows the patient well to characterize cognition, + behavior, and effects on daily life. +- Source: [Syphilis: STI Treatment Guidelines](https://www.cdc.gov/std/treatment-guidelines/syphilis.htm) +- Publisher: Centers for Disease Control and Prevention +- Supports: A reactive nontreponemal test such as RPR requires confirmation with + a treponemal test; a single serologic test is insufficient for diagnosis. +- Accessed: 2026-07-13 +- Reviewer: Codex + +## step3-pediatrics-physiologic-anemia-infancy-940 + +- Source: [Well Care for Formerly Preterm Infants](https://publications.aap.org/first1000days/module/27506/section/1cd7f046-cb2d-4e02-b460-4ffc870c33e9) +- Publisher: American Academy of Pediatrics +- Supports: Physiologic anemia in term infants reaches a hemoglobin nadir at + approximately 8-12 weeks, later and at a higher level than in preterm infants. +- Source: [Perinatal Anemia](https://www.msdmanuals.com/professional/pediatrics/perinatal-hematologic-disorders/perinatal-anemia) +- Publisher: MSD Manual Professional Edition +- Supports: Increased oxygenation after birth suppresses erythropoietin and + erythropoiesis; the shorter neonatal erythrocyte lifespan also contributes to + the fall over the first 2-3 months, followed by recovery without treatment in + healthy term infants. +- Source: [Pathophysiology of Anemia During the Neonatal Period, Including Anemia of Prematurity](https://pmc.ncbi.nlm.nih.gov/articles/PMC2867612/) +- Publisher: NeoReviews / U.S. National Library of Medicine +- Supports: Healthy term infants are generally asymptomatic as hemoglobin falls + to its physiologic nadir at approximately 8-10 weeks and then gradually rises. +- Accessed: 2026-07-13 +- Reviewer: Codex + +## step3-oncology-metastatic-adenocarcinoma-prognosis-941 + +- Source: [Cancer of Unknown Primary Treatment (PDQ), Health Professional Version](https://www.cancer.gov/types/unknown-primary/hp/unknown-primary-treatment-pdq) +- Publisher: National Cancer Institute +- Supports: CUP generally has poor prognosis, with approximately 30% of patients + alive at 1 year; adenocarcinoma histology, older age, hepatic involvement, poor + performance status, and elevated LDH are associated with worse survival. +- Source: [SEOM-GECOD Clinical Guideline for Cancer of Unknown Primary, Update 2025](https://pmc.ncbi.nlm.nih.gov/articles/PMC13099792/) +- Publisher: Spanish Society of Medical Oncology / Springer Nature +- Supports: Approximately 80% of CUP cases belong to an unfavorable subgroup + with median overall survival of roughly 6-12 months; performance status and LDH + further refine prognosis, and selected favorable clinicopathologic subsets + require separate management. +- Accessed: 2026-07-13 +- Reviewer: Codex + +## step3-geriatrics-depression-weightloss-mirtazapine-942 + +- Source: [Unintentional Weight Loss in Older Adults](https://www.aafp.org/pubs/afp/issues/2021/0700/p34.html) +- Publisher: American Academy of Family Physicians +- Supports: Mirtazapine can cause appetite increase and weight gain when used to + treat depression, but evidence does not support prescribing it solely as an + appetite stimulant; somnolence and dizziness may increase fall risk. +- Source: [Choosing Wisely](https://www.healthinaging.org/choosing-wisely) +- Publisher: American Geriatrics Society / Health in Aging Foundation +- Supports: Avoid prescription appetite stimulants for nonspecific anorexia in + older adults; megestrol has minimal benefit and increases thrombotic events, + fluid retention, and death, whereas mirtazapine may increase appetite when it + is being used for coexisting depression. +- Source: [American Geriatrics Society 2023 Updated AGS Beers Criteria](https://agsjournals.onlinelibrary.wiley.com/doi/10.1111/jgs.18372) +- Publisher: American Geriatrics Society +- Supports: Megestrol should be avoided in older adults because its effect on + weight is minimal and it increases thrombotic events and possibly death. +- Accessed: 2026-07-13 +- Reviewer: Codex + +## step3-postoperative-fluid-overload-diuresis-943 + +- Source: [Acute Heart Failure: Diagnosis and Management](https://www.nice.org.uk/guidance/cg187/chapter/Recommendations) +- Publisher: National Institute for Health and Care Excellence +- Supports: Acute pulmonary congestion should be treated with intravenous loop + diuretics, with close monitoring of renal function, weight, and urine output; + ventilatory support is considered when severe respiratory failure or persistent + distress is present. +- Source: [2013 ACCF/AHA Guideline for the Management of Heart Failure, Executive Summary](https://www.acc.org/~/media/Non-Clinical/Files-PDFs-Excel-MS-Word-etc/Tools%20and%20Practice%20Support/Quality%20Programs/Heart%20Failure%20Roundtable%202016/Heart%20Failure%20Guidelines/HFG%203%202013%20ACCFAHA%20Guideline.pdf) +- Publisher: American College of Cardiology / American Heart Association +- Supports: Hospitalized patients with significant fluid overload should receive + prompt intravenous loop diuretics, with serial assessment of urine output, + congestion, renal function, and electrolytes. +- Source: [Diuretic Therapy for Patients With Heart Failure](https://www.acc.org/latest-in-cardiology/ten-points-to-remember/2020/03/09/15/28/Diuretic-Therapy-for-Patients-With-Heart-Failure) +- Publisher: American College of Cardiology +- Supports: Loop diuretic dosing is guided by volume status and decongestion; + renal function changes must be interpreted in the context of persistent congestion. +- Accessed: 2026-07-13 +- Reviewer: Codex + +## step3-cardiovascular-white-coat-hypertension-device-check-944 + +- Source: [Home Blood Pressure Monitoring](https://www.heart.org/en/health-topics/high-blood-pressure/understanding-blood-pressure-readings/monitoring-your-blood-pressure-at-home) +- Publisher: American Heart Association +- Supports: Patients should use a validated upper-arm device with the correct + cuff size, bring it to clinic so accuracy and technique can be checked, and use + standardized preparation, positioning, and repeated measurements. +- Source: [Device Calibration Test for Self-Measured Blood Pressure Devices](https://www.ama-assn.org/system/files/2019-04/smbp-device-accuracy-test.pdf) +- Publisher: American Medical Association +- Supports: When home results are unreasonably discrepant from office results, + compare sequential readings from the patient's device and a validated office + device after confirming proper preparation, positioning, and technique. +- Source: [Harmonization of ACC/AHA and ESC/ESH Blood Pressure Guidelines](https://www.acc.org/latest-in-cardiology/ten-points-to-remember/2022/08/22/16/48/harmonization-of-the-acc-aha) +- Publisher: American College of Cardiology +- Supports: Accurate measurement using validated devices and multiple readings + is foundational; home or ambulatory monitoring is recommended to identify and + confirm white-coat and masked blood pressure patterns. +- Accessed: 2026-07-13 +- Reviewer: Codex diff --git a/README.md b/README.md index a357e48..f208459 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,94 @@ The Godot client reads this from `project.godot`: step3/questions_api_url ``` +## Question Image Copyright Review + +All questions containing images must receive a copyright and licensing review +before publication or distribution. This applies both to newly submitted images +and to every image already stored in the question bank. + +For each image-bearing question, document: + +- the original source and creator, when known; +- the applicable license or written permission; +- whether attribution is required and where it is displayed; +- whether the image was modified or generated; +- the reviewer and review date. + +Do not publish an image when its source or reuse rights cannot be established. +Remove or replace images that fail review. Images added for development or +manual testing are not exempt from this requirement. + +Outstanding action: audit every existing question with a non-empty `media` +field before treating the current question bank as cleared for release. + +## Question Text Originality Review + +Every question must also receive an originality and copyright review before +publication or distribution. Review the stem, lead-in, answer choices, +explanations, follow-up questions, teaching points, and distinctive combinations +of patient details for substantial overlap with copyrighted question banks, +books, articles, screenshots, or other source material. + +Changing only names, ages, individual values, or a few words is not sufficient +when the structure, sequence, and expression remain recognizably derived from a +copyrighted source. Clinical facts and concepts may be used, but each question +must express them independently with original organization and wording. + +For each reviewed question, document the reviewer, review date, any reference +materials consulted, and whether revisions were required. Do not publish a +question when substantial textual or structural overlap remains unresolved. + +Outstanding action: perform this review for every existing question in the +question bank, not only newly submitted questions, before considering the bank +cleared for release. + +## Question Verification References + +Every question must provide direct reference links to authoritative sources +that allow reviewers to verify the clinical, scientific, statistical, or +ethical information used in the stem, answer key, and explanation. References +are required before publication, even when the tested fact is considered +standard knowledge. + +Prefer current primary or authoritative sources, including professional society +guidelines, government health agencies, original research, and official drug or +product labeling. Use secondary sources only when a suitable primary or +authoritative source is unavailable. Link to the specific guideline, article, +or document rather than a search-results page or an organization's home page. + +For each question, document: + +- at least one direct reference URL; +- the title and publishing organization for each reference; +- which key claim or teaching point the reference supports; +- the date the source was accessed and the reviewer who verified it. + +References must support the keyed answer and any management recommendations, +diagnostic thresholds, formulas, or numerical claims. A citation does not grant +permission to copy wording or media; the separate text-originality and image- +copyright requirements still apply. If the question schema does not expose a +reference field, retain this information in the associated authoring or review +record until it can be stored with the question. + +## Duplicate Question Review + +Every question must be checked for duplicates before publication. This review +must detect both exact duplicates and near-duplicates that test the same concept +with substantially equivalent stems, decisive findings, lead-ins, answer sets, +or teaching objectives despite different wording or external IDs. + +Repeated coverage of a learning objective is acceptable when the presentation, +reasoning path, or learner task is meaningfully different. Reject exact copies +and near-duplicates that merely change a patient age, reorder answers, or make +minor value and wording changes. When substantial duplication remains, retain +the stronger question, merge any useful unique teaching material, and remove or +substantially differentiate the other version. + +Document the reviewer, review date, compared question IDs, and disposition of +each potential duplicate. Outstanding action: run this review across the entire +existing question bank before considering it cleared for release. + ## Push Build `.github/workflows/questions-api.yml` builds and publishes the Questions API Docker image to GitHub Container Registry on pushes to `main`. diff --git a/api/QuestionsApi/Controllers/QuestionReportsController.cs b/api/QuestionsApi/Controllers/QuestionReportsController.cs new file mode 100644 index 0000000..f202fef --- /dev/null +++ b/api/QuestionsApi/Controllers/QuestionReportsController.cs @@ -0,0 +1,125 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using QuestionsApi.Models; +using QuestionsApi.Services; +using System.Security.Claims; + +namespace QuestionsApi.Controllers; + +[ApiController] +[Route("api/question-reports")] +public class QuestionReportsController : ControllerBase +{ + private const int MinDetailsLength = 10; + private const int MaxDetailsLength = 2000; + private const int MaxReviewerNoteLength = 2000; + + private readonly QuestionStore _questions; + private readonly QuestionReportStore _reports; + + public QuestionReportsController(QuestionStore questions, QuestionReportStore reports) + { + _questions = questions; + _reports = reports; + } + + [HttpPost] + [Authorize(Roles = "USER,SUPER")] + public async Task Create([FromBody] CreateQuestionReportRequest request) + { + var questionExternalId = (request.QuestionExternalId ?? "").Trim(); + var category = (request.Category ?? "").Trim().ToLowerInvariant(); + var details = (request.Details ?? "").Trim(); + + if (string.IsNullOrWhiteSpace(questionExternalId)) + return BadRequest("questionExternalId required"); + if (!QuestionReportCategory.All.Contains(category)) + return BadRequest("category is invalid"); + if (details.Length < MinDetailsLength || details.Length > MaxDetailsLength) + return BadRequest($"details must be between {MinDetailsLength} and {MaxDetailsLength} characters"); + + var question = await _questions.GetByExternalIdAsync(questionExternalId); + if (question is null || (!question.IsPublished && !User.IsInRole("SUPER"))) + return NotFound(); + + var userId = CurrentUserId(); + if (string.IsNullOrWhiteSpace(userId)) + return Unauthorized(); + + var report = await _reports.CreateAsync(question, userId, category, details); + return StatusCode(StatusCodes.Status201Created, new CreateQuestionReportResponse + { + Id = report.Id ?? "", + QuestionExternalId = report.QuestionExternalId, + Category = report.Category, + Status = report.Status, + CreatedUtc = report.CreatedUtc + }); + } + + [HttpGet] + [Authorize(Roles = "SUPER")] + public async Task List( + [FromQuery] string status = QuestionReportStatus.Open, + [FromQuery] string category = "", + [FromQuery] string questionExternalId = "", + [FromQuery] string userId = "", + [FromQuery] int skip = 0, + [FromQuery] int limit = 50) + { + status = status.Trim().ToLowerInvariant(); + category = category.Trim().ToLowerInvariant(); + questionExternalId = questionExternalId.Trim(); + userId = userId.Trim(); + + if (status != "all" && status != QuestionReportStatus.Open && !QuestionReportStatus.Terminal.Contains(status)) + return BadRequest("status is invalid"); + if (!string.IsNullOrWhiteSpace(category) && !QuestionReportCategory.All.Contains(category)) + return BadRequest("category is invalid"); + if (skip < 0) + return BadRequest("skip must be zero or greater"); + if (limit is < 1 or > 100) + return BadRequest("limit must be between 1 and 100"); + + return Ok(await _reports.SearchAsync(status, category, questionExternalId, userId, skip, limit)); + } + + [HttpGet("{id}")] + [Authorize(Roles = "SUPER")] + public async Task Get(string id) + { + var report = await _reports.GetByIdAsync(id.Trim()); + return report is null ? NotFound() : Ok(report); + } + + [HttpPatch("{id}/status")] + [Authorize(Roles = "SUPER")] + public async Task UpdateStatus(string id, [FromBody] UpdateQuestionReportStatusRequest request) + { + var status = (request.Status ?? "").Trim().ToLowerInvariant(); + var reviewerNote = (request.ReviewerNote ?? "").Trim(); + if (!QuestionReportStatus.Terminal.Contains(status)) + return BadRequest("status must be resolved or dismissed"); + if (reviewerNote.Length > MaxReviewerNoteLength) + return BadRequest($"reviewerNote must be {MaxReviewerNoteLength} characters or fewer"); + + var existing = await _reports.GetByIdAsync(id.Trim()); + if (existing is null) + return NotFound(); + if (existing.Status != QuestionReportStatus.Open) + return Conflict("report is already closed"); + + var reviewerUserId = CurrentUserId(); + if (string.IsNullOrWhiteSpace(reviewerUserId)) + return Unauthorized(); + + var updated = await _reports.CloseAsync(id.Trim(), status, reviewerUserId, reviewerNote); + return updated is null ? Conflict("report is already closed") : Ok(updated); + } + + private string CurrentUserId() => + User.FindFirstValue(ClaimTypes.NameIdentifier) + ?? User.FindFirstValue(ClaimTypes.Name) + ?? User.Identity?.Name + ?? ""; +} diff --git a/api/QuestionsApi/Models/QuestionReport.cs b/api/QuestionsApi/Models/QuestionReport.cs new file mode 100644 index 0000000..f8bc829 --- /dev/null +++ b/api/QuestionsApi/Models/QuestionReport.cs @@ -0,0 +1,96 @@ +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Attributes; + +namespace QuestionsApi.Models; + +public static class QuestionReportCategory +{ + public const string Clarity = "clarity"; + public const string MedicalAccuracy = "medical_accuracy"; + public const string AnswerExplanation = "answer_explanation"; + public const string FormattingMedia = "formatting_media"; + public const string TechnicalIssue = "technical_issue"; + public const string Other = "other"; + + public static readonly HashSet All = + [ + Clarity, + MedicalAccuracy, + AnswerExplanation, + FormattingMedia, + TechnicalIssue, + Other + ]; +} + +public static class QuestionReportStatus +{ + public const string Open = "open"; + public const string Resolved = "resolved"; + public const string Dismissed = "dismissed"; + + public static readonly HashSet Terminal = [Resolved, Dismissed]; +} + +public class QuestionReport +{ + [BsonId] + [BsonRepresentation(BsonType.ObjectId)] + public string? Id { get; set; } + + public string QuestionExternalId { get; set; } = ""; + public string QuestionMongoId { get; set; } = ""; + public string UserId { get; set; } = ""; + public string Category { get; set; } = ""; + public string Details { get; set; } = ""; + public string Status { get; set; } = QuestionReportStatus.Open; + public QuestionReportSnapshot QuestionSnapshot { get; set; } = new(); + public string ReviewedByUserId { get; set; } = ""; + public string ReviewerNote { get; set; } = ""; + public DateTime? ReviewedUtc { get; set; } + public DateTime CreatedUtc { get; set; } = DateTime.UtcNow; + public DateTime UpdatedUtc { get; set; } = DateTime.UtcNow; +} + +public class QuestionReportSnapshot +{ + public string Stem { get; set; } = ""; + public string LeadIn { get; set; } = ""; + public List Choices { get; set; } = []; + public string CorrectChoiceId { get; set; } = ""; + public string Explanation { get; set; } = ""; + public Dictionary ChoiceExplanations { get; set; } = []; + public Dictionary WrongAnswerFollowups { get; set; } = []; + public List Labs { get; set; } = []; + public List Media { get; set; } = []; +} + +public class CreateQuestionReportRequest +{ + public string QuestionExternalId { get; set; } = ""; + public string Category { get; set; } = ""; + public string Details { get; set; } = ""; +} + +public class CreateQuestionReportResponse +{ + public string Id { get; set; } = ""; + public string QuestionExternalId { get; set; } = ""; + public string Category { get; set; } = ""; + public string Status { get; set; } = QuestionReportStatus.Open; + public DateTime CreatedUtc { get; set; } +} + +public class UpdateQuestionReportStatusRequest +{ + public string Status { get; set; } = ""; + public string ReviewerNote { get; set; } = ""; +} + +public class QuestionReportListResponse +{ + public List Items { get; set; } = []; + public long Total { get; set; } + public int Skip { get; set; } + public int Limit { get; set; } +} diff --git a/api/QuestionsApi/Program.cs b/api/QuestionsApi/Program.cs index 9abc1d1..64e1dfa 100644 --- a/api/QuestionsApi/Program.cs +++ b/api/QuestionsApi/Program.cs @@ -12,6 +12,7 @@ builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); +builder.Services.AddSingleton(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(c => diff --git a/api/QuestionsApi/README.md b/api/QuestionsApi/README.md index 333e809..66fec1a 100644 --- a/api/QuestionsApi/README.md +++ b/api/QuestionsApi/README.md @@ -12,5 +12,15 @@ STEP-style question bank service for study games and clients. - `POST /api/questions/bulk` Upsert questions by `externalId` (SUPER only). - `PUT /api/questions/{id}` Update question (SUPER only). - `DELETE /api/questions/{id}` Delete question (SUPER only). +- `POST /api/question-reports` Submit a categorized question report (USER or SUPER). +- `GET /api/question-reports` List and filter reports, newest first (SUPER only). +- `GET /api/question-reports/{id}` Get a report and its question snapshot (SUPER only). +- `PATCH /api/question-reports/{id}/status` Resolve or dismiss an open report (SUPER only). Player reads require `USER` or `SUPER` JWT auth. Authoring endpoints require `SUPER`. + +Questions submitted through authoring endpoints must have authoritative direct +reference links recorded as described in the repository's **Question +Verification References** policy. The references must verify the keyed answer +and the material claims in the explanation; search-result links are not +acceptable. diff --git a/api/QuestionsApi/Services/QuestionReportStore.cs b/api/QuestionsApi/Services/QuestionReportStore.cs new file mode 100644 index 0000000..52ec8f6 --- /dev/null +++ b/api/QuestionsApi/Services/QuestionReportStore.cs @@ -0,0 +1,146 @@ +using MongoDB.Bson; +using MongoDB.Driver; +using QuestionsApi.Models; + +namespace QuestionsApi.Services; + +public class QuestionReportStore +{ + private readonly IMongoCollection _reports; + + public QuestionReportStore(IConfiguration cfg) + { + var connectionString = cfg["MongoDB:ConnectionString"] ?? "mongodb://127.0.0.1:27017"; + var databaseName = cfg["MongoDB:DatabaseName"] ?? "GameDb"; + var client = new MongoClient(connectionString); + var database = client.GetDatabase(databaseName); + _reports = database.GetCollection("QuestionReports"); + + _reports.Indexes.CreateMany( + [ + new CreateIndexModel( + Builders.IndexKeys + .Ascending(r => r.Status) + .Descending(r => r.CreatedUtc)), + new CreateIndexModel( + Builders.IndexKeys.Ascending(r => r.QuestionExternalId)), + new CreateIndexModel( + Builders.IndexKeys.Ascending(r => r.UserId)) + ]); + } + + public async Task CreateAsync(Question question, string userId, string category, string details) + { + var now = DateTime.UtcNow; + var report = new QuestionReport + { + QuestionExternalId = question.ExternalId, + QuestionMongoId = question.Id ?? "", + UserId = userId, + Category = category, + Details = details, + Status = QuestionReportStatus.Open, + QuestionSnapshot = new QuestionReportSnapshot + { + Stem = question.Stem, + LeadIn = question.LeadIn, + Choices = question.Choices + .Select(choice => new QuestionChoice { Id = choice.Id, Text = choice.Text }) + .ToList(), + CorrectChoiceId = question.CorrectChoiceId, + Explanation = question.Explanation, + ChoiceExplanations = new Dictionary(question.ChoiceExplanations), + WrongAnswerFollowups = question.WrongAnswerFollowups.ToDictionary( + item => item.Key, + item => new WrongAnswerFollowup + { + Prompt = item.Value.Prompt, + Choices = item.Value.Choices + .Select(choice => new QuestionChoice { Id = choice.Id, Text = choice.Text }) + .ToList(), + CorrectChoiceId = item.Value.CorrectChoiceId, + TeachingPoint = item.Value.TeachingPoint + }), + Labs = question.Labs + .Select(lab => new QuestionLab + { + Name = lab.Name, + Value = lab.Value, + Unit = lab.Unit, + Reference = lab.Reference + }) + .ToList(), + Media = [.. question.Media] + }, + CreatedUtc = now, + UpdatedUtc = now + }; + + await _reports.InsertOneAsync(report); + return report; + } + + public async Task GetByIdAsync(string id) + { + if (!ObjectId.TryParse(id, out _)) + return null; + return await _reports.Find(r => r.Id == id).FirstOrDefaultAsync(); + } + + public async Task SearchAsync( + string status, + string category, + string questionExternalId, + string userId, + int skip, + int limit) + { + var filter = Builders.Filter.Empty; + if (!string.Equals(status, "all", StringComparison.OrdinalIgnoreCase)) + filter &= Builders.Filter.Eq(r => r.Status, status); + if (!string.IsNullOrWhiteSpace(category)) + filter &= Builders.Filter.Eq(r => r.Category, category); + if (!string.IsNullOrWhiteSpace(questionExternalId)) + filter &= Builders.Filter.Eq(r => r.QuestionExternalId, questionExternalId); + if (!string.IsNullOrWhiteSpace(userId)) + filter &= Builders.Filter.Eq(r => r.UserId, userId); + + var total = await _reports.CountDocumentsAsync(filter); + var items = await _reports + .Find(filter) + .SortByDescending(r => r.CreatedUtc) + .Skip(skip) + .Limit(limit) + .ToListAsync(); + + return new QuestionReportListResponse + { + Items = items, + Total = total, + Skip = skip, + Limit = limit + }; + } + + public async Task CloseAsync(string id, string status, string reviewerUserId, string reviewerNote) + { + if (!ObjectId.TryParse(id, out _)) + return null; + + var now = DateTime.UtcNow; + var filter = Builders.Filter.And( + Builders.Filter.Eq(r => r.Id, id), + Builders.Filter.Eq(r => r.Status, QuestionReportStatus.Open)); + var update = Builders.Update + .Set(r => r.Status, status) + .Set(r => r.ReviewerNote, reviewerNote) + .Set(r => r.ReviewedByUserId, reviewerUserId) + .Set(r => r.ReviewedUtc, now) + .Set(r => r.UpdatedUtc, now); + + return await _reports.FindOneAndUpdateAsync( + filter, + update, + new FindOneAndUpdateOptions { ReturnDocument = ReturnDocument.After }); + } +} diff --git a/assets/question_images/alopecia-areata-occipital-001.png b/assets/question_images/alopecia-areata-occipital-001.png new file mode 100644 index 0000000..46d8524 Binary files /dev/null and b/assets/question_images/alopecia-areata-occipital-001.png differ diff --git a/assets/question_images/alopecia-areata-occipital-001.png.import b/assets/question_images/alopecia-areata-occipital-001.png.import new file mode 100644 index 0000000..9363887 --- /dev/null +++ b/assets/question_images/alopecia-areata-occipital-001.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b1ul1abd3ancy" +path="res://.godot/imported/alopecia-areata-occipital-001.png-cac14e23748bed69672554273e867cf9.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/question_images/alopecia-areata-occipital-001.png" +dest_files=["res://.godot/imported/alopecia-areata-occipital-001.png-cac14e23748bed69672554273e867cf9.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/question_images/asbestos-ferruginous-body-528.png b/assets/question_images/asbestos-ferruginous-body-528.png new file mode 100644 index 0000000..d8b0363 Binary files /dev/null and b/assets/question_images/asbestos-ferruginous-body-528.png differ diff --git a/assets/question_images/asbestos-ferruginous-body-528.png.import b/assets/question_images/asbestos-ferruginous-body-528.png.import new file mode 100644 index 0000000..2e9c209 --- /dev/null +++ b/assets/question_images/asbestos-ferruginous-body-528.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cf3a0cl2atyw8" +path="res://.godot/imported/asbestos-ferruginous-body-528.png-e5de794a289107157349231884cf169c.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/question_images/asbestos-ferruginous-body-528.png" +dest_files=["res://.godot/imported/asbestos-ferruginous-body-528.png-e5de794a289107157349231884cf169c.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/question_images/atrial-fibrillation-controlled-response-5172.png b/assets/question_images/atrial-fibrillation-controlled-response-5172.png new file mode 100644 index 0000000..2a912f4 Binary files /dev/null and b/assets/question_images/atrial-fibrillation-controlled-response-5172.png differ diff --git a/assets/question_images/atrial-fibrillation-controlled-response-5172.png.import b/assets/question_images/atrial-fibrillation-controlled-response-5172.png.import new file mode 100644 index 0000000..1bc6ed3 --- /dev/null +++ b/assets/question_images/atrial-fibrillation-controlled-response-5172.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://2phukqqwkr0j" +path="res://.godot/imported/atrial-fibrillation-controlled-response-5172.png-9fe67e541e5dbd55542ed0f497a51d66.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/question_images/atrial-fibrillation-controlled-response-5172.png" +dest_files=["res://.godot/imported/atrial-fibrillation-controlled-response-5172.png-9fe67e541e5dbd55542ed0f497a51d66.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/question_images/hsv-grouped-vesicles-mucocutaneous-3041.png b/assets/question_images/hsv-grouped-vesicles-mucocutaneous-3041.png new file mode 100644 index 0000000..9a9cfbc Binary files /dev/null and b/assets/question_images/hsv-grouped-vesicles-mucocutaneous-3041.png differ diff --git a/assets/question_images/hsv-grouped-vesicles-mucocutaneous-3041.png.import b/assets/question_images/hsv-grouped-vesicles-mucocutaneous-3041.png.import new file mode 100644 index 0000000..fbfb7fa --- /dev/null +++ b/assets/question_images/hsv-grouped-vesicles-mucocutaneous-3041.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cgaj6mqqk8txf" +path="res://.godot/imported/hsv-grouped-vesicles-mucocutaneous-3041.png-4f4d86d3e278d5b18e7cf944720c4403.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/question_images/hsv-grouped-vesicles-mucocutaneous-3041.png" +dest_files=["res://.godot/imported/hsv-grouped-vesicles-mucocutaneous-3041.png-4f4d86d3e278d5b18e7cf944720c4403.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/question_images/huntington-pedigree-3528.png b/assets/question_images/huntington-pedigree-3528.png new file mode 100644 index 0000000..837f17a Binary files /dev/null and b/assets/question_images/huntington-pedigree-3528.png differ diff --git a/assets/question_images/huntington-pedigree-3528.png.import b/assets/question_images/huntington-pedigree-3528.png.import new file mode 100644 index 0000000..be4cfe3 --- /dev/null +++ b/assets/question_images/huntington-pedigree-3528.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c12lrclgs8xtp" +path="res://.godot/imported/huntington-pedigree-3528.png-ef596230c5e63c2dbbdf5e9df3061b8f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/question_images/huntington-pedigree-3528.png" +dest_files=["res://.godot/imported/huntington-pedigree-3528.png-ef596230c5e63c2dbbdf5e9df3061b8f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/question_images/huntington-pedigree-3528.svg b/assets/question_images/huntington-pedigree-3528.svg new file mode 100644 index 0000000..6951c19 --- /dev/null +++ b/assets/question_images/huntington-pedigree-3528.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + I + II + III + At-risk husband + Wife + + diff --git a/assets/question_images/huntington-pedigree-3528.svg.import b/assets/question_images/huntington-pedigree-3528.svg.import new file mode 100644 index 0000000..d80100d --- /dev/null +++ b/assets/question_images/huntington-pedigree-3528.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dvprnn2mwq7h0" +path="res://.godot/imported/huntington-pedigree-3528.svg-b6915e7f1c86a790ca2b1d9134425a60.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/question_images/huntington-pedigree-3528.svg" +dest_files=["res://.godot/imported/huntington-pedigree-3528.svg-b6915e7f1c86a790ca2b1d9134425a60.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/assets/question_images/papilledema-fundus-original.png b/assets/question_images/papilledema-fundus-original.png new file mode 100644 index 0000000..f7d4588 Binary files /dev/null and b/assets/question_images/papilledema-fundus-original.png differ diff --git a/assets/question_images/papilledema-fundus-original.png.import b/assets/question_images/papilledema-fundus-original.png.import new file mode 100644 index 0000000..fc7d56b --- /dev/null +++ b/assets/question_images/papilledema-fundus-original.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cg0f4dp5l5puy" +path="res://.godot/imported/papilledema-fundus-original.png-e6cfd47dd210cfce0b1895feccd9bdf7.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/question_images/papilledema-fundus-original.png" +dest_files=["res://.godot/imported/papilledema-fundus-original.png-e6cfd47dd210cfce0b1895feccd9bdf7.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/question_images/pcp-diffuse-bilateral-interstitial-cxr-2801.png b/assets/question_images/pcp-diffuse-bilateral-interstitial-cxr-2801.png new file mode 100644 index 0000000..8e47b98 Binary files /dev/null and b/assets/question_images/pcp-diffuse-bilateral-interstitial-cxr-2801.png differ diff --git a/assets/question_images/pcp-diffuse-bilateral-interstitial-cxr-2801.png.import b/assets/question_images/pcp-diffuse-bilateral-interstitial-cxr-2801.png.import new file mode 100644 index 0000000..9b60b90 --- /dev/null +++ b/assets/question_images/pcp-diffuse-bilateral-interstitial-cxr-2801.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dq7r8yq65kutq" +path="res://.godot/imported/pcp-diffuse-bilateral-interstitial-cxr-2801.png-9b10bd4d25c9c74ad7b984ef2a458d32.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/question_images/pcp-diffuse-bilateral-interstitial-cxr-2801.png" +dest_files=["res://.godot/imported/pcp-diffuse-bilateral-interstitial-cxr-2801.png-9b10bd4d25c9c74ad7b984ef2a458d32.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/question_images/pediatric-left-lower-lobe-postobstructive-pneumonia.png b/assets/question_images/pediatric-left-lower-lobe-postobstructive-pneumonia.png new file mode 100644 index 0000000..8a1530c Binary files /dev/null and b/assets/question_images/pediatric-left-lower-lobe-postobstructive-pneumonia.png differ diff --git a/assets/question_images/pediatric-left-lower-lobe-postobstructive-pneumonia.png.import b/assets/question_images/pediatric-left-lower-lobe-postobstructive-pneumonia.png.import new file mode 100644 index 0000000..e95e91f --- /dev/null +++ b/assets/question_images/pediatric-left-lower-lobe-postobstructive-pneumonia.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://blladq71aek48" +path="res://.godot/imported/pediatric-left-lower-lobe-postobstructive-pneumonia.png-65c5f5042ce198b18c2a8356a93ca274.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/question_images/pediatric-left-lower-lobe-postobstructive-pneumonia.png" +dest_files=["res://.godot/imported/pediatric-left-lower-lobe-postobstructive-pneumonia.png-65c5f5042ce198b18c2a8356a93ca274.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/question_images/step3-cardiology-preop-ecg-incidental-552.png b/assets/question_images/step3-cardiology-preop-ecg-incidental-552.png new file mode 100644 index 0000000..e00fae3 Binary files /dev/null and b/assets/question_images/step3-cardiology-preop-ecg-incidental-552.png differ diff --git a/assets/question_images/step3-cardiology-preop-ecg-incidental-552.png.import b/assets/question_images/step3-cardiology-preop-ecg-incidental-552.png.import new file mode 100644 index 0000000..dc033e0 --- /dev/null +++ b/assets/question_images/step3-cardiology-preop-ecg-incidental-552.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dpbme1e646oto" +path="res://.godot/imported/step3-cardiology-preop-ecg-incidental-552.png-98ee131255d583fc3b714377bb7f05e2.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/question_images/step3-cardiology-preop-ecg-incidental-552.png" +dest_files=["res://.godot/imported/step3-cardiology-preop-ecg-incidental-552.png-98ee131255d583fc3b714377bb7f05e2.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/question_images/step3-infectious-bacterial-meningitis-3001.png b/assets/question_images/step3-infectious-bacterial-meningitis-3001.png new file mode 100644 index 0000000..10c3dd2 Binary files /dev/null and b/assets/question_images/step3-infectious-bacterial-meningitis-3001.png differ diff --git a/assets/question_images/step3-infectious-bacterial-meningitis-3001.png.import b/assets/question_images/step3-infectious-bacterial-meningitis-3001.png.import new file mode 100644 index 0000000..858b358 --- /dev/null +++ b/assets/question_images/step3-infectious-bacterial-meningitis-3001.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://daws5c8gngey" +path="res://.godot/imported/step3-infectious-bacterial-meningitis-3001.png-d415a86d7d931dce1df2789095c995e1.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/question_images/step3-infectious-bacterial-meningitis-3001.png" +dest_files=["res://.godot/imported/step3-infectious-bacterial-meningitis-3001.png-d415a86d7d931dce1df2789095c995e1.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/project.godot b/project.godot index 9701333..4bd67f4 100644 --- a/project.godot +++ b/project.godot @@ -40,3 +40,4 @@ rendering_device/driver.windows="d3d12" [step3] questions_api_url="https://s3q.ranaze.com/api/questions/search" +question_reports_api_url="https://s3q.ranaze.com/api/question-reports" diff --git a/scripts/autoload/question_bank_service.gd b/scripts/autoload/question_bank_service.gd index 2f04bff..bb69c4f 100644 --- a/scripts/autoload/question_bank_service.gd +++ b/scripts/autoload/question_bank_service.gd @@ -4,6 +4,7 @@ const DEFAULT_QUESTIONS_API_URL := "https://s3q.ranaze.com/api/questions/search" const DEFAULT_QUESTION_ATTEMPT_API_URL := "https://s3q.ranaze.com/api/questions/attempts/first" const DEFAULT_QUESTION_API_BASE_URL := "https://s3q.ranaze.com/api/questions" const DEFAULT_RATINGS_API_URL := "https://s3q.ranaze.com/api/ratings/me" +const DEFAULT_QUESTION_REPORTS_API_URL := "https://s3q.ranaze.com/api/question-reports" const RETRY_DELAYS := [2, 5, 10, 20, 30] signal questions_changed @@ -12,17 +13,21 @@ signal choice_percentages_updated(question_id: String, percentages: Dictionary) signal ratings_changed signal question_rating_updated(question_id: String, question_elo: int, rating: Dictionary) signal question_skipped(question_id: String, correct_choice_id: String, question_elo: int, rating: Dictionary) +signal question_report_submitted(question_id: String, report_id: String) +signal question_report_failed(question_id: String, message: String) var questions: Array = [] var request: HTTPRequest var attempt_request: HTTPRequest var rating_request: HTTPRequest var skip_request: HTTPRequest +var report_request: HTTPRequest var retry_timer: Timer var questions_api_url := DEFAULT_QUESTIONS_API_URL var question_attempt_api_url := DEFAULT_QUESTION_ATTEMPT_API_URL var question_api_base_url := DEFAULT_QUESTION_API_BASE_URL var ratings_api_url := DEFAULT_RATINGS_API_URL +var question_reports_api_url := DEFAULT_QUESTION_REPORTS_API_URL var is_loading := false var last_error := "" var load_state := "idle" @@ -32,12 +37,14 @@ var overall_elo := 1000 var rated_question_count := 0 var category_elos := {} var last_rating_change := {} +var pending_report_question_id := "" func _ready() -> void: questions_api_url = str(ProjectSettings.get_setting("step3/questions_api_url", DEFAULT_QUESTIONS_API_URL)) question_attempt_api_url = str(ProjectSettings.get_setting("step3/question_attempt_api_url", DEFAULT_QUESTION_ATTEMPT_API_URL)) question_api_base_url = str(ProjectSettings.get_setting("step3/question_api_base_url", DEFAULT_QUESTION_API_BASE_URL)) ratings_api_url = str(ProjectSettings.get_setting("step3/ratings_api_url", DEFAULT_RATINGS_API_URL)) + question_reports_api_url = str(ProjectSettings.get_setting("step3/question_reports_api_url", DEFAULT_QUESTION_REPORTS_API_URL)) request = HTTPRequest.new() request.request_completed.connect(_on_api_questions_loaded) add_child(request) @@ -54,6 +61,10 @@ func _ready() -> void: skip_request.request_completed.connect(_on_question_skipped) add_child(skip_request) + report_request = HTTPRequest.new() + report_request.request_completed.connect(_on_question_report_submitted) + add_child(report_request) + retry_timer = Timer.new() retry_timer.one_shot = true retry_timer.timeout.connect(_on_retry_timer_timeout) @@ -135,6 +146,8 @@ func clear_questions() -> void: rating_request.cancel_request() if skip_request != null: skip_request.cancel_request() + if report_request != null: + report_request.cancel_request() if retry_timer != null: retry_timer.stop() questions.clear() @@ -147,6 +160,7 @@ func clear_questions() -> void: rated_question_count = 0 category_elos = {} last_rating_change = {} + pending_report_question_id = "" questions_changed.emit() ratings_changed.emit() @@ -182,6 +196,37 @@ func skip_question(question_id: String) -> void: push_warning("Failed to record skipped question.") +func submit_question_report(question_id: String, category: String, details: String) -> bool: + if AuthState.access_token.is_empty() or question_id == "": + question_report_failed.emit(question_id, "Login is required to submit a report.") + return false + if report_request.get_http_client_status() != HTTPClient.STATUS_DISCONNECTED: + question_report_failed.emit(question_id, "Another report is still being submitted.") + return false + + var headers := PackedStringArray([ + "Content-Type: application/json", + "Authorization: Bearer %s" % AuthState.access_token + ]) + var payload := { + "questionExternalId": question_id, + "category": category, + "details": details + } + pending_report_question_id = question_id + var err := report_request.request( + question_reports_api_url, + headers, + HTTPClient.METHOD_POST, + JSON.stringify(payload) + ) + if err != OK: + pending_report_question_id = "" + question_report_failed.emit(question_id, "The report could not be submitted. Please try again.") + return false + return true + + func load_ratings_from_api() -> void: if AuthState.access_token.is_empty(): return @@ -305,6 +350,35 @@ func _on_question_skipped(result: int, response_code: int, _headers: PackedStrin question_skipped.emit(question_id, correct_choice_id, question_elo, rating) +func _on_question_report_submitted(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void: + var parsed: Variant = JSON.parse_string(body.get_string_from_utf8()) + var question_id := "" + if typeof(parsed) == TYPE_DICTIONARY: + question_id = str(parsed.get("questionExternalId", parsed.get("question_external_id", ""))) + if question_id == "": + question_id = pending_report_question_id + pending_report_question_id = "" + + if result != HTTPRequest.RESULT_SUCCESS or response_code < 200 or response_code >= 300: + var message := "The report could not be submitted. Please try again." + if typeof(parsed) == TYPE_DICTIONARY: + message = str(parsed.get("detail", parsed.get("title", message))) + elif typeof(parsed) == TYPE_STRING and not str(parsed).strip_edges().is_empty(): + message = str(parsed).strip_edges() + question_report_failed.emit(question_id, message) + return + + if typeof(parsed) != TYPE_DICTIONARY: + question_report_failed.emit(question_id, "The report API returned an invalid response.") + return + + var report_id := str(parsed.get("id", "")) + if question_id == "" or report_id == "": + question_report_failed.emit(question_id, "The report API returned an incomplete response.") + return + question_report_submitted.emit(question_id, report_id) + + func _on_ratings_loaded(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void: if result != HTTPRequest.RESULT_SUCCESS or response_code < 200 or response_code >= 300: push_warning("Ratings API request failed with status %d." % response_code) diff --git a/scripts/ui/question_player.gd b/scripts/ui/question_player.gd index 4630a4d..fc17a96 100644 --- a/scripts/ui/question_player.gd +++ b/scripts/ui/question_player.gd @@ -6,6 +6,16 @@ const CORRECT_ADVANCE_DELAY_SECONDS := 1.25 const TEXT_SCALE_MIN := 0.85 const TEXT_SCALE_MAX := 1.35 const TEXT_SCALE_STEP := 0.1 +const REPORT_DETAILS_MIN := 10 +const REPORT_DETAILS_MAX := 2000 +const REPORT_CATEGORIES := [ + {"id": "clarity", "label": "Clarity"}, + {"id": "medical_accuracy", "label": "Medical accuracy"}, + {"id": "answer_explanation", "label": "Answer / explanation"}, + {"id": "formatting_media", "label": "Formatting / media"}, + {"id": "technical_issue", "label": "Technical issue"}, + {"id": "other", "label": "Other"} +] var main: Control var choice_buttons: Array[Button] = [] @@ -54,6 +64,20 @@ var feedback_fog: ColorRect var labs_overlay: Control var labs_panel: PanelContainer var labs_content: VBoxContainer +var report_overlay: Control +var report_panel: PanelContainer +var report_form_content: VBoxContainer +var report_success_content: VBoxContainer +var report_category_group: ButtonGroup +var report_category_buttons: Array[CheckBox] = [] +var report_details: TextEdit +var report_char_count: Label +var report_error_label: Label +var report_submit_button: Button +var report_cancel_button: Button +var report_success_label: Label +var report_is_submitting := false +var report_question_id := "" var media_requests: Array[HTTPRequest] = [] var red_fog_time := 0.0 var green_fog_time := 0.0 @@ -76,6 +100,10 @@ func _ready() -> void: QuestionBankService.ratings_changed.connect(_refresh_player_stats) if not AuthState.auth_changed.is_connected(_refresh_player_stats): AuthState.auth_changed.connect(_refresh_player_stats) + if not QuestionBankService.question_report_submitted.is_connected(_on_question_report_submitted): + QuestionBankService.question_report_submitted.connect(_on_question_report_submitted) + if not QuestionBankService.question_report_failed.is_connected(_on_question_report_failed): + QuestionBankService.question_report_failed.connect(_on_question_report_failed) var top := HBoxContainer.new() top.add_theme_constant_override("separation", 12) @@ -156,6 +184,8 @@ func _ready() -> void: report_button.tooltip_text = "Report question" report_button.icon = _make_report_icon() report_button.custom_minimum_size = Vector2(44, 44) + Style.style_chip(report_button, Style.CYAN) + UISoundService.set_button_sound(report_button, "open") report_button.pressed.connect(_toggle_report_current_question) question_toolbar.add_child(report_button) @@ -326,17 +356,23 @@ func _ready() -> void: add_child(feedback_fog) _build_labs_modal() + _build_report_modal() func on_show(_payload: Variant = null) -> void: _load_question() +func on_hide() -> void: + _hide_report_modal(true) + _hide_labs_modal() + + func _process(delta: float) -> void: _update_answer_feedback(delta) if visible and BlockSessionService.block_started and BlockSessionService.session_kind == "core": _update_timer_bar() - if visible and BlockSessionService.block_started and BlockSessionService.mode == "Timed": + if visible and BlockSessionService.block_started and BlockSessionService.mode == "Timed" and (report_overlay == null or not report_overlay.visible): BlockSessionService.seconds_remaining = max(0.0, BlockSessionService.seconds_remaining - delta) var shown_seconds := int(ceil(BlockSessionService.seconds_remaining)) var minutes := int(floor(float(shown_seconds) / 60.0)) @@ -346,6 +382,10 @@ func _process(delta: float) -> void: func _input(event: InputEvent) -> void: + if report_overlay != null and report_overlay.visible and event.is_action_pressed("ui_cancel"): + _hide_report_modal() + get_viewport().set_input_as_handled() + return if labs_overlay != null and labs_overlay.visible and event.is_action_pressed("ui_cancel"): _hide_labs_modal() get_viewport().set_input_as_handled() @@ -367,6 +407,7 @@ func _input(event: InputEvent) -> void: func _load_question() -> void: + _hide_report_modal(true) _reset_wrong_feedback() _hide_labs_modal() eliminated.clear() @@ -785,11 +826,7 @@ func _toggle_report_current_question() -> void: var question_id := str(BlockSessionService.get_current_question().get("id", "")) if question_id == "": return - if reported_question_ids.has(question_id): - reported_question_ids.erase(question_id) - else: - reported_question_ids.append(question_id) - _refresh_toolbar_state() + _show_report_modal(question_id) func _refresh_toolbar_state() -> void: @@ -799,6 +836,7 @@ func _refresh_toolbar_state() -> void: if report_button != null: var question_id := str(BlockSessionService.get_current_question().get("id", "")) Style.style_chip(report_button, Style.RED if reported_question_ids.has(question_id) else Style.CYAN) + report_button.tooltip_text = "Report submitted; report another issue" if reported_question_ids.has(question_id) else "Report question" func _refresh_player_stats() -> void: @@ -976,6 +1014,280 @@ func _on_media_loaded( status.visible = false +func _build_report_modal() -> void: + report_overlay = Control.new() + report_overlay.visible = false + report_overlay.top_level = true + report_overlay.mouse_filter = Control.MOUSE_FILTER_STOP + report_overlay.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + report_overlay.gui_input.connect(_report_overlay_gui_input) + add_child(report_overlay) + + var dim := ColorRect.new() + dim.color = Color(0.02, 0.03, 0.05, 0.78) + dim.mouse_filter = Control.MOUSE_FILTER_IGNORE + dim.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + report_overlay.add_child(dim) + + var center := CenterContainer.new() + center.mouse_filter = Control.MOUSE_FILTER_IGNORE + center.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + report_overlay.add_child(center) + + report_panel = PanelContainer.new() + report_panel.custom_minimum_size = Vector2(700, 600) + report_panel.mouse_filter = Control.MOUSE_FILTER_STOP + report_panel.add_theme_stylebox_override("panel", Style.panel_box(Color("172337"), Style.RED)) + center.add_child(report_panel) + + var modal_body := VBoxContainer.new() + modal_body.add_theme_constant_override("separation", 14) + report_panel.add_child(modal_body) + + var header := HBoxContainer.new() + header.add_theme_constant_override("separation", 10) + modal_body.add_child(header) + + var title := Label.new() + title.text = "Report question" + title.size_flags_horizontal = Control.SIZE_EXPAND_FILL + _set_scaled_label(title, 26, Style.TEXT) + header.add_child(title) + + var close_button := Button.new() + close_button.text = "X" + close_button.tooltip_text = "Close report form" + close_button.custom_minimum_size = Vector2(42, 38) + Style.style_chip(close_button, Style.RED) + UISoundService.set_button_sound(close_button, "close") + close_button.pressed.connect(_hide_report_modal) + header.add_child(close_button) + + report_form_content = VBoxContainer.new() + report_form_content.add_theme_constant_override("separation", 12) + modal_body.add_child(report_form_content) + + var category_label := Label.new() + category_label.text = "What is the problem?" + _set_scaled_label(category_label, 18, Style.CYAN) + report_form_content.add_child(category_label) + + var category_grid := GridContainer.new() + category_grid.columns = 2 + category_grid.add_theme_constant_override("h_separation", 18) + category_grid.add_theme_constant_override("v_separation", 8) + report_form_content.add_child(category_grid) + + report_category_group = ButtonGroup.new() + report_category_group.allow_unpress = false + for category in REPORT_CATEGORIES: + var category_button := CheckBox.new() + category_button.text = str(category["label"]) + category_button.set_meta("report_category_id", str(category["id"])) + category_button.button_group = report_category_group + category_button.size_flags_horizontal = Control.SIZE_EXPAND_FILL + category_button.custom_minimum_size = Vector2(0, 38) + _set_scaled_button_font(category_button, 16) + category_button.toggled.connect(_on_report_category_toggled) + category_grid.add_child(category_button) + report_category_buttons.append(category_button) + + var details_header := HBoxContainer.new() + report_form_content.add_child(details_header) + + var details_label := Label.new() + details_label.text = "Details" + details_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL + _set_scaled_label(details_label, 18, Style.CYAN) + details_header.add_child(details_label) + + report_char_count = Label.new() + report_char_count.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT + _set_scaled_label(report_char_count, 14, Style.MUTED) + details_header.add_child(report_char_count) + + report_details = TextEdit.new() + report_details.placeholder_text = "Describe what is wrong and what should be reviewed." + report_details.custom_minimum_size = Vector2(0, 190) + report_details.size_flags_vertical = Control.SIZE_EXPAND_FILL + report_details.wrap_mode = TextEdit.LINE_WRAPPING_BOUNDARY + report_details.add_theme_font_size_override("font_size", 16) + report_details.add_theme_color_override("font_color", Style.TEXT) + report_details.add_theme_color_override("font_placeholder_color", Style.MUTED) + report_details.add_theme_stylebox_override("normal", Style.panel_box(Style.SURFACE_DARK, Color("3b4964"))) + report_details.text_changed.connect(_on_report_details_changed) + report_form_content.add_child(report_details) + + report_error_label = Label.new() + report_error_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART + report_error_label.custom_minimum_size = Vector2(0, 28) + _set_scaled_label(report_error_label, 15, Style.RED) + report_form_content.add_child(report_error_label) + + var actions := HBoxContainer.new() + actions.add_theme_constant_override("separation", 10) + report_form_content.add_child(actions) + + report_cancel_button = Button.new() + report_cancel_button.text = "Cancel" + report_cancel_button.custom_minimum_size = Vector2(130, 46) + Style.style_chip(report_cancel_button, Style.MUTED) + UISoundService.set_button_sound(report_cancel_button, "close") + report_cancel_button.pressed.connect(_hide_report_modal) + actions.add_child(report_cancel_button) + + report_submit_button = Button.new() + report_submit_button.text = "Submit report" + report_submit_button.custom_minimum_size = Vector2(170, 46) + report_submit_button.size_flags_horizontal = Control.SIZE_EXPAND_FILL + Style.style_primary_button(report_submit_button) + UISoundService.set_button_sound(report_submit_button, "confirmation") + report_submit_button.pressed.connect(_submit_question_report) + actions.add_child(report_submit_button) + + report_success_content = VBoxContainer.new() + report_success_content.visible = false + report_success_content.size_flags_vertical = Control.SIZE_EXPAND_FILL + report_success_content.alignment = BoxContainer.ALIGNMENT_CENTER + report_success_content.add_theme_constant_override("separation", 18) + modal_body.add_child(report_success_content) + + report_success_label = Label.new() + report_success_label.text = "Report submitted" + report_success_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + report_success_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART + _set_scaled_label(report_success_label, 24, Style.LIME) + report_success_content.add_child(report_success_label) + + var success_close_button := Button.new() + success_close_button.text = "Close" + success_close_button.custom_minimum_size = Vector2(180, 48) + Style.style_primary_button(success_close_button) + UISoundService.set_button_sound(success_close_button, "close") + success_close_button.pressed.connect(_hide_report_modal) + report_success_content.add_child(success_close_button) + + _update_report_form_state() + + +func _report_overlay_gui_input(event: InputEvent) -> void: + var mouse_event := event as InputEventMouseButton + if mouse_event == null or not mouse_event.pressed or mouse_event.button_index != MOUSE_BUTTON_LEFT: + return + if report_panel != null and not report_panel.get_global_rect().has_point(mouse_event.global_position): + _hide_report_modal() + get_viewport().set_input_as_handled() + + +func _show_report_modal(question_id: String) -> void: + if report_overlay == null or report_is_submitting: + return + _hide_labs_modal() + report_question_id = question_id + report_form_content.visible = true + report_success_content.visible = false + report_details.text = "" + report_error_label.text = "" + for category_button in report_category_buttons: + category_button.button_pressed = false + _set_report_submitting(false) + _update_report_form_state() + report_overlay.visible = true + report_overlay.move_to_front() + BlockSessionService.pause_current_question_timer() + + +func _hide_report_modal(force: bool = false) -> void: + if report_overlay == null or (report_is_submitting and not force): + return + if report_overlay.visible: + report_overlay.visible = false + BlockSessionService.resume_current_question_timer() + if not report_is_submitting: + report_question_id = "" + + +func _on_report_category_toggled(pressed: bool) -> void: + if pressed: + _update_report_form_state() + + +func _on_report_details_changed() -> void: + _update_report_form_state() + + +func _selected_report_category() -> String: + if report_category_group == null: + return "" + var selected := report_category_group.get_pressed_button() + if selected == null: + return "" + return str(selected.get_meta("report_category_id", "")) + + +func _update_report_form_state() -> void: + if report_details == null or report_submit_button == null: + return + var details_length := report_details.text.strip_edges().length() + report_char_count.text = "%d / %d" % [details_length, REPORT_DETAILS_MAX] + report_char_count.add_theme_color_override("font_color", Style.RED if details_length > REPORT_DETAILS_MAX else Style.MUTED) + if not report_is_submitting: + report_error_label.text = "" + report_submit_button.disabled = ( + report_is_submitting + or _selected_report_category() == "" + or details_length < REPORT_DETAILS_MIN + or details_length > REPORT_DETAILS_MAX + ) + + +func _set_report_submitting(value: bool) -> void: + report_is_submitting = value + if report_details != null: + report_details.editable = not value + for category_button in report_category_buttons: + category_button.disabled = value + if report_cancel_button != null: + report_cancel_button.disabled = value + if report_submit_button != null: + report_submit_button.text = "Submitting..." if value else "Submit report" + _update_report_form_state() + + +func _submit_question_report() -> void: + if report_is_submitting or report_question_id == "": + return + var category := _selected_report_category() + var details := report_details.text.strip_edges() + if category == "" or details.length() < REPORT_DETAILS_MIN or details.length() > REPORT_DETAILS_MAX: + _update_report_form_state() + return + report_error_label.text = "" + _set_report_submitting(true) + QuestionBankService.submit_question_report(report_question_id, category, details) + + +func _on_question_report_submitted(question_id: String, _report_id: String) -> void: + if question_id != report_question_id: + return + _set_report_submitting(false) + if not reported_question_ids.has(question_id): + reported_question_ids.append(question_id) + _refresh_toolbar_state() + report_form_content.visible = false + report_success_content.visible = true + report_success_label.text = "Report submitted\nThank you for helping improve this question." + UISoundService.play_sound("confirmation") + + +func _on_question_report_failed(question_id: String, message: String) -> void: + if question_id != report_question_id: + return + _set_report_submitting(false) + report_error_label.text = message + UISoundService.play_sound("error") + + func _build_labs_modal() -> void: labs_overlay = Control.new() labs_overlay.visible = false