§
    ƒØjí  ã                  ó:  — d dl mZ d dlZd dlZd dlZd dlmZ d dlmZ d dlmZ d dlm	Z	 d dlm
Z
  G d„ d	¦  «        Z G d
„ d¦  «        Z G d„ de¦  «        Z G d„ dej        ¦  «        Z G d„ dej        ¦  «        Zedk    rd dlZ ej        e¦  «         dS dS )é    )ÚannotationsN)Úchord)Úkey)Úinterval)Únote)Ústreamc                  ó°   — e Zd ZdZd„ Zd„ Zdd„Zdd„Zdd„Zdd„Z	dd	„Z
dd
„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zdd„ZdS )ÚHasheraÂ  
    This is a modular hashing object that can hash notes, chords, and rests, and some of their
    properties. Steps to using and calling the hasher:

    1) Initialize a hasher object

    2) Set the properties that you want to hash. There are 4 main groups of properties/settings::

        a) self.validTypes should be some combination of notes, chords, rests

        b) general hashing settings include self.includeReference. if
           self.includeReference is True, a reference to the original note/rest/chord is created
           and kept track of during the hashing process.

        c) note properties are things like pitch, duration, offset, and some slightly fancier
           properties

        d) self.stateVars is a dictionary of things you might want to hash that require some memory
           e.g. current key signature, interval from the last note

    3) call the hashStream() function on the stream you want to hash.

    This is what the Hasher object does the in background once hashStream() is called:

    1) It runs self.setupValidTypesAndStateVars() and sets up properties from (a) and (d) from
    above based on your settings

    2) It runs self.preprocessStream() and based on settings from (d)

    3) It determines which objects in the passed-in stream should be hashed

    4) It runs self.setupTupleList() and sets up self.tupleList, self.hashingFunctions
    and self.tupleClass, all related to each other. self.tupleList is a list of all the
    properties that are hashed. self.hashingFunctions is a dictionary of which hashing function
    should be used for each property (there are multiple ways of hashing a note's pitch, for
    example, by MIDI number, or by a string representation). self.tupleClass is a NamedTuple
    that is constructed ad hoc based on which properties are to be hashed.

    5) For all the elements from the stream that are to be hashed, the hasher hashes every one of
    its properties that are to be hashed using the hashing function listed in
    self.hashingFunctions. It creates a single NamedTuple called a NoteHash for each element
    from the stream. However, if self.includeReference is set to True, a NoteHashWithReference
    tuple is created instead.
    c                ón  — t           j        t           j        t          j        g| _        d| _        d| _        d| _        d| _	        d| _
        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        g | _        d| _        i | _        i | _        dS )z¡
        The Hasher object is initialized with defaults of what objects should be hashed, and
        what properties of those objects should be hashed.
        FTé    N)r   ÚNoteÚRestr   ÚChordÚ
validTypesÚincludeReferenceÚ	hashPitchÚhashMIDIÚhashNoteNameOctaveÚ
hashOctaveÚhashDurationÚroundDurationAndOffsetÚ
hashOffsetÚgranularityÚhashIntervalFromLastNoteÚhashIsAccidentalÚ
hashIsTiedÚhashChordsAsNotesÚhashChordsAsChordsÚhashNormalOrderStringÚhashPrimeFormStringÚ	tupleListÚ
tupleClassÚ	stateVarsÚhashingFunctions©Úselfs    ú’/Users/tedpeters/Documents/Projects/Claude Projects/Misc Tools/notename-sheets/.venv/lib/python3.11/site-packages/music21/alpha/analysis/hasher.pyÚ__init__zHasher.__init__E   sÀ   € õ  œ9¥d¤iµ´Ð=ˆŒð !&ˆÔð ˆŒàˆŒà"'ˆÔØˆŒØ ˆÔØ&*ˆÔ#ØˆŒàˆÔØ(-ˆÔ%Ø %ˆÔØˆŒð
 "&ˆÔØ"'ˆÔØ%*ˆÔ"Ø#(ˆÔ ð ˆŒØˆŒð ˆŒØ "ˆÔÐÐó    c                ó–   — | j         r
d| j        d<   | j        r0| j                             t
          j        ¦  «         d| j        d<   dS dS )aa  
        Sets up the self.stateVars dictionary depending on how the flags for
        self.hashIntervalFromLastNote and self.hashIsAccidental are set.

        >>> h = alpha.analysis.hasher.Hasher()
        >>> h.hashIntervalFromLastNote = True
        >>> h.setupValidTypesAndStateVars()
        >>> h.stateVars
        {'IntervalFromLastNote': None}

        >>> h2 = alpha.analysis.hasher.Hasher()
        >>> h2.hashIsAccidental = True
        >>> h2.setupValidTypesAndStateVars()
        >>> h2.stateVars
        {'KeySignature': None}

        >>> key.KeySignature in h2.validTypes
        True
        NÚIntervalFromLastNoteÚKeySignature)r   r#   r   r   Úappendr   r,   r%   s    r'   ÚsetupValidTypesAndStateVarsz"Hasher.setupValidTypesAndStateVarss   s\   € ð( Ô(ð 	:Ø59ˆDŒNÐ1Ñ2àÔ ð 	2ØŒO×"Ò"¥3Ô#3Ñ4Ô4Ð4Ø-1ˆDŒN˜>Ñ*Ð*Ð*ð	2ð 	2r)   Nc                ó6   — |r|j         j        S |j         j        S )a¢  
        returns the duration of a chord object passed in, otherwise the duration of a note
        object passed in.

        >>> h = alpha.analysis.hasher.Hasher()
        >>> n = note.Note('A-', quarterLength=2.5)
        >>> h._hashDuration(n)
        2.5

        >>> d = duration.Duration(2.0)
        >>> c = chord.Chord('A-4 C#5 E5', duration=d)
        >>> h._hashDuration(n, thisChord=c)
        2.0
        )ÚdurationÚquarterLength©r&   ÚeÚ	thisChords      r'   Ú_hashDurationzHasher._hashDuration�   s#   € ð ð 	4ØÔ%Ô3Ð3ØŒzÔ'Ð'r)   c                óâ   — |r,|                       t          |j        j        ¦  «        ¦  «        S |                       t          |j        j        ¦  «        ¦  «        |j        _        |j        j        S )z0
        TODO: Check if this is working
        )Ú_getApproxDurOrOffsetÚfloatr0   r1   r2   s      r'   Ú_hashRoundedDurationzHasher._hashRoundedDuration¢   s_   € ð ð 	WØ×-Ò-­e°IÔ4FÔ4TÑ.UÔ.UÑVÔVÐVØ#'×#=Ò#=½eÀAÄJÔD\Ñ>]Ô>]Ñ#^Ô#^ˆŒ
Ô ØŒzÔ'Ð'r)   c                óh   — |r	| j         rdS t          |t          j        ¦  «        rdS |j        j        S )a,  
        returns midi pitch value (21-108) of a note
        returns 0 if rest
        returns 1 if not hashing individual notes of a chord

        >>> n = note.Note(72)
        >>> c = chord.Chord('A-4 C#5 E5')
        >>> h = alpha.analysis.hasher.Hasher()
        >>> h.hashChordsAsChords = True
        >>> h._hashMIDIPitchName(n, thisChord=c)
        1
        >>> h.hashChordsAsChords = False
        >>> h._hashMIDIPitchName(n, thisChord=c)
        72
        >>> r = note.Rest()
        >>> h._hashMIDIPitchName(r, thisChord=c)
        0

        é   r   )r   Ú
isinstancer   r   ÚpitchÚmidir2   s      r'   Ú_hashMIDIPitchNamezHasher._hashMIDIPitchName«   s>   € ð( ð 	˜Ô0ð 	Ø�1Ý˜�4œ9Ñ%Ô%ð 	Ø�1ØŒwŒ|Ðr)   c                óx   — |r	| j         rdS t          |t          j        ¦  «        rdS t	          |j        ¦  «        S )aQ  
        returns string representation of a note e.g. 'F##4'
        returns 'r' if rest
        returns 'z' if not hashing individual notes of a chord (i.e. hashing chords as chords)

        >>> n = note.Note(72)
        >>> c = chord.Chord('A-4 C#5 E5')
        >>> h = alpha.analysis.hasher.Hasher()
        >>> h.hashChordsAsChords = True
        >>> h._hashPitchName(n, thisChord=c)
        'z'
        >>> h.hashChordsAsChords = False
        >>> h._hashPitchName(n, thisChord=c)
        'C5'
        >>> r = note.Rest()
        >>> h._hashPitchName(r, thisChord=c)
        'r'
        ÚzÚr©r   r<   r   r   Ústrr=   r2   s      r'   Ú_hashPitchNamezHasher._hashPitchNameÅ   sB   € ð& ð 	˜Ô0ð 	Ø�3Ý˜�4œ9Ñ%Ô%ð 	Ø�3Ý�1”7‰|Œ|Ðr)   c                óˆ   — |r	| j         rdS t          |t          j        ¦  «        rdS t	          |j        ¦  «        dd…         S )aZ  
        returns string representation of a note without the octave e.g. 'F##'
        returns 'r' if rest
        returns 'z' if not hashing individual notes of a chord

        >>> n = note.Note(72)
        >>> c = chord.Chord('A-4 C#5 E5')
        >>> h = alpha.analysis.hasher.Hasher()
        >>> h.hashChordsAsChords = True
        >>> h._hashPitchNameNoOctave(n, thisChord=c)
        'z'
        >>> h.hashChordsAsChords = False
        >>> h._hashPitchNameNoOctave(n, thisChord=c)
        'C'
        >>> r = note.Rest()
        >>> h._hashPitchNameNoOctave(r, thisChord=c)
        'r'
        rA   rB   NéÿÿÿÿrC   r2   s      r'   Ú_hashPitchNameNoOctavezHasher._hashPitchNameNoOctaveÞ   sK   € ð& ð 	˜Ô0ð 	Ø�3Ý˜�4œ9Ñ%Ô%ð 	Ø�3Ý�1”7‰|Œ|˜C˜R˜CÔ Ð r)   c                óŽ   — t          |t          j        ¦  «        r	| j        rdS t          |t          j        ¦  «        rdS |j        S )aú  
        returns octave number of a note
        returns -1 if rest or not hashing individual notes of a chord

        >>> n = note.Note(72)
        >>> c = chord.Chord('A-4 C#5 E5')
        >>> h = alpha.analysis.hasher.Hasher()
        >>> h.hashChordsAsChords = True
        >>> h._hashOctave(c, thisChord=c)
        -1
        >>> h.hashChordsAsChords = False
        >>> h._hashOctave(n, thisChord=c)
        5
        >>> r = note.Rest()
        >>> h._hashOctave(r, thisChord=c)
        -1
        rG   )r<   r   r   r   r   r   Úoctaver2   s      r'   Ú_hashOctavezHasher._hashOctave÷   sG   € õ$ �a�œÑ%Ô%ð 	¨$Ô*Að 	Ø�2Ý˜�4œ9Ñ%Ô%ð 	Ø�2ØŒxˆr)   c                ó   — d S ©N© r2   s      r'   Ú_hashIsAccidentalzHasher._hashIsAccidental  s   € àˆr)   c                ó†   — |r|                       |j        ¦  «        S |                       |j        ¦  «        |_        |j        S )zÈ
        Returns offset rounded to the nearest subdivided beat.
        The subdivided beat is indicated with self.granularity.
        By default, the granularity is set to 32, or 32nd notes
        )r7   Úoffsetr2   s      r'   Ú_hashRoundedOffsetzHasher._hashRoundedOffset  sB   € ð ð 	@Ø×-Ò-¨iÔ.>Ñ?Ô?Ð?Ø×-Ò-¨a¬hÑ7Ô7ˆŒØŒxˆr)   c                ó"   — |r|j         S |j         S )zW
        returns an unrounded floating point representation of a note's offset
        )rQ   r2   s      r'   Ú_hashOffsetzHasher._hashOffset  s   € ð ð 	$ØÔ#Ð#ØŒxˆr)   c                óJ  — 	 t          |t          j        ¦  «        rt|                     d¦  «        �a|                     d¦  «        }|€dS t	          j        ||¬¦  «        j        }t	          j        t	          j        |¦  «        j        ¦  «        S dS dS # t          $ r Y dS w xY w)zÆ
        returns the interval between last note and current note, if extant
        known issues with first note of every measure in transposed pieces
        returns 0 if things don't work
        r   Nr   )Ú	noteStartÚnoteEnd)	r<   r   r   Úpreviousr   ÚIntervalÚintervalClassÚconvertGenericÚ	TypeError)r&   r3   r4   ÚpreviousNoteÚintFromLastNotes        r'   Ú_hashIntervalFromLastNotez Hasher._hashIntervalFromLastNote&  sÁ   € ð
	Ý˜1�dœiÑ(Ô(ð aØŸ
š
 6Ñ*Ô*Ð6Ø Ÿzšz¨&Ñ1Ô1�ØÐ'Ø˜1Ý"*Ô"3¸lØ<=ð#?ñ #?ô #?Ü?Lð  åÔ.­xÔ/@ÀÑ/QÔ/QÔ/_Ñ`Ô`Ð`ðað aØ6Ð6øõ ð 	ð 	ð 	Ø�1�1ð	øøøs   ‚AB Á
AB Â
B"Â!B"c                ó   — |r|j         S dS )zg
        returns prime form of a chord as a string e.g. '<037>'
        returns '<>' otherwise
        ú<>)ÚprimeFormStringr2   s      r'   Ú_hashPrimeFormStringzHasher._hashPrimeFormString8  s   € ð
 ð 	-ØÔ,Ð,Øˆtr)   c                ó>   — |r|                      |j        ¦  «        S dS )zi
        returns normal order of a chord as a string e.g. '<047>'
        returns '<>' otherwise
        ra   )ÚformatVectorStringÚnormalOrderr2   s      r'   Ú_hashChordNormalOrderStringz"Hasher._hashChordNormalOrderStringA  s)   € ð
 ð 	GØ×/Ò/°	Ô0EÑFÔFÐFØˆtr)   c                óü  — g }| j         r’|                     d¦  «         | j        r| j        | j        d<   n;| j        s| j        s| j        | j        d<   n| j        s| j        r| j        | j        d<   | j        r$|                     d¦  «         | j	        | j        d<   | j
        r$|                     d¦  «         | j        | j        d<   | j        rn]| j        rV| j        r$|                     d¦  «         | j        | j        d<   | j        r$|                     d¦  «         | j        | j        d<   | j        r;|                     d¦  «         | j        r| j        | j        d<   n| j        | j        d<   | j        r;|                     d¦  «         | j        r| j        | j        d<   n| j        | j        d<   | j        r$|                     d¦  «         | j        | j        d<   || _        t9          j        d	|¦  «        | _        d
S )aü  
        Sets up self.hashingFunctions, a dictionary of which properties of self.validTypes should
        be hashed and which hashing functions should be used for those properties. Creates a
        tupleList of all the properties that are hashed and uses that to create a named tuple
        NoteHash with those properties. This is how we can generate a malleable named tuple
        NoteHash that is different depending upon which properties a particular instance of
        Hasher object hashes.
        ÚPitchÚIsAccidentalÚOctaveÚNormalOrderStringÚPrimeFormStringÚDurationÚOffsetr+   ÚNoteHashN)r   r-   r   r?   r$   r   rE   rH   r   rO   r   rK   r   r   r   rg   r    rc   r   r   r9   r5   r   rR   rT   r   r_   r!   ÚcollectionsÚ
namedtupler"   )r&   r!   s     r'   ÚsetupTupleListzHasher.setupTupleListL  s`  € ð ˆ	àŒ>ð 	OØ×Ò˜WÑ%Ô%Ð%ØŒ}ð MØ15Ô1H�Ô% gÑ.Ð.Ø”]ð M¨4Ô+Bð MØ15Ô1D�Ô% gÑ.Ð.Ø”]ð M tÔ'>ð MØ15Ô1L�Ô% gÑ.àÔ$ð OØ× Ò  Ñ0Ô0Ð0Ø8<Ô8N�Ô% nÑ5àŒ?ð 	?Ø×Ò˜XÑ&Ô&Ð&Ø.2Ô.>ˆDÔ! (Ñ+àÔ!ð 	UØØÔ$ð 	UØÔ)ð ^Ø× Ò Ð!4Ñ5Ô5Ð5Ø=AÔ=]�Ô%Ð&9Ñ:ØÔ'ð UØ× Ò Ð!2Ñ3Ô3Ð3Ø;?Ô;T�Ô%Ð&7Ñ8àÔð 	GØ×Ò˜ZÑ(Ô(Ð(ØÔ*ð GØ48Ô4M�Ô% jÑ1Ð1à48Ô4F�Ô% jÑ1àŒ?ð 	CØ×Ò˜XÑ&Ô&Ð&ØÔ*ð CØ26Ô2I�Ô% hÑ/Ð/à26Ô2B�Ô% hÑ/àÔ(ð 	[Ø×ÒÐ3Ñ4Ô4Ð4Ø<@Ô<ZˆDÔ!Ð"8Ñ9à"ˆŒÝ%Ô0°¸YÑGÔGˆŒˆˆr)   c                ó   — dS )zW
        lightweight hasher. only hashes number of notes, first and last pitch
        NrN   )r&   Úss     r'   ÚhashMeasureszHasher.hashMeasures‡  s   € € € r)   c                ó’  ‡ ‡‡‡— g }‰                       ¦   «          |                     ¦   «         }t          ‰ j        ¦  «        Šˆfd„|D ¦   «         }‰                      ¦   «          |D ]ßŠ‰ j        r%t          ‰t          j        ¦  «        r‰‰ j	        d<   Œ.t          ‰t          j        ¦  «        rl‰ j        r2‰D ].Šˆˆˆ fd„‰ j        D ¦   «         }‰                      ||‰¦  «         Œ/Œ�‰ j        r+ˆˆ fd„‰ j        D ¦   «         }‰                      ||‰¦  «         Œ´ˆˆ fd„‰ j        D ¦   «         }‰                      ||‰¦  «         Œà|S )a˜  
        This method is the meat of the program. It goes through all the elements that are left
        to be hashed and individually hashes them by looking up which hashing functions ought
        to be used on each element and passing off the element to the method
        self.addSingleNoteHashToFinalHash, which creates the appropriate hash for that element
        and adds it to self.finalHash
        c                ó4   •— g | ]}t          |‰¦  «        ¯|‘ŒS rN   )r<   )Ú.0ÚeltÚtupValidTypess     €r'   ú
<listcomp>z%Hasher.hashStream.<locals>.<listcomp>˜  s(   ø€ ÐSÐSÐS sµJ¸sÀMÑ4RÔ4RÐS˜sÐSÐSÐSr)   Ú
currKeySigc                ó@   •— g | ]} ‰j         |         ‰‰¬ ¦  «        ‘ŒS )©r4   ©r$   )ry   ÚhashPropertyrz   Únr&   s     €€€r'   r|   z%Hasher.hashStream.<locals>.<listcomp>£  sH   ø€ ð *Pð *Pð *PØ0<ð +N¨$Ô*?ÀÔ*MÈaÐ[^Ð*_Ñ*_Ô*_ð *Pð *Pð *Pr)   c                ó@   •— g | ]} ‰j         |         d ‰¬¦  «        ‘ŒS )Nr   r€   ©ry   r�   rz   r&   s     €€r'   r|   z%Hasher.hashStream.<locals>.<listcomp>¨  sH   ø€ ð &Lð &Lð &LØ,8ð 'J dÔ&;¸LÔ&IÈ$ÐZ]Ð&^Ñ&^Ô&^ð &Lð &Lð &Lr)   c                ó<   •— g | ]} ‰j         |         ‰¦  «        ‘ŒS rN   r€   r„   s     €€r'   r|   z%Hasher.hashStream.<locals>.<listcomp>¬  sB   ø€ ð "Hð "Hð "HØ(4ð #F $Ô"7¸Ô"EÀcÑ"JÔ"Jð "Hð "Hð "Hr)   )r.   ÚrecurseÚtupler   rs   r   r<   r   r,   r#   r   r   r   r!   ÚaddHashToFinalHashr   )	r&   ru   Ú	finalHashÚssÚfinalEltsToBeHashedÚsingleNoteHashrz   r‚   r{   s	   `     @@@r'   Ú
hashStreamzHasher.hashStreamŒ  sò  øøøø€ ð ˆ	Ø×(Ò(Ñ*Ô*Ð*Ø�YŠY‰[Œ[ˆÝ˜dœoÑ.Ô.ˆØSÐSÐSÐS¨bÐSÑSÔSÐØ×ÒÑÔÐð 'ð 	Hð 	HˆCàÔ$ð H­°C½Ô9IÑ)JÔ)Jð HØ/2�”˜|Ñ,Ð,Ý˜C¥¤Ñ-Ô-ð HØÔ)ð 	LØ ð Nð N˜ð*Pð *Pð *Pð *Pð *Pð *PØ@DÄð*Pñ *Pô *P˜ð ×/Ò/°À	È1ÑMÔMÐMÐMð	Nð
 Ô,ð Lð&Lð &Lð &Lð &Lð &LØ<@¼Nð&Lñ &Lô &L�Nà×+Ò+¨N¸IÀsÑKÔKÐKøð"Hð "Hð "Hð "Hð "HØ8<¼ð"Hñ "Hô "H�à×'Ò'¨¸	À3ÑGÔGÐGÐGàÐr)   c                ó¦   — | j                              |¦  «        }| j        r|                      |||¦  «         d S |                      ||¦  «         d S rM   )r"   Ú_maker   Ú#addNoteHashWithReferenceToFinalHashÚaddNoteHashToFinalHash)r&   rŒ   r‰   Ú	referenceÚ	tupleHashs        r'   rˆ   zHasher.addHashToFinalHash²  s\   € Ø”_×*Ò*¨>Ñ:Ô:ˆ	ØÔ ð 	>Ø×4Ò4°YÀ	È9ÑUÔUÐUÐUÐUà×'Ò'¨	°9Ñ=Ô=Ð=Ð=Ð=r)   c                ó\   — t          |¦  «        }||_        |                     |¦  «         dS )a¨  
        creates a NoteHashWithReference object from tupleHash and with the reference pass in
        and adds the NoteHashWithReference object to the end of finalHash

        >>> from collections import namedtuple
        >>> n = note.Note('C4')
        >>> NoteHash = namedtuple('NoteHash', ['Pitch', 'Duration'])
        >>> nh = NoteHash(n.pitch, n.duration)
        >>> finalHash = []
        >>> h = alpha.analysis.hasher.Hasher()
        >>> h.addNoteHashWithReferenceToFinalHash(finalHash, nh, n)
        >>> finalHash
        [NoteHashWithReference(Pitch=C4, Duration=<music21.duration.Duration 1.0>)]

        >>> finalHash[0].reference.id == n.id
        True
        N)ÚNoteHashWithReferencer’   r-   )r&   r‰   r“   r’   Únhwrs        r'   r�   z*Hasher.addNoteHashWithReferenceToFinalHash¹  s2   € õ& % YÑ/Ô/ˆØ"ˆŒØ×Ò˜ÑÔÐÐÐr)   c                óN   — t          |¦  «        }|                     |¦  «         dS )a  
        creates a NoteHash object from tupleHash and adds the NoteHash
        object to the end of finalHash

        >>> from collections import namedtuple
        >>> n = note.Note('C4')
        >>> NoteHash = namedtuple('NoteHash', ['Pitch', 'Duration'])
        >>> nh = NoteHash(n.pitch, n.duration)
        >>> finalHash = []
        >>> h = alpha.analysis.hasher.Hasher()
        >>> h.addNoteHashToFinalHash(finalHash, nh)
        >>> finalHash
        [(<music21.pitch.Pitch C4>, <music21.duration.Duration 1.0>)]
        N)rp   r-   )r&   r‰   r“   Únhs       r'   r‘   zHasher.addNoteHashToFinalHashÐ  s+   € õ  �iÑ Ô ˆØ×Ò˜ÑÔÐÐÐr)   c                ó@   — t          || j        z  ¦  «        | j        z  S rM   )Úroundr   )r&   ÚdurOrOffsets     r'   r7   zHasher._getApproxDurOrOffsetô  s    € Ý�[ 4Ô#3Ñ3Ñ4Ô4°tÔ7GÑGÐGr)   é   c                óf   — ||k    p+t          |d|z  z  ¦  «        t          |d|z  z  ¦  «        k    S ©z˜
        use to look at whether beat lengths are close, within a certain range
        probably can use for other things that are approx. equal
        é
   ©Úint©r&   ÚaÚbÚsig_figs       r'   Ú_approximatelyEqualzHasher._approximatelyEqual÷  ó:   € ð
 �AŠvÐI�˜Q  w¡Ñ.Ñ/Ô/µ3°q¸2À¹=Ñ7HÑ3IÔ3IÒIÐIr)   rM   )rœ   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r(   r.   r5   r9   r?   rE   rH   rK   rO   rR   rT   r_   rc   rg   rs   rv   r�   rˆ   r�   r‘   r7   r¦   rN   r)   r'   r
   r
      sº  € € € € € ð+ð +ðZ,#ð ,#ð ,#ð\2ð 2ð 2ð8(ð (ð (ð (ð&(ð (ð (ð (ðð ð ð ð4ð ð ð ð2!ð !ð !ð !ð2ð ð ð ð0ð ð ð ð	ð 	ð 	ð 	ðð ð ð ðð ð ð ð$ð ð ð ðð ð ð ð9Hð 9Hð 9Hðvð ð ð
$ð $ð $ðL>ð >ð >ðð ð ð.ð ð ðHHð Hð HðJð Jð Jð Jð Jð Jr)   r
   c                  ó$   — e Zd ZdZd„ Zd„ Zd„ ZdS )r•   aT  
    returns tuple with reference to original note or chord or rest

    >>> from collections import namedtuple
    >>> NoteHash = namedtuple('NoteHash', ['Pitch', 'Duration'])
    >>> nh = NoteHash(60, 4)
    >>> nhwr = alpha.analysis.hasher.NoteHashWithReference(nh)
    >>> nhwr.reference = note.Note('C4')
    >>> nhwr
    NoteHashWithReference(Pitch=60, Duration=4)

    >>> nhwr.Pitch
    60
    >>> nhwr.Duration
    4

    >>> nhwr.hashItemsKeys
    ('Pitch', 'Duration')

    >>> for val in nhwr:
    ...     print(val)
    60
    4

    >>> nhwr.reference
    <music21.note.Note C>
    c                óÀ   — d | _         |                     ¦   «         }|D ]}t          | |||         ¦  «         Œt          |                     ¦   «         ¦  «        | _        d S rM   )r’   Ú_asdictÚsetattrr‡   ÚkeysÚhashItemsKeys)r&   ÚhashItemsNTÚhashItemsDictÚxs       r'   r(   zNoteHashWithReference.__init__  se   € ØˆŒØ#×+Ò+Ñ-Ô-ˆØð 	/ð 	/ˆAÝ�D˜!˜]¨1Ô-Ñ.Ô.Ð.Ð.Ý" =×#5Ò#5Ñ#7Ô#7Ñ8Ô8ˆÔÐÐr)   c              #  óB   K  — | j         D ]}t          | |¦  «        V — Œd S rM   )r±   Úgetattr)r&   ÚkeyNames     r'   Ú__iter__zNoteHashWithReference.__iter__&  s;   è è € ØÔ)ð 	)ð 	)ˆGÝ˜$ Ñ(Ô(Ð(Ð(Ð(Ð(ð	)ð 	)r)   c                óÔ   — d}g }| j         D ]>}|}|dz  }|t          t          | |¦  «        ¦  «        z  }|                     |¦  «         Œ?|d                     |¦  «        z  }|dz  }|S )NzNoteHashWithReference(ú=z, ú))r±   rD   r¶   r-   Újoin)r&   ÚnhStrAllÚvalsr´   ÚnhStrs        r'   Ú__repr__zNoteHashWithReference.__repr__*  s   € Ø+ˆàˆØÔ#ð 	ð 	ˆAØˆEØ�S‰LˆEØ•S�  qÑ)Ô)Ñ*Ô*Ñ*ˆEØ�KŠK˜ÑÔÐÐØ�D—I’I˜d‘O”OÑ#ˆØ�C‰ˆØˆr)   N)r¨   r©   rª   r«   r(   r¸   rÀ   rN   r)   r'   r•   r•     sK   € € € € € ðð ð89ð 9ð 9ð)ð )ð )ðð ð ð ð r)   r•   c                  ó"   ‡ — e Zd ZdZˆ fd„Zˆ xZS )rp   zé
    >>> note1 = note.Note('C4')
    >>> nh = alpha.analysis.hasher.NoteHash((1, 2))
    >>> nh
    (1, 2)
    >>> a, b = nh
    >>> a
    1
    >>> b
    2
    >>> nh.__class__
    <... 'music21.alpha.analysis.hasher.NoteHash'>
    c                óp   •— t          t          | ¦  «                             | t          |¦  «        ¦  «        S rM   )Úsuperrp   Ú__new__r‡   )ÚclsÚtupElsÚ	__class__s     €r'   rÄ   zNoteHash.__new__F  s)   ø€ Ý•X˜sÑ#Ô#×+Ò+¨Cµ°v±´Ñ?Ô?Ð?r)   )r¨   r©   rª   r«   rÄ   Ú__classcell__)rÇ   s   @r'   rp   rp   8  sK   ø€ € € € € ðð ð@ð @ð @ð @ð @ð @ð @ð @ð @r)   rp   c                  óF   — e Zd Zd„ Zdd„Zd„ Zd„ Zd„ Zd„ Zd„ Z	d	„ Z
d
„ ZdS )ÚTestc                óB   — ddl m}  || t          ¦   «         ¦  «         d S )Nr   )ÚtestCopyAll)Úmusic21.test.commonTestrÌ   Úglobals)r&   rÌ   s     r'   ÚtestCopyAndDeepcopyzTest.testCopyAndDeepcopyK  s0   € Ø7Ð7Ð7Ð7Ð7Ð7Øˆ�D�'™)œ)Ñ$Ô$Ð$Ð$Ð$r)   é   c                óf   — ||k    p+t          |d|z  z  ¦  «        t          |d|z  z  ¦  «        k    S rž   r    r¢   s       r'   r¦   zTest._approximatelyEqualO  r§   r)   c                ó¾  ‡
— t          j        ¦   «         }t          j        d¦  «        }d|j        _        t          j        d¦  «        }t          j        d¦  «        }t          j        g d¢¦  «        }d|j        _        t          j        d¬¦  «        }| 	                    |¦  «         | 	                    |¦  «         | 	                    |¦  «         | 	                    |¦  «         | 	                    |¦  «         t          ¦   «         }g d¢}t          j        d	g d
¢¦  «        Š
ˆ
fd„|D ¦   «         }	|                      |                     |¦  «        |	¦  «         dS )zz
        test for hasher with basic settings: pitch, rounded duration, offset
        with notes, chord, and rest
        ÚC4ÚhalfzF#4zB-2©rÓ   ÚG4zE-5ç      ø?)r1   ))é<   ç       @ç        )éB   ç      ð?rÙ   )é.   rÜ   g      @)rØ   rÙ   ç      @)éC   rÙ   rÞ   )éK   rÙ   rÞ   )r   r×   g      @rp   ©ri   rn   ro   c                ó4   •— g | ]\  }}} ‰|||¬ ¦  «        ‘ŒS ©rá   rN   )ry   r´   ÚyrA   Ú	CNoteHashs       €r'   r|   z&Test.testBasicHash.<locals>.<listcomp>n  óF   ø€ ð Cð Cð CÙ )  A qð &˜I¨A¸À!ÐDÑDÔDð Cð Cð Cr)   N)r   ÚStreamr   r   r0   Útyper   r   r   r-   r
   rq   rr   ÚassertEqualr�   )r&   Ús1Únote1Únote2Únote3ÚcMinorrB   ÚhÚhashes_plain_numbersÚhashes_in_formatrå   s             @r'   ÚtestBasicHashzTest.testBasicHashV  s`  ø€ õ
 Œ]‰_Œ_ˆÝ”	˜$‘”ˆØ$ˆŒÔÝ”	˜%Ñ Ô ˆÝ”	˜%Ñ Ô ˆÝ”Ð0Ð0Ð0Ñ1Ô1ˆØ%ˆŒÔÝŒI CÐ(Ñ(Ô(ˆØ
�	Š	�%ÑÔÐØ
�	Š	�%ÑÔÐØ
�	Š	�%ÑÔÐØ
�	Š	�&ÑÔÐØ
�	Š	�!‰Œˆå‰HŒHˆð Oð  Oð  OÐåÔ*¨:Ð7VÐ7VÐ7VÑWÔWˆ	ðCð Cð Cð CØ-AðCñ Cô CÐð 	×Ò˜Ÿš bÑ)Ô)Ð+;Ñ<Ô<Ð<Ð<Ð<r)   c                ó^  ‡— t          j        ¦   «         }t          j        d¦  «        }d|j        _        t          j        g d¢¦  «        }d|j        _        t          j        g d¢¦  «        }d|j        _        |                     |¦  «         |                     |¦  «         |                     |¦  «         t          ¦   «         }d|_
        d|_        d|_        t          j        dg d	¢¦  «        Šg d
¢}ˆfd„|D ¦   «         }|                      |                     |¦  «        |¦  «         dS )zY
        test to make sure that hashing works when trying to hash chord as chord
        rÓ   rÔ   rÕ   )rÓ   rÖ   ÚE4ÚwholeTFrp   ©ri   rm   rn   ro   )©rØ   ra   rÙ   rÚ   ©r;   ú<037>rÙ   rÙ   )r;   rù   rÞ   rÞ   c                ó8   •— g | ]\  }}}} ‰||||¬ ¦  «        ‘ŒS )rö   rN   ©ry   r´   rä   rA   r£   rå   s        €r'   r|   z>Test.testHashChordsAsChordsPrimeFormString.<locals>.<listcomp>‰  sK   ø€ ð Fð Fð FÙ ,  A q¨!ð &˜I¨A¸qÈ1ÐUVÐWÑWÔWð Fð Fð Fr)   N)r   rç   r   r   r0   rè   r   r   r-   r
   r   r   r    rq   rr   ré   r�   )	r&   rê   rë   rî   ÚcMajorrï   rð   rñ   rå   s	           @r'   Ú%testHashChordsAsChordsPrimeFormStringz*Test.testHashChordsAsChordsPrimeFormStrings  sS  ø€ õ Œ]‰_Œ_ˆÝ”	˜$‘”ˆØ$ˆŒÔÝ”Ð0Ð0Ð0Ñ1Ô1ˆØ%ˆŒÔÝ”Ð/Ð/Ð/Ñ0Ô0ˆØ&ˆŒÔØ
�	Š	�%ÑÔÐØ
�	Š	�&ÑÔÐØ
�	Š	�&ÑÔÐÝ‰HŒHˆØ#ˆÔØ#ˆÔØ $ˆÔÝÔ*¨:ð 8Nð 8Nð 8Nñ Oô Oˆ	ð 8ð  8ð  8ÐðFð Fð Fð FØ0DðFñ Fô FÐð 	×Ò˜Ÿš bÑ)Ô)Ð+;Ñ<Ô<Ð<Ð<Ð<r)   c                ól  ‡— t          j        ¦   «         }t          j        d¦  «        }d|j        _        t          j        g d¢¦  «        }d|j        _        t          j        g d¢¦  «        }d|j        _        |                     |¦  «         |                     |¦  «         |                     |¦  «         t          ¦   «         }d|_
        d|_        d|_        d|_        t          j        dg d	¢¦  «        Šg d
¢}ˆfd„|D ¦   «         }|                      |                     |¦  «        |¦  «         d S )NrÓ   rÔ   rÕ   )rÓ   rÖ   ÚE3rõ   TFrp   ©ri   rl   rn   ro   )r÷   rø   )r;   z<047>rÞ   rÞ   c                ó8   •— g | ]\  }}}} ‰||||¬ ¦  «        ‘ŒS )r   rN   rû   s        €r'   r|   z:Test.testHashChordsAsChordsNormalOrder.<locals>.<listcomp>¢  sK   ø€ ð Fð Fð FÙ ,  A q¨!ð &˜I¨AÀÈQÐWXÐYÑYÔYð Fð Fð Fr)   )r   rç   r   r   r0   rè   r   r   r-   r
   r   r   r    r   rq   rr   ré   r�   )	r&   Ús2rë   rî   rü   rï   rð   rñ   rå   s	           @r'   Ú!testHashChordsAsChordsNormalOrderz&Test.testHashChordsAsChordsNormalOrderŽ  sW  ø€ ÝŒ]‰_Œ_ˆÝ”	˜$‘”ˆØ$ˆŒÔÝ”Ð0Ð0Ð0Ñ1Ô1ˆØ%ˆŒÔÝ”Ð/Ð/Ð/Ñ0Ô0ˆØ&ˆŒÔØ
�	Š	�%ÑÔÐØ
�	Š	�&ÑÔÐØ
�	Š	�&ÑÔÐÝ‰HŒHˆØ#ˆÔØ#ˆÔØ %ˆÔØ"&ˆÔÝÔ*¨:ð 8Nð 8Nð 8Nñ Oô Oˆ	ð 8ð  8ð  8ÐðFð Fð Fð FØ0DðFñ Fô FÐà×Ò˜Ÿš bÑ)Ô)Ð+;Ñ<Ô<Ð<Ð<Ð<r)   c                óF  ‡ ‡— t          j        ¦   «         }t          j        d¦  «        }t          j        d¦  «        }t	          j        ddg¦  «        }d|j        _        d|j        _        d|j        _        | 	                    |¦  «         | 	                    |¦  «         | 	                    |¦  «         t          ¦   «         }d|_        t          j        dg d¢¦  «        Šg d	¢}ˆfd
„|D ¦   «         }|                     |¦  «        }|d         d         |d         d         |d         d         |d         d         g}	|d         d         |d         d         |d         d         |d         d         g}
t          ˆ fd„t!          |	|
¦  «        D ¦   «         ¦  «        sJ ‚d S )NrÓ   rÖ   çºI+‡ü?çUUUUUUå?rÔ   Frp   rá   ))rØ   r  rÚ   )rß   r  r  )rØ   rÙ   ç2z[Öê˜@)rß   rÙ   r  c                ó4   •— g | ]\  }}} ‰|||¬ ¦  «        ‘ŒS rã   rN   ©ry   r´   rA   r£   rå   s       €r'   r|   z2Test.testHashUnroundedDuration.<locals>.<listcomp>¶  ræ   r)   r   rÐ   r;   é   c              3  ó,   •K  — | ]} ‰j         |Ž V — Œd S rM   )r¦   )ry   Úvaluesr&   s     €r'   ú	<genexpr>z1Test.testHashUnroundedDuration.<locals>.<genexpr>¾  sI   øè è € ð Að AØð ,�4Ô+¨VÐ4ð Að Að Að Að Að Ar)   )r   rç   r   r   r   r   r0   r1   rè   r-   r
   r   rq   rr   r�   ÚallÚzip)r&   Ús3rë   rì   rî   rï   rð   rñ   Úh3Ú	h3_floatsÚanswers_floatsrå   s   `          @r'   ÚtestHashUnroundedDurationzTest.testHashUnroundedDuration¦  sÜ  øø€ ÝŒ]‰_Œ_ˆÝ”	˜$‘”ˆÝ”	˜$‘”ˆÝ”˜d D˜\Ñ*Ô*ˆØ',ˆŒÔ$Ø',ˆŒÔ$Ø%ˆŒÔØ
�	Š	�%ÑÔÐØ
�	Š	�%ÑÔÐØ
�	Š	�&ÑÔÐÝ‰HŒHˆØ#(ˆÔ ÝÔ*¨:Ð7VÐ7VÐ7VÑWÔWˆ	ð :ð  :ð  :ÐðCð Cð Cð CØ-AðCñ Cô CÐà�\Š\˜"ÑÔˆØ˜”U˜1”X˜r !œu Qœx¨¨A¬¨q¬°2°a´5¸´8Ð<ˆ	Ø*¨1Ô-¨aÔ0Ø*¨1Ô-¨aÔ0Ø*¨1Ô-¨aÔ0Ø*¨1Ô-¨aÔ0ð2ˆõ ð Að Að Að AÝ!$ Y°Ñ!?Ô!?ðAñ Aô Añ Aô Að 	Að 	Að Að 	Að 	Ar)   c                ó®  ‡— t          j        ¦   «         }t          j        d¦  «        }t          j        d¦  «        }t	          j        ddg¦  «        }d|j        _        d|j        _        d|j        _        | 	                    |¦  «         | 	                    |¦  «         | 	                    |¦  «         t          ¦   «         }d|_        t          j        dg d¢¦  «        Šg d	¢}ˆfd
„|D ¦   «         }|                     |¦  «        }|                      ||¦  «         d|_        g d¢}	|                     |¦  «        }
|                      |
|	¦  «         d S )NrÓ   rÖ   r  r  rÔ   Trp   rá   ))rØ   ç     €ü?rÚ   )rß   g      å?r  )rØ   rÙ   ç     €@)rß   rÙ   r  c                ó4   •— g | ]\  }}} ‰|||¬ ¦  «        ‘ŒS rã   rN   r	  s       €r'   r|   z0Test.testHashRoundedDuration.<locals>.<listcomp>Ò  ræ   r)   é   ))rØ   ç      ü?rÚ   )rß   g      ä?r  )rØ   rÙ   ç      @)rß   rÙ   r  )r   rç   r   r   r   r   r0   r1   rè   r-   r
   r   rq   rr   r�   ré   r   )r&   r  rë   rì   rî   rï   rð   rñ   r  Únew_hashes_in_formatÚh4rå   s              @r'   ÚtestHashRoundedDurationzTest.testHashRoundedDurationÁ  sl  ø€ ÝŒ]‰_Œ_ˆÝ”	˜$‘”ˆÝ”	˜$‘”ˆÝ”˜d D˜\Ñ*Ô*ˆØ',ˆŒÔ$Ø',ˆŒÔ$Ø%ˆŒÔØ
�	Š	�%ÑÔÐØ
�	Š	�%ÑÔÐØ
�	Š	�&ÑÔÐÝ‰HŒHˆØ#'ˆÔ åÔ*¨:Ð7VÐ7VÐ7VÑWÔWˆ	ð 3ð  3ð  3ÐðCð Cð Cð CØ-AðCñ Cô CÐà�\Š\˜"ÑÔˆØ×Ò˜Ð-Ñ.Ô.Ð.ØˆŒð 0ð  0ð  0Ðð �\Š\˜"ÑÔˆØ×Ò˜Ð1Ñ2Ô2Ð2Ð2Ð2r)   c                ó²  — t          j        ¦   «         }t          j        d¦  «        }t          j        d¦  «        }|                     ||g¦  «         t          ¦   «         }d|_        |                     |¦  «        }|d         j        }|d         j        }|  	                    |j
        |j
        ¦  «         |  	                    |j
        |j
        ¦  «         d S )NrÓ   rÖ   Tr   r;   )r   rç   r   r   r-   r
   r   r�   r’   ré   Úid)r&   ru   rë   rì   rï   ÚhashesÚnote1refÚnote2refs           r'   ÚtestReferenceszTest.testReferencesÞ  s¯   € ÝŒM‰OŒOˆÝ”	˜$‘”ˆÝ”	˜$‘”ˆØ	�Š�%˜�Ñ Ô Ð å‰HŒHˆØ!ˆÔØ—’˜a‘”ˆà˜!”9Ô&ˆØ˜!”9Ô&ˆà×Ò˜œ 8¤;Ñ/Ô/Ð/Ø×Ò˜œ 8¤;Ñ/Ô/Ð/Ð/Ð/r)   c                óR  — t          j        ¦   «         }t          j        d¦  «        }t          j        d¦  «        }t          j        d¦  «        }|                     |||g¦  «         t          ¦   «         }d|_        d|_        d|_        d|_	        | 
                    |¦  «        }d S )NÚE5ÚD5ÚA5TF)r   rç   r   r   r-   r
   r   r   r   r   r�   )r&   ru   rë   rì   rí   rï   Úunused_hashess          r'   ÚtestIntervalszTest.testIntervalsî  s†   € ÝŒM‰OŒOˆÝ”	˜$‘”ˆÝ”	˜$‘”ˆÝ”	˜$‘”ˆØ	�Š�%˜ Ð&Ñ'Ô'Ð'Ý‰HŒHˆØˆŒØˆŒØˆŒØ%)ˆÔ"ØŸš Q™œˆˆˆr)   N)rÐ   )r¨   r©   rª   rÏ   r¦   rò   rý   r  r  r  r$  r*  rN   r)   r'   rÊ   rÊ   J  s§   € € € € € ð%ð %ð %ðJð Jð Jð Jð=ð =ð =ð:=ð =ð =ð6=ð =ð =ð0Að Að Að63ð 3ð 3ð:0ð 0ð 0ð (ð (ð (ð (ð (r)   rÊ   c                  ó   — e Zd ZdZd„ Zd„ ZdS )ÚTestExternalTc                ó@  — ddl m} t          ¦   «         }d|_        d|_        |                     dd¦  «        j                             ¦   «         }|                     dd¦  «        j                             ¦   «         }|                     d¦  «        j                             ¦   «         }|                     |¦  «        }|                     |¦  «        }|                     |¦  «        }| j	        r³t          t          j        ||¬¦  «                             ¦   «         ¦  «         t          t          j        ||¬¦  «                             ¦   «         ¦  «         t          t          j        ||¬¦  «                             ¦   «         ¦  «         | 	                    ¦   «          d|_        d	|_        d	|_        |                     |¦  «        }|                     |¦  «        }|                     |¦  «        }| j	        r¡t          t          j        ||¬¦  «                             ¦   «         ¦  «         t          t          j        ||¬¦  «                             ¦   «         ¦  «         t          t          j        ||¬¦  «                             ¦   «         ¦  «         d S d S )
Nr   ©ÚcorpusFÚ
schoenbergé   rÐ   úbwv66.6©r£   r¤   T)Úmusic21r/  r
   r   r   ÚparseÚpartsÚfirstr�   ÚshowÚprintÚdifflibÚSequenceMatcherÚratior   )	r&   r/  rï   rê   r  r  Úhashes1Úhashes2Úhashes3s	            r'   Ú	testBvSvSzTestExternal.testBvSvS?  s:  € Ø"Ð"Ð"Ð"Ð"Ð"Ý‰HŒHˆØˆŒØˆŒØ�\Š\˜,¨Ñ*Ô*Ô0×6Ò6Ñ8Ô8ˆØ�\Š\˜,¨Ñ*Ô*Ô0×6Ò6Ñ8Ô8ˆØ�\Š\˜)Ñ$Ô$Ô*×0Ò0Ñ2Ô2ˆØ—,’,˜rÑ"Ô"ˆØ—,’,˜rÑ"Ô"ˆØ—,’,˜rÑ"Ô"ˆàŒ9ð 	Ý•'Ô)¨G°wÐ?Ñ?Ô?×EÒEÑGÔGÑHÔHÐHÝ•'Ô)¨G°wÐ?Ñ?Ô?×EÒEÑGÔGÑHÔHÐHÝ•'Ô)¨G°wÐ?Ñ?Ô?×EÒEÑGÔGÑHÔHÐHØ�GŠG‰IŒIˆIàˆŒØˆŒØˆŒà—,’,˜rÑ"Ô"ˆØ—,’,˜rÑ"Ô"ˆØ—,’,˜rÑ"Ô"ˆàŒ9ð 	IÝ•'Ô)¨G°wÐ?Ñ?Ô?×EÒEÑGÔGÑHÔHÐHÝ•'Ô)¨G°wÐ?Ñ?Ô?×EÒEÑGÔGÑHÔHÐHÝ•'Ô)¨G°wÐ?Ñ?Ô?×EÒEÑGÔGÑHÔHÐHÐHÐHð	Ið 	Ir)   c                ó¼  — ddl m} t          ¦   «         }|                     d¦  «        j                             ¦   «         }|                     d¦  «        j                             ¦   «                              d¦  «        }|                     |¦  «        }|                     |¦  «        }| j        r5t          t          j        ||¬¦  «                             ¦   «         ¦  «         d|_        d|_        |                     |¦  «        }|                     |¦  «        }| j        r7t          t          j        ||¬¦  «                             ¦   «         ¦  «         d S d S )Nr   r.  r2  ÚM2r3  TF)r4  r/  r
   r5  r6  r7  Ú	transposer�   r8  r9  r:  r;  r<  r   r   )r&   r/  rï   r  Ús4r?  Úhashes4s          r'   ÚtestIntervalzTestExternal.testInterval^  s:  € Ø"Ð"Ð"Ð"Ð"Ð"Ý‰HŒHˆØ�\Š\˜)Ñ$Ô$Ô*×0Ò0Ñ2Ô2ˆØ�\Š\˜)Ñ$Ô$Ô*×0Ò0Ñ2Ô2×<Ò<¸TÑBÔBˆà—,’,˜rÑ"Ô"ˆØ—,’,˜rÑ"Ô"ˆàŒ9ð 	IÝ•'Ô)¨G°wÐ?Ñ?Ô?×EÒEÑGÔGÑHÔHÐHà%)ˆÔ"ØˆŒà—,’,˜rÑ"Ô"ˆØ—,’,˜rÑ"Ô"ˆàŒ9ð 	IÝ•'Ô)¨G°wÐ?Ñ?Ô?×EÒEÑGÔGÑHÔHÐHÐHÐHð	Ið 	Ir)   N)r¨   r©   rª   r8  r@  rF  rN   r)   r'   r,  r,  ü  s@   € € € € € Ø€DðDIð Ið Ið>Ið Ið Ið Ið Ir)   r,  Ú__main__)Ú
__future__r   rq   r:  Úunittestr4  r   r   r   r   r   r
   r•   r‡   rp   ÚTestCaserÊ   r,  r¨   ÚmainTestrN   r)   r'   ú<module>rL     sÐ  ðð #Ð "Ð "Ð "Ð "Ð "à Ð Ð Ð Ø €€€Ø €€€à Ð Ð Ð Ð Ð Ø Ð Ð Ð Ð Ð Ø Ð Ð Ð Ð Ð Ø Ð Ð Ð Ð Ð Ø Ð Ð Ð Ð Ð ðeJð eJð eJð eJð eJñ eJô eJð eJðT4ð 4ð 4ð 4ð 4ñ 4ô 4ð 4ðn@ð @ð @ð @ð @ˆuñ @ô @ð @ð$o(ð o(ð o(ð o(ð o(ˆ8Ôñ o(ô o(ð o(ðduIð uIð uIð uIð uI�8Ô$ñ uIô uIð uIðp ˆzÒÐØ€N€N€NØ€GÔ�TÑÔÐÐÐð Ðr)   