@macho992

Как произвести правильный подсчет в тесте?

Есть тест, который немного не правильно подсчитывает баллы. Создал тест, в нем два вопроса. В каждом вопросе по 4 вариантов ответа, и в каждом один правильный ответ. Если выбрать в одном вопросе правильный ответ, а в другом один не правильный, то результат 75 баллов.. Если выбрать в одном вопросе правильный ответ, а в другом два неправильных ответа, то результат 50 баллов. Ну соответственно при выборе правильных ответов в одном и другом вопросе результат 100 баллов.
Вопрос в том, что почему, если выбрать в одном вопросе правильный ответ, а в другом один не правильный, то результат 75 баллов?
<?php


namespace frontend\controllers;


use common\models\Question;
use common\models\Settings;
use common\models\Test;
use common\models\TestResult;
use common\models\TestResultQuestion;
use common\models\Theme;
use yii\data\Pagination;
use yii\db\ActiveQuery;
use yii\filters\AccessControl;
use yii\helpers\ArrayHelper;
use yii\web\Controller;
use yii\web\NotFoundHttpException;

class TestController extends Controller
{
    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'rules' => [
                    [
                        'actions' => ['index', 'index-theme', 'test', 'result', 'show-result'],
                        'allow' => true,
                        'roles' => ['@'],
                    ],
                ],
            ]
        ];
    }

    public function beforeAction($action) 
    { 
        $this->enableCsrfValidation = false; 
        return parent::beforeAction($action); 
    }

    public function actionIndexTheme($theme_id)
    {
        $theme = Theme::findOne(['id' => $theme_id]);
        $query = Test::find()
            ->innerJoinWith('testQuestions')
            ->where(['theme_id' => $theme_id])
        ->groupBy('test.id');
        $countQuery = clone $query;
        $pages = new Pagination(['totalCount' => $countQuery->count()]);
        $pages->pageSize = 5;
        $models = $query->offset($pages->offset)
            ->limit($pages->limit)
            ->all();

        return $this->render('index-theme', [
            'models' => $models,
            'pages' => $pages,
            'theme' => $theme,
        ]);
    }

    public function actionIndex()
    {
        $query = Test::find()
            ->innerJoinWith('testQuestions')
            ->groupBy('test.id');
        $countQuery = clone $query;
        $pages = new Pagination(['totalCount' => $countQuery->count()]);
        $pages->pageSize = 5;
        $models = $query->offset($pages->offset)
            ->limit($pages->limit)
            ->all();

        return $this->render('index', [
            'models' => $models,
            'pages' => $pages,
        ]);
    }

    public function actionTest($id)
    {
        $time = 300;
        /** @var Settings $settings */
        $settings = Settings::find()->one();
        if ($settings && $settings->time) {
            $time = $settings->time;
        }
        /** @var Test $test */
        $test = Test::find()
            ->where(['test.id' => $id])
            ->innerJoinWith('testQuestions.question.answers')
            ->groupBy('test.id')
            ->one();
        if (!$test) throw new NotFoundHttpException();

        return $this->render('test', [
            'test' => $test,
            'time' => $time,
        ]);
    }

    public function actionResult($test_id)
    {
        $points = 100;
        $answers = \Yii::$app->request->post();

        $answers_id = [];
        $questions = Question::find()
            ->select('question.*')
            ->innerJoinWith(['testQuestions', 'answers' => function (ActiveQuery $query) {
                return $query->where(['answer.is_true' => 1]);
            }])
            ->where(['test_id' => $test_id])
            ->groupBy('question.id')
            ->all();

        $points_question = $points / count($questions);
        $points_result = 0;
        foreach ($questions as $key => $question) {
            $points_for_question = 0;
            if (array_key_exists($question->id, $answers)) {
                $answers_id = array_merge($answers_id, $answers[$question->id]);
                $true_answers = ArrayHelper::getColumn($question->answers, 'id');
                if (count($true_answers) >= count($answers[$question->id])) {
                    $diff = array_diff($true_answers, $answers[$question->id]);
                    if (count($diff) > 0) {
                        $points_for_question = $points_question / 2;
                    } else {
                        $points_for_question = $points_question;
                    }
                } else {
                    $diff = array_diff($answers[$question->id], $true_answers);
                    if (count($diff) < count($answers[$question->id])) {
                        $points_for_question = $points_question / 2;
                    }
                }
            }
            $points_result += $points_for_question;
        }

        $test_result = new TestResult();
        $test_result->result = round($points_result);
        $test_result->test_id = $test_id;
        $test_result->user_id = \Yii::$app->getUser()->getId();
        $test_result->save();

        foreach ($answers_id as $answer) {
            $testrq = new TestResultQuestion();
            $testrq->test_result_id = $test_result->id;
            $testrq->answer_id = $answer;
            $testrq->save();
        }
        return $this->redirect(['show-result','test_result_id' =>$test_result->id ]);
    }

    public function actionShowResult($test_result_id)
    {
        /** @var TestResult $test_result */
        $test_result =  TestResult::find()
            ->joinWith('testResultQuestions')
            ->where(['test_result.id' => $test_result_id])->one();

        $answers_pick = ($test_result->testResultQuestions)
                ? ArrayHelper::getColumn($test_result->testResultQuestions,'answer_id')
                : [];

        $test = Test::find()
            ->where(['test.id' => $test_result->test_id])
            ->innerJoinWith('testQuestions.question.answers')
            ->groupBy('test.id')
            ->one();

        return $this->render('result', [
            'answers_pick' => $answers_pick,
            'test' => $test,
            'test_result' => $test_result,
        ]);
    }
}
  • Вопрос задан
  • 163 просмотра
Решения вопроса 1
myks92
@myks92 Куратор тега Yii
Нашёл решение — пометь вопрос ответом!
Такой код, где много if, else тестировать очень сложно и это сложно читаемо. Вынесите весь код логики в отдельные классы, с методами и тестируйте их. Например класс может быть класс QuestionPoint . В нем методы
public function isAnswerExists($answers){}

и тому подобные..

Получится такой код, если совсем примитивно

$question = 1;
foreach ($questions as $key => $question) {
$questionPoint = new  QuestionPoint($question);
$questionPoint->isAnswerExists($question, $answer)
}


Поэтому делайте код по ООП или DDD и тогда будет вам счастье. В вашем случае будет гемор. Особенно если код в контроллере. Тестировать его будет крайне сложно и долго. Такие тесты запускать никому не захочется. Вам придется в тестах поднимать приложение и базу данных. Хотя в вашем случае это вообще лишнее!

В общем выносите код из контроллера и избавляйтесь от лапши. Создавайте объекты.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы