menikev commited on
Commit
34d246d
·
verified ·
1 Parent(s): 90e7053

Upload 15 files

Browse files
Dockerfile ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9
2
+
3
+ WORKDIR /app
4
+
5
+ COPY requirements.txt .
6
+ RUN pip install -r requirements.txt
7
+
8
+ COPY . .
9
+
10
+ CMD ["gunicorn", "app:app", "-b", "0.0.0.0:7860"]
Procfile ADDED
@@ -0,0 +1 @@
 
 
1
+ web: gunicorn app:app
main.py ADDED
@@ -0,0 +1,575 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, render_template, request, redirect, url_for, flash, send_from_directory, send_file
2
+ from flask_sqlalchemy import SQLAlchemy
3
+ from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
4
+ from flask_wtf import FlaskForm
5
+ from wtforms import StringField, PasswordField, SubmitField
6
+ from wtforms.validators import DataRequired, Email, EqualTo
7
+ from werkzeug.security import generate_password_hash, check_password_hash
8
+ from flask_migrate import Migrate
9
+ from datetime import datetime, timezone
10
+ import os
11
+ from pdf_generator import generate_pdf_report
12
+ import io
13
+
14
+
15
+ app = Flask(__name__, static_folder='static')
16
+ app.config['SECRET_KEY'] = '001'
17
+ app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db'
18
+ db = SQLAlchemy(app)
19
+ migrate = Migrate(app, db)
20
+ login_manager = LoginManager(app)
21
+ login_manager.login_view = 'login'
22
+
23
+ if os.path.exists('users.db'):
24
+ os.remove('users.db')
25
+
26
+ with app.app_context():
27
+ db.create_all()
28
+
29
+ class User(UserMixin, db.Model):
30
+ id = db.Column(db.Integer, primary_key=True)
31
+ email = db.Column(db.String(120), unique=True, nullable=False)
32
+ password_hash = db.Column(db.String(128))
33
+
34
+ def set_password(self, password):
35
+ self.password_hash = generate_password_hash(password)
36
+
37
+ def check_password(self, password):
38
+ return check_password_hash(self.password_hash, password)
39
+
40
+ @login_manager.user_loader
41
+ def load_user(user_id):
42
+ return User.query.get(int(user_id))
43
+
44
+ class RegistrationForm(FlaskForm):
45
+ email = StringField('Email', validators=[DataRequired(), Email()])
46
+ password = PasswordField('Password', validators=[DataRequired()])
47
+ confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')])
48
+ submit = SubmitField('Register')
49
+
50
+ class LoginForm(FlaskForm):
51
+ email = StringField('Email', validators=[DataRequired(), Email()])
52
+ password = PasswordField('Password', validators=[DataRequired()])
53
+ submit = SubmitField('Login')
54
+
55
+ class AssessmentQuestion(db.Model):
56
+ id = db.Column(db.Integer, primary_key=True)
57
+ category = db.Column(db.String(50), nullable=False)
58
+ subcategory = db.Column(db.String(50), nullable=False)
59
+ text = db.Column(db.String(500), nullable=False)
60
+ options = db.Column(db.JSON, nullable=False)
61
+ scores = db.Column(db.JSON, nullable=False)
62
+ max_score = db.Column(db.Float, nullable=False)
63
+
64
+ class Assessment(db.Model):
65
+ id = db.Column(db.Integer, primary_key=True)
66
+ user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
67
+ start_date = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc))
68
+ completion_date = db.Column(db.DateTime)
69
+ current_question = db.Column(db.Integer, default=1)
70
+ status = db.Column(db.String(20), default='In Progress')
71
+ strategy_score = db.Column(db.Float, default=0)
72
+ governance_score = db.Column(db.Float, default=0)
73
+ data_infrastructure_score = db.Column(db.Float, default=0)
74
+ organization_score = db.Column(db.Float, default=0)
75
+ total_score = db.Column(db.Float, default=0)
76
+ readiness_level = db.Column(db.String(50))
77
+
78
+ class Response(db.Model):
79
+ id = db.Column(db.Integer, primary_key=True)
80
+ assessment_id = db.Column(db.Integer, db.ForeignKey('assessment.id'), nullable=False)
81
+ question_id = db.Column(db.Integer, db.ForeignKey('assessment_question.id'), nullable=False)
82
+ answer = db.Column(db.String(500))
83
+ score = db.Column(db.Float)
84
+
85
+ def __init__(self, assessment_id, question_id, answer):
86
+ self.assessment_id = assessment_id
87
+ self.question_id = question_id
88
+ self.answer = answer
89
+ question = AssessmentQuestion.query.get(question_id)
90
+ if question and question.options:
91
+ option_index = question.options.index(answer)
92
+ self.score = question.scores[option_index]
93
+
94
+ def populate_questions():
95
+ questions = [
96
+ # Strategy (19 points max)
97
+ AssessmentQuestion(
98
+ category='Strategy',
99
+ subcategory='AI Strategy',
100
+ text='Does your organization have a well-defined AI strategy?',
101
+ options=["Yes, we have a detailed AI strategy.",
102
+ "No, we are currently developing an AI strategy.",
103
+ "No, we have not started developing an AI strategy.",
104
+ "Unsure"],
105
+ scores=[5, 3, 1, 0],
106
+ max_score=5
107
+ ),
108
+ AssessmentQuestion(
109
+ category='Strategy',
110
+ subcategory='Leadership and Ownership',
111
+ text='Is there clear leadership or a dedicated team responsible for the AI strategy?',
112
+ options=["Yes, there is a dedicated AI team or leader.",
113
+ "No, it is managed in an organic and decentralized manner.",
114
+ "Unsure"],
115
+ scores=[5, 2, 0],
116
+ max_score=5
117
+ ),
118
+ AssessmentQuestion(
119
+ category='Strategy',
120
+ subcategory='Impact Measurement',
121
+ text='Do you have a process to measure the impact of AI deployment?',
122
+ options=["Yes, we have a process and clearly defined metrics.",
123
+ "Yes, we have a process but are still working on actual metrics.",
124
+ "No, we don’t have a process or metrics but are likely to develop this within 12 months.",
125
+ "No, we don’t have a process or metrics and are unlikely to develop this within 12 months.",
126
+ "Unsure"],
127
+ scores=[5, 4, 2, 1, 0],
128
+ max_score=5
129
+ ),
130
+ AssessmentQuestion(
131
+ category='Strategy',
132
+ subcategory='Financial Strategy',
133
+ text='Has your organization established a financial strategy for sustainable AI funding?',
134
+ options=["Yes, both short-term and long-term financial strategies are in place.",
135
+ "Yes, only a short-term financial strategy is in place.",
136
+ "No, but we are currently developing a financial strategy.",
137
+ "No, we have no plans to develop a financial strategy.",
138
+ "Unsure"],
139
+ scores=[5, 3, 2, 1, 0],
140
+ max_score=5
141
+ ),
142
+ AssessmentQuestion(
143
+ category='Strategy',
144
+ subcategory='Budget Allocation',
145
+ text='How is your organization prioritizing budget allocation for AI deployment compared to other technological initiatives?',
146
+ options=["AI deployment is the highest priority with additional budget allocated.",
147
+ "AI deployment is given equal priority with some additional funding.",
148
+ "AI deployment is important but requires cutting spending in other areas.",
149
+ "AI deployment depends on other technical initiatives being in place first.",
150
+ "Unsure"],
151
+ scores=[5, 4, 3, 2, 0],
152
+ max_score=5
153
+ ),
154
+
155
+ # Governance (17 points max)
156
+ AssessmentQuestion(
157
+ category='Governance',
158
+ subcategory='AI Governance Framework',
159
+ text='Does your organization have a clearly defined AI governance framework?',
160
+ options=["Yes", "No", "Developing"],
161
+ scores=[5, 0, 3],
162
+ max_score=5
163
+ ),
164
+ AssessmentQuestion(
165
+ category='Governance',
166
+ subcategory='Ethical AI Policies',
167
+ text='Are there established policies and procedures for ethical AI development and use?',
168
+ options=["Yes", "No", "Developing"],
169
+ scores=[5, 0, 3],
170
+ max_score=5
171
+ ),
172
+ AssessmentQuestion(
173
+ category='Governance',
174
+ subcategory='C-suite Engagement',
175
+ text='How engaged is your C-suite with AI implementation issues?',
176
+ options=["Excellent", "Very Good", "Good", "Fair", "Poor"],
177
+ scores=[5, 4, 3, 2, 1],
178
+ max_score=5
179
+ ),
180
+ AssessmentQuestion(
181
+ category='Governance',
182
+ subcategory='Resource Allocation',
183
+ text='How would you rate the allocation of resources (financial, human, technological) to support AI projects?',
184
+ options=["Excellent", "Very Good", "Solid", "Fair", "Poor"],
185
+ scores=[5, 4, 3, 2, 1],
186
+ max_score=5
187
+ ),
188
+ AssessmentQuestion(
189
+ category='Governance',
190
+ subcategory='Performance Metrics',
191
+ text='Do you have established metrics and KPIs to measure AI initiatives\' performance and impact?',
192
+ options=["Yes", "No"],
193
+ scores=[5, 0],
194
+ max_score=5
195
+ ),
196
+ AssessmentQuestion(
197
+ category='Governance',
198
+ subcategory='Change Management',
199
+ text='Have you developed a change management plan to address organizational impacts from AI implementations?',
200
+ options=["Yes", "No", "Developing"],
201
+ scores=[5, 0, 3],
202
+ max_score=5
203
+ ),
204
+ AssessmentQuestion(
205
+ category='Governance',
206
+ subcategory='Transparency and Accountability',
207
+ text='Are there mechanisms to ensure transparency and accountability in AI decision-making processes?',
208
+ options=["Yes", "No"],
209
+ scores=[5, 0],
210
+ max_score=5
211
+ ),
212
+ AssessmentQuestion(
213
+ category='Governance',
214
+ subcategory='Risk Management',
215
+ text='How does your organization manage risks associated with AI implementation, such as bias, privacy concerns, and regulatory compliance?',
216
+ options=["Excellent", "Solid", "Good", "Fair", "Poor"],
217
+ scores=[5, 4, 3, 2, 1],
218
+ max_score=5
219
+ ),
220
+
221
+ # Data & Infrastructure (20 points max)
222
+ AssessmentQuestion(
223
+ category='Data & Infrastructure',
224
+ subcategory='Data Availability',
225
+ text='To what extent is your organization’s data structured and available for AI analysis?',
226
+ options=["Data is not available.",
227
+ "Data is available but with privacy/compliance concerns.",
228
+ "Data is mostly prepared with minor access limitations.",
229
+ "Data is fully prepared and accessible.",
230
+ "Other"],
231
+ scores=[0, 2, 3, 5, 0],
232
+ max_score=5
233
+ ),
234
+ AssessmentQuestion(
235
+ category='Data & Infrastructure',
236
+ subcategory='Data Collection',
237
+ text='Do you collect data on your services?',
238
+ options=["Yes", "No"],
239
+ scores=[5, 0],
240
+ max_score=5
241
+ ),
242
+ AssessmentQuestion(
243
+ category='Data & Infrastructure',
244
+ subcategory='Data Accuracy',
245
+ text='How would you rate the accuracy and reliability of your data?',
246
+ options=["Excellent", "Good", "Moderate", "Fair", "Poor"],
247
+ scores=[5, 4, 3, 2, 1],
248
+ max_score=5
249
+ ),
250
+ AssessmentQuestion(
251
+ category='Data & Infrastructure',
252
+ subcategory='Data Up-to-Date',
253
+ text='Do you have a mechanism to ensure your data is up-to-date?',
254
+ options=["Yes", "No"],
255
+ scores=[5, 0],
256
+ max_score=5
257
+ ),
258
+ AssessmentQuestion(
259
+ category='Data & Infrastructure',
260
+ subcategory='Data Access',
261
+ text='How easy is it for authorized personnel to access the data needed for AI analysis?',
262
+ options=["Easy", "Somewhat difficult", "Difficult"],
263
+ scores=[5, 3, 1],
264
+ max_score=5
265
+ ),
266
+ AssessmentQuestion(
267
+ category='Data & Infrastructure',
268
+ subcategory='Data Integration',
269
+ text='Do you have systems to integrate data from different sources (e.g., CRM, ERP)?',
270
+ options=["Yes", "No"],
271
+ scores=[5, 0],
272
+ max_score=5
273
+ ),
274
+ AssessmentQuestion(
275
+ category='Data & Infrastructure',
276
+ subcategory='Infrastructure Performance',
277
+ text='How would you rate the performance of your data storage and computing infrastructure?',
278
+ options=["Excellent", "Very Good", "Solid", "Fair", "Poor"],
279
+ scores=[5, 4, 3, 2, 1],
280
+ max_score=5
281
+ ),
282
+ AssessmentQuestion(
283
+ category='Data & Infrastructure',
284
+ subcategory='Scalability',
285
+ text='How would you rate your infrastructure\'s capacity to scale to accommodate changing AI demands?',
286
+ options=["Excellent", "Very Good", "Solid", "Fair", "Poor"],
287
+ scores=[5, 4, 3, 2, 1],
288
+ max_score=5
289
+ ),
290
+ AssessmentQuestion(
291
+ category='Data & Infrastructure',
292
+ subcategory='Cloud Solutions',
293
+ text='Have you considered cloud-based solutions for scalability and flexibility?',
294
+ options=["Yes", "No"],
295
+ scores=[5, 0],
296
+ max_score=5
297
+ ),
298
+ AssessmentQuestion(
299
+ category='Data & Infrastructure',
300
+ subcategory='Security Policies',
301
+ text='Are there policies to ensure data security and privacy?',
302
+ options=["Yes", "No"],
303
+ scores=[5, 0],
304
+ max_score=5
305
+ ),
306
+
307
+ # Organization (Talent & Culture) (17 points max)
308
+ AssessmentQuestion(
309
+ category='Organization (Talent & Culture)',
310
+ subcategory='Talent Availability',
311
+ text='Does your organization have a dedicated team with expertise in AI technologies?',
312
+ options=["Yes", "No"],
313
+ scores=[5, 0],
314
+ max_score=5
315
+ ),
316
+ AssessmentQuestion(
317
+ category='Organization (Talent & Culture)',
318
+ subcategory='Team Capacity',
319
+ text='How would you rate your team’s capacity to manage and analyze data effectively?',
320
+ options=["Excellent", "Very Good", "Solid", "Fair", "Poor"],
321
+ scores=[5, 4, 3, 2, 1],
322
+ max_score=5
323
+ ),
324
+ AssessmentQuestion(
325
+ category='Organization (Talent & Culture)',
326
+ subcategory='Training Programs',
327
+ text='Has your company invested in training programs to upskill employees in AI-related competencies?',
328
+ options=["Yes, through external vendors.",
329
+ "Yes, with comprehensive internal programs.",
330
+ "No, but plans to in the future.",
331
+ "No, with no plans.",
332
+ "Unsure"],
333
+ scores=[5, 4, 3, 1, 0],
334
+ max_score=5
335
+ ),
336
+ AssessmentQuestion(
337
+ category='Organization (Talent & Culture)',
338
+ subcategory='Knowledge Sharing',
339
+ text='Does your organization have mechanisms for knowledge sharing and documentation of best practices in AI development?',
340
+ options=["Yes", "No"],
341
+ scores=[5, 0],
342
+ max_score=5
343
+ ),
344
+ AssessmentQuestion(
345
+ category='Organization (Talent & Culture)',
346
+ subcategory='Cross-functional Collaboration',
347
+ text='Are there opportunities for collaboration between technical teams and domain experts in AI projects?',
348
+ options=["Yes", "No"],
349
+ scores=[5, 0],
350
+ max_score=5
351
+ ),
352
+ AssessmentQuestion(
353
+ category='Organization (Talent & Culture)',
354
+ subcategory='Cultural Readiness',
355
+ text='How urgently is your organization looking to embrace AI?',
356
+ options=["High urgency", "Moderate urgency", "Limited urgency", "No urgency"],
357
+ scores=[5, 4, 3, 1],
358
+ max_score=5
359
+ ),
360
+ AssessmentQuestion(
361
+ category='Organization (Talent & Culture)',
362
+ subcategory='Board Receptiveness',
363
+ text='How receptive is your Board to changes brought about by AI?',
364
+ options=["High receptiveness", "Moderate receptiveness", "Limited receptiveness", "Not receptive", "Unsure"],
365
+ scores=[5, 4, 3, 1, 0],
366
+ max_score=5
367
+ ),
368
+ AssessmentQuestion(
369
+ category='Organization (Talent & Culture)',
370
+ subcategory='Leadership Receptiveness',
371
+ text='How receptive is your Leadership Team to changes brought about by AI?',
372
+ options=["High receptiveness", "Moderate receptiveness", "Limited receptiveness", "Not receptive", "Unsure"],
373
+ scores=[5, 4, 3, 1, 0],
374
+ max_score=5
375
+ ),
376
+ AssessmentQuestion(
377
+ category='Organization (Talent & Culture)',
378
+ subcategory='Change Management Plan',
379
+ text='Do you have a change management plan in place to address changes brought about by AI?',
380
+ options=["Yes", "No", "Developing"],
381
+ scores=[5, 0, 3],
382
+ max_score=5
383
+ ),
384
+ AssessmentQuestion(
385
+ category='Organization (Talent & Culture)',
386
+ subcategory='Employee Receptiveness',
387
+ text='How receptive are your employees to changes brought about by AI?',
388
+ options=["High receptiveness", "Moderate receptiveness", "Limited receptiveness", "Not receptive", "Unsure"],
389
+ scores=[5, 4, 3, 1, 0],
390
+ max_score=5
391
+ ),
392
+ ]
393
+ db.session.bulk_save_objects(questions)
394
+ db.session.commit()
395
+
396
+
397
+ def calculate_score(assessment):
398
+ responses = Response.query.filter_by(assessment_id=assessment.id).all()
399
+ category_scores = {
400
+ 'Strategy': 0,
401
+ 'Governance': 0,
402
+ 'Data & Infrastructure': 0,
403
+ 'Organization (Talent & Culture)': 0
404
+ }
405
+ category_max_scores = {
406
+ 'Strategy': 19,
407
+ 'Governance': 17,
408
+ 'Data & Infrastructure': 20,
409
+ 'Organization (Talent & Culture)': 17
410
+ }
411
+
412
+ for response in responses:
413
+ question = AssessmentQuestion.query.get(response.question_id)
414
+ if question and question.options:
415
+ option_index = question.options.index(response.answer)
416
+ score = question.scores[option_index]
417
+ category_scores[question.category] += score
418
+
419
+ # Normalize scores to respect maximum categories scores
420
+ for category in category_scores:
421
+ category_scores[category] = min(category_scores[category],
422
+ category_max_scores[category])
423
+
424
+ assessment.strategy_score = category_scores['Strategy']
425
+ assessment.governance_score = category_scores['Governance']
426
+ assessment.data_infrastructure_score = category_scores['Data & Infrastructure']
427
+ assessment.organization_score = category_scores['Organization (Talent & Culture)']
428
+
429
+ total_score = sum(category_scores.values())
430
+ assessment.total_score = total_score
431
+
432
+ if total_score <= 21:
433
+ assessment.readiness_level = 'AI Novice'
434
+ elif total_score <= 43:
435
+ assessment.readiness_level = 'AI Ready'
436
+ elif total_score <= 65:
437
+ assessment.readiness_level = 'AI Proficient'
438
+ else:
439
+ assessment.readiness_level = 'AI Advanced'
440
+
441
+ db.session.commit()
442
+
443
+ @app.route('/static/<path:filename>')
444
+ def serve_static(filename):
445
+ return send_from_directory(app.static_folder, filename)
446
+
447
+ @app.route('/')
448
+ def home():
449
+ return render_template('home.html')
450
+
451
+ @app.route('/register', methods=['GET', 'POST'])
452
+ def register():
453
+ form = RegistrationForm()
454
+ if form.validate_on_submit():
455
+ user = User.query.filter_by(email=form.email.data).first()
456
+ if user:
457
+ flash('Email already registered. Please use a different email.', 'danger')
458
+ return redirect(url_for('register'))
459
+ new_user = User(email=form.email.data)
460
+ new_user.set_password(form.password.data)
461
+ db.session.add(new_user)
462
+ db.session.commit()
463
+ flash('Registration successful. Please log in.', 'success')
464
+ return redirect(url_for('login'))
465
+ return render_template('register.html', form=form)
466
+
467
+ @app.route('/login', methods=['GET', 'POST'])
468
+ def login():
469
+ form = LoginForm()
470
+ if form.validate_on_submit():
471
+ user = User.query.filter_by(email=form.email.data).first()
472
+ if user and user.check_password(form.password.data):
473
+ login_user(user)
474
+ flash('Login successful.', 'success')
475
+ return redirect(url_for('dashboard'))
476
+ else:
477
+ flash('Invalid email or password.', 'danger')
478
+ return render_template('login.html', form=form)
479
+
480
+ @app.route('/logout')
481
+ @login_required
482
+ def logout():
483
+ logout_user()
484
+ flash('You have been logged out.', 'info')
485
+ return redirect(url_for('home'))
486
+
487
+ @app.route('/dashboard')
488
+ @login_required
489
+ def dashboard():
490
+ return render_template('dashboard.html')
491
+
492
+ @app.route('/start_assessment')
493
+ @login_required
494
+ def start_assessment():
495
+ assessment = Assessment(user_id=current_user.id)
496
+ db.session.add(assessment)
497
+ db.session.commit()
498
+ return redirect(url_for('assessment_question', assessment_id=assessment.id))
499
+
500
+ @app.route('/assessment/<int:assessment_id>', methods=['GET', 'POST'])
501
+ @login_required
502
+ def assessment_question(assessment_id):
503
+ assessment = Assessment.query.get_or_404(assessment_id)
504
+ if assessment.user_id != current_user.id:
505
+ flash('Unauthorized access to assessment', 'danger')
506
+ return redirect(url_for('dashboard'))
507
+
508
+ questions = AssessmentQuestion.query.all()
509
+ current_question_index = assessment.current_question - 1
510
+
511
+ if current_question_index >= len(questions):
512
+ return redirect(url_for('assessment_complete', assessment_id=assessment_id))
513
+
514
+ current_questions = questions[current_question_index:current_question_index+4]
515
+
516
+ if request.method == 'POST':
517
+ for question in current_questions:
518
+ answer = request.form.get(f'question_{question.id}')
519
+ if answer:
520
+ response = Response(assessment_id=assessment_id, question_id=question.id, answer=answer)
521
+ db.session.add(response)
522
+ assessment.current_question += len(current_questions)
523
+
524
+ db.session.commit()
525
+ return redirect(url_for('assessment_question', assessment_id=assessment_id))
526
+ return render_template('assessment_questions.html', questions=current_questions, assessment=assessment)
527
+
528
+ @app.route('/assessment/<int:assessment_id>/complete')
529
+ @login_required
530
+ def assessment_complete(assessment_id):
531
+ assessment = Assessment.query.get_or_404(assessment_id)
532
+ if assessment.user_id != current_user.id:
533
+ flash('Unauthorized access to assessment', 'danger')
534
+ return redirect(url_for('dashboard'))
535
+
536
+ calculate_score(assessment)
537
+ assessment.status = 'Complete'
538
+ assessment.completion_date = datetime.now(timezone.utc)
539
+ db.session.commit()
540
+
541
+ return render_template('assessment_complete.html', assessment=assessment, strategy_score=assessment.strategy_score,
542
+ governance_score=assessment.governance_score,
543
+ data_infrastructure_score=assessment.data_infrastructure_score,
544
+ organization_score=assessment.organization_score,
545
+ total_score=assessment.total_score,
546
+ readiness_level=assessment.readiness_level)
547
+
548
+ @app.route('/assessment/<int:assessment_id>/pdf')
549
+ @login_required
550
+ def generate_pdf(assessment_id):
551
+ assessment = Assessment.query.get_or_404(assessment_id)
552
+ if assessment.user_id != current_user.id:
553
+ flash('Unauthorized access to assessment', 'danger')
554
+ return redirect(url_for('dashboard'))
555
+
556
+ pdf_buffer = generate_pdf_report(assessment)
557
+ pdf_buffer.seek(0)
558
+ return send_file(
559
+ io.BytesIO(pdf_buffer.getvalue()),
560
+ mimetype='application/pdf',
561
+ as_attachment=True,
562
+ download_name=f'AI_Readiness_Report_{assessment_id}.pdf' # Changed from attachment_filename
563
+ )
564
+
565
+ with app.app_context():
566
+ db.drop_all()
567
+ db.create_all()
568
+ populate_questions()
569
+
570
+ if __name__ == '__main__':
571
+ with app.app_context():
572
+ db.create_all()
573
+ if not AssessmentQuestion.query.first():
574
+ populate_questions()
575
+ app.run(debug=True)
pdf_generator.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from reportlab.lib import colors
2
+ from reportlab.lib.pagesizes import letter
3
+ from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle
4
+ from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
5
+ from reportlab.lib.units import inch
6
+ from io import BytesIO
7
+
8
+ def generate_pdf_report(assessment):
9
+ buffer = BytesIO()
10
+ doc = SimpleDocTemplate(buffer, pagesize=letter)
11
+ styles = getSampleStyleSheet()
12
+ elements = []
13
+
14
+ # Title
15
+ elements.append(Paragraph("AI Readiness Assessment Report", styles['Title']))
16
+ elements.append(Spacer(1, 12))
17
+
18
+ # Summary
19
+ elements.append(Paragraph("Summary", styles['Heading1']))
20
+ elements.append(Paragraph(f"Total Score: {assessment.total_score}", styles['Normal']))
21
+ elements.append(Paragraph(f"Readiness Level: {assessment.readiness_level}", styles['Normal']))
22
+ elements.append(Spacer(1, 12))
23
+
24
+ # Scores Table
25
+ data = [
26
+ ["Category", "Score"],
27
+ ["Strategy", assessment.strategy_score],
28
+ ["Governance", assessment.governance_score],
29
+ ["Data & Infrastructure", assessment.data_infrastructure_score],
30
+ ["Organization", assessment.organization_score]
31
+ ]
32
+ table = Table(data)
33
+ table.setStyle(TableStyle([
34
+ ('BACKGROUND', (0, 0), (-1, 0), colors.grey),
35
+ ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
36
+ ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
37
+ ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
38
+ ('FONTSIZE', (0, 0), (-1, 0), 14),
39
+ ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
40
+ ('BACKGROUND', (0, 1), (-1, -1), colors.beige),
41
+ ('TEXTCOLOR', (0, 1), (-1, -1), colors.black),
42
+ ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
43
+ ('FONTNAME', (0, 1), (-1, -1), 'Helvetica'),
44
+ ('FONTSIZE', (0, 1), (-1, -1), 12),
45
+ ('TOPPADDING', (0, 1), (-1, -1), 6),
46
+ ('BOTTOMPADDING', (0, 1), (-1, -1), 6),
47
+ ('GRID', (0, 0), (-1, -1), 1, colors.black)
48
+ ]))
49
+ elements.append(table)
50
+ elements.append(Spacer(1, 12))
51
+
52
+ # Recommendations
53
+ elements.append(Paragraph("Recommendations", styles['Heading1']))
54
+ if assessment.strategy_score < 15:
55
+ elements.append(Paragraph("• Focus on developing a comprehensive AI strategy aligned with business goals.", styles['Normal']))
56
+ if assessment.governance_score < 13:
57
+ elements.append(Paragraph("• Strengthen AI governance frameworks and ethical guidelines.", styles['Normal']))
58
+ if assessment.data_infrastructure_score < 16:
59
+ elements.append(Paragraph("• Invest in improving data quality and infrastructure to support AI initiatives.", styles['Normal']))
60
+ if assessment.organization_score < 13:
61
+ elements.append(Paragraph("• Enhance AI skills and promote a culture of innovation within the organization.", styles['Normal']))
62
+
63
+ doc.build(elements)
64
+ buffer.seek(0)
65
+ return buffer
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ Flask==2.2.3
2
+ Flask-SQLAlchemy==3.0.3
3
+ Flask-Login==0.6.2
4
+ Flask-WTF==1.1.1
5
+ WTForms==3.0.1
6
+ Werkzeug==2.2.3
7
+ Flask-Migrate==4.0.4
8
+ reportlab==3.6.12
9
+ gunicorn==20.1.0
runtime.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ python-3.9.16
static/style.css ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body {
2
+ min-height: 100vh;
3
+ display: flex;
4
+ flex-direction: column;
5
+ }
6
+
7
+ .container {
8
+ flex: 1;
9
+ }
10
+
11
+ .footer {
12
+ margin-top: auto;
13
+ }
14
+
15
+ .card {
16
+ box-shadow: 0 4px 8px rgba(0,0,0,0.1);
17
+ }
18
+
19
+ .card-header {
20
+ font-weight: bold;
21
+ }
22
+
23
+ .btn-primary {
24
+ background-color: #007bff;
25
+ border-color: #007bff;
26
+ }
27
+
28
+ .btn-primary:hover {
29
+ background-color: #0056b3;
30
+ border-color: #0056b3;
31
+ }
32
+
33
+ .jumbotron {
34
+ background-color: #f8f9fa;
35
+ border-radius: 0.3rem;
36
+ }
templates/assessment.html ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block content %}
4
+ <h2>AI Readiness Assessment</h2>
5
+ <form method="POST">
6
+ {% for question in questions %}
7
+ <div class="card mb-3">
8
+ <div class="card-body">
9
+ <h5 class="card-title">{{ question.subcategory }}</h5>
10
+ <p class="card-text">{{ question.text }}</p>
11
+ {% for option in question.options %}
12
+ <div class="form-check">
13
+ <input class="form-check-input" type="radio" name="question_{{ question.id }}" id="option_{{ question.id }}_{{ loop.index }}" value="{{ option }}">
14
+ <label class="form-check-label" for="option_{{ question.id }}_{{ loop.index }}">
15
+ {{ option }}
16
+ </label>
17
+ </div>
18
+ {% endfor %}
19
+ </div>
20
+ </div>
21
+ {% endfor %}
22
+ <button type="submit" class="btn btn-primary">Next</button>
23
+ </form>
24
+ {% endblock %}
templates/assessment_complete.html ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}Assessment Complete - AI Readiness Assessment{% endblock %}
4
+
5
+ {% block content %}
6
+ <h2 class="mb-4">Assessment Complete</h2>
7
+ <p>Thank you for completing the AI Readiness Assessment.</p>
8
+
9
+ <div class="row">
10
+ <div class="col-md-6">
11
+ <h3>Your Results:</h3>
12
+ <ul>
13
+ <li>Strategy Score: {{ assessment.strategy_score }}</li>
14
+ <li>Governance Score: {{ assessment.governance_score }}</li>
15
+ <li>Data & Infrastructure Score: {{ assessment.data_infrastructure_score }}</li>
16
+ <li>Organization Score: {{ assessment.organization_score }}</li>
17
+ </ul>
18
+ <h4>Total Score: {{ assessment.total_score }}</h4>
19
+ <h4>Readiness Level: {{ assessment.readiness_level }}</h4>
20
+ </div>
21
+ <div class="col-md-6">
22
+ <canvas id="radarChart"></canvas>
23
+ </div>
24
+ </div>
25
+
26
+ <div class="row mt-4">
27
+ <div class="col-md-6">
28
+ <canvas id="barChart"></canvas>
29
+ </div>
30
+ <div class="col-md-6">
31
+ <h3>Gap Analysis</h3>
32
+ <div id="gapAnalysis"></div>
33
+ </div>
34
+ </div>
35
+
36
+ <div class="row mt-4">
37
+ <div class="col-md-12">
38
+ <h3>Recommendations</h3>
39
+ <div id="recommendations"></div>
40
+ </div>
41
+ </div>
42
+
43
+ <div class="row mt-4">
44
+ <div class="col-md-12">
45
+ <a href="{{ url_for('generate_pdf', assessment_id=assessment.id) }}" class="btn btn-primary">Download PDF Report</a>
46
+ </div>
47
+ </div>
48
+
49
+ <a href="{{ url_for('dashboard') }}" class="btn btn-primary mt-3">Return to Dashboard</a>
50
+
51
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
52
+
53
+ <script>
54
+ document.addEventListener('DOMContentLoaded', function() {
55
+ try {
56
+ // Radar Chart
57
+ const radarCtx = document.getElementById('radarChart').getContext('2d');
58
+ new Chart(radarCtx, {
59
+ type: 'radar',
60
+ data: {
61
+ labels: ['Strategy', 'Governance', 'Data & Infrastructure', 'Organization'],
62
+ datasets: [{
63
+ label: 'Your Scores',
64
+ data: [
65
+ {{ assessment.strategy_score }},
66
+ {{ assessment.governance_score }},
67
+ {{ assessment.data_infrastructure_score }},
68
+ {{ assessment.organization_score }}
69
+ ],
70
+ backgroundColor: 'rgba(54, 162, 235, 0.2)',
71
+ borderColor: 'rgb(54, 162, 235)',
72
+ pointBackgroundColor: 'rgb(54, 162, 235)',
73
+ pointBorderColor: '#fff',
74
+ pointHoverBackgroundColor: '#fff',
75
+ pointHoverBorderColor: 'rgb(54, 162, 235)'
76
+ }]
77
+ },
78
+ options: {
79
+ responsive: true,
80
+ scales: {
81
+ r: {
82
+ angleLines: {
83
+ display: false
84
+ },
85
+ suggestedMin: 0,
86
+ suggestedMax: 20
87
+ }
88
+ }
89
+ }
90
+ });
91
+
92
+ // Bar Chart
93
+ const barCtx = document.getElementById('barChart').getContext('2d');
94
+ new Chart(barCtx, {
95
+ type: 'bar',
96
+ data: {
97
+ labels: ['Strategy', 'Governance', 'Data & Infrastructure', 'Organization'],
98
+ datasets: [{
99
+ label: 'Scores',
100
+ data: [
101
+ {{ assessment.strategy_score }},
102
+ {{ assessment.governance_score }},
103
+ {{ assessment.data_infrastructure_score }},
104
+ {{ assessment.organization_score }}
105
+ ],
106
+ backgroundColor: [
107
+ 'rgba(255, 99, 132, 0.2)',
108
+ 'rgba(54, 162, 235, 0.2)',
109
+ 'rgba(255, 206, 86, 0.2)',
110
+ 'rgba(75, 192, 192, 0.2)'
111
+ ],
112
+ borderColor: [
113
+ 'rgba(255, 99, 132, 1)',
114
+ 'rgba(54, 162, 235, 1)',
115
+ 'rgba(255, 206, 86, 1)',
116
+ 'rgba(75, 192, 192, 1)'
117
+ ],
118
+ borderWidth: 1
119
+ }]
120
+ },
121
+ options: {
122
+ responsive: true,
123
+ scales: {
124
+ y: {
125
+ beginAtZero: true,
126
+ max: 20
127
+ }
128
+ }
129
+ }
130
+ });
131
+
132
+ // Gap Analysis
133
+ const gapAnalysis = document.getElementById('gapAnalysis');
134
+ const scores = [
135
+ { category: 'Strategy', score: {{ assessment.strategy_score }}, max: 19 },
136
+ { category: 'Governance', score: {{ assessment.governance_score }}, max: 17 },
137
+ { category: 'Data & Infrastructure', score: {{ assessment.data_infrastructure_score }}, max: 20 },
138
+ { category: 'Organization', score: {{ assessment.organization_score }}, max: 17 }
139
+ ];
140
+
141
+ let gapHtml = '<ul>';
142
+ scores.forEach(item => {
143
+ const gap = item.max - item.score;
144
+ const status = gap <= 2 ? 'Strength' : 'Area for Improvement';
145
+ gapHtml += `<li>${item.category}: ${status} (Gap: ${gap.toFixed(1)})</li>`;
146
+ });
147
+ gapHtml += '</ul>';
148
+ gapAnalysis.innerHTML = gapHtml;
149
+
150
+ // Recommendations
151
+ const recommendations = document.getElementById('recommendations');
152
+ let recoHtml = '<ul>';
153
+ if ({{ assessment.strategy_score }} < 15) {
154
+ recoHtml += '<li>Focus on developing a comprehensive AI strategy aligned with business goals.</li>';
155
+ }
156
+ if ({{ assessment.governance_score }} < 13) {
157
+ recoHtml += '<li>Strengthen AI governance frameworks and ethical guidelines.</li>';
158
+ }
159
+ if ({{ assessment.data_infrastructure_score }} < 16) {
160
+ recoHtml += '<li>Invest in improving data quality and infrastructure to support AI initiatives.</li>';
161
+ }
162
+ if ({{ assessment.organization_score }} < 13) {
163
+ recoHtml += '<li>Enhance AI skills and promote a culture of innovation within the organization.</li>';
164
+ }
165
+ recoHtml += '</ul>';
166
+ recommendations.innerHTML = recoHtml;
167
+
168
+ } catch (error) {
169
+ console.error('An error occurred:', error);
170
+ document.getElementById('radarChart').innerHTML = 'Error loading chart: ' + error.message;
171
+ document.getElementById('barChart').innerHTML = 'Error loading chart: ' + error.message;
172
+ }
173
+ });
174
+ </script>
175
+ {% endblock %}
templates/assessment_questions.html ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}AI Readiness Assessment{% endblock %}
4
+
5
+ {% block content %}
6
+ <h2 class="mb-4">AI Readiness Assessment</h2>
7
+ <p>Category: {{ questions[0].category }}</p>
8
+ <form method="POST">
9
+ {% for question in questions %}
10
+ <div class="card mb-3">
11
+ <div class="card-body">
12
+ <h5 class="card-title">{{ question.subcategory }}</h5>
13
+ <p class="card-text">{{ question.text }}</p>
14
+ {% for option in question.options %}
15
+ <div class="form-check">
16
+ <input class="form-check-input" type="radio" name="question_{{ question.id }}" id="option_{{ question.id }}_{{ loop.index }}" value="{{ option }}" required>
17
+ <label class="form-check-label" for="option_{{ question.id }}_{{ loop.index }}">
18
+ {{ option }}
19
+ </label>
20
+ </div>
21
+ {% endfor %}
22
+ </div>
23
+ </div>
24
+ {% endfor %}
25
+ <button type="submit" class="btn btn-primary">Next</button>
26
+ </form>
27
+ <a href="{{ url_for('dashboard') }}" class="btn btn-secondary mt-3">Save and Continue Later</a>
28
+ {% endblock %}
templates/base.html ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>{% block title %}AI Readiness Assessment{% endblock %}</title>
7
+ <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
8
+ <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
9
+ </head>
10
+ <body>
11
+ <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
12
+ <div class="container">
13
+ <a class="navbar-brand" href="{{ url_for('home') }}">AI Readiness</a>
14
+ <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
15
+ <span class="navbar-toggler-icon"></span>
16
+ </button>
17
+ <div class="collapse navbar-collapse" id="navbarNav">
18
+ <ul class="navbar-nav ml-auto">
19
+ {% if current_user.is_authenticated %}
20
+ <li class="nav-item">
21
+ <a class="nav-link" href="{{ url_for('logout') }}">Logout</a>
22
+ </li>
23
+ {% else %}
24
+ <li class="nav-item">
25
+ <a class="nav-link" href="{{ url_for('login') }}">Login</a>
26
+ </li>
27
+ <li class="nav-item">
28
+ <a class="nav-link" href="{{ url_for('register') }}">Register</a>
29
+ </li>
30
+ {% endif %}
31
+ </ul>
32
+ </div>
33
+ </div>
34
+ </nav>
35
+
36
+ <div class="container mt-4">
37
+ {% with messages = get_flashed_messages(with_categories=true) %}
38
+ {% if messages %}
39
+ {% for category, message in messages %}
40
+ <div class="alert alert-{{ category }} alert-dismissible fade show" role="alert">
41
+ {{ message }}
42
+ <button type="button" class="close" data-dismiss="alert" aria-label="Close">
43
+ <span aria-hidden="true">&times;</span>
44
+ </button>
45
+ </div>
46
+ {% endfor %}
47
+ {% endif %}
48
+ {% endwith %}
49
+
50
+ {% block content %}{% endblock %}
51
+ </div>
52
+
53
+ <footer class="footer mt-auto py-3 bg-light">
54
+ <div class="container text-center">
55
+ <span class="text-muted">&copy; 2024 AI Readiness Assessment. All rights reserved.</span>
56
+ </div>
57
+ </footer>
58
+
59
+ <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
60
+ <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.3/dist/umd/popper.min.js"></script>
61
+ <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
62
+ </body>
63
+ </html>
templates/dashboard.html ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}Dashboard - AI Readiness Assessment{% endblock %}
4
+
5
+ {% block content %}
6
+ <h1 class="mb-4">Hello, {{ current_user.email }}! Here you can manage your AI Readiness Assessment.</h1>
7
+
8
+ <div class="row mt-4">
9
+ <div class="col-md-6">
10
+ <div class="card mb-4">
11
+ <div class="card-header">
12
+ <h5 class="card-title mb-0">Start New Assessment</h5>
13
+ </div>
14
+ <div class="card-body">
15
+ <p class="card-text">Begin a new AI Readiness Assessment to evaluate your organization's current state.</p>
16
+ <a href="{{ url_for('start_assessment') }}" class="btn btn-primary">Start Assessment</a>
17
+ </div>
18
+ </div>
19
+ </div>
20
+ <div class="col-md-6">
21
+ <div class="card mb-4">
22
+ <div class="card-header">
23
+ <h5 class="card-title mb-0">Previous Assessments</h5>
24
+ </div>
25
+ <div class="card-body">
26
+ <p class="card-text">View and compare your previous AI Readiness Assessment results.</p>
27
+ <a href="#" class="btn btn-secondary">View History</a>
28
+ </div>
29
+ </div>
30
+ </div>
31
+ </div>
32
+
33
+ <div class="row">
34
+ <div class="col-md-12">
35
+ <div class="card">
36
+ <div class="card-header">
37
+ <h5 class="card-title mb-0">AI Readiness Overview</h5>
38
+ </div>
39
+ <div class="card-body">
40
+ <p class="card-text">Your AI Readiness is assessed across four key areas:</p>
41
+ <ul>
42
+ <li>Strategy</li>
43
+ <li>Governance</li>
44
+ <li>Data & Infrastructure</li>
45
+ <li>Organization (Talent & Culture)</li>
46
+ </ul>
47
+ <p>Complete an assessment to see your scores and recommendations in these areas.</p>
48
+ </div>
49
+ </div>
50
+ </div>
51
+ </div>
52
+ {% endblock %}
templates/home.html ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block content %}
4
+ <div class="jumbotron">
5
+ <h1 class="display-4">Welcome to AI Readiness Assessment</h1>
6
+ <p class="lead">This tool helps organizations evaluate their readiness to adopt AI technologies. By assessing key areas such as strategy, governance, data & infrastructure, and organizational talent & culture, we provide a comprehensive analysis of your AI capabilities and identify areas for improvement.</p>
7
+ <hr class="my-4">
8
+ {% if current_user.is_authenticated %}
9
+ <a href="{{ url_for('dashboard') }}" class="btn btn-primary btn-lg">Go to Dashboard</a>
10
+ {% else %}
11
+ <a href="{{ url_for('register') }}" class="btn btn-primary btn-lg">Get Started</a>
12
+ <a href="{{ url_for('login') }}" class="btn btn-secondary btn-lg">Login</a>
13
+ {% endif %}
14
+ </div>
15
+ {% endblock %}
templates/login.html ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block content %}
4
+ <div class="row justify-content-center">
5
+ <div class="col-md-6">
6
+ <div class="card">
7
+ <div class="card-header bg-primary text-white">
8
+ <h2 class="mb-0">Login</h2>
9
+ </div>
10
+ <div class="card-body">
11
+ <form method="POST" action="{{ url_for('login') }}">
12
+ {{ form.hidden_tag() }}
13
+ <div class="form-group">
14
+ {{ form.email.label(class="form-label") }}
15
+ {{ form.email(class="form-control") }}
16
+ {% for error in form.email.errors %}
17
+ <small class="text-danger">{{ error }}</small>
18
+ {% endfor %}
19
+ </div>
20
+ <div class="form-group">
21
+ {{ form.password.label(class="form-label") }}
22
+ {{ form.password(class="form-control") }}
23
+ {% for error in form.password.errors %}
24
+ <small class="text-danger">{{ error }}</small>
25
+ {% endfor %}
26
+ </div>
27
+ {{ form.submit(class="btn btn-primary btn-block") }}
28
+ </form>
29
+ </div>
30
+ <div class="card-footer text-center">
31
+ <p class="mb-0">Don't have an account? <a href="{{ url_for('register') }}">Register here</a></p>
32
+ </div>
33
+ </div>
34
+ </div>
35
+ </div>
36
+ {% endblock %}
templates/register.html ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block content %}
4
+ <div class="row justify-content-center">
5
+ <div class="col-md-6">
6
+ <div class="card">
7
+ <div class="card-header bg-primary text-white">
8
+ <h2 class="mb-0">Register</h2>
9
+ </div>
10
+ <div class="card-body">
11
+ <form method="POST" action="{{ url_for('register') }}">
12
+ {{ form.hidden_tag() }}
13
+ <div class="form-group">
14
+ {{ form.email.label(class="form-label") }}
15
+ {{ form.email(class="form-control") }}
16
+ {% for error in form.email.errors %}
17
+ <small class="text-danger">{{ error }}</small>
18
+ {% endfor %}
19
+ </div>
20
+ <div class="form-group">
21
+ {{ form.password.label(class="form-label") }}
22
+ {{ form.password(class="form-control") }}
23
+ {% for error in form.password.errors %}
24
+ <small class="text-danger">{{ error }}</small>
25
+ {% endfor %}
26
+ </div>
27
+ <div class="form-group">
28
+ {{ form.confirm_password.label(class="form-label") }}
29
+ {{ form.confirm_password(class="form-control") }}
30
+ {% for error in form.confirm_password.errors %}
31
+ <small class="text-danger">{{ error }}</small>
32
+ {% endfor %}
33
+ </div>
34
+ {{ form.submit(class="btn btn-primary btn-block") }}
35
+ </form>
36
+ </div>
37
+ <div class="card-footer text-center">
38
+ <p class="mb-0">Already have an account? <a href="{{ url_for('login') }}">Login here</a></p>
39
+ </div>
40
+ </div>
41
+ </div>
42
+ </div>
43
+ {% endblock %}