396 lines
14 KiB
Python
396 lines
14 KiB
Python
import pdfkit
|
|
from jinja2 import Environment, FileSystemLoader
|
|
|
|
env = Environment(loader=FileSystemLoader("report_gen"))
|
|
|
|
# Define templates and their unique contexts
|
|
pages = [
|
|
("page_1.html", {"name": "John Doe", "surname": "Moran", "date": "July 29, 2025"}),
|
|
("page_2.html", {"content": "This is page 2 content"}),
|
|
(
|
|
"page_3.html",
|
|
{
|
|
"patient_name": "Keirstyn Moran",
|
|
"age": "34",
|
|
"height": "5'4\"",
|
|
"weight": "123lbs",
|
|
"focus": "Endurance",
|
|
"fat_mass": "27.6lbs",
|
|
"fat_percentage": "22.4%",
|
|
"lean_mass": "95.4lbs",
|
|
"lean_percentage": "77.6%",
|
|
"body_fat_percent": "22.4%",
|
|
"age_range": "20-39",
|
|
"gender": "F",
|
|
"contact_email": "info@ishplabs.com",
|
|
"website": "www.ishplabs.com",
|
|
"social": "@ishplabs",
|
|
"page_number": "4",
|
|
"body_composition_chart": "../graphs/page_1_body_composition.png",
|
|
"body_fat_chart": "../graphs/page_1_body_fat.png",
|
|
},
|
|
),
|
|
(
|
|
"page_4.html",
|
|
{
|
|
"patient_name": "Keirstyn Moran",
|
|
"age": "34",
|
|
"height": "5'4\"",
|
|
"weight": "123lbs",
|
|
"focus": "Endurance",
|
|
"contact_email": "info@ishplabs.com",
|
|
"website": "www.ishplabs.com",
|
|
"social": "@ishplabs",
|
|
"page_number": "3",
|
|
},
|
|
),
|
|
(
|
|
"page_5.html",
|
|
{
|
|
"patient_name": "Keirstyn Moran",
|
|
"age": "34",
|
|
"height": "5'4\"",
|
|
"weight": "123lbs",
|
|
"focus": "Endurance",
|
|
"resting_calories": "1386kCals",
|
|
"fat_percentage": "33%",
|
|
"carb_percentage": "67%",
|
|
"neat_calories": "762kCals",
|
|
"weight_loss_calories": "423kCals",
|
|
"weight_loss_rate": "1.1lbs",
|
|
"total_calories": "~1725kCals",
|
|
"contact_email": "info@ishplabs.com",
|
|
"website": "www.ishplabs.com",
|
|
"social": "@ishplabs",
|
|
"page_number": "5",
|
|
},
|
|
),
|
|
(
|
|
"page_6.html",
|
|
{
|
|
"patient_name": "Keirstyn Moran",
|
|
"age": "34",
|
|
"height": "5'4\"",
|
|
"weight": "123lbs",
|
|
"focus": "Endurance",
|
|
"deficit_calories": "1725KCals",
|
|
"deficit_protein": "120g Protein",
|
|
"deficit_carbs": "155g Carbs",
|
|
"deficit_fat": "69g Fat",
|
|
"deficit_fiber": "25g Fibre",
|
|
"refeed_weekday_calories": "1615KCals",
|
|
"refeed_weekday_protein": "120g Protein",
|
|
"refeed_weekday_carbs": "142g Carbs",
|
|
"refeed_weekday_fat": "63g Fat",
|
|
"refeed_weekday_fiber": "24g Fibre",
|
|
"refeed_weekend_calories": "2000KCals",
|
|
"refeed_weekend_protein": "120g Protein",
|
|
"refeed_weekend_carbs": "190g Carbs",
|
|
"refeed_weekend_fat": "84g Fat",
|
|
"refeed_weekend_fiber": "30g Fibre",
|
|
"protein_percentage": "28%",
|
|
"carbs_percentage": "36%",
|
|
"fats_percentage": "36%",
|
|
"contact_email": "info@ishplabs.com",
|
|
"website": "www.ishplabs.com",
|
|
"social": "@ishplabs",
|
|
"page_number": "6",
|
|
},
|
|
),
|
|
(
|
|
"page_7.html",
|
|
{
|
|
"patient_name": "Keirstyn Moran",
|
|
"age": "34",
|
|
"height": "5'4\"",
|
|
"weight": "123lbs",
|
|
"focus": "Endurance",
|
|
"fvc_value": "4.24L → 112.0%",
|
|
"fev1_value": "3.26L → 103.3%",
|
|
"fev1_fvc_ratio": "76.89% → 91.8%",
|
|
"indication": "No Respiratory Capacity Limitation",
|
|
"respiratory_graph": "../graphs/respiratory_chart.png",
|
|
"peak_vt_value": "2.38L/Breath which occurs at 172bpm (Zone 3)",
|
|
"peak_vt_percentage": "73% of FEV1",
|
|
"contact_email": "info@ishplabs.com",
|
|
"website": "www.ishplabs.com",
|
|
"social": "@ishplabs",
|
|
"page_number": "7",
|
|
},
|
|
),
|
|
(
|
|
"page_8.html",
|
|
{
|
|
"patient_name": "Keirstyn Moran",
|
|
"age": "34",
|
|
"height": "5'4\"",
|
|
"weight": "123lbs",
|
|
"focus": "Endurance",
|
|
"vo2_max_value": "49.5",
|
|
"vo2_max_percentile": "100th percentile",
|
|
"age_range": "30-39",
|
|
"very_poor_range": "19.0-24.1",
|
|
"poor_range": "24.1-28.2",
|
|
"fair_range": "28.2-32.2",
|
|
"good_range": "32.2-35.7",
|
|
"excellent_range": "35.7-45.8",
|
|
"superior_range": "45.8+",
|
|
"zone1_percentage": "55-65% of Max Heart Rate",
|
|
"zone2_percentage": "65-75% of Max Heart Rate",
|
|
"zone3_percentage": "80-85% of Max Heart Rate",
|
|
"zone4_percentage": "85-88% of Max Heart Rate",
|
|
"zone5_percentage": "90% of Max Heart Rate",
|
|
"zone1_bpm": "81-96bpm",
|
|
"zone2_bpm": "96-100bpm",
|
|
"zone3_bpm": "100-178bpm",
|
|
"zone4_bpm": "178-188bpm",
|
|
"zone5_bpm": "188-198bpm",
|
|
"zone1_speed": "3.5mph",
|
|
"zone2_speed": "3.5-4.0mph",
|
|
"zone3_speed": "4.0-6.5mph",
|
|
"zone4_speed": "6.5-7.0mph",
|
|
"zone5_speed": "7.0-8.0mph",
|
|
"zone1_incline": "2% Incline",
|
|
"zone2_incline": "2% Incline",
|
|
"zone3_incline": "2% Incline",
|
|
"zone4_incline": "2% Incline",
|
|
"zone5_incline": "2% Incline",
|
|
"zone1_pace": "10:39min/km Pace",
|
|
"zone2_pace": "10:39-9:19min/km Pace",
|
|
"zone3_pace": "9:19-5:44min/km Pace",
|
|
"zone4_pace": "5:44-5:20min/km Pace",
|
|
"zone5_pace": "5:20-4:40min/km Pace",
|
|
"zone1_calories": "4.4kcals/minute",
|
|
"zone2_calories": "5.9kcals/minute",
|
|
"zone3_calories": "9.4kcals/minute",
|
|
"zone4_calories": "12.5kcals/minute",
|
|
"zone5_calories": "12.8kcals/minute",
|
|
"zone1_carb": "Avg: 0.4g/min Carb Utilization",
|
|
"zone2_carb": "Avg: 0.6g/min Carb Utilization",
|
|
"zone3_carb": "Avg: 1.9g/min Carb Utilization",
|
|
"zone4_carb": "Avg: 2.9g/min Carb Utilization",
|
|
"zone5_carb": "Avg: 3.1g/min Carb Utilization",
|
|
"zone1_breaths": "Avg: 27 breaths",
|
|
"zone2_breaths": "Avg: 28 breaths",
|
|
"zone3_breaths": "Avg: 31 breaths",
|
|
"zone4_breaths": "Avg: 42 breaths",
|
|
"zone5_breaths": "Avg: 51 breaths",
|
|
"zone1_breath_range": "Ideal Range: 15-20 breaths",
|
|
"zone2_breath_range": "Ideal Range: 20-25 breaths",
|
|
"zone3_breath_range": "Ideal Range: 25-30 breaths",
|
|
"zone4_breath_range": "Ideal Range: 30-35 breaths",
|
|
"zone5_breath_range": "Ideal Range: 40+ breaths",
|
|
"contact_email": "info@ishplabs.com",
|
|
"website": "www.ishplabs.com",
|
|
"social": "@ishplabs",
|
|
"page_number": "8",
|
|
},
|
|
),
|
|
(
|
|
"page_9.html",
|
|
{
|
|
"patient_name": "Keirstyn Moran",
|
|
"age": "34",
|
|
"height": "5'4\"",
|
|
"weight": "123lbs",
|
|
"focus": "Endurance",
|
|
"fuel_utilization_chart": "../graphs/fuel_utilization_chart.png",
|
|
"client_name": "Keirstyn Moran",
|
|
"assessment_date": "July 29 2025",
|
|
"contact_email": "info@ishplabs.com",
|
|
"website": "www.ishplabs.com",
|
|
"social": "@ishplabs",
|
|
"page_number": "9",
|
|
},
|
|
),
|
|
(
|
|
"page_10.html",
|
|
{
|
|
"patient_name": "Keirstyn Moran",
|
|
"age": "34",
|
|
"height": "5'4\"",
|
|
"weight": "123lbs",
|
|
"focus": "Endurance",
|
|
"vo2_pulse_drop_bpm": "180 bpm",
|
|
"vo2_pulse_drop_zone": "Zone 4",
|
|
"vo2_pulse_chart": "../graphs/vo2_pulse_chart.png",
|
|
"vo2_breath_drop_bpm": "173 bpm",
|
|
"vo2_breath_drop_zone": "Zone 3",
|
|
"vo2_breath_chart": "../graphs/vo2_breath_chart.png",
|
|
"contact_email": "info@ishplabs.com",
|
|
"website": "www.ishplabs.com",
|
|
"social": "@ishplabs",
|
|
"page_number": "9",
|
|
},
|
|
),
|
|
(
|
|
"page_11.html",
|
|
{
|
|
"patient_name": "Keirstyn Moran",
|
|
"age": "34",
|
|
"height": "5'4\"",
|
|
"weight": "123lbs",
|
|
"focus": "Endurance",
|
|
"fat_max_optimal": "*Optimal 10-12Kcals/minute",
|
|
"fat_max_value": "3.8Kcals/min",
|
|
"fat_max_heart_rate": "49% of Max Heart Rate",
|
|
"fat_max_bpm": "97 bpm",
|
|
"crossover_bpm": "100bpm",
|
|
"crossover_heart_rate": "51% of Max Heart Rate",
|
|
"fat_metabolism_note": "100bpm at a speed of 4.0mph and incline of 2%",
|
|
"fat_metabolism_chart": "../graphs/fat_metabolism_chart.png",
|
|
"cardiac_recovery_time": "(1 minute)",
|
|
"cardiac_recovery_percentage": "33%",
|
|
"metabolic_recovery_time": "(2 minute)",
|
|
"metabolic_recovery_percentage": "65%",
|
|
"breath_recovery_time": "(2.5 minute)",
|
|
"breath_recovery_percentage": "76%",
|
|
"recovery_chart": "../graphs/recovery_chart.png",
|
|
"resting_heart_rate": "53bpm",
|
|
"hr_age_range": "26-35",
|
|
"hr_poor": "82bpm +",
|
|
"hr_below_avg": "75-81bpm",
|
|
"hr_average": "71-74bpm",
|
|
"hr_above_avg": "66-70bpm",
|
|
"hr_good": "62-65bpm",
|
|
"hr_excellent": "55-61bpm",
|
|
"hr_athlete": "44-54bpm",
|
|
"contact_email": "info@ishplabs.com",
|
|
"website": "www.ishplabs.com",
|
|
"social": "@ishplabs",
|
|
"page_number": "10",
|
|
},
|
|
),
|
|
(
|
|
"page_13.html",
|
|
{
|
|
"patient_name": "Keirstyn Moran",
|
|
"age": "34",
|
|
"height": "5'4\"",
|
|
"weight": "123lbs",
|
|
"focus": "Endurance",
|
|
"zone2_frequency": "3-4x/week",
|
|
"zone2_duration": "40+ minutes",
|
|
"zone2_hr_range": "____",
|
|
"zone2_speed": "____ mph",
|
|
"zone2_incline": "2% Incline",
|
|
"zone3_frequency": "1-2x/week",
|
|
"zone3_duration": "10-20 minutes",
|
|
"zone3_hr_range": "____ bpm",
|
|
"zone3_speed": "____mph",
|
|
"zone3_incline": "2% Incline",
|
|
"zone3_target_hr": "___ bpm",
|
|
"zone3_recovery_speed": "____mph",
|
|
"zone3_recovery_incline": "2% Incline",
|
|
"zone1_hr_range": "____bpm",
|
|
"zone1_duration": "4-8 minutes",
|
|
"zone3_repeats": "2-3 times",
|
|
"short_sets": "8-10",
|
|
"short_duration": "10-30 seconds",
|
|
"short_zone": "5",
|
|
"short_rpe": "10",
|
|
"short_recovery": "20-60 seconds",
|
|
"medium_sets": "6-8",
|
|
"medium_duration": "30-90 seconds",
|
|
"medium_zone": "4",
|
|
"medium_rpe": "8-9",
|
|
"medium_recovery": "30-90 seconds",
|
|
"long_sets": "4-6",
|
|
"long_duration": "5-10 minutes",
|
|
"long_zone": "3/4",
|
|
"long_rpe": "7-8",
|
|
"long_recovery": "2.5-5 minutes",
|
|
"tempo_sets": "2-3",
|
|
"tempo_duration": "10-20 minutes",
|
|
"tempo_zone": "3",
|
|
"tempo_rpe": "6-7",
|
|
"tempo_recovery": "4-8 minutes",
|
|
"cardio_sets": "1",
|
|
"cardio_duration": ">40 minutes",
|
|
"cardio_zone": "2",
|
|
"cardio_rpe": "4-5",
|
|
"cardio_recovery": "N/A",
|
|
"week1_mon_zone": "Zone 2",
|
|
"week1_mon_duration": "45 mins",
|
|
"week1_tue_zone": "Zone 2",
|
|
"week1_tue_duration": "45 mins",
|
|
"week1_wed_zone": "Zone 3",
|
|
"week1_wed_duration1": "10mins On",
|
|
"week1_wed_duration2": "8mins Rest",
|
|
"week1_wed_sets": "x2",
|
|
"week1_thu_content": "",
|
|
"week1_fri_zone": "Zone 2",
|
|
"week1_fri_duration": "45 mins",
|
|
"week1_sat_content": "",
|
|
"week1_sun_content": "",
|
|
"week2_mon_zone": "Zone 2",
|
|
"week2_mon_duration": "50 mins",
|
|
"week2_tue_zone": "Zone 2",
|
|
"week2_tue_duration": "50 mins",
|
|
"week2_wed_zone": "Zone 3",
|
|
"week2_wed_duration1": "10mins On",
|
|
"week2_wed_duration2": "6mins Rest",
|
|
"week2_wed_sets": "x2",
|
|
"week2_thu_content": "",
|
|
"week2_fri_zone": "Zone 2",
|
|
"week2_fri_duration": "50 mins",
|
|
"week2_sat_content": "",
|
|
"week2_sun_content": "",
|
|
"contact_email": "info@ishplabs.com",
|
|
"website": "www.ishplabs.com",
|
|
"social": "@ishplabs",
|
|
"page_number": "12",
|
|
},
|
|
),
|
|
("page_14.html", {}),
|
|
("page_15.html", {}),
|
|
("page_16.html", {}),
|
|
("page_17.html", {}),
|
|
("page_18.html", {}),
|
|
("page_19.html", {}),
|
|
]
|
|
|
|
# Render each template with its own context
|
|
html_pages = []
|
|
for tpl, ctx in pages:
|
|
template = env.get_template(tpl)
|
|
html_pages.append(template.render(ctx))
|
|
|
|
# Combine with page breaks
|
|
final_html = "<div class='page-break'></div>".join(html_pages)
|
|
|
|
# Wrap in full HTML document
|
|
html_doc = f"""
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<link href="https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css" rel="stylesheet">
|
|
<style>
|
|
.page-break {{ page-break-after: always; }}
|
|
.page {{
|
|
height: 386mm;
|
|
}}
|
|
</style>
|
|
</head>
|
|
<body class="m-0 p-0">
|
|
{final_html}
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
print(html_doc)
|
|
# Generate PDF
|
|
options = {
|
|
"page-size": "A4",
|
|
"encoding": "UTF-8",
|
|
"margin-top": "0mm",
|
|
"margin-bottom": "0mm",
|
|
"margin-left": "0mm",
|
|
"margin-right": "0mm",
|
|
"no-outline": None,
|
|
}
|
|
pdfkit.from_string(html_doc, "multi_page_report.pdf", options=options)
|
|
|
|
print("✅ PDF generated: multi_page_report.pdf")
|