function show_failures(rundir)

if nargin == 0
    rundir = 'p:\xbeach\skillbed\lastrun';
end

%% Gather all unfinished or crashed calculations
runfailures = struct(...
    'test',[],...
    'run',[],...
    'rundir',[],...
    'ErrorFile',[],...
    'ErrorFileExists',[],...
    'ErrorFileSize',[]);
runfailures(1) = [];

dirs = dir(rundir);
for idir = 3:length(dirs)
    if (dirs(idir).isdir)
        runfailures = findrunfailuresrecursive(runfailures,fullfile(rundir,dirs(idir).name),dirs(idir).name);
    end
end

%% Loop .sh files and look which test is run from which sh file
disp(' ');
disp('======== Skillbed failed runs ======================');
disp(' ');
files = dir(fullfile(rundir,'*.sh'));
for ifile = 1:length(files)
    %% Open file and search for subdirs
    fid = fopen(fullfile(rundir,files(ifile).name),'r');
    c = textscan(fid,'%s','delimiter',char(10));
    fclose(fid);
    lineid = cellfun(@strncmp,c{1},repmat({'subdirs'},size(c{1})),repmat({7},size(c{1})));
    line = c{1}{lineid};
    be = strfind(line,'"');
    if(length(be) ~= 2)
        continue;
    end
    subdirs = textscan(line(be(1)+1:be(2)-1),'%s','delimiter',' ');
    %% Register failures and reference to struct with failed calculations
    failures = false(size(subdirs{1}));
    ids = nan(size(subdirs{1}));
    for isub = 1:length(subdirs{1})
        tn = strsplit(subdirs{1}{isub}(2:end),'/');
        id = ismember({runfailures.test},tn(1)) & ismember({runfailures.run},tn(2:end));
        if any(id)
            failures(isub) = true;
            ids(isub) = find(id,1,'first');
        end
    end
    %% If any failures, display information
    if any(failures)
        %% Gather run information and file paths
        [~, basename,~] = fileparts(files(ifile).name);
        otherfiles = dir(fullfile(rundir,[basename,'.*']));
        ide = ~cellfun(@isempty,strfind({otherfiles.name},'.e'));
        if (sum(ide) > 1)
            ide = max(otherfiles(ide).datenum) == [otherfiles.datenum] & ide;
        end
        ido = ~cellfun(@isempty,strfind({otherfiles.name},'.o'));
        if (sum(ido) > 1)
            ido = max(otherfiles(ido).datenum) == [otherfiles.datenum] & ido;
        end
        fid = fopen(fullfile(rundir,[otherfiles(ido).name]),'r');
        node = textscan(fid,'%s',1);node = node{1}{1};
        fclose(fid);
        
        %% Display information
        disp(['Shell script on node ' node ': <a href="matlab: opentoline(''', fullfile(rundir,files(ifile).name), ''',1)">', files(ifile).name ,'</a> (',...
            '<a href="matlab: opentoline(''', fullfile(rundir,otherfiles(ide).name), ''',1)">', otherfiles(ide).name ,'</a>,',...
            '<a href="matlab: opentoline(''', fullfile(rundir,otherfiles(ido).name), ''',1)">', otherfiles(ido).name ,'</a>)']);
                
        disp(['    on node: ' node]);
        if (exist('xb_run_sh_scripts','file'))
            disp(['   <a href="matlab: xb_run_sh_scripts(''',rundir,''', ''' files(ifile).name ''', ''ssh_host'', ''h5'',''ssh_prompt'', true, ''queue'',''normal-i7'');">enqueue again</a>']);
        end
        
        disp('    failing runs:');
        for ifail = 1:length(failures)
            if (failures(ifail))
                str = ['       ','<a href="matlab: winopen(''', runfailures(ids(ifail)).rundir, ''')">',runfailures(ids(ifail)).test, ':', runfailures(ids(ifail)).run,'</a>'];
                if (runfailures(ids(ifail)).ErrorFileExists)
                    str = [str,'(<a href="matlab: opentoline(''', runfailures(ids(ifail)).ErrorFile, ''',1)">XBError.txt</a>)'];
                end
                if (exist(fullfile(runfailures(ids(ifail)).rundir,'xb.log'),'file'))
                    str = [str,'(<a href="matlab: opentoline(''', fullfile(runfailures(ids(ifail)).rundir,'xb.log'), ''',1)">xb.log</a>)'];
                end
                disp(str);
            end
        end
    end
end
disp(' ');
disp('============================================');
disp(' ');

end

function runfailures = findrunfailuresrecursive(runfailures,rundir,testname,runname)
if nargin < 4
    runname = '';
end

if (exist(fullfile(rundir,'params.txt'),'file'))
    %% Is actual rundir
    errorfilepath = fullfile(rundir,'XBerror.txt');
    errorFileExists = exist(errorfilepath,'file');
    if (exist(fullfile(rundir,'XBLog.txt'),'file') && ~errorFileExists)
        return;
    end
    runfailures(end+1) = struct(...
        'test',testname,...
        'run',runname,...
        'rundir',rundir,...
        'ErrorFile',errorfilepath,...
        'ErrorFileExists',errorFileExists,...
        'ErrorFileSize',0);
    if (exist(errorfilepath,'file'))
        file = dir(errorfilepath);
        runfailures(end).ErrorFileSize = file.bytes;
    end
else
    %% Try subdirs
    runs = dir(rundir);
    for irun = 3:length(runs)
        if (~runs(irun).isdir)
            continue;
        end
        runfailures = findrunfailuresrecursive(runfailures,fullfile(rundir,runs(irun).name),testname,runs(irun).name);
    end
end
end
