Source: eval/driver/MatchingEvaluation.js

import {EvalConfig} from '../../config/EvalConfig.js';
import {AggregateMatchResult} from '../result/AggregateMatchResult.js';
import {Logger} from '../../util/Logger.js';
import {DirectoryScraper} from '../case/DirectoryScraper.js';
import {MatchTestCase} from '../case/MatchTestCase.js';
import {markdownTable} from 'markdown-table';
import {AbstractEvaluation} from './AbstractEvaluation.js';
import {MatchPipeline} from '../../diff/match/MatchPipeline.js';
import {CpeeMatchAdapter} from '../match_adapters/CpeeMatchAdapter.js';

/**
 * An evaluation of matching algorithms using predefined test cases.
 */
export class MatchingEvaluation extends AbstractEvaluation {
  /**
   * Construct a new MatchingEvaluation instance.
   * @param {Array<MatchAdapter>} adapters The adapters of the matching
   *     algorithms to be evaluated.
   */
  constructor(adapters = []) {
    super(adapters);
  }

  /**
   * Create a MatchingEvaluation instance with all available matching
   * algorithms.
   * @return {MatchingEvaluation}
   */
  static all() {
    const adapters = [];
    for (const matchMode of Object.values(MatchPipeline.MATCH_MODES)) {
      adapters.unshift(new CpeeMatchAdapter(matchMode));
    }
    return new MatchingEvaluation(adapters);
  }

  /**
   * @inheritDoc
   * @param {String} rootDir The path to the directory containing the predefined
   *     match test case directories. A match test case directory at least
   *     includes an old and new process tree as XML documents and a set of
   *     rules for the expected matching.
   * @override
   */
  evalAll(rootDir) {
    Logger.section('Matching Evaluation with Cases from ' + rootDir, this);

    const resultsPerAdapter = new Map();
    for (const adapter of this._adapters) {
      resultsPerAdapter.set(adapter, []);
    }

    // Collect all test case directories
    const caseDirs = DirectoryScraper.scrape(rootDir);
    for (const testCaseDir of caseDirs) {
      const testCase = MatchTestCase.from(testCaseDir);

      if (testCase == null) {
        Logger.warn(
            'Skipping empty match test case directory ' + testCaseDir,
            this,
        );
        continue;
      }

      for (const adapter of this._adapters) {
        Logger.info(
            'Running match test  case ' + testCase.name +
            ' for ' + adapter.displayName + '...',
            this,
        );

        const result = adapter.evalCase(testCase);
        resultsPerAdapter.get(adapter).push(result);
      }
    }

    const aggregateResults = [];
    for (const [, resultsList] of resultsPerAdapter) {
      aggregateResults.push(AggregateMatchResult.of(resultsList));
    }
    const table = [
      AggregateMatchResult.header(),
      ...aggregateResults.map((result) => result.values()),
    ];
    Logger.result('Results of the matching evaluation' + ':\n' +
        markdownTable(table), this);
  }
}