313 lines
8.0 KiB
PHP
313 lines
8.0 KiB
PHP
<?php
|
|
|
|
namespace Drupal\ufc;
|
|
|
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
|
use Drupal\ufc\Fighter;
|
|
use Drupal\node\Entity\Node;
|
|
use Drupal\Core\Entity\EntityTypeManager;
|
|
use Drupal\Core\Config\ConfigFactory;
|
|
|
|
class FightPredictor {
|
|
|
|
/**
|
|
* First Fighter.
|
|
*
|
|
* @var Drupal\node\Entity\Node
|
|
*/
|
|
protected $fighterOne;
|
|
|
|
/**
|
|
* Second Fighter.
|
|
*
|
|
* @var Drupal\node\Entity\Node
|
|
*/
|
|
protected $fighterTwo;
|
|
|
|
/**
|
|
* Entity Type Manager.
|
|
*
|
|
* @var Drupal\Core\Entity\EntityTypeManager
|
|
*/
|
|
protected $entityTypeManager;
|
|
|
|
/**
|
|
* Config for ufc weights.
|
|
*
|
|
* @var Drupal\Core\Config\ConfigFactory
|
|
*/
|
|
protected $config;
|
|
|
|
/**
|
|
* Weights config object.
|
|
*
|
|
* @var Drupal\Core\Config\ConfigFactory
|
|
*/
|
|
protected $weights;
|
|
|
|
|
|
/**
|
|
* Public constructor.
|
|
*/
|
|
public function __construct(EntityTypeManager $entityTypeManager, ConfigFactory $config) {
|
|
$this->entityTypeManager = $entityTypeManager;
|
|
$this->config = $config->getEditable('ufc.weights');
|
|
$this->weights = $config->getEditable('ufc.weights')->get('fight_weights');
|
|
}
|
|
|
|
/**
|
|
* The results of the fight.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $results = [
|
|
'fighter_one' => [
|
|
'name' => null,
|
|
'points' => 0,
|
|
'advantages' => [],
|
|
'disadvantages' => []
|
|
],
|
|
'fighter_two' => [
|
|
'name' => null,
|
|
'points' => 0,
|
|
'advantages' => [],
|
|
'disadvantages' => []
|
|
],
|
|
'skips' => 0
|
|
];
|
|
|
|
/**
|
|
* The amount of categories skipped.
|
|
*
|
|
* @var int
|
|
*/
|
|
protected $skipCount;
|
|
|
|
/**
|
|
* Calculate the fight results.
|
|
*/
|
|
public function calculate(Node $fighter_one, Node $fighter_two) {
|
|
// Reset skip count.
|
|
$this->skipCount = 0;
|
|
// First Fighter.
|
|
$this->fighterOne = $fighter_one;
|
|
// Second Fighter.
|
|
$this->fighterTwo = $fighter_two;
|
|
|
|
// Run the fight.
|
|
$this->runFight();
|
|
|
|
// Label the results array.
|
|
$this->results['fighter_one']['name'] = $fighter_one->label();
|
|
$this->results['fighter_two']['name'] = $fighter_two->label();
|
|
// Add total skips.
|
|
$this->results['skips'] = $this->skipCount;
|
|
|
|
// echo "<pre>";
|
|
// print_r($this->results);
|
|
// echo "</pre>";
|
|
// exit();
|
|
|
|
return $this->results;
|
|
}
|
|
|
|
/**
|
|
* Populate fight results.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function runFight() {
|
|
$points = 0;
|
|
$this->calcComparativePoints();
|
|
}
|
|
|
|
/**
|
|
* Calculate comparative points.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function calcComparativePoints() {
|
|
$this->calculateDiff('field_height', 'height');
|
|
$this->calculateDiff('field_weight', 'weight');
|
|
$this->calculateDiff('field_age', 'age');
|
|
$this->calculateDiff('field_reach', 'reach');
|
|
$this->calculateDiff('field_leg_reach', 'leg_reach');
|
|
$this->calculateDiff('field_wins', 'wins');
|
|
$this->calculateDiff('field_losses', 'losses', TRUE);
|
|
$this->calculateDiff('field_ties', 'ties');
|
|
$this->calculateDiff('field_decisions', 'decisions');
|
|
$this->calculateDiff('field_knockouts', 'knockouts');
|
|
$this->calculateDiff('field_submissions', 'submissions');
|
|
$this->calculateDiff('field_grappling_accuracy', 'grappling_accuracy');
|
|
$this->calculateDiff('field_striking_accuracy', 'striking_accuracy');
|
|
$this->calculateDiff('field_strikes_per_minute', 'strikes_per_minute');
|
|
$this->calculateDiff('field_absorbed_per_min', 'absorbed_per_min', TRUE);
|
|
$this->calculateDiff('field_takedowns_per_15', 'takedowns_per_15');
|
|
$this->calculateDiff('field_knockdown_ratio', 'knockdown_ratio');
|
|
}
|
|
|
|
/**
|
|
* Calculate the weighted diff between two fighters.
|
|
*
|
|
* @param [type] $field
|
|
* @param [type] $weight_label
|
|
* @return void
|
|
*/
|
|
public function calculateDiff($field, $weight_label, $inverse = FALSE) {
|
|
$f1 = $this->getFieldValue($field, $this->fighterOne);
|
|
$f2 = $this->getFieldValue($field, $this->fighterTwo);
|
|
|
|
if (empty($f1) || empty($f2)) {
|
|
$this->skipCount += 1;
|
|
return;
|
|
}
|
|
|
|
$weighted_points = 1 * $this->config->get('fight_weights')[$weight_label];
|
|
|
|
if ($f1 === $f2) {
|
|
$this->skipCount += 1;
|
|
return;
|
|
}
|
|
|
|
if ($inverse) {
|
|
if ($f1 < $f2) {
|
|
$this->results['fighter_one']['points'] += $weighted_points;
|
|
$this->results['fighter_one']['advantages'][] = $field;
|
|
$this->results['fighter_two']['disadvantages'][] = $field;
|
|
return;
|
|
}
|
|
elseif ($f1 > $f2) {
|
|
$this->results['fighter_two']['points'] += $$weighted_points;
|
|
$this->results['fighter_two']['advantages'][] = $field;
|
|
$this->results['fighter_one']['disadvantages'][] = $field;
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
if ($f1 > $f2) {
|
|
$this->results['fighter_one']['points'] += $weighted_points;
|
|
$this->results['fighter_one']['advantages'][] = $field;
|
|
$this->results['fighter_two']['disadvantages'][] = $field;
|
|
}
|
|
elseif ($f1 < $f2) {
|
|
$this->results['fighter_two']['points'] += $weighted_points;
|
|
$this->results['fighter_two']['advantages'][] = $field;
|
|
$this->results['fighter_one']['disadvantages'][] = $field;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get value from a field.
|
|
*/
|
|
public function getFieldValue($field, Node $fighter) {
|
|
$field_values = reset($fighter->get($field)->getValue());
|
|
|
|
if (empty($field_values['value'])) {
|
|
return 0;
|
|
}
|
|
|
|
return (float) $field_values['value'];
|
|
}
|
|
|
|
/**
|
|
* Calculate the knockout percentage for a fighter.
|
|
*
|
|
* @param Node $fighter
|
|
* @return void
|
|
*/
|
|
public function getKnockoutPercentage(Node $fighter) {
|
|
|
|
$total_fights =
|
|
$this->getFieldValue('field_wins', $fighter) +
|
|
$this->getFieldValue('field_losses', $fighter) +
|
|
$this->getFieldValue('field_ties', $fighter);
|
|
|
|
$knockout_pct = $this->getFieldValue('field_knockouts', $fighter) / $total_fights;
|
|
|
|
return $knockout_pct;
|
|
}
|
|
|
|
/**
|
|
* Update predictions for all fights in batches
|
|
*/
|
|
public function updatePredictionsBatched($fights, &$context) {
|
|
// $fights = $this->entityTypeManager->getStorage('node')->loadByProperties(['type' => 'fight']);
|
|
$results = [];
|
|
foreach ($fights as $fight) {
|
|
\Drupal::logger('ufc')->notice("Starting " . $fight->label() . "");
|
|
$fight->save();
|
|
$results[] = $fight->id();
|
|
}
|
|
$context['results'] = $results;
|
|
}
|
|
|
|
/**
|
|
* Update predictions for all fights.
|
|
*/
|
|
public function updatePredictions() {
|
|
$fights = $this->entityTypeManager->getStorage('node')->loadByProperties(['type' => 'fight']);
|
|
|
|
// $count = 0;
|
|
|
|
foreach ($fights as $fight) {
|
|
\Drupal::logger('ufc')->notice("Starting " . $fight->label() . "");
|
|
$fight->save();
|
|
|
|
// if ($count == 4) {
|
|
// return;
|
|
// }
|
|
// $count++;
|
|
}
|
|
|
|
}
|
|
|
|
public function adjustWeights($adv, $dis_adv) {
|
|
foreach ($adv as $cat_to_increase) {
|
|
$clean = str_replace('field_', '', $cat_to_increase);
|
|
$this->adjustWeight($clean, 2);
|
|
}
|
|
|
|
foreach ($dis_adv as $cat_to_decrease) {
|
|
$clean = str_replace('field_', '', $cat_to_decrease);
|
|
$this->adjustWeight($clean, -1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function to increase the weight of a category.
|
|
*/
|
|
public function adjustWeight($key, $increment) {
|
|
$current_val = $this->config->get('fight_weights')[$key];
|
|
$increase = $current_val + $increment;
|
|
$target = 'fight_weights.' . $key;
|
|
$this->config->set($target, $increase)->save();
|
|
}
|
|
|
|
/**
|
|
* Helper function to reset all weighting.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function resetWeights() {
|
|
foreach ($this->config->get('fight_weights') as $cat => $weight) {
|
|
$this->config->set('fight_weights.' . $cat, 1)->save();
|
|
}
|
|
}
|
|
|
|
public function fightUpdatedCallback($success, $results, $operations) {
|
|
// The 'success' parameter means no fatal PHP errors were detected. All
|
|
// other error management should be handled using 'results'.
|
|
if ($success) {
|
|
$message = \Drupal::translation()->formatPlural(
|
|
count($results),
|
|
'One fight processed.', '@count fight processed.'
|
|
);
|
|
}
|
|
else {
|
|
$message = t('Finished with an error.');
|
|
}
|
|
drupal_set_message($message);
|
|
}
|
|
|
|
} |