1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
attempt.php
См. документацию.
1<?php
2
7
8abstract class CAllTestAttempt
9{
10 public function CheckFields(&$arFields, $ID = false, $bCheckRights = true)
11 {
12 global $DB, $APPLICATION;
13
14 if ($ID===false && !is_set($arFields, "TEST_ID"))
15 {
16 $APPLICATION->ThrowException(GetMessage("LEARNING_BAD_TEST_ID"), "EMPTY_TEST_ID");
17 return false;
18 }
19 elseif (is_set($arFields, "TEST_ID"))
20 {
21 if ($bCheckRights)
22 $r = CTest::GetByID($arFields["TEST_ID"]);
23 else
24 {
25 $r = CTest::getList(
26 array(),
27 array(
28 'ID' => $arFields['TEST_ID'],
29 'CHECK_PERMISSIONS' => 'N'
30 )
31 );
32 }
33
34 if(!$r->Fetch())
35 {
36 $APPLICATION->ThrowException(GetMessage("LEARNING_BAD_TEST_ID_EX"), "ERROR_NO_TEST_ID");
37 return false;
38 }
39 }
40
41 if ($ID===false && !is_set($arFields, "STUDENT_ID"))
42 {
43 $APPLICATION->ThrowException(GetMessage("LEARNING_BAD_USER_ID"), "EMPTY_STUDENT_ID");
44 return false;
45 }
46 elseif (is_set($arFields, "STUDENT_ID"))
47 {
48 $dbResult = CUser::GetByID($arFields["STUDENT_ID"]);
49 if (!$dbResult->Fetch())
50 {
51 $APPLICATION->ThrowException(GetMessage("LEARNING_BAD_USER_ID_EX"), "ERROR_NO_STUDENT_ID");
52 return false;
53 }
54 }
55
56 if (is_set($arFields, "DATE_START") && (!$DB->IsDate($arFields["DATE_START"], false, LANG, "FULL")))
57 {
58 $APPLICATION->ThrowException(GetMessage("LEARNING_BAD_DATE_START"), "ERROR_DATE_START");
59 return false;
60 }
61
62 if (is_set($arFields, "DATE_END") && $arFields["DATE_END"] <> '' && (!$DB->IsDate($arFields["DATE_END"], false, LANG, "FULL")))
63 {
64 $APPLICATION->ThrowException(GetMessage("LEARNING_BAD_DATE_END"), "ERROR_DATE_END");
65 return false;
66 }
67
68 //Defaults
69 if (is_set($arFields, "STATUS") && !in_array($arFields["STATUS"], Array("B", "D", "F", "N")))
70 $arFields["STATUS"] = "B";
71
72 if (is_set($arFields, "COMPLETED") && $arFields["COMPLETED"] != "Y")
73 $arFields["COMPLETED"] = "N";
74
75 return true;
76 }
77
78
79 public function Add($arFields)
80 {
82
83 if(CTestAttempt::CheckFields($arFields) && $USER_FIELD_MANAGER->CheckFields("LEARN_ATTEMPT", 0, $arFields))
84 {
85 unset($arFields["ID"]);
86
87 //$ID = $DB->Add("b_learn_attempt", $arFields, Array(""), "learning");
88
89 $arInsert = $DB->PrepareInsert("b_learn_attempt", $arFields, "learning");
90
92
93 CGradeBook::RecountAttempts($arFields["STUDENT_ID"], $arFields["TEST_ID"]);
94
95 if ($ID)
96 {
97 $USER_FIELD_MANAGER->Update("LEARN_ATTEMPT", $ID, $arFields);
98 }
99
100 return $ID;
101 }
102
103 return false;
104 }
105
106
107 public function Update($ID, $arFields, $arParams = array())
108 {
109 global $DB, $USER_FIELD_MANAGER;
110
111 $ID = intval($ID);
112 if ($ID < 1) return false;
113
114 $bCheckRights = true;
115 if (isset($arParams['CHECK_PERMISSIONS']) && ($arParams['CHECK_PERMISSIONS'] === 'N'))
116 $bCheckRights = false;
117
118 if ($this->CheckFields($arFields, $ID, $bCheckRights) && $USER_FIELD_MANAGER->CheckFields("LEARN_ATTEMPT", 0, $arFields))
119 {
120 unset($arFields["ID"]);
121 unset($arFields["TEST_ID"]);
122
123 $arBinds=Array(
124 //""=>$arFields[""]
125 );
126
127 $strUpdate = $DB->PrepareUpdate("b_learn_attempt", $arFields, "learning");
128 $strSql = "UPDATE b_learn_attempt SET ".$strUpdate." WHERE ID=".$ID;
129 $DB->QueryBind($strSql, $arBinds);
130
131 $USER_FIELD_MANAGER->Update("LEARN_ATTEMPT", $ID, $arFields);
132
133 return true;
134 }
135
136 return false;
137 }
138
139
140 public static function Delete($ID)
141 {
142 global $DB, $USER_FIELD_MANAGER;
143
144 $ID = intval($ID);
145 if ($ID < 1) return false;
146
147 //Results
148 $strSql = "DELETE FROM b_learn_test_result WHERE ATTEMPT_ID = ".$ID;
149 if (!$DB->Query($strSql))
150 return false;
151
152 //Attempt
153 $strSql = "DELETE FROM b_learn_attempt WHERE ID = ".$ID;
154 if (!$DB->Query($strSql))
155 return false;
156
157 $USER_FIELD_MANAGER->Delete("LEARN_ATTEMPT", $ID);
158
159 return true;
160 }
161
162
163 public static function GetFilter($arFilter)
164 {
165
166 if (!is_array($arFilter))
167 $arFilter = Array();
168
169 $arSqlSearch = Array();
170
171 foreach ($arFilter as $key => $val)
172 {
174 $key = $res["FIELD"];
175 $cOperationType = $res["OPERATION"];
176
177 $key = mb_strtoupper($key);
178
179 switch ($key)
180 {
181 case "ID":
182 case "TEST_ID":
183 case "STUDENT_ID":
184 case "SCORE":
185 case "MAX_SCORE":
186 case "QUESTIONS":
187 $arSqlSearch[] = CLearnHelper::FilterCreate("A.".$key, $val, "number", $bFullJoin, $cOperationType);
188 break;
189
190 case "SPEED":
191 $arSqlSearch[] = CLearnHelper::FilterCreate(self::getSpeedFieldSql(), $val, "number", $bFullJoin, $cOperationType);
192 break;
193
194 case "STATUS":
195 case "COMPLETED":
196 $arSqlSearch[] = CLearnHelper::FilterCreate("A.".$key, $val, "string_equal", $bFullJoin, $cOperationType);
197 break;
198
199 case "DATE_START":
200 case "DATE_END":
201 $arSqlSearch[] = CLearnHelper::FilterCreate("A.".$key, $val, "date", $bFullJoin, $cOperationType);
202 break;
203
204 case "USER":
205 $arSqlSearch[] = GetFilterQuery("U.ID, U.LOGIN, U.NAME, U.LAST_NAME",$val);
206 break;
207
208 case "USER_LOGIN":
209 $arSqlSearch[] = CLearnHelper::FilterCreate("U.LOGIN", $val, "string_equal", $bFullJoin, $cOperationType);
210 break;
211
212 case "USER_NAME":
213 $arSqlSearch[] = CLearnHelper::FilterCreate("U.NAME", $val, "string_equal", $bFullJoin, $cOperationType);
214 break;
215
216 case "USER_LAST_NAME":
217 $arSqlSearch[] = CLearnHelper::FilterCreate("U.LAST_NAME", $val, "string_equal", $bFullJoin, $cOperationType);
218 break;
219 }
220 }
221
222 return $arSqlSearch;
223 }
224
225
226 public static function GetByID($ID)
227 {
228 if ((int) $ID > 0)
229 return CTestAttempt::GetList(array(), array("ID" => (int) $ID));
230 else
231 return (new CDBResult());
232 }
233
234
235 public static function GetCount($TEST_ID, $STUDENT_ID)
236 {
237 global $DB;
238
239 $strSql =
240 "SELECT COUNT(*) as C ".
241 "FROM b_learn_attempt A ".
242 "WHERE A.TEST_ID = '".intval($TEST_ID)."' AND A.STUDENT_ID = '".intval($STUDENT_ID)."'";
243
244 $res = $DB->Query($strSql);
245 $res_cnt = $res->Fetch();
246
247 return intval($res_cnt["C"]);
248 }
249
250
251 public static function IsTestCompleted($ATTEMPT_ID, $PERCENT)
252 {
253 global $DB;
254
255 $strSql =
256 "SELECT * ".
257 "FROM b_learn_test_result TR, b_learn_question Q ".
258 "WHERE TR.QUESTION_ID = Q.ID AND TR.CORRECT = 'N' AND Q.CORRECT_REQUIRED = 'Y' AND TR.ATTEMPT_ID = '".intval($ATTEMPT_ID)."'";
259
260 if (!$res = $DB->Query($strSql))
261 return false;
262
263 if ($arStat = $res->Fetch())
264 return false;
265
266 $strSql =
267 "SELECT SUM(Q.POINT) as CNT_ALL, SUM(CASE WHEN TR.CORRECT = 'Y' THEN TR.POINT ELSE 0 END) as CNT_RIGHT ".
268 "FROM b_learn_test_result TR, b_learn_question Q ".
269 "WHERE TR.ATTEMPT_ID = '".intval($ATTEMPT_ID)."' AND TR.QUESTION_ID = Q.ID";
270
271 if (!$res = $DB->Query($strSql))
272 return false;
273
274 if (!$arStat = $res->Fetch())
275 return false;
276
277 if($arStat["CNT_RIGHT"]<=0 || $arStat["CNT_ALL"] == 0)
278 return false;
279
280 // Do some magic due to IEEE 754
281 $epsilon = 0.001;
282
283 $scoreForSuccess = (float) ((int) $PERCENT);
284 $userScore = round( ($arStat["CNT_RIGHT"] / $arStat["CNT_ALL"]) * 100, 2);
285
286 $delta = abs($userScore - $scoreForSuccess);
287
288 $isTestComplete = false;
289 if ($userScore > $scoreForSuccess)
290 $isTestComplete = true;
291 elseif ($delta < $epsilon) // it means, that $userScore == $scoreForSuccess
292 $isTestComplete = true;
293
294 return ($isTestComplete);
295 }
296
297
298 public static function OnAttemptChange($ATTEMPT_ID, $bCOMPLETED = false)
299 {
300 global $DB;
301
302 $ATTEMPT_ID = intval($ATTEMPT_ID);
303
304 if ($ATTEMPT_ID < 1)
305 return false;
306
307 $strSql = "SELECT A.*, T.APPROVED, T.COMPLETED_SCORE, T.COURSE_ID ".
308 "FROM b_learn_attempt A ".
309 "INNER JOIN b_learn_test T ON A.TEST_ID = T.ID ".
310 "WHERE A.ID = '".$ATTEMPT_ID."' AND A.STATUS = 'F' ";
311 $res = $DB->Query($strSql);
312 if (!$arAttempt = $res->Fetch())
313 return false;
314
315
316 $COMPLETED = "N";
317 if (
318 $arAttempt["APPROVED"] == "Y" &&
319 intval($arAttempt["COMPLETED_SCORE"])>0 &&
320 CTestAttempt::IsTestCompleted($ATTEMPT_ID,$arAttempt["COMPLETED_SCORE"])
321 )
322 $COMPLETED = "Y";
323
324 if ($bCOMPLETED)
325 $COMPLETED = "Y";
326
327 $strSql =
328 "UPDATE b_learn_attempt SET COMPLETED = '".$COMPLETED."' ".
329 "WHERE ID = '".$ATTEMPT_ID."'";
330
331 if (!$res = $DB->Query($strSql))
332 return false;
333
334 $strSql = "SELECT * FROM b_learn_gradebook WHERE STUDENT_ID='".$arAttempt["STUDENT_ID"]."' AND TEST_ID='".$arAttempt["TEST_ID"]."'";
335 $res = $DB->Query($strSql);
336 if (!$arGradeBook = $res->Fetch())
337 {
338 $arFields = Array(
339 "STUDENT_ID" => $arAttempt["STUDENT_ID"],
340 "TEST_ID" => $arAttempt["TEST_ID"],
341 "RESULT" => $arAttempt["SCORE"],
342 "MAX_RESULT" => intval($arAttempt["MAX_SCORE"]),
343 "COMPLETED" => $COMPLETED,
344 );
345
346 $at = new CGradeBook;
347
348 if (!$res = $at->Add($arFields))
349 return false;
350
351 CCertification::Certificate($arAttempt["STUDENT_ID"], $arAttempt["COURSE_ID"]);
352 }
353 else
354 {
355 $strSql =
356 "SELECT A.SCORE, A.MAX_SCORE FROM b_learn_attempt A ".
357 "WHERE A.STUDENT_ID = '".$arAttempt["STUDENT_ID"]."' AND A.TEST_ID = '".$arAttempt["TEST_ID"]."' ORDER BY COMPLETED DESC, SCORE DESC";
358 //AND A.COMPLETED = 'Y'
359 $res = $DB->Query($strSql);
360 if (!$arMaxScore = $res->Fetch())
361 return false;
362
363 if ($arGradeBook["COMPLETED"] == "Y")
364 $COMPLETED = "Y";
365
366 $strSql =
367 "UPDATE b_learn_gradebook SET RESULT = '".intval($arMaxScore["SCORE"])."', MAX_RESULT = '".intval($arMaxScore["MAX_SCORE"])."',COMPLETED = '".$COMPLETED."' ".
368 "WHERE ID = '".$arGradeBook["ID"]."'";
369
370 if (!$res = $DB->Query($strSql))
371 return false;
372
373 CCertification::Certificate($arAttempt["STUDENT_ID"], $arAttempt["COURSE_ID"]);
374 }
375
376 return true;
377 }
378
379
380 public function AttemptFinished($ATTEMPT_ID)
381 {
382 global $DB;
383
384 $ATTEMPT_ID = intval($ATTEMPT_ID);
385
386 if ($ATTEMPT_ID < 1)
387 return false;
388
389 $strSql =
390 "SELECT SUM(TR.POINT) as SCORE, SUM(Q.POINT) MAX_SCORE ".
391 "FROM b_learn_test_result TR ".
392 "INNER JOIN b_learn_question Q ON TR.QUESTION_ID = Q.ID ".
393 "WHERE ATTEMPT_ID = '".$ATTEMPT_ID."' ";
394
395 $res = $DB->Query($strSql);
396 if (!$ar = $res->Fetch())
397 return false;
398
399 $res = $this->Update($ATTEMPT_ID,
400 array(
401 "SCORE" => $ar["SCORE"],
402 "MAX_SCORE" => $ar["MAX_SCORE"],
403 "STATUS"=>"F",
404 "~DATE_END"=>CDatabase::CurrentTimeFunction(),
405 )
406 );
407
408 foreach(GetModuleEvents('learning', 'OnAfterAttemptFinished', true) as $arEvent)
409 ExecuteModuleEventEx($arEvent, array($ATTEMPT_ID));
410
411 if($res)
412 return CTestAttempt::OnAttemptChange($ATTEMPT_ID);
413 else
414 return false;
415 }
416
417
418 public static function RecountQuestions($ATTEMPT_ID)
419 {
420 global $DB;
421
422 $ATTEMPT_ID = intval($ATTEMPT_ID);
423
424 if ($ATTEMPT_ID < 1)
425 return false;
426
427 $strSql = "SELECT COUNT(*) CNT, SUM(TR.POINT) CNT_SUM, SUM(Q.POINT) MAX_POINT ".
428 "FROM b_learn_test_result TR ".
429 "INNER JOIN b_learn_question Q ON TR.QUESTION_ID = Q.ID ".
430 "WHERE TR.ATTEMPT_ID = ".$ATTEMPT_ID;
431 $res = $DB->Query($strSql);
432 if (!$ar = $res->Fetch())
433 return false;
434
435 $strSql = "UPDATE b_learn_attempt SET QUESTIONS = '".intval($ar["CNT"])."', SCORE = '".intval($ar["CNT_SUM"])."', MAX_SCORE = '".intval($ar["MAX_POINT"])."' WHERE ID = ".$ATTEMPT_ID;
436 if (!$DB->Query($strSql))
437 return false;
438
439 return true;
440 }
441
442
443 public static function IsTestFailed($ATTEMPT_ID, $PERCENT)
444 {
445 global $DB;
446
447 $strSql =
448 "SELECT * ".
449 "FROM b_learn_test_result TR, b_learn_question Q ".
450 "WHERE TR.QUESTION_ID = Q.ID AND TR.CORRECT = 'N' AND TR.ANSWERED = 'Y' AND Q.CORRECT_REQUIRED = 'Y' AND TR.ATTEMPT_ID = '".intval($ATTEMPT_ID)."'";
451
452
453 if (!$res = $DB->Query($strSql))
454 return true;
455
456 if ($arStat = $res->Fetch())
457 return true;
458
459 $strSql =
460 "SELECT SUM(Q.POINT) as CNT_ALL, SUM(CASE WHEN TR.CORRECT = 'N' AND TR.ANSWERED = 'Y' THEN Q.POINT ELSE 0 END) as CNT_WRONG ".
461 "FROM b_learn_test_result TR, b_learn_question Q ".
462 "WHERE TR.ATTEMPT_ID = '".intval($ATTEMPT_ID)."' AND TR.QUESTION_ID = Q.ID";
463
464 if (!$res = $DB->Query($strSql))
465 return true;
466
467 if (!$arStat = $res->Fetch())
468 return true;
469
470 if($arStat["CNT_ALL"] == 0)
471 {
472 return true;
473 }
474 elseif ($arStat["CNT_WRONG"]==0)
475 {
476 return false;
477 }
478
479
480
481 // Do some work due to IEEE 754
482 $epsilon = 0.001;
483
484 $cntNotFailed = $arStat["CNT_ALL"] - $arStat["CNT_WRONG"];
485
486 $scoreForSuccess = (float) ((int) $PERCENT);
487 $userScore = round( ($cntNotFailed / $arStat["CNT_ALL"]) * 100, 2);
488
489 $delta = abs($userScore - $scoreForSuccess);
490
491 $isTestFailed = true;
492 if ($userScore > $scoreForSuccess)
493 $isTestFailed = false;
494 elseif ($delta < $epsilon) // it means, that $userScore == $scoreForSuccess
495 $isTestFailed = false;
496
497 return ($isTestFailed);
498 }
499
500
501 public static function GetList($arOrder=array(), $arFilter=array(), $arSelect = array(), $arNavParams = array())
502 {
504
505 $obUserFieldsSql = new CUserTypeSQL;
506 $obUserFieldsSql->SetEntity("LEARN_ATTEMPT", "A.ID");
507 $obUserFieldsSql->SetSelect($arSelect);
508 $obUserFieldsSql->SetFilter($arFilter);
509 $obUserFieldsSql->SetOrder($arOrder);
510
512 "ID" => "A.ID",
513 "TEST_ID" => "A.TEST_ID",
514 "OBY_DATE_END" => "A.DATE_END",
515 "STUDENT_ID" => "A.STUDENT_ID",
516 "DATE_START" => $DB->DateToCharFunction("A.DATE_START", "FULL"),
517 "DATE_END" => $DB->DateToCharFunction("A.DATE_END", "FULL"),
518 "STATUS" => "A.STATUS",
519 "COMPLETED" => "A.COMPLETED",
520 "SCORE" => "A.SCORE",
521 "MAX_SCORE" => "A.MAX_SCORE",
522 "QUESTIONS" => "A.QUESTIONS",
523 "TEST_NAME" => "T.NAME",
524 "USER_NAME" => $DB->Concat("'('",'U.LOGIN',"') '","CASE WHEN U.NAME IS NULL THEN '' ELSE U.NAME END","' '", "CASE WHEN U.LAST_NAME IS NULL THEN '' ELSE U.LAST_NAME END"),
525 "USER_ID" => "U.ID",
526 "MARK" => "TM.MARK",
527 "MESSAGE" => "TM.DESCRIPTION",
528 "LINKED_LESSON_ID" => "C.LINKED_LESSON_ID",
529 "COURSE_ID" => "C.ID",
530 "SPEED" => self::getSpeedFieldSql()
531 );
532
533 if (count($arSelect) <= 0 || in_array("*", $arSelect))
534 $arSelect = array_keys($arFields);
535
536 $arSqlSelect = array();
537 foreach($arSelect as $field)
538 {
539 $field = mb_strtoupper($field);
540 if(array_key_exists($field, $arFields))
541 $arSqlSelect[$field] = $arFields[$field]." AS ".$field;
542 }
543
544 $sSelect = implode(",\n", $arSqlSelect);
545
546 if (!is_array($arFilter))
547 $arFilter = Array();
548
549 $arSqlSearch = CTestAttempt::GetFilter($arFilter);
550
551 $strSqlSearch = "";
552 $arSqlSearchCnt = count($arSqlSearch);
553 for($i=0; $i<$arSqlSearchCnt; $i++)
554 if($arSqlSearch[$i] <> '')
555 $strSqlSearch .= " AND ".$arSqlSearch[$i]." ";
556
557 $r = $obUserFieldsSql->GetFilter();
558 if($r <> '')
559 $strSqlSearch .= " AND (".$r.") ";
560
561 $bCheckPerm = 'ORPHANED VAR';
562
563 $strSqlFrom = '';
564 $strSql = static::_GetListSQLFormer($sSelect, $obUserFieldsSql, $bCheckPerm, $USER, $arFilter, $strSqlSearch, $strSqlFrom);
565
566 if (!is_array($arOrder))
567 $arOrder = Array();
568
569 $arSqlOrder = [];
570 foreach($arOrder as $by=>$order)
571 {
572 $by = mb_strtolower($by);
573 $order = mb_strtolower($order);
574 if ($order!="asc")
575 $order = "desc";
576
577 if ($by == "id")
578 $arSqlOrder[] = " A.ID ".$order." ";
579 elseif ($by == "test_id")
580 $arSqlOrder[] = " A.TEST_ID ".$order." ";
581 elseif ($by == "student_id")
582 $arSqlOrder[] = " A.STUDENT_ID ".$order." ";
583 elseif ($by == "date_start")
584 $arSqlOrder[] = " A.DATE_START ".$order." ";
585 elseif ($by == "date_end")
586 $arSqlOrder[] = " A.DATE_END ".$order." ";
587 elseif ($by == "status")
588 $arSqlOrder[] = " A.STATUS ".$order." ";
589 elseif ($by == "score")
590 $arSqlOrder[] = " A.SCORE ".$order." ";
591 elseif ($by == "max_score")
592 $arSqlOrder[] = " A.MAX_SCORE ".$order." ";
593 elseif ($by == "completed")
594 $arSqlOrder[] = " A.COMPLETED ".$order." ";
595 elseif ($by == "questions")
596 $arSqlOrder[] = " A.QUESTIONS ".$order." ";
597 elseif ($by == "user_name")
598 $arSqlOrder[] = " USER_NAME ".$order." ";
599 elseif ($by == "test_name")
600 $arSqlOrder[] = " TEST_NAME ".$order." ";
601 elseif ($by == "speed")
602 $arSqlOrder[] = " SPEED ".$order." ";
603 elseif ($s = $obUserFieldsSql->GetOrder($by))
604 $arSqlOrder[$by] = " ".$s." ".$order." ";
605 else
606 $arSqlOrder[] = " A.ID ".$order." ";
607 }
608
609 $strSqlOrder = "";
610 DelDuplicateSort($arSqlOrder);
611 $arSqlOrderCnt = count($arSqlOrder);
612 for ($i=0; $i<$arSqlOrderCnt; $i++)
613 {
614 if($i==0)
615 $strSqlOrder = " ORDER BY ";
616 else
617 $strSqlOrder .= ",";
618
619 $strSqlOrder .= $arSqlOrder[$i];
620 }
621
622 $strSql .= $strSqlOrder;
623
624 if ( ! empty($arNavParams) )
625 {
626 $nTopCount = null;
627 if (isset($arNavParams['NAV_PARAMS']['nPageTop']) && ($arNavParams['NAV_PARAMS']['nPageTop'] > 0))
628 $nTopCount = (int) $arNavParams['NAV_PARAMS']['nPageTop'];
629 else if (isset($arNavParams['nPageTop']))
630 $nTopCount = (int) $arNavParams['nPageTop'];
631 else if (isset($arNavParams['nTopCount']))
632 $nTopCount = (int) $arNavParams['nTopCount'];
633 else
634 {
635 $res_cnt = $DB->Query("SELECT COUNT(A.ID) as C " . $strSqlFrom);
636 $res_cnt = $res_cnt->fetch();
637 $res = new CDBResult();
638 $res->NavQuery($strSql, $res_cnt['C'], $arNavParams);
639 $res->SetUserFields($USER_FIELD_MANAGER->GetUserFields("LEARN_ATTEMPT"));
640 }
641
642 if ($nTopCount !== null)
643 {
644 $strSql = $DB->TopSql($strSql, $nTopCount);
645 $res = $DB->Query($strSql);
646 $res->SetUserFields($USER_FIELD_MANAGER->GetUserFields("LEARN_ATTEMPT"));
647 }
648 }
649 else
650 {
651 $res = $DB->Query($strSql);
652 $res->SetUserFields($USER_FIELD_MANAGER->GetUserFields("LEARN_ATTEMPT"));
653 }
654
655
656 return $res;
657 }
658
659 private static function getSpeedFieldSql()
660 {
661 return "round((unix_timestamp(coalesce(A.DATE_END, A.DATE_START))-unix_timestamp(A.DATE_START)) / (case when A.QUESTIONS > 0 then A.QUESTIONS else 1 end))";
662 }
663
664 public static function CreateAttemptQuestions($ATTEMPT_ID)
665 {
666 global $APPLICATION, $DB;
667
668 $ATTEMPT_ID = intval($ATTEMPT_ID);
669
670 $attempt = CTestAttempt::GetByID($ATTEMPT_ID);
671 if (!$arAttempt = $attempt->Fetch())
672 {
673 $APPLICATION->ThrowException(GetMessage("LEARNING_BAD_ATTEMPT_ID_EX"), "ERROR_NO_ATTEMPT_ID");
674 return false;
675 }
676
677 $test = CTest::GetByID($arAttempt["TEST_ID"]);
678 if (!$arTest = $test->Fetch())
679 {
680 $APPLICATION->ThrowException(GetMessage("LEARNING_BAD_TEST_ID_EX"), "ERROR_NO_TEST_ID");
681 return false;
682 }
683
684 $strSql = "DELETE FROM b_learn_test_result WHERE ATTEMPT_ID = ".$ATTEMPT_ID;
685 if (!$DB->Query($strSql))
686 return false;
687
709
710 if ($arTest["QUESTIONS_FROM"] == "C" || $arTest["QUESTIONS_FROM"] == "L")
711 {
712 $courseId = $arTest['COURSE_ID'] + 0;
713 $courseLessonId = CCourse::CourseGetLinkedLesson ($courseId);
714 if ($courseLessonId === false)
715 {
716 $APPLICATION->ThrowException(GetMessage("LEARNING_BAD_TEST_IS_EMPTY"), "ERROR_TEST_IS_EMPTY");
717 return false;
718 }
719
720 $clauseAllChildsLessons = CLearnHelper::SQLClauseForAllSubLessons ($courseLessonId);
721
722 if ($arTest["QUESTIONS_FROM"] == "C") // X questions from every lessons from every chapter in the course
723 {
724 $strSql =
725 "SELECT Q.ID as QUESTION_ID, TLEUP.SOURCE_NODE as FROM_ID
726 FROM b_learn_lesson L
727 INNER JOIN b_learn_question Q ON L.ID = Q.LESSON_ID
728 INNER JOIN b_learn_lesson_edges TLEUP ON L.ID = TLEUP.TARGET_NODE
729 LEFT OUTER JOIN b_learn_lesson_edges TLEDOWN ON L.ID = TLEDOWN.SOURCE_NODE "
730 . "WHERE L.ID IN (" . $clauseAllChildsLessons . ") \n" // only lessons from COURSE_ID = $arTest['COURSE_ID']
731 . " AND TLEDOWN.SOURCE_NODE IS NULL \n" // exclude lessons, contains other lessons ("chapters")
732
733 // include lessons in current course tree context only (and exclude immediate childs of course)
734 . " AND TLEUP.SOURCE_NODE IN (" . $clauseAllChildsLessons . ") \n"
735
736 . " AND Q.ACTIVE = 'Y' " // active questions only
737 . ($arTest["INCLUDE_SELF_TEST"] != "Y" ? "AND Q.SELF = 'N' " : "")
738 . "ORDER BY ".($arTest["RANDOM_QUESTIONS"] == "Y" ? CTest::GetRandFunction() : "L.SORT, Q.SORT, L.ID");
739 }
740 else // 'L' X questions from every lesson in course
741 {
742 $strSql =
743 "SELECT Q.ID as QUESTION_ID, L.ID as FROM_ID ".
744 "FROM b_learn_lesson L ".
745 "INNER JOIN b_learn_question Q ON L.ID = Q.LESSON_ID ".
746 "WHERE L.ID IN (" . $clauseAllChildsLessons . ") AND Q.ACTIVE = 'Y' ".
747 ($arTest["INCLUDE_SELF_TEST"] != "Y" ? "AND Q.SELF = 'N' " : "").
748 "ORDER BY ".($arTest["RANDOM_QUESTIONS"] == "Y" ? CTest::GetRandFunction() : "L.SORT, Q.SORT, L.ID");
749 }
750
751 if (!$res = $DB->Query($strSql))
752 return false;
753
754 $Values = Array();
755 $tmp = Array();
756 while ($arRecord = $res->Fetch())
757 {
758 if (is_set($tmp, $arRecord["FROM_ID"]))
759 {
760 if ($tmp[$arRecord["FROM_ID"]] < $arTest["QUESTIONS_AMOUNT"])
761 $tmp[$arRecord["FROM_ID"]]++;
762 else
763 continue;
764 }
765 else
766 {
767 $tmp[$arRecord["FROM_ID"]] = 1;
768 }
769 $Values[]= $arRecord["QUESTION_ID"];
770 }
771
772 if (empty($Values))
773 {
774 $APPLICATION->ThrowException(GetMessage("LEARNING_BAD_TEST_IS_EMPTY"), "ERROR_TEST_IS_EMPTY");
775 return false;
776 }
777
778 $DB->StartTransaction();
779 foreach ($Values as $ID)
780 {
781 $strSql = "INSERT INTO b_learn_test_result (ATTEMPT_ID, QUESTION_ID) VALUES (".$ATTEMPT_ID.",".$ID.")";
782 if (!$DB->Query($strSql))
783 {
784 $DB->Rollback();
785 return false;
786 }
787 }
788 $DB->Commit();
789 }
790 elseif (($arTest["QUESTIONS_FROM"] == "H" || $arTest["QUESTIONS_FROM"] == "S" || $arTest["QUESTIONS_FROM"] == "R") && $arTest["QUESTIONS_FROM_ID"])
791 {
792 $WHERE = '';
793 if ($arTest["QUESTIONS_FROM"] == "H")
794 {
802 $APPLICATION->ThrowException(GetMessage("LEARNING_BAD_TEST_IS_EMPTY"), "ERROR_TEST_IS_EMPTY");
803 return false;
804 }
805 elseif ($arTest["QUESTIONS_FROM"] == 'R') // all questions from the tree with root at selected lesson (include questions of selected lesson) in the course (unilesson_id in QUESTIONS_FROM_ID)
806 {
807 $clauseAllChildsLessons = CLearnHelper::SQLClauseForAllSubLessons ($arTest['QUESTIONS_FROM_ID']);
808 $WHERE = " (L.ID IN(" . $clauseAllChildsLessons . ") OR (L.ID = " . ($arTest['QUESTIONS_FROM_ID'] + 0) . ")) ";
809 }
810 elseif ($arTest["QUESTIONS_FROM"] == 'S') // 'S' - all questions from the selected lesson (unilesson_id in QUESTIONS_FROM_ID)
811 {
812 $clauseAllChildsLessons = $arTest["QUESTIONS_FROM_ID"] + 0;
813 $WHERE = " (L.ID IN(" . $clauseAllChildsLessons . ") OR (L.ID = " . ($arTest['QUESTIONS_FROM_ID'] + 0) . ")) ";
814 }
815 else
816 {
817 return (false);
818 }
819
820 $strSql =
821 "SELECT Q.ID AS QUESTION_ID ".
822 "FROM b_learn_lesson L ".
823 "INNER JOIN b_learn_question Q ON L.ID = Q.LESSON_ID ".
824 "WHERE " . $WHERE . " AND Q.ACTIVE = 'Y' ".
825 ($arTest["INCLUDE_SELF_TEST"] != "Y" ? "AND Q.SELF = 'N' " : "").
826 "ORDER BY ".($arTest["RANDOM_QUESTIONS"] == "Y" ? CTest::GetRandFunction() : "L.SORT, Q.SORT, L.ID ").
827 ($arTest["QUESTIONS_AMOUNT"] > 0 ? "LIMIT ".$arTest["QUESTIONS_AMOUNT"] :"");
828
829 $success = false;
830 $rsQuestions = $DB->Query($strSql);
831
832 $strSql = '';
833 if ($rsQuestions)
834 {
835 $arSqlSubstrings = array();
836 while ($arQuestion = $rsQuestions->fetch())
837 $arSqlSubstrings[] = "(" . $ATTEMPT_ID . ", " . $arQuestion['QUESTION_ID'] . ")";
838
839 if ( ! empty($arSqlSubstrings) )
840 $strSql = "INSERT INTO b_learn_test_result (ATTEMPT_ID, QUESTION_ID) VALUES " . implode(",\n", $arSqlSubstrings);
841
842 if ($strSql !== '')
843 {
844 $rc = $DB->Query($strSql);
845 if ($rc && intval($rc->AffectedRowsCount()) > 0)
846 $success = true;
847 }
848 }
849
850 if ( ! $success )
851 {
852 $APPLICATION->ThrowException(GetMessage("LEARNING_BAD_TEST_IS_EMPTY"), "ERROR_TEST_IS_EMPTY");
853 return false;
854 }
855 }
856 elseif ($arTest["QUESTIONS_FROM"] == 'A')
857 {
858 $courseId = $arTest['COURSE_ID'] + 0;
859 $courseLessonId = CCourse::CourseGetLinkedLesson ($courseId);
860 if ($courseLessonId === false)
861 {
862 $APPLICATION->ThrowException(GetMessage("LEARNING_BAD_TEST_IS_EMPTY"), "ERROR_TEST_IS_EMPTY");
863 return false;
864 }
865
866 $clauseAllChildsLessons = CLearnHelper::SQLClauseForAllSubLessons ($courseLessonId);
867
868 $strSql =
869 "SELECT Q.ID AS QUESTION_ID
870 FROM b_learn_lesson L
871 INNER JOIN b_learn_question Q ON L.ID = Q.LESSON_ID
872 WHERE (L.ID IN (" . $clauseAllChildsLessons . ") OR (L.ID = " . ($courseLessonId + 0) . ") )
873 AND Q.ACTIVE = 'Y' "
874 . ($arTest["INCLUDE_SELF_TEST"] != "Y" ? "AND Q.SELF = 'N' " : "").
875 "ORDER BY " . ($arTest["RANDOM_QUESTIONS"] == "Y" ? CTest::GetRandFunction() : "L.SORT, Q.SORT, L.ID ").
876 ($arTest["QUESTIONS_AMOUNT"] > 0 ? "LIMIT " . ($arTest["QUESTIONS_AMOUNT"] + 0) : "");
877
878
879 $success = false;
880 $rsQuestions = $DB->Query($strSql);
881
882 $strSql = '';
883 if ($rsQuestions)
884 {
885 $arSqlSubstrings = array();
886 while ($arQuestion = $rsQuestions->fetch())
887 $arSqlSubstrings[] = "(" . $ATTEMPT_ID . ", " . $arQuestion['QUESTION_ID'] . ")";
888
889 if ( ! empty($arSqlSubstrings) )
890 $strSql = "INSERT INTO b_learn_test_result (ATTEMPT_ID, QUESTION_ID) VALUES " . implode(",\n", $arSqlSubstrings);
891
892 if ($strSql !== '')
893 {
894 $rc = $DB->Query($strSql);
895 if ($rc && intval($rc->AffectedRowsCount()) > 0)
896 $success = true;
897 }
898 }
899
900 if ( ! $success )
901 {
902 $APPLICATION->ThrowException(GetMessage("LEARNING_BAD_TEST_IS_EMPTY"), "ERROR_TEST_IS_EMPTY");
903 return false;
904 }
905 }
906 else
907 return (false);
908
909 $strSql = "UPDATE b_learn_attempt SET QUESTIONS = '".CTestResult::GetCount($ATTEMPT_ID)."' WHERE ID = ".$ATTEMPT_ID;
910 $DB->Query($strSql);
911
912 return true;
913 }
914}
$arParams
Определения access_dialog.php:21
global $APPLICATION
Определения include.php:80
static Certificate($STUDENT_ID, $COURSE_ID, $checkPerms=true)
Определения certification.php:306
static RecountAttempts($STUDENT_ID, $TEST_ID)
Определения gradebook.php:191
Определения attempt.php:9
static CreateAttemptQuestions($ATTEMPT_ID)
Определения attempt.php:664
CheckFields(&$arFields, $ID=false, $bCheckRights=true)
Определения attempt.php:10
static IsTestCompleted($ATTEMPT_ID, $PERCENT)
Определения attempt.php:251
static IsTestFailed($ATTEMPT_ID, $PERCENT)
Определения attempt.php:443
static Delete($ID)
Определения attempt.php:140
static GetByID($ID)
Определения attempt.php:226
AttemptFinished($ATTEMPT_ID)
Определения attempt.php:380
static RecountQuestions($ATTEMPT_ID)
Определения attempt.php:418
static GetCount($TEST_ID, $STUDENT_ID)
Определения attempt.php:235
Update($ID, $arFields, $arParams=array())
Определения attempt.php:107
Add($arFields)
Определения attempt.php:79
static GetFilter($arFilter)
Определения attempt.php:163
static OnAttemptChange($ATTEMPT_ID, $bCOMPLETED=false)
Определения attempt.php:298
static GetList($arOrder=array(), $arFilter=array(), $arSelect=array(), $arNavParams=array())
Определения attempt.php:501
static GetByID($ID)
Определения test.php:264
static CourseGetLinkedLesson($courseId)
Определения course.php:55
Определения gradebook.php:4
static FilterCreate($fname, $vals, $type, &$bFullJoin, $cOperationType=false, $bSkipEmpty=true)
Определения clearnhelper.php:214
static SQLClauseForAllSubLessons($parentLessonId)
Определения clearnhelper.php:108
static MkOperationFilter($key)
Определения clearnhelper.php:143
static DoInsert($arInsert, $arFields)
Определения attempt.php:7
static GetRandFunction()
Определения test.php:7
Определения usertypesql.php:4
SetEntity($entity_id, $ID)
Определения usertypesql.php:16
if(!is_array($prop["VALUES"])) $tmp
Определения component_props.php:203
$arFields
Определения dblapprove.php:5
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$res
Определения filter_act.php:7
GetFilterQuery($field, $val, $procent="Y", $ex_sep=array(), $clob="N", $div_fields="Y", $clob_upper="N")
Определения filter_tools.php:383
global $USER_FIELD_MANAGER
Определения attempt.php:6
if($ajaxMode) $ID
Определения get_user.php:27
global $DB
Определения cron_frame.php:29
global $USER
Определения csv_new_run.php:40
$success
Определения mail_entry.php:69
ExecuteModuleEventEx($arEvent, $arParams=[])
Определения tools.php:5214
DelDuplicateSort(&$arSort)
Определения tools.php:2055
GetModuleEvents($MODULE_ID, $MESSAGE_ID, $bReturnArray=false)
Определения tools.php:5177
is_set($a, $k=false)
Определения tools.php:2133
GetMessage($name, $aReplace=null)
Определения tools.php:3397
$order
Определения payment.php:8
$delta
Определения prolog_main_admin.php:363
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$ar
Определения options.php:199
if(empty($signedUserToken)) $key
Определения quickway.php:257
$i
Определения factura.php:643
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936
$val
Определения options.php:1793
$dbResult
Определения updtr957.php:3
$arFilter
Определения user_search.php:106