
    xi$                     p   d dl Z d dlmZ d dlZd dlZd dlmZ d dlZd dlm	Z	 d dl
 d dlmZ d dlmZmZ d dlmZ d d	lmZ d d
lmZ d dlmZ  e         e e j0                  d            Z e j0                  dd      Z e j0                  dd      Z e j0                  dd      ZdZdZdZ G d d      Z y)    N)OpenAI)HTML)HtmlFormatter)*)load_dotenv)	PdfReader	PdfWriter)BytesIO)canvas)Color)letterOPENAI_API_KEY)api_keyOPENAI_MODELzgpt-4oOPENAI_MINI_MODELzgpt-4o-miniOUTPUT_FOLDERz./result
imscc_tempwiki_contenta  
<script>
MathJax = {
  tex: {
    inlineMath: [['$', '$'], ['\\(', '\\)']],
    displayMath: [['\\[', '\\]']]
  },
  svg: {
    fontCache: 'global'
  }
};
</script>
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js" async></script>
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script><script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
c                       e Zd Zd Zd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd ZddZd ZddZd dZd Zd Zd Zd ZdededefdZdddefdZy)!CourseCreatorc                 (   |j                   | _         |j                  | _        |j                  | _        |j                  | _        |j                  | _        |j
                  | _        |j                  | _        |j                  | _        |j                  | _        |j                  | _	        |j                  | _
        |j                  | _        |j                  | _        |j                  r|j                  nd| _        |j                  r|j                  nd| _        |j                  r|j                  nd| _        d| _        | j                   j%                  dd      | _        t(        j*                  j-                  t.        | j&                   d      | _        t(        j*                  j3                  t.              st)        j4                  t.        d	       | j                  d
k(  rd| _        n5| j                  dk(  rd| _        n| j                  dk(  rd| _        nd| _        | j                  dk(  rd| _        n5| j                  dk(  rd| _        n| j                  dk(  rd| _        nd| _        | j                  dk(  rd| _        g | _        y | j                  dk(  rd| _        g | _        y | j                  dk(  rd| _        g | _        y | j                  dk(  rd| _        g | _        y | j                  dk(  rd| _        g | _        y d| _        g | _        y ) NeasyMCQ   i.   _.mdTexist_okbachelorzBachelor's DegreemasterszMaster's Degreedoctoralz!Doctoral and Post-Graduate DegreebloomzRevised Bloom's TaxonomysolozSolo TaxonomywebbzWebb's Depth of Knowledge (DOK)designz2Learning Approach based on Design Thinking Processprojectz%Project-based Learning (PBL) Approach
competencyz(Competency-based Learning (CBL) Approach	21centuryz21st Century Learning Approachinterdisciplinaryz#Interdisciplinary Learning Approach)topicskillstonedegreetaxonomyallocated_timelearning_approachno_of_modulesmode_of_deliveryoutlinelanguagecontent_outcomescontent_descriptionlevel_of_difficultytype_of_assessmentno_of_questionsnum_of_questionsmax_paragraph_lengthreplacebase_filenameospathjoinr   course_pathexistsmakedirsdegree_nametaxonomy_desclearning_approach_descglossary_list)selfcourses     :/var/www/html/content_weaver/dependencies/CourseCreator.py__init__zCourseCreator.__init__*   s    \\
mmKK	mm$33!'!9!9#11 & 7 7~~ & 7 7#)#=#= AGA[A[6#=#=ag ?E?X?X&";";^c:@:P:P 6 6VW$)!!ZZ//S977<<$:L:L9MS7QRww~~m,KK5 ;;*$2D[[I%0D[[J&BD2D ==G#!;D]]f$!0D]]f$!BD!;D !!X-*^D'   ##y0*QD'   ##|3*TD'   ##{2*JD'   ##'::*OD'
   +_D'      c                     d| j                    d| j                   d| j                   d| j                   d| j                   d| j
                   d| j                   d| j                   d	| j                   d
S )NzCourseCreator(topic=z	, skills=z, tone=z	, degree=z, taxonomy=z, allocated_time=z, learning_approach=z, no_of_modules=z, mode_of_delivery=))	r+   r,   r-   r.   r/   r0   r1   r2   r3   )rI   s    rK   __repr__zCourseCreator.__repr__k   s    %djj\4;;-wtyykYbcgcncnbooz{  |I  |I  {J  J[  \`  \o  \o  [p  pD  EI  E[  E[  D\  \l  mq  m  m  l@  @S  TX  Ti  Ti  Sj  jk  l  	lrM   c                 n   | j                   st        d      d| j                   d| j                   d| j                   d}d| j                    d| j                   d| j                    d	| j                   d
| j
                   d| j                   d| j                   d}| j                  ||ddd      }|S )z-Generate a course summary based on the topic.z-Course topic is required to generate summary._You are an experienced teacher and an expert in designing courses for students and learners of  on  in a  tone.
You are good in creating logical flow of courses in which you break down the course into modules and arrange them in sequential flow for students to understand the subject.7You are an experienced course creator and an expert in z;.
You are planning to create a course to teach students of  about ===  ===.
In a ) tone, you will be creating a course for zP level skills development of the students.
The student will spend not more than z hours in studying the course including the completion of exercises.
When planning and organizing the content, you will be following z definition as much as possible.
Your task now is to generate a summary of this course that you are going to create. The summary should include the main topics that will be covered in the course and the overall learning objectives.皙?  ?r+   
ValueErrorrE   rF   r-   r,   r0   
clientCallrI   system_promptuser_promptresponses       rK   generate_course_summaryz%CourseCreator.generate_course_summaryo   s   zzLMMyz~  {K  {K  zL  LP  QU  Qc  Qc  Pd  dj  ko  kt  kt  ju  ui  jOPTPZPZ|  \X  Y]  Yi  Yi  Xj  ju  vz  v@  v@  uA  AM  NR  NW  NW  MX  XA  BF  BM  BM  AN  N_  `d  `s  `s  _t  tz  {  {M  {M  zN  Nv  w ??=+sD#NrM   c                 n   | j                   st        d      d| j                   d| j                   d| j                   d}d| j                    d| j                   d| j                    d	| j                   d
| j
                   d| j                   d| j                   d}| j                  ||ddd      }|S )z.Generate course objectives based on the topic.z0Course topic is required to generate objectives.rR   rS   rT   rU   rV   8.
You are going to create a course to teach students of rW   rX   rY   U level skills development of the students.
The student will be spending a maximum of  hours in studying this course including the completion of exercises.
When planning and organizing the content, you will be following z definition as much as possible.
Your task now is to create a set of clear and measurable objectives of this course that you are going to create. The objectives should be specific, measurable, achievable, relevant, and time bound.rZ   r[   r\   r]   r`   s       rK   generate_course_objectivesz(CourseCreator.generate_course_objectives~   s   zzOPPyz~  {K  {K  zL  LP  QU  Qc  Qc  Pd  dj  ko  kt  kt  ju  ui  jOPTPZPZ|  \U  VZ  Vf  Vf  Ug  gr  sw  s}  s}  r~  ~J  KO  KT  KT  JU  U~  C  J  J  ~K  Ka  bf  bu  bu  av  v}  ~B  ~P  ~P  }Q  Qx  y ??=+sD#NrM   c                    | j                   st        d      d}t        | j                  d      }t        | j                  d      }t        | j
                  d      }t        | j                  d      }|d| d	| d	| d	| z  }d
| j                    d| j                   d| j                    d| j                   d| j
                   d| j                   d| j                   d| j                    d}|dz  }|dz  }|d| j                   dz  }| j                  ||ddd      }|j                  d      d   j                         }|j                  d      \  }}	|j                         }|	j                         j                  d	      }	|	D 
cg c]#  }
|
j                         s|
j                         % }	}
d	j                  |	      }	||	dS c c}
w )z,Generate course outcomes based on the topic.z.Course topic is required to generate outcomes.zYou are an experienced teacher and an expert in designing courses for students and learners. Follow and adhere to the following definitions:prompt-degreeprompt_typeprompt-toneprompt-skillszprompt-taxonomy


rV   rf   rW   rX   rY   rg   rh   zh definition as much as possible.
First, give an overview of the content of the course for the topic === a&   ===.
And then define in no more than 5-7 bullet points about the outcome of this course that you have planned and designed.
These points should be clear and specific statements of what the learner will be able to achieve upon the successful study and completion of this course.

The format is:z

### Course Overview:
z### Course Outcomes:
z0

The course overview and outcomes should be in 
 language.      ?r[   r\   z### Course Overview:   z### Course Outcomes:)overviewoutcomes)r+   r^   
get_promptr.   r-   r,   r/   rE   r0   rF   r5   r_   splitstriprA   )rI   ra   degree_prompttone_promptskills_prompttaxonomy_promptrb   rc   ru   rv   outcomes              rK   generate_course_outcomesz&CourseCreator.generate_course_outcomes   sv   zzMNN g"4;;OL F"4;;OL$T]]@QR4br+bQ`Pabb PPTPZPZ|  \U  VZ  Vf  Vf  Ug  gr  sw  s}  s}  r~  ~J  KO  KT  KT  JU  U~  C  J  J  ~K  Ka  bf  bu  bu  av  v}  ~B  ~P  ~P  }Q  Qz	  {		  {	E
  {	E
  z	F
  F
p  q34/0KDMM?Zdee??=+sD#N>>"89!<BBD%^^,BC(>>#>>#))$/3;Ow}}GMMOOO99X&  
 	
 Ps   G#Gc                    | j                   r|r|st        d      d| j                   d| j                   d| j                   d| d| d}d| j                    d	| j                   d| j                    d
| j
                   d| j                    d| j                   d| j                   d| j                   d}| j                  ||ddd      }|S )z8Generate course modules based on the topic and outcomes.z?Topic, overview, and outcomes are required to generate modules.rR   rS   rT   a
   tone.
You are very good in creating logical flow of courses in which you break down the course into modules and arrange them in sequential flow for a student to understand the subject.

You are already designing and working on a course, the description of which is z9.
You have carefully defined the course outcome which is .z_You are now seriously working on the teaching structure of a course, the title of which is === z= ===.
Your goal is to create a course layout for students of zi, so that they can fully understand the subject for their level.
Your task now is to create a maximum of z for this course on === z} ===. Think of the modules in a sequential and logical order of understanding and learning. 
Remember that you are following a   framework. 
For each module, think of the subtopics in that module which you will cover and summarize them in not more than 3 lines on what the module will cover. Then list down all the modules and the clear description of what will be covered in each of the module along with the subtopics. Then provide the estimated time for each module in minutes. 

The course module should be in a   language. 

The course layout should be in the following format:

 ## Course Outline
 ### Module 1: [Module Title]
**Description:** [Brief description of what will be covered in this module]
**Subtopics:**
- Subtopic 1
- Subtopic 2
- Subtopic 3
**Estimated Time:** [Time in minutes]

### Module 2: [Module Title]
**Description:** [Brief description of what will be covered in this module]
**Subtopics:**
- Subtopic 1
- Subtopic 2
- Subtopic 3
**Estimated Time:** [Time in minutes]

...

### Module N: [Module Title]
**Description:** [Brief description of what will be covered in this module]
**Subtopics:**
- Subtopic 1
- Subtopic 2
- Subtopic 3
**Estimated Time:** [Time in minutes]

Remember to use  tone333333?  r\   )r+   r^   rE   rF   r-   r2   r5   r_   )rI   course_overviewcourse_outcomesra   rb   rc   s         rK   generate_course_modulesz%CourseCreator.generate_course_modules   s   zz^__yz~  {K  {K  zL  LP  QU  Qc  Qc  Pd  dj  ko  kt  kt  ju  uB  CR  BS  SM  N]  M^  ^_  `wx|  yC  yC  xD  DB  CG  CS  CS  BT  TX  Y]  Yc  Yc  Xd  dN  OS  Oa  Oa  Nb  bz  {  {E  {E  zF  FD  EI  EW  EW  DX  X]  ^b  ^k  ^k  ]l  lI  JN  JS  JS  IT  TY  Z ??=+sD#NrM   c                 .   d}|rt        | j                  d      }t        | j                  d      }d| d}t        | j                  d      }t        | j                  d      }t        | j
                  d	      }	t        | j                  d      }
t        | j                  d
      }|d| d|	 d| d|
 z  }|d| j
                   d| j                   d| j                   d| j                   d	z  }|d   }|d   }t        |d      D ]  \  }}|d   }|j                  dg       }t        d|       |rdj                  d |D              nd}|dk(  r
d| d| d}nd| d| d d}|}d | d!| d"| j                   d#| d$	}|| dz  }|d%z  }|d&| j                   d'z  }| j                  ||d(d)d*      }|d+| d,| d| dz  }| d}|r|d-z  }|D ]  }|j!                         }|st        |       |rd.| nd}d/| j
                   d| j                   d| j                   d| j                   d0| d1| d2}d3| d4| d5}| j                  ||d(d6d*t"              }|| dz  }|| dz  } |d7z  }|| j%                  |      z  } |S )8z*Generate detailed content for each module. zprompt-learning-approachrl   zprompt-mode-of-deliveryzuYou are an experienced teacher and an expert in designing courses for students and learners. You are a specialist in z1. Follow and adhere to the following definitions:rk   rn   ro   ztemplate-outlinerp   rq   z,

You are creating content for a course for z* level skills of students and learners of rT   z" tone.
It is important to use the z when generating the content.ru   rv   rt   startmodule_title	subtopicsz
Subtopics:c              3   &   K   | ]	  }d |   yw)- N ).0sts     rK   	<genexpr>zACourseCreator.generate_module_detailed_content.<locals>.<genexpr>   s     .MRB4y.Ms   zNo specific subtopics provided.zFYou are writing the first module of the course, the title of which is z . The outcome of this module is r   zDNow you are writing the module of the course, the title of which is zC. Remember that the last module which you have already written was zSYou are already working on detailed content for a course, the overview of which is z and the course outcome is z.
You have planned z modules within this course.
aQ  


Your task is to create a detailed content for this module, keeping in mind the outcome.
 No need to include module title in content.
You will start with a springboard to introduce each module and then add minimum 4 paragraphs of content to achieve the outcome of the module covering all the key objectives.

Use the following format:
zAdd suggested reading links and exercises/activities at the end of the module content.
 Include the instructional videos and links wherever necessary.
zThe content should be in rr   rZ   ix  r\   z### Module z: z#### Subtopic:
r   zYou are an expert in generating comprehensive content blocks for each subtopic of a module. As a content writer, you are creating content for a course for z[ when generating the content. Now you are going to write a content block for the subtopic 'z' of the module 'z'.zaYou are now writing a comprehensive content block covering the following subtopic of the module 'z':
z&

Write minimum 6 paragraphs in total.i  z#### Questions:

)rw   r1   r3   r.   r-   r,   r4   rE   rG   	enumerategetprintrA   r2   r5   r_   ry   r   generate_mcq_questions)rI   modulesr   mdprompt_learning_approachmode_descriptionra   rz   r{   r|   learning_approach_prompttemplate_promptru   rv   indexmoduletitler   subtopic_list_text	milestonelast_modulerb   rc   mcq_contentsubtopicsubtopic_promptsubtopic_responses                              rK    generate_module_detailed_contentz.CourseCreator.generate_module_detailed_content   s    '1$2H2HVp'q$)$*?*?Mfg T  Ue  Tf  fW  XM&t{{PM$TYYMJK&t{{PM'1$2H2HVp'q$(CUVOtM?"]O2k]RTUmTnooMMdkk]  [E  FJ  FV  FV  EW  W]  ^b  ^g  ^g  ]h  hK  LP  Lg  Lg  Kh  hE  F  FM&z2H&z2H!*7!!< G?v~."JJ{B7	lI.QZTYY.M9.M%M  aB"A:"hinho  pP  Qc  Pd  de  !fI"fglfm  nN  Oa  Nb  be  fq  er  rs  !tI# st|s}  ~Y  Zb  Yc  cw  x|  xJ  xJ  wK  Ki  js  it  tM	  N	/!2$77  "{  |!:4==/TT  ??=+sDRUVE7"UG2hZtDD "*
$/ ,-B$- B#+>>#3'$h AIr(_No* +F  GK  GR  GR  FS  S}  ~B  ~N  ~N  }O  OU  VZ  V_  V_  U`  `C  DH  D_  D_  C`  `{  |D  {E  EV  W\  V]  ]_  )` -N  OT  NU  UY  Zl  Ym  mU  +V,0OOM?\_aegjlx,y)!2 3488#*;)<D'AA!BB +,d11+>>OG?R 	rM   c                 H   |st        d      |j                         }t        |      | j                  kD  r|d| j                   }t	        | j
                   dd      }d| j                   d| d}d	| j                   d
| d}| j                  ||dddt              }| dS )z3Generate MCQ questions based on the course content.z5Content is required to generate assessment questions.Nz-mixedquestion_guidelinesrl   z	Generate a   unambiguous, unbiased, and verifiable multiple-choice questions based on the following paragraph with  answers at the end. 

        Ensure the questions and options are unbiased, free from any cultural, racial, or gender bias, and are appropriate for diverse audiences.

        Each question MUST be unique, and have exactly 4 options (A, B, C, D), with only one correct answer. Format each question as follows: The format will be in markdown format:
        
        Question 1: [Question text]
        A. [Option A]
        B. [Option B]
        C. [Option C]
        D. [Option D]
        Correct Answer: [A/B/C/D]

        Ensure that the options are plausible and avoid trivial or obviously incorrect answers.

        The paragraph is 

=== z

===

Question:zYou are an expert in generating multiple choice questions within the scope of a given text. You are now given a text and are going to generate zV from it. But you are going to follow these guidelines when generating the questions: z  r   i  r\   rp   )	r^   ry   lenr<   rw   r/   r;   r_   r   )rI   contentincoming_textr   rb   ra   rc   s          rK   r   z$CourseCreator.generate_mcq_questions   s    TUU} 9 99)*D4+D+DEM(DMM?&)AOde#D$9$9#: ;" #00DH" j  ko  k@  k@  jA  AW  Xk  Wl  ln  o ??=+sD#O`a4  rM   c                    | j                   st        d      d| j                   d| j                   d| j                   d}d| j                    d| j                   d| j                    d	| j                   d
| j
                   d| j                   d| j                   d| j                    d| j                   d| j                   d| j                   d}| j                  ||ddd      }|S )z1Generate a course description based on the topic.z1Course topic is required to generate description.rR   rS   rT   z tone.
You are very good in creating logical flow of courses in which you break down the course into modules and arrange them in sequential flow for a student to understand the subject.rV   rf   rW   rX   rY   rg   rh   a|   definition as much as possible.
Your task now is to create a brief description of the course that you are going to plan and design. The description should include the main topics that will be covered in the course and the overall learning objectives. 
The description should be engaging and informative, suitable for attracting students to enroll in the course.
 
This course on z is designed for aH   students who are looking to enhance their understanding and skills in this subject. The course will cover the following main topics:
1. Topic 1
2. Topic 2
3. Topic 3

By the end of this course, students will be able to achieve the following goals:
- Objective 1
- Objective 2
- Objective 3

The course description should be in z language.
Remember to use r   rZ   r[   r\   )	r+   r^   rE   rF   r-   r,   r0   r5   r_   r`   s       rK   generate_course_descriptionz)CourseCreator.generate_course_descriptionD  s   zzPQQyz~  {K  {K  zL  LP  QU  Qc  Qc  Pd  dj  ko  kt  kt  ju  uo  pOPTPZPZ|  \U  VZ  Vf  Vf  Ug  gr  sw  s}  s}  r~  ~J  KO  KT  KT  JU  U~  C  J  J  ~K  Ka  bf  bu  bu  av  v}  ~B  ~P  ~P  }Q  QQ  RV  R\  R\  Q]  ]n  os  o  o  n@  @R  SW  S`  S`  Ra  a}  ~B  ~G  ~G  }H  HM  N ??=+sD#NrM   c                     | j                   st        d      d| j                   d| j                   d| j                   d}d| j                    d| j
                   d}| j                  ||d	d
d      }|S )z.Generate a course glossary based on the topic.z.Course topic is required to generate glossary.zvYou are an experienced teacher and good in understanding words and researching their meaning and explaining them in a z2 tone. Your audience are students and learners of 
 and have  level skills.rV   a5  .
Your task now is to create a glossary of key terms and concepts related to the course topic. The glossary should include definitions and explanations of important terms that will be used throughout the course.
Each explanation should be in as plain and clear language as possible.
The glossary should be in z/ language and it must be in alphabetical order.rs   r[   r\   )r+   r^   r-   rE   r,   r5   r_   r`   s       rK   generate_course_glossaryz&CourseCreator.generate_course_glossaryR  s    zzMNN Q  RV  R[  R[  Q\  \N  OS  O_  O_  N`  `j  ko  kv  kv  jw  wE  FOPTPZPZ|  \T  UY  Ub  Ub  Tc  cR  S ??=+sD#NrM   c                    |st        d      |dk(  r| j                         }|d   S 	 d| d| d| j                   d| d| d	| j                   d
| j                   d| d| j
                   d| j                   d}d| d| d| j
                   d| j                   d	}t        d|        t        d|        | j                  ||ddd      }|S )z:Generate AI content based on the content type and content.z0Content type is required to generate AI content.r6   rv   z You are an expert in generating z. Your task is to create z  based on the following topic:

z

Please provide the z$ in a clear and concise manner. The z should be in z language. Remember to use z tone. The z1 should be suitable for students and learners of z with r   zJ. You have a deep understanding of how to create engaging and informative zI based on the provided input. Your audience are students and learners of r   zSystem Prompt: zUser Prompt: rs   r[   r\   )	r^   r   r+   r5   r-   rE   r,   r   r_   )rI   content_typer   rb   ra   rc   s         rK   generate_ai_contentz!CourseCreator.generate_ai_content`  s   OPP--";;=O":..T<\NJcdpcq  rT  UY  U_  U_  T`  `w  xD  wE  Ei  jv  iw  wE  FJ  FS  FS  ET  To  pt  py  py  oz  zE  FR  ES  SD  EI  EU  EU  DV  V\  ]a  ]h  ]h  \i  iw  xK>|n  MW  Xd  We  en  os  o  o  n@  @J  KO  KV  KV  JW  We  fMOM?34M+/0}k3cRHOrM   c                    | j                   st        d      d| j                    d}t        d| j                           | j                  rt        d       | j                  }n| j	                         }t        d|        |d| dz  }t        d| j                           | j                         }t        d	| j                           | j                  r| j                  |d
<   t        d|d
           | j                  ||d
         }| j                  |      }t        d|        | j                  ||      }|d|d
    dz  }|| dz  }|d| dz  }|| j                          dz  }t        | j                   dd      5 }|j                  |       ddd       t        d| j                          | j                  |       | j                  ||d   |d
   |||dS # 1 sw Y   LxY w)z-Generate course materials based on the topic.z-Course topic is required to generate content.z
# Course: rp   z)Generating course Description for topic: z"Using provided course description.zCourse Description: z## Course Description
z&Generating course outcomes for topic: z%Generating course modules for topic: rv   zCourse Outcomes: Module Titles: z## Course Outcomes
z## Module Details
wutf-8encodingNu,   ✅ Course materials generated and saved to ru   )rB   module_titlesr   r   markdown_contentmodule_detailcourse_description)r+   r^   r   r7   r   r   r6   r   extract_module_titlesr   r   openrB   writeexport_to_html_and_pdf)rI   r   r   r   course_modulesr   r   fs           rK   generate_course_materialsz'CourseCreator.generate_course_materialsr  s3   zzLMM$**T* 	9$**FG##67!%!9!9!%!A!A!C$%7$89:
'(:';4@@ 	6tzzlCD7795djj\BC   *.*?*?OJ'!/*"=!>?@556H/ZdJef22>B/0==m_] 	$_Z%@$AFF
 %%
#M?$77 	..0166 T%%&w? 	1GGBK	<T=M=M<NOP##B'  ++*.z:.z: "*"4
 	
	 	s   	G&&G/c                    d}d}g }|j                         D ]  }|j                         }t        j                  d|t        j                        xs t        j                  d|t        j                        xss t        j                  d|t        j                        xsL t        j                  d|t        j                        xs% t        j                  d|t        j                        }|r9|r|j                  |       |j                  d      j                         g d	}d}t        j                  d
|t        j                        rd}9t        j                  d|t        j                        }t        j                  d|t        j                        }|r||j                  d      j                         }	|	r[|	dvrW|	j                  d      D 
cg c]#  }
|
j                         s|
j                         % }}
|r|d   j                  |       d}t        j                  d|t        j                        s%t        j                  d|t        j                        rd}O|rYt        j                  d|      }|r:|j                  d      j                         }|r |dvr|d   j                  |       n|sd}nd}|s|j                  d      j                         }|s|s||d<    |r|j                  |       |S c c}
w )z.Extract module titles from the course outline.NFz(?:#+\s*)?Module\s*\d+:\s*(.+)z\*\*Module\s*\d+:\s*(.+?)\*\*z^#{3,4}\s*Module\s+\d+:\s*(.+)z!^#{3,4}\s*Module\s+\d+\s*:\s*(.+)z^#{3,4}\s*Module\s+\d+:\s+(.+)rt   )r   r   z^\*\*Subtopics:?\*\*$Tz-\s*\*\*Subtopics\*\*\s*(.*)z*[*]{1,2}Estimated Time:[:]*[*]{0,2}\s*(.+)):**,r   z#-\s*(?:\*\*)?Subtopics:?(\*\*)?\s*$z^#{3,4}\s*Subtopics:?$z^- (.+))r   r   r   estimated_time)	
splitlinesry   rematch
IGNORECASEappendgrouprx   extend)rI   course_outlinecurrent_modulecollecting_subtopicsr   linemodule_matchinline_subtopics_matchestimated_time_matchsubtopic_strtr   subtopic_itemr+   r   s                  rK   r   z#CourseCreator.extract_module_titles  s    $"--/ E	FD::<D :D"--P Q94OQ:D"--PQ =tR]]SQ :D"--P  !NN>2 %1$6$6q$9$?$?$A!#"
 (-$xx0$F'+$ &(XX.MtUWUbUb%c"#%88,Y[_acanan#o %5;;A>DDF(C4@4F4Fs4K Yqqwwy YI Y%&{3::9E+0( xx>bmmTXZX`X`az  }A  CE  CP  CP  YQ'+$ $ "T : )//288:E%%*F&{3::5A+0( ,1( $!5!;!;A!>!D!D!F!n7EN#34KE	FL NN>*I !Zs   L	*L	Nc                     t         j                  j                  | j                        st	        dd      ||}nt        | j                        }| j                  |      }t        d|        |S )z4Get the module titles from the course markdown file.  Course markdown file not found.status_codedetailr   )r?   r@   rC   rB   HTTPExceptionread_txt_filer   r   )rI   markdown_textr   r   s       rK   get_module_titleszCourseCreator.get_module_titles  sh     ww~~d../C8YZZ$#G#D$4$45G227;/0rM   c                     t         j                  j                  | j                        st	        dd      t        | j                        }|S )z.Get the course content from the markdown file.r   r   r   )r?   r@   rC   rB   r   r   )rI   r   s     rK   get_course_contentz CourseCreator.get_course_content  s=     ww~~d../C8YZZ 0 01rM   c           	         g d}t        j                  ||      }t               j                  d      }|dz  }d}d| d| dt         d	| d
	}t
        j                  j                  t        | j                        }| d}	t        |	dd      5 }
|
j                  |       ddd       | d}|r| }nd}t        |      }|j                         }t        t        |            }t!               }t"        \  }}|j$                  D ]  }t               }t'        j(                  |||f      }|j+                  dd       |j-                  t/        dddd             |j1                          |j3                  |dz  |dz         |j5                  d       |j7                  dd|       |j9                          |j;                          |j=                  d       t        |      j$                  d   }|j?                  |       |jA                  |        t        |d      5 }
|j                  |
       ddd       tC        d|	 d|        |	|dS # 1 sw Y   xY w# 1 sw Y   ,xY w) z2Export the course content to HTML and PDF formats.	zfenced-code-blockszcode-friendlytableszcuddled-listszbreak-on-newlinezsmarty-pants	footnotestocztarget-blank-linksextras.codehilitea  
        body {
            font-family: Arial, sans-serif;
            line-height: 1.5;
            margin: 10px;
        }
        h1, h2, h3, h4, h5, h6 {
            margin-top: 1em;
            margin-bottom: 0.5em;
        }
        table {
            border-collapse: collapse;
            margin: 1em 0;
            width: 100%;
        }
        table, th, td {
            border: 1px solid #888;
            padding: 8px;
            text-align: left;
        }
        code, pre {
            background: #f8f8f8;
            padding: 4px;
            border-radius: 4px;
        }
        pre {
            overflow-x: auto;
            padding: 10px;
        }
        z[<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/katex.min.css">V<!DOCTYPE html>
                    <html lang="en">
                    <head><style>z	</style>
rq   z"</head>
                    <body>#</body>
                    </html>.htmlr   r   r   Nz.pdfCONFIDENTIAL)string)pagesizezHelvetica-Bold2   g333333?g?)alpha   -   r   wbu   ✅ Exported to z and )	html_filepdf_file)"	markdown2markdownr   get_style_defsMATHJAX_CDNr?   r@   rA   r   r>   r   r   r   	write_pdfr   r
   r	   r   pagesr   CanvassetFontsetFillColorr   	saveState	translaterotatedrawCentredStringrestoreStatesaveseek
merge_pageadd_pager   )rI   r   tenent_namer   html_contentstyle	katex_css	full_htmloutput_baser   r   r   watermark_texthtml_obj	pdf_bytes
pdf_reader
pdf_writer
page_widthpage_heightpagewatermark_buffercwatermark_pages                          rK   r   z$CourseCreator.export_to_html_and_pdf"  sl    b ))*:6J ..}=  	> r	""'
9+R} M'. )	 ggll=$2D2DE #m5)	)S73 	qGGI	 "]$'  +}N+N y)&&(	 wy12
[
"(
K$$ 	&D&y.*k9RSAII&+NN5c3c:; KKMKK
Qa8HHRL1n5NNFFH!!!$&'78>>qANOON+%)	&, (D! 	 QQ	  	 5
;<" 
 	
e	 	\	  	 s   I#I I I)c                    t        j                  d|      }t        j                  dd|t        j                        }t        j                  dd|      j                  d      }t        |      |kD  r|d| j                  d      }|xs dS )	z@Make a filesystem-safe, reasonably short filename from a string.NFKDz[^\w\s-]r   flagsz[-\s]+r   Nuntitled)unicodedata	normalizer   subUry   r   rstrip)rI   smax_lens      rK   safe_filenamezCourseCreator.safe_filename  sy     !!&!,FF;ARTTF2FF9c1%++C0q6G(7""3'AJrM   c           	      T   t        | j                  j                  dd      j                  dd            }t        j                  j                  t        |      }t        j                  j                  |t              }t        j                  t        d       t        j                  |d       t        j                  j                  t        | d      }t        j                  j                  t        | d      }t        j                  j                  |      s|t        d	d
      | j                  |||       t        ||t        t        j                  j                  |d             t        j                  |dt        j                         5 }t        j"                  t              D ]`  \  }}	}
|
D ]U  }t        j                  j                  ||      }t        j                  j%                  ||      }|j'                  ||       W b 	 ddd       |S # 1 sw Y   |S xY w)zE
        Generate an IMSCC package from the article content.
        r   r   /Tr   z.imsccr   Nr   z:Markdown file not found. Please generate the course first.r   zimsmanifest.xml)course_titlecontent_dirwiki_diroutput_filer   r   )truncate_filenamer+   r=   r?   r@   rA   working_dirr2  rD   r   rC   r   save_sections_as_htmlcreate_manifestzipfileZipFileZIP_DEFLATEDwalkrelpathr   )rI   r   article_titlearticle_dirwiki_content_diroutput_pathmarkdown_pathzfrootr   filesfile	full_patharcnames                 rK   generate_imscczCourseCreator.generate_imscc  s    *

""3,44S#> ggll;>77<<[A
K$/
$t4ggll=]O62JK]}oS4IJww~~m,C8tuu""7;7GH 	&# [2CD		
 __[#w/C/CD 	1"$''+"6 1a! 1D "T4 8I ggooi{oKGHHY011	1 	1 s   A=HH'c           
         dddd}|j                         D ]  \  }}t        j                  ||t        j                  t        j                  z        }|rW|Ut        j                  |j                  d            }| j                  t        j                  j                  ||      |       t        d|         t        j                  dt        j                  t        j                  z  t        j                  z        }	|	j                  |      }
|
D ]2  \  }}}d	| }t        j                  j                  ||      }t        j                   |d
       t        j#                  dd|t        j                  t        j                  z  t        j                  z        }| j%                  |d      dz   }| j'                  |j)                         |      }| j+                  |j)                         ||       t-        |j)                               dz   }t        j                  j                  ||      }	 | j                  ||       5 t        dt1        |       d|        y# t.        $ rf}t        d| d|dd  d|        t        j                  j                  |d	| d      }t        d|        | j                  ||       Y d}~d}~ww xY w)zi
        Reads a markdown file, splits it into sections, and saves each section as an HTML file.
        z;##\s*Course Description\s*\n(.*?)(?=\n##\s*Course Outcomes)z7##\s*Course Outcomes\s*\n(.*?)(?=\n##\s*Course Outline)z9##\s*Course Outline[^\n]*\n(.*?)(?=\n##\s*Module Details))zcourse-description.htmlzcourse-outcomes.htmlzcourse-outline.htmlNrt   z[WARN] Section not found for zp^#{2,6}\s*Module\s+(\d+):\s*([^\r\n]+)\r?\n+^#{2,6}\s*Module Details\s*\r?\n+(.*?)(?=^#{2,6}\s*Module\s+\d+:|\Z)r   Tr   z7^#{2,6}\s*Questions\s*[:\-]?\s*\r?\n.*?(?=^#{1,6}\s|\Z)r   r$  P   )r-  r   z&[ERROR] Failed saving file for module z with title 'x   z': z%[INFO] Attempting fallback filename: u   ✅ Exported z sections to: )itemsr   searchSr   r   r   r   	save_htmlr?   r@   rA   r   compileMfindallrD   r)  r.  markdown_to_htmlry   extract_mcq_questionsreplace_special_characters	Exceptionr   )rI   r   r2  r@  sectionsfilenamepatternr   htmlmodule_patternr   num	raw_titlefolder_name
module_dircontent_no_questions
file_title	html_pageout_pathefallbacks                        rK   r7  z#CourseCreator.save_sections_as_html  s    (f$^#_
 "*!1 	BHgIIgwr}}0DEE* ))%++a.9rww||KBDI5hZ@A	B 3 DD244K"--'	
 !((1'. 	4#CG"3%.K&6DJKK
T2#%66JddRTTkBMM1	 $* $  ++Ir+BWLJ --ioo.?AUVI &&y'8':N 4IOO4EFPJww||J
;H4x31	4d 	c(m_N;K:LMN3  4>se=QZ[_\_Q`Paadefdghi77<<
fSE4GH=hZHIx334s   6I&&	K/AKKc           	         t         j                  dt         j                  t         j                  z  t         j                  z        }|j                  |      }|st        d       y|g d}d}t        |      D ]  \  }\  }	}
}}}}d|dz    d|	j                          d}d	|
j                          d
|j                          d|j                          d|j                          g}d|j                          }|| ddj                  |      z   dz   |z   dz   z  }|d   j                  |	j                         |
j                         |j                         |j                         |j                         g|j                         d        t        ||d   |       t        dt        |       d| d|        y)zHExtract MCQ questions from the content and save them as a separate file.zfQuestion\s*\d+:\s*(.*?)\nA\.\s*(.*?)\nB\.\s*(.*?)\nC\.\s*(.*?)\nD\.\s*(.*?)\nCorrect Answer:\s*([A-D])z-[WARN] No MCQ questions found in the content.N)r   mcq_questionsr   r   rt   z. zA. zB. zC. zD. zCorrect Answer: rq   rp   rh  )questionoptionsansweru   ✅ Extracted and saved z MCQ questions for module 'z' to )r   rQ  rO  rR  r   rS  r   r   ry   rA   r   create_qti_for_moduler   )rI   r   r   r`  mcq_patternmatchesmodule_datar   iri  option_aoption_boption_coption_dcorrect_answerquestion_textrj  correct_options                     rK   rU  z#CourseCreator.extract_mcq_questions  s    jjuDD244K"--'

 %%g.AB "
 U^_fUg 	QAQ(Hh. 1R(8'9<Mhnn&'(hnn&'(hnn&'(hnn&'(	G  00D0D0F/GHNm_B/$))G2DDtKn\_eeeK(//$NN,$NN,hnn.>@PRZR`R`Rbc(..01 	$ 	e[%A:N(W6QRWQXX]^h]ijkrM   c                 l    t        |dd      5 }|j                  |       ddd       y# 1 sw Y   yxY w)z#Save HTML file with UTF-8 encoding.r   r   r   N)r   r   )rI   rY  r  r   s       rK   rP  zCourseCreator.save_html?  s1    (C'2 	"aGGL!	" 	" 	"s   *3r   r   returnc                     g d}t        j                  ||      }t               j                  d      }|dz  }d| dt         d| d}|S )	z6Convert markdown content to HTML with MathJax support.r   r   r   z
        body, h1, h2, h3, h4, h5, h6, pre, code {
            word-wrap: break-word;
            overflow-wrap: break-word;
            white-space: normal;
        }
        pre, code {
            white-space: pre-wrap;
        }
        r   z</style></head><body>
rq   r   )r   r   r   r  r  )rI   r   r   r   r  r  r  s          rK   rT  zCourseCreator.markdown_to_htmlD  sk     b ))'&A ..}= 	 		""'(?}B|n ]	
 rM   gffffff?r   g      ?c                     |r|st        d      t        j                  j                  j	                  |d|dd|dg|||      }|j
                  d   j                  j                  j                         S )a   Call the OpenAI API with the provided prompts and parameters.
        Args:
            system_prompt (str): The system prompt to guide the model.
            user_prompt (str): The user prompt to provide context.
            temperature (float): The temperature for response variability.
            max_tokens (int): The maximum number of tokens for the response.
        Returns:
            str: The response from the model.
        z.System prompt and user prompt cannot be empty.system)roler   user)modelmessagestemperature
max_tokenstop_pr   )	r^   clientchatcompletionscreatechoicesmessager   ry   )rI   ra   rb   r  r  r  r  rc   s           rK   r_   zCourseCreator.clientCall]  s     KMNN;;**11!m<K8 $! 2 	
 "**2288::rM   )N)d   )__name__
__module____qualname__rL   rP   rd   ri   r   r   r   r   r   r   r   r   r   r   r   r   r.  rI  r7  rU  rP  strrT  r   r_   r   rM   rK   r   r   )   s    ? Bl
@bH!!H$F
PObh
T*XOOb'lR"
S 3 3 2 @Ct[^fw ;rM   r   )!r?   openair   r   r9  
weasyprintr   r'  pygments.formattersr   dependencies.helperdotenvr   PyPDF2r   r	   ior
   reportlab.pdfgenr   reportlab.lib.colorsr   reportlab.lib.pagesizesr   getenvr  r   r   r   r6  r2  r  r   r   rM   rK   <module>r     s    	      - !  '  # & * 				"23	4ryy2BII1=A 		/:6 K; K;rM   