<commit_before><?php

namespace NatureQuizzer\Model\Utils;

use NatureQuizzer\Database\Model\Answer;
use NatureQuizzer\Database\Model\Concept;
use NatureQuizzer\Database\Model\CurrentKnowledge;
use NatureQuizzer\Database\Model\Model;
use NatureQuizzer\Database\Model\Organism;
use NatureQuizzer\Database\Model\OrganismCommonness;
use NatureQuizzer\Database\Model\OrganismDifficulty;
use NatureQuizzer\Database\Model\PriorKnowledge;
use NatureQuizzer\Database\Model\QuestionType;
use NatureQuizzer\Model\AModelFacade;
use NatureQuizzer\Runtime\CurrentLanguage;
use NatureQuizzer\Utils\Helpers;
use Nette\Utils\ArrayHash;
use Tracy\Debugger;
use Tracy\ILogger;

abstract class BasicElo extends AModelFacade
{
	/** @var Organism */
	protected $organism;
	/** @var Answer */
	protected $answer;
	/** @var OrganismDifficulty */
	protected $organismDifficulty;
	/** @var OrganismCommonness */
	protected $organismCommonness;
	/** @var PriorKnowledge */
	protected $priorKnowledge;
	/** @var CurrentKnowledge */
	protected $currentKnowledge;
	/** @var CurrentLanguage */
	protected $currentLanguage;

	protected $targetProbability;        // Target probability of round. e.g. 0.75 (75 %)
	protected $weightProbability;
	protected $weightTime;
	protected $weightCount;
	protected $weightCommonness;
	protected $weightInvalidAnswer;        // ELO update impact if the answer was invalid
	protected $weightCorrectAnswer;        // ELO update impact if the answer was correct
	protected $eloUpdateFactorA;        // ELO `K` function parameters for uncertainty function
	protected $eloUpdateFactorB;
	protected $distractorCount = 3;

	public function __construct(Organism $organism, CurrentLanguage $currentLanguage, Answer $answer,
								OrganismDifficulty $organismDifficulty, OrganismCommonness $organismCommonness,
								PriorKnowledge $priorKnowledge, CurrentKnowledge $currentKnowledge, Model $model)
	{
		parent::__construct($model);

		$this->organism = $organism;
		$this->organismCommonness = $organismCommonness;
		$this->currentLanguage = $currentLanguage;
		$this->answer = $answer;
		$this->organismDifficulty = $organismDifficulty;
		$this->priorKnowledge = $priorKnowledge;
		$this->currentKnowledge = $currentKnowledge;

		$this->initParameters();
	}

	/** Inits all needed parameters */
	protected abstract function initParameters();

	public function get($userId, $concept, $count)
	{
		$organismIds = $this->selectMainQuestions($userId, $concept, $count);
		$distractorsIds = $this->selectDistractors($userId, $organismIds, $this->distractorCount);

		$data = $this->fetchData($organismIds, $distractorsIds);

		$questions = [];
		foreach ($organismIds as $seqId => $organismId) {
			if (!isset ($data[$organismId])) {
				continue; // TBD: prober handling
			}
			$questionType = (rand(0, 1) == 1) ? QuestionType::CHOOSE_NAME : QuestionType::CHOOSE_REPRESENTATION;
			$questionDistractors = $distractorsIds[$seqId];
			if ($questionType === QuestionType::CHOOSE_NAME) {
				$questions[] = $this->prepareChooseNameQuestion($data, $organismId, $questionDistractors);
			} elseif ($questionType === QuestionType::CHOOSE_REPRESENTATION) {
				$questions[] = $this->prepareChooseRepresentationQuestion($data, $organismId, $questionDistractors);
			}
		}
		return $questions;
	}

	private function fetchData($organismIds, $distractorsIds)
	{
		$allOrganisms = array_merge($organismIds, call_user_func_array('array_merge', $distractorsIds));
		$result = $this->organism->getRepresentationsWithInfoByOrganisms($this->currentLanguage->get(), $allOrganisms);
		return $result;
	}

	private function getRandomItem($array)
	{
		$index = array_rand($array);
		return $array[$index];
	}

	private function prepareChooseNameQuestion($data, $organismId, $questionDistractors)<commit_msg>Change ratio between types of questions.<commit_after><?php

namespace NatureQuizzer\Model\Utils;

use NatureQuizzer\Database\Model\Answer;
use NatureQuizzer\Database\Model\Concept;
use NatureQuizzer\Database\Model\CurrentKnowledge;
use NatureQuizzer\Database\Model\Model;
use NatureQuizzer\Database\Model\Organism;
use NatureQuizzer\Database\Model\OrganismCommonness;
use NatureQuizzer\Database\Model\OrganismDifficulty;
use NatureQuizzer\Database\Model\PriorKnowledge;
use NatureQuizzer\Database\Model\QuestionType;
use NatureQuizzer\Model\AModelFacade;
use NatureQuizzer\Runtime\CurrentLanguage;
use NatureQuizzer\Utils\Helpers;
use Nette\Utils\ArrayHash;
use Tracy\Debugger;
use Tracy\ILogger;

abstract class BasicElo extends AModelFacade
{
	/** @var Organism */
	protected $organism;
	/** @var Answer */
	protected $answer;
	/** @var OrganismDifficulty */
	protected $organismDifficulty;
	/** @var OrganismCommonness */
	protected $organismCommonness;
	/** @var PriorKnowledge */
	protected $priorKnowledge;
	/** @var CurrentKnowledge */
	protected $currentKnowledge;
	/** @var CurrentLanguage */
	protected $currentLanguage;

	protected $targetProbability;        // Target probability of round. e.g. 0.75 (75 %)
	protected $weightProbability;
	protected $weightTime;
	protected $weightCount;
	protected $weightCommonness;
	protected $weightInvalidAnswer;        // ELO update impact if the answer was invalid
	protected $weightCorrectAnswer;        // ELO update impact if the answer was correct
	protected $eloUpdateFactorA;        // ELO `K` function parameters for uncertainty function
	protected $eloUpdateFactorB;
	protected $distractorCount = 3;

	public function __construct(Organism $organism, CurrentLanguage $currentLanguage, Answer $answer,
								OrganismDifficulty $organismDifficulty, OrganismCommonness $organismCommonness,
								PriorKnowledge $priorKnowledge, CurrentKnowledge $currentKnowledge, Model $model)
	{
		parent::__construct($model);

		$this->organism = $organism;
		$this->organismCommonness = $organismCommonness;
		$this->currentLanguage = $currentLanguage;
		$this->answer = $answer;
		$this->organismDifficulty = $organismDifficulty;
		$this->priorKnowledge = $priorKnowledge;
		$this->currentKnowledge = $currentKnowledge;

		$this->initParameters();
	}

	/** Inits all needed parameters */
	protected abstract function initParameters();

	public function get($userId, $concept, $count)
	{
		$organismIds = $this->selectMainQuestions($userId, $concept, $count);
		$distractorsIds = $this->selectDistractors($userId, $organismIds, $this->distractorCount);

		$data = $this->fetchData($organismIds, $distractorsIds);

		$questions = [];
		foreach ($organismIds as $seqId => $organismId) {
			if (!isset ($data[$organismId])) {
				continue; // TBD: prober handling
			}
			$questionType = (rand(0, 100) >= 60) ? QuestionType::CHOOSE_NAME : QuestionType::CHOOSE_REPRESENTATION;
			$questionDistractors = $distractorsIds[$seqId];
			if ($questionType === QuestionType::CHOOSE_NAME) {
				$questions[] = $this->prepareChooseNameQuestion($data, $organismId, $questionDistractors);
			} elseif ($questionType === QuestionType::CHOOSE_REPRESENTATION) {
				$questions[] = $this->prepareChooseRepresentationQuestion($data, $organismId, $questionDistractors);
			}
		}
		return $questions;
	}

	private function fetchData($organismIds, $distractorsIds)
	{
		$allOrganisms = array_merge($organismIds, call_user_func_array('array_merge', $distractorsIds));
		$result = $this->organism->getRepresentationsWithInfoByOrganisms($this->currentLanguage->get(), $allOrganisms);
		return $result;
	}

	private function getRandomItem($array)
	{
		$index = array_rand($array);
		return $array[$index];
	}

	private function prepareChooseNameQuestion($data, $organismId, $questionDistractors)
{'fraction_non_alphanumeric': 0.1191102921821532, 'fraction_numerical': 0.002763885232956041, 'mean_word_length': 5.742679680567879, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 42, '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': '90236', 'n_tokens_mistral': 2523, 'n_tokens_neox': 2294, 'n_words': 478}