ProfessorLeVesseur commited on
Commit
4f91af3
·
verified ·
1 Parent(s): 3d2f26f

Update report.py

Browse files
Files changed (1) hide show
  1. report.py +144 -32
report.py CHANGED
@@ -1,24 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import io
2
  from reportlab.lib.pagesizes import letter
3
  from reportlab.platypus import SimpleDocTemplate, Image, Paragraph, Spacer
4
  from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
5
- from reportlab.lib.enums import TA_JUSTIFY
6
  from reportlab.lib.units import inch
7
  import matplotlib.pyplot as plt
8
  import markdown
9
- from xml.etree import ElementTree as ET
10
  from PIL import Image as PILImage
11
- from xml.parsers.expat import ExpatError
12
- from html import escape
13
 
14
  class ReportGenerator:
15
  def __init__(self):
16
  self.styles = getSampleStyleSheet()
17
  self.styles.add(ParagraphStyle(name='Justify', alignment=TA_JUSTIFY))
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  def create_combined_pdf(self, intervention_fig, student_metrics_fig, recommendations):
20
  buffer = io.BytesIO()
21
- doc = SimpleDocTemplate(buffer, pagesize=letter)
22
 
23
  elements = []
24
 
@@ -81,32 +205,20 @@ class ReportGenerator:
81
  # Convert markdown to HTML
82
  html = markdown.markdown(recommendations)
83
 
84
- # Wrap the HTML in a root element to ensure valid XML
85
- wrapped_html = f"<root>{html}</root>"
86
-
87
- try:
88
- root = ET.fromstring(wrapped_html)
89
- except ExpatError:
90
- # If parsing fails, fallback to treating the entire content as plain text
91
- elements.append(Paragraph(escape(recommendations), self.styles['BodyText']))
92
- return elements
93
-
94
- for elem in root:
95
- if elem.tag == 'h3':
96
- elements.append(Paragraph(elem.text or "", self.styles['Heading3']))
97
- elif elem.tag == 'h4':
98
- elements.append(Paragraph(elem.text or "", self.styles['Heading4']))
99
- elif elem.tag == 'p':
100
- text = ''.join(elem.itertext())
101
- elements.append(Paragraph(text, self.styles['Justify']))
102
- elif elem.tag == 'ul':
103
- for li in elem.findall('li'):
104
- bullet_text = '• ' + ''.join(li.itertext()).strip()
105
- elements.append(Paragraph(bullet_text, self.styles['BodyText']))
106
- else:
107
- # For any other tags, just extract the text
108
- text = ''.join(elem.itertext())
109
- if text.strip():
110
- elements.append(Paragraph(text, self.styles['BodyText']))
111
 
112
  return elements
 
1
+ # import io
2
+ # from reportlab.lib.pagesizes import letter
3
+ # from reportlab.platypus import SimpleDocTemplate, Image, Paragraph, Spacer
4
+ # from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
5
+ # from reportlab.lib.enums import TA_JUSTIFY
6
+ # from reportlab.lib.units import inch
7
+ # import matplotlib.pyplot as plt
8
+ # import markdown
9
+ # from xml.etree import ElementTree as ET
10
+ # from PIL import Image as PILImage
11
+ # from xml.parsers.expat import ExpatError
12
+ # from html import escape
13
+
14
+ # class ReportGenerator:
15
+ # def __init__(self):
16
+ # self.styles = getSampleStyleSheet()
17
+ # self.styles.add(ParagraphStyle(name='Justify', alignment=TA_JUSTIFY))
18
+
19
+ # def create_combined_pdf(self, intervention_fig, student_metrics_fig, recommendations):
20
+ # buffer = io.BytesIO()
21
+ # doc = SimpleDocTemplate(buffer, pagesize=letter)
22
+
23
+ # elements = []
24
+
25
+ # elements.extend(self._add_chart(intervention_fig, "Intervention Dosage"))
26
+ # elements.extend(self._add_chart(student_metrics_fig, "Student Attendance and Engagement"))
27
+ # elements.extend(self._add_recommendations(recommendations))
28
+
29
+ # doc.build(elements)
30
+ # buffer.seek(0)
31
+ # return buffer
32
+
33
+ # def _add_chart(self, fig, title):
34
+ # elements = []
35
+ # elements.append(Paragraph(title, self.styles['Heading2']))
36
+ # img_buffer = io.BytesIO()
37
+
38
+ # if hasattr(fig, 'write_image'): # Plotly figure
39
+ # fig.write_image(img_buffer, format="png", width=700, height=400)
40
+ # elif isinstance(fig, plt.Figure): # Matplotlib figure
41
+ # fig.set_size_inches(10, 6) # Set a consistent size
42
+ # fig.savefig(img_buffer, format='png', dpi=100, bbox_inches='tight')
43
+ # plt.close(fig)
44
+ # else:
45
+ # raise ValueError(f"Unsupported figure type: {type(fig)}")
46
+
47
+ # img_buffer.seek(0)
48
+
49
+ # # Use PIL to get image dimensions
50
+ # with PILImage.open(img_buffer) as img:
51
+ # img_width, img_height = img.size
52
+
53
+ # # Calculate width and height to maintain aspect ratio
54
+ # max_width = 6.5 * inch # Maximum width (letter width is 8.5 inches, leaving margins)
55
+ # max_height = 4 * inch # Maximum height
56
+
57
+ # aspect = img_width / float(img_height)
58
+
59
+ # if img_width > max_width:
60
+ # img_width = max_width
61
+ # img_height = img_width / aspect
62
+
63
+ # if img_height > max_height:
64
+ # img_height = max_height
65
+ # img_width = img_height * aspect
66
+
67
+ # # Reset buffer position
68
+ # img_buffer.seek(0)
69
+
70
+ # # Create ReportLab Image with calculated dimensions
71
+ # img = Image(img_buffer, width=img_width, height=img_height)
72
+
73
+ # elements.append(img)
74
+ # elements.append(Spacer(1, 12))
75
+ # return elements
76
+
77
+ # def _add_recommendations(self, recommendations):
78
+ # elements = []
79
+ # elements.append(Paragraph("MTSS.ai Analysis", self.styles['Heading1']))
80
+
81
+ # # Convert markdown to HTML
82
+ # html = markdown.markdown(recommendations)
83
+
84
+ # # Wrap the HTML in a root element to ensure valid XML
85
+ # wrapped_html = f"<root>{html}</root>"
86
+
87
+ # try:
88
+ # root = ET.fromstring(wrapped_html)
89
+ # except ExpatError:
90
+ # # If parsing fails, fallback to treating the entire content as plain text
91
+ # elements.append(Paragraph(escape(recommendations), self.styles['BodyText']))
92
+ # return elements
93
+
94
+ # for elem in root:
95
+ # if elem.tag == 'h3':
96
+ # elements.append(Paragraph(elem.text or "", self.styles['Heading3']))
97
+ # elif elem.tag == 'h4':
98
+ # elements.append(Paragraph(elem.text or "", self.styles['Heading4']))
99
+ # elif elem.tag == 'p':
100
+ # text = ''.join(elem.itertext())
101
+ # elements.append(Paragraph(text, self.styles['Justify']))
102
+ # elif elem.tag == 'ul':
103
+ # for li in elem.findall('li'):
104
+ # bullet_text = '• ' + ''.join(li.itertext()).strip()
105
+ # elements.append(Paragraph(bullet_text, self.styles['BodyText']))
106
+ # else:
107
+ # # For any other tags, just extract the text
108
+ # text = ''.join(elem.itertext())
109
+ # if text.strip():
110
+ # elements.append(Paragraph(text, self.styles['BodyText']))
111
+
112
+ # return elements
113
+
114
+
115
  import io
116
  from reportlab.lib.pagesizes import letter
117
  from reportlab.platypus import SimpleDocTemplate, Image, Paragraph, Spacer
118
  from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
119
+ from reportlab.lib.enums import TA_JUSTIFY, TA_LEFT
120
  from reportlab.lib.units import inch
121
  import matplotlib.pyplot as plt
122
  import markdown
123
+ from bs4 import BeautifulSoup
124
  from PIL import Image as PILImage
 
 
125
 
126
  class ReportGenerator:
127
  def __init__(self):
128
  self.styles = getSampleStyleSheet()
129
  self.styles.add(ParagraphStyle(name='Justify', alignment=TA_JUSTIFY))
130
+ self.styles.add(ParagraphStyle(
131
+ name='Bullet',
132
+ parent=self.styles['BodyText'],
133
+ leftIndent=20,
134
+ firstLineIndent=0,
135
+ alignment=TA_LEFT
136
+ ))
137
+ # Adjust heading styles for better hierarchy
138
+ self.styles['Heading1'].fontSize = 18
139
+ self.styles['Heading2'].fontSize = 16
140
+ self.styles['Heading3'].fontSize = 14
141
+ self.styles['Heading4'].fontSize = 12
142
 
143
  def create_combined_pdf(self, intervention_fig, student_metrics_fig, recommendations):
144
  buffer = io.BytesIO()
145
+ doc = SimpleDocTemplate(buffer, pagesize=letter, topMargin=0.5*inch, bottomMargin=0.5*inch)
146
 
147
  elements = []
148
 
 
205
  # Convert markdown to HTML
206
  html = markdown.markdown(recommendations)
207
 
208
+ # Parse HTML
209
+ soup = BeautifulSoup(html, 'html.parser')
210
+
211
+ for element in soup.find_all(['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'ul']):
212
+ if element.name.startswith('h'):
213
+ level = int(element.name[1])
214
+ style = f'Heading{min(level, 4)}'
215
+ elements.append(Paragraph(element.text, self.styles[style]))
216
+ elif element.name == 'p':
217
+ elements.append(Paragraph(element.text, self.styles['BodyText']))
218
+ elif element.name == 'ul':
219
+ for li in element.find_all('li'):
220
+ bullet_text = '• ' + li.text
221
+ elements.append(Paragraph(bullet_text, self.styles['Bullet']))
222
+ elements.append(Spacer(1, 6))
 
 
 
 
 
 
 
 
 
 
 
 
223
 
224
  return elements