entityTypeManager = $entityTypeManager; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { // Instantiates this form class. return new static( // Load the service required to construct this class. $container->get('entity_type.manager'), ); } /** * Generates all fighting data for training NN. */ public function generateTrainingData(): CacheableJsonResponse { // Go get all fights. $all_fights = $this->entityTypeManager->getStorage('node')->loadByProperties(['type' => 'fight']); $training_data = []; foreach ($all_fights as $fight) { $train_array = [ 'input' => [], 'output' => [], ]; // Ensure we have a winner. if (!$fight->field_result->target_id) { continue; } // Extract fighters. $fighter_one_id = $fight->field_fighter_one->target_id; $fighter_two_id = $fight->field_fighter_two->target_id; if (!$fighter_one_id || !$fighter_two_id) { continue; } $fighter_one_data = $this->getFighterData($fighter_one_id); $fighter_two_data = $this->getFighterData($fighter_two_id, FALSE); if (empty($fighter_one_data) || empty($fighter_two_data)) { continue; } $train_array['input'] = array_merge($fighter_one_data, $fighter_two_data); if ($fight->field_result->target_id == $fighter_one_id) { $train_array['output'] = [ 'fighter_one' => 1, 'fighter_two' => 0, ]; $training_data[] = $train_array; } else if ($fight->field_result->target_id == $fighter_two_id) { $train_array['output'] = [ 'fighter_one' => 0, 'fighter_two' => 1, ]; $training_data[] = $train_array; } else { continue; } } return new CacheableJsonResponse($training_data); } /** * Retrieves data about a specific fight for predictions. */ public function getFightData(NodeInterface $fight): CacheableJsonResponse { $fighter_1_id = $fight->field_fighter_one->target_id; $fighter_2_id = $fight->field_fighter_two->target_id; $fight_data = array_merge( $this->getFighterData($fighter_1_id), $this->getFighterData($fighter_2_id, FALSE), ); return new CacheableJsonResponse($fight_data); } /** * Gets the fighter data. * * @return array */ private function getFighterData(int $id, bool $is_f1 = TRUE): array { if ($is_f1) { $prefix = 'fighter_one_'; } else { $prefix = 'fighter_two_'; } $extracted_values = $this->extractValuesFromFields($id, $this->fields, $prefix); /* return $extracted_values; */ return $this->normalizeData($extracted_values); } /** * Extracts a value from a given field (cannot be ent reference) */ private function extractValuesFromFields(int $id, array $field_names, string $prefix): mixed { $fighter = Node::load($id); $values = []; foreach ($field_names as $field) { $value_key = $prefix . $field; $field_machine_name = 'field_' . $field; $values[$value_key] = $fighter->{$field_machine_name}->value ?? 0; } return $values; } /** * Normalize the field value. * * This needs to be between 0-1 */ private function normalizeData(array $data): array { // @todo - this creates an issue where duration of fight is the largest number which isnt really correct // and smaller duration would be better // $min = min(array_values($data)); $max = max(array_values($data)); $normalized = []; foreach ($data as $key => $value) { $value = (float) $value; $normalized[$key] = $this->convertToDecimal($value); /* $norm_val = 0; */ /* if ($max - $min == 0) { */ /* $normalized[$key] = $norm_val; */ /* } */ /* else { */ /* $norm_val = ($value - $min) / ($max - $min); */ /* $normalized[$key] = $norm_val; */ /* } */ } return $normalized; } public function convertToDecimal(float $input) { $output = 0; if ($input > 0 && $input <= 1) { $output = $input / 100; } elseif ($input > 1 && $input < 10) { $output = $input / 100; } elseif ($input > 10 && $input < 100) { $output = $input / 1000; } elseif ($input > 100 && $input < 1000) { $output = $input / 10000; } return $output; } /** * Gets the trained neural network. */ public function getNeuralNetwork(): CacheableJsonResponse { $build = []; $cur_network = \Drupal::state()->get('neuralNetwork') ?? FALSE; if (!$cur_network) { $build['ERROR'] = "There is no spoon."; } else { $build['data'] = base64_decode($cur_network); } return new CacheableJsonResponse($build); } }