function out = obtainDecompositionData()
%
% data.caseNameIndex
% data.caseIndex
% data.nC
% data.nH
% data.nPS
% data.nPU
% data.validVector

thisDirName = which('obtainDecompositionData');
tmpIndex = find(thisDirName == filesep, 1, 'last');
thisDirName = thisDirName(1:tmpIndex);

data = load([thisDirName 'data/summarizedData.mat']);
data = data.data;
%! DEBUGGING:
%  changed data.mat to summarizedData.mat
%  now, data does not contain what is expected below
%/

fieldNameList = fieldnames(data);

%% Initialize data
nCase = length(fieldNameList);
out.nC  = nan([1 nCase]);
out.nH  = nan([1 nCase]);
out.nS  = nan([1 nCase]);
out.nPS = nan([1 nCase]);
out.nPU = nan([1 nCase]);
out.decValid                 = nan([1 nCase]);
out.caseNameIndex            = nan([1 nCase]);
out.caseIndex                = nan([1 nCase]);
out.timeDec                  = nan([1 nCase]);
out.timeDecGenerateValidCone = nan([1 nCase]);
out.timeDecSimplifyCone      = nan([1 nCase]);
out.timeDecDecompose         = nan([1 nCase]);
out.timeDecValidate          = nan([1 nCase]);
%
nMeas = length(fieldnames(data.(fieldNameList{1}).decMeas.measureData));
meas.nameIndex                 = nan([1 nMeas*nCase]);
meas.caseIndex                 = nan([1 nMeas*nCase]);
meas.dimension                 = nan([1 nMeas*nCase]);
meas.timeMixedVolumeTensor     = nan([1 nMeas*nCase]);
meas.timeConversionTensor      = nan([1 nMeas*nCase]);
meas.totalTimeUnifiedPartition = nan([1 nMeas*nCase]);
meas.timeUnifiedPartition      = nan([1 nMeas*nCase]);
meas.totalTimeSimplexPartition = nan([1 nMeas*nCase]);
meas.timeSimplexPartition      = nan([1 nMeas*nCase]);
meas.totalTimeMeasureDec       = nan([1 nMeas*nCase]);
meas.timeMeasureDec            = nan([1 nMeas*nCase]);
meas.totalTimeMeasureReal      = nan([1 nMeas*nCase]);
meas.timeMeasureReal           = nan([1 nMeas*nCase]);

%% Extract data
thisMeasureIndex = 0;
for iCase = 1:nCase
    % identify case name
    thisCaseName = data.(fieldNameList{iCase}).filename;
    indexGeneric = strfind(thisCaseName, 'generic_');
    if ~isempty(indexGeneric)
        thisCaseName = thisCaseName(9:end);
    end
    
    % find caseNameIndex
    if iCase == 1
        out.caseNameList{1} = thisCaseName;
    end
    [thisCaseNameIndex, out.caseNameList] = findStringListIndex(thisCaseName, ...
        out.caseNameList);
    out.caseNameIndex(iCase) = thisCaseNameIndex;
    
    % parameter
    out.caseIndex(iCase) = data.(fieldNameList{iCase}).par;
    
    % numbers
    out.nC(iCase) = data.(fieldNameList{iCase}).dec.nC;
    out.nH(iCase) = data.(fieldNameList{iCase}).dec.nH;
    out.nS(iCase) = data.(fieldNameList{iCase}).dec.nS;
    out.nPS(iCase) = data.(fieldNameList{iCase}).dec.nPS;
    out.nPU(iCase) = data.(fieldNameList{iCase}).dec.nPU;
    
    % valid
    out.decValid(iCase) = data.(fieldNameList{iCase}).decVerified;
    
    % timing
    out.timeDec(iCase) = data.(fieldNameList{iCase}).time.obtainDec;
    out.timeDecGenerateValidCone(iCase) = ...
        data.(fieldNameList{iCase}).dec.timingData.generateCone;
    out.timeDecSimplifyCone(iCase) = ...
        data.(fieldNameList{iCase}).dec.timingData.simplifyCone;
    out.timeDecDecompose(iCase) = ...
        data.(fieldNameList{iCase}).dec.timingData.decomposeCone;
    out.timeDecValidate(iCase) = data.(fieldNameList{iCase}).time.validateDec;
    
    % measures
    thisMeasureList = fieldnames(data.(fieldNameList{iCase}).decMeas.measureData);
    for iMeas = 1:length(thisMeasureList)
        thisIndex = (iCase-1)*nMeas + iMeas;
        thisMeas = data.(fieldNameList{iCase}).decMeas.measureData.(thisMeasureList{iMeas});
        thisMeasName = thisMeasureList{iMeas};
        % find measureNameIndex
        if iCase == 1 && iMeas == 1
            meas.nameList{1} = thisMeasName;
        end
        [thisMeasNameIndex, meas.nameList] = findStringListIndex(thisMeasName, ...
            meas.nameList);
        meas.nameIndex(thisIndex) = thisMeasNameIndex;
        thisMeasureIndex = thisMeasureIndex + 1;
        
        % case
        meas.caseIndex(thisIndex) = iCase;
        
        % dimension
        meas.dimension(thisIndex) = thisMeas.dim;
        
        % generation timing
        for iTime = 1:length(thisMeas.time)
            if iTime == 1
                 meas.timeMixedVolumeTensor(thisIndex) = ...
                     thisMeas.time(iTime).mixedVolumeTensor;
                 meas.timeConversionTensor(thisIndex) = ...
                     thisMeas.time(iTime).convertedTensor;
            else
                 meas.timeMixedVolumeTensor(thisIndex) = ...
                      meas.timeMixedVolumeTensor(thisIndex) + ...
                      thisMeas.time(iTime).mixedVolumeTensor;
                 meas.timeConversionTensor(thisIndex) = ...
                     meas.timeConversionTensor(thisIndex) + ...
                     thisMeas.time(iTime).convertedTensor; 
            end
        end
        meas.timeMixedVolumeTensor(thisIndex) = meas.timeMixedVolumeTensor(thisIndex) / ...
            thisMeas.timing.obtainMeasureNPar;
        meas.timeConversionTensor(thisIndex) = meas.timeConversionTensor(thisIndex) / ...
            thisMeas.timing.obtainMeasureNPar;
        
        % computing timings
        meas.totalTimeUnifiedPartition(thisIndex) = ...
            thisMeas.timing.obtainUnifiedTime;
        meas.timeUnifiedPartition(thisIndex) = ...
            thisMeas.timing.obtainUnifiedTime / ...
            thisMeas.timing.obtainUnifiedSamples;
        
        meas.totalTimeSimplexPartition(thisIndex) = ...
            thisMeas.timing.obtainSimplexTime;
        meas.timeSimplexPartition(thisIndex) = ...
            thisMeas.timing.obtainSimplexTime / ...
            thisMeas.timing.obtainSimplexSamples;
        
        meas.totalTimeMeasureDec(thisIndex) = ...
            thisMeas.timing.obtainMeasureTime;
        meas.timeMeasureDec(thisIndex) = ...
            thisMeas.timing.obtainMeasureTime / ...
            thisMeas.timing.obtainMeasureSamples / ...
            thisMeas.timing.obtainMeasureNPar;
        
        meas.totalTimeMeasureReal(thisIndex) = ...
            thisMeas.timing.realMeasureTime;
        meas.timeMeasureReal(thisIndex) = ...
            thisMeas.timing.realMeasureTime / ...
            thisMeas.timing.realMeasureSamples / ...
            thisMeas.timing.realMeasureNPar;
    
    end
end

% aggregation of data
meas.timeCoefficient = meas.timeMixedVolumeTensor + meas.timeConversionTensor;

disp(['The minimum total time for finding simplex partition is: ' ...
      num2str(min(meas.totalTimeSimplexPartition)) ' s']);
disp(['The minimum total time for finding unified partition is: ' ...
      num2str(min(meas.totalTimeUnifiedPartition)) ' s']);
disp(['The minimum total time for measure calculation is      : ' ...
      num2str(min(meas.totalTimeMeasureDec)) ' s']);
disp(['The minimum total time for real measure calculation is : ' ...
      num2str(min(meas.totalTimeMeasureReal)) ' s']);
  
out.meas = meas;


end
