
    ĞiP                         d dl Z d dlZd dlZd dlZd dlZd dl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mZmZmZmZmZmZmZmZmZmZmZ ddlmZ  G d d          Z dS )    N   )BreaklineStatusPrinterMultilineLoggerMultilinePrinterQuietMultilinePrinter)IDENTITY
NO_DEFAULTLockingUnsupportedError	NamespaceRetryManagerclasspropertydeprecation_warningformat_bytesjoin_nonemptyparse_bytesremove_startsanitize_openshell_quotetimeconverttimetuple_from_msectry_call)_ProgressStatec            	          e Zd ZdZdZdZd Zd Zd ZeZ	e
d             Zed             Zed	             Zed
             Zed             Zeeefd            Zed             Zed             Zed             Zed             Zed             Zed             Zd Zd Zd Zd ZdddZ edd          d             Z ed          d             Z  ed          d              Z!d! Z"d" Z#d9d$Z$d% Z% e&d&d&d'd(d)d*d*+          Z'd, Z(d- Z)d. Z*d/ Z+edfd0Z,d1 Z-ed2             Z.d:d3Z/d4 Z0d5 Z1d6 Z2d;d7Z3d8 Z4dS )<FileDownloadera 	  File Downloader class.

    File downloader objects are the ones responsible of downloading the
    actual video file and writing it to disk.

    File downloaders accept a lot of parameters. In order not to saturate
    the object constructor with arguments, it receives a dictionary of
    options instead.

    Available options:

    verbose:            Print additional info to stdout.
    quiet:              Do not print messages to stdout.
    ratelimit:          Download speed limit, in bytes/sec.
    throttledratelimit: Assume the download is being throttled below this speed (bytes/sec)
    retries:            Number of times to retry for expected network errors.
                        Default is 0 for API, but 10 for CLI
    file_access_retries:   Number of times to retry on file access error (default: 3)
    buffersize:         Size of download buffer in bytes.
    noresizebuffer:     Do not automatically resize the download buffer.
    continuedl:         Try to continue downloads if possible.
    noprogress:         Do not print the progress bar.
    nopart:             Do not use temporary .part files.
    updatetime:         Use the Last-modified header to set output file timestamps.
    test:               Download only first bytes to test the downloader.
    min_filesize:       Skip files smaller than this size
    max_filesize:       Skip files larger than this size
    progress_delta:     The minimum time between progress output, in seconds
    external_downloader_args:  A dictionary of downloader keys (in lower case)
                        and a list of additional command-line arguments for the
                        executable. Use 'default' as the name for arguments to be
                        passed to all downloaders. For compatibility with youtube-dl,
                        a single list of args can also be used
    hls_use_mpegts:     Use the mpegts container for HLS videos.
    http_chunk_size:    Size of a chunk for chunk-based HTTP downloading. May be
                        useful for bypassing bandwidth throttling imposed by
                        a webserver (experimental)
    progress_template:  See YoutubeDL.py
    retry_sleep_functions: See YoutubeDL.py

    Subclasses of this one must re-define the real_download method.
    i(  Nc                 @   |                      |           g | _        || _        |                                  |                     | j                   | j                            d          r2t          j                    | _	        t          j                    | _        dS dS )z6Create a FileDownloader object with the given options.progress_deltaN)_set_ydl_progress_hooksparams_prepare_multiline_statusadd_progress_hookreport_progressget	threadingLock_progress_delta_locktime	monotonic_progress_delta_time)selfydlr   s      ]C:\Users\betacode\Desktop\descargarYoutube\venv\Lib\site-packages\yt_dlp/downloader/common.py__init__zFileDownloader.__init__T   s    c!&&(((t3444;??+,, 	9(1(8(8D%(,(8(8D%%%	9 	9    c           	      |    || _         dD ]1}t          | |          st          | |t          ||                     2d S )N)	r   deprecated_featurereport_errorreport_file_already_downloadedreport_warningto_console_title	to_stderrtroublewrite_debug)r+   hasattrsetattrgetattr)r*   r+   funcs      r,   r   zFileDownloader._set_ydl_   sU    

 	8 	8D 4&& 8dGC$6$6777	8 	8r.   c                 ^     | j         j        |d| j                            d          i| d S )Nquiet)r+   	to_screenr   r#   )r*   argskargss      r,   r>   zFileDownloader.to_screenp   s5    DJ(@(@JEJJJJJr.   c                 l    t          j        dd| j        d d                                                   S )Nz(?<=[a-z])(?=[A-Z])_)resub__name__lower)clss    r,   FD_NAMEzFileDownloader.FD_NAMEu   s.    v,c3<3DEEKKMMMr.   c                 b    | dS t          | dz            }|j        dk    rdS d|d d         z  S )Nz Unknowni  c   z--:--:--z%02d:%02d:%02d)r   hours)secondsr'   s     r,   format_secondszFileDownloader.format_secondsy   s@    ?:"7T>22:??:$ss)++r.   c                 L    t          |                     |          d          dS )Nz00:z>8s)r   rO   )rH   rN   s     r,   
format_etazFileDownloader.format_eta   s&    s11'::EBBHHHr.   c                 N    |d S t          |           t          |          z  dz  S )N      Y@float)byte_counterdata_lens     r,   calc_percentzFileDownloader.calc_percent   s+    4\""U8__4u<<r.   c                     | dn| ddS )Nz  N/A%z>5.1f% )percents    r,   format_percentzFileDownloader.format_percent   s    "?xx70C0C0C0CCr.   c                 4   |t           u r+||}}d ||fv rd S t          t          |          |z            S ||}}|d S |t          j                    }|                     |||          }|o.t          t          |          t          |          z
  |z            S N)r	   intrU   r'   
calc_speed)	rH   start_or_ratenow_or_remainingtotalcurrentrate	remainingstartnows	            r,   calc_etazFileDownloader.calc_eta   s    J+-=)Di(((tuY''$.///"$4s=4;)++C~~eS'22CU5\\E'NN:dBCCCr.   c                 L    || z
  }|dk    s|dk     rd S t          |          |z  S )Nr   MbP?rT   )rh   ri   bytesdifs       r,   ra   zFileDownloader.calc_speed   s2    EkA::u4U||c!!r.   c                 0    | dnt          |           ddS )Nz Unknown B/s>10sz/s)r   )speeds    r,   format_speedzFileDownloader.format_speed   s$    !&~~|E7J7J4S4S4S4SSr.   c                 J    | t          d          k    rdnt          |           S )Ninf)rU   r`   )retriess    r,   format_retrieszFileDownloader.format_retries   s"    5<<//uuS\\Ar.   c                     t           j                            |           rt           j                            |           S dS )Nr   )ospathisfilegetsize)unencoded_filenames    r,   filesize_or_nonezFileDownloader.filesize_or_none   s3    7>>,-- 	77??#5666qr.   c                    t          |dz  d          }t          t          |dz  d          d          }| dk     rt          |          S || z  }||k    rt          |          S ||k     rt          |          S t          |          S )Ng       @g      ?i  @ rl   )maxminr`   )elapsed_timerm   new_minnew_maxrf   s        r,   best_block_sizezFileDownloader.best_block_size   s    eck3''c%#+s++W55%w<<|#'>>w<<'>>w<<4yyr.   c                 >    t          d           t          |           S )z:Parse a string indicating a byte quantity into an integer.zvyt_dlp.FileDownloader.parse_bytes is deprecated and may be removed in the future. Use yt_dlp.utils.parse_bytes instead)r   r   )bytestrs    r,   r   zFileDownloader.parse_bytes   s-     	 a 	b 	b 	b7###r.   c                 (   | j                             d          }||dk    rdS |t          j                    }||z
  }|dk    rdS t          |          |z  }||k    r1t          |          |z  |z
  }|dk    rt          j        |           dS dS dS )z3Sleep if the download speed is over the rate limit.	ratelimitNr   g        )r   r#   r'   rU   sleep)r*   
start_timeri   rV   
rate_limitelapsedrq   
sleep_times           r,   	slow_downzFileDownloader.slow_down   s    [__[11
!2!2F;)++C
"c>>Fl##g-:|,,z9GCJA~~
:&&&&& ~r.   c                     | j                             dd          sD|dk    s>t          j                            |          r!t          j                            |          s|S |dz   S )z4Returns a temporary filename for the given filename.nopartF-.part)r   r#   rx   ry   existsrz   r*   filenames     r,   	temp_namezFileDownloader.temp_name   s^    ;??8U++ 	x3)) 0?24'..2J2J 0?O'!!r.   c                 `    |                     d          r|d t          d                    S |S )Nr   )endswithlenr   s     r,   undo_temp_namezFileDownloader.undo_temp_name   s4    W%% 	,Nc'll]N++r.   c                     |dz   S )Nz.ytdlr[   r   s     r,   ytdl_filenamezFileDownloader.ytdl_filename   s    '!!r.   F)fatalc                \      fdfd}t          j        t           j        |          S )Nc                    t          j        | ||j        fdrd nfdj                            di                               d                    S )Nc                 b    t          j        d                              d d|            fS )Ng{Gz?z[download] Unable to  file: )r'   r   r>   eactionfds    r,   <lambda>zIFileDownloader.wrap_file_access.<locals>.error_callback.<locals>.<lambda>   s5    
4 0 0",,?iW]?i?ifg?i?i2j2jk r.   c                 :                         d d|            S )Nz
Unable to r   r1   r   s    r,   r   zIFileDownloader.wrap_file_access.<locals>.error_callback.<locals>.<lambda>   s&    2??CbPVCbCb_`CbCb3c3c r.   retry_sleep_functionsfile_access)infowarnerror
sleep_func)r   report_retry_FileDownloader__to_screenr   r#   )errcountru   r   r   r   s      `r,   error_callbackz7FileDownloader.wrap_file_access.<locals>.error_callback   sw    ,UG".kkkkk#cdd)c)c)c)c)c9==)@"EEII-XX	Z Z Z Zr.   c                 2   t          | j                            dd          |           D ]i}	  || g|R i |c S # t          $ rL}|j        t          j        t          j        fv r||_        Y d }~F|                    |dd           Y d }~bd }~ww xY wd S )Nfile_access_retries   )r      r   )	r   r   r#   OSErrorerrnoEACCESEINVALr   r   )r*   r;   r?   kwargsretryr   r   s         r,   wrapperz0FileDownloader.wrap_file_access.<locals>.wrapper   s    %dkoo6KQ&O&OQ_dhiii 4 4446t666v66666 4 4 4yU\5<$@@@&) ((a33333333	44 4s   >
B&B3BB)	functoolspartialpartialmethod)r   r   r   r   s   `` @r,   wrap_file_accesszFileDownloader.wrap_file_access   sZ    	Z 	Z 	Z 	Z 	Z 	Z	4 	4 	4 	4 	4  !8'BBBr.   openTc                     t          ||          \  }}t          |dd           s$|                     t          j         dd           ||fS )Nlockedz. Proceeding without lockingT)	only_once)r   r:   r7   r
   msg)r*   r   	open_modefs       r,   r   zFileDownloader.sanitize_open   s[    #Hi888q(D)) 	k 7 ;YYYeijjj({r.   removec                 p    t           j                            |          rt          j        |           d S d S r_   )rx   ry   rz   r   r   s     r,   
try_removezFileDownloader.try_remove  s8    7>>(## 	 Ih	  	 r.   renamec                 @    ||k    rd S t          j        ||           d S r_   )rx   replace)r*   old_filenamenew_filenames      r,   
try_renamezFileDownloader.try_rename  s*    <''F

<.....r.   c                 D   |dS t           j                            |          sdS |}|dS t          |          }||S |dk    rdS t	          j        t                    5  t          j        |t          j                    |f           ddd           n# 1 swxY w Y   |S )z4Try to set the last-modified time of the given file.Nr   )	rx   ry   rz   r   
contextlibsuppress	Exceptionutimer'   )r*   r   last_modified_hdrtimestrfiletimes        r,   	try_utimezFileDownloader.try_utime  s    $Fw~~h'' 	F#?Fw''Oq==F ++ 	8 	8HX	X6777	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8s    )BBBc                 6    |                      d|z              dS )zReport destination filename.z[download] Destination: Nr>   r   s     r,   report_destinationz!FileDownloader.report_destination!  s     1H<=====r.   r   c                 |   | j                             d          rt                      | _        n| j        j                             d          r&t          | j        j         d         |          | _        n}| j                             d          r%t          | j        j        j        |          | _        n>t          | j        j        j        || j                             d                     | _        | j        j
        j        o| j        j
        j        dk    | j        _        | j        j
        j        | j        _        d S )N
noprogressloggerprogress_with_newliner=   no_color)r   r#   r   
_multiliner+   r   r   
_out_filesoutr   _allow_colorsallow_colors_HAVE_FULLCAP)r*   liness     r,   r    z(FileDownloader._prepare_multiline_status%  s    ;??<(( 	m355DOOX_  ** 	m-dhoh.GOODOO[__455 	m4TX5H5LeTTDOO.tx/B/FSWS^SbSbcjSkSkOkllDO'+x'='A'ndhF\F`dnFn$(,(>(B%%%r.   c                 8    | j                                          d S r_   )r   endr*   s    r,   _finish_multiline_statusz'FileDownloader._finish_multiline_status1  s    r.   z
light blueyellowgreenz
bold white )downloaded_bytesr\   etarq   r   total_bytestotal_bytes_estimatec                    | j         j        D ]/\  }}d| d}||vr|                     ||         |          ||<   0||z  |d<   |                                }|                    d           |d         |d}| j                            di           }| j                            | j	        
                    |                    d          pd|          |                    d	          pd
           |                     | j	        
                    |                    d          pd|          t          j        |          |                    d                     d S )NrB   _str_default_template	info_dict)r   progressprogress_templatedownloadz)[download] %(progress._default_template)sprogress_idxr   zdownload-titlez%yt-dlp %(progress._default_template)s_percent)ProgressStylesitems__format_progresscopypopr   r#   r   print_at_liner+   evaluate_outtmplr4   r   	from_dict)r*   sdefault_templatenamestyleprogress_dictr   s          r,   _report_progress_statusz&FileDownloader._report_progress_status>  s|   .5 	< 	<KD%!t>>>D1}}++AdGU;;AdGG!1A!5
+&&&!";]KK KOO,?DD%%dh&?&?!!*--\1\' 'EE.116Q	8 	8 	8 	dh77!!"233^7^ *4Q77z9J9J	L 	L 	L 	L 	Lr.   c                 X     | j         j        | j        j        | j        j        g|R i |S r_   )r+   _format_textr   streamr   )r*   r?   r   s      r,   r  zFileDownloader._format_progressR  sK    $tx$O"DO$@SCGS S SKQS S 	Sr.   c                    ddfd
}fd}d         dk    r| j                             d          r|                     d           t          fd	          }                    ||                     |                                           |d
          |                                         d                    d|                     d          d           | 	                    t          d |d           |d           |d          d                     d         dk    rd S | j                             d          x}rY| j        5  t          j                    | j        k     r	 d d d            d S | xj        |z  c_        d d d            n# 1 swxY w Y   t          fdfdfd          }                    |                                         d                                                    |                                         d                    ||                     |           |d
           |d           |d          |                                         d                    d            |dd d!d"d#          }| |d$d%          z  }| 	                    |           d S )&Nr   )defaultc                 V    |D ]$^ }}t          fd|D                       r|c S %| S )Nc              3   F   K   | ]}                     |          d uV  d S r_   r#   ).0r   r  s     r,   	<genexpr>zFFileDownloader.report_progress.<locals>.with_fields.<locals>.<genexpr>Y  s2      <<quuQxxt+<<<<<<r.   )all)r  tupsfieldstmplr  s       r,   with_fieldsz3FileDownloader.report_progress.<locals>.with_fieldsW  sN    !%    <<<<V<<<<<  KKK Nr.   c                 L    t                              |                     dS )Nrp   )r   r#   )kr  s    r,   r   z0FileDownloader.report_progress.<locals>.<lambda>]  s    \!%%((%;%;"B"B r.   statusfinishedr   z[download] Download completedc                  &     d          d         z  S )Nr   r   r[   r  s   r,   r   z0FileDownloader.report_progress.<locals>.<lambda>b  s    Q}%5)%D r.   r   r   rS   d   )rq   
_speed_str_total_bytes_str_elapsed_strr   _percent_strz100%%)r   zof %(_total_bytes_str)s)r   zin %(_elapsed_str)s)rq   zat %(_speed_str)s )delimdownloadingr   c                  ,    d d         z   d         z  S )Nr"  r   r   r[   r!  s   r,   r   z0FileDownloader.report_progress.<locals>.<lambda>|  s    C!.//!M2BB r.   c                  ,    d d         z   d         z  S )Nr"  r   r   r[   r!  s   r,   r   z0FileDownloader.report_progress.<locals>.<lambda>}  s    C!.//!4J2KK r.   c                        d         dk    odS )Nr   r   r[   r!  s   r,   r   z0FileDownloader.report_progress.<locals>.<lambda>~  s    A()Q.41 r.   r   rq   r   r   )_eta_strr#  r   r&  r$  _total_bytes_estimate_str_downloaded_bytes_strr%  )r   zK%(_percent_str)s of %(_total_bytes_str)s at %(_speed_str)s ETA %(_eta_str)s)r   zU%(_percent_str)s of ~%(_total_bytes_estimate_str)s at %(_speed_str)s ETA %(_eta_str)s)r   r   z>%(_downloaded_bytes_str)s at %(_speed_str)s (%(_elapsed_str)s))r   z+%(_downloaded_bytes_str)s at %(_speed_str)sz3%(_percent_str)s at %(_speed_str)s ETA %(_eta_str)s)fragment_indexfragment_countz- (frag %(fragment_index)s/%(fragment_count)s))r0  z (frag %(fragment_index)s))r   r#   r>   r   updaterr   striprO   r]   r  r   r&   r'   r(   r)   rQ   )r*   r  r  _format_bytesrq   update_deltar   msg_templates    `      r,   r"   zFileDownloader.report_progressV  s   ') 	 	 	 	 	 	 	 CBBBX;*$${|,, @>???DDDDEEEHH"//66<<>>$1M-$@$@ $ 3 3AEE)4D4D E E! $ 3 3C 8 8     ((MFGG>??:;;- - -    X;-''F;??+;<<<< 	:* : :>##d&???: : : : : : : : ))\9)): : : : : : : : : : : : : : :
 BBBBKKKK44446 6 	
e55;;==++AEE'NN;;  //99 -m < <)67M)N)N%2]3E%F%F //i0@0@AA	
 	
 		 		 		 #{j}mOIK K K 	a<> > 	> 	$$Q55555s   F?FF"Fc                 6    |                      d|            dS )z'Report attempt to resume at given byte.z%[download] Resuming download at byte Nr   )r*   
resume_lens     r,   report_resuming_bytez#FileDownloader.report_resuming_byte  s#    KzKKLLLLLr.   c                      |t           u rdnd}t          j        ||| j         fd|st          n fd j                            di                               |pd          |rd|dnd	|  nd
           dS )zReport retryFfragmentc                 4                         d|            S )Nz[download] Got error: )r   )r   r*   s    r,   r   z-FileDownloader.report_retry.<locals>.<lambda>  s    T--.Ls.L.LMM r.   c                 4                         d|            S )Nz[download] Got error: r   )r   r*   s    r,   r   z-FileDownloader.report_retry.<locals>.<lambda>  s    t7H7HIgdeIgIg7h7h r.   r   httpNr  r'  )r   r   r   r   suffix)r	   r   r   r   r   r   r#   )r*   r   r   ru   
frag_indexr   is_frags   `      r,   r   zFileDownloader.report_retry  s    %33%%!d&6MMMM"'h((-h-h-h-h{'>CCGGHYSYZZSZdOZ%7cc=M=M=MOOO`d	f 	f 	f 	f 	f 	fr.   c                 0    |                      d           dS )z,Report it was impossible to resume download.z[download] Unable to resumeNr   r   s    r,   report_unable_to_resumez&FileDownloader.report_unable_to_resume  s    455555r.   c                     dS )zp Whether the downloader can download the fragments from the manifest.
        Redefine in subclasses if needed. Nr[   )manifests    r,   supports_manifestz FileDownloader.supports_manifest  s	     	r.   c                    | j                             dd           ot          j                            |          }t          |d          s| j                             dd          o:t          j                            |          o| j                             dd           }|dk    rf|s|rb|                     |           |                     |dt          j        	                    |          d	|           | 
                                 d
S d}|r| j                             d          pd}n| j                             d          pd}| j                             d          pd}	|                    d          p|g}
t          d |
D                       x}r5|t          t          j                              z
  }||k    rd}|}||	k    r|}	t          j        ||	p|          }|dk    r1|                     d|dd| d           t          j        |           |                     ||          }| 
                                 |dfS )zpDownload to a filename using the info from info_dict
        Return True on success and False otherwise
        
overwritesTwrite
continuedlr   Fr   r  )r   r  r   )TFr   sleep_interval_subtitlesr   sleep_intervalmax_sleep_intervalrequested_formatsc              3   D   K   | ]}|                     d           pdV  dS )available_atr   Nr  )r  r   s     r,   r  z*FileDownloader.download.<locals>.<genexpr>  s3      "Y"Y!155#8#8#=A"Y"Y"Y"Y"Y"Yr.   zas required by the sitez[download] Sleeping z.2fz	 seconds z...)r   r#   rx   ry   r   r8   rz   r2   _hook_progressr{   r   r   r`   r'   randomuniformr>   r   real_download)r*   r   r   subtitlenooverwrites_and_existscontinuedl_and_exists
sleep_noterL  min_sleep_intervalrM  rN  rP  forced_sleep_intervalrets                 r,   r   zFileDownloader.download  s   
 d333 )x(( 	 
 x)) 	#d33 9GNN8,,9%888 " 3$;?T33H===## ((#%7??8#<#<% % 	  
 --///"{
 	N![__-GHHMANN!%1A!B!B!Ga!%1E!F!F!K! ).A B B Qyk""Y"YGX"Y"Y"YYYY| ?(4s49;;7G7G(G%(+===!:J)>&(+===)>&#^"$6$L:LN NN ANN^.^^^z^^^___J~&&&  955%%'''Dyr.   c                      t          d          )z.Real download process. Redefine in subclasses.z-This method must be implemented by subclasses)NotImplementedError)r*   r   r   s      r,   rT  zFileDownloader.real_download  s    !"QRRRr.   c                 :    ||d<   | j         D ]} ||           d S )Nr   )r   )r*   r  r   phs       r,   rQ  zFileDownloader._hook_progress  s9    '{ & 	 	BBvJJJJ	 	r.   c                 :    | j                             |           d S r_   )r   append)r*   r_  s     r,   r!   z FileDownloader.add_progress_hook  s!     	##B'''''r.   c                     | j                             dd          sd S |%t          j                            |d                   }|                     | dt          |                      d S )NverboseFr   z command line: )r   r#   rx   ry   basenamer7   r   )r*   r?   exes      r,   
_debug_cmdzFileDownloader._debug_cmd  sm    {y%00 	F;'""47++CCCCD0A0ACCDDDDDr.   c                     |                     d          }|d S | j                            |          \  }}|r|S |r-|                     | j                            |                     d S )Nimpersonate)r#   r+   _parse_impersonate_targetsr3   _unavailable_targets_message)r*   r   rh  available_targetrequested_targetss        r,   _get_impersonate_targetz&FileDownloader._get_impersonate_target  s}    mmM224.2h.Q.QR].^.^++ 	Z## 	Z E EFW X XYYYtr.   )r   )Fr_   )5rF   
__module____qualname____doc___TEST_FILE_SIZEr   r-   r   r>   r   r   rI   staticmethodrO   classmethodrQ   rX   r]   r	   rj   ra   rr   rv   r}   r   r   r   r   r   r   r   r   r   r   r   r   r    r   r   r   r  r  r"   r9  r   rC  rF  r   rT  rQ  r!   rf  rm  r[   r.   r,   r   r   %   s	       ) )V OF	9 	9 	98 8 8"K K K KN N ]N , , \, I I [I = = \=
 D D \D =GQ[ D D D [D " " \" T T \T B B \B   \
 
 
 \
 $ $ \$' ' ' " " "  
" " " +0 C C C C C( fD)))  *) h       h/ /  /
  &> > >
C 
C 
C 
C   Y%  NL L L(S S S>6 >6 >6@M M M <FT f f f f6 6 6   \
4 4 4 4lS S S  ( ( (
E E E E	 	 	 	 	r.   r   )!r   r   r   rx   rR  rD   r$   r'   
minicursesr   r   r   r   utilsr   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   utils._utilsr   r   r[   r.   r,   <module>rw     s            				  				                                                   $ * ) ) ) ) )c c c c c c c c c cr.   