public function get_all_tasks() { $fields_config = array(array('name' => 'created', 'caption' => 'lang:common_table_header_created'), array('name' => 'updated', 'caption' => 'lang:common_table_header_updated'), array('name' => 'name', 'caption' => 'lang:admin_tasks_table_header_name'), array('name' => 'categories', 'caption' => 'lang:admin_tasks_table_header_categories'), array('name' => 'task_sets', 'caption' => 'lang:admin_tasks_table_header_task_sets'), array('name' => 'test_count', 'caption' => 'lang:admin_tasks_table_header_test_count'), array('name' => 'author', 'caption' => 'lang:admin_tasks_table_header_author')); $filter = $this->input->post('filter'); $this->store_filter($filter); $this->inject_stored_filter(); $tasks = new Task(); $tasks->include_related('author', 'fullname'); $tasks->include_related_count('test'); if (isset($filter['categories']['clauses']) && count($filter['categories']['clauses']) > 0) { $tasks->add_categories_filter($filter['categories']['clauses']); } if (isset($filter['name']) && trim($filter['name']) != '' || isset($filter['text']) && trim($filter['text']) != '') { $tasks->group_start(); if (isset($filter['name']) && trim($filter['name']) != '') { $tasks->or_like_with_overlay('name', trim($filter['name'])); } if (isset($filter['text']) && trim($filter['text']) != '') { $tasks->or_like_with_overlay('text', trim($filter['text']), 'both', TRUE); } $tasks->group_end(); } if (isset($filter['tests'])) { $tests = $tasks->test; $tests->select_func('COUNT', '@id', 'tests_count'); $tests->where_related('task', 'id', '${parent}.id'); if ($filter['tests'] == 'have') { if (isset($filter['test_types']) && is_array($filter['test_types']) && count($filter['test_types']) > 0) { $tests->where_in('type', $filter['test_types']); } $tasks->where_subquery('0 < ', $tests); } elseif ($filter['tests'] == 'donthave') { $tasks->where_subquery('0 = ', $tests); } } if (isset($filter['author'])) { if (trim($filter['author']) !== '') { if ($filter['author'] == '0') { $tasks->where('author_id', NULL); } else { $tasks->where('author_id', (int) $filter['author']); } } } if (isset($filter['time']) && isset($filter['time_days'])) { if (is_numeric($filter['time_days']) && $filter['time_days'] >= 1 && $filter['time'] != 'disable') { $days = $filter['time_days'] - 1; $day_min = date('Y-m-d H:i:s', strtotime(date('Y-m-d') . ' 00:00:00' . ($days == 1 ? ' -1 day' : ($days > 1 ? ' -' . $days . ' days' : '')))); if ($filter['time'] == 'created') { $tasks->where('created >=', $day_min); } elseif ($filter['time'] == 'updated') { $tasks->where('updated >=', $day_min); } } } $tasks->include_related_count('task_set'); $order_by_direction = $filter['order_by_direction'] == 'desc' ? 'desc' : 'asc'; if ($filter['order_by_field'] == 'created') { $tasks->order_by('created', $order_by_direction); } elseif ($filter['order_by_field'] == 'updated') { $tasks->order_by('updated', $order_by_direction); } elseif ($filter['order_by_field'] == 'name') { $tasks->order_by_with_overlay('name', $order_by_direction); } elseif ($filter['order_by_field'] == 'task_sets') { $tasks->order_by('task_set_count', $order_by_direction); } elseif ($filter['order_by_field'] == 'test_count') { $tasks->order_by('test_count', $order_by_direction); } elseif ($filter['order_by_field'] == 'author') { $tasks->order_by_related_as_fullname('author', 'fullname', $order_by_direction); } $tasks->get_paged_iterated(isset($filter['page']) ? intval($filter['page']) : 1, isset($filter['rows_per_page']) ? intval($filter['rows_per_page']) : 25); $this->lang->init_overlays('tasks', $tasks->all_to_array(), array('name')); $this->parser->parse('backend/tasks/all_tasks.tpl', array('tasks' => $tasks, 'fields_config' => $fields_config)); }
public function evaluate_test_result($task_set_id, $student_id, $version, $test_type, $token) { $task_set = new Task_set(); $task_set->include_related('course', 'test_scoring_deadline'); $task_set->get_by_id((int) $task_set_id); $student = new Student(); $student->get_by_id((int) $student_id); $output = new stdClass(); $output->result = FALSE; $output->message = ''; $output->points_new = 0; $output->points_before = 0; $this->load->model('test_score'); if ($task_set->exists() && $student->exists()) { if ($task_set->course_test_scoring_deadline >= date('Y-m-d H:i:s') && $task_set->enable_tests_scoring > 0) { $results = $this->test_score->get_data_for_student($student->id, $token, $test_type); $this->_transaction_isolation(); $this->db->trans_start(); $tests = new Test(); $tests->where_related('task/task_set', 'id', $task_set->id); $tests->where('type', $test_type); $tests->where('enable_scoring >', 0); $tests->group_by('task_id'); $tests->where('task_task_task_set_rel.bonus_task', 0); $tests->get_iterated(); //$output->debug = $tests->check_last_query(array('', ''), TRUE); $test_count = $tests->result_count(); $min_results = $task_set->test_min_needed > $test_count ? $test_count : $task_set->test_min_needed; $course = new Course(); $course->where_related_task_set('id', $task_set->id); $course->get(); $min_points_limit = -$course->default_points_to_remove; if ($test_count > 0) { $total_score = 0; $score_array = array(); $bonus_tasks_array = array(); $score_percentage = array(); $bonus_tasks_percentage = array(); if (count($results)) { foreach ($results as $task_id => $score) { $this->db->select('*'); $this->db->where('task_set_id', $task_set->id); $this->db->where('task_id', (int) $task_id); $query = $this->db->get('task_task_set_rel'); if ($query->num_rows() > 0) { $task_rel = $query->row_object(); $min = $task_rel->test_min_points; $max = $task_rel->test_max_points; $diff = abs($max - $min); $score_percent = (double) $score / 100; $sub_score = round(10 * ($min + $diff * $score_percent)) / 10; if ($task_rel->bonus_task == 0) { $score_array[$task_id] = $sub_score; $score_percentage[$task_id] = $score; } else { $bonus_tasks_array[$task_id] = $sub_score; $bonus_tasks_percentage[$task_id] = $score; } } $query->free_result(); } } $max_results = $task_set->test_max_allowed < count($score_array) ? $task_set->test_max_allowed : count($score_array); arsort($score_array, SORT_NUMERIC); $i = 0; foreach ($score_array as $task_id => $points) { if ($i < $max_results) { $total_score += $points; $i++; } else { break; } } $total_score = $total_score < $min_points_limit ? $min_points_limit : $total_score; arsort($bonus_tasks_array, SORT_NUMERIC); $total_score += array_sum($bonus_tasks_array); if (count($score_array) >= $min_results) { $tasks = new Task(); $tasks->where_related_task_set('id', $task_set_id); $tasks->order_by('`task_task_set_rel`.`sorting`', 'asc'); $tasks->get_iterated(); //$output->debug = $tasks->check_last_query(array('', ''), TRUE); $output->evaluation = $this->parser->parse('backend/tests/evaluation_table.tpl', array('tasks' => $tasks, 'real_points' => $score_array, 'bonus_points' => $bonus_tasks_array, 'real_percentage' => $score_percentage, 'bonus_percentage' => $bonus_tasks_percentage, 'max_results' => $max_results), TRUE); $solution = new Solution(); $solution->where('task_set_id', $task_set->id); $solution->where('student_id', $student->id); $solution->get(); $save_solution = FALSE; $solution_not_considered = FALSE; $output->points_new = $total_score; if ($solution->exists()) { if ($solution->not_considered == 0) { $output->points_before = $solution->points; if ($solution->points < $total_score || is_null($solution->points)) { $solution->points = $total_score; $solution->comment = ''; $solution->teacher_id = NULL; $solution->best_version = (int) $version; $solution->revalidate = 0; $save_solution = TRUE; } } else { $solution_not_considered = TRUE; } } else { $solution->points = $total_score; $solution->comment = ''; $solution->teacher_id = NULL; $solution->best_version = (int) $version; $solution->task_set_id = $task_set->id; $solution->student_id = $student->id; $solution->revalidate = 0; $save_solution = TRUE; } if ($save_solution) { $solution->save(); $output->result = TRUE; $this->_action_success(); } else { if (!$solution_not_considered) { $output->message = sprintf($this->lang->line('admin_tests_test_result_nothing_to_update'), $output->points_new, $output->points_before); } else { $output->message = $this->lang->line('admin_tests_test_result_solution_not_considered'); } } } else { $output->message = sprintf($this->lang->line('admin_tests_test_result_minimum_number_of_test_not_selected'), $min_results); } } else { $output->message = $this->lang->line('admin_tests_test_result_no_evaluationg_tests'); } $this->db->trans_complete(); } else { $output->message = $this->lang->line('admin_tests_test_result_disabled'); } } else { $output->message = $this->lang->line('admin_tests_test_result_input_error'); } $this->test_score->delete_token($token); $this->output->set_content_type('application/json'); $this->output->set_output(json_encode($output)); }
public function test_result($test_queue_id) { $this->usermanager->student_login_protected_redirect(); $this->parser->add_css_file('frontend_tasks.css'); $test_queue = new Test_queue(); $test_queue->where_related('student', 'id', $this->usermanager->get_student_id()); $test_queue->include_related('task_set'); $test_queue->include_related('task_set/course'); $test_queue->include_related('task_set/course/period'); $test_queue->get_by_id((int) $test_queue_id); $tasks = new Task(); if ($test_queue->exists()) { $tasks->distinct(); $tasks->where_related('task_set', 'id', $test_queue->task_set_id); $tasks->order_by('task_task_set_rel.sorting', 'asc'); $tasks->get_iterated(); $tests = $test_queue->test->include_join_fields()->order_by('id', 'asc')->get_iterated(); $tests_per_task = array(); $overlays_tests = array(); foreach ($tests as $test) { $test_line = array('id' => $test->id, 'name' => $test->name, 'task_id' => $test->task_id, 'result' => $test->join_result, 'result_text' => $test->join_result_text, 'percent_points' => $test->join_percent_points, 'percent_bonus' => $test->join_percent_bonus, 'points' => $test->join_points, 'bonus' => $test->join_bonus, 'evaluation_table' => is_null($test->join_evaluation_table) ? array() : unserialize($test->join_evaluation_table)); $overlays_tests[] = $test->id; $tests_per_task[$test->task_id][] = $test_line; } $this->lang->init_overlays('tests', $overlays_tests, array('name')); $this->parser->assign('tests_per_task', $tests_per_task); } $this->load->helper('tests'); $test_types = get_all_supported_test_types(); $this->parser->parse('frontend/tasks/test_result.tpl', array('test_queue' => $test_queue, 'tasks' => $tasks, 'test_types' => $test_types)); }
public function index($worker_id = 0) { $test_queue = new Test_queue(); $execute_tests = FALSE; try { $this->db->query('SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;'); $this->db->trans_begin(); $test_queue->where('worker', NULL); $test_queue->where('status', 0); $test_queue->where('version >', 0); $test_queue->group_start(' NOT '); $test_queue->where('task_set_id', NULL); $test_queue->group_end(); $test_queue->group_start(' NOT '); $test_queue->where('student_id', NULL); $test_queue->group_end(); $test_queue->order_by('priority', 'asc'); $test_queue->order_by('start', 'asc'); $test_queue->limit(1); $sql_query = $test_queue->get_sql(); $sql_query = rtrim($sql_query, '; ' . "\n\r") . ' FOR UPDATE;'; $test_queue->query($sql_query); if ($test_queue->exists()) { $test_queue->worker = (int) $worker_id; $test_queue->status = 1; $test_queue->exec_start = date('Y-m-d H:i:s'); $test_queue->where('worker', NULL); $test_queue->where('status', 0); if ($test_queue->save()) { $this->db->trans_commit(); $execute_tests = TRUE; } else { $this->db->trans_rollback(); } } else { $this->db->trans_rollback(); } } catch (Exception $e) { } if ($test_queue->exists() && $execute_tests) { //$this->db->query('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;'); //$this->db->trans_begin(); $this->lang->reinitialize_for_idiom($test_queue->system_language); $this->lang->load('admin/tests'); $task_set = new Task_set(); $task_set->include_related('course', 'test_scoring_deadline'); $task_set->get_by_id($test_queue->task_set_id); $student = new Student(); $student->get_by_id($test_queue->student_id); $tests = new Test(); $tests->where_related($test_queue); $tests->get_iterated(); try { if ($task_set->exists() && $student->exists() && $tests->exists()) { $version = $test_queue->version; $run_evaluation = $task_set->enable_tests_scoring > 0 && $task_set->course_test_scoring_deadline >= date('Y-m-d H:i:s') ? TRUE : FALSE; $score_percent = array(); $score_points = array(); $bonus_percent = array(); $bonus_points = array(); $total_tests_count = $tests->result_count(); foreach ($tests as $test) { $test_queue->single_test_exec_start = date('Y-m-d H:i:s'); $test_queue->save(); $files = $task_set->get_student_files($student->id, (int) $version); if (isset($files[(int) $version]['filepath']) && file_exists($files[(int) $version]['filepath'])) { $test_object = $this->load->test($test->type); $test_object->initialize($test); $token = ''; //echo 'Test queue ' . $test_queue->id . ' is running test ' . $test->id . ' ... ' . PHP_EOL; try { $test_output = $test_object->run($files[(int) $version]['filepath'], $run_evaluation && $test->enable_scoring > 0, $student->id, $token); $test_score = $test_object->get_last_test_score(); } catch (Exception $e) { $test_output = $e->getMessage(); $test_score = 0; } $test_queue->set_join_field($test, 'result_text', $test_output); $test_queue->set_join_field($test, 'evaluation_table', $test_object->get_last_test_scoring()); $test_queue->set_join_field($test, 'result', $test_object->get_last_exit_code()); //echo 'Test queue ' . $test_queue->id . ' is done with test ' . $test->id . ' ... ' . PHP_EOL; if ($run_evaluation && $test->enable_scoring > 0) { $this->db->select('*'); $task_id = $test->task_id; $this->db->where('task_set_id', $task_set->id); $this->db->where('task_id', (int) $task_id); $query = $this->db->get('task_task_set_rel'); if ($query->num_rows() > 0) { $task_rel = $query->row_object(); $min = (double) $task_rel->test_min_points; $max = (double) $task_rel->test_max_points; $percent = (double) $test_score / 100.0; $points = (1.0 - $percent) * $min + $percent * $max; if ($task_rel->bonus_task == 0) { $test_queue->set_join_field($test, 'percent_points', $test_score); $test_queue->set_join_field($test, 'points', $points); $score_percent[$task_id] = isset($score_percent[$task_id]) ? $score_percent[$task_id] + $percent : $percent; $percent = (double) $score_percent[$task_id]; $points = (1.0 - $percent) * $min + $percent * $max; $score_points[$task_id] = $points; } else { $test_queue->set_join_field($test, 'percent_bonus', $test_score); $test_queue->set_join_field($test, 'bonus', $points); $bonus_percent[$task_id] = isset($bonus_percent[$task_id]) ? $bonus_percent[$task_id] + $percent : $percent; $percent = (double) $bonus_percent[$task_id]; $points = (1.0 - $percent) * $min + $percent * $max; $bonus_points[$task_id] = $points; } } $query->free_result(); } } else { //$this->db->trans_rollback(); $test_queue->worker = NULL; $test_queue->status = 3; $test_queue->finish = date('Y-m-d H:i:s'); $test_queue->save(); die; } } $tests = new Test(); $tests->where_related('task/task_set', 'id', $task_set->id); $tests->where('type', $test_queue->test_type); $tests->where('enable_scoring >', 0); $tests->group_by('task_id'); $tests->where('task_task_task_set_rel.bonus_task', 0); $tests->get_iterated(); $test_count = $tests->result_count(); $min_results = $task_set->test_min_needed > $test_count ? $test_count : $task_set->test_min_needed; $course = new Course(); $course->where_related_task_set('id', $task_set->id); $course->get(); $min_points_limit = -$course->default_points_to_remove; if ($test_count > 0 && $run_evaluation) { $max_results = $task_set->test_max_allowed < count($score_points) ? $task_set->test_max_allowed : count($score_points); arsort($score_points, SORT_NUMERIC); $i = 0; $total_score = 0; foreach ($score_points as $task_id => $points) { if ($i < $max_results) { $total_score += $points; $i++; } else { break; } } $total_score = $total_score < $min_points_limit ? $min_points_limit : $total_score; $total_bonus = array_sum($bonus_points); $total_score += $total_bonus; if (count($score_points) >= $min_results) { $solution = new Solution(); $solution->where('task_set_id', $task_set->id); $solution->where('student_id', $student->id); $solution->get(); $save_solution = FALSE; $solution_not_considered = FALSE; $solution_disable_evaluation = FALSE; $best_old_score = $min_points_limit; if ($solution->exists()) { if ($solution->not_considered == 0) { if ($solution->disable_evaluation_by_tests == 0) { if ($solution->tests_points < $total_score || is_null($solution->tests_points)) { $solution->tests_points = $total_score; $solution->teacher_id = NULL; $solution->best_version = (int) $version; $solution->revalidate = 0; $save_solution = TRUE; } else { $best_old_score = $solution->tests_points; } } else { $solution_disable_evaluation = TRUE; } } else { $solution_not_considered = TRUE; } } else { $solution->tests_points = $total_score; $solution->comment = ''; $solution->teacher_id = NULL; $solution->best_version = (int) $version; $solution->task_set_id = $task_set->id; $solution->student_id = $student->id; $solution->revalidate = 0; $save_solution = TRUE; } if ($save_solution) { $solution->save(); $this->parser->clearCache('frontend/tasks/index.tpl'); $test_queue->result_message = $this->lang->line('admin_tests_test_result_new_points_added'); } else { if (!$solution_disable_evaluation) { if (!$solution_not_considered) { $test_queue->result_message = sprintf($this->lang->line('admin_tests_test_result_nothing_to_update'), $total_score, $best_old_score); } else { $test_queue->result_message = $this->lang->line('admin_tests_test_result_solution_not_considered'); } } else { $test_queue->result_message = $this->lang->line('admin_tests_test_result_solution_disable_evaluation'); } } $test_queue->points = $total_score - $total_bonus; $test_queue->bonus = $total_bonus; } else { $test_queue->result_message = sprintf($this->lang->line('admin_tests_test_result_minimum_number_of_test_not_selected'), $min_results); } $result_table_tasks = new Task(); $result_table_tasks->where_related_task_set('id', $task_set->id); $result_table_tasks->order_by('`task_task_set_rel`.`sorting`', 'asc'); $result_table_tasks->get_iterated(); $test_queue->result_html = $this->parser->parse('backend/tests/evaluation_table.tpl', array('tasks' => $result_table_tasks, 'real_points' => $score_points, 'bonus_points' => $bonus_points, 'real_percentage' => $score_percent, 'bonus_percentage' => $bonus_percent, 'max_results' => $max_results), TRUE); $test_queue->worker = NULL; $test_queue->status = 2; $test_queue->finish = date('Y-m-d H:i:s'); $test_queue->save(); //$this->db->trans_commit(); } else { if ($total_tests_count && !$run_evaluation) { $test_queue->worker = NULL; $test_queue->status = 2; $test_queue->finish = date('Y-m-d H:i:s'); $test_queue->result_message = $this->lang->line('admin_tests_test_result_testing_finished'); $test_queue->save(); //$this->db->trans_commit(); } else { //$this->db->trans_rollback(); $test_queue->worker = NULL; $test_queue->status = 3; $test_queue->finish = date('Y-m-d H:i:s'); $test_queue->result_message = $this->lang->line('admin_tests_test_result_no_test_selected'); $test_queue->save(); } } } else { //$this->db->trans_rollback(); $test_queue->worker = NULL; $test_queue->status = 3; $test_queue->finish = date('Y-m-d H:i:s'); $test_queue->result_message = $this->lang->line('admin_tests_test_result_configuration_error'); $test_queue->save(); } } catch (Exception $e) { //$this->db->trans_rollback(); $test_queue->worker = NULL; $test_queue->status = 3; $test_queue->finish = date('Y-m-d H:i:s'); $test_queue->result_message = $this->lang->line('admin_tests_test_result_execution_error'); $test_queue->result_html = '<pre>' . $e->getMessage() . '</pre>'; $test_queue->save(); } } //@unlink($test_locks_path . 'worker_' . (int)$worker_id . '_lock.txt'); }