MilanM commited on
Commit
d0abf12
·
verified ·
1 Parent(s): 8a4d267

Update report_gen.py

Browse files
Files changed (1) hide show
  1. report_gen.py +138 -20
report_gen.py CHANGED
@@ -1,31 +1,109 @@
1
- from io import BytesIO
 
2
  from reportlab.lib import colors
3
  from reportlab.lib.pagesizes import A4
4
  from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
5
- from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
6
  from reportlab.lib.units import mm
 
7
 
8
- def generate_pdf(pages, answers):
9
- buffer = BytesIO()
10
- doc = SimpleDocTemplate(buffer, pagesize=A4, rightMargin=20*mm, leftMargin=20*mm, topMargin=20*mm, bottomMargin=20*mm)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
- # Define custom colors
13
- dark_purple = colors.Color(0.2, 0, 0.4) # Very dark purple for titles
14
- light_purple = colors.Color(0.6, 0.4, 0.8) # Lighter purple for answers
15
- medium_gray = colors.Color(0.5, 0.5, 0.5) # Medium gray for descriptions
 
16
 
 
 
 
 
 
 
 
 
 
 
17
  styles = getSampleStyleSheet()
18
- styles.add(ParagraphStyle(name='SectionTitle', fontName='Helvetica', fontSize=16, spaceAfter=6, textColor=dark_purple))
19
- styles.add(ParagraphStyle(name='Description', fontName='Helvetica', fontSize=12, spaceAfter=6, textColor=medium_gray))
20
- styles.add(ParagraphStyle(name='Answer', fontName='Helvetica', fontSize=12, spaceAfter=12, textColor=light_purple))
21
- styles.add(ParagraphStyle(name='MainTitle', fontName='Helvetica-Bold', fontSize=16, spaceAfter=24, textColor=dark_purple))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
- story = [Paragraph("AI Trust and Opacity Evaluation", styles['MainTitle'])]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
  for page in pages[:-1]: # Skip the last page
26
  if 'input_key' in page and page['input_key'] is not None:
27
- story.append(Paragraph(page['title'], styles['SectionTitle']))
28
- story.append(Paragraph(page['content'], styles['Description']))
29
 
30
  answer = answers.get(page['input_key'], "")
31
  if isinstance(answer, list):
@@ -34,11 +112,51 @@ def generate_pdf(pages, answers):
34
  if page.get('input_type') == 'combined':
35
  option = answers.get(page['input_key'], "")
36
  conclusion = answers.get(f"{page['input_key']}_conclusion", "")
37
- answer = f"Option selected: {option}\n\nConclusion: {conclusion}"
 
 
 
 
 
 
 
38
 
39
- story.append(Paragraph(f"<b>Answer:</b> {answer}", styles['Answer']))
40
  story.append(Spacer(1, 12))
41
 
42
- doc.build(story)
43
  buffer.seek(0)
44
- return buffer
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import io
2
+ import re
3
  from reportlab.lib import colors
4
  from reportlab.lib.pagesizes import A4
5
  from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
6
+ from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Flowable
7
  from reportlab.lib.units import mm
8
+ from reportlab.graphics.shapes import Drawing, Rect, String, Line
9
 
10
+ class SliderFlowable(Flowable):
11
+ def __init__(self, name, value, min_val, max_val, is_percentage=False):
12
+ Flowable.__init__(self)
13
+ self.name = name
14
+ self.value = value
15
+ self.min_val = min_val
16
+ self.max_val = max_val
17
+ self.is_percentage = is_percentage
18
+ self.width = 400
19
+ self.height = 80
20
+
21
+ def draw(self):
22
+ drawing = Drawing(self.width, self.height)
23
+
24
+ # Draw slider bar
25
+ bar = Rect(50, 30, 300, 20, fillColor=colors.HexColor("#f7fbfd"), strokeColor=colors.HexColor("#9999ff"))
26
+ drawing.add(bar)
27
+
28
+ # Draw slider value
29
+ if self.max_val == self.min_val:
30
+ value_width = 50 # or some default width
31
+ else:
32
+ value_width = 50 + ((self.value - self.min_val) / (self.max_val - self.min_val) * 300)
33
+ value_bar = Rect(50, 30, value_width - 50, 20, fillColor=colors.HexColor("#9999ff"), strokeColor=None)
34
+ drawing.add(value_bar)
35
+
36
+ # Add slider name
37
+ drawing.add(String(0, 60, self.name, fontSize=12, fillColor=colors.HexColor("#26004d")))
38
 
39
+ # Add range labels
40
+ min_str = f"{self.min_val:.1f}%" if self.is_percentage else f"{self.min_val:.1f}"
41
+ max_str = f"{self.max_val:.1f}%" if self.is_percentage else f"{self.max_val:.1f}"
42
+ drawing.add(String(40, 10, min_str, fontSize=10, fillColor=colors.HexColor("#26004d")))
43
+ drawing.add(String(340, 10, max_str, fontSize=10, fillColor=colors.HexColor("#26004d")))
44
 
45
+ # Add value label
46
+ value_str = f"{self.value:.1f}%" if self.is_percentage else f"{self.value:.1f}"
47
+ drawing.add(String(value_width - 20, 55, value_str, fontSize=10, fillColor=colors.HexColor("#26004d")))
48
+
49
+ # Add value marker
50
+ drawing.add(Line(value_width, 25, value_width, 55, strokeColor=colors.HexColor("#26004d"), strokeWidth=2))
51
+
52
+ drawing.drawOn(self.canv, 0, 0)
53
+
54
+ def create_styles():
55
  styles = getSampleStyleSheet()
56
+ styles['Title'].fontName = 'Helvetica-Bold'
57
+ styles['Title'].fontSize = 18
58
+ styles['Title'].spaceAfter = 16
59
+ styles['Title'].textColor = colors.HexColor("#26004d")
60
+
61
+ styles['Heading1'].fontName = 'Helvetica-Bold'
62
+ styles['Heading1'].fontSize = 16
63
+ styles['Heading1'].spaceAfter = 10
64
+ styles['Heading1'].textColor = colors.HexColor("#3b0b75")
65
+
66
+ styles['Heading2'].fontName = 'Helvetica'
67
+ styles['Heading2'].fontSize = 14
68
+ styles['Heading2'].spaceAfter = 12
69
+ styles['Heading2'].textColor = colors.HexColor("#52176a")
70
+
71
+ styles['BodyText'].fontName = 'Helvetica'
72
+ styles['BodyText'].fontSize = 12
73
+ styles['BodyText'].spaceAfter = 12
74
+ styles['BodyText'].textColor = colors.HexColor("#26004d")
75
 
76
+ styles.add(ParagraphStyle(
77
+ name='Answer',
78
+ parent=styles['BodyText'],
79
+ backColor=colors.HexColor("#f0f2fd"),
80
+ borderColor=colors.HexColor("#9999ff"),
81
+ borderWidth=0.5,
82
+ borderPadding=(5, 5, 5, 5),
83
+ spaceAfter=10
84
+ ))
85
+
86
+ return styles
87
+
88
+ def create_page_template(canvas, doc):
89
+ canvas.saveState()
90
+ canvas.setFillColor(colors.HexColor("#e6ebfb"))
91
+ canvas.rect(0, 0, doc.pagesize[0], doc.pagesize[1], fill=1)
92
+ canvas.setFillColor(colors.HexColor("#26004d"))
93
+ canvas.setFont('Helvetica', 9)
94
+ canvas.drawString(30, 20, f"Page {doc.page}")
95
+ canvas.restoreState()
96
+
97
+ def generate_pdf(pages, answers):
98
+ buffer = io.BytesIO()
99
+ doc = SimpleDocTemplate(buffer, pagesize=A4, rightMargin=20*mm, leftMargin=20*mm, topMargin=20*mm, bottomMargin=20*mm)
100
+ styles = create_styles()
101
+ story = [Paragraph("AI Trust and Opacity Evaluation", styles['Title'])]
102
 
103
  for page in pages[:-1]: # Skip the last page
104
  if 'input_key' in page and page['input_key'] is not None:
105
+ story.append(Paragraph(page['title'], styles['Heading1']))
106
+ story.append(Paragraph(page['content'], styles['BodyText']))
107
 
108
  answer = answers.get(page['input_key'], "")
109
  if isinstance(answer, list):
 
112
  if page.get('input_type') == 'combined':
113
  option = answers.get(page['input_key'], "")
114
  conclusion = answers.get(f"{page['input_key']}_conclusion", "")
115
+ story.append(Paragraph(f"<b>Option selected:</b> {option}", styles['Answer']))
116
+ story.append(Paragraph(f"<b>Conclusion:</b> {conclusion}", styles['Answer']))
117
+ else:
118
+ story.append(Paragraph(f"<b>Answer:</b> {answer}", styles['Answer']))
119
+
120
+ # Add quantitative criteria visualization if applicable
121
+ if page['input_key'] in ['technological_literacy', 'cognitive_mismatch']:
122
+ story.extend(process_quantitative_criteria(answer, styles))
123
 
 
124
  story.append(Spacer(1, 12))
125
 
126
+ doc.build(story, onFirstPage=create_page_template, onLaterPages=create_page_template)
127
  buffer.seek(0)
128
+ return buffer
129
+
130
+ def process_quantitative_criteria(answer, styles):
131
+ story = []
132
+ lines = answer.split('\n')
133
+ for line in lines:
134
+ parsed = parse_quantitative_criteria(line)
135
+ if parsed:
136
+ name, value, min_val, max_val, is_percentage = parsed
137
+ if is_percentage:
138
+ slider = SliderFlowable(name, value*100, min_val*100, max_val*100, is_percentage=True)
139
+ else:
140
+ slider = SliderFlowable(name, value, min_val, max_val, is_percentage=False)
141
+ story.append(slider)
142
+ return story
143
+
144
+ def parse_quantitative_criteria(input_string):
145
+ match = re.match(r'(.+):\s*([-+]?(?:\d*\.*\d+)(?:%)?)(?:\s*\[([-+]?(?:\d*\.*\d+)(?:%)?)\s*-\s*([-+]?(?:\d*\.*\d+)(?:%)?)?\])?', input_string)
146
+ if match:
147
+ name, value, min_val, max_val = match.groups()
148
+ name = name.strip()
149
+
150
+ # Handle percentage inputs
151
+ is_percentage = '%' in value or '%' in min_val or '%' in max_val
152
+ value = float(value.rstrip('%'))
153
+ min_val = float(min_val.rstrip('%') if min_val else 0)
154
+ max_val = float(max_val.rstrip('%') if max_val else 100)
155
+
156
+ if is_percentage:
157
+ value /= 100
158
+ min_val /= 100
159
+ max_val /= 100
160
+
161
+ return name, value, min_val, max_val, is_percentage
162
+ return None