#925 - Создать каркас модуля тестирования

parent 9a707a6d
<?php
namespace common\modules\testings\controllers;
use Yii;
use common\components\AdminController;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use common\modules\testings\models\Mistake;
use common\modules\testings\models\Passing;
class MistakeAdminController extends AdminController
{
public $errorSummaryCssClass = 'error-summary';
public $encodeErrorSummary = true;
public static function actionsTitles()
{
return array(
'View' => 'Просмотр ошибки',
'Create' => 'Создание ошибки',
'Update' => 'Редактирование ошибки',
);
}
public function actionView($passing)
{
return $this->render('view', [
'model' => Mistake::find()->where(['passing_id' => $passing])->one(),
]);
}
public function actionCreate($passing)
{
$model = new Mistake;
Yii::$app->controller->page_title = 'Добавить ошибку';
Yii::$app->controller->breadcrumbs = [
['Список прохождений' => '/testings/passing-admin/manage', 'session' => $model->passing->test->session_id],
'Добавить ошибку'
];
$model->load(Yii::$app->request->post());
$model->passing_id = $passing;
if (Yii::$app->request->isPost && $model->save())
{
if ($model->retest)
{
$pass = new Passing;
$oldpass = Passing::findOne($model->passing_id);
$pass->attributes = $oldpass->attributes;
$pass->is_passed = null;
$pass->pass_date = null;
$pass->attempt = 0;
$pass->pass_date_start = '';
$pass->save();
}
return $this->redirect(['/testings/passing-admin/manage', 'session' => $model->passing->test->session_id]);
}
else
{
$form = new \common\components\BaseForm('/common/modules/testings/forms/MistakeForm', $model);
return $this->render('create', [
'model' => $model,
'form' => $form->out
]);
}
}
public function actionUpdate($passing)
{
Yii::$app->controller->page_title = 'Редактировать ошибку';
Yii::$app->controller->breadcrumbs = [
['Список прохождений' => '/testings/passing-admin/manage', 'session' => $model->passing->test->session_id],
'Редактировать ошибку'
];
$model = Mistake::find()->where(['passing_id' => $passing])->one();
$model->load(Yii::$app->request->post());
$model->passing_id = $passing;
if (Yii::$app->request->isPost && $model->save())
{
if ($model->retest)
{
$pass = new Passing;
$pass->attributes = $model->passing->attributes;
$pass->is_passed = null;
$pass->pass_date = null;
$pass->attempt = 0;
$pass->pass_date_start = '';
$pass->save();
}
return $this->redirect(['/testings/passing-admin/manage', 'session' => $model->passing->test->session_id]);
}
else
{
$form = new \common\components\BaseForm('/common/modules/testings/forms/MistakeForm', $model);
return $this->render('update', [
'model' => $model,
'form' => $form->out
]);
}
}
/**
* Finds the Faq model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* @param integer $id
* @return Faq the loaded model
* @throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Answer::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
}
...@@ -4,10 +4,11 @@ namespace common\modules\testings\controllers; ...@@ -4,10 +4,11 @@ namespace common\modules\testings\controllers;
use Yii; use Yii;
use yii\web\NotFoundHttpException; use yii\web\NotFoundHttpException;
use yii\helpers\Json; use yii\web\Response;
use common\modules\testings\models\Test; use common\modules\testings\models\Test;
use common\modules\testings\models\Passing; use common\modules\testings\models\Passing;
use common\modules\testings\models\Question;
use common\modules\testings\models\QuestionPassing; use common\modules\testings\models\QuestionPassing;
class TestController extends \common\components\BaseController class TestController extends \common\components\BaseController
...@@ -45,105 +46,6 @@ class TestController extends \common\components\BaseController ...@@ -45,105 +46,6 @@ class TestController extends \common\components\BaseController
} }
} }
public function actionSendNotAttempt($id)
{
if(Yii::$app->request->isAjax)
{
$passing = $this->findModel($id);
if($model && $model->sendNotAttempt(Yii::$app->request->post('message')))
{
echo Json::encode([
'success' => true,
'message' => 'Сообщение отправлено!'
]);
}
}
else
{
throw new NotFoundHttpException('The requested page does not exist.');
}
}
public function actionSetAnswer($id)
{
if(Yii::$app->request->isAjax)
{
header('Content-type: application/json');
$passing = $this->findModel($id);
$pq = QuestionPassing::find()->where([
'question_id' => $_POST['question_id'],
'passing_id' => $passing->id,
])->one();
$pq->user_answer = $_POST['userAnswer'];
$pq->answer_time = ceil($_POST['time']);
if($pq->save())
{
$passing->recountPassResult();
$passing->percent_rights = $passing->getPercent();
if($passing->is_passed == Passing::PASSED)
{
$passing->pass_date = date('d.m.Y H:i:s');
}
$passing->save();
return Json::encode([
'success' => true,
'percent' => $pq->passing->percent,
]);
}
else
{
return Json::encode([
'massage' => 'Временные неполадки на сервере, попробуйте еще раз.'
]);
}
}
else
{
throw new NotFoundHttpException('The requested page does not exist.');
}
}
public function actionFinishTest($id)
{
if(Yii::$app->request->isPost)
{
header('Content-type: application/json');
$passing = $this->findModel($id);
// если тест сдан, результаты модифицировать нельзя
if ($passing->pass_date === null)
{
$passing->pass_date = date('d.m.Y H:i:s');
$passing->recountPassResult();
$passing->percent_rights = $passing->getPercent();
$passing->save();
return Json::encode(['status' => 'ok']);
}
else
{
return Json::encode(['massage'=>'Тест уже был сдан!']);
}
}
else
{
throw new NotFoundHttpException('The requested page does not exist.');
}
}
public function actionGenPass($id) public function actionGenPass($id)
{ {
$transaction = Yii::$app->db->beginTransaction(); $transaction = Yii::$app->db->beginTransaction();
...@@ -161,350 +63,95 @@ class TestController extends \common\components\BaseController ...@@ -161,350 +63,95 @@ class TestController extends \common\components\BaseController
{ {
$passing = new Passing; $passing = new Passing;
$passing->user_id = Yii::$app->user->identity->id; $passing->user_id = Yii::$app->user->identity->id;
$passing->test_id = $id; $passing->test_id = $test->id;
$passing->status = Passing::NOT_STARTED;
} }
$transaction->commit(); // Проверяем статус прохождения
} switch ($passing->status)
catch (\Exception $e)
{
$transaction->rollBack();
throw $e;
}
$user_id = Yii::app()->request->cookies[self::AUTH_COOKIE]->value;
$cr3 = new CDbCriteria;
$cr3->with = 'test.session';
$cr3->addCondition('user_id = :user_id');
$cr3->addCondition('t.id = :p_id');
//$cr3->addCondition('t.is_passed is NULL');
$cr3->addCondition('STR_TO_DATE(`session`.`start_date`,"%d.%m.%Y %H:%i") <= NOW()');
$cr3->addCondition('(STR_TO_DATE(`session`.`end_date`,"%d.%m.%Y %H:%i") > NOW()) OR (STR_TO_DATE(`t`.`end_date`,"%d.%m.%Y %H:%i") > NOW())');
$cr3->params = array(
'user_id' => $user_id,
'p_id' => $id
);
$cr3->group = 't.id';
$cr3->together = true;
$tp = TestingPassing::model()->find($cr3);
if (empty($tp))
{
echo 'Доступ к этому тесту запрещен';
}
else
{
// только проверив состояния, можно допустить юзера к тесту
switch ($passing->status)
{ {
case TestingPassing::NOT_STARTED : case Passing::FAILED :
$passing->pass_date_start = date('d.m.Y H:i:s'); case Passing::PASSED :
break; case Passing::NOT_STARTED :
case TestingPassing::MISTAKE : $passing->start_date = date('d.m.Y H:i:s');
Yii::app()->end(); $passing->passed = Passing::FAILED;
$passing->end_date = null;
$passing->percent = 0;
$passing->attempt = 0;
$passing->points = 0;
break; break;
case TestingPassing::STARTED :
$this->redirect(Yii::app()->createUrl('/testings/testingTest/pass', array('id' => $passing->id))); case Passing::STARTED :
Yii::app()->end(); return $this->redirect(['/testing/pass/'.$passing->id]);
break; break;
case null : case null :
break; throw new NotFoundHttpException('Что-то пошло не так! Обратитесь к администратору.');
case TestingPassing::FAILED :
case TestingPassing::PASSED :
$this->render('pass_statistics', array(
'model' => $passing,
));
Yii::app()->end();
break; break;
} }
if($passing->test->mix) $passing->status = Passing::STARTED;
{ $passing->save();
// Если данные не заполнены не генерируем вопросы к прохождению
if($passing->test->minutes && $passing->test->questions && $passing->test->pass_percent && $passing->test->attempt)
{
$criteria = new CDbCriteria;
$criteria->with = 'test'; // Берем все активные вопросы относящиеся к тесту
$criteria->together = true; $questions = Question::find()->where([
'test_id' => $test->id,
'is_active' => Question::ACTIVE,
])->all();
$criteria->addCondition('test.session_id = ' . $passing->test->session_id); if(count($questions) < $test->questions)
$criteria->addCondition('t.user_id = ' . $user_id); {
$criteria->addCondition('test.id <> ' . $passing->test->id); throw new NotFoundHttpException('В тесте не хватает вопросов для заполнения прохождения! Обратитесь к администратору.');
}
$criteria->group = 'test.id'; // Перемешиваем
shuffle($questions);
$passes = TestingPassing::model()->findAll($criteria); // Чистим старые вопросы
QuestionPassing::deleteAll(['passing_id' => $passing->id]);
if($passes) $s = true;
{ for ($i = 1; $i <= $test->questions; $i++)
// Проверяем хватает ли вопросов в назначенных пользователю тестах {
$questions_count = 0; $pq = new QuestionPassing;
foreach ($passes as $pass)
{
$questions_count += count($pass->test->questionsRelation);
}
if($questions_count >= $passing->test->questions)
{
// определение количества вопросов, которое нужно взять из каждого теста
$need_count_questions = ceil($passing->test->questions / count($passes));
// Берем все вопросы по тестам
$questions = array();
$backup = 0;
foreach ($passes as $pass)
{
$cr = new CDbCriteria;
$cr->addCondition('test_id = :test_id');
$cr->addCondition('is_active = :is_active');
$cr->params = array(
':test_id' => $pass->test_id,
':is_active' => TestingQuestion::ACTIVE,
);
$test_questions = TestingQuestion::model()->findAll($cr);
$count_questions = count($test_questions);
$questions_needed_in_this_test = $need_count_questions + $backup;
if($questions_needed_in_this_test > $count_questions)
{
$backup = abs($questions_needed_in_this_test - $count_questions);
$questions_needed_in_this_test = $count_questions;
}
else
{
$backup = 0;
}
shuffle($test_questions);
for ($i = 1; $i <= $questions_needed_in_this_test; $i++)
{
if(count($questions) < $passing->test->questions)
{
$questions[] = array_shift($test_questions);
}
}
}
shuffle($questions);
if (count($questions) < $passing->test->questions)
{
$diff = abs(count($questions) - $passing->test->questions);
Yii::app()->user->setFlash('flash',"В назначенных тестах не хватило несколько вопросов ($diff) для заполнения микса! Обратитесь к администратору.");
}
if (count($questions) == $passing->test->questions)
{
$passing->is_passed = 0;
if ($passing->save())
{
// сначала на всякий случай чистим старые вопросы. вдруг да остались из-за какого глюка..
$old_questions = TestingQuestionPassing::model()->findAll('passing_id = :passing_id',array(':passing_id' => $passing->id));
foreach ($old_questions as $old_q)
{
$old_q->delete();
}
// а вот теперь заполняем новыми вопросами
foreach ($questions as $question)
{
$pq = new TestingQuestionPassing;
$pq->passing_id = $passing->id;
$pq->question_id = $question->id;
$pq->question_text = $question->text;
$pq->answer_text = $question->rightAnswer;
$pq->save();
}
}
}
}
else
{
Yii::app()->user->setFlash('flash',"В назначенных тестах не хватает вопросов для заполнения микса! Обратитесь к администратору.");
}
}
else
{
Yii::app()->user->setFlash('flash',"Не хватает назначенных тестов для заполнения микса! Обратитесь к администратору.");
}
if (($passing->pass_date === null) && ($passing->is_passed === null)) $pq->passing_id = $passing->id;
{ $pq->question_id = $questions[$i]->id;
$this->render('info', array( $pq->question_text = $questions[$i]->text;
'model' => $passing $pq->answer_text = $questions[$i]->rightAnswer;
));
Yii::app()->end(); if(!$pq->save())
}
}
else
{ {
$this->redirect(Yii::app()->createUrl('/testings/testingTest/index')); $s = false;
}
}
else
{
// заполнение списка гамм выбранными пользователем, генерация списка вопросов
if (isset($_POST['mg']) || isset($_POST['te'])) {
$mg_array = array();
$te_array = array();
if (isset($_POST['mg'])) {
foreach ($_POST['mg'] as $gamma_id) {
$gamma = TestingGamma::model()->findByPk($gamma_id);
if ($gamma) {
$mg_array[] = $gamma;
}
}
}
if (isset($_POST['te'])) {
foreach ($_POST['te'] as $gamma_id) {
$gamma = TestingGamma::model()->findByPk($gamma_id);
if ($gamma) {
$te_array[] = $gamma;
}
}
}
// если выбрано достаточное кол-во гамм продукции, делаем выбор вопросов и начинаем тестирование
if ((count($mg_array) >= $passing->test->mg_count) && (count($te_array) >= $passing->test->te_count)) {
// определение количества вопросов, которое нужно взять из каждой основной гаммы
$mg_questions_count = round($passing->test->questions * $passing->test->mg_percent / ($passing->test->mg_percent + $passing->test->te_percent));
$te_questions_count = $passing->test->questions - $mg_questions_count;
// определение количества вопросов, которое нужно взять из каждой гаммы продукции
$mg_questions_in_each_gamma = count($mg_array) ? ceil($mg_questions_count / count($mg_array)) : 0;
$te_questions_in_each_gamma = count($te_array) ? ceil($te_questions_count / count($te_array)) : 0;
// выбор вопросов для строительной гаммы
$questions = array();
$backup = 0; // кол-во вопросов, которое не хватило в какой-нибудь другой гамме
foreach (array_reverse($mg_array) as $gamma) {
$cr = new CDbCriteria;
$cr->addCondition('gamma_id = :gamma_id');
$cr->addCondition('test_id = :test_id');
$cr->addCondition('is_active = :is_active');
$cr->params = array(
':gamma_id' => $gamma->id,
':test_id' => $passing->test_id,
':is_active' => TestingQuestion::ACTIVE,
);
$questions_needed_in_this_gamma = $mg_questions_in_each_gamma + $backup;
$questions_in_gamma = TestingQuestion::model()->findAll($cr);
$count_questions_in_gamma = count($questions_in_gamma);
// если нужно вопросов больше, чем есть в этой гамме, просим поддержки у остальных гамм
if ($questions_needed_in_this_gamma > $count_questions_in_gamma) {
$backup = abs($questions_needed_in_this_gamma - $count_questions_in_gamma);
$questions_needed_in_this_gamma = $count_questions_in_gamma;
} else {
$backup = 0;
}
shuffle($questions_in_gamma);
for ($i=1; $i<=$questions_needed_in_this_gamma; $i++) {
$questions[] = array_shift($questions_in_gamma);
}
}
foreach (array_reverse($te_array) as $gamma) {
$cr = new CDbCriteria;
$cr->addCondition('gamma_id = :gamma_id');
$cr->addCondition('test_id = :test_id');
$cr->addCondition('is_active = :is_active');
$cr->params = array(
':gamma_id' => $gamma->id,
':test_id' => $passing->test_id,
':is_active' => TestingQuestion::ACTIVE,
);
$questions_needed_in_this_gamma = $te_questions_in_each_gamma + $backup;
$questions_in_gamma = TestingQuestion::model()->findAll($cr);
$count_questions_in_gamma = count($questions_in_gamma);
// если нужно вопросов больше, чем есть в этой гамме, просим поддержки у остальных гамм
if ($questions_needed_in_this_gamma > $count_questions_in_gamma) {
$backup = abs($questions_needed_in_this_gamma - $count_questions_in_gamma);
$questions_needed_in_this_gamma = $count_questions_in_gamma;
} else {
$backup = 0;
}
shuffle($questions_in_gamma);
for ($i=1; $i<=$questions_needed_in_this_gamma; $i++) {
$questions[] = array_shift($questions_in_gamma);
}
}
// рандомизируем вопросы
shuffle($questions);
// если вопросов получилось БОЛЬШЕ, чем надо (погрешности при округлении в большую сторону),
// тогда убираем несколько лишних
if (count($questions) > $passing->test->questions) {
$diff = count($questions) - $passing->test->questions;
for ($i=1; $i<=$diff; $i++) {
array_shift($questions);
}
}
// если вопросов получилось МЕНЬШЕ, чем надо,
// значит вопросов в гаммах не хватило, выводим сообщение пользователю
if (count($questions) < $passing->test->questions) {
$diff = abs(count($questions) - $passing->test->questions);
Yii::app()->user->setFlash('flash',"В выбранных гаммах не хватило несколько вопросов ($diff) для заполнения теста! Обратитесь к администратору.");
}
// и вот, если наконец-то всё ок: вопросы выбраны, количество идеально -
// заполняем базу вопросами и разрешаем юзеру пройти тест
if (count($questions) == $passing->test->questions) {
$passing->is_passed = 0;
if ($passing->save()) {
// сначала на всякий случай чистим старые вопросы. вдруг да остались из-за какого глюка..
$old_questions = TestingQuestionPassing::model()->findAll('passing_id = :passing_id',array(':passing_id'=>$passing->id));
foreach ($old_questions as $old_q) {
$old_q->delete();
}
// а вот теперь заполняем новыми вопросами
foreach ($questions as $question) {
$pq = new TestingQuestionPassing;
$pq->passing_id = $passing->id;
$pq->question_id = $question->id;
$pq->question_text = $question->text;
$pq->answer_text = $question->rightAnswer;
$pq->save();
}
}
}
} else {
Yii::app()->user->setFlash('flash','Выбрано недостаточное количество гамм продукции!');
foreach ($mg_array as $item) {
array_unshift($mg_gammas, $item->id);
}
foreach ($te_array as $item) {
array_unshift($te_gammas, $item->id);
}
}
} }
}
if (($passing->pass_date === null) && ($passing->is_passed === null)) { if($s)
$this->render('pass_fill_gammas', array( {
'model' => $passing, $transaction->commit();
'mg_gammas' => $mg_gammas,
'te_gammas' => $te_gammas,
));
Yii::app()->end();
}
} }
if (($passing->pass_date === null) && ($passing->is_passed === TestingPassing::FAILED)) if ($passing->end_date === null && $passing->status === Passing::STARTED)
{ {
$this->redirect(Yii::app()->createUrl('/testings/test/pass', array('id' => $passing->id))); return $this->redirect(['/testing/pass/'.$passing->id]);
} }
else else
{ {
$this->redirect(Yii::app()->createUrl('/testings/test/statistic', array('id' => $passing->id))); return $this->redirect(['/testing/statistic/'.$passing->id]);
} }
} }
catch (\Exception $e)
{
$transaction->rollBack();
throw $e;
}
} }
public function actionPass($id) public function actionPass($id)
{ {
$passing = $this->findModel($id); $this->view->registerJsFile('/js/testing.js', ['position' => yii\web\View::POS_END ]);
$passing = $this->findPassing($id);
switch ($passing->status) switch ($passing->status)
{ {
...@@ -512,16 +159,16 @@ class TestController extends \common\components\BaseController ...@@ -512,16 +159,16 @@ class TestController extends \common\components\BaseController
$passing->attempt += 1; $passing->attempt += 1;
$passing->save(false, ['attempt']); $passing->save(false, ['attempt']);
$count_answer = QuestionPassing::find()->where(['passing_id' => $id])->andWhere(['not', 'user_answer', null])->count(); $count_answer = QuestionPassing::find()->where(['passing_id' => $id])->andWhere(['!=', 'user_answer', ''])->count();
return $this->render('pass_testing', [ return $this->render('test', [
'model' => $passing, 'model' => $passing,
'current_answer' => $count_answer + 1 'current_answer' => $count_answer + 1
]); ]);
break; break;
case Passing::FAILED : case Passing::FAILED :
if($passing->attempt < $passing->test->attempt && strtotime($passing->pass_date_start) + ($passing->test->minutes * 60) >= time()) if($passing->attempt < $passing->test->attempt && strtotime($passing->start_date) + ($passing->test->minutes * 60) >= time())
{ {
return $this->redirect(['/testings/test/statistic', 'id' => $passing->id]); return $this->redirect(['/testings/test/statistic', 'id' => $passing->id]);
} }
...@@ -529,13 +176,13 @@ class TestController extends \common\components\BaseController ...@@ -529,13 +176,13 @@ class TestController extends \common\components\BaseController
{ {
if($passing->attempt >= $passing->test->attempt) if($passing->attempt >= $passing->test->attempt)
{ {
return $this->render('pass_not_attempt', [ return $this->render('not_attempt', [
'model' => $passing, 'model' => $passing,
]); ]);
} }
elseif(strtotime($passing->pass_date_start) + ($passing->test->minutes * 60) < time()) elseif(strtotime($passing->start_date) + ($passing->test->minutes * 60) < time())
{ {
return $this->render('pass_not_time', [ return $this->render('not_time', [
'model' => $passing, 'model' => $passing,
]); ]);
} }
...@@ -549,21 +196,124 @@ class TestController extends \common\components\BaseController ...@@ -549,21 +196,124 @@ class TestController extends \common\components\BaseController
} }
} }
public function actionSendNotAttempt($id)
{
if(Yii::$app->request->isAjax)
{
Yii::$app->response->format = Response::FORMAT_JSON;
$passing = $this->findModel($id);
if($model && $model->sendNotAttempt(Yii::$app->request->post('message')))
{
echo [
'success' => true,
'message' => 'Сообщение отправлено!'
];
}
}
else
{
throw new NotFoundHttpException('The requested page does not exist.');
}
}
public function actionSetAnswer($id)
{
if(Yii::$app->request->isAjax)
{
Yii::$app->response->format = Response::FORMAT_JSON;
$passing = $this->findPassing($id);
$pq = QuestionPassing::find()->where([
'question_id' => $_POST['question_id'],
'passing_id' => $passing->id,
])->one();
$pq->user_answer = $_POST['userAnswer'];
$pq->answer_time = ceil($_POST['time']);
if($pq->save())
{
$passing->recountPassResult();
$passing->percent = $passing->getPercentRight();
if($passing->status == Passing::PASSED)
{
$passing->end_date = date('d.m.Y H:i:s');
}
$passing->save();
return [
'success' => true,
'percent' => $pq->passing->percent,
];
}
else
{
return [
'massage' => 'Временные неполадки на сервере, попробуйте еще раз.'
];
}
}
else
{
throw new NotFoundHttpException('The requested page does not exist.');
}
}
public function actionFinishTest($id)
{
if(Yii::$app->request->isPost)
{
Yii::$app->response->format = Response::FORMAT_JSON;
$passing = $this->findPassing($id);
// если тест сдан, результаты модифицировать нельзя
if ($passing->end_date === null)
{
$passing->end_date = date('d.m.Y H:i:s');
$passing->status = Passing::ENDED;
$passing->recountPassResult();
$passing->percent = $passing->getPercentRight();
$passing->save();
return ['status' => 'ok'];
}
else
{
return ['massage'=>'Тест уже был сдан!'];
}
}
else
{
throw new NotFoundHttpException('The requested page does not exist.');
}
}
public function actionStatistic($id) public function actionStatistic($id)
{ {
$passing = $this->findModel($id); $passing = $this->findPassing($id);
switch ($passing->status) switch ($passing->passed)
{ {
case TestingPassing::FAILED : case Passing::FAILED :
case TestingPassing::PASSED : case Passing::PASSED :
return $this->render('pass_statistics', [ return $this->render('statistics', [
'model' => $passing, 'model' => $passing,
]); ]);
break; break;
default : default :
return $this->redirect(['/testings/test/index']); throw new NotFoundHttpException('The requested page does not exist.');
break; break;
} }
} }
...@@ -583,4 +333,20 @@ class TestController extends \common\components\BaseController ...@@ -583,4 +333,20 @@ class TestController extends \common\components\BaseController
throw new NotFoundHttpException('The requested page does not exist.'); throw new NotFoundHttpException('The requested page does not exist.');
} }
} }
/**
* Finds the Faq model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* @param integer $id
* @return Faq the loaded model
* @throws NotFoundHttpException if the model cannot be found
*/
protected function findPassing($id)
{
if (($model = Passing::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
} }
<?php
namespace common\modules\testings\models;
use Yii;
use yii\behaviors\TimestampBehavior;
use yii\db\Expression;
class Mistake extends \common\components\ActiveRecordModel
{
const PAGE_SIZE = 10;
const NOT_AGREED = 0;
const AGREED = 1;
public $company;
public $managerField;
public $mistakeField;
public $retest = 0;
public static $state_list = [
self::NOT_AGREED => 'Не согласовано',
self::AGREED => 'Согласовано',
];
public static function tableName()
{
return 'testings_mistakes';
}
public function name()
{
return 'Сообщения об ошибках';
}
public function attributeLabels()
{
return [
'passing_id' => 'Прохождение',
'description' => 'Описание ошибки',
'is_expert_agreed' => 'Согласовано ли с экспертом',
'create_date' => 'Время создания',
];
}
/**
* @inheritdoc
*/
public function behaviors()
{
// $behaviors['FileManager'] = array(
// 'class' => 'application.components.activeRecordBehaviors.FileManagerBehavior'
// );
return [
[
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'create_date',
'updatedAtAttribute' => 'create_date',
'value' => new Expression('NOW()'),
],
];
}
public function rules()
{
return [
[['passing_id', 'description', 'is_expert_agreed'], 'required'],
[['passing_id', 'is_expert_agreed'], 'integer'],
[['description'], 'string', 'max' => 3000],
[['retest'], 'safe']
];
}
public function getPassing()
{
return $this->hasOne(Passing::className(), ['id' => 'passing_id']);
}
// public function getFiles()
// {
// return $this->hasMany(FileManager::className(), ['object_id' => 'id'])
// ->andWhere([
// 'files.model_id' => get_class($this),
// 'files.tag' => 'files'
// ])
// ->orderBy(['files.order DESC']);
// }
}
\ No newline at end of file
...@@ -12,24 +12,30 @@ class Passing extends \common\components\ActiveRecordModel ...@@ -12,24 +12,30 @@ class Passing extends \common\components\ActiveRecordModel
{ {
const PAGE_SIZE = 10; const PAGE_SIZE = 10;
const STARTED = 0; const NOT_STARTED = 0;
const STARTED = 11;
const ENDED = 1;
const FAILED = 0;
const PASSED = 1; const PASSED = 1;
const MISTAKE = 8;
const FAILED = 9;
const PASSING_PERCENT_RIGHT_CENTER = 50; const PASSING_PERCENT_RIGHT_CENTER = 50;
const PASSING_PERCENT_RIGHT_ALMOST = 75; const PASSING_PERCENT_RIGHT_ALMOST = 75;
const PASSING_PERCENT_RIGHT_ALL = 100; const PASSING_PERCENT_RIGHT_ALL = 100;
public static $state_list = [ public static $state_list = [
self::STARTED => 'Начал тестирование', self::NOT_STARTED => 'Не сдавал',
self::STARTED => 'Тестирование',
self::ENDED => 'Завершено',
];
public static $passed_list = [
self::FAILED => 'Не сдал', self::FAILED => 'Не сдал',
self::PASSED => 'Сдал', self::PASSED => 'Сдал',
self::MISTAKE => 'Ошибка',
]; ];
public static $answer_list = [ public static $answer_list = [
self::STARTED => 'Не верно', self::FAILED => 'Не верно',
self::PASSED => 'Верно', self::PASSED => 'Верно',
]; ];
...@@ -57,8 +63,8 @@ class Passing extends \common\components\ActiveRecordModel ...@@ -57,8 +63,8 @@ class Passing extends \common\components\ActiveRecordModel
{ {
return [ return [
[['user_id', 'test_id'], 'required'], [['user_id', 'test_id'], 'required'],
[['user_id', 'test_id', 'is_passed'], 'integer'], [['user_id', 'test_id', 'status', 'passed', 'percent', 'points'], 'integer'],
[['pass_date', 'pass_date_start', 'attempt'], 'safe'], [['start_date', 'attempt'], 'safe'],
[['end_date'], 'required', 'on' => 'extend'], [['end_date'], 'required', 'on' => 'extend'],
]; ];
} }
...@@ -66,14 +72,14 @@ class Passing extends \common\components\ActiveRecordModel ...@@ -66,14 +72,14 @@ class Passing extends \common\components\ActiveRecordModel
public function attributeLabels() public function attributeLabels()
{ {
return [ return [
'is_passed' => 'Состояние',
'test_id' => 'Tест', 'test_id' => 'Tест',
'user_id' => 'ФИО', 'user_id' => 'ФИО',
'create_date' => 'Дата создания', 'passed' => 'Сдал/Не сдал',
'pass_date' => 'Дата прохождения теста', 'status' => 'Статус',
'start_date' => 'Дата создания',
'end_date' => 'Дата прохождения теста',
'session_id' => 'Сессия', 'session_id' => 'Сессия',
'filter_user_email' => 'Email', 'filter_user_email' => 'Email',
'filter_user_company_name' => 'Наименование компании',
'filter_user_last_name' => 'ФИО', 'filter_user_last_name' => 'ФИО',
]; ];
} }
...@@ -113,7 +119,7 @@ class Passing extends \common\components\ActiveRecordModel ...@@ -113,7 +119,7 @@ class Passing extends \common\components\ActiveRecordModel
return $count; return $count;
} }
public function getPercent() public function getPercentRight()
{ {
$all = 0; $all = 0;
$right = 0; $right = 0;
...@@ -156,17 +162,18 @@ class Passing extends \common\components\ActiveRecordModel ...@@ -156,17 +162,18 @@ class Passing extends \common\components\ActiveRecordModel
public function getTime() public function getTime()
{ {
if($this->pass_date_start && $this->pass_date) if($this->start_date && $this->end_date)
{ {
return (strtotime($this->pass_date) - strtotime($this->pass_date_start)); return (strtotime($this->end_date) - strtotime($this->start_date));
} }
else else
{ {
$timeSummary = 0; $time = 0;
foreach ($this->questions as $q) { foreach ($this->questions as $q)
$timeSummary += $q->answer_time; {
$time += $q->answer_time;
} }
return $timeSummary; return $time;
} }
} }
...@@ -175,4 +182,18 @@ class Passing extends \common\components\ActiveRecordModel ...@@ -175,4 +182,18 @@ class Passing extends \common\components\ActiveRecordModel
$cases = array (2, 0, 1, 1, 1, 2); $cases = array (2, 0, 1, 1, 1, 2);
return $number." ".$titles[ ($number%100 > 4 && $number %100 < 20) ? 2 : $cases[min($number%10, 5)] ]; return $number." ".$titles[ ($number%100 > 4 && $number %100 < 20) ? 2 : $cases[min($number%10, 5)] ];
} }
public function recountPassResult()
{
if ($this->percent >= $this->test->pass_percent)
{
$this->passed = self::PASSED;
}
else
{
$this->passed = self::FAILED;
}
return true;
}
} }
...@@ -169,7 +169,7 @@ class Question extends \common\components\ActiveRecordModel ...@@ -169,7 +169,7 @@ class Question extends \common\components\ActiveRecordModel
break; break;
case self::USER_ANSWER: case self::USER_ANSWER:
$models = $query->one(); $model = $query->one();
if ($model) if ($model)
{ {
$answer = trim(preg_replace('/\s+/', ' ', $model->text)); $answer = trim(preg_replace('/\s+/', ' ', $model->text));
......
...@@ -46,17 +46,15 @@ class QuestionPassing extends \common\components\ActiveRecordModel ...@@ -46,17 +46,15 @@ class QuestionPassing extends \common\components\ActiveRecordModel
{ {
return [ return [
[['passing_id', 'question_id'], 'required'], [['passing_id', 'question_id'], 'required'],
[['passing_id', 'answer_time'], 'integer'], [['passing_id', 'question_id', 'answer_time'], 'integer'],
[['question_id'], 'string', 'max' => 11],
[['user_answer'], 'string', 'max' => 3000], [['user_answer'], 'string', 'max' => 3000],
// array('id, passing_id, question_id, user_answer, answer_time', 'safe', 'on' => 'search'),
]; ];
} }
public function attributeLabels() public function attributeLabels()
{ {
return [ return [
'question_id' => 'Наименование вопроса', 'question_id' => 'Вопрос',
'user_answer' => 'Ответ пользователя', 'user_answer' => 'Ответ пользователя',
'answer_time' => 'Время прохождения, секунд', 'answer_time' => 'Время прохождения, секунд',
'create_date' => 'Дата создания', 'create_date' => 'Дата создания',
...@@ -72,7 +70,7 @@ class QuestionPassing extends \common\components\ActiveRecordModel ...@@ -72,7 +70,7 @@ class QuestionPassing extends \common\components\ActiveRecordModel
public function getPassing() public function getPassing()
{ {
return $this->hasOne(Passing::className(), ['passing_id' => 'id']); return $this->hasOne(Passing::className(), ['id' => 'passing_id']);
} }
public function search($passing = null) public function search($passing = null)
......
...@@ -15,7 +15,6 @@ use common\modules\testings\models\Mistake; ...@@ -15,7 +15,6 @@ use common\modules\testings\models\Mistake;
class SearchPassing extends Passing class SearchPassing extends Passing
{ {
public $filter_user_email; public $filter_user_email;
public $filter_user_company_name;
public $filter_user_last_name; public $filter_user_last_name;
/** /**
...@@ -24,8 +23,8 @@ class SearchPassing extends Passing ...@@ -24,8 +23,8 @@ class SearchPassing extends Passing
public function rules() public function rules()
{ {
return [ return [
[['id', 'user_id', 'test_id', 'is_passed'], 'integer'], [['id', 'user_id', 'test_id', 'status'], 'integer'],
[['id', 'user_id', 'test_id', 'is_passed', 'pass_date', 'filter_user_email', 'filter_user_company_name', 'filter_user_last_name'], 'safe'], [['id', 'user_id', 'test_id', 'status', 'end_date', 'filter_user_email', 'filter_user_last_name'], 'safe'],
]; ];
} }
...@@ -53,7 +52,7 @@ class SearchPassing extends Passing ...@@ -53,7 +52,7 @@ class SearchPassing extends Passing
'query' => $query, 'query' => $query,
'pagination' => ['pageSize' => self::PAGE_SIZE], 'pagination' => ['pageSize' => self::PAGE_SIZE],
'sort' => [ 'sort' => [
'defaultOrder'=>'create_date DESC', 'defaultOrder'=>'start_date DESC',
], ],
]); ]);
...@@ -80,7 +79,7 @@ class SearchPassing extends Passing ...@@ -80,7 +79,7 @@ class SearchPassing extends Passing
'id' => $this->id, 'id' => $this->id,
'user_id' => $this->user_id, 'user_id' => $this->user_id,
'test_id' => $this->test_id, 'test_id' => $this->test_id,
'create_date' => $this->create_date, 'start_date' => $this->start_date,
Test::tableName() . '.session_id' => Yii::$app->request->get('session'), Test::tableName() . '.session_id' => Yii::$app->request->get('session'),
]); ]);
...@@ -90,12 +89,6 @@ class SearchPassing extends Passing ...@@ -90,12 +89,6 @@ class SearchPassing extends Passing
$query->andFilterWhere(['like', User::tableName() . '.email', $this->filter_user_email]); $query->andFilterWhere(['like', User::tableName() . '.email', $this->filter_user_email]);
} }
if($this->filter_user_company_name)
{
$with['user'] = true;
$query->andFilterWhere(['like', User::tableName() . '.company_name', $this->filter_user_company_name]);
}
if($this->filter_user_last_name) if($this->filter_user_last_name)
{ {
$with['user'] = true; $with['user'] = true;
...@@ -104,35 +97,35 @@ class SearchPassing extends Passing ...@@ -104,35 +97,35 @@ class SearchPassing extends Passing
// $tpassing = Yii::app()->request->getQuery('Passing'); // $tpassing = Yii::app()->request->getQuery('Passing');
// $pass_date = 'CONCAT( RIGHT( LEFT( pass_date, 10 ) , 4 ) , "-", TRIM( // $end_date = 'CONCAT( RIGHT( LEFT( end_date, 10 ) , 4 ) , "-", TRIM(
// TRAILING CONCAT( ".", SUBSTRING_INDEX( LEFT( pass_date, 10 ) , ".", -1 ) ) // TRAILING CONCAT( ".", SUBSTRING_INDEX( LEFT( end_date, 10 ) , ".", -1 ) )
// FROM TRIM( // FROM TRIM(
// LEADING CONCAT( SUBSTRING_INDEX( LEFT( pass_date, 10 ) , ".", 1 ) , "." ) // LEADING CONCAT( SUBSTRING_INDEX( LEFT( end_date, 10 ) , ".", 1 ) , "." )
// FROM LEFT( pass_date, 10 ) ) ) , "-", LEFT( pass_date, 2 ) )'; // FROM LEFT( end_date, 10 ) ) ) , "-", LEFT( end_date, 2 ) )';
// if (($tpassing['pass_date']) && (Yii::app()->request->getQuery('date_to'))) { // if (($tpassing['end_date']) && (Yii::app()->request->getQuery('date_to'))) {
// $criteria->addCondition($pass_date.' BETWEEN "'.$tpassing['pass_date'].'" AND "'.Yii::app()->request->getQuery('date_to').'"'); // $criteria->addCondition($end_date.' BETWEEN "'.$tpassing['end_date'].'" AND "'.Yii::app()->request->getQuery('date_to').'"');
// } // }
// elseif(Yii::app()->request->getQuery('date_to')) { // elseif(Yii::app()->request->getQuery('date_to')) {
// $criteria->addCondition($pass_date.' < "'.Yii::app()->request->getQuery('date_to').'"'); // $criteria->addCondition($end_date.' < "'.Yii::app()->request->getQuery('date_to').'"');
// } // }
// elseif($tpassing['pass_date']) { // elseif($tpassing['end_date']) {
// $criteria->addCondition($pass_date.' > "'.Yii::app()->request->getQuery('pass_date').'"'); // $criteria->addCondition($end_date.' > "'.Yii::app()->request->getQuery('end_date').'"');
// } // }
// switch ($this->is_passed) // switch ($this->status)
// { // {
// case Passing::AUTH: // case Passing::AUTH:
// $with['user'] = true; // $with['user'] = true;
// $query->andFilterWhere(['>', 'ser.create_date', '2014-06-05 00:00:00']); // $query->andFilterWhere(['>', 'ser.start_date', '2014-06-05 00:00:00']);
// $query->andFilterWhere([User::tableName() . '.is_auth' => 0]); // $query->andFilterWhere([User::tableName() . '.is_auth' => 0]);
// break; // break;
// case Passing::STARTED: // case Passing::STARTED:
// $query->andFilterWhere([ // $query->andFilterWhere([
// 'is_passed' => 0, // 'status' => 0,
// 'pass_date' => null, // 'end_date' => null,
// Mistake::tableName() . '.passing_id' => null // Mistake::tableName() . '.passing_id' => null
// ]); // ]);
// break; // break;
...@@ -145,7 +138,7 @@ class SearchPassing extends Passing ...@@ -145,7 +138,7 @@ class SearchPassing extends Passing
// case Passing::PASSED: // case Passing::PASSED:
// $with['mistake'] = true; // $with['mistake'] = true;
// $query->andFilterWhere([ // $query->andFilterWhere([
// 'is_passed' => 1, // 'status' => 1,
// Mistake::tableName() . '.passing_id' => null // Mistake::tableName() . '.passing_id' => null
// ]); // ]);
// break; // break;
...@@ -153,16 +146,16 @@ class SearchPassing extends Passing ...@@ -153,16 +146,16 @@ class SearchPassing extends Passing
// case Passing::FAILED: // case Passing::FAILED:
// $with['mistake'] = true; // $with['mistake'] = true;
// $query->andFilterWhere([ // $query->andFilterWhere([
// 'is_passed' => 0, // 'status' => 0,
// Mistake::tableName() . '.passing_id' => null // Mistake::tableName() . '.passing_id' => null
// ]); // ]);
// $query->andFilterWhere(['not', 'pass_date', null]); // $query->andFilterWhere(['not', 'end_date', null]);
// break; // break;
// case Passing::NOT_STARTED: // case Passing::NOT_STARTED:
// $with['mistake'] = true; // $with['mistake'] = true;
// $query->andFilterWhere([ // $query->andFilterWhere([
// 'is_passed' => null, // 'status' => null,
// Mistake::tableName() . '.passing_id' => null // Mistake::tableName() . '.passing_id' => null
// ]); // ]);
// break; // break;
...@@ -183,7 +176,7 @@ class SearchPassing extends Passing ...@@ -183,7 +176,7 @@ class SearchPassing extends Passing
{ {
$query = $this->query(Yii::$app->request->queryParams); $query = $this->query(Yii::$app->request->queryParams);
$query->andWhere(['is_passed' => 1]); $query->andWhere(['status' => 1]);
return $query->count(); return $query->count();
} }
...@@ -192,7 +185,7 @@ class SearchPassing extends Passing ...@@ -192,7 +185,7 @@ class SearchPassing extends Passing
{ {
$query = $this->query(Yii::$app->request->queryParams); $query = $this->query(Yii::$app->request->queryParams);
$query->andWhere(['is_passed' => 0]); $query->andWhere(['status' => 0]);
return $query->count(); return $query->count();
} }
...@@ -201,7 +194,7 @@ class SearchPassing extends Passing ...@@ -201,7 +194,7 @@ class SearchPassing extends Passing
{ {
$query = $this->query(Yii::$app->request->queryParams); $query = $this->query(Yii::$app->request->queryParams);
$query->andWhere(['is_passed' => 2]); $query->andWhere(['status' => 2]);
return $query->count(); return $query->count();
} }
...@@ -210,7 +203,7 @@ class SearchPassing extends Passing ...@@ -210,7 +203,7 @@ class SearchPassing extends Passing
{ {
$query = $this->query(Yii::$app->request->queryParams); $query = $this->query(Yii::$app->request->queryParams);
$query->andWhere(['is_passed' => null]); $query->andWhere(['status' => null]);
return $query->count(); return $query->count();
} }
......
...@@ -106,7 +106,7 @@ class Session extends \common\components\ActiveRecordModel ...@@ -106,7 +106,7 @@ class Session extends \common\components\ActiveRecordModel
$query->andWhere([ $query->andWhere([
Test::tableName() . '.session_id' => $this->id, Test::tableName() . '.session_id' => $this->id,
'is_passed' => Passing::PASSED, 'status' => Passing::PASSED,
]); ]);
$query->groupBy(['user_id', 'test_id']); $query->groupBy(['user_id', 'test_id']);
......
<?php
/*
$this->tabs = array(
'добавить' => $this->createUrl('create')
);
*/
$this->widget('AdminGrid', array(
'id' => 'testing-mistake-grid',
'dataProvider' => $model->search(),
'filter' => $model,
'columns' => array(
array('name' => 'passing_id'),
array('name' => 'description'),
array(
'name' => 'is_expert_agreed',
'value' => 'TestingMistake::$state_list[$data->is_expert_agreed]',
),
array('name' => 'create_date'),
array(
'class' => 'CButtonColumn',
),
),
));
<?php
echo $form;
\ No newline at end of file
<?php
use yii\helpers\Html;
use yii\widgets\DetailView;
use common\modules\testings\models\Mistake;
/* @var $this yii\web\View */
?>
<div class="faq-view">
<p>
<?= Html::a(Yii::t('content', 'Update'), ['update', 'passing' => $model->passing_id], ['class' => 'btn btn-primary']) ?>
</p>
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'description',
[
'attribute' => 'is_expert_agreed',
'value' => Mistake::$state_list[$model->is_expert_agreed],
],
'create_date',
],
]) ?>
</div>
<?php
// if ($model->files) {
// $this->widget('fileManager.portlets.FileList', array(
// 'model' => $model,
// 'tag' => 'files',
// 'tagName' => 'div',
// 'htmlOptions' => array(
// 'class' => 'file-list',
// 'style' => 'margin: 20px 10px 0 10px;'
// ),
// ));
// }
\ No newline at end of file
...@@ -62,14 +62,6 @@ use common\modules\testings\models\Passing; ...@@ -62,14 +62,6 @@ use common\modules\testings\models\Passing;
return Html::a($model->user->email, "mailto:" . $model->user->email); return Html::a($model->user->email, "mailto:" . $model->user->email);
} }
], ],
[
'attribute' => 'filter_user_company_name',
'format' => 'html',
'value' => function($model)
{
return $model->user->company_name;
}
],
[ [
'attribute' => 'test_id', 'attribute' => 'test_id',
'format' => 'html', 'format' => 'html',
...@@ -80,7 +72,7 @@ use common\modules\testings\models\Passing; ...@@ -80,7 +72,7 @@ use common\modules\testings\models\Passing;
} }
], ],
[ [
'attribute' => 'is_passed', 'attribute' => 'status',
'format' => 'html', 'format' => 'html',
'filter' => Passing::$state_list, 'filter' => Passing::$state_list,
'value' => function($model) 'value' => function($model)
...@@ -88,46 +80,16 @@ use common\modules\testings\models\Passing; ...@@ -88,46 +80,16 @@ use common\modules\testings\models\Passing;
return Html::tag("span", Passing::$state_list[$model->status], ["class" => "STATE" . $model->status]); return Html::tag("span", Passing::$state_list[$model->status], ["class" => "STATE" . $model->status]);
} }
], ],
'pass_date', [
[ 'attribute' => 'passed',
'header' => 'Ответственный менеджер',
'format' => 'html',
'value' => function($model)
{
if($model->user && $model->user->manager)
{
return Html::a($model->user->manager->name, ["/users/user-admin/view", "id" => $model->user->manager->id]);
}
else
{
return "Пользователь удалён";
}
}
],
[
'header' => 'Загрузить сообщение об ошибке',
'format' => 'html', 'format' => 'html',
'filter' => false, 'filter' => Passing::$passed_list,
'value' => function($model) 'value' => function($model)
{ {
if($model->is_passed !== null) return Html::tag("span", Passing::$passed_list[$model->passed], ["class" => "STATE" . $model->passed]);
{
if($model->mistake)
{
$text = "Сведения " . $model->mistake->create_date;
}
else
{
$text = "Загрузить";
}
return Html::a($text, ["/testings/passing-admin/mistake", "id" => $model->id]);
}
else
{
return "";
}
} }
], ],
'end_date',
[ [
'class' => 'common\components\ColorActionColumn', 'class' => 'common\components\ColorActionColumn',
'template' => '{view} {delete}', 'template' => '{view} {delete}',
......
...@@ -66,14 +66,6 @@ use \common\components\zii\AdminGrid; ...@@ -66,14 +66,6 @@ use \common\components\zii\AdminGrid;
return Html::a("Список групп", ["/testings/user-admin/manage-group", "session" => $model->id]); return Html::a("Список групп", ["/testings/user-admin/manage-group", "session" => $model->id]);
}, },
], ],
[
'header' => 'Список пользователей',
'format' => 'html',
'value' => function($model)
{
// return Html::a("Список пользователей", ["/testings/user-admin/manage", "session" => $model->id]);
},
],
[ [
'header' => 'Список прохождений', 'header' => 'Список прохождений',
'format' => 'html', 'format' => 'html',
...@@ -82,14 +74,6 @@ use \common\components\zii\AdminGrid; ...@@ -82,14 +74,6 @@ use \common\components\zii\AdminGrid;
return Html::a("Список прохождений", ["/testings/passing-admin/manage", "session" => $model->id]); return Html::a("Список прохождений", ["/testings/passing-admin/manage", "session" => $model->id]);
}, },
], ],
// [
// 'header' => 'Статистика прохождений',
// 'format' => 'html',
// 'value' => function($model)
// {
// return Html::a("Статистика прохождений", ["/testings/passing-admin/statistics", "session" => $model->id]);
// },
// ],
[ [
'class' => 'common\components\ColorActionColumn', 'class' => 'common\components\ColorActionColumn',
'template' => '{view} {update}', 'template' => '{view} {update}',
......
...@@ -90,4 +90,6 @@ $this->crumbs = array( ...@@ -90,4 +90,6 @@ $this->crumbs = array(
</div> </div>
</div> </div>
</div> </div>
<br> <br>
\ No newline at end of file
<?php echo $this->render('@app/views/layouts/footer-testing'); ?>
\ No newline at end of file
<?php
use common\modules\testings\widgets\NotCloseTabsWidget;
use common\modules\testings\models\Question;
?>
<?= NotCloseTabsWidget::widget() ?>
<?php
$questions = [];
$count = 0;
foreach ($model->questions as $question)
{
$count++;
$pictures = [];
foreach ($question->question->files as $file)
{
$pictures[] = $file->url;
}
$answers = [];
// если ответ вводит сам пользователь, нельзя отправлять ответ - поскольку в нём указан верный ответ.
foreach ($question->question->answers as $answer)
{
if ($question->question->type <> Question::USER_ANSWER)
{
$answers[] = $answer->text;
}
else
{
$answers[] = 'тут должен быть ответ';
}
}
$questions[$count] = [
'id' => $question->question->id,
'text' => $question->question->text,
'type' => $question->question->type,
'pictures' => $pictures,
'answers' => $answers,
'userAnswer' => '',
'time' => 0,
'gamma' => $question->question->gamma->name,
];
}
?>
<script type="text/javascript">
function updatePicture(link)
{
var img = $(link).prev('img');
var imgCopy = img.clone();
img.remove();
imgCopy.insertBefore(link);
return false;
}
</script>
<script type="text/javascript">
$(function(){
countDown = {
init : function() {
<?php if(!$model->pass_date_start) { ?>
this.current_time = new Date('<?=date("d F Y H:i:s", strtotime($model->pass_date_start))?>');
this.end_time = new Date(this.current_time);
this.end_time.setMinutes( this.current_time.getMinutes() + <?=$model->test->minutes;?> );
<? } else {
$d1 = time();
$d2 = strtotime($model->pass_date_start);
$interval = $d1 - $d2; ?>
this.current_time = new Date();
this.end_time = new Date(this.current_time);
this.end_time.setSeconds( this.current_time.getSeconds() + <?=($model->test->minutes * 60) - $interval;?> );
<? } ?>
this.tick();
},
convert : function(x) {
if (x > 0)
{
if (x < 60)
{
h = 0;
m = 0;
s = x;
}
if (x >= 60)
{
sec = x / 60;
a = (sec.toString()).split(".");
s = x - (a[0] * 60);
if (a[0] < 60)
{
h = 0;
m = a[0];
}
if (a[0] >= 60)
{
b = ((a[0] / 60).toString()).split(".");
h = b[0];
m = a[0] - (b[0] * 60);
}
}
if (h < 10) { h = h.toString(); h = "0" + h; }
if (m < 10) { m = m.toString(); m = "0" + m; }
if (s < 10) { s = s.toString(); s = "0" + s; }
return h + ":" + m + ":" + s;
}
return '00:00:00';
},
showOnThePage : function(millisec) {
$('#countdown_timer').html(this.convert(parseInt(millisec/1000)));
},
tick : function() {
this.current_time.setSeconds(this.current_time.getSeconds() + 1);
var diff = this.end_time.getTime() - this.current_time.getTime();
this.showOnThePage(diff);
if (diff >= 1) {
setTimeout('countDown.tick()',1000);
} else {
tester.finishTesting();
}
}
}
countDown.init();
});
</script>
<script type="text/javascript">
$(function(){
tester = {
init : function() {
this.global_id = <?=$current_answer?>;
this.one_option = <?php echo TestingQuestion::ONE_OPTION; ?>;
this.few_options = <?php echo TestingQuestion::FEW_OPTIONS; ?>;
this.user_answer = <?php echo TestingQuestion::USER_ANSWER; ?>;
this.delimiter = '<?php echo TestingQuestion::DELIMITER; ?>';
this.questions_count = <?php echo count($questions); ?>;
this.questions = <?php echo json_encode($questions); ?>;
this.questionNumberBox = $('.questionNumber');
this.answerBox = $('#answerBox');
this.questionBox = $('#questionTextBox');
this.pictureBox = $('#questionPictureBox');
this.progressbarText = $('#progressbarText');
this.progressbar = $('#progressbar');
this.timeOfStartOfAnswering = new Date();
this.setQuestion(this.global_id);
},
updateNumber : function() {
this.questionNumberBox.text(this.global_id);
this.updateProgressbar();
},
updateProgressbar : function() {
var progress = Math.round(((this.global_id - 1) / this.questions_count) * 100);
this.progressbarText.text(progress);
this.progressbar.css('width', progress + '%');
},
resetQuestion : function() {
this.questionBox.html('');
this.answerBox.html('');
var sendInfoBox = $('#sendInfoBox');
sendInfoBox.append('<p>Результат Вашего тестирования необходимо отправить на сервер для обработки.</p>');
sendInfoBox.append('<p>Этот процесс может занять некоторое время. Не производите никаких действий и не закрывайте окно браузера до тех пор, пока не будет получен результат тестирования.</p>');
this.pictureBox.html('');
/* delete */
$('#questionGammaBox').html('');
},
setQuestion : function(id) {
var q = this.questions[id];
this.questionBox.text(q['text']);
this.answerBox.html('');
$.each(q['answers'],function(a,b) {
if (q['type'] == tester.one_option) {
var html = '<input id="answer'+a+'" type="radio" name="radio" autocomplete="off">' + b;
var html = '<label class="btn btn-primary" for="answer'+a+'">' + html + '</label>';
var html = '<div class="checkbox_button_wr_1">' + html + '</div>';
var html = '<div class="gray_wr">' + html + '</div>';
tester.answerBox.append(html);
}
if (q['type'] == tester.few_options) {
var html = '<input id="answer'+a+'" type="checkbox" name="radio" autocomplete="off">' + b;
var html = '<label class="btn btn-primary" for="answer'+a+'">' + html + '</label>';
var html = '<div class="checkbox_button_wr_2">' + html + '</div>';
var html = '<div class="gray_wr">' + html + '</div>';
tester.answerBox.append(html);
}
if (q['type'] == tester.user_answer) {
tester.answerBox.html('');
tester.answerBox.append('<div class="gray_wr"><input type="text" value="" placeholder="Ваш ответ" /></div>');
}
tester.answerBox.append('<div class="clear"></div>');
});
this.answersChangeStatus();
this.pictureBox.html('');
$.each(q['pictures'],function(a,b) {
tester.pictureBox.append('<img src="'+b+'" /><span class="fakeLink" onclick="updatePicture(this);">Обновить изображение</span><br /><br />');
});
/* delete */
$('#questionGammaBox').text(q['gamma']);
this.updateNumber();
},
saveAnswer : function(id)
{
var send = false;
var clickNext = $('#clickNext');
var q = this.questions[id];
var answer = [];
if (q['type'] == this.one_option)
{
tester.answerBox.find('input:radio:checked').each(function(){
answer.push($(this).parent().text());
});
}
if (q['type'] == this.few_options)
{
tester.answerBox.find('input:checkbox:checked').each(function(){
answer.push($(this).parent().text());
});
}
if (q['type'] == this.user_answer)
{
tester.answerBox.find('textarea').each(function(){
answer.push($(this).val());
});
}
// сохранение времени ответа
var current_time = new Date();
var diff = current_time.getTime() - this.timeOfStartOfAnswering.getTime();
var time = diff/1000;
this.timeOfStartOfAnswering = new Date();
clickNext.attr('disabled','disabled');
// сохранение ответа
$.ajax({
url : '<?php echo Yii::app()->createAbsoluteUrl('/testings/testingTest/setAnswer/id/'.$model->id); ?>',
data : {
'question_id' : q['id'],
'userAnswer' : answer.join(this.delimiter),
'time' : time
},
dataType : 'json',
type : 'POST',
timeout : 20000,
success : function(data) {
if(data.success)
{
$('#button'+tester.global_id).removeClass('selected');
if (tester.global_id == tester.questions_count)
{
tester.finishTesting();
}
else
{
tester.global_id++;
$('#button'+tester.global_id).addClass('selected');
tester.setQuestion(tester.global_id);
tester.restoreUserAnswer(tester.global_id);
}
if($('#messageStep50').data('timer') != 'true' && data.percentStep == 50)
{
$('#messageStep50').data('timer', 'true');
$('#messageStep50').text(data.messageStep);
setTimeout(function(){
$('#messageStep50').css('display', 'none');
}, 10000);
}
else if($('#messageStep75').data('timer') != 'true' && data.percentStep == 75)
{
$('#messageStep75').data('timer', 'true');
$('#messageStep75').text(data.messageStep);
setTimeout(function(){
$('#messageStep75').css('display', 'none');
}, 10000);
}
else if(data.percentStep == 100)
{
$('#messageStep100').text(data.messageStep);
}
}
else
{
$('p.uploading_info').remove();
clickFinish.removeAttr('disabled');
sendInfoBox.append('<p class="uploading_info" style="color: red;">Произошла ошибка при отправке данных!</p>');
sendInfoBox.append('<p class="uploading_info" style="color: red;">Подождите пару минут и нажмите на кнопку ниже.</p>');
}
if (($('#answerBox input:radio:checked').length > 0)
|| ($('#answerBox input:checkbox:checked').length > 0)
|| ($('#answerBox input[type="text"]').length > 0)
) {
clickNext.removeAttr('disabled');
} else {
clickNext.attr('disabled','disabled');
}
},
error : function() {
$('p.uploading_info').remove();
clickFinish.removeAttr('disabled');
sendInfoBox.append('<p class="uploading_info" style="color: red;">Произошла ошибка при отправке данных!</p>');
sendInfoBox.append('<p class="uploading_info" style="color: red;">Подождите пару минут и нажмите на кнопку ниже.</p>');
}
});
this.updateNumber();
},
restoreUserAnswer : function(id) {
var q = this.questions[id];
var userAnswer = q['userAnswer'];
var answers = userAnswer.split(this.delimiter);
if (q['type'] == this.one_option) {
$.each(answers,function(a,b){
$('#answerBox label').each(function(){
if ($(this).text() == b) {
$(this).prev('input:radio').attr('checked','checked');
}
});
});
}
if (q['type'] == this.few_options) {
$.each(answers,function(a,b){
$('#answerBox label').each(function(){
if ($(this).text() == b) {
$(this).prev('input:checkbox').attr('checked','checked');
}
});
});
}
if (q['type'] == this.user_answer) {
$.each(answers,function(a,b){
$('#answerBox textarea').text(b);
});
}
},
finishTesting : function() {
var clickNext = $('#clickNext');
var clickFinish = $('#clickFinish');
var sendInfoBox = $('#sendInfoBox');
clickNext.css('display','none');
this.resetQuestion();
$('p.uploading_info').remove();
clickFinish.css('display','inline-block');
clickFinish.attr('disabled','disabled');
sendInfoBox.append('<p class="uploading_info">Подождите, происходит отправка данных…</p>');
sendInfoBox.append('<p class="uploading_info"><img src="/images/site/preloader.gif"></img></p>');
var request = $.ajax({
url : '<?php echo Yii::app()->createAbsoluteUrl('/testings/testingTest/finishTest/id/'.$model->id); ?>',
data : {
'questions': tester.questions
},
dataType : 'json',
type : 'POST',
timeout : 20000
});
request.done(function(){
//window.history.go();
window.location.href = '<?php echo Yii::app()->createAbsoluteUrl('/testings/testingTest/pass/id/'.$model->id); ?>';
});
request.fail(function(){
$('p.uploading_info').remove();
clickFinish.removeAttr('disabled');
sendInfoBox.append('<p class="uploading_info" style="color: red;">Произошла ошибка при отправке данных!</p>');
sendInfoBox.append('<p class="uploading_info" style="color: red;">Подождите пару минут и нажмите на кнопку ниже.</p>');
});
},
nextQuestion : function()
{
this.saveAnswer(this.global_id);
},
answersChangeStatus : function() {
var clickNext = $('#clickNext');
if (($('#answerBox input:radio:checked').length > 0)
|| ($('#answerBox input:checkbox:checked').length > 0)
|| ($('#answerBox input[type="text"]').length > 0)
) {
clickNext.removeAttr('disabled');
} else {
clickNext.attr('disabled','disabled');
}
}
}
tester.init();
$('#answerBox').on('change','*',tester.answersChangeStatus);
});
</script>
<section class="top_line_testing">
<div class="container">
<div class="row">
<div class="col-md-12 col-xs-12 col-sm-12">
<strong>Тест:</strong>
<!-- <p>Базовые знания интернет-маркетинг для бизнеса | Как правильно общаться с заказчиком?</p> -->
</div>
</div>
</div>
</section>
<section class="testing_block">
<div class="container">
<div class="row">
<div class="col-md-1 col-xs-1 col-sm-2">
<span class="testing_num questionNumber">1</span>
</div>
<div class="col-md-11 col-xs-11 col-sm-10">
<h1 class="testing_block_title" id="questionTextBox"></h1>
</div>
</div>
<div class="row">
<div class="col-md-4 col-xs-4 col-sm-12">
<div class="number_questions_img_box" id="questionPictureBox"></div>
<!-- <div class="testing_img_block">
<img src="/images/testing_img.jpg" height="123" width="203" alt="">
</div> -->
</div>
</div>
<div class="row">
<div class="col-md-12 col-xs-12 col-sm-12">
<form class="testing_form">
<div class="questions" id="answerBox" data-toggle="buttons" class="btn-group"></div>
<div class="answer" id="sendInfoBox"></div>
<!-- <div class="input_bg">
<input id="radio1" type="radio" name="radio" class="radio" checked>
<label for="radio1">Только макет в PSD</label>
</div>
<div class="input_bg">
<input id="checkbox1" type="checkbox" class="checkbox">
<label for="checkbox1">Макет и техническое задание по проекту</label>
</div>
<div class="input_bg">
<input id="radio2" type="radio" name="radio" class="radio">
<label for="radio2">Макет и задание описывающее краткий функционал front-end (дизайна)</label>
</div>
<div class="input_bg">
<input type="text" placeholder="Ваш ответ">
</div> -->
<button class="testing_form_btn" onClick="tester.nextQuestion();">Подтвердить ответ</button>
</form>
</div>
</div>
<div class="row col-md-12 col-xs-12 col-sm-12">
<h4 class="testing_info_foot" id="messageStep50"></h4>
<h4 class="testing_info_foot" id="messageStep75"></h4>
<h4 class="testing_info_foot" id="messageStep100"></h4>
</div>
</div>
</section>
<section class="testing_foot">
<div class="container">
<div class="row">
<div class="test_ft clearfix">
<div class="col-md-6 col-xs-8 col-sm-12">
<div class="testing_votes">Вопрос <strong class="questionNumber">1</strong> из <strong><?=count($questions)?></strong></div>
<div class="testing_progress"><div class="testing_progress_proc" id="progressbar" style="width:0%;"></div></div>
</div>
<div class="col-md-6 col-xs-4 col-sm-12">
<div class="testing_time">До конца осталось: <span id="countdown_timer"></span></div>
</div>
</div>
</div>
</div>
</section>
\ No newline at end of file
<?php
use common\modules\testings\models\Passing;
?>
<section class="top_line_testing"> <section class="top_line_testing">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
...@@ -12,10 +18,10 @@ ...@@ -12,10 +18,10 @@
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-md-12 col-xs-12 col-sm-12"> <div class="col-md-12 col-xs-12 col-sm-12">
<?php if ($model->is_passed == TestingPassing::PASSED) : ?> <?php if ($model->passed == Passing::PASSED) : ?>
<h1 class="successfully_title">Поздравляем, Вы сдали тест</h1> <h1 class="successfully_title">Поздравляем, Вы сдали тест</h1>
<div class="successfully_subtitle">Тестирование завершено</div> <div class="successfully_subtitle">Тестирование завершено</div>
<?php elseif ($model->is_passed == TestingPassing::FAILED) : ?> <?php elseif ($model->passed == Passing::FAILED) : ?>
<h1 class="successfully_title">Тест не сдан!</h1> <h1 class="successfully_title">Тест не сдан!</h1>
<div class="successfully_subtitle">Тестирование завершено</div> <div class="successfully_subtitle">Тестирование завершено</div>
<?php endif; ?> <?php endif; ?>
...@@ -61,4 +67,6 @@ ...@@ -61,4 +67,6 @@
</div> </div>
</div> </div>
</div> </div>
</section> </section>
\ No newline at end of file
<?php echo $this->render('@app/views/layouts/footer-testing'); ?>
\ No newline at end of file
<?php
use yii\helpers\Url;
use common\modules\testings\widgets\NotCloseTabsWidget;
use common\modules\testings\models\Question;
?>
<?php
$questions = [];
$count = 0;
foreach ($model->questions as $question)
{
$count++;
$pictures = [];
foreach ($question->question->files as $file)
{
$pictures[] = $file->url;
}
$answers = [];
// если ответ вводит сам пользователь, нельзя отправлять ответ - поскольку в нём указан верный ответ.
foreach ($question->question->answers as $answer)
{
if ($question->question->type <> Question::USER_ANSWER)
{
$answers[] = $answer->text;
}
else
{
$answers[] = 'тут должен быть ответ';
}
}
$questions[$count] = [
'id' => $question->question->id,
'text' => $question->question->text,
'type' => $question->question->type,
'pictures' => $pictures,
'answers' => $answers,
'userAnswer' => '',
'time' => 0,
'theme' => $question->question->theme->name,
];
}
?>
<script type="text/javascript">
$(function(){
countDown.init({
continue: <?=($model->start_date?'true':'false')?>,
startDate: '<?=date("d F Y H:i:s", strtotime($model->start_date))?>',
startDateTime: <?=strtotime($model->start_date)?>,
minutes: <?=$model->test->minutes;?>,
time: <?=time()?>
});
tester.init({
global_id: <?=$current_answer?>,
one_option: <?=Question::ONE_OPTION?>,
few_options: <?=Question::FEW_OPTIONS?>,
user_answer: <?=Question::USER_ANSWER?>,
delimiter: '<?=Question::DELIMITER?>',
questions_count: <?=count($questions)?>,
questions: <?=\yii\helpers\Json::encode($questions)?>,
answerUrl: '<?=Url::to(["/testing/set-answer/".$model->id])?>',
finishUrl: '<?=Url::to(["/testing/finish-test/".$model->id])?>',
passUrl: '<?=Url::to(["/testing/pass/".$model->id])?>'
});
$('#answerBox').on('change','*',tester.answersChangeStatus);
});
</script>
<section class="top_line_testing">
<div class="container">
<div class="row">
<div class="col-md-12 col-xs-12 col-sm-12">
<strong>Тест: </strong>
<p><?=$model->test->name?> | <span id="questionThemeBox"></span></p>
</div>
</div>
</div>
</section>
<section class="testing_block">
<div class="container">
<?= NotCloseTabsWidget::widget() ?>
<br>
<div class="row">
<div class="col-md-1 col-xs-1 col-sm-2">
<span class="testing_num questionNumber"></span>
</div>
<div class="col-md-11 col-xs-11 col-sm-10">
<h1 class="testing_block_title" id="questionTextBox"></h1>
</div>
</div>
<div class="row">
<div class="col-md-4 col-xs-4 col-sm-12">
<div class="number_questions_img_box" id="questionPictureBox"></div>
<!-- <div class="testing_img_block">
<img src="/images/testing_img.jpg" height="123" width="203" alt="">
</div> -->
</div>
</div>
<div class="row">
<div class="col-md-12 col-xs-12 col-sm-12">
<form class="testing_form">
<div class="questions" id="answerBox"></div>
<div class="answer" id="sendInfoBox"></div>
<!-- <div class="input_bg">
<input id="radio1" type="radio" name="radio" class="radio" checked>
<label for="radio1">Только макет в PSD</label>
</div>
<div class="input_bg">
<input id="checkbox1" type="checkbox" class="checkbox">
<label for="checkbox1">Макет и техническое задание по проекту</label>
</div>
<div class="input_bg">
<input id="radio2" type="radio" name="radio" class="radio">
<label for="radio2">Макет и задание описывающее краткий функционал front-end (дизайна)</label>
</div>
<div class="input_bg">
<input type="text" placeholder="Ваш ответ">
</div> -->
<button id="clickNext" class="testing_form_btn" onClick="tester.nextQuestion(); return false;">Подтвердить ответ</button>
</form>
</div>
</div>
<div class="row col-md-12 col-xs-12 col-sm-12">
<h4 class="testing_info_foot" id="messageStep50"></h4>
<h4 class="testing_info_foot" id="messageStep75"></h4>
<h4 class="testing_info_foot" id="messageStep100"></h4>
</div>
</div>
</section>
<section class="testing_foot">
<div class="container">
<div class="row">
<div class="test_ft clearfix">
<div class="col-md-6 col-xs-8 col-sm-12">
<div class="testing_votes">Вопрос <strong class="questionNumber">1</strong> из <strong><?=count($questions)?></strong></div>
<div class="testing_progress"><div class="testing_progress_proc" id="progressbar" style="width:0%;"></div></div>
</div>
<div class="col-md-6 col-xs-4 col-sm-12">
<div class="testing_time">До конца осталось: <span id="countdown_timer"></span></div>
</div>
</div>
</div>
</div>
</section>
<?php echo $this->render('@app/views/layouts/footer-testing'); ?>
\ No newline at end of file
...@@ -10,7 +10,7 @@ class NotCloseTabsWidget extends Widget ...@@ -10,7 +10,7 @@ class NotCloseTabsWidget extends Widget
public function run() public function run()
{ {
return $this->render('NotCloseTabsWidget', [ return $this->render('NotCloseTabsWidget', [
'message' => Settings::getValue('not_close_tabs_message'); 'message' => Settings::getValue('not_close_tabs_message')
]); ]);
} }
} }
......
<?php
use yii\db\Schema;
use yii\db\Migration;
class m160225_043622_fix_passing_table extends Migration
{
// Use safeUp/safeDown to run migration code within a transaction
public function safeUp()
{
$this->alterColumn('testings_passings', 'attempt', Schema::TYPE_INTEGER . '(3) NOT NULL DEFAULT 0');
$this->addColumn('testings_passings', 'percent', Schema::TYPE_INTEGER . '(11) NOT NULL DEFAULT 0 AFTER points');
$this->addColumn('testings_passings', 'passed', Schema::TYPE_INTEGER . '(1) NOT NULL DEFAULT 0 AFTER status');
$this->dropTable('testings_mistakes');
}
public function safeDown()
{
$this->alterColumn('testings_passings', 'attempt', Schema::TYPE_INTEGER . '(3) NOT NULL');
$this->dropColumn('testings_passings', 'percent');
$this->dropColumn('testings_passings', 'passed');
$this->createTable('testings_mistakes', [
'id' => Schema::TYPE_PK,
'passing_id' => Schema::TYPE_INTEGER . '(11) NOT NULL',
'description' => Schema::TYPE_STRING . '(3000) NOT NULL',
'is_expert_agreed' => 'tinyint(1) NOT NULL',
'create_date' => Schema::TYPE_TIMESTAMP . ' NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP',
]);
}
}
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<?php $this->registerJsFile('/js/modernizr.min.js', ['position' => yii\web\View::POS_END ]);?> <?php $this->registerJsFile('/js/modernizr.min.js', ['position' => yii\web\View::POS_END ]);?>
<?php $this->registerJsFile('/js/libs/bootstrap/js/bootstrap.min.js', ['position' => yii\web\View::POS_END ]);?> <?php $this->registerJsFile('/js/libs/bootstrap/js/bootstrap.js', ['position' => yii\web\View::POS_END ]);?>
<?php $this->registerJsFile('/js/libs/waypoints/waypoints.min.js', ['position' => yii\web\View::POS_END ]);?> <?php $this->registerJsFile('/js/libs/waypoints/waypoints.min.js', ['position' => yii\web\View::POS_END ]);?>
<?php $this->registerJsFile('/js/libs/magnific/jquery.magnific-popup.min.js', ['position' => yii\web\View::POS_END ]);?> <?php $this->registerJsFile('/js/libs/magnific/jquery.magnific-popup.min.js', ['position' => yii\web\View::POS_END ]);?>
<?php $this->registerJsFile('/js/libs/bxslider/jquery.bxslider.min.js', ['position' => yii\web\View::POS_END ]);?> <?php $this->registerJsFile('/js/libs/bxslider/jquery.bxslider.min.js', ['position' => yii\web\View::POS_END ]);?>
......
...@@ -48,6 +48,13 @@ section .container ol:not([class]) li { ...@@ -48,6 +48,13 @@ section .container ol:not([class]) li {
section.reviews-block .row { section.reviews-block .row {
margin-bottom: 50px; margin-bottom: 50px;
} }
.input_bg {
padding: 6px 10px 13px;
line-height: 18px;
}
.input_bg label {
padding: 6px 0px 0px 35px !important;
}
a.login_form_link, a.login_form_popup_link, a.reg_popup_link, a.reg_form_link{ a.login_form_link, a.login_form_popup_link, a.reg_popup_link, a.reg_form_link{
margin-top: 20px; margin-top: 20px;
display: block; display: block;
......
function updatePicture(link)
{
var img = $(link).prev('img');
var imgCopy = img.clone();
img.remove();
imgCopy.insertBefore(link);
return false;
}
countDown = {
init : function(options)
{
this.options = options;
if(!this.options.continue)
{
this.current_time = new Date(this.options.startDate);
this.end_time = new Date(this.current_time);
this.end_time.setMinutes( this.current_time.getMinutes() + this.options.minutes );
}
else
{
interval = this.options.time - this.options.startDateTime;
this.current_time = new Date();
this.end_time = new Date(this.current_time);
this.end_time.setSeconds( this.current_time.getSeconds() + (this.options.minutes * 60) - interval );
}
this.tick();
},
convert : function(x)
{
if (x > 0)
{
if (x < 60)
{
h = 0;
m = 0;
s = x;
}
if (x >= 60)
{
sec = x / 60;
a = (sec.toString()).split(".");
s = x - (a[0] * 60);
if (a[0] < 60)
{
h = 0;
m = a[0];
}
if (a[0] >= 60)
{
b = ((a[0] / 60).toString()).split(".");
h = b[0];
m = a[0] - (b[0] * 60);
}
}
if (h < 10) { h = h.toString(); h = "0" + h; }
if (m < 10) { m = m.toString(); m = "0" + m; }
if (s < 10) { s = s.toString(); s = "0" + s; }
return h + ":" + m + ":" + s;
}
return '00:00:00';
},
showOnThePage : function(millisec)
{
$('#countdown_timer').html(this.convert(parseInt(millisec/1000)));
},
tick : function()
{
this.current_time.setSeconds(this.current_time.getSeconds() + 1);
var diff = this.end_time.getTime() - this.current_time.getTime();
this.showOnThePage(diff);
if (diff >= 1) {
setTimeout('countDown.tick()',1000);
} else {
tester.finishTesting();
}
}
};
tester = {
init : function(options)
{
this.options = options;
this.questionNumberBox = $('.questionNumber');
this.answerBox = $('#answerBox');
this.questionBox = $('#questionTextBox');
this.pictureBox = $('#questionPictureBox');
this.progressbarText = $('#progressbarText');
this.progressbar = $('#progressbar');
this.timeOfStartOfAnswering = new Date();
this.setQuestion(this.options.global_id);
},
updateNumber : function()
{
this.questionNumberBox.text(this.options.global_id);
this.updateProgressbar();
},
updateProgressbar : function()
{
var progress = Math.round(((this.options.global_id - 1) / this.options.questions_count) * 100);
this.progressbarText.text(progress);
this.progressbar.css('width', progress + '%');
},
resetQuestion : function()
{
this.questionBox.html('');
this.answerBox.html('');
var sendInfoBox = $('#sendInfoBox');
sendInfoBox.append('<p>Результат Вашего тестирования необходимо отправить на сервер для обработки.</p>');
sendInfoBox.append('<p>Этот процесс может занять некоторое время. Не производите никаких действий и не закрывайте окно браузера до тех пор, пока не будет получен результат тестирования.</p>');
this.pictureBox.html('');
/* delete */
$('#questionThemeBox').html('');
},
setQuestion : function(id)
{
var q = this.options.questions[id];
this.questionBox.text(q['text']);
this.answerBox.html('');
$.each(q['answers'],function(a,b) {
if (q['type'] == tester.options.one_option) {
html = '<input id="answer-'+a+'" type="radio" name="radio" class="radio"><label for="answer-'+a+'">' + b + '</label>';
html = '<div class="input_bg">' + html + '</div>';
tester.answerBox.append(html);
}
if (q['type'] == tester.options.few_options) {
html = '<input id="answer-'+a+'" type="checkbox" class="checkbox"><label for="answer-'+a+'">' + b + '</label>';
html = '<div class="input_bg">' + html + '</div>';
tester.answerBox.append(html);
}
if (q['type'] == tester.options.user_answer) {
tester.answerBox.html('');
tester.answerBox.append('<div class="input_bg"><input type="text" value="" placeholder="Ваш ответ" /></div>');
}
tester.answerBox.append('<div class="clear"></div>');
});
this.answersChangeStatus();
this.pictureBox.html('');
$.each(q['pictures'],function(a,b) {
tester.pictureBox.append('<img src="'+b+'" /><span class="fakeLink" onclick="updatePicture(tester);">Обновить изображение</span><br /><br />');
});
/* delete */
$('#questionThemeBox').text(q['theme']);
this.updateNumber();
},
saveAnswer : function(id)
{
var send = false;
var clickNext = $('#clickNext');
var q = this.options.questions[id];
var answer = [];
if (q['type'] == this.options.one_option)
{
this.answerBox.find('input:radio:checked').each(function(){
answer.push($(this).parent().text());
});
}
if (q['type'] == this.options.few_options)
{
this.answerBox.find('input:checkbox:checked').each(function(){
answer.push($(this).parent().text());
});
}
if (q['type'] == this.options.user_answer)
{
this.answerBox.find('textarea').each(function(){
answer.push($(this).val());
});
}
// сохранение времени ответа
var current_time = new Date();
var diff = current_time.getTime() - this.timeOfStartOfAnswering.getTime();
var time = diff/1000;
this.timeOfStartOfAnswering = new Date();
clickNext.attr('disabled','disabled');
// сохранение ответа
$.ajax({
url : this.options.answerUrl,
data : {
'question_id' : q['id'],
'userAnswer' : answer.join(this.delimiter),
'time' : time
},
dataType : 'json',
type : 'POST',
timeout : 20000,
success : function(data) {
if(data.success)
{
$('#button'+tester.options.global_id).removeClass('selected');
if (tester.options.global_id == tester.options.questions_count)
{
tester.finishTesting();
}
else
{
tester.options.global_id++;
$('#button'+tester.options.global_id).addClass('selected');
tester.setQuestion(tester.options.global_id);
tester.restoreUserAnswer(tester.options.global_id);
}
if($('#messageStep50').data('timer') != 'true' && data.percentStep == 50)
{
$('#messageStep50').data('timer', 'true');
$('#messageStep50').text(data.messageStep);
setTimeout(function(){
$('#messageStep50').css('display', 'none');
}, 10000);
}
else if($('#messageStep75').data('timer') != 'true' && data.percentStep == 75)
{
$('#messageStep75').data('timer', 'true');
$('#messageStep75').text(data.messageStep);
setTimeout(function(){
$('#messageStep75').css('display', 'none');
}, 10000);
}
else if(data.percentStep == 100)
{
$('#messageStep100').text(data.messageStep);
}
}
else
{
$('p.uploading_info').remove();
clickFinish.removeAttr('disabled');
sendInfoBox.append('<p class="uploading_info" style="color: red;">Произошла ошибка при отправке данных!</p>');
sendInfoBox.append('<p class="uploading_info" style="color: red;">Подождите пару минут и нажмите на кнопку ниже.</p>');
}
if (($('#answerBox input:radio:checked').length > 0)
|| ($('#answerBox input:checkbox:checked').length > 0)
|| ($('#answerBox input[type="text"]').length > 0)
) {
clickNext.removeAttr('disabled');
} else {
clickNext.attr('disabled','disabled');
}
},
error : function() {
$('p.uploading_info').remove();
clickFinish.removeAttr('disabled');
sendInfoBox.append('<p class="uploading_info" style="color: red;">Произошла ошибка при отправке данных!</p>');
sendInfoBox.append('<p class="uploading_info" style="color: red;">Подождите пару минут и нажмите на кнопку ниже.</p>');
}
});
this.updateNumber();
},
restoreUserAnswer : function(id)
{
var q = this.options.questions[id];
var userAnswer = q['userAnswer'];
var answers = userAnswer.split(this.options.delimiter);
if (q['type'] == this.options.one_option) {
$.each(answers,function(a,b){
$('#answerBox label').each(function(){
if ($(this).text() == b) {
$(this).prev('input:radio').attr('checked','checked');
}
});
});
}
if (q['type'] == this.options.few_options) {
$.each(answers,function(a,b){
$('#answerBox label').each(function(){
if ($(this).text() == b) {
$(this).prev('input:checkbox').attr('checked','checked');
}
});
});
}
if (q['type'] == this.options.user_answer) {
$.each(answers,function(a,b){
$('#answerBox textarea').text(b);
});
}
},
finishTesting : function() {
var clickNext = $('#clickNext');
var clickFinish = $('#clickFinish');
var sendInfoBox = $('#sendInfoBox');
clickNext.css('display','none');
this.resetQuestion();
$('p.uploading_info').remove();
clickFinish.css('display','inline-block');
clickFinish.attr('disabled','disabled');
sendInfoBox.append('<p class="uploading_info">Подождите, происходит отправка данных…</p>');
sendInfoBox.append('<p class="uploading_info"><img src="/images/site/preloader.gif"></img></p>');
var request = $.ajax({
url : tester.options.finishUrl,
data : {
'questions': this.options.questions
},
dataType : 'json',
type : 'POST',
timeout : 20000
});
request.done(function() {
window.location.href = tester.options.passUrl;
});
request.fail(function(){
$('p.uploading_info').remove();
clickFinish.removeAttr('disabled');
sendInfoBox.append('<p class="uploading_info" style="color: red;">Произошла ошибка при отправке данных!</p>');
sendInfoBox.append('<p class="uploading_info" style="color: red;">Подождите пару минут и нажмите на кнопку ниже.</p>');
});
},
nextQuestion : function()
{
this.saveAnswer(this.options.global_id);
},
answersChangeStatus : function() {
var clickNext = $('#clickNext');
if (($('#answerBox input:radio:checked').length > 0)
|| ($('#answerBox input:checkbox:checked').length > 0)
|| ($('#answerBox input[type="text"]').length > 0)
) {
clickNext.removeAttr('disabled');
} else {
clickNext.attr('disabled','disabled');
}
}
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment