o
    iƪ                     @   s  d Z ddlZddlZddlmZmZmZmZ ddlm	Z	m
Z
mZmZmZ ddlmZ ddlmZmZ zddlmZmZmZmZmZmZmZmZmZmZ W n3 ey   ddlZej !ej "ej #e$ ddlmZmZmZmZmZmZmZmZmZmZ Y nw ej%ej&dd	 e'd
Z(G dd deZ)G dd deZ*G dd deZ+G dd deZ,G dd deZ-G dd deZ.G dd deZ/G dd deZ0G dd deZ1G dd deZ2G dd  d eZ3G d!d" d"eZ4G d#d$ d$eZ5G d%d& d&eZ6G d'd( d(eZ7G d)d* d*eZ8G d+d, d,eZ9G d-d. d.eZ:G d/d0 d0eZ;G d1d2 d2eZ<G d3d4 d4eZ=G d5d6 d6eZ>G d7d8 d8eZ?G d9d: d:eZ@G d;d< d<eZAG d=d> d>eZBe	d?d@e dAdBdCZCeCjDedDgdEdDgdDgdF eCjEdGe@dHdIdJdKidJdLidJdMidJdNidOdPgdQedRdSdTdUfdVe4dWedXeFfdYdZZGdXeFd[eHfd\d]ZIeCjJd^d_d`dJdaidJdbidJdcidddegdfedRdSdTdUfdXeFfdgdhZKeCjJdidjdegdkedRdSdlfdXeFfdmdnZLeCjJdodpdegdkedRdSdledRdqdrfdXeFdseMfdtduZNeCjJdvdwdegdkedRdSdledRdxdrfdXeFdyeMfdzd{ZOeCjJd|eBd}d~dJdidJdiddegdQedRdSdTdUfdXeFfddZPeCjJddddgddd ZQeCjRddddJdidJdidJdiddgdfedRdSdTdUfdXeFfddZSeCjJddddgddd ZTdEddddSdddddddddddddddddddddSdddddddddSdddddddddSdddddddddddddddddddddddddddSddddddddddddg	ddǜZUdEddddddddd˜ddd˜ddd˜gdddddќdҜddddSdSddd˜ddSd˜ddSd˜gdddddќdҜgdd؜ZVdEddddddddddEdddSddݜddddddddddddSddݜgdddZWi ddEddddۓddddƓddddddȓddɓddȓddɓddddddddddddddddddddEdddddddddddddddߐd ddddEdEddddddߐddddgdg ddddd	dEd
d
dddddddߐdddddEdEddddddߐddddddߐddddgdg di ddddddddddEddddddddddd dd!dd"dEdEd#dddddߐd$d%ddddߐd&d'ddddߐd(dddgd)dd*dd+g gd,gZXdS (-  u   
Assessment Report Analysis — FastAPI Layer
===========================================

Enterprise-grade HTTP API for the LMS Assessment Skill Intelligence feature.
Provides a two-phase workflow:

  Phase 1 — TRAIN:  POST /train/{client_id}
      Accepts the organisation's data, queues background LLM analysis,
      and persists the results isolated per client.

  Phase 2 — REPORT: GET /report/{client_id}
      Retrieves the pre-computed analysis for a specific client instantly.

All data is client-isolated — no cross-contamination between organisations.

Architecture:
  PHP Controller  →  THIS FastAPI FILE  →  Processor  →  Ollama LLM
                                                ↕
                                       Client Data Store
    N)AnyDictListOptional)FastAPIHTTPExceptionPathstatusBackgroundTasks)CORSMiddleware)	BaseModelField)
start_training_metarun_training_pipelineget_training_statusget_analysis_resultlist_all_clientsdelete_client_datacheck_ollama_healthTrainingStatusOLLAMA_MODELOLLAMA_BASE_URLz4%(asctime)s | %(levelname)s | %(name)s | %(message)s)levelformatassessment_report_apic                   @   s   e Zd ZU edddZeed< edddZeed< edddd	d
Ze	ed< edddZ
ee ed< edddZe	ed< edddZe	ed< edddZee ed< edddZee ed< edddZee ed< G dd dZdS )QuestionBankItem.z%Unique encrypted question identifier.descriptionidz)Full question content (may contain HTML).questionText      u   Question format type (1–11).)geler   questionType zAnswer rationale/explanation.explanationz Difficulty/cognitive load score.
complexityzMaximum marks.markszCorrect answer value.correctAnswerzComma-separated answer options.questionOptionz8Category/module name of the question for classification.categoryNamec                   @      e Zd ZdZdS )zQuestionBankItem.ConfigignoreN__name__
__module____qualname__extra r3   r3   s/var/www/eduai.edurigo.com/assessment_competency_evaluation/production/assessment_competency_evaluation_fast_api.pyConfigY       r5   N)r/   r0   r1   r   r   str__annotations__r   r$   intr&   r   r'   r(   r)   r*   r+   r5   r3   r3   r3   r4   r   O   s   
 r   c                   @   d   e Zd ZU edZeed< edZeed< edZ	e
e ed< edZee ed< G dd dZdS )	QuestionBankPayload.r	   messagedataNTotalQuestionc                   @   r,   )zQuestionBankPayload.Configr-   Nr.   r3   r3   r3   r4   r5   b   r6   r5   )r/   r0   r1   r   r	   boolr8   r<   r7   r=   r   r   r>   r   r9   r5   r3   r3   r3   r4   r;   ]      
 r;   c                   @   s<   e Zd ZU edZeed< edZeed< G dd dZ	dS )UserAssignDataItem.namevaluec                   @   r,   )zUserAssignDataItem.Configr-   Nr.   r3   r3   r3   r4   r5   k   r6   r5   N)
r/   r0   r1   r   rB   r7   r8   rC   r9   r5   r3   r3   r3   r4   rA   h   s   
 rA   c                   @   s\   e Zd ZU edZeed< edZeed< edZe	ed< edZ
e	ed< G dd dZdS )	LearningData.learningAccuracyTotalRightlearningAccuracyTotalWronglearningAccuracyRightPerlearningAccuracyWrongPerc                   @   r,   )zLearningData.Configr-   Nr.   r3   r3   r3   r4   r5   t   r6   r5   N)r/   r0   r1   r   rE   r9   r8   rF   rG   floatrH   r5   r3   r3   r3   r4   rD   o   s   
 rD   c                   @   s   e Zd ZU edZeed< edZeed< edZ	eed< edZ
eed< edZeed< edZee ed< edZeed< G d	d
 d
ZdS )AssessmentSummaryItem.r   rB   enrolled	completed
notStarteduserAssignDatalearningDatac                   @   r,   )zAssessmentSummaryItem.Configr-   Nr.   r3   r3   r3   r4   r5      r6   r5   N)r/   r0   r1   r   r   r9   r8   rB   r7   rK   rL   rM   rN   r   rA   rO   rD   r5   r3   r3   r3   r4   rJ   x   s   
 rJ   c                   @   r:   )	AssessmentSummaryPayload.r	   r<   r=   NassessmentCountc                   @   r,   )zAssessmentSummaryPayload.Configr-   Nr.   r3   r3   r3   r4   r5      r6   r5   )r/   r0   r1   r   r	   r?   r8   r<   r7   r=   r   rJ   rQ   r   r9   r5   r3   r3   r3   r4   rP      r@   rP   c                   @   s@  e Zd ZU edZeed< edZeed< edZeed< edZ	e
e ed< eddd	Ze
e ed
< eddd	Ze
e ed< edZe
e ed< edZeed< edZeed< edZeed< edddZe
e ed< edZe
e ed< edZe
e ed< eddd	Ze
e ed< edZe
e ed< G dd dZdS )CompletedUserRecord.r   assessmentIduserIdr%   userNameN&Manager ID for hierarchical reporting.r   	managerId"Manager name for display purposes.managerNamequizName
totalMarksobtainedMarkstotalObtPercentagepass)aliaspass_attemptNumberr   	isSectionz0Submission mode (may be string or int from PHP).isSubmitTypegradec                   @   s   e Zd ZdZdZdS )zCompletedUserRecord.Configr-   TN)r/   r0   r1   r2   populate_by_namer3   r3   r3   r4   r5      s    r5   )r/   r0   r1   r   r   r9   r8   rS   rT   rU   r   r7   rW   rY   rZ   r[   r\   r]   rI   r`   r?   ra   r   rb   rc   rd   r5   r3   r3   r3   r4   rR      s"   
 rR   c                   @   sx   e Zd ZU edZeed< edZeed< edZ	e
e ed< edZee ed< edZee ed< G dd	 d	ZdS )
CompletedUsersPayload.r	   r<   r=   NassessmentNamerQ   c                   @   r,   )zCompletedUsersPayload.Configr-   Nr.   r3   r3   r3   r4   r5      r6   r5   )r/   r0   r1   r   r	   r?   r8   r<   r7   r=   r   rR   rg   r   rQ   r9   r5   r3   r3   r3   r4   rf      s   
 rf   c                   @   sp   e Zd ZU edZeed< edZeed< edZe	ed< edZ
eed< edZee ed< G dd	 d	Zd
S )QuestionOption.correct_answer_optionuser_answer	option_idquestion_optionr%   question_option_imagec                   @   r,   )zQuestionOption.Configr-   Nr.   r3   r3   r3   r4   r5      r6   r5   N)r/   r0   r1   r   ri   r?   r8   rj   rk   r9   rl   r7   rm   r   r5   r3   r3   r3   r4   rh      s   
 rh   c                   @   sL  e Zd ZU edZeed< edZeed< edZ	eed< edZ
ee ed< edZee ed< edZee ed	< edZee ed
< edZee ed< edZee ed< edZee ed< edZeed< edZeed< edZee ed< edZee ed< edZee ed< eg Zeee  ed< G dd dZdS )AttemptQuestionDetail.question_idquestion_namequestion_typer%   question_explanationTis_attemptedcorrect_answerrj   NquesTyper   isGrade	gradeMarktotal_marksobtained_marksrl   user_question_optionuser_question_option_imagemarks_rangec                   @   r,   )zAttemptQuestionDetail.Configr-   Nr.   r3   r3   r3   r4   r5      r6   r5   )r/   r0   r1   r   ro   r9   r8   rp   r7   rq   rr   r   rs   r?   rt   rj   ru   rv   rw   rI   rx   ry   rl   r   rh   rz   r{   r|   r   r5   r3   r3   r3   r4   rn      s$   
 rn   c                   @   s  e Zd ZU edZee ed< edZee	 ed< edddZ
ee ed< edZee	 ed< edd	dZee ed
< edddZee	 ed< edZee ed< edZee ed< edZee ed< edZee ed< edZee ed< edZee	 ed< edZee ed< edZee	 ed< edZee ed< edZee ed< edZee ed< edZee ed< edZee	 ed< edZee	 ed< edZee ed< edZee ed< edZ ee ed< edZ!e"e# ed < G d!d" d"Z$dS )#UserAttemptDetailPayloadNr	   r<   zUnique user identifier.r   rT   r%   rU   rV   rW   rX   rY   
totalScoreobtainScoreuserPercentagepassingMarksrS   rg   	contentIdrZ   isProctoringisGamificationr   totalTabChangedtotalFaceRemovedquizStartTimequizEndTimequizDurationgalleryDetailIdproctoringConfidence.r=   c                   @   r,   )zUserAttemptDetailPayload.Configr-   Nr.   r3   r3   r3   r4   r5      r6   r5   )%r/   r0   r1   r   r	   r   r?   r8   r<   r7   rT   r9   rU   rW   rY   r~   r   r   rI   r   rS   rg   r   rZ   r   r   r   r   r   r   r   r   r   r=   r   rn   r5   r3   r3   r3   r4   r}      s4   
 r}   c                   @   s   e Zd ZU dZedddZee ed< ee	ddZ
ee ed< ee	d	dZee ed
< edddZee ed< edddZeeeee f  ed< G dd dZdS )TrainRequestz@
    Standardised payload for initiating analysis training.
    .z'Organisation question bank (flat list).r   question_bankz!Assessment catalogue (flat list).default_factoryr   assessment_summaryz+Completed user attempt records (flat list).completed_users_dataz"Granular per-user attempt details.user_attempt_detailsNz3Optional mapping of Manager ID to list of User IDs.manager_mappingc                   @   r,   )zTrainRequest.Configr-   Nr.   r3   r3   r3   r4   r5      r6   r5   )r/   r0   r1   __doc__r   r   r   r   r8   listr   rJ   r   rR   r   r}   r   r   r   r7   r9   r5   r3   r3   r3   r4   r      s   
 $r   c                   @   s   e Zd ZU dZeed< dZeed< dZeed< dZ	e
ed< dZe
ed	< d
Zee
 ed< dZee ed< dZe
ed< G dd dZd
S )QuestionUserAttemptz7Individual user's interaction with a specific question.user_idr%   	user_nameF
is_correctr   ry   rx   Nassessment_idassessment_namer    total_attempts_by_userc                   @   r,   )zQuestionUserAttempt.ConfigallowNr.   r3   r3   r3   r4   r5     r6   r5   )r/   r0   r1   r   r7   r8   r   r   r?   ry   r9   rx   r   r   r   r   r5   r3   r3   r3   r4   r     s   
 r   c                   @   s\   e Zd ZU dZdZeed< dZeed< dZ	e
ed< dZe
ed< d	Zeed
< G dd dZdS )QuestionAssessmentAppearancez/Tracks which assessments a question appears in.Nr   r%   r   r   attempts_in_assessmentcorrect_in_assessment        accuracy_in_assessmentc                   @   r,   )z#QuestionAssessmentAppearance.Configr   Nr.   r3   r3   r3   r4   r5     r6   r5   )r/   r0   r1   r   r   r   r8   r   r7   r   r9   r   r   rI   r5   r3   r3   r3   r4   r     s   
 r   c                   @   s8  e Zd ZU dZeed< dZeed< dZeed< dZeed< d	Z	eed
< dZ
eed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< g Zee ed< g Zee ed< dZeed< dZeed < d!Zeed"< d#Z eed$< G d%d& d&Z!d'S )(QuestionReportuw   
    Professional Question Intelligence Mapping — V3.
    Covers every question in the bank with full analytics.
    ro   r%   question_text_previewUncategorizedcategoryGeneral Knowledgesubject_domainGeneral Reasoningprimary_skillBeginner
skill_tierr   rq   Unknownquestion_format_descriptorcomplexity_score	max_markstotal_attemptscorrect_countwrong_countunattempted_countr   average_accuracy_across_usersaverage_marks_obtained
user_countusers_attemptedassessments_appeared_inzNot Attempteddifficulty_ratingzN/Adiscrimination_indexUnusedr	   unknownclassification_sourcec                   @   r,   )zQuestionReport.Configr   Nr.   r3   r3   r3   r4   r5   9  r6   r5   N)"r/   r0   r1   r   r7   r8   r   r   r   r   r   rq   r9   r   r   r   r   r   r   r   r   rI   r   r   r   r   r   r   r   r   r   r	   r   r5   r3   r3   r3   r4   r     s4   
 r   c                   @   s   e Zd ZU dZdZeed< dZeed< dZeed< i Z	e
eef ed< i Ze
eef ed< i Ze
eef ed< i Ze
eef ed	< i Ze
eef ed
< i Ze
eef ed< i Ze
eef ed< dZeed< dZeed< G dd dZdS )QuestionBankSummaryz5Aggregate statistics across the entire question bank.r   total_questionstotal_activetotal_unusedcategory_distributiondomain_distributionskill_distributionskill_tier_distributiondifficulty_distributionquestion_type_distributionclassification_source_breakdownr   'average_accuracy_of_attempted_questionsaverage_complexityc                   @   r,   )zQuestionBankSummary.Configr   Nr.   r3   r3   r3   r4   r5   M  r6   r5   N)r/   r0   r1   r   r   r9   r8   r   r   r   r   r7   r   r   r   r   r   r   r   rI   r   r5   r3   r3   r3   r4   r   ?  s   
 r   c                   @   s   e Zd ZU dZeed< dZeed< dZeed< dZeed< d	Z	eed
< dZ
eed< dZeed< dZeed< dZeed< dZee ed< dZee ed< dS )UserQuestionDetailz:Per-question detail attached to an individual user report.ro   r%   text_previewr   r   r   domainr   r   r   skill_levelFr   r   ry   rx   Nr   r   )r/   r0   r1   r   r7   r8   r   r   r   r   r   r   r?   ry   r9   rx   r   r   r   r3   r3   r3   r4   r   S  s   
 r   c                   @   sh   e Zd ZU dZdZeed< dZeed< dZeed< dZ	eed< dZ
eed< dZeed	< G d
d dZdS )AdminSummaryzAdmin-level summary counters.r   total_questions_in_banktotal_active_questionstotal_unused_questionstotal_userstotal_assessmentsr   average_accuracyc                   @   r,   )zAdminSummary.Configr   Nr.   r3   r3   r3   r4   r5   l  r6   r5   N)r/   r0   r1   r   r   r9   r8   r   r   r   r   r   rI   r5   r3   r3   r3   r4   r   d  s   
 r   c                   @   sT   e Zd ZU g Zee ed< g Zee ed< g Zee	ee
f  ed< G dd dZdS )SkillInsights
top_skillsweak_skillsskill_accuracy_detailsc                   @   r,   )zSkillInsights.Configr   Nr.   r3   r3   r3   r4   r5   t  r6   r5   N)r/   r0   r1   r   r   r7   r8   r   r   r   r   r5   r3   r3   r3   r4   r   p  s
   
 r   c                   @   s   e Zd ZU dZeed< eed< eedZ	eed< g Z
ee ed< g Zeeeef  ed< g Zeeeef  ed< g Zee ed	< g Zee ed
< g Zee ed< g Zee ed< eeddZeeef ed< G dd dZdS )AdminReportz
    Full admin-level analytics report.
    question_skill_map contains EVERY question in the bank with complete analytics.
    summaryskill_insightsr   question_bank_summaryquestion_skill_mapassessment_healthintegrity_flagskey_insightsactionsbehavior_patternshigh_failure_questionsz1Advanced visualizations data for admin dashboard.r   
chart_datac                   @   r,   )zAdminReport.Configr   Nr.   r3   r3   r3   r4   r5     r6   r5   N)r/   r0   r1   r   r   r8   r   r   r   r   r   r   r   r   r   r7   r   r   r   r   r   r   dictr   r5   r3   r3   r3   r4   r   x  s   
 r   c                   @   s   e Zd ZU eed< dZeed< dZeed< dZe	ed< g Z
ee ed< g Zee ed	< g Zee ed
< i Zeee	f ed< g Zee ed< eeddZeeeef  ed< eeddZeeeef  ed< eeddZeeef ed< G dd dZdS )ManagerReport
manager_idr%   manager_namer   	team_sizer   team_accuracytop_performerslow_performers
skill_gapsskill_accuracyrecommendationszList of team members.r   team_memberszAssessments taken by the team.team_assessments_attemptedz3Advanced visualizations data for manager dashboard.r   c                   @   r,   )zManagerReport.Configr   Nr.   r3   r3   r3   r4   r5     r6   r5   N)r/   r0   r1   r7   r8   r   r   r9   r   rI   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r5   r3   r3   r3   r4   r     s   
   r   c                   @   s  e Zd ZU eed< dZeed< dZeed< dZeed< dZ	eed< g Z
ee ed< g Zee ed	< i Zeeef ed
< dZeed< dZeed< dZeed< g Zee ed< g Zee ed< g Zee ed< dZeed< eeddZeeef ed< G dd dZdS )
UserReportr   r%   r   r   accuracyoverall_score_gaugepercentile_rankstrong_skillsr   skill_accuracy_breakdownr   questions_attemptedquestions_correctquestions_wrongquestion_detailsassessments_attemptedr   Lowactivity_levelz0Advanced visualizations data for user dashboard.r   r   c                   @   r,   )zUserReport.Configr   Nr.   r3   r3   r3   r4   r5     r6   r5   N)r/   r0   r1   r7   r8   r   r   rI   r   r   r   r   r   r   r   r   r9   r   r   r   r   r   r   r  r   r   r   r   r5   r3   r3   r3   r4   r     s$   
 r   c                   @   sr   e Zd ZU eedZeeef e	d< ee
dZeeeef  e	d< ee
dZeeeef  e	d< G dd dZdS )MasterReportr   admin_reportmanager_reportsuser_reportsc                   @   r,   )zMasterReport.Configr   Nr.   r3   r3   r3   r4   r5     r6   r5   N)r/   r0   r1   r   r   r  r   r7   r   r8   r   r  r   r  r5   r3   r3   r3   r4   r    s
   
 r  c                   @   f   e Zd ZU edddZeed< edddZeed< edddZ	e
ed< edd	dZeeef ed
< dS )TrainResponse.zTrue if training was queued.r   r	   Status message.r<   z'The client ID training was started for.	client_idTraining metadata.trainingNr/   r0   r1   r   r	   r?   r8   r<   r7   r	  r9   r  r   r   r3   r3   r3   r4   r    
   
  r  c                   @   s^   e Zd ZU edddZeed< edddZeed< edddZ	e
ed< edd	dZeed
< dS )ReportResponse.zTrue if report is available.r   r	   r  r<   The client ID.r	  z Full analysis JSON from the LLM.resultN)r/   r0   r1   r   r	   r?   r8   r<   r7   r	  r9   r  r  r3   r3   r3   r4   r    s
   
 r  c                   @   r  )StatusResponse.zTrue if client exists.r   r	   r  r<   r  r	  r
  r  Nr  r3   r3   r3   r4   r    r  r  Assessment Report Analysis APIzn## LMS Assessment Skill Intelligence API

Enterprise-grade, client-isolated assessment analytics powered by **u  ** (Ollama).

### Two-Phase Workflow

| Phase | Endpoint | Method | Purpose |
|-------|----------|--------|---------|
| **Train** | `/train/{client_id}` | POST | Accepts data, queues background analysis, stores results |
| **Report** | `/report/{client_id}` | GET | Retrieves stored analysis instantly |

### Client Isolation
Every organisation (client) has its own isolated data store. Data from client `12345` is **never** mixed with client `67890`. Client IDs are integers (any digit length).

### Additional Endpoints
- `GET /report/status/{client_id}` — Check training progress
- `GET /clients` — List all trained clients
- `DELETE /client/{client_id}` — Remove a client's data
- `GET /health` — System health check2.0.0)titler   version*T)allow_originsallow_credentialsallow_methodsallow_headersz/train/{client_id}u.   Phase 1 — Train: Analyse & store client datau]  Accepts the organisation's complete question bank, assessment summary, completed user records, and individual attempt details.

**The analysis runs in the background** — this endpoint returns immediately with a `queued` status. Poll `/report/status/{client_id}` to check progress.

Once training completes, results are stored persistently and can be retrieved via `GET /report/{client_id}` at any time.

**Client isolation**: Each `client_id` has its own dedicated storage. Re-training a client overwrites its previous results.

**Concurrent safety**: Only one training job per client can run at a time.r   zTraining queued successfully.z-Training already in progress for this client.z$Validation error in request payload.zInternal server error.)     i  i  Training)response_modelr   r   	responsestags.r    z&Unique integer client/organisation ID.)r"   r   payloadbackground_tasksr	  c           	         sN  t d| dt| j dt| j dt| j dt| j 
 zAdd | jD }dd | jD }d	d | jD }d
d | jD }t|||||| jd}|	dt
jkra|t|||||| j W n5 tyw } z	ttjt|dd}~w ty } zt d| d|  ttjd| dd}~ww tdd| d| d||dS )z
    Accepts all four data inputs, validates them, and starts background training.
    Returns immediately with queued status.
    zPOST /train/z | questions=z | assessments=z | completed_attempts=z | attempt_details=c                 S      g | ]}|j d dqS F)by_alias
model_dump).0qr3   r3   r4   
<listcomp>%      z train_client.<locals>.<listcomp>c                 S   r#  r$  r&  )r(  ar3   r3   r4   r*  &  r+  c                 S   r#  r$  r&  r(  cr3   r3   r4   r*  '  r+  c                 S   r#  r$  r&  )r(  dr3   r3   r4   r*  (  r+  )r	  r   r   r   r   r   r	   status_codedetailNz$Failed to start training for client : zFailed to start training: TzTraining queued for client z. Poll GET /report/status/z to check progress.r	   r<   r	  r  )loggerinfolenr   r   r   r   r   r   getr   QUEUEDadd_taskr   RuntimeErrorr   r	   HTTP_409_CONFLICTr7   	Exception	exceptionHTTP_500_INTERNAL_SERVER_ERRORr  )	r!  r"  r	  q_banka_sumc_usersu_atttraining_metaexcr3   r3   r4   train_client  sj    	rF  returnc              	      s   t | }|du rttjd|  d|  dd|d}|tjkr,ttjd|  dd|tjkr<ttjd	|  dd|tj	krVttj
d
|  d|dd d|  ddt| }|du rittj
d|  dd|S )zAHelper to fetch and validate training status, returning raw dict.NNo data found for client z%. Please train first via POST /train/.r0  r	   zTraining is queued for client z. Please wait.z)Training is still in progress for client zTraining failed for client z	. Error: errorr   z". Please re-train via POST /train/z+Analysis result file is missing for client z. Please re-train.)r   r   r	   HTTP_404_NOT_FOUNDr8  r   r9  HTTP_202_ACCEPTED
PROCESSINGFAILEDr?  r   )r	  metacurrent_statusr  r3   r3   r4   _fetch_raw_resultT  sH   








rQ  z/report/{client_id}u,   Phase 2 — Report: Retrieve stored analysisuv  Returns the pre-computed analysis for a specific client.

**Prerequisites**: The client must have completed training via `POST /train/{client_id}` first.

The response contains the full structured JSON analysis including:
- Question → Skill mapping with Bloom's Taxonomy
- Organisational skill intelligence
- Assessment health reports
- Integrity flags
- Executive summaryz Analysis retrieved successfully.z+Client not found or training not completed.zTraining still in progress.)r       Report)r   r   r  r   c                    sB   t d|   t| I dH }|di }dd|  d| |dS )zRReturns the saved analysis result for a specific client, optimized for Admin view.zGET /report/Nr  TzAnalysis report for client z retrieved successfully.r	   r<   r	  r  )r5  r6  rQ  r8  )r	  r  
admin_datar3   r3   r4   
get_report  s   
rW  z/report/admin/{client_id}z#Admin Report: System-level insights)r   r   )r"   c                    s   t | I dH S )z(Convenience alias for the master report.N)rW  )r	  r3   r3   r4   get_admin_report  s   rX  z(/report/manager/{client_id}/{manager_id}z#Manager Report: Team-level insightszID of the manager.r   r   c                    h   t | I dH }|dg }t fdd|D d}|s)tdd  d|  dd	d
d  d| |dS )z;Returns the manager's team report from the master analysis.Nr  c                 3   *    | ]}t |d t  kr|V  qdS )r   Nr7   r8  )r(  mr   r3   r4   	<genexpr>     ( z%get_manager_report.<locals>.<genexpr>rR  zManager " not found in analysis for client rI  r0  TzManager report for  retrieved.rU  rQ  r8  nextr   )r	  r   r  r  manager_datar3   r]  r4   get_manager_report     

re  z"/report/user/{client_id}/{user_id}z User Report: Individual insightszID of the user.r   c                    rY  )z<Returns the individual user report from the master analysis.Nr  c                 3   rZ  )r   Nr[  )r(  ur   r3   r4   r^    r_  z"get_user_report.<locals>.<genexpr>rR  zUser r`  rI  r0  TzUser report for ra  rU  rb  )r	  r   r  r  	user_datar3   rh  r4   get_user_report  rf  rj  z/report/status/{client_id}zCheck training statusu   Returns the current training status for a client.

**Possible statuses:**
- `queued` — Training is scheduled
- `processing` — LLM analysis is running
- `completed` — Analysis is done and available
- `failed` — Training encountered an errorzStatus retrieved.zClient not found.)r  rR  c                    sL   t | }|du rttjd|  ddtdd|  d|d d| |d	S )
z;Returns the training status metadata for a specific client.NrH  rI  r0  TzStatus for client r3  r	   r4  )r   r   r	   rK  r  r8  )r	  rO  r3   r3   r4   check_status  s   
rk  z/clientszList all trained clientszReturns a list of all clients that have training data stored, with their current status and metadata. Useful for admin dashboards and bulk status checks.
Management)r   r   r   c                     s$   t  } dt|  dt| | dS )z%Lists all clients with training data.Tz client(s) found.)r	   r<   total_clientsclients)r   r7  )rn  r3   r3   r4   list_clients"  s   ro  z/client/{client_id}zDelete client datazPermanently removes all stored data for a specific client, including analysis results, input snapshots, and metadata.

**Cannot delete while training is in progress.**zClient data deleted.u'   Training in progress — cannot delete.)r  rR  r  c              
      sx   t d|   zt| }W n ty$ } z	ttjt|dd}~ww |s2ttjd|  dddd|  d| d	S )
z%Deletes all stored data for a client.zDELETE /client/r0  NrH  rI  TzAll data for client z has been permanently deleted.)r	   r<   r	  )	r5  r6  r   r;  r   r	   r<  r7   rK  )r	  deletedrE  r3   r3   r4   delete_client;  s(   

rq  z/healthzSystem health checkz@Returns API status, Ollama connectivity, and model availability.Systemc                     sd   t  } t }tdd |D }tdd |D }tdd |D }dddt||||dd	| S )
u;   Liveness probe — verifies API and Ollama are operational.c                 s   $    | ]}| d tjkrdV  qdS r	   r    N)r8  r   	COMPLETEDr-  r3   r3   r4   r^  v     " zhealth_check.<locals>.<genexpr>c                 s   rs  rt  )r8  r   rM  r-  r3   r3   r4   r^  w  rv  c                 s   rs  rt  )r8  r   rN  r-  r3   r3   r4   r^  x  rv  okr  r  )totalrL   
processingfailed)r	   apir  client_stats)r   r   sumr7  )ollama_healthrn  rL   ry  rz  r3   r3   r4   health_checkj  s"   	
r  zRecords availableey_q1z0Write a review for assign Storigo in your words!r%         )r   r   r$   r&   r'   r(   r)   r*   ey_q2zUnder education loan scheme as per RBI norms for secured loan from Nationalised Banks, what type of mortgage is done by bank for overseas loan ?   zZConventional mortgages,Equity Mortgage,Jumbo mortgages,Registered mortgage,Simple Mortgageey_q3z2Make addition Checkbox;(Make addition : 2 + 2 = ?)   FOURzFOUR,ONE,THREE,TWOey_q4z8Make addition Drop down text (Make addition : 2 + 2 = ?)   ey_q5zis this correct = 1+1=2   TruezTrue, Falseey_q6zBelow some pronouns are given that can be used with Have or Has. Move the pronouns that are used with have to the left and pronouns used with has to the right.   zI have only 100 rupees today.0   zHe,I,It,She,They,We,Youey_q7z@Match the sentence on the left to its correct type on the right.    zland,air,water,spacezcar,plane,ship,rocketey_q8zSort Alphabet
   z	A,B,C,D,Ez	A,E,C,D,Bey_q9zSProfessionals _______ teachers and lawyers should have ______ communication skills.r!   zsuch as, goodzas,bad,good,such as,such like	   )r	   r<   r=   r>   i  zAssesment on quiz attemptEnrolled)rB   rC   	CompletedzNot Started   gGzNP@gp=
cA@)rE   rF   rG   rH   )r   rB   rK   rL   rM   rN   rO   i  zAssesment Classic   gGz4@g{GS@)r	   r<   r=   rQ   Z   i\  z
Hari Singhd   )r   rS   rT   rU   rZ   r[   r\   r]   r^   ra   rb   rc   rd   Y   F)r	   r<   r=   rg   rQ   r	   r<   rU   r~      r   r   K   r   2   rS   rg   r   rZ   r   r   r   r   r   z30-05-2023 10:13:10r   z30-05-2023 10:13:32   i-  z,Make subtraction of Two Number : 20 - 35 = ?z.Make subtraction of Two Number : 20 - 35 = -15209482iQ  15)ri   rj   rk   rl   rm   iQ  z-20iQ  z-15iQ  35)ro   rp   rq   rr   rs   rt   rj   ru   rv   rw   rx   ry   rl   rz   r|   i,  z)Make Addition Of two Number : 10 + 21 = ?z*Make Addition Of two Number : 10 + 21 = 3120943iQ  20iQ  31iQ  25iQ  33ro   i   rp   z%<p>Number Addition &nbsp;:- 10 +5</p>rq   rr   rs   rt   20922rj   ru   rv   rw   rx   ry   rl   iQ  iQ  10iQ  5iQ  rz   r{   r|   )r   r   r   r=   )Yr   osloggingtypingr   r   r   r   fastapir   r   r   r	   r
   fastapi.middleware.corsr   pydanticr   r   $assessment_report_analysis_processorr   r   r   r   r   r   r   r   r   r   ImportErrorsyspathappenddirnameabspath__file__basicConfigINFO	getLoggerr5  r   r;   rA   rD   rJ   rP   rR   rf   rh   rn   r}   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  appadd_middlewarepostr9   rF  r   rQ  r8  rW  rX  r7   re  rj  rk  ro  deleterq  r  TEST_QUESTION_BANKTEST_ASSESSMENT_SUMMARYTEST_COMPLETED_USERSTEST_USER_ATTEMPT_DETAILSr3   r3   r3   r4   <module>   s   44
		
!%A0





 



"j