import doctest

class Instrument():
    '''Base class for all objects inheriting from the Instrument class.
    '''

    def __init__(self, objectName=None, soundingRange=None, transposition=None, extendedTechniques=None):
        '''Instantiates an Instrument object, taking in values for the name,
        range, transposition, and extended techniques.

        objectName must be a string, soundingRange must be a list of strings,
        transposition should be an integer, and extendedTechniques must be a list of strings.
        '''
        self.name = objectName
        self.soundingRange = soundingRange
        self.transposition = transposition
        self.extendedTechniques = extendedTechniques


    def setSoundingRange(self, lowPitch, highPitch):
        '''Takes in a list containing two pitches as strings in letter name and octave formate (ie 'C4')
        and sets the first element of self.soundingRange (or self.soundingRange[0]) to lowPitch and the second
        element of self.soundingRange to highPitch.

        >>> foo = Instrument()
        >>> foo.setSoundingRange('A3', 'G5')
        >>> foo.getSoundingRange()
        ['A3', 'G5']
        
        ****AS PART OF YOUR ASSIGNMENT, PUT MORE TESTS HERE***
        '''
        self.soundingRange = [lowPitch, highPitch]

    def getSoundingRange(self):
        '''Returns a list containing the highest and lowest notes that are
        feasible to play.
        '''
        return self.soundingRange



    def setTransposition(self, interval):
        '''Sets the transposition of the instrument to interval, which is a
        positive or negative interger representing number of semitones.
        '''
        self.transposition = interval

    def getTransposition(self):
        '''Returns the transposition of the instrument, which is a
        positive or negative interger representing number of semitones.
        '''
        return self.transposition



    def setName(self, value):
        '''Sets the name of the instrument to value, which is a string.
        '''
        self.name = value

    def getName(self):
        '''Returns the name of the instrument, which is a string.
        '''
        return self.name



    def convertSoundingRangeToWritten(self):
        '''Returns a list containing the two pitches that have both been
        transposed from the sounding pitch by the interval contained in self.transposition.


	>>> vln1 = Violin('vln1')
	>>> vln1.convertSoundingRangeToWritten()
	['G3', 'G7']


        >>> clar1 = Clarinet_BFlat('clar1')
        >>> clar1.convertSoundingRangeToWritten()
        [***PUT CORRECT RESULTS HERE***]
        '''

        ### *** write this method (Hint: the script you wrote for 2 will be helpful here).
        ###     Be sure to write code that handles scenarios in which you receive input both in the form
        ###     of letter names/octave numbers (ie. 'G4') and midi numbers (i.e., 60). 

        ### *** make sure the test code works!

#____________________________________________________________________________
#
# String Instruments
#____________________________________________________________________________

class StringInstrument(Instrument):
    '''Class for objects belonging to the string instrument family; inherits
    from Instrument().
    '''
    
    def __init__(self, objectName=None, soundingRange=None, transposition=None, extendedTechniques=['pizzicato', 'harmonics', 'col lengo']):
            '''Instantiates a StringInstrument object, taking in values for the name,
            range, transposition, and extended techniques.

            objectName must be a string, soundingRange must be a list of strings,
            transposition should be an integer, and extendedTechniques must be a list of strings.
            '''
            self.name = objectName
            self.soundingRange = soundingRange
            self.transposition = transposition
            self.extendedTechniques = extendedTechniques


class Violin(StringInstrument):
    '''Class for objects that are violins. Inherits from StringInstrument()
    and Instrument().
    '''

    def __init__(self, objectName, soundingRange=['G3', 'G7'], transposition=0, extendedTechniques=['pizzicato', 'harmonics', 'col lengo']):
            '''Instantiates a StringInstrument object, taking in values for the name,
            range, transposition, and extended techniques.

            objectName must be a string, soundingRange must be a list of strings,
            transposition should be an integer, and extendedTechniques must be a list of strings.
            '''

            self.name = objectName
            self.soundingRange = soundingRange
            self.transposition = transposition
            self.extendedTechniques = extendedTechniques
        
class Viola(StringInstrument):
    '''Class for objects that are violas. Inherits from StringInstrument()
    and Instrument().
    '''

    def __init__(self, objectName, soundingRange=['C3', 'E6'], transposition=0, extendedTechniques=['pizzicato', 'harmonics', 'col lengo']):
            '''Instantiates a Viola object, taking in values for the name,
            range, transposition, and extended techniques.

            objectName must be a string, soundingRange must be a list of strings,
            transposition should be an integer, and extendedTechniques must be a list of strings.
            '''
            
            self.name = objectName
            self.soundingRange = soundingRange
            self.transposition = transposition
            self.extendedTechniques = extendedTechniques

        
class Cello(StringInstrument):
    '''Class for objects that are cellos. Inherits from StringInstrument()
    and Instrument().
    '''
    
    def __init__(self, objectName, soundingRange=['C2', 'G5'], transposition=0, extendedTechniques=['pizzicato', 'harmonics', 'col lengo']):
            '''Instantiates a Cello object, taking in values for the name,
            range, transposition, and extended techniques.

            objectName must be a string, soundingRange must be a list of strings,
            transposition should be an integer, and extendedTechniques must be a list of strings.
            '''
            
            self.name = objectName
            self.soundingRange = soundingRange
            self.transposition = transposition
            self.extendedTechniques = extendedTechniques


class DoubleBass(StringInstrument):
    '''Class for objects that are double basses. Inherits from StringInstrument()
    and Instrument().
    '''
    
    def __init__(self, objectName, soundingRange=['E1', 'B4'], transposition=-12, extendedTechniques=['pizzicato', 'harmonics', 'col lengo']):
            '''Instantiates a DoubleBass object, taking in values for the name,
            range, transposition, and extended techniques.

            objectName must be a string, soundingRange must be a list of strings,
            transposition should be an integer, and extendedTechniques must be a list of strings.
            '''
            
            self.name = objectName
            self.soundingRange = soundingRange
            self.transposition = transposition
            self.extendedTechniques = extendedTechniques




#____________________________________________________________________________
#
# Wind Instruments
#____________________________________________________________________________

class WindInstrument(Instrument):
    '''Class for objects belonging to the wind instrument family; inherits
    from Instrument().
    '''
    
    def __init__(self, objectName=None, soundingRange=None, transposition=None, extendedTechniques=['flutter-tongue', 'harmonics']):
            '''Instantiates a WindInstrument object, taking in values for the name,
            range, transposition, and extended techniques.

            objectName must be a string, soundingRange must be a list of strings,
            transposition should be an integer, and extendedTechniques must be a list of strings.
            '''
            self.name = objectName
            self.soundingRange = soundingRange
            self.transposition = transposition
            self.extendedTechniques = extendedTechniques


class Clarinet_BFlat(WindInstrument):
    '''Class for objects that are clarinets. Inherits from WindInstrument()
    and Instrument().
    '''

    def __init__(self, objectName, soundingRange=['D3', 'B-7'], transposition=-2, extendedTechniques=['flutter-tongue', 'harmonics', 'key clicks']):
            '''Instantiates a Clarinet_BFlat object, taking in values for the name,
            range, transposition, and extended techniques.

            objectName must be a string, soundingRange must be a list of strings,
            transposition should be an integer, and extendedTechniques must be a list of strings.
            '''
            
            self.name = objectName
            self.soundingRange = soundingRange
            self.transposition = transposition
            self.extendedTechniques = extendedTechniques


class Flute(WindInstrument):
    '''Class for objects that are flutes. Inherits from WindInstrument()
    and Instrument().
    '''
    
    def __init__(self, objectName, soundingRange=['C4', 'C7'], transposition=0, extendedTechniques=['flutter-tongue', 'harmonics']):
            '''Instantiates a Flute object, taking in values for the name,
            range, transposition, and extended techniques.

            objectName must be a string, soundingRange must be a list of strings,
            transposition should be an integer, and extendedTechniques must be a list of strings.
            '''
            
            self.name = objectName
            self.soundingRange = soundingRange
            self.transposition = transposition
            self.extendedTechniques = extendedTechniques

        

# *** Create two more subclasses of Instrument() and populate each subclass with various instruments.

#____________________________________________________________________________
#
# ____ Instruments
#____________________________________________________________________________


#____________________________________________________________________________
#
# _____ Instruments
#____________________________________________________________________________        


if __name__ == '__main__':
    import doctest
    doctest.testmod()

