function [resSEFF,resSEFF_CDF] = CMCQN_CS_respTime_SEFF(processors, SEFF, Rfull, RT_CDF_SEFF, Xfull, verbose)
% A = CMCQN_CS_RESPTIME_SEFF(P,SEFF,R) determines the mean response times of 
% the services defined as SEFF in an LQN model derived from a PCM
% instance, or equivalent. P contains the list of processors in the LQN model and 
% Rfull the mean response times for each class and station in the associated 
% Closed Multi-Class Queueing Network with Class Switching (CMCQNCS). 
% More details on this type of queueing networks can be found 
% on the LINE documentation, available at http://code.google.com/p/line
% 
% Parameters: 
% processors:   list of processors in the LQN model
% SEFF:         SEFF structure describing all the SEFF services in an LQN-PCM model
% Rfull:        mean response times for each class and station in the
%               associated queueing network model 
% RT_CDF_fullP: response time distributions for each SEFF
% Xfull:        throughput for each request class in the model
% verbose:      1 for screen output
% 
% Ouput:
% resSEFF:      mean response times of the SEFF services 
%
% Copyright (c) 2012-2015, Imperial College London 
% All rights reserved.

np = length(processors); 
nonEmptyProc = zeros(np,1);
resSEFF = cell(np,3);
for i = 1:np
    if SEFF(i).numCalls > 0 && ~strcmp(processors(i).tasks.scheduling, 'ref')
        resSEFF{i,1} = processors(i).name;
        respTime = 0;
        % for each activity in this processor/SEFF
        for j = 1:size(processors(i).tasks.actNames,1)
            % if this activity called any resource-demanding activity
            if ~isempty(SEFF(i).actCalls(j).actNames)
                temp = 0;
                for k = 1:size(SEFF(i).actCalls(j).actNames,1)
                    % add mean resp time for the associated (proc,class)
                    % multiply by the probability of calling this
                    % (proc,class) in this activity call
                    temp = temp + Rfull(SEFF(i).actCalls(j).procs(k), SEFF(i).actCalls(j).classes(k) ) * SEFF(i).actCalls(j).probs(k); 
                end
                temp = temp * processors(i).tasks.actProbs(j); % multiply by the probability of visiting this activity
                respTime = respTime + temp; 
            end
        end
        respTime = respTime/SEFF(i).numCalls; % divide by the number of calls to this processor -> all activities
        resSEFF{i,2} = respTime;
        nonEmptyProc(i) = 1;
        
        %throughput computation 
        numActs = size(processors(i).tasks.actNames,1); 
        % indexes of current activities
        currActs = zeros(1,numActs);
        currActs(processors(i).tasks.initActID) = 1; 
        % first layer of activities with actual calls
        firstLayerActs = zeros(1,numActs);
        firstLayerTput = zeros(1,numActs);
        ready = false;
        while ~(sum(currActs)==0) && ~ready
            nextActs = zeros(1,numActs);
            for j = find(currActs > 0)
                nextActs = nextActs + processors(i).tasks.actGraph(j,:)>0; 
            end
            for j = find(nextActs > 0)
                % add activities with actual calls
                if ~isempty(SEFF(i).actCalls(j).actNames)
                    firstLayerActs(j) = processors(i).tasks.actProbs(j);
                    firstLayerTput(j) = Xfull(SEFF(i).actCalls(j).procs(1), SEFF(i).actCalls(j).classes(1) ); 
                    % remove these activities from further analysis
                    nextActs(j) = 0;
                end
            end
            if sum(firstLayerActs) == 1
                ready = true;
            end
            currActs = nextActs;
        end
        resSEFF{i,3} = sum(firstLayerActs.*firstLayerTput);
    end
end
resSEFF = reshape({resSEFF{nonEmptyProc==1,:}}',sum(nonEmptyProc),3);

if ~isempty(RT_CDF_SEFF)
    resSEFF_CDF = reshape({RT_CDF_SEFF{nonEmptyProc==1,:}}',sum(nonEmptyProc),2);
else
    resSEFF_CDF = [];
end
