<commit_before><?php

namespace App\Helpers\ExerciseConfig\Compilation;

use App\Exceptions\ExerciseConfigException;
use App\Helpers\ExerciseConfig\Compilation\Tree\Node;
use App\Helpers\ExerciseConfig\Compilation\Tree\RootedTree;
use App\Helpers\ExerciseConfig\Pipeline\Box\Box;
use App\Helpers\ExerciseConfig\Pipeline\Box\BoxMeta;
use App\Helpers\ExerciseConfig\Pipeline\Box\CopyFileToDirBox;
use App\Helpers\ExerciseConfig\Pipeline\Box\CopyFilesToDirBox;
use App\Helpers\ExerciseConfig\Pipeline\Box\MkdirBox;
use App\Helpers\ExerciseConfig\Pipeline\Box\DumpResultsBox;
use App\Helpers\ExerciseConfig\Pipeline\Ports\Port;
use App\Helpers\ExerciseConfig\Pipeline\Ports\PortMeta;
use App\Helpers\ExerciseConfig\Variable;
use App\Helpers\ExerciseConfig\VariableTypes;
use Nette\Utils\Random;


/**
 * Internal exercise configuration compilation service. Handles creation of the directories used during execution and
 * creating dumping boxes for all created directories. Alongside that for optimized boxes the name of the directory in
 * which they will be processed has to be found.
 * @note Should be called after optimisation.
 */
class DirectoriesResolver {

  /**
   * Process single node in context of directories resolver.
   * Basically we need to track directories which should be created.
   * @param Node $node
   * @param string $directoryName
   * @param array $directoriesNodes
   */
  private function processNode(Node $node, string $directoryName, array &$directoriesNodes) {
    // set the directory to the current box in node
    if ($node->getBox()) {
      $node->getBox()->setDirectory($directoryName);
    }

    // all nodes for each directory are saved and further dependencies
    // on mkdir tasks are set on them
    if (!array_key_exists($directoryName, $directoriesNodes)) {
      $directoriesNodes[$directoryName] = [];
    }
    $directoriesNodes[$directoryName][] = $node;

    // set directory on variable, this is used during creation of copy tasks
    foreach ($node->getBox()->getOutputPorts() as $outputPort) {
      $variableValue = $outputPort->getVariableValue();
      if ($variableValue && $variableValue->isFile()) {
        $outputPort->getVariableValue()->setDirectory($directoryName);
      }
    }
  }

  /**
   * Go through the tree from current node and determine the name of the directory in which the node should be
   * executed in. The name is composed of categories of the boxes.
   * @param Node $current
   * @return string
   */
  private function findOptimizedNodesDirectory(Node $current): string {
    $name = "";
    while ($current->getTestId() === null) {
      $category = $current->getBox() ? $current->getBox()->getCategory() : "";
      $name .= !empty($category) ? $category . "_" : "";

      if (count($current->getChildren()) < 1) {
        break;
      }
      $current = current($current->getChildren());
    }

    return $name . Random::generate(10);
  }
<commit_msg>Input variables which does not have output box, have to have proper directory set in DirectoriesResolver<commit_after><?php

namespace App\Helpers\ExerciseConfig\Compilation;

use App\Exceptions\ExerciseConfigException;
use App\Helpers\ExerciseConfig\Compilation\Tree\Node;
use App\Helpers\ExerciseConfig\Compilation\Tree\RootedTree;
use App\Helpers\ExerciseConfig\Pipeline\Box\Box;
use App\Helpers\ExerciseConfig\Pipeline\Box\BoxMeta;
use App\Helpers\ExerciseConfig\Pipeline\Box\CopyFileToDirBox;
use App\Helpers\ExerciseConfig\Pipeline\Box\CopyFilesToDirBox;
use App\Helpers\ExerciseConfig\Pipeline\Box\MkdirBox;
use App\Helpers\ExerciseConfig\Pipeline\Box\DumpResultsBox;
use App\Helpers\ExerciseConfig\Pipeline\Ports\Port;
use App\Helpers\ExerciseConfig\Pipeline\Ports\PortMeta;
use App\Helpers\ExerciseConfig\Variable;
use App\Helpers\ExerciseConfig\VariableTypes;
use Nette\Utils\Random;


/**
 * Internal exercise configuration compilation service. Handles creation of the directories used during execution and
 * creating dumping boxes for all created directories. Alongside that for optimized boxes the name of the directory in
 * which they will be processed has to be found.
 * @note Should be called after optimisation.
 */
class DirectoriesResolver {

  /**
   * Process single node in context of directories resolver.
   * Basically we need to track directories which should be created.
   * @param Node $node
   * @param string $directoryName
   * @param array $directoriesNodes
   */
  private function processNode(Node $node, string $directoryName, array &$directoriesNodes) {
    // set the directory to the current box in node
    if ($node->getBox()) {
      $node->getBox()->setDirectory($directoryName);
    }

    // all nodes for each directory are saved and further dependencies
    // on mkdir tasks are set on them
    if (!array_key_exists($directoryName, $directoriesNodes)) {
      $directoriesNodes[$directoryName] = [];
    }
    $directoriesNodes[$directoryName][] = $node;

    foreach ($node->getBox()->getInputPorts() as $inputPort) {
      $variableValue = $inputPort->getVariableValue();
      if ($variableValue && $variableValue->isFile() &&
          $variableValue->getDirectory() === null) {
        // set directory only if it was not set by processing previous node
        // (this effectively means that the variable has no output box)
        $inputPort->getVariableValue()->setDirectory($directoryName);
      }
    }

    // set directory on variable, this is used during creation of copy tasks
    foreach ($node->getBox()->getOutputPorts() as $outputPort) {
      $variableValue = $outputPort->getVariableValue();
      if ($variableValue && $variableValue->isFile()) {
        $outputPort->getVariableValue()->setDirectory($directoryName);
      }
    }
  }

  /**
   * Go through the tree from current node and determine the name of the directory in which the node should be
   * executed in. The name is composed of categories of the boxes.
   * @param Node $current
   * @return string
   */
  private function findOptimizedNodesDirectory(Node $current): string {
    $name = "";
    while ($current->getTestId() === null) {
      $category = $current->getBox() ? $current->getBox()->getCategory() : "";
      $name .= !empty($category) ? $category . "_" : "";

      if (count($current->getChildren()) < 1) {
        break;
      }
      $current = current($current->getChildren());
    }

    return $name . Random::generate(10);
  }

{'fraction_non_alphanumeric': 0.11254469143478937, 'fraction_numerical': 0.000932690812995492, 'mean_word_length': 3.8890577507598785, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4625961', 'n_tokens_mistral': 1770, 'n_tokens_neox': 1762, 'n_words': 513}