Index: common/db/score.php
===================================================================
--- common/db/score.php	(revision 1168)
+++ common/db/score.php	(working copy)
@@ -4,6 +4,7 @@
 require_once(IA_ROOT_DIR."common/db/round.php");
 require_once(IA_ROOT_DIR."common/parameter.php");
 require_once(IA_ROOT_DIR."common/rating.php");
+require_once(IA_ROOT_DIR."common/cache.php");
 
 // Updates a user's rating and deviation
 function score_update_rating($user_id, $round_id, $deviation, $rating)
@@ -27,6 +28,9 @@
     log_assert(is_task_id($task_id), "Bad task id '$task_id'");
     log_assert(is_round_id($round_id), "Bad round id '$round_id'");
 
+    // 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);
+
     // 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(',',
Index: common/db/task.php
===================================================================
--- common/db/task.php	(revision 1168)
+++ common/db/task.php	(working copy)
@@ -360,13 +360,24 @@
         log_error("Invalid user id");
     }
 
+    // Check the cache
+    if (($res = mem_cache_get("user-task-round:".$user_id."-".$task_id."-".$round_id)) != false) {
+        log_var_dump($res);
+        return $res;
+    }
+
+    // Query database
     $query = sprintf(
         "SELECT `score` FROM ia_score_user_round_task
          WHERE round_id = %s AND task_id = %s AND user_id = %s",
          db_quote($round_id), db_quote($task_id), db_quote($user_id));
     $res = db_fetch($query);
+    $score = getattr($res, "score", null);
 
-    return getattr($res, "score", null);
+    // Keep in cache
+    mem_cache_set("user-task-round:".$user_id."-".$task_id."-".$round_id, (int)$score);
+
+    return $score;
 }
 
 /**
Index: common/round.php
===================================================================
--- common/round.php	(revision 1168)
+++ common/round.php	(working copy)
@@ -1,4 +1,4 @@
-B0;95;c<?php
+<?php
 // This module implements round and round-param related stuff.
 
 // Get valid round types.
Index: common/security.php
===================================================================
--- common/security.php	(revision 1168)
+++ common/security.php	(working copy)
@@ -1,6 +1,7 @@
 <?php
 
 require_once(IA_ROOT_DIR."common/db/round.php");
+require_once(IA_ROOT_DIR."common/db/task.php");
 
 
 // This module implements everything related to security.
@@ -570,26 +571,16 @@
     return $is_admin;
 }
 
-
 // There is no job-eval, jobs are evaluated on the spot, we check job-view instead.
 function security_job($user, $action, $job) {
     $usersec = getattr($user, 'security_level', 'anonymous');
     $is_admin = $usersec == 'admin';
     $is_intern = $usersec == 'intern';
     $is_owner = ($job['user_id'] == $user['id']);
-    $is_task_owner = ($job['task_owner_id'] == $user['id'] && 
+    $is_task_owner = ($job['task_owner_id'] == $user['id'] &&
                       in_array($usersec, array('helper', 'intern')));
-    $can_view_job = ($job['task_hidden'] == false) || $is_task_owner || $is_admin;
-    $can_view_source = ($job['task_open_source'] == true) || $is_task_owner || 
-                       $is_owner || $is_admin || $is_intern;
-    $can_view_source_size = ($job['round_type'] == "archive") ||
-                            ($job['round_type'] != "archive" && $job['round_state'] == "complete") ||
-                            $can_view_source;
-    $can_view_score = ($job['round_public_eval'] == true) || $is_task_owner || $is_admin || $is_intern;
-    $can_view_partial_feedback = $is_owner || $is_admin || $is_intern;
-    $can_view_sensitive_info = in_array($usersec, array('admin', 'intern', 'helper'));
 
-    // Log query response.
+     // Log query response.
     $action = security_simplify_action($action);
     $level = ($is_admin ? 'admin' : ($is_owner ? 'owner' : ($is_task_owner ? 'task-owner' : 'other')));
     $objid = $job['id'];
@@ -598,11 +589,28 @@
                 "($level, $action, $objid): ".
                 "(level, action, object)");
     }
+    if ($action == 'simple-critical') {
+        return $is_admin || $is_intern;
+    }
 
+    $can_view_job = ($job['task_hidden'] == false) || $is_task_owner || $is_admin;
+    $can_view_source = ($job['task_open_source'] == true) || $is_task_owner ||
+                       $is_owner || $is_admin || $is_intern;
+    // make ALL solved tasks visible
+    if (!$can_view_source && is_user_id($user['id']) && $job['round_type'] == "archive") {
+        $score = task_get_user_score($job['task_id'], $user['id'], $job['round_id']);
+        if ($score == 100) {
+            $can_view_source = true;
+        }
+    }
+    $can_view_source_size = ($job['round_type'] == "archive") ||
+                            ($job['round_type'] != "archive" && $job['round_state'] == "complete") ||
+                            $can_view_source;
+    $can_view_score = ($job['round_public_eval'] == true) || $is_task_owner || $is_admin || $is_intern;
+    $can_view_partial_feedback = $is_owner || $is_admin || $is_intern;
+    $can_view_sensitive_info = in_array($usersec, array('admin', 'intern', 'helper'));
+
     switch ($action) {
-        case 'simple-critical':
-            return $is_admin || $is_intern;
-
         case 'job-view':
             return $can_view_job;
 
