Index: common/db/score.php
===================================================================
--- common/db/score.php	(revision 1184)
+++ common/db/score.php	(working copy)
@@ -31,6 +31,14 @@ function score_update($user_id, $task_id, $round_id, $value) {
     // Add user_id score for task_id at round_id to cache
     mem_cache_set("user-task-round:".$user_id."-".$task_id."-".$round_id, (int)$value);
 
+    // Also update user-task-max-score if it's in the cache
+    $cache_key = 'user-task-last-score:'.$user_id.'-'.$task_id;
+    if (($res = mem_cache_get($cache_key)) != false) {
+        if ($value > $res) {
+            mem_cache_set($cache_key, $value);
+        }
+    }
+
     // Update user_id score for task_id at round_id
     $query = "INSERT INTO `ia_score_user_round_task` (`user_id`, `round_id`, `task_id`, `score`)
             VALUES (".implode(',',
@@ -410,6 +418,7 @@ function score_get_rankings($rounds, $tasks, $start = 0, $count = 999999,
                 FROM ia_score_user_round
                 WHERE ".implode('AND', $where);
         $scores = db_fetch_all($query);
+        $round_scores = array(array());
         foreach ($scores as $score) {
             $user_id = $score['user_id'];
             $round_id = $score['round_id'];
@@ -424,6 +433,7 @@ function score_get_rankings($rounds, $tasks, $start = 0, $count = 999999,
                 FROM ia_score_user_round_task
                 WHERE ".implode('AND', $where);
         $scores = db_fetch_all($query);
+        $task_scores = array(array());
         foreach ($scores as $score) {
             $user_id = $score['user_id'];
             $task_id = $score['task_id'];
@@ -487,4 +497,4 @@ function score_get_rankings($rounds, $tasks, $start = 0, $count = 999999,
 }
 
 
-?>
+
Index: common/db/task.php
===================================================================
--- common/db/task.php	(revision 1184)
+++ common/db/task.php	(working copy)
@@ -382,6 +382,40 @@ function task_get_user_score($task_id, $user_id, $round_id = 'arhiva') {
 }
 
 /**
+ * Returns the maximum last score a user got on a task in archives.
+ *
+ * @param $task_id string
+ * @param $user_id string
+ * @return int
+*/
+function task_get_user_last_score($task_id, $user_id) {
+    // Validate
+    log_assert(is_task_id($task_id));
+    log_assert(is_user_id($user_id));
+
+    // Check the cache
+    $cache_key = 'user-task-last-score:'.$user_id.'-'.$task_id;
+    if (($res = mem_cache_get($cache_key)) != false) {
+        return $res;
+    }
+
+    // Query database
+    $query = sprintf(
+        "SELECT MAX(`score`) as maxscore FROM ia_score_user_round_task
+         LEFT JOIN ia_round ON ia_round.id = round_id AND
+         ia_round.type = 'archive' WHERE task_id = %s AND
+         ia_score_user_round_task.user_id = %s ",
+         db_quote($task_id), db_quote($user_id)) ;
+    $res = db_fetch($query);
+    $score = getattr($res, "maxscore", null);
+
+    // Keep in cache
+    mem_cache_set($cache_key, (int)$score);
+
+    return $score;
+}
+
+/**
  * Returns the number of previous submits of an users to a task in a contest
  *
  * @param int $user_id
Index: common/security.php
===================================================================
--- common/security.php	(revision 1184)
+++ common/security.php	(working copy)
@@ -159,6 +159,7 @@ function security_simplify_action($action) {
         case 'grader-download':
         case 'task-use-in-user-round':
         case 'task-submit':
+        case 'task-view-last-score':
         case 'round-edit':
         case 'round-create':
         case 'round-submit':
@@ -431,6 +432,9 @@ function security_task($user, $action, $task) {
             }
             return ($task['security'] != 'private' && $is_running);
 
+        case 'task-view-last-score':
+            return $task['security'] == 'public' || $is_boss;
+
         case 'grader-download':
             return ($task['open_tests'] && $task['security'] == 'public')
                     || $is_boss;
Index: www/format/format.php
===================================================================
--- www/format/format.php	(revision 1184)
+++ www/format/format.php	(working copy)
@@ -355,3 +355,25 @@ function format_blogpost_author($blogpost) {
           . '</div>';
     return $text;
 }
+
+/**
+ * Formats the task author tags
+ *
+ * @param array $authors    an array containing the author tags
+ * @return array
+ */
+function format_task_author_tags($authors) {
+    if ($authors == null)
+      return array();
+
+    log_assert(is_array($authors));
+
+    $authors_formatted = array();
+    foreach ($authors as $tag) {
+      $authors_formatted[] =
+          format_link(
+              url_task_search(array($tag["id"])), $tag["name"]);
+    }
+
+    return $authors_formatted;
+}
Index: www/macros/macro_taskparam.php
===================================================================
--- www/macros/macro_taskparam.php	(revision 1184)
+++ www/macros/macro_taskparam.php	(working copy)
@@ -53,10 +53,7 @@ function macro_taskparam($args) {
 
         case 'author':
             $authors = task_get_authors($task['id']);
-            function format_author($tag) {
-                return format_link(url_task_search(array($tag["id"])), $tag["name"]);
-            }
-            return implode(", ", array_map('format_author', $authors));
+            return implode(", ", format_task_author_tags($authors));
 
         case 'source':
             // TODO: This should also be converted into tags.
@@ -92,12 +89,13 @@ function macro_taskparam($args) {
                                'type' => 'normal');
             return macro_stars($star_args);
 
-        case 'archivescore':
+        case 'lastscore':
             $user = identity_get_user();
-            if (is_null($user)) {
+            if (is_null($user) ||
+                !identity_can("task-view-last-score", $task)) {
                 return 'N/A';
             } else {
-                $score = task_get_user_score($task['id'], $user['id']);
+                $score = task_get_user_last_score($task['id'], $user['id']);
                 if (is_null($score)) {
                     return 'N/A';
                 } else {
@@ -118,4 +116,4 @@ function macro_taskparam($args) {
             }
     }
 }
-?>
+
