
    ˿i:                        d dl Z d dlZd dlZd dlZd dlmZmZ d dlmZm	Z	 d dl
mZ d dlmZ d dlmZmZ i ddd	d
dddddddddddddddddddddd d!d"d#d$d%d&d'd(i d)d*d+d,d-d.d/d0d1d2d3d4d5d6d7d8d9d:d;d<d=d>d?d@dAdBdCdDdEdFdGdHdIdJZej$                  j'                  ej$                  j)                  e            Zej$                  j)                  ej$                  j/                  edKdKdK            Zej$                  j/                  edL      Zej$                  j/                  edMdN      Z ej6                  edOP        e       Zej;                  dQ      dRefdS       Z e edT      U      ZdVe dWe fdXZ!dYe dWe fdZZ"dVe dWe fd[Z#dVe dWe fd\Z$d] Z%ejM                  d^d_      d`e'fda       Z(ejM                  db      dc        Z)y)d    N)	APIRouterHTTPException)FileResponseJSONResponse)VesselFilter)VesselService)EnvironmentFileSystemLoaderzsire-chapter-03-crew-managementz	MSSV-2000z-sire-chapter-04-navigation-and-communicationsz	MSSV-2050z!sire-chapter-05-safety-managementz	MSSV-2100z$sire-chapter-06-pollution-preventionz	MSSV-2150z!sire-chapter-07-maritime-securityz	MSSV-2175z7sire-chapter-8-1-8-3-cargo-and-ballast-system-petroleumz	MSSV-2200z6sire-chapter-8-2-8-3-cargo-and-ballast-system-chemicalz	MSSV-2225z9sire-chapter-8-4-8-5-8-6-cargo-and-ballast-system-lpg-lngz	MSSV-2250z%sire-chapter-09-mooring-and-anchoringz	MSSV-2300z9sire-chapter-10-machinery-space-engine-and-steering-spacez	MSSV-2400z1sire-chapter-11-general-appearance-and-conditionsz	MSSV-2325zsire-chapter-12-icez	MSSV-2350zsire-value-added-coursesz	MSSV-2500dry-bulk-navigation	DBMV-2000dry-bulk-cargo	DBMV-3000dry-bulk-safety	DBMV-4000dry-bulk-care-for-persons	DBMV-5000dry-bulk-engineering	DBMV-6000dry-bulk-management	DBMV-8000zdeepsea-navigationz	MSVE-1000z9deepsea-engineering-and-control-systems-for-deck-officersz	MSVE-1050zdeepsea-cargo-handlingz	MSVE-1100z0deepsea-safety-of-operation-and-care-for-personsz	MSVE-1200zdeepsea-soft-skillsz	MSVE-1300zdeepsea-marine-engineeringz	MSVE-1400
navigationzMSTS-200z1engineering-and-control-systems-for-deck-officerszMSTS-250zcargo-handlingzMSTS-300z(safety-of-operation-and-care-for-personsMSTS-400zsoft-skillszMSTS-500zmarine-engineeringzMSTS-600z*electrical-electronics-control-engineeringzMSTS-700zmanagement-functionszMSTS-800zasp-internal-courseszASP-2500z..filesASTAPI_STRUCTUREOffline_ContentTexist_okz'/courses/roles-functional-areas-coursesfiltersc                 4    t               j                  |       S )N)r   &get_roles_functional_areas_and_courses)r   s    3/var/www/html/beaconod-api/app/api/vessel/router.pyr    r    :   s    ?AA'JJ    	templates)loadernamereturnc                     | j                         j                         } t        j                  dd|       } | j                  d      } | S )z
    Sanitize functional area name to create a valid HTML file name.
    Lowercase, replace spaces with '-', remove all special characters.
    
[^a-z0-9]+-striplowerresubr%   s    r!   sanitize_filenamer0   @   s<    
 ::<D66-d+D::c?DKr"   functional_areac                     t        |       dz   }t        j                  j                  t        j                  j	                  dd|            }d|j                  t        j                  d       S )zO
    Generate a file:/// URL for the local HTML file of a functional area.
    .htmr   z*ASTAPI_STRUCTURE/Offline_Content/eLearningfile:////)r0   ospathabspathjoinreplacesep)r1   filenamer7   s      r!   generate_file_urlr=   J   sU     !1F:H77??277<<1]_ghiDdll2663/011r"   c                     | j                         j                         } t        j                  dd|       } | j                  d      } | S )z
    Convert role name into safe flat filename part:
    - Replace spaces with '-'
    - Replace '/' with '-'
    - Keep letters, numbers, '-', '&'
    - Lowercase
    r(   r)   r*   r/   s    r!   sanitize_pathr?   R   s<     ::<D66-d+D::c?DKr"   c                     | j                         j                         } t        j                  dd|       } | j                  d      S )Nr(   r)   r*   r/   s    r!   normalize_keyrA   _   s6    ::<D66-d+D::c?r"   c                    g }| xs g D ]  }t        |t              rSd|v r|j                  d|d   i       .d|v r|j                  d|d   i       I|j                  dt        |      i       f|j                  dt        |      i        |S )z~
    Standardize course list for both roles and functional areas.
    Supports input as list of strings OR list of dicts.
    
lms_course
courseName)
isinstancedictappendstr)courses
normalizedcs      r!   normalize_coursesrL   e   s    
 J]]aq !!<<"AB"!!<<"AB !!<Q"89 |SV45  r"   z-/courses/vessel/{vessel_id}/generate-all-html)response_model	vessel_idc                    t               }|j                  t        |             }|j                  d      dk7  rt	        d|j                  dd            |d   } |j                  d	i       }t
        }t        j                  |d
       t        j                  |      D ]j  }t        j                  j                  ||      }t        j                  j                  |      sC|j                         dv sVt        j                  |       l i }|j                         D ]  \  }}	|j                         dk(  rdn3d|j                         v rdn|j!                  dd      j                         }
t        j                  j                  ||
      }t        j                  |d
       |	j                  d      xs i }|	j                  d      xs i }i }|j                         D ]4  \  }}|j#                         D ci c]  }|dt%        |       d c}||<   6 t        j                  j                  |d      }t        j                  j                  |d      }t&        j)                  d      j+                  |      }t&        j)                  d      j+                  t-        |j#                                     }||f||ffD ]-  \  }}	t/        |dd      5 }|j1                  |	       ddd       / i }i }|j                         D ]  \  }}|j                         D ]  \  }}t%        |      j                         }| d}t        j                  j                  ||      }t3        |t,              st5        d | d!| d"t7        |              st8        j                  |d#      }|d$k(  rd%d&d'd(d)d*d+} | j                  |d,      }n+|d-k(  r&t5        |       d.d/d0d1d2d3d+}!|!j                  |d4      }|D ]E  }"t3        |"t:              r!t=        |"j                  d5d6            }#|||#<   4|"}$t=        |$      }#|||#<   G t&        j)                  d7      j+                  ||t?        |      8      }%t/        |dd      5 }|j1                  |%       ddd       t/        |d9d      5 }|jA                         }&ddd       &j!                  d:d;      j!                  d<d=      j!                  d>d?      j!                  d@dA      }&t        j                  j                  ||      }'t        j                  |'d
       t        j                  j                  |'d      }(t/        |(dd      5 }|j1                  |&       ddd       dBt        j                  jC                  |      j!                  t        jD                  dC       ||<     i })|j                         D ]  \  }*}dDtG        |*       d}t        j                  j                  ||      }t?        |      }+|+D ]  }"t=        |"j                  d5d6            }# t&        j)                  dE      j+                  |*||+D "cg c]3  }"i |"dF|j                  t=        |"j                  d5d6            dG      i5 c}"H      }%t/        |dd      5 }|j1                  |%       ddd        dBt        j                  jC                  |      j!                  t        jD                  dC       dBt        j                  jC                  |      j!                  t        jD                  dC       |)|dI||<   dJ},t        j                  j                  |d      }-tI        dK |j#                         D              }.tI        dL |j#                         D              }/t&        j)                  |,      j+                  |.|/M      }0t/        |-dd      5 }|j1                  |0       ddd        tK        ddN|  | t-        |j#                               |dO      S c c}w # 1 sw Y   xxY w# 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y   xY wc c}"w # 1 sw Y   xY w# 1 sw Y   axY w)Pz
    Generate HTML files for all roles and functional areas for a vessel,
    replacing old content within Offline_Content directory.
    )vesselIdstatus1  messagezData not foundstatus_codedetailrP   dataTr   >   	elearningvideo-seriesrY   videorZ    _rolesfunctional_areasz./r3   z	start.htmzrole.htmzstart_template.html)category_functional_areaszrole_template.html)r^   wzutf-8)encodingNz$ Skipping invalid courses data for 'z' in 'z': r   zDry Bulk E-learning CourseszDBMS-200zDBMS-300zDBMS-400zDBMS-500zDBMS-600zDBMS-800)r   r   r   r   r   r   zDBMS-999zDry Bulk Video Series Coursesr   r   r   r   r   r   z	DBMV-9999rC    zfunctional_area_template.html)r1   prefixrI   rz	href="../zhref="../../zsrc="../zsrc="../../zwindow.location.replace(`zwindow.location.replace(`../zhref="start.htm"zhref="../start.htm"r4   r5   zrole-zrole_series_template.htmlrd   zNo-Prefix-found)roleseriesrI   )startrf   
role_filesfunctional_area_fileszhome_template.htmlc              3   @   K   | ]  }d |j                         v   yw)rY   Nr,   .0keys     r!   	<genexpr>z/generate_all_html_for_vessel.<locals>.<genexpr>A  s     \E[c{ciik9E[   c              3   @   K   | ]  }d |j                         v   yw)r[   Nrl   rm   s     r!   rp   z/generate_all_html_for_vessel.<locals>.<genexpr>B  s     T=Sc7ciik1=Srq   )elearning_existsvideo_existsz3All HTML files generated successfully for vesselId )rQ   rT   rP   series_generatedr   )&r   r    r   getr   OFFLINE_CONTENT_DIRr6   makedirslistdirr7   r9   isdirr,   shutilrmtreeitemsr:   keysr0   r#   get_templaterenderlistopenwriterE   printtypeFUNCTIONAL_AREA_PREFIX_MAPrF   rA   rL   readr8   r;   r?   anyr   )1rN   serviceresponserX   base_dirfolderfolder_pathgenerated_filesseries_namecontentfolder_name
output_dir
roles_dictfunctional_areas_dictr`   category_name
func_areasfunc_area_name
start_file	role_file
start_html	role_htmlr7   frj   prefix_lookup	area_namerI   sanitized_area	file_name	file_pathrd   dry_bulk_prefix_mapdry_bulk_video_prefix_mapcoursero   key_parthtmlhtml_content
prefix_dirprefix_start_fileri   	role_namenormalized_courseshome_templatehome_output_pathrs   rt   	home_htmls1                                                    r!   generate_all_html_for_vesselr   |   s    oG==lT]>^_H||H$HLLL\4]^^$I<<#D"HKK4( **X&ggll8V477==%&,,.<Y*YMM+& '
 O !%

W&,,.+=K#*k.?.?.A#A$$S#.446 	
 WW\\(K8

J.[[)/R
 ',> ? E2$&!)>)D)D)F%M: '1oo&78&7N "%6~%F$Gt LL&78%m4 *G WW\\*k:
GGLLZ8	++,ABII&? J 

 **+?@GGz() H 
	  *:6I8NOMD'dC'2a  32 P
 !#)>)D)D)F%M:&0&6&6&8"	7!29!=!C!C!E-.d3	GGLLY?	!'40@6R_Q``cdhipdqcrst377
S !$AA 0:*4+55?0:/9+' 144^ZPF"&EE.)/:*5+65@0;/:1- 7::>;WF%F!&$/+FJJ|R,HI-3c*
 $*+H5-3c* & !--.MNUU$-!-g6 V  )S7;qGGDM < )S7;q#$668L <
 !W[.9WZ7W8:XYW/1FG   WW\\*f=
J6 %'GGLL[$I!+S7CqGGL) D 6>bggooi>X>`>`acagagil>m=n3o%i0k '9 *Gx 
","2"2"4Iwi 89>IZ;I!27!; -#FJJ|R$@A - ))*EFMM" #5
 #5  -"3"3)&**\2*FG-# #5
 N D  iw71 875 #5<  
 ; C CBFFC PQRrwwy9AA"&&#NOP$%:	(
$ -77<<+>\_EYEYE[\\T_=Q=Q=STT **=9@@-% A 
	
 "C':aGGI ;:g !-j HT !5!5!78   O8  32| <; <;& DC4
 87. ;:sT   :`+`0:`=	"a
	"a	8a$+a)#a60`:=a
aa!)a36b 	z!/courses/offline-content/downloadc                  4   t         j                  j                  t              st	        dd      t
        j
                  j                         j                  d      } d|  }t         j                  j                  t        |      }| d}	 t        j                  |dt               t        t         j                  j                  |      t         j                  j                  |      d	      S # t        $ r}t	        d
dt!        |             d}~ww xY w)zP
    Compress the Offline_Content folder into a zip and return as download.
    rS   z Offline_Content folder not foundrU   z%Y%m%d_%H%M%SOffline_Content_z.zipzipzapplication/zip)r7   r<   
media_typei  zError creating ZIP: N)r6   r7   existsrw   r   datetimenowstrftimer9   FILES_BASE_DIRr{   make_archiver   r8   basename	ExceptionrH   )	timestampzip_namezip_basezip_pathes        r!   download_offline_contentr   V  s    
 77>>-.4VWW!!%%'00AI!)-Hww||NH5H4 HUHe-@A*WW%%h/(
 	

  U6J3q6(4STTUs   A"C0 0	D9DD)*r   r6   r-   r{   fastapir   r   fastapi.responsesr   r   app.api.vessel.schemasr   app.api.vessel.servicer   jinja2r	   r
   r   r7   dirnamer8   __file__CURRENT_DIRr9   PROJECT_ROOTr   rw   rx   vessel_routerpostr    r#   rH   r0   r=   r?   rA   rL   rv   intr   r    r"   r!   <module>r      s2    	 	  , 8 / 0 0$%{$3[$ ($ +K	$
 ($ >{$ =k$ @$ ,[$ @$ 8$ ;$ $ ;$ k$  {!$"  #$$ K%$& ;'$( +)$* @+$, k-$. 7/$0 ;1$2 !+3$6 *7$8 89$: j;$< /
=$> :?$@ *A$B 1*C$D JE$F JG$ L ggoobggooh78wwrww||KtTJKlG4ggll>3EGXY  $ /=>KL K ?K /<=	C C 2s 2s 2    . BSWXVC V YVr 67U 8Ur"   