ecoverify-ai / pdf_module.py
lmcuong199's picture
Create pdf_module.py
9758500 verified
from fpdf import FPDF
from datetime import datetime
import tempfile
import os
class EcoVerifyReport(FPDF):
def header(self):
self.set_fill_color(45, 122, 79)
self.rect(0, 0, 210, 28, 'F')
self.set_font("Helvetica", "B", 16)
self.set_text_color(255, 255, 255)
self.set_xy(0, 8)
self.cell(0, 10, "EcoVerify AI - Official Site Report", align="C")
self.set_font("Helvetica", "", 9)
self.set_xy(0, 18)
self.cell(0, 6, "AI-powered Waste Management Verification for ASEAN Ecotourism", align="C")
self.set_text_color(0, 0, 0)
self.ln(18)
def footer(self):
self.set_y(-15)
self.set_font("Helvetica", "I", 8)
self.set_text_color(128, 128, 128)
self.cell(0, 10, f"Generated by EcoVerify AI | {datetime.now().strftime('%d %b %Y %H:%M')} | Page {self.page_no()}", align="C")
def section_title(self, title):
self.set_fill_color(240, 250, 244)
self.set_draw_color(45, 122, 79)
self.set_font("Helvetica", "B", 11)
self.set_text_color(30, 80, 50)
self.cell(0, 9, f" {title}", ln=True, fill=True, border="LB")
self.set_text_color(0, 0, 0)
self.ln(2)
def key_value(self, key, value, color=None):
self.set_font("Helvetica", "B", 10)
self.cell(70, 7, f" {key}:", ln=False)
self.set_font("Helvetica", "", 10)
if color:
self.set_text_color(*color)
self.cell(0, 7, str(value), ln=True)
self.set_text_color(0, 0, 0)
def body_text(self, text):
self.set_font("Helvetica", "", 10)
self.multi_cell(0, 6, f" {text}")
self.ln(1)
def risk_bar(self, label, score):
self.set_font("Helvetica", "", 9)
self.cell(55, 6, f" {label}", ln=False)
# Bar background
bar_x = self.get_x()
bar_y = self.get_y() + 1
self.set_fill_color(220, 220, 220)
self.rect(bar_x, bar_y, 80, 4, 'F')
# Bar fill
filled = score * 80
if score > 0.6:
self.set_fill_color(231, 76, 60)
elif score > 0.3:
self.set_fill_color(243, 156, 18)
else:
self.set_fill_color(46, 204, 113)
self.rect(bar_x, bar_y, filled, 4, 'F')
self.set_x(bar_x + 85)
self.set_font("Helvetica", "B", 9)
self.cell(20, 6, f"{score:.2f}", ln=True)
def generate_pdf(
site_name,
site_type,
site_size,
visitor_count,
nlp_risk,
img_risk,
combined_risk,
nlp_output,
img_output,
rec_output,
impact_output,
warn_output,
language="English"
) -> str:
pdf = EcoVerifyReport()
pdf.set_auto_page_break(auto=True, margin=20)
pdf.add_page()
# ── SITE INFO ─────────────────────────────────────────
pdf.section_title("Site Information")
pdf.key_value("Site Name", site_name)
pdf.key_value("Site Type", site_type)
pdf.key_value("Site Size", site_size)
pdf.key_value("Avg Visitors/day", str(int(visitor_count)))
pdf.key_value("Report Date", datetime.now().strftime("%d %B %Y"))
pdf.ln(4)
# ── RISK SUMMARY ──────────────────────────────────────
pdf.section_title("Risk Summary")
if combined_risk > 0.6:
verdict = "HIGH RISK - Greenwashing Suspected"
v_color = (231, 76, 60)
elif combined_risk > 0.3:
verdict = "MEDIUM RISK - Partial Inconsistency"
v_color = (243, 156, 18)
else:
verdict = "LOW RISK - Claims Appear Consistent"
v_color = (46, 204, 113)
pdf.key_value("Overall Verdict", verdict, color=v_color)
pdf.ln(2)
pdf.risk_bar("NLP Risk Score", nlp_risk)
pdf.risk_bar("Image Risk Score", img_risk)
pdf.risk_bar("Combined Risk Score", combined_risk)
pdf.ln(4)
# ── EARLY WARNING ─────────────────────────────────────
pdf.section_title("Early Warning Analysis")
clean_warn = _clean_text(warn_output)
pdf.body_text(clean_warn[:800])
pdf.ln(4)
# ── RECOMMENDATION ────────────────────────────────────
pdf.section_title("Waste Management Recommendation")
clean_rec = _clean_text(rec_output)
pdf.body_text(clean_rec[:1000])
pdf.ln(4)
# ── IMPACT ────────────────────────────────────────────
pdf.section_title("Environmental & Economic Impact")
waste_total = visitor_count * 0.5
unmanaged = waste_total * combined_risk
water_bod = round(unmanaged * 0.15, 2)
co2 = round(unmanaged * 2.5, 2) if combined_risk > 0.5 else 0.0
bad_cost = round(unmanaged * 1.5, 1)
good_cost = round(waste_total * 0.4, 1)
daily_save = round(max(bad_cost - good_cost, 0), 1)
annual_save = int(daily_save * 365)
pdf.key_value("Unmanaged Waste", f"{unmanaged:.1f} kg/day")
pdf.key_value("Water Pollution", f"{water_bod} kg BOD/day")
pdf.key_value("CO2 Emission", f"{co2} kg/day")
pdf.key_value("Current Cost", f"${bad_cost}/day")
pdf.key_value("Optimized Cost", f"${good_cost}/day")
pdf.key_value("Potential Savings", f"${annual_save:,}/year", color=(46, 204, 113))
pdf.ln(4)
# ── CERTIFICATION READINESS ───────────────────────────
pdf.section_title("ASEAN Certification Readiness")
waste_ready = round((1 - combined_risk) * 100)
water_ready = round((1 - combined_risk * 0.8) * 100)
energy_ready = round((1 - combined_risk * 0.6) * 100)
overall_ready = round((waste_ready + water_ready + energy_ready) / 3)
months_needed = max(1, round((100 - overall_ready) / 8))
pdf.risk_bar("Waste Management", 1 - waste_ready/100)
pdf.risk_bar("Wastewater", 1 - water_ready/100)
pdf.risk_bar("Energy Efficiency", 1 - energy_ready/100)
pdf.ln(2)
pdf.key_value("Overall Readiness", f"{overall_ready}%")
pdf.key_value("Est. Time to Certify", f"{months_needed} months")
pdf.ln(6)
# ── FOOTER NOTE ───────────────────────────────────────
pdf.set_font("Helvetica", "I", 8)
pdf.set_text_color(128, 128, 128)
pdf.multi_cell(0, 5,
"This report is generated by EcoVerify AI for informational purposes. "
"It supports post-certification monitoring and does not replace official inspection. "
"Built for AI ASEAN Ready Competition."
)
# ── SAVE ──────────────────────────────────────────────
tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf",
prefix=f"EcoVerify_{site_name.replace(' ','_')}_")
pdf.output(tmp.name)
return tmp.name
def _clean_text(text: str) -> str:
"""Strip markdown symbols cho PDF."""
import re
text = re.sub(r"#{1,6}\s?", "", text)
text = re.sub(r"\*{1,3}(.*?)\*{1,3}", r"\1", text)
text = re.sub(r"\|.*?\|", "", text)
text = re.sub(r"-{3,}", "", text)
text = re.sub(r"\n{3,}", "\n\n", text)
return text.strip()