UC1:
    number:
        Use Case 1.1
    title:        
        Add RateConstant
    description:    
        User adds a RateConstant to the MarkovModel
    actor:
        User
    level: 
        User
    preconditions:  
        - 1. An instance of MarkovModel is initialized
        - 2. A RateConstant is initialized with valid parameters and stored in a smart_ptr
    postconditions: 
        - 1. The RateConstant is added to MarkovModel's map_of_states with its name as the key
    steps:
        - 1. The user calls MarkovModel's method addRateConstant() with a smart_ptr to the initialized RateConstant as the only arguement
        - 2. MarkovModel searches map_of_states for a RateConstant with the same key value as the RateConstant to be added; none exist
        - 3. The RateConstant is added to map_of_rates with its name as the key
    extensions:
        - 2a. A RateConstant with the same name exists in map_of_rates:
            - 1. System throws a runtime exception notifying the user that the RateConstant already exists
            - 2. map_of_rates is unmodified

UC2:
    number:
        Use Case 1.2
    title:        
        Add rate constant with duplicate name
    description:    
        User adds a RateConstant to the MarkovModel when a RateConstant with the same name already exists in map_of_states
    actor:
        User
    level:
        User
    preconditions:  
        - An instance of MarkovModel is initialized
        - A new RateConstant is initialized with valid parameters
        - A RateConstant with the same name as the new RateConstant already exists in map_of_states
    postconditions: 
        addRateConstant() throws a RateConstantAlreadyExists exception
    steps:
        - The user calls MarkovModel's method addRateConstant() with a pointer to the initialized RateConstant as the only parameter
        - MarkovModel searches map_of_states for a RateConstant with the key value matching the name of the new RateConstant; a match is found
        - addRateConstant() throws a RateConstantAlreadyExists exception 
        - The RateConstant passed to addRateConstant() is unmodified
        - map_of_states is unmodified 
    extensions:  

UC3:
    number:
        Use Case 1.3
    title:        
        Add a state
    description:    
        User adds a State to the MarkovModel
    actor:
        User
    level:
        User
    preconditions:  
        - An instance of MarkovModel is initialized
        - A State is initialized with valid parameters
    postconditions: 
        The state is added to MarkovModel's map_of_states with its name as the key
    steps:
        - The user calls MarkovModel's method addState() with a pointer to the initialized State as the only parameter
        - MarkovModel searches map_of_states for a State with the same key value as the State to be added; none exist
        - The State is added to map_of_states with its name as the key
    extensions:
        - A State with the same name exists in map_of_states before the call to addState()
        - map_of_states is full

UC4:
    number:
        Use Case 1.4
    title:        
        Add state with duplicate name
    description:    
        User adds a State to the MarkovModel when a State with the same name already exists in map_of_states
    actor:
        Modeler
    level:
        user
    preconditions:  
        - An instance of MarkovModel is initialized
        - A new State is initialized with valid parameters
        - A State with the same name as the new State already exists in map_of_states
    postconditions: 
        addState() throws a StateAlreadyExists exception
    steps:
        - The user calls MarkovModel's method addState() with a pointer to the initialized State as the only parameter
        - MarkovModel searches map_of_states for a State with the key value matching the name of the new State; a match is found
        - addState() throws a StateAlreadyExists exception 
        - The State passed to addState() is unmodified
        - map_of_states is unmodified 
    extensions:  

UC5:
    number:
        Use Case 1.5
    title:        
        Connect two states with a given rate
    description:    
        Create a connection between two states, a start state and end state, using a specified rate constant. 
        The states and rate constant do not have to be declared yet. A connection between the same state is valid.
    actor:
        Modeler
    level:
        user
    preconditions:  
        - An instance of MarkovModel is initialized
        - The States do not have to be added to the model yet.
        - The RateConstant does not have to be added to the model yet.
    postconditions: 
        The connection is added to MarkovModel's vector of connections
    steps:
        - The user calls MarkovModel's method addConnection()
        - The user passes the name of the start state, the name of the end state, and the name of the rate constant to the method
    extensions:  
        - The vector of connections is full

UC6:
    number:
        Use Case 1.6
    title:        
        Set the initial state
    description:    
        Sets the state with the specified name to be the MarkovModel's initial state.
    actor:
        Modeler
    level:
        user
    preconditions:  
        - An instance of MarkovModel is initialized
        - The state does not have to be added to the model yet
        - This is the first call to setInitialState()
    postconditions: 
        MarkovModel's initial_state_name will be set to the specified value
    steps:
        - The user calls MarkovModel's method setInitialState()
        - The user passes the name of the initial state to the method
    extensions:  
        - The method setInitialState() has already been called once.

UC7:
    number:
        Use Case 1.7
    title:        
        Reset the initial state
    description:    
        Resets the state with the specified name to be the MarkovModel's initial state when the initial state has already been set previously.
    actor:
        Modeler
    level:
        user
    preconditions:  
        - An instance of MarkovModel is initialized
        - The state does not have to be added to the model yet
        - This is not the first call to setInitialState()
    postconditions: 
        - MarkovModel's initial_state_name will be set to the specified value
        - The user will be warned that the initial state has been changed
    steps:
        - The user calls MarkovModel's method setInitialState()
        - The user passes the name of the initial state to the method
        - The system warns the user that the initial state has been changed
    extensions:  

UC8:
    number:
        Use Case 1.8
    title:        
        Validate MarkovModel
    description:    
        Validate the MarkovModel and notify the user of any mistakes
    actor:
        System
    level:
        system
    preconditions:  
        - An instance of MarkovModel is initialized
        - The user has declared the concentrations in the Experiment class
    postconditions: 
        The user is notified that the MarkovModel is correct
    steps:
        - The system calls MarkovModel's method validate()
        - The system checks that at least one connection has been defined
        - The system checks that every state name in the vector of connections has a corresponding entry in the map_of_states
        - If a state referenced in the vector of connections is not found in map_of_states, it is created and added as a non-conducting state, and the user is warned
        - The system checks that every rate constant name in the vector of connections has a corresponding entry in the map_of_rates
        - The system checks that the initial state has been defined
        - For every ligand gated RateConstant, the system checks that the concentration has been declared
        - The system notifies the user that the model has been validated
    extensions:  
        - No connections have been defined
        - A rate constant listed in the vector of connections cannot be located in the map_of_rates
        - An initial state has not been defined