MilanM commited on
Commit
0663d77
·
verified ·
1 Parent(s): 2c81b27

Create pdf_generator.py

Browse files
Files changed (1) hide show
  1. pdf_generator.py +173 -0
pdf_generator.py ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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, Table, TableStyle, Flowable
7
+ from reportlab.lib.units import mm, inch
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(session_state):
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("Pilot Drafting", styles['Title'])]
102
+
103
+ for page in session_state.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
+
107
+ if page['input_key'] == 'workload_scope':
108
+ story.extend(process_workload_scope(session_state, styles))
109
+ elif page['input_key'] == 'useful_assets':
110
+ story.extend(process_useful_assets(session_state, styles))
111
+ elif page['input_key'] == 'pilot_evaluation':
112
+ story.extend(process_pilot_evaluation(session_state, styles))
113
+
114
+ story.append(Spacer(1, 12))
115
+
116
+ doc.build(story, onFirstPage=create_page_template, onLaterPages=create_page_template)
117
+ buffer.seek(0)
118
+ return buffer
119
+
120
+ def process_workload_scope(session_state, styles):
121
+ story = []
122
+ answers = session_state.answers['workload_scope']
123
+
124
+ story.append(Paragraph("Time Commitments:", styles['Heading2']))
125
+ story.append(Paragraph(answers.get('time_commitments', ""), styles['Answer']))
126
+
127
+ story.append(Paragraph("Deadlines:", styles['Heading2']))
128
+ story.append(Paragraph(answers.get('deadlines', ""), styles['Answer']))
129
+
130
+ story.append(Paragraph("Feature Prioritization:", styles['Heading2']))
131
+ story.append(Paragraph(answers.get('feature_prioritization', ""), styles['Answer']))
132
+
133
+ return story
134
+
135
+ def process_useful_assets(session_state, styles):
136
+ story = []
137
+ answers = session_state.answers['useful_assets']
138
+
139
+ story.append(Paragraph("Useful Assets and Libraries:", styles['Heading2']))
140
+ for asset in answers.get('assets', []):
141
+ story.append(Paragraph(asset, styles['Answer']))
142
+
143
+ return story
144
+
145
+ def process_pilot_evaluation(session_state, styles):
146
+ story = []
147
+ answers = session_state.answers['pilot_evaluation']
148
+
149
+ story.append(Paragraph("Metrics to Track:", styles['Heading2']))
150
+ for metric in answers.get('metrics', []):
151
+ story.append(Paragraph(metric, styles['Answer']))
152
+
153
+ return story
154
+
155
+ def parse_quantitative_criteria(input_string):
156
+ match = re.match(r'(.+)\[([-+]?(?:\d*\.*\d+)(?:%)?)\s*-\s*([-+]?(?:\d*\.*\d+)(?:%)?)?\]', input_string)
157
+ if match:
158
+ name, min_val, max_val = match.groups()
159
+ name = name.strip()
160
+
161
+ # Handle percentage inputs
162
+ is_percentage = '%' in min_val or '%' in max_val
163
+ min_val = float(min_val.rstrip('%'))
164
+ max_val = float(max_val.rstrip('%'))
165
+
166
+ if is_percentage:
167
+ min_val /= 100
168
+ max_val /= 100
169
+
170
+ is_integer = '.' not in input_string or (min_val.is_integer() and max_val.is_integer())
171
+
172
+ return name, min_val, max_val, is_percentage, is_integer
173
+ return None