
    /h2X                        d Z 	 ddlmZ n# e$ r	 ddlmZ Y nw xY wddlmZ ddlZddlm	Z	m
Z
 ddlmZmZmZmZ ddlm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 ddl m!Z! ddl"m#Z# ddl$m%Z%m&Z& dZ'dZ(dZ)dZ*dZ+e' ed          fe( ed          fe) ed          fe* ed          fe+ ed          ffZ,e' ed          fe( ed          fe) ed          fe* ed          fe+ ed          ffZ-d  ed!          fd" ed#          fd$ ed%          fd& ed'          fd( ed)          fd* ed+          fd, ed-          fd. ed/          fd0 ed1          fg	Z.d2 Z/d3 Z0 G d4 d5ej1                  Z2 G d6 d7ej1                  Z3 G d8 d9ej1                  Z4 G d: d;ej1                  Z5 G d< d=ej1                  Z6 G d> d?ej1                  Z7dS )@zDatabase models.    )available_timezones)	timedeltaN)current_app	schedules)FormatExceptionMissingFieldExceptionWrongArgumentExceptionget_description)settings)MultipleObjectsReturnedValidationError)MaxValueValidatorMinValueValidator)models)gettext_lazy   )	querysets
validators)clocked)TzAwareCrontab
make_awarenowdayshoursminutessecondsmicrosecondsDaysHoursMinutesSecondsMicrosecondsDayHourMinuteSecondMicroseconddawn_astronomicalzAstronomical dawn
dawn_civilz
Civil dawndawn_nauticalzNautical dawndusk_astronomicalzAstronomical dusk
dusk_civilz
Civil duskdusk_nauticalzNautical dusk
solar_noonz
Solar noonsunriseSunrisesunsetSunsetc                 P    | r#t          |                               dd          pdS )z"Representation of cron expression.  *)strreplace)fields    ]/var/www/html/e360mart/e360mart_env/lib/python3.11/site-packages/django_celery_beat/models.pycronexpr<   ;   s(    0SZZ''R007C7    c                      	 t          t          dt          j        z            } n# t          $ r Y dS w xY w| t                      v r| S dS )zReturn timezone string from Django settings ``CELERY_TIMEZONE`` variable.

    If is not defined or is not a valid timezone, return ``"UTC"`` instead.
    z%s_TIMEZONEUTC)getattrr   r   	namespaceAttributeErrorr   )CELERY_TIMEZONEs    r;    crontab_schedule_celery_timezonerD   @   sd    
!mk&;;= =   uu-////5s   "% 
33c            
          e Zd ZdZ ej        de ed           ed                    Z ej	        dd ed           ed	           e
d
           ed          g          Z ej	        dd ed           ed           e
d           ed          g          Z G d d          Zed             Zed             Zd ZdS )SolarSchedulezSchedule following astronomical patterns.

    Example: to run every sunrise in New York City:

    >>> event='sunrise', latitude=40.7128, longitude=74.0060
       zSolar Eventz/The type of solar event when the job should run
max_lengthchoicesverbose_name	help_text	      Latitudez4Run the task when the event happens at this latitudeiZ   )
max_digitsdecimal_placesrK   rL   r   	Longitudez5Run the task when the event happens at this longitudeiL   c                   F    e Zd ZdZ ed          Z ed          ZdZdZdS )SolarSchedule.MetaTable information.zsolar eventzsolar eventseventlatitude	longitudeN)	__name__
__module____qualname____doc___rK   verbose_name_pluralorderingunique_together r=   r;   MetarV   i   s=          q''a//5<r=   re   c                 R    t          j        | j        | j        | j        d           S )Nc                  8    t          t                                S Nr   rd   r=   r;   <lambda>z(SolarSchedule.schedule.<locals>.<lambda>v   s    j.?.? r=   nowfun)r   solarrY   rZ   r[   selfs    r;   schedulezSolarSchedule.scheduleq   s3    tz#}#~&?&?A A A 	Ar=   c                     |j         |j        |j        d}	  | j        j        di |S # | j        $ r  | di |cY S w xY w)NrX   rd   )rY   latlonobjectsgetDoesNotExistclsro   specs      r;   from_schedulezSolarSchedule.from_schedulex   sr    !$L%\+ +	"3;?**T*** 	 	 	3;;;;	s   ) >>c                 h    d                     |                                 | j        | j                  S )Nz{} ({}, {}))formatget_event_displayrZ   r[   rm   s    r;   __str__zSolarSchedule.__str__   s3    ##""$$MN
 
 	
r=   N)r\   r]   r^   r_   r   	CharFieldSOLAR_SCHEDULESr`   rY   DecimalFieldr   r   rZ   r[   re   propertyro   classmethodry   r}   rd   r=   r;   rF   rF   O   sy         FQ}%%!EFF  E
 #v"QQz]]!JKK%%c**,=,=b,A,AB	  H $#QQ{^^!KLL%%d++->->s-C-CD	  I= = = = = = = = A A XA 
 
 [

 
 
 
 
r=   rF   c                   <   e Zd ZdZeZeZeZeZeZe	Z	 e
j        d ed           ed           ed          g          Z e
j        de	 ed           ed	          
          Z G d d          Zed             Zeefd            Zd Zed             ZdS )IntervalSchedulezpSchedule executing on a regular interval.

    Example: execute every 2 days:

    >>> every=2, period=DAYS
    FzNumber of Periodsz@Number of interval periods to wait before running the task againr   )nullrK   rL   r   rG   zInterval Periodz4The type of period between task runs (Example: days)rH   c                   F    e Zd ZdZ ed          Z ed          ZddgZdS )IntervalSchedule.MetarW   interval	intervalsperiodeveryNr\   r]   r^   r_   r`   rK   ra   rb   rd   r=   r;   re   r      s9          q}}anng&r=   re   c                 \    t          j        t          di | j        | j        id           S )Nc                  8    t          t                                S rh   r   rd   r=   r;   ri   z+IntervalSchedule.schedule.<locals>.<lambda>   s    :cee,, r=   rj   rd   )r   ro   r   r   r   rm   s    r;   ro   zIntervalSchedule.schedule   s<    !22dj122,,
 
 
 	
r=   c                 6   t          |j                                        d          }	 | j                            ||          S # | j        $ r  | ||          cY S t          $ r1 | j                            ||                                          cY S w xY w)Nr   )r   r   )	max	run_everytotal_secondsrs   rt   ru   r   filterfirst)rw   ro   r   r   s       r;   ry   zIntervalSchedule.from_schedule   s    H&4466::	J;??v?>>> 	3 	3 	33U6222222& 	J 	J 	J;%%E&%AAGGIIIII	Js   A B7BBc                 h   d }| j         dk    rPt          D ]&\  }}|| j        k    r|                                } n't	          d                              |          S t          D ]&\  }}|| j        k    r|                                } n't	          d                              | j         |          S )Nr   zevery {}zevery {} {})r   SINGULAR_PERIODSr   lowerr`   r{   PERIOD_CHOICES)rn   readable_periodr   _readable_periods       r;   r}   zIntervalSchedule.__str__   s    :??,<  ((T[((&6&<&<&>&>OE ) Z==''888(6 	 	$F$$$"2"8"8":": % &&tz?CCCr=   c                      | j         d d         S )N)r   rm   s    r;   period_singularz IntervalSchedule.period_singular   s    {3B3r=   N)r\   r]   r^   r_   DAYSHOURSMINUTESSECONDSMICROSECONDSr   r   IntegerFieldr`   r   r   r~   r   re   r   ro   r   ry   r}   r   rd   r=   r;   r   r      s`         DEGGL#NFQ*++! - . .%%a(()  E V~Q())!JKK  F' ' ' ' ' ' ' ' 
 
 X
 ,3 J J J [JD D D     X     r=   r   c                       e Zd ZdZ ej         ed           ed                    Z G d d          Zd Z	e
d             Zed	             Zd
S )ClockedSchedulezclocked schedule.z
Clock TimezRun the task at clocked time)rK   rL   c                   D    e Zd ZdZ ed          Z ed          ZdgZdS )ClockedSchedule.MetarW   r   clocked_timeNr   rd   r=   r;   re   r      s7          q||a	ll"#r=   re   c                 ,    t          | j                   S rh   )r   r   rm   s    r;   r}   zClockedSchedule.__str__   s    T.//11r=   c                 0    t          | j                  }|S )N)r   )r   r   )rn   cs     r;   ro   zClockedSchedule.schedule   s    !2333r=   c                     d|j         i}	  | j        j        di |S # | j        $ r  | di |cY S t          $ r'  | j        j        di |                                cY S w xY w)Nr   rd   )r   rs   rt   ru   r   r   r   rv   s      r;   ry   zClockedSchedule.from_schedule   s     56	6"3;?**T*** 	 	 	3;;;;& 	6 	6 	6%3;%----3355555	6s    A!-A! A!N)r\   r]   r^   r_   r   DateTimeFieldr`   r   re   r}   r   ro   r   ry   rd   r=   r;   r   r      s        '6'Q|__!233  L
$ $ $ $ $ $ $ $2 2 2   X 6 6 [6 6 6r=   r   c                      e Zd ZdZ ej        dd ed           ed          ej        g          Z	 ej        dd ed           ed	          ej
        g          Z ej        d
d ed           ed          ej        g          Z ej        dd ed           ed          ej        g          Z ej        dd ed           ed          ej        g          Z ej        ed ed           ed                    Z G d d          Zed             Zd Zed             Zed             Zd ZdS )CrontabSchedulezTimezone Aware Crontab-like schedule.

    Example:  Run every hour at 0 minutes for days of month 10-15:

    >>> minute="0", hour="*", day_of_week="*",
    ... day_of_month="10-15", month_of_year="*"
       r7   z	Minute(s)z9Cron Minutes to Run. Use "*" for "all". (Example: "0,30"))rI   defaultrK   rL   r   `   zHour(s)z7Cron Hours to Run. Use "*" for "all". (Example: "8,20")|   zDay(s) Of The MonthzCCron Days Of The Month to Run. Use "*" for "all". (Example: "1,15")@   zMonth(s) Of The YearzKCron Months (1-12) Of The Year to Run. Use "*" for "all". (Example: "1,12")zDay(s) Of The Weekz`Cron Days Of The Week to Run. Use "*" for "all", Sunday is 0 or 7, Monday is 1. (Example: "0,5")FzCron Timezonez5Timezone to Run the Cron Schedule on. Default is UTC.)r   use_pytzrK   rL   c                   F    e Zd ZdZ ed          Z ed          Zg dZdS )CrontabSchedule.MetarW   crontabcrontabs)month_of_yearday_of_monthday_of_weekhourminutetimezoneNr   rd   r=   r;   re   r   6  sC          q||a
mmA A Ar=   re   c                     	 t          j        | j        | j        | j        | j        | j                  }|j        r5t          |j                  t          t          d                    k    rd}n:t          d
                    t          t          |j                                      }n$# t          $ r t          | j                  }Y nw xY wd                    t          | j                  t          | j                  t          | j                  t          | j                  |          }	 t          |          }n6# t           t"          t$          f$ r | dt          | j                   cY S w xY w| dt          | j                   S )Nr   r   r   r   r      r7   ,z{} {} {} {} {}r5   )r   r   r   r   r   r   r   setranger<   joinmapr8   
ValueErrorr{   r
   r   r   r	   r   )rn   r   r   cron_expressionhuman_readables        r;   r   zCrontabSchedule.human_readable>  s   	4!{Y ,!."0  A } IQ]!3!3s588}}!D!D!%chhs3/F/F&G&GHH 	4 	4 	4!$"233KKK	4 +11DK  '$)"4"4D%&&0B(C(C
 

	=,_==NN!"
 	= 	= 	=
 &<<DM(:(:<<<<<	= !773t}#5#5777s$   B(B+ +CC1E 0E43E4c           
         d                     t          | j                  t          | j                  t          | j                  t          | j                  t          | j                  t          | j                            S )Nz{} {} {} {} {} (m/h/dM/MY/d) {})	r{   r<   r   r   r   r   r   r8   r   rm   s    r;   r}   zCrontabSchedule.__str__^  sh    077DK  '$)"4"4D%&&0B(C(CD$%%s4='9'9
 
 	
r=   c                     t          j        | j        | j        | j        | j        | j                  }t          t          dd          r3t          | j        | j        | j        | j        | j        | j
                  }|S )Nr   DJANGO_CELERY_BEAT_TZ_AWARET)r   r   r   r   r   tz)r   r   r   r   r   r   r   r@   r   r   r   )rn   r   s     r;   ro   zCrontabSchedule.schedulee  s    #;(*,
 
 
 8:DAA 	${Y ,!."0=  G r=   c                    |j         |j        |j        |j        |j        |j        d}	  | j        j        di |S # | j        $ r  | di |cY S t          $ r'  | j        j
        di |                                cY S w xY w)N)r   r   r   r   r   r   rd   )_orig_minute
_orig_hour_orig_day_of_week_orig_day_of_month_orig_month_of_yearr   rs   rt   ru   r   r   r   rv   s      r;   ry   zCrontabSchedule.from_scheduley  s    "/ +'9 ( ;!)!=$K 	6"3;?**T*** 	 	 	3;;;;& 	6 	6 	6%3;%----3355555	6s   ; A?-A?>A?c                 r    |                     |          }| j                            |          \  }}}||z   S rh   )
astimezonero   remaining_delta)rn   initial_start_timer   
start_timestartends_inr   s          r;   due_start_timezCrontabSchedule.due_start_time  s;    '22266
"m;;JGGwwr=   N)r\   r]   r^   r_   r   r~   r`   r   minute_validatorr   hour_validatorr   day_of_month_validatorr   month_of_year_validatorr   day_of_week_validatorr   timezone_fieldTimeZoneFieldrD   r   re   r   r   r}   ro   r   ry   r   rd   r=   r;   r   r      sv         V3Q{^^!GI I/0  F 63Qy\\!EG G-.  D $6#3Q,--! ! ! 56  L %F$sQ-..! ! ! 67  M #&"sQ+,,!78 8 45  K ,~+0Q''!CE E	  HA A A A A A A A 8 8 X8>
 
 
   X& 6 6 [6    r=   r   c                       e Zd ZdZ ej        ddd          Z ej        d          Z G d d          Z	e
d	             Ze
d
             Ze
d             ZdS )PeriodicTasksaQ  Helper table for tracking updates to periodic tasks.

    This stores a single row with ``ident=1``. ``last_update`` is updated via
    signals whenever anything changes in the :class:`~.PeriodicTask` model.
    Basically this acts like a DB data audit trigger.
    Doing this so we also track deletions, and not just insert/update.
    r   T)r   primary_keyuniqueF)r   c                   :    e Zd Z ed          Z ed          ZdS )PeriodicTasks.Metazperiodic task trackzperiodic task tracksN)r\   r]   r^   r`   rK   ra   rd   r=   r;   re   r     s1        q.//a 677r=   re   c                 @    |j         s|                                  d S d S rh   )
no_changesupdate_changed)rw   instancekwargss      r;   changedzPeriodicTasks.changed  s/    " 	!     	! 	!r=   c                 Z    | j                             ddt                      i           d S )Nr   last_update)identdefaults)rs   update_or_creater   )rw   r   s     r;   r   zPeriodicTasks.update_changed  s,    $$1suu7M$NNNNNr=   c                 f    	 | j                             d          j        S # | j        $ r Y d S w xY w)Nr   )r   )rs   rt   r   ru   )rw   s    r;   last_changezPeriodicTasks.last_change  sE    	;???++77 	 	 	DD	s   " 
00N)r\   r]   r^   r_   r   SmallIntegerFieldr   r   r   re   r   r   r   r   rd   r=   r;   r   r     s          %F$QDNNNE&&&E222K8 8 8 8 8 8 8 8 ! ! [! O O [O   [  r=   r   c                       e Zd ZdZ ej        dd ed           ed                    Z ej        dd ed          	          Z ej	        e
ej        dd ed
           ed                    Z ej	        eej        dd ed           ed                    Z ej	        eej        dd ed           ed                    Z ej	        eej        dd ed           ed                    Z ej        dd ed           ed                    Z ej        dd ed           ed                    Z ej        dddd ed           ed                    Z ej        dddd ed           ed                    Z ej        dddd ed            ed!                    Z ej        dd ed"           ed#                    Z ej        d ed$          gdd ed%           ed&          '          Z ej        dd ed(           ed)          *          Z ej        dd ed+           ed,          *          Z ej         d- ed.           ed/          0          Z! ej        dd ed1           ed2          *          Z" ej         d ed3           ed4          0          Z# ej        d-d-d-dd ed5           ed6          7          Z$ ej        d8d- ed9           ed:          ;          Z% ej        d ed<           ed=          >          Z& ej        d ed?           ed@          A          Z'e(j)        *                                Z+d-Z, G dB dC          Z- fdDZ. fdEZ/ fdFZ0dG Z1e2dH             Z3dI Z4e2dJ             Z5e2dK             Z6dL Z7 xZ8S )MPeriodicTaskz#Model representing a periodic task.   TNamezShort Description For This Task)rI   r   rK   rL   z	Task NamezXThe Name of the Celery Task that Should be Run.  (Example: "proj.tasks.import_contacts"))rI   rK   rL   zInterval SchedulezYInterval Schedule to run the task on.  Set only one schedule type, leave the others null.)	on_deleter   blankrK   rL   zCrontab SchedulezXCrontab Schedule to run the task on.  Set only one schedule type, leave the others null.zSolar SchedulezVSolar Schedule to run the task on.  Set only one schedule type, leave the others null.zClocked SchedulezXClocked Schedule to run the task on.  Set only one schedule type, leave the others null.z[]zPositional Argumentsz=JSON encoded positional arguments (Example: ["arg1", "arg2"]))r   r   rK   rL   z{}zKeyword Argumentsz?JSON encoded keyword arguments (Example: {"argument": "value"})NzQueue OverridezDQueue defined in CELERY_TASK_QUEUES. Leave None for default queuing.)rI   r   r   r   rK   rL   Exchangez,Override Exchange for low-level AMQP routingzRouting Keyz/Override Routing Key for low-level AMQP routingzAMQP Message Headersz2JSON encoded message headers for the AMQP message.   PriorityzcPriority Number between 0 and 255. Supported by: RabbitMQ, Redis (priority reversed, 0 is highest).)r   r   r   r   rK   rL   zExpires DatetimezHDatetime after which the schedule will no longer trigger the task to run)r   r   rK   rL   zExpires timedelta with secondszPTimedelta with seconds which the schedule will no longer trigger the task to runFzOne-off Taskz:If True, the schedule will only run the task a single time)r   rK   rL   zStart DatetimezBDatetime when the schedule should begin triggering the task to runEnabledz$Set to False to disable the schedulezLast Run DatetimezdDatetime that the schedule last triggered the task to run. Reset to None if enabled is set to False.)auto_nowauto_now_addeditabler   r   rK   rL   r   zTotal Run CountzCRunning count of how many times the schedule has triggered the task)r   r  rK   rL   zLast Modifiedz1Datetime that this PeriodicTask was last modified)r  rK   rL   Descriptionz<Detailed description about the details of this Periodic Task)r   rK   rL   c                   >    e Zd ZdZ ed          Z ed          ZdS )PeriodicTask.MetarW   zperiodic taskzperiodic tasksN)r\   r]   r^   r_   r`   rK   ra   rd   r=   r;   re   r  K  s6          q))a 011r=   re   c                 H     t                      j        |i | g d} fd|D             }t          |          dk    rt          d          d}t          |          dk    ri }|D ]}|g||<   	t          |           j        r j        sd}t          |          d S d S )Nr   r   rl   r   c                 4    g | ]}t          |          |S rd   )r@   ).0srn   s     r;   
<listcomp>z0PeriodicTask.validate_unique.<locals>.<listcomp>U  s7     #8 #8 #8&-dA&6&6#81 #8 #8 #8r=   r   z8One of clocked, interval, crontab, or solar must be set.z<Only one of clocked, interval, crontab, or solar must be setr   z.clocked must be one off, one_off must set True)supervalidate_uniquelenr   r   one_off)	rn   argsr   schedule_typesselected_schedule_typeserr_msg
error_infoselected_schedule_type	__class__s	   `       r;   r  zPeriodicTask.validate_uniqueQ  s
   0000DDD#8 #8 #8 #8n #8 #8 #8 &''1,,!  
#&''!++J*A ? ?&6=Y
122!*--- < 	+ 	+FG!'***	+ 	+ 	+ 	+r=   c                 J   | j         pd | _         | j        pd | _        | j        pd | _        | j        pd | _        | j        sd | _        |                                  |                                   t                      j	        |i | t                              |            d S rh   )exchangerouting_keyqueueheadersenabledlast_run_at_clean_expiresr  r  saver   r   rn   r  r   r  s      r;   r!  zPeriodicTask.savek  s    -+3tZ'4
|+t| 	$#Dd%f%%%d#####r=   c                 n     t                      j        |i | t                              |            d S rh   )r  deleter   r   r"  s      r;   r$  zPeriodicTask.deletew  s8    ''''d#####r=   c                 ^    | j         #| j        rt          t          d                    d S d S )Nz2Only one can be set, in expires and expire_seconds)expire_secondsexpiresr   r`   rm   s    r;   r   zPeriodicTask._clean_expires{  s>    *t|*!FGG   +***r=   c                     | j         p| j        S rh   )r'  r&  rm   s    r;   expires_zPeriodicTask.expires_  s    |2t22r=   c                 x    d}| j         rd}| j        rd}| j        rd}| j        rd}|                    |           S )Nz{0.name}: {{no schedule}}z{0.name}: {0.interval}z{0.name}: {0.crontab}z{0.name}: {0.solar}z{0.name}: {0.clocked})r   r   rl   r   r{   )rn   fmts     r;   r}   zPeriodicTask.__str__  sU    )= 	+*C< 	*)C: 	('C< 	*)Czz$r=   c                 v    | j         r| j         S | j        r| j        S | j        r| j        S | j        r| j        S d S rh   r	  rm   s    r;   	schedulerzPeriodicTask.scheduler  sT    = 	!= < 	 <: 	:< 	 <	  	 r=   c                     | j         j        S rh   )r-  ro   rm   s    r;   ro   zPeriodicTask.schedule  s    ~&&r=   c                 ^    | j         r | j                             | j        |          S | j        S rh   )r   r   r   )rn   r   s     r;   r   zPeriodicTask.due_start_time  s.    < 	#<..tCCC?"r=   )9r\   r]   r^   r_   r   r~   r`   nametask
ForeignKeyr   CASCADEr   r   r   rF   rl   r   r   	TextFieldr  r   r  r  r  r  PositiveIntegerFieldr   priorityr   r'  r&  BooleanFieldr  r   r  r  total_run_countdate_changeddescriptionr   PeriodicTaskQuerySet
as_managerrs   r   re   r  r!  r$  r   r   r)  r}   r-  ro   r   __classcell__)r  s   @r;   r   r     s       --6tQvYY!566  D
 6 ! > ? ?  D !v FNAA.A,B,B! I J J  H  f6>DQ)**! I J J  G Fd$Q'((! I J J  E  f6>DQ)**! I J J  G 6DQ-..!*+ +  D VDQ*++!/0 0  F FdtQ'((!./ /  E  vdtQz]]!BCC  H
 #&"dtQ}%%!EFF  K
 fDQ-..!HII  G +v*"3"3C"8"8!9Qz]]!OP P	  H #f"Q)**!&' '  G 1V0Q788!&' '  N "f!Q~&&!HJ J  G &%Q'((!)* *  J "f!Qy\\!:;;  G
 '&&UdQ*++!89 9	  K 2f1EQ())!%& &  O (6'Q''!GHH  L
 #&"Q}%%!JL L  K ,7799GJ2 2 2 2 2 2 2 2+ + + + +4
$ 
$ 
$ 
$ 
$$ $ $ $ $   3 3 X3
  
  
      X  ' ' X'# # # # # # #r=   r   )8r_   zoneinfor   ImportErrorbackports.zoneinfodatetimer   r   celeryr   r   cron_descriptorr   r   r	   r
   django.confr   django.core.exceptionsr   r   django.core.validatorsr   r   	django.dbr   django.utils.translationr   r`   r6   r   r   clockedscheduler   	tzcrontabr   utilsr   r   r   r   r   r   r   r   r   r   r<   rD   ModelrF   r   r   r   r   r   rd   r=   r;   <module>rM     sT    7,,,,,,, 7 7 7666666667           ) ) ) ) ) ) ) )F F F F F F F F F F F F             K K K K K K K K G G G G G G G G       6 6 6 6 6 6 # # # # # # # # $ $ $ $ $ $ % % % % % % " " " " " " " "

 
11V99
AAgJJaa	llaa	ll11^$$% 
11U88
AAfIIaakkaakk11]##$  !!/00111\??#aa(()!!/00111\??#aa(()11\??#)qq{{
8 8 8
  ;
 ;
 ;
 ;
 ;
FL ;
 ;
 ;
|E  E  E  E  E v| E  E  E P6 6 6 6 6fl 6 6 6DU U U U Ufl U U Up    FL   Bt# t# t# t# t#6< t# t# t# t# t#s    