function completed = main(varargin)
% main - runs all scripts to repeat the evaluation section of the paper
%
% results and plots will be saved to ./results
%
% Syntax:
%    completed = main()
%    completed = main(evalname)
%
% Inputs:
%    evalname - str, results are stored in ./results/<evalname>
%                    defaults to current date and time
%
% Outputs:
%    completed - boolean

% ------------------------------ BEGIN CODE -------------------------------

% 1. SETTINGS (update as needed) ------------------------------------------

% general settings
PAPER_TITLE = 'CORA'; % !
VENUE_NAME = 'ICLR';   % !
aux_runStartup(PAPER_TITLE,VENUE_NAME);

% also change 3. Scripts below

% 2. SETUP (nothing to change here) ---------------------------------------

% parse input
if nargin < 1
    evalname = 'cora';
else
    evalname = varargin{1};
end

% set up paths
basepath = '.';

% PATH                      VARIABLE        PURPOSE
% ./                        basepath        base path
% - ./code                  codepath        path to code
%   - ./cora                -               path to CORA
%   - ./scripts             -               path to auxiliary scripts
%   - ./main.m              -               main evaluation file (this file)
% - ./data                  datapath        path to data
% - ./results/<evalname>    resultspath     path to results
%   - ./evaluation          evalpath        path to store any evaluation results
%   - ./plots               plotspath       path to plots; any open figure after
%                                           each script will be stored there
%   - ./results.txt         -               logs all outputs to command window
%
[codepath,datapath,resultspath] = aux_setup(basepath,evalname);

% 3. RUN SCRIPTS (update as needed) ---------------------------------------

benchmarks = {...
    ... % VNN-COMP'24 benchmarks
    'acasxu_2023',...
    ... 'cifar100',...
    ... 'collins_rul_cnn_2023',...
    ... 'cora',...
    ... 'dist_shift_2023',...
    ... 'linearizenn',...
    ... 'metaroom_2023',... 
    ... 'safenlp',...
    ... 'tinyimagenet',....
    ... 'tllverifybench_2023', ...
    ... % VNN-COMP'22 benchmarks
    ... 'collins_rul_cnn',....
    ... 'mnist_fc',....
    ... 'oval21', ...
    ... 'reach_prob_density', ...
    ... 'rl_benchmarks', ...
};

scripts = { ...
    @() run_benchmarks(benchmarks,datapath,resultspath), 'run_benchmarks';
};

% run scripts
aux_runScripts(scripts)

% 4. WRAP UP (nothing to change here) -------------------------------------

aux_wrapup()
completed = true;

end


% Auxiliary functions -----------------------------------------------------

function aux_runStartup(PAPER_TITLE,VENUE_NAME)
    rng(1)
    warning off

    % show startup block
    disp(' ')
    aux_seperateLine()
    disp(' ')
    disp('Repeatability Package')
    fprintf("Paper: %s\n", PAPER_TITLE)
    fprintf("Venue: %s\n", VENUE_NAME)
    fprintf("Date: %s\n", datestr(datetime()))
    disp(' ')
    if ~isempty(which('CORAVERSION'))
        fprintf('CORA: %s\n', CORAVERSION)
    end
    fprintf('Matlab: %s\n', version)
    fprintf('System: %s\n', computer)
    fprintf('GPU available: %i', canUseGPU)
    disp(' ')
    aux_seperateLine()
    disp(' ')
    pause(2) % to make the startup block readable
end

function [codepath,datapath,resultspath] = aux_setup(basepath,evalname)

    % set up paths
    codepath = sprintf("%s/code", basepath);
    datapath = sprintf("%s/data", basepath);
    resultspath = sprintf("%s/results/%s/%s", basepath, ...
        datestr(datetime,'yymmdd-hhMMss'), evalname);
    mkdir(resultspath)
    
    % for smooth images (only for eps)
    set(0, 'defaultFigureRenderer', 'painters')
    
    % set up diary
    resultstxt = sprintf("%s/results.txt", resultspath);
    delete(resultstxt)
    diary(resultstxt)
end

function aux_runScripts(scripts,plotspath,plotSettings)
    % run scripts

    % process input
    n = size(scripts, 1);
    fprintf("Running %d scripts.. \n", n);
    disp(" ")
    
    for i = 1:n
        % run script i
        aux_seperateLine()
        disp(' ')
        script = scripts{i, 1};
        name = scripts{i, 2};
    
        try
            % call script
            fprintf("Running '%s' ...\n", name)
            script();
            disp(" ")
            fprintf("'%s' was run successfully!\n", name)
    
        catch ME
            % error handling
            disp(" ")
            fprintf("An ERROR occured during execution of '%s':\n", name);
            disp(ME.getReport())
            disp("Continuing with next script..")
        end
    
        disp(" ")
    end
end

function aux_wrapup()
    % wrap up evaluation
    aux_seperateLine()
    disp(" ")
    disp("Completed!")
    fprintf("Date: %s\n", datestr(datetime()))
    diary off;
end

function aux_seperateLine()
    disp ------------------------------------------------------------------
end

% ------------------------------ END OF CODE ------------------------------
