MilanM commited on
Commit
3921727
·
verified ·
1 Parent(s): 6d577f3

Update pdf_generator.py

Browse files
Files changed (1) hide show
  1. pdf_generator.py +38 -61
pdf_generator.py CHANGED
@@ -1,21 +1,20 @@
1
- from io import BytesIO
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, Table, TableStyle, 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, is_integer=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.is_integer = is_integer
19
  self.width = 400
20
  self.height = 80
21
 
@@ -38,13 +37,13 @@ class SliderFlowable(Flowable):
38
  drawing.add(String(0, 60, self.name, fontSize=12, fillColor=colors.HexColor("#26004d")))
39
 
40
  # Add range labels
41
- min_str = self.format_label(self.min_val)
42
- max_str = self.format_label(self.max_val)
43
  drawing.add(String(40, 10, min_str, fontSize=10, fillColor=colors.HexColor("#26004d")))
44
  drawing.add(String(340, 10, max_str, fontSize=10, fillColor=colors.HexColor("#26004d")))
45
-
46
  # Add value label
47
- value_str = self.format_label(self.value)
48
  drawing.add(String(value_width - 20, 55, value_str, fontSize=10, fillColor=colors.HexColor("#26004d")))
49
 
50
  # Add value marker
@@ -52,14 +51,6 @@ class SliderFlowable(Flowable):
52
 
53
  drawing.drawOn(self.canv, 0, 0)
54
 
55
- def format_label(self, value):
56
- if self.is_percentage:
57
- return f"{value:.2f}%"
58
- elif self.is_integer:
59
- return f"{int(value)}"
60
- else:
61
- return f"{value:.2f}"
62
-
63
  def create_styles():
64
  styles = getSampleStyleSheet()
65
  styles['Title'].fontName = 'Helvetica-Bold'
@@ -103,15 +94,12 @@ def create_page_template(canvas, doc):
103
  canvas.drawString(30, 20, f"Page {doc.page}")
104
  canvas.restoreState()
105
 
106
- def generate_pdf(session_state):
107
- buffer = BytesIO()
108
  doc = SimpleDocTemplate(buffer, pagesize=A4, rightMargin=20*mm, leftMargin=20*mm, topMargin=20*mm, bottomMargin=20*mm)
109
  styles = create_styles()
110
  story = [Paragraph("AI Trust and Opacity Evaluation", styles['Title'])]
111
 
112
- pages = session_state.pages
113
- answers = session_state.answers
114
-
115
  for page in pages[:-1]: # Skip the last page
116
  if 'input_key' in page and page['input_key'] is not None:
117
  story.append(Paragraph(page['title'], styles['Heading1']))
@@ -124,62 +112,51 @@ def generate_pdf(session_state):
124
  if page.get('input_type') == 'combined':
125
  option = answers.get(page['input_key'], "")
126
  conclusion = answers.get(f"{page['input_key']}_conclusion", "")
127
- answer = f"Option selected: {option}\n\nConclusion: {conclusion}"
128
-
129
- # Create a table for the answer to allow multi-line text within a block
130
- data = [[Paragraph(str(answer), styles['Answer'])]]
131
- t = Table(data, colWidths=[450])
132
- t.setStyle(TableStyle([
133
- ('BACKGROUND', (0, 0), (-1, -1), colors.HexColor("#f0f2fd")),
134
- ('TEXTCOLOR', (0, 0), (-1, -1), colors.HexColor("#26004d")),
135
- ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
136
- ('VALIGN', (0, 0), (-1, -1), 'TOP'),
137
- ('INNERGRID', (0, 0), (-1, -1), 0.25, colors.HexColor("#9999ff")),
138
- ('BOX', (0, 0), (-1, -1), 0.25, colors.HexColor("#9999ff")),
139
- ]))
140
- story.append(t)
141
- story.append(Spacer(1, 12))
142
 
143
  # Add quantitative criteria visualization if applicable
144
- if page['input_key'] == 'useful_assets':
145
- story.extend(process_quantitative_criteria(answers['useful_assets'], styles))
 
 
146
 
147
  doc.build(story, onFirstPage=create_page_template, onLaterPages=create_page_template)
148
  buffer.seek(0)
149
  return buffer
150
 
151
- def process_quantitative_criteria(answers, styles):
152
  story = []
153
- quantitative_criteria = answers.get('quantitative', [])
154
- for i, criterion in enumerate(quantitative_criteria):
155
- parsed = parse_quantitative_criteria(criterion)
156
  if parsed:
157
- name, min_val, max_val, is_percentage, is_integer = parsed
158
- value = answers.get(f'quant_value_{i}', min_val)
159
- slider = SliderFlowable(name, value, min_val, max_val, is_percentage=is_percentage, is_integer=is_integer)
 
 
160
  story.append(slider)
161
- story.append(Paragraph(f"{name}: {value:.1f}%" if is_percentage else (f"{name}: {int(value)}" if is_integer else f"{name}: {value:.2f}"), styles['BodyText']))
162
  return story
163
 
164
  def parse_quantitative_criteria(input_string):
165
- match = re.match(r'(.+?)\s*\[([-+]?(?:\d*\.*\d+)(?:%)?)\s*-\s*([-+]?(?:\d*\.*\d+)(?:%)?)\]', input_string)
166
  if match:
167
- name, min_val, max_val = match.groups()
168
  name = name.strip()
169
 
170
- def parse_value(val):
171
- if '%' in val:
172
- return float(val.rstrip('%')), True
173
- elif '.' in val:
174
- return float(val), False
175
- else:
176
- return int(val), False
177
-
178
- min_val, is_min_percent = parse_value(min_val)
179
- max_val, is_max_percent = parse_value(max_val)
180
 
181
- is_percentage = is_min_percent or is_max_percent
182
- is_integer = isinstance(min_val, int) and isinstance(max_val, int) and not is_percentage
 
 
183
 
184
- return name, min_val, max_val, is_percentage, is_integer
185
  return None
 
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
 
 
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
 
51
 
52
  drawing.drawOn(self.canv, 0, 0)
53
 
 
 
 
 
 
 
 
 
54
  def create_styles():
55
  styles = getSampleStyleSheet()
56
  styles['Title'].fontName = 'Helvetica-Bold'
 
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']))
 
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