ZainabFatimaa commited on
Commit
18a38f3
Β·
verified Β·
1 Parent(s): f90e322

Update src/app.py

Browse files
Files changed (1) hide show
  1. src/app.py +102 -27
src/app.py CHANGED
@@ -31,12 +31,16 @@ import language_tool_python
31
  from sklearn.feature_extraction.text import TfidfVectorizer
32
  from sklearn.metrics.pairwise import cosine_similarity
33
 
34
- # Report generation
35
  from reportlab.lib.pagesizes import letter
36
- from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, BarChart
37
  from reportlab.lib.styles import getSampleStyleSheet
38
  from reportlab.lib.units import inch
39
 
 
 
 
 
40
  # Download NLTK data if not already present
41
  @st.cache_resource
42
  def download_nltk_data():
@@ -305,6 +309,60 @@ class ResumeAnalyzer:
305
 
306
  return summary
307
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
308
  def main():
309
  st.set_page_config(
310
  page_title="AI Resume Analyzer",
@@ -347,6 +405,12 @@ def main():
347
  # Process the resume
348
  st.success("βœ… Resume uploaded and processed successfully!")
349
 
 
 
 
 
 
 
350
  # Create tabs for different analyses
351
  tab1, tab2, tab3, tab4, tab5 = st.tabs([
352
  "πŸ“Š Overview", "🎯 Skills Analysis", "πŸ“ Section Breakdown",
@@ -365,9 +429,6 @@ def main():
365
 
366
  st.metric("Word Count", word_count)
367
  st.metric("Character Count", char_count)
368
-
369
- # Extract sections
370
- sections = analyzer.extract_sections(text)
371
  st.metric("Sections Found", len([s for s in sections.values() if s]))
372
 
373
  with col2:
@@ -391,9 +452,6 @@ def main():
391
  with tab2:
392
  st.header("Skills Analysis")
393
 
394
- # Extract skills
395
- tech_skills, soft_skills = analyzer.extract_skills(text)
396
-
397
  col1, col2 = st.columns(2)
398
 
399
  with col1:
@@ -405,7 +463,7 @@ def main():
405
  st.info("No technical skills detected")
406
 
407
  with col2:
408
- st.subheader("🀝 Soft Skills")
409
  if soft_skills:
410
  for skill in soft_skills:
411
  st.badge(skill, type="primary")
@@ -414,7 +472,6 @@ def main():
414
 
415
  # Job role matching
416
  st.subheader(f"🎯 Match Analysis for {selected_role}")
417
- found_keywords, match_percentage = analyzer.keyword_matching(text, selected_role)
418
 
419
  # Progress bar for match percentage
420
  st.metric("Match Percentage", f"{match_percentage:.1f}%")
@@ -435,8 +492,6 @@ def main():
435
  with tab3:
436
  st.header("Section Breakdown")
437
 
438
- sections = analyzer.extract_sections(text)
439
-
440
  for section_name, content in sections.items():
441
  if content:
442
  with st.expander(f"πŸ“‹ {section_name.title()} Section"):
@@ -447,9 +502,6 @@ def main():
447
  with tab4:
448
  st.header("ATS Analysis")
449
 
450
- # Calculate ATS score
451
- ats_score = analyzer.calculate_ats_score(text, sections)
452
-
453
  col1, col2 = st.columns(2)
454
 
455
  with col1:
@@ -566,9 +618,13 @@ def main():
566
 
567
  # Generate downloadable report
568
  st.subheader("πŸ“„ Download Report")
569
- if st.button("Generate PDF Report"):
570
- # Create a simple text report (in real implementation, use ReportLab)
571
- report_content = f"""
 
 
 
 
572
  RESUME ANALYSIS REPORT
573
  Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
574
 
@@ -578,7 +634,7 @@ OVERVIEW:
578
  - Overall Score: {overall_score:.1f}/100
579
 
580
  PERSONA SUMMARY:
581
- {persona_summary}
582
 
583
  TECHNICAL SKILLS FOUND:
584
  {', '.join(tech_skills) if tech_skills else 'None detected'}
@@ -594,14 +650,33 @@ STRENGTHS:
594
 
595
  AREAS FOR IMPROVEMENT:
596
  {chr(10).join(f'- {i}' for i in improvements)}
597
- """
598
-
599
- st.download_button(
600
- label="πŸ“₯ Download Report",
601
- data=report_content,
602
- file_name=f"resume_analysis_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt",
603
- mime="text/plain"
604
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
605
  else:
606
  st.error("❌ Error processing the uploaded file. Please try a different file.")
607
 
 
31
  from sklearn.feature_extraction.text import TfidfVectorizer
32
  from sklearn.metrics.pairwise import cosine_similarity
33
 
34
+ # Report generation - FIXED IMPORTS
35
  from reportlab.lib.pagesizes import letter
36
+ from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
37
  from reportlab.lib.styles import getSampleStyleSheet
38
  from reportlab.lib.units import inch
39
 
40
+ # Chart imports (if you need charts for PDF reports)
41
+ from reportlab.graphics.charts.barcharts import VerticalBarChart
42
+ from reportlab.graphics.shapes import Drawing
43
+
44
  # Download NLTK data if not already present
45
  @st.cache_resource
46
  def download_nltk_data():
 
309
 
310
  return summary
311
 
312
+ def create_pdf_report(self, text, sections, ats_score, match_percentage, selected_role, tech_skills, soft_skills, found_keywords):
313
+ """Create a PDF report using ReportLab"""
314
+ buffer = io.BytesIO()
315
+ doc = SimpleDocTemplate(buffer, pagesize=letter)
316
+ styles = getSampleStyleSheet()
317
+ story = []
318
+
319
+ # Title
320
+ story.append(Paragraph("Resume Analysis Report", styles['Title']))
321
+ story.append(Spacer(1, 12))
322
+
323
+ # Date
324
+ story.append(Paragraph(f"Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", styles['Normal']))
325
+ story.append(Spacer(1, 12))
326
+
327
+ # Overview section
328
+ story.append(Paragraph("Overview", styles['Heading1']))
329
+ story.append(Paragraph(f"ATS Score: {ats_score}/100", styles['Normal']))
330
+ story.append(Paragraph(f"Role Match for {selected_role}: {match_percentage:.1f}%", styles['Normal']))
331
+ story.append(Paragraph(f"Overall Score: {(ats_score + match_percentage) / 2:.1f}/100", styles['Normal']))
332
+ story.append(Spacer(1, 12))
333
+
334
+ # Skills section
335
+ story.append(Paragraph("Skills Analysis", styles['Heading1']))
336
+ if tech_skills:
337
+ story.append(Paragraph(f"Technical Skills: {', '.join(tech_skills)}", styles['Normal']))
338
+ if soft_skills:
339
+ story.append(Paragraph(f"Soft Skills: {', '.join(soft_skills)}", styles['Normal']))
340
+ if found_keywords:
341
+ story.append(Paragraph(f"Role-specific Keywords Found: {', '.join(found_keywords)}", styles['Normal']))
342
+ story.append(Spacer(1, 12))
343
+
344
+ # Recommendations
345
+ story.append(Paragraph("Recommendations", styles['Heading1']))
346
+ recommendations = []
347
+
348
+ if ats_score < 70:
349
+ recommendations.extend([
350
+ "β€’ Add more bullet points to improve readability",
351
+ "β€’ Include contact information (email, phone)",
352
+ "β€’ Ensure all major sections are present"
353
+ ])
354
+
355
+ if match_percentage < 60:
356
+ recommendations.append(f"β€’ Include more {selected_role}-specific keywords")
357
+
358
+ for rec in recommendations:
359
+ story.append(Paragraph(rec, styles['Normal']))
360
+
361
+ # Build PDF
362
+ doc.build(story)
363
+ buffer.seek(0)
364
+ return buffer
365
+
366
  def main():
367
  st.set_page_config(
368
  page_title="AI Resume Analyzer",
 
405
  # Process the resume
406
  st.success("βœ… Resume uploaded and processed successfully!")
407
 
408
+ # Extract data for analysis
409
+ sections = analyzer.extract_sections(text)
410
+ tech_skills, soft_skills = analyzer.extract_skills(text)
411
+ found_keywords, match_percentage = analyzer.keyword_matching(text, selected_role)
412
+ ats_score = analyzer.calculate_ats_score(text, sections)
413
+
414
  # Create tabs for different analyses
415
  tab1, tab2, tab3, tab4, tab5 = st.tabs([
416
  "πŸ“Š Overview", "🎯 Skills Analysis", "πŸ“ Section Breakdown",
 
429
 
430
  st.metric("Word Count", word_count)
431
  st.metric("Character Count", char_count)
 
 
 
432
  st.metric("Sections Found", len([s for s in sections.values() if s]))
433
 
434
  with col2:
 
452
  with tab2:
453
  st.header("Skills Analysis")
454
 
 
 
 
455
  col1, col2 = st.columns(2)
456
 
457
  with col1:
 
463
  st.info("No technical skills detected")
464
 
465
  with col2:
466
+ st.subheader("🀝 Soft Skills")
467
  if soft_skills:
468
  for skill in soft_skills:
469
  st.badge(skill, type="primary")
 
472
 
473
  # Job role matching
474
  st.subheader(f"🎯 Match Analysis for {selected_role}")
 
475
 
476
  # Progress bar for match percentage
477
  st.metric("Match Percentage", f"{match_percentage:.1f}%")
 
492
  with tab3:
493
  st.header("Section Breakdown")
494
 
 
 
495
  for section_name, content in sections.items():
496
  if content:
497
  with st.expander(f"πŸ“‹ {section_name.title()} Section"):
 
502
  with tab4:
503
  st.header("ATS Analysis")
504
 
 
 
 
505
  col1, col2 = st.columns(2)
506
 
507
  with col1:
 
618
 
619
  # Generate downloadable report
620
  st.subheader("πŸ“„ Download Report")
621
+
622
+ col1, col2 = st.columns(2)
623
+
624
+ with col1:
625
+ # Text report
626
+ if st.button("Generate Text Report"):
627
+ report_content = f"""
628
  RESUME ANALYSIS REPORT
629
  Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
630
 
 
634
  - Overall Score: {overall_score:.1f}/100
635
 
636
  PERSONA SUMMARY:
637
+ {analyzer.generate_persona_summary(text, sections)}
638
 
639
  TECHNICAL SKILLS FOUND:
640
  {', '.join(tech_skills) if tech_skills else 'None detected'}
 
650
 
651
  AREAS FOR IMPROVEMENT:
652
  {chr(10).join(f'- {i}' for i in improvements)}
653
+ """
654
+
655
+ st.download_button(
656
+ label="πŸ“₯ Download Text Report",
657
+ data=report_content,
658
+ file_name=f"resume_analysis_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt",
659
+ mime="text/plain"
660
+ )
661
+
662
+ with col2:
663
+ # PDF report
664
+ if st.button("Generate PDF Report"):
665
+ try:
666
+ pdf_buffer = analyzer.create_pdf_report(
667
+ text, sections, ats_score, match_percentage,
668
+ selected_role, tech_skills, soft_skills, found_keywords
669
+ )
670
+
671
+ st.download_button(
672
+ label="πŸ“„ Download PDF Report",
673
+ data=pdf_buffer.getvalue(),
674
+ file_name=f"resume_analysis_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pdf",
675
+ mime="application/pdf"
676
+ )
677
+ except Exception as e:
678
+ st.error(f"Error generating PDF: {str(e)}")
679
+ st.info("PDF generation requires all ReportLab dependencies. Using text report as fallback.")
680
  else:
681
  st.error("❌ Error processing the uploaded file. Please try a different file.")
682