Index: common/db/job.php
===================================================================
--- common/db/job.php	(revision 983)
+++ common/db/job.php	(working copy)
@@ -357,4 +357,30 @@
     return db_fetch_all($query);
 }
 
+// Returns an array of public test informations for a job
+function job_test_get_public($job_id) {
+    $query = sprintf("
+        SELECT `test_count`, `public_tests` FROM `ia_task`
+        WHERE `id` = (
+            SELECT `task_id` FROM `ia_job`
+            WHERE `id` = %s
+        )", db_quote($job_id));
+
+    $task = db_fetch($query);
+    log_assert(!is_null($task));
+
+    $test_ids = task_parse_test_group($task["public_tests"], $task["test_count"]);
+    if (!count($test_ids)) {
+        return array();
+    }
+
+    $query = sprintf("
+        SELECT * FROM `ia_job_test`
+        WHERE `job_id` = %s AND `test_number` IN (%s)
+        ORDER BY `test_number`",
+        db_quote($job_id),
+        implode(", ", array_map("db_quote", array_values($test_ids))));
+    return db_fetch_all($query);
+}
+
 ?>
Index: common/security.php
===================================================================
--- common/security.php	(revision 983)
+++ common/security.php	(working copy)
@@ -158,6 +158,7 @@
         case 'job-view-source':
         case 'job-view-source-size':
         case 'job-view-score':
+        case 'job-view-partial-feedback':
             return $action;
 
         default:
@@ -517,6 +518,7 @@
                             ($job['round_type'] != "archive" && $job['round_state'] == "complete") ||
                             $can_view_source;
     $can_view_score = ($job['round_public_eval'] == true) || $is_task_owner || $is_admin;
+    $can_view_partial_feedback = $is_owner || $is_admin;
 
     // Log query response.
     $action = security_simplify_action($action);
@@ -544,6 +546,9 @@
         case 'job-view-score':
             return $can_view_job && $can_view_score;
 
+        case 'job-view-partial-feedback':
+            return $can_view_job && $can_view_partial_feedback;
+
         default:
             log_error('Invalid job action: '.$action);
     }
Index: common/task.php
===================================================================
--- common/task.php	(revision 983)
+++ common/task.php	(working copy)
@@ -14,72 +14,23 @@
 // Get parameter infos.
 function task_get_parameter_infos() {
     return array(
-            'classic' => array(
-                'timelimit' => array(
-                        'description' => "Limita de timp (in secunde)",
-                        'default' => 1,
-                        'type' => 'float',
-                        'name' => 'Limita de timp',
-                ),
-                'memlimit' => array(
-                        'description' => "Limita de memorie (in kilobytes)",
-                        'default' => 16384,
-                        'type' => 'integer',
-                        'name' => 'Limita de memorie',
-                ),
-                'tests' => array(
-                        'description' => "Numar de teste",
-                        'default' => 10,
-                        'type' => 'integer',
-                        'name' => "Numar de teste",
-                ),
-                'testgroups' => array(
-                        'description' => "Descrierea gruparii testelor.",
-                        'default' => '1;2;3;4;5;6;7;8;9;10',
-                        'type' => 'string',
-                        'name' => "Grupare teste",
-
+        'classic' => array(
+            'timelimit' => array(
+                    'description' => "Limita de timp (in secunde)",
+                    'default' => 1,
+                    'type' => 'float',
+                    'name' => 'Limita de timp',
             ),
-            'okfiles' => array(
-                    'description' => "Daca evaluator-ul foloseste fisiere .ok",
-                    'default' => '0',
-                    'type' => 'bool',
-                    'name' => "Foloseste .ok",
-            ),
-            'evaluator' => array(
-                    'description' => "Sursa evaluatorului. Poate fi omis pentru evaluare cu diff",
-                    'default' => 'eval.c',
-                    'type' => 'string',
-                    'name' => "Evaluator",
-            ),
-    ),
-    'output-only' => array(
-            'tests' => array(
-                    'description' => "Numar de teste",
-                    'default' => 10,
+            'memlimit' => array(
+                    'description' => "Limita de memorie (in kilobytes)",
+                    'default' => 16384,
                     'type' => 'integer',
-                    'name' => "Numar de teste",
+                    'name' => 'Limita de memorie',
             ),
-            'testgroups' => array(
-                    'description' => "Descrierea gruparii testelor.",
-                    'default' => '1;2;3;4;5;6;7;8;9;10',
-                    'type' => 'string',
-                    'name' => "Grupare teste",
-            ),
-            'okfiles' => array(
-                    'description' => "Daca evaluator-ul foloseste fisiere .ok",
-                    'default' => '0',
-                    'type' => 'bool',
-                    'name' => "Foloseste .ok",
-            ),
-            'evaluator' => array(
-                    'description' => "Sursa evaluatorului. Poate fi omis pentru evaluare cu diff",
-                    'default' => 'eval.c',
-                    'type' => 'string',
-                    'name' => "Evaluator",
-            ),
-    ),
-);
+        ),
+        'output-only' => array(
+        ),
+    );
 }
 
 // Initialize a task object
@@ -93,6 +44,11 @@
             'page_name' => IA_TASK_TEXTBLOCK_PREFIX . $task_id,
             'open_source' => 0,
             'open_tests' => 0,
+            'test_count' => 10,
+            'test_groups' => NULL,
+            'public_tests' => NULL,
+            'evaluator' => NULL,
+            'use_ok_files' => 1,
     );
 
     // User stuff. ugly
@@ -152,22 +108,102 @@
         $errors['id'] = 'ID de task invalid';
     }
 
+    if (!is_whole_number($task['test_count'])) {
+        $errors['test_count'] = "Numarul de teste trebuie sa fie un numar.";
+    } else if ($task['test_count'] < 1) {
+        $errors['test_count'] = "Minim 1 test.";
+    } else if ($task['test_count'] > 100) {
+        $errors['test_count'] = "Maxim 100 de teste.";
+    }
+
+    if ($task['use_ok_files'] != '0' && $task['use_ok_files'] != '1') {
+        $errors['use_ok_files'] = "0/1 only";
+    }
+
+    if ($task['evaluator'] == "") {
+        if (!$task['use_ok_files']) {
+            $errors['evaluator'] = "Pentru evaluare cu diff e nevoie e fisiere .ok";
+        }
+    } else {
+        if (!is_attachment_name($task['evaluator'])) {
+            $errors['evaluator'] = "Nume de fisier invalid.";
+        }
+    }
+
+    if (task_get_testgroups($task) === false) {
+        $errors['test_groups'] = "Eroare de sintaxa in expresie.";
+    }
+
+    if (task_parse_test_group($task["public_tests"], $task["test_count"]) === false) {
+        $errors['public_tests'] = "Eroare de sintaxa in expresie.";
+    }
+
     return $errors;
 }
 
-// Parse test grouping expression from task parameters and returns groups as an array
+// Parse test grouping expression from task and returns groups as an array
 // If there is no grouping parameter defined it returns a group for each test by default
 // If the expression string contains errors the function returns false
 // Expression syntax:
-// item: number | number-number 
+// item: number | number-number
 // group: item | item,group
 // groups: group | group;groups
-function task_get_testgroups($parameters) {
-    $test_count = $parameters['tests'];
+function task_parse_test_group($string, $test_count) {
+    if (strlen($string) == 0)
+        return array();
+
+    $current_group = array();
+    $items = explode(',', $string);
+    $used_count = array();
+    for ($test = 1; $test <= $test_count; $test++) {
+        $used_count[$test]  = 0;
+    }
+
+    foreach ($items as &$item) {
+        $tests = explode('-', $item);
+        if (count($tests) < 1 || count($tests) > 2) {
+            return false;
+        }
+        foreach ($tests as &$test) {
+            $test = trim($test);
+            if (!is_whole_number($test)) {
+                return false;
+            }
+        }
+        if (count($tests) == 1) {
+            if ($tests[0] < 1 || $tests[0] > $test_count) {
+                return false;
+            }
+            $current_group[] = $tests[0];
+            $used_count[$tests[0]] = 1;
+        } else {
+            $left = (int) $tests[0];
+            $right = (int) $tests[1];
+            if ($left < 1 || $right < 1 || $left > $test_count || $right > $test_count) {
+                return false;
+            }
+            for ($test = min($left, $right); $test <= max($left, $right); $test++) {
+                $current_group[] = $test;
+                $used_count[$test]++;
+            }
+        }
+    }
+
+    for ($test = 1; $test <= $test_count; $test++) {
+        if ($used_count[$test] > 1) {
+            return false;
+        }
+    }
+
+    return $current_group;
+}
+
+function task_get_testgroups($task) {
+    $test_count = $task['test_count'];
     if (!is_whole_number($test_count)) {
         return false;
     }
-    if (is_null(getattr($parameters, 'testgroups'))) {
+    if (!getattr($task, 'test_groups')) {
         $testgroups = array();
         for ($test = 1; $test <= $test_count; $test++) {
             $group = array($test);
@@ -181,40 +217,15 @@
         $used_count[$test]  = 0;
     }
     $testgroups = array();
-    $groups = explode(';', $parameters['testgroups']);
+    $groups = explode(';', $task['test_groups']);
     foreach ($groups as &$group) {
-        $current_group = array();
-        $items = explode(',', $group);
-        foreach ($items as &$item) {
-            $tests = explode('-', $item);
-            if (count($tests) < 1 || count($tests) > 2) {
-                return false;
-            }
-            foreach ($tests as &$test) {
-                $test = trim($test);
-                if (!is_whole_number($test)) {
-                    return false;
-                }
-            }
-            if (count($tests) == 1) {
-                if ($tests[0] < 1 || $tests[0] > $test_count) {
-                    return false;
-                }
-                $current_group[] = $tests[0];
-                $used_count[$tests[0]]++;
-            }
-            else {
-                $left = (int) $tests[0];
-                $right = (int) $tests[1];
-                if ($left < 1 || $right < 1 || $left > $test_count || $right > $test_count) {
-                    return false;
-                }
-                for ($test = min($left, $right); $test <= max($left, $right); $test++) {
-                    $current_group[] = $test;
-                    $used_count[$test]++;
-                }
-            }
+        $current_group = task_parse_test_group($group, $test_count);
+        if (!$current_group) {
+            return false;
         }
+        foreach ($current_group as $test) {
+            $used_count[$test]++;
+        }
         $testgroups[] = $current_group;
     }
 
@@ -246,60 +257,8 @@
         } else if ($parameters['memlimit'] > 131072) {
             $errors['memlimit'] = "Maxim 128 megabytes.";
         }
-
-        if (!is_whole_number($parameters['tests'])) {
-            $errors['tests'] = "Numarul de teste trebuie sa fie un numar.";
-        } else if ($parameters['tests'] < 1) {
-            $errors['tests'] = "Minim 1 test.";
-        } else if ($parameters['tests'] > 100) {
-
-            $errors['tests'] = "Maxim 100 de teste.";
-        }
-
-        if ($parameters['okfiles'] != '0' && $parameters['okfiles'] != '1') {
-            $errors['okfiles'] = "0/1 only";
-        }
-
-        if ($parameters['evaluator'] == "") {
-            if (!$parameters['okfiles']) {
-                $errors['evaluator'] = "Pentru evaluare cu diff e nevoie e fisiere .ok";
-            }
-        } else {
-            if (!is_attachment_name($parameters['evaluator'])) {
-                $errors['evaluator'] = "Nume de fisier invalid.";
-            }
-        }
-
-        if (task_get_testgroups($parameters) === false) {
-            $errors['testgroups'] = "Eroare de sintaxa in expresie.";
-        }
-
     } else if ($task_type == 'output-only') {
-        if ($parameters['okfiles'] != '0' && $parameters['okfiles'] != '1') {
-            $errors['okfiles'] = "0/1 only";
-        }
-
-        if (!is_whole_number($parameters['tests'])) {
-            $errors['tests'] = "Numarul de teste trebuie sa fie un numar.";
-        } else if ($parameters['tests'] < 1) {
-            $errors['tests'] = "Minim 1 test.";
-        } else if ($parameters['tests'] > 100) {
-            $errors['tests'] = "Maxim 100 de teste.";
-        }
-
-        if ($parameters['evaluator'] == "") {
-            if (!$parameters['okfiles']) {
-                $errors['evaluator'] = "Pentru evaluare cu diff e nevoie e fisiere .ok";
-            }
-        } else {
-            if (!is_attachment_name($parameters['evaluator'])) {
-                $errors['evaluator'] = "Nume de fisier invalid.";
-            }
-        }
-
-        if (task_get_testgroups($parameters) === false) {
-            $errors['testgroups'] = "Eroare de sintaxa in expresie.";
-        }
+        // Nothing to validate
     } else {
         log_error("Bad task_type");
     }
Index: eval/classic_grader.php
===================================================================
--- eval/classic_grader.php	(revision 983)
+++ eval/classic_grader.php	(working copy)
@@ -20,19 +20,19 @@
 
     // Compile custom evaluator.
     // Don't send system error, send custom message
-    if ($tparams['evaluator'] !== '') {
-        if (!copy_grader_file($task, $tparams['evaluator'],
-                    IA_ROOT_DIR.'eval/temp/'.$tparams['evaluator'])) {
+    if ($task['evaluator']) {
+        if (!copy_grader_file($task, $task['evaluator'],
+                    IA_ROOT_DIR.'eval/temp/'.$task['evaluator'])) {
             log_print('Task eval not found');
             $result['message'] = 'Eroare in setarile problemei';
             $result['log'] = "Lipseste evaluatorul problemei.\n";
             $result['log'] .= "Ar trebui sa existe un atasament".
-                " 'grader_{$tparams['evaluator']}' ".
+                " 'grader_{$task['evaluator']}' ".
                 "la pagina cu enuntul problemei";
             return $result;
         }
 
-        if (!compile_file($tparams['evaluator'], 'eval', $compiler_messages)) {
+        if (!compile_file($task['evaluator'], 'eval', $compiler_messages)) {
             log_print('Task eval compile error');
             $result['message'] = 'Eroare de compilare in evaluator';
             $result['log'] = "Eroare de compilare:\n" . $compiler_messages;
@@ -57,10 +57,10 @@
 
     // Running tests.
     $test_score = array();
-    for ($testno = 1; $testno <= $tparams['tests']; ++$testno) {
+    for ($testno = 1; $testno <= $task['test_count']; ++$testno) {
         $test_score[$testno] = 0;
     }
-    $test_groups = task_get_testgroups($tparams);
+    $test_groups = task_get_testgroups($task);
     $group_idx = 0;
     foreach ($test_groups as $group) {
         $group_idx++;
@@ -118,7 +118,7 @@
             $grader_mem = null;
 
             // Copy ok file, if used.
-            if ($tparams['okfiles']) {
+            if ($task['use_ok_files']) {
                 if (!copy_grader_file($task , 'test' . $testno . '.ok', $okfile)) {
                     log_print("Test $testno: .ok file not found");
                     $result['message'] = 'Eroare in teste';
@@ -131,13 +131,13 @@
                 }
             }
 
-            if ($tparams['evaluator'] === '') {
+            if (!$task['evaluator']) {
                 // Diff grading, trivial.
                 if (is_readable($outfile)) {
                     $diff_output = shell_exec("diff -qBbEa $outfile $okfile");
                     if ($diff_output == '') {
                         log_print("Test $testno: Diff eval: Files identical"); 
-                        $score = 100 / $tparams['tests'];
+                        $score = 100 / $task['test_count'];
                         $test_msg = "OK";
                         $test_score[$testno] = $score;
                     } else {
Index: scripts/migrate_task_parameters
===================================================================
--- scripts/migrate_task_parameters	(revision 0)
+++ scripts/migrate_task_parameters	(revision 0)
@@ -0,0 +1,60 @@
+#! /usr/bin/env php
+<?php
+
+require_once(dirname($argv[0]) . "/utilities.php");
+
+db_connect();
+
+db_query("
+ALTER TABLE `ia_task`
+    ADD COLUMN `test_count` INTEGER NOT NULL DEFAULT 10,
+    ADD COLUMN `test_groups` VARCHAR(256),
+    ADD COLUMN `public_tests` VARCHAR(256),
+    ADD COLUMN `evaluator` VARCHAR(64),
+    ADD COLUMN `use_ok_files` TINYINT(1) NOT NULL DEFAULT 1");
+
+$query = "SELECT * FROM `ia_parameter_value`
+          WHERE `object_type` = 'task' AND
+                `parameter_id` != 'memlimit' AND
+                `parameter_id` != 'timelimit'";
+$rows = db_fetch_all($query);
+
+$tasks = array();
+
+foreach ($rows as $row) {
+    $task_id = $row["object_id"];
+    if (!array_key_exists($task_id, $tasks)) {
+        $tasks[$task_id] = array();
+    }
+
+    $tasks[$task_id][$row["parameter_id"]] = $row["value"];
+}
+
+foreach ($tasks as $task_id => $task) {
+    $params = array();
+
+    if (!isset($task["tests"])) {
+        log_error("Task $task_id doesn't have a test number");
+    } else {
+        $params["test_count"] = $task["tests"];
+    }
+    if (!isset($task["okfiles"])) {
+        log_error("Task $task_id doesn't have a okfiles bool");
+    } else {
+        $params["use_ok_files"] = $task["okfiles"];
+    }
+
+    $params["test_groups"] = getattr($task, "testgroups", "");
+    $params["evaluator"] = getattr($task, "evaluator", "");
+
+    log_print("Migrating parameters for task $task_id");
+    db_update('ia_task', $params, '`id` = ' . db_quote($task_id));
+}
+
+db_query("DELETE FROM `ia_parameter_value`
+          WHERE `object_type` = 'task' AND
+                `parameter_id` != 'timelimit' AND
+                `parameter_id` != 'memlimit'");
+
+?>
+

Property changes on: scripts/migrate_task_parameters
___________________________________________________________________
Added: svn:executable
   + *

Index: www/controllers/job_detail.php
===================================================================
--- www/controllers/job_detail.php	(revision 983)
+++ www/controllers/job_detail.php	(working copy)
@@ -35,10 +35,12 @@
 
     $view['title'] = 'Borderou de evaluare (job #'.$job_id.')';
     $view['job'] = $job;
-    $view['group_count'] = 0;
     $view['tests'] = array();
 
     if (identity_can('job-view-score', $job)) {
+        $view['group_tests'] = true;
+        $view['group_count'] = 0;
+
         $view['tests'] = job_test_get_all($job_id);
         foreach ($view['tests'] as $test) {
             $view['group_count'] = max($view['group_count'], $test['test_group']);
@@ -62,7 +64,11 @@
             }
         }
     } else {
-        $view['job']['score'] = "Ascuns";
+        $view['group_tests'] = false;
+        $view['job']['score'] = NULL;
+        if (identity_can("job-view-partial-feedback", $job)) {
+            $view['tests'] = job_test_get_public($job_id);
+        }
     }
 
     if (!$view['job']['eval_message']) {
@@ -71,7 +77,6 @@
     execute_view_die('views/job_detail.php', $view);
 }
 
-
 function controller_job_view_source($job_id) {
     if (!is_whole_number($job_id)) {
         flash_error("Numar de job invalid.");
@@ -86,6 +91,9 @@
     }
 
     identity_require('job-view-source', $job);
+    if (!identity_can("job-view-score", $job)) {
+        $job['score'] = NULL;
+    }
 
     $view = array();
     $view['title'] = 'Cod sursa (job #'.$job_id.')';
Index: www/controllers/monitor.php
===================================================================
--- www/controllers/monitor.php	(revision 983)
+++ www/controllers/monitor.php	(working copy)
@@ -2,6 +2,7 @@
 
 require_once(IA_ROOT_DIR."www/format/pager.php");
 require_once(IA_ROOT_DIR."common/db/job.php");
+require_once(IA_ROOT_DIR."common/db/task.php");
 require_once(IA_ROOT_DIR."www/controllers/job_filters.php");
 
 // Job monitor controller.
@@ -15,8 +16,27 @@
     // FIXME: shouldn't this constant be in config.php? 
     $options = pager_init_options(array('display_entries' => 25));
 
+    $job_data = job_get_range($view['filters'], $options['first_entry'], $options['display_entries']);
+    $jobs = array();
+    foreach ($job_data as $job) {
+        if (!identity_can("job-view-score", $job)) {
+            $job["score"] = NULL;
+            if (identity_can("job-view-partial-feedback", $job)) {
+                $task = task_get($job["task_id"]);
+                if ($task["public_tests"]) {
+                    $job["feedback_available"] = true;
+                }
+            }
+        }
+        if (!identity_can('job-view-source-size', $job)) {
+            $job["job_size"] = NULL;
+        }
+
+        $jobs[] = $job;
+    }
+
     $view['title'] = 'Monitorul de evaluare';
-    $view['jobs'] = job_get_range($view['filters'], $options['first_entry'], $options['display_entries']);
+    $view['jobs'] = $jobs;
     $view['total_entries'] = job_get_count($view['filters']);
     $view['first_entry'] = $options['first_entry'];
     $view['display_entries'] = $options['display_entries'];
Index: www/controllers/task.php
===================================================================
--- www/controllers/task.php	(revision 983)
+++ www/controllers/task.php	(working copy)
@@ -42,15 +42,14 @@
     $errors = array();
 
     // Fill in form values from request, defaults in $task
-    $values['author'] = request('author', $task['author']);
-    $values['type'] = request('type', $task['type']);
-    $values['source'] = request('source', $task['source']);
-    $values['hidden'] = request('hidden', $task['hidden']);
-    $values['title'] = request('title', $task['title']);
-    $values['page_name'] = request('page_name', $task['page_name']);
-    $values['open_source'] = request('open_source', $task['open_source']);
-    $values['open_tests'] = request('open_tests', $task['open_tests']);
+    $fields = array('author', 'type', 'source', 'hidden', 'title', 'page_name',
+                    'open_source', 'open_tests', 'test_count', 'test_groups',
+                    'evaluator', 'use_ok_files', 'public_tests');
 
+    foreach ($fields as $field) {
+        $values[$field] = request($field, $task[$field]);
+    }
+
     // Parameter values, for all possible types of tasks.
     // Yucky, but functional.
     foreach (task_get_types() as $task_type => $pretty_name) {
@@ -71,14 +70,9 @@
     if (request_is_post()) {
         // Build new task
         $new_task = $task;
-        $new_task['title'] = $values['title'];
-        $new_task['page_name'] = $values['page_name'];
-        $new_task['author'] = $values['author'];
-        $new_task['source'] = $values['source'];
-        $new_task['type'] = $values['type'];
-        $new_task['hidden'] = $values['hidden'];
-        $new_task['open_source'] = $values['open_source'];
-        $new_task['open_tests'] = $values['open_tests'];
+        foreach ($fields as $field) {
+            $new_task[$field] = $values[$field];
+        }
 
         $task_errors = task_validate($new_task);
         $errors = $task_errors;
Index: www/macros/macro_taskparam.php
===================================================================
--- www/macros/macro_taskparam.php	(revision 983)
+++ www/macros/macro_taskparam.php	(working copy)
@@ -63,20 +63,20 @@
         case 'id':
             return html_escape($task['id']);
 
-        case 'owner':	    
-	    if( $task['user_id']=='0' ) {
-		return '';
-	    }
-	    $user = user_get_by_id( $task['user_id'] );	    
+        case 'owner':
+            if ($task['user_id'] == '0') {
+                return '';
+            }
+            $user = user_get_by_id($task['user_id']);
             return html_escape($user['full_name']);
 
         case 'formatted_owner':
-	    if( $task['user_id']=='0' ) {
-		return '';
-	    }
-	    $user = user_get_by_id( $task['user_id'] );
-	    return format_user_tiny($user['username'], $user['full_name'],
-		                    $user['rating_cache']);
+            if ($task['user_id'] == '0') {
+                return '';
+            }
+            $user = user_get_by_id($task['user_id']);
+            return format_user_tiny($user['username'], $user['full_name'],
+                                    $user['rating_cache']);
 
         default:
             if (!isset($params[$param])) {

Property changes on: www/controllers/textblock_copy.php
___________________________________________________________________
Deleted: svn:noexecutable
   - on
Deleted: svn:executable
   - *

Index: www/views/job_detail.php
===================================================================
--- www/views/job_detail.php	(revision 983)
+++ www/views/job_detail.php	(working copy)
@@ -5,7 +5,8 @@
 require_once(IA_ROOT_DIR . 'www/url.php');
 
 // display group sum column?
-$show_groups = ($view['group_count'] < count($view['tests']));
+$show_groups = $view['group_tests'] &&
+               ($view['group_count'] < count($view['tests']));
 
 ?>
 
@@ -22,7 +23,7 @@
     <th class="task-id">Problema</th>
     <td class="task-id"><?= format_link(url_textblock($job['task_page_name']), $job['task_title']) ?></td>
     <th class="score">Scor</th>
-    <td class="score"><?= html_escape($job['score']) ?></td>
+    <td class="score"><?= html_escape(is_null($job['score']) ? "Ascuns" : $job['score']) ?></td>
 </tr>
 </tr>
 <tr>
@@ -70,8 +71,16 @@
 <tbody>
 <?php
     $last_group = 0;
+    if (!$view["group_tests"]) {
+        $test_row = 0;
+    }
     foreach ($view['tests'] as $test) {
-        echo '<tr class="'.($test['test_group'] % 2 == 1 ? "odd" : "even").'">';
+        if ($view["group_tests"]) {
+            echo '<tr class="'.($test['test_group'] % 2 == 1 ? "odd" : "even").'">';
+        } else {
+            echo '<tr class="'.($test_row % 2 == 1 ? "odd" : "even").'">';
+            $test_row++;
+        }
         echo '<td class="number">'.$test['test_number'].'</td>';
         echo '<td class="number">'.$test['exec_time'].'ms</td>';
         echo '<td class="number">'.$test['mem_used'].'kb</td>';
@@ -85,8 +94,10 @@
         }
         echo '</tr>';
     }
-    echo '<tr><td colspan="'.($show_groups ? 5 : 4).'">'.
-         'Punctaj total</td><td class="total_score number">'.$job['score'].'</td></tr>';
+    if (!is_null($job['score'])) {
+        echo '<tr><td colspan="'.($show_groups ? 5 : 4).'">'.
+             'Punctaj total</td><td class="total_score number">'.$job['score'].'</td></tr>';
+    }
 ?>
 </tbody>
 </table>
Index: www/views/job_view_source.php
===================================================================
--- www/views/job_view_source.php	(revision 983)
+++ www/views/job_view_source.php	(working copy)
@@ -17,7 +17,7 @@
     <th class="task-id">Problema</th>
     <td class="task-id"><?= format_link(url_textblock($job['task_page_name']), $job['task_title']) ?></td>
     <th class="score">Scor</th>
-    <td class="score"><?= html_escape($job['score']) ?></td>
+    <td class="score"><?= html_escape(is_null($job['score']) ? "Ascuns" : $job['score']) ?></td>
 </tr>
 </tr>
 <tr>
Index: www/views/monitor.php
===================================================================
--- www/views/monitor.php	(revision 983)
+++ www/views/monitor.php	(working copy)
@@ -67,11 +67,14 @@
     function format_state($row) {
         $url = url_job_detail($row['id']);
         if ($row['status'] == 'done') {
-            if (identity_can("job-view-score", $row)) {
+            if (!is_null($row['score'])) {
                 $msg = html_escape(sprintf("%s: %s puncte",
                     $row['eval_message'], $row['score']));
             } else {
                 $msg = html_escape($row['eval_message']);
+                if (isset($row["feedback_available"])) {
+                    $msg .= ": rezultate partiale disponibile";
+                }
             }
             $msg = "<span style=\"job-status-done\">$msg</span>";
             return format_link($url, $msg, false);
@@ -124,7 +127,7 @@
 
     // For the size column.
     function format_size($row) {
-        if (!identity_can('job-view-source-size', $row)) {
+        if (is_null($row['job_size'])) {
             return "...";
         }
         $size = sprintf("%.2f", $row['job_size']/1024)." kb";
Index: www/views/task_edit.php
===================================================================
--- www/views/task_edit.php	(revision 983)
+++ www/views/task_edit.php	(working copy)
@@ -58,6 +58,36 @@
                 'name' => 'Acces liber la teste',
                 'type' => 'bool'
         ),
+        'test_count' => array(
+                'description' => "Numar de teste",
+                'default' => 10,
+                'type' => 'integer',
+                'name' => "Numar de teste",
+        ),
+        'test_groups' => array(
+                'description' => "Descrierea gruparii testelor.",
+                'default' => '1;2;3;4;5;6;7;8;9;10',
+                'type' => 'string',
+                'name' => "Grupare teste",
+        ),
+        'public_tests' => array(
+                'description' => "Lista de teste pe care utilizatorii pot vedea rezultatele in concursuri.",
+                'default' => '',
+                'type' => 'string',
+                'name' => "Detailed feedback",
+        ),
+        'use_ok_files' => array(
+                'description' => "Daca evaluator-ul foloseste fisiere .ok",
+                'default' => '0',
+                'type' => 'bool',
+                'name' => "Foloseste .ok",
+        ),
+        'evaluator' => array(
+                'description' => "Sursa evaluatorului. Poate fi omis pentru evaluare cu diff",
+                'default' => 'eval.c',
+                'type' => 'string',
+                'name' => "Evaluator",
+        ),
 );
 
 ?>
@@ -107,6 +137,12 @@
     <fieldset>
     <legend>Detalii despre evaluare</legend>
     <ul class="form">
+        <?= view_form_field_li($form_fields['test_count'], 'test_count') ?>
+        <?= view_form_field_li($form_fields['test_groups'], 'test_groups') ?>
+        <?= view_form_field_li($form_fields['public_tests'], 'public_tests') ?>
+        <?= view_form_field_li($form_fields['use_ok_files'], 'use_ok_files') ?>
+        <?= view_form_field_li($form_fields['evaluator'], 'evaluator') ?>
+
         <?= view_form_field_li($form_fields['type'], 'type') ?>
         <li><hr /></li>
         <li id="field_params">
