Index: common/db/round.php
===================================================================
--- common/db/round.php	(revision 1009)
+++ common/db/round.php	(working copy)
@@ -80,7 +80,7 @@
     if ($count === null) {
         $count = 666013;
     }
-    $fields = "round_task.task_id AS id, ".
+    $fields = "round_task.task_id AS task_id, ".
               "task.`order` AS `order`, ".
               "task.`title` AS `title`, ".
               "task.`author` AS `author`, ".
@@ -95,44 +95,41 @@
         $query = sprintf("SELECT $fields
                           FROM ia_round_task as round_task
                           LEFT JOIN ia_task as task ON task.id = round_task.task_id
-                          WHERE `round_task`.`round_id` = '%s'
+                          WHERE `round_task`.`round_id` IN ( %s )
                           ORDER BY task.`order` LIMIT %d, %d",
-                         db_escape($round_id), db_escape($first), db_escape($count));
+                         db_escape_array($round_id), db_escape($first), db_escape($count));
     } else {
         $filter_clause = db_get_task_filter_clause($filter, 'score');
         log_assert(is_whole_number($user_id));
-        $query = sprintf("SELECT $fields, score.score as score
+        $query = sprintf("SELECT $fields, score.`score` AS `score`
                           FROM ia_round_task as round_task
                           LEFT JOIN ia_task as task ON task.id = round_task.task_id
-                          LEFT JOIN ia_score as score ON
+                          LEFT JOIN ia_score_user_round_task as score ON
                                 score.user_id = %s AND
-                                score.name = '%s' AND
                                 score.round_id = '%s' AND
                                 score.task_id = round_task.task_id
-                          WHERE `round_task`.`round_id` = '%s'
+                          WHERE `round_task`.`round_id` IN ( '%s' )
                               AND %s
                           ORDER BY task.`order` LIMIT %d, %d",
-                         db_escape($user_id), db_escape($score_name), db_escape($round_id),
-                         db_escape($round_id), db_escape($filter_clause),
+                         db_escape($user_id), db_escape($round_id),
+                         db_escape_array($round_id), db_escape($filter_clause),
                          db_escape($first), db_escape($count));
     }
     return db_fetch_all($query);
 }
 
-function round_get_task_count($round_id, $user_id, $scores, $filter)
+function round_get_task_count($round_id, $user_id, $filter)
 {
-    if ($user_id && $filter && $scores) {
-        $filter_clause = db_get_task_filter_clause($filter, 'ia_score');
+    if ($user_id && $filter) {
+        $filter_clause = db_get_task_filter_clause($filter, 'ia_score_user_round_task');
         $query = sprintf("SELECT COUNT(*) FROM ia_round_task " .
-                         "LEFT JOIN ia_score " .
-                         "ON ia_round_task.round_id = ia_score.round_id " .
-                         "AND ia_round_task.task_id = ia_score.task_id " .
-                         "AND ia_score.user_id = %s " .
-                         "AND ia_score.name = '%s' " .
+                         "LEFT JOIN ia_score_user_round_task " .
+                         "ON ia_round_task.round_id = ia_score_user_round_task.round_id " .
+                         "AND ia_round_task.task_id = ia_score_user_round_task.task_id " .
+                         "AND ia_score_user_round_task.user_id = %s " .                         
                          "WHERE ia_round_task.round_id = '%s' " .
                          "AND %s",
                          db_escape($user_id),
-                         db_escape($scores),
                          db_escape($round_id),
                          db_escape($filter_clause)
                          );
Index: common/db/score.php
===================================================================
--- common/db/score.php	(revision 1009)
+++ common/db/score.php	(working copy)
@@ -26,16 +26,55 @@
     log_assert(is_null($user_id) || is_user_id($user_id), "Bad user id '$user_id'");
     log_assert(is_null($task_id) || is_task_id($task_id), "Bad task id '$task_id'");
     log_assert(is_null($round_id) || is_round_id($round_id), "Bad round id '$round_id'");
-    $query = sprintf("
-            INSERT INTO ia_score (`name`, `score`, `user_id`, `task_id`, `round_id`)
-            VALUES ('%s', %s, %s, %s, %s) ON DUPLICATE KEY UPDATE `score`=%s",
-            db_escape($name), $value,
-            ($user_id === null ? 'NULL' : $user_id),
-            ($task_id === null ? 'NULL' : "'".db_escape($task_id)."'"),
-            ($round_id === null ? 'NULL' : "'".db_escape($round_id)."'"),
-            $value);
-    //log_print($query);
-    return db_query($query);
+
+    if ($name == 'deviation' || $name == 'rating') {
+        if ($name == 'deviation') {
+            $deviation = $value;
+            $rating = 0;
+        } else {
+            $deviation = 0;
+            $rating = $value;
+        }
+        $query = "INSERT INTO `ia_rating` (`user_id`, `round_id`, `deviation`, `rating`)
+                VALUES (".implode(',', 
+                array(db_quote($user_id),
+                    db_quote($round_id),
+                    db_quote($deviation),
+                    db_quote($rating)
+                )).") ON DUPLICATE KEY UPDATE ".
+                    $name ." = ". $value;
+        db_query($query);
+    } else {
+        //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(',',
+                array(db_quote($user_id),
+                    db_quote($round_id),
+                    db_quote($task_id),
+                    db_quote($value)
+                )).") ON DUPLICATE KEY UPDATE
+                    `score` = ".db_quote($value);
+        db_query($query);
+
+        //get score for round_id 
+        $query = "SELECT SUM(`score`) AS 'score' FROM `ia_score_user_round_task` 
+                WHERE 
+                    `round_id` = ".db_quote($round_id)." &&
+                    `user_id` = ".db_quote($user_id)."
+                GROUP BY `user_id`";
+        $result = db_fetch_all($query);
+        $rscore = $result['score'];
+
+        //update score for round_id
+        $query = "INSERT INTO `ia_score_user_round` (`user_id`, `round_id`, `score`)
+                VALUES (".implode(',', 
+                array(db_quote($user_id),
+                    db_quote($round_id),
+                    db_quote($rscore)
+                )).") ON DUPLICATE KEY UPDATE 
+                    `score` = ".db_quote($rscore);
+        db_query($query);
+    }
 }
 
 // Builds a where clause for a score query.
@@ -86,30 +125,18 @@
     return $where;
 }
 
-// Build a query for a certain score.
-// Can be used as a subquery.
-function score_build_query($score, $user, $task, $round)
-{
-    $cond = score_build_where_clauses($user, $task, $round);
-    $cond[] = "(id = '".db_escape($score['name'])."')";
-    $query = "SELECT SUM(score) FROM ia_score WHERE " . implode(" AND ", $cond);
-}
-
 // Get scores.
 // $user, $task, $round can be null, string or an array.
 // If null it's ignored, otherwise only scores for those users/tasks/rounds
 // are counted.
-function score_get_range($score_name, $user, $task, $round, $groupby = "user_id", $start = 0, $count = 999999, $with_rankings = false)
+function score_get_range($user, $task, $round, $groupby = "user_id", $start = 0, $count = 999999, $with_rankings = false)
 {
-    log_assert(is_score_name($score_name));
     $where = score_build_where_clauses($user, $task, $round);
-    $where[] = sprintf("ia_score.`name` = '%s'", db_escape($score_name));
-    $query = sprintf("SELECT
-                ia_score.`name` AS `score_name`, `user_id`, `task_id`, `round_id`, SUM(`score`) AS score, 
+    $query = sprintf("SELECT `user_id`, `task_id`, `round_id`, SUM(`score`) AS score, 
                 ia_user.username AS user_name, ia_user.full_name AS user_full,
                 ia_user.rating_cache AS user_rating
-            FROM ia_score
-                LEFT JOIN ia_user ON ia_user.id = ia_score.user_id
+            FROM ia_score_user_round_task
+                LEFT JOIN ia_user ON ia_user.id = ia_score_user_round_task.user_id
             WHERE %s GROUP BY %s
             ORDER BY `score` DESC LIMIT %s, %s",
             join($where, " AND "), $groupby, $start, $count);
@@ -121,9 +148,8 @@
         // We need to count all users with a greater score than the first user
         // in the requested range.
         $where = score_build_where_clauses($user, $task, $round);
-        $where[] = sprintf("ia_score.`name` = '%s'", db_escape($score_name));
         $query = sprintf("SELECT SUM(`score`) AS score 
-                          FROM ia_score
+                          FROM ia_score_user_round_task
                           WHERE %s GROUP BY %s
                           HAVING score > %s",
                          join($where, " AND "), $groupby, $first_score);
@@ -152,17 +178,12 @@
 // Count function for score_get_range
 function score_get_count($score_name, $user, $task, $round, $groupby) {
     log_assert(is_score_name($score_name));
+
     $where = score_build_where_clauses($user, $task, $round);
-    $where[] = sprintf("ia_score.`name` = '%s'", db_escape($score_name));
-    if ($user !== null) {
-        $join = "LEFT JOIN ia_user ON ia_user.id = ia_score.user_id";
-    } else {
-        $join = "";
-    }
     $query = sprintf("SELECT COUNT(DISTINCT user_id) AS `cnt`
-            FROM ia_score $join
+            FROM ia_score_user_round 
             WHERE %s",
-            join($where, " AND "), $groupby);
+            join($where, " AND "));
     $res = db_fetch($query);
     return $res['cnt'];
 }
@@ -176,9 +197,9 @@
     log_assert(is_task_id($task_id));
     log_assert(is_user_id($round_id));
 
-    $query = sprintf("SELECT score FROM ia_score
-                WHERE name = '%s', task_id='%s', round_id='%s', user_id = %s",
-                $score_name, $task_id, $round_id, $user_id);
+    $query = sprintf("SELECT score FROM ia_score_user_round_task_id
+                WHERE task_id='%s', round_id='%s', user_id = %s",
+                $task_id, $round_id, $user_id);
     $res = db_fetch($query);
     return getattr($res, 'score', null);
 }
@@ -197,6 +218,7 @@
 //      ...
 //  );
 // Rounds are ordered in chronological order.
+// FIXME
 function rating_history($user_id) {
     log_assert(is_whole_number($user_id));
 
@@ -204,30 +226,17 @@
     $history = rating_rounds();
 
     // get user scores
-    $query = sprintf("SELECT * FROM `ia_score`
+    $query = sprintf("SELECT * FROM `ia_rating`
                       LEFT JOIN ia_round ON round_id = ia_round.id
-                      WHERE `name` IN ('deviation', 'rating')
-                            AND user_id = '%s'
+                      WHERE ia_rating.user_id = '%s'
                             AND ia_round.state = 'complete'
-                     ",
-                     db_escape($user_id));
+                     ", db_escape($user_id));
     $rows = db_fetch_all($query);
 
-    // process user scores
     foreach ($rows as $row) {
         $round_id = $row['round_id'];
-        log_assert(isset($history[$round_id]));
-
-        switch ($row['name']) {
-            case 'rating':
-                $history[$round_id]['rating'] = $row['score'];
-                break;
-            case 'deviation':
-                $history[$round_id]['deviation'] = $row['score'];
-                break;
-            default:
-                log_error("Query returned invalid rating scores");
-        }
+        $history[$round_id]['rating'] = $row['rating'];
+        $history[$round_id]['rating'] = $row['deviation'];
     }
 
     // filter out rows which user has not participated in
@@ -326,47 +335,33 @@
 //
 // Last user ratings (but no deviation / timestamp) is stored directly in
 // table ia_user.
+// FIXME
 function rating_last_scores() {
     // FIXME: horrible query
     $query = "SELECT
-        ia_score.name AS `name`, ia_score.score AS score,
-               ia_score.user_id, ia_score.round_id,
+        ia_rating.rating AS `rating`, ia_rating.deviation AS deviation,
+               ia_rating.user_id, ia_rating.round_id,
                pv.`value` AS `timestamp`, ia_user.username
-        FROM ia_score
+        FROM ia_rating
         LEFT JOIN ia_parameter_value AS pv
-            ON pv.object_type = 'round' AND pv.object_id = ia_score.round_id
+            ON pv.object_type = 'round' AND pv.object_id = ia_rating.round_id
             AND pv.parameter_id = 'rating_timestamp'
-        LEFT JOIN ia_user ON ia_user.id = ia_score.user_id
-        WHERE ia_score.name IN ('rating', 'deviation')
-        ORDER BY `timestamp` DESC, ia_score.round_id DESC
+        LEFT JOIN ia_user ON ia_user.id = ia_rating.user_id
+        ORDER BY `timestamp` DESC, ia_rating.round_id DESC
     ";
     $rows = db_fetch_all($query);
 
-    // FIXME: We should filter out rounds having rating_update off
-    // but these should not have any ratings stored in database anyway...
-
-    // parse rows 
     $users = array();
     foreach ($rows as $row) {
         $username = $row['username'];
-        $field = $row['name'];
         if (isset($users[$username])) {
-            if (isset($users[$username][$field])) {
-                // FIXME: This is currently a hack.
-                // Query shouldn't return more then one rating for each user
-                continue;
-            }
-            else {
-                $users[$username][$field] = $row['score'];
-            }
+            continue;
         }
-        else {
-            $users[$username] = array(
-                $field => $row['score'],
-                'timestamp' => parameter_decode('rating_timestamp',
-                                                $row['timestamp'])
-            );
-        }
+
+        $users[$username] = array(
+                'rating' => $row['rating'],
+                'deviation' => $row['deviation'],
+                'timestamp' => $row['timestamp']);
     }
 
     return $users;
@@ -459,8 +454,88 @@
 
 // Clears ALL user ratings & rating history
 function rating_clear() {
-    db_query("DELETE FROM ia_score WHERE `name` IN ('rating', 'deviation')");
+    db_query("DELETE FROM ia_rating");
     db_query("UPDATE ia_user SET rating_cache = NULL");
 }
 
+//computes rankings for $rounds
+//returns entries from start to count
+//if detail == true, extra columns for each task will be created
+function get_rankings($rounds, $tasks, $start = 0, $count = 999999, $detail = 0)
+{
+    $where = score_build_where_clauses(null, null, $rounds);
+
+    $query = "SELECT SUM(score) AS score, user_id, ia_user.username AS user_name, ia_user.full_name AS user_full, 
+                    ia_user.rating_cache AS user_rating
+            FROM ia_score_user_round
+            LEFT JOIN ia_user ON ia_user.id = ia_score_user_round.user_id
+            WHERE ".implode('AND', $where)."
+            GROUP BY `user_id`
+            ORDER BY score DESC
+            LIMIT ".$start.", ".$count;
+
+    $rankings = db_fetch_all($query);
+
+    if ($detail == 1) {
+        $query = "SELECT task_id, user_id, score 
+                FROM ia_score_user_round_task 
+                WHERE ".implode('AND', $where);
+
+        $task_scores = db_fetch_all($query);
+        foreach ($task_scores as $task) {
+            $user_id = $task['user_id'];
+            $task_id = $task['task_id'];
+            $score = $task['score'];
+            $detailed_scores[$user_id][$task_id] = $score;
+        }
+    }
+
+    $top_score = $rankings[0]['score'];
+    $query = "SELECT SUM(score) AS score
+                FROM ia_score_user_round
+                WHERE ".implode(',', $where)."
+                GROUP BY user_id
+                HAVING score > ".db_quote($top_score);
+    $first_rank = db_num_rows(db_query($query)) + 1;
+
+    //create first entry
+    $rankings[0]['ranking'] = $first_rank; 
+    $user_id = $rankings[0]['user_id'];
+    foreach ($tasks as $task) {
+                $task_id = $task['task_id'];
+                if (isset($detailed_scores[$user_id][$task_id])) {
+                    $score = $detailed_scores[$user_id][$task_id];
+                } else {
+                    $score = 0;
+                }
+                $rankings[0][$task_id] = $score;
+            }
+
+    //create all entries
+    for ($i = 1; $i < count($rankings); $i++) {
+        if ($detail == 1) {
+            $user_id = $rankings[$i]['user_id'];
+            foreach ($tasks as $task) {
+                $task_id = $task['task_id'];
+                if (isset($detailed_scores[$user_id][$task_id])) {
+                    $score = $detailed_scores[$user_id][$task_id];
+                } else {
+                    $score = 0;
+                }
+                $rankings[$i][$task_id] = $score;
+            }
+        }
+
+        if ($rankings[$i]['score'] == $rankings[$i - 1]['score']) {
+            $rankings[$i]['ranking'] = $rankings[$i - 1]['ranking'];
+        } else {
+            $rankings[$i]['ranking'] = $start + $i + 1;
+        }
+    }
+
+    log_print_r($rankings);
+    return $rankings;
+}
+
+
 ?>
Index: common/db/task.php
===================================================================
--- common/db/task.php	(revision 1009)
+++ common/db/task.php	(working copy)
@@ -65,14 +65,42 @@
     // Delete problem page
     textblock_delete($task["page_name"]);
 
+    // Delete all scores received on task
+    db_query("DELETE FROM `ia_score_user_round_task`
+              WHERE `task_id` = " . db_quote($task["id"]));
+
+    // Recompute round scores
+    $query = "SELECT `round_id` FROM `ia_round_task` 
+                WHERE `task_id` = ".db_quote($task['id']);
+    $rounds = db_fetch_all($query);
+
+    foreach ($rounds as $round) {
+        $round_id = $round['round_id'];
+
+        $query = "SELECT * FROM `ia_score_user_round` 
+                    WHERE `round_id` = ".db_quote($round);
+        $rows = db_fetch_all($query);
+        foreach($rows as $row) {
+            $user_id = $row['user_id'];
+            $round_id = $row['round_id'];
+
+            $query = "SELECT SUM(`score`) AS score FROM `ia_score_user_round_task`
+                        WHERE `user_id` = ".db_quote($user_id)." &&
+                            `round_id` = ".db_quote($round_id);
+            $score = db_query($query);
+
+            $query = "UPDATE `ia_score_user_round` 
+                    SET `score` = ".db_quote($score[0]['score'])."
+                    WHERE `user_id` = ".db_quote($user_id)." &&
+                          `round_id` = ".db_quote($round_id);
+            db_query($query);
+        }
+    }
+
     // Remove task from all rounds
     db_query("DELETE FROM `ia_round_task`
               WHERE `task_id` = " . db_quote($task["id"]));
 
-    // Delete all scores received on task
-    db_query("DELETE FROM `ia_score`
-              WHERE `task_id` = " . db_quote($task["id"]));
-
     // Delete task jobs
     $job_ids_fetched = db_fetch_all("
         SELECT `id`
Index: common/db/user.php
===================================================================
--- common/db/user.php	(revision 1009)
+++ common/db/user.php	(working copy)
@@ -217,10 +217,10 @@
         $where = '';
     }
     elseif ($solved) {
-        $where = 'AND ia_score.score = 100';
+        $where = 'AND ia_score_user_round_task.score = 100';
     }
     elseif ($failed) {
-        $where = 'AND ia_score.score < 100';
+        $where = 'AND ia_score_user_round_task.score < 100';
     }
     else {
         // This shouldn't happen
@@ -228,10 +228,10 @@
     }
 
     $query = sprintf("SELECT *
-        FROM ia_score
-        LEFT JOIN ia_task ON ia_task.id = ia_score.task_id
-        WHERE ia_score.`name` = 'score' AND ia_score.user_id = '%s'
-              AND ia_score.round_id = 'arhiva' AND NOT ia_task.id IS NULL %s
+        FROM ia_score_user_round_task
+        LEFT JOIN ia_task ON ia_task.id = ia_score_user_round_task.task_id
+        WHERE ia_score_user_round_task.user_id = '%s'
+              AND ia_score_user_round_task.round_id = 'arhiva' AND NOT ia_task.id IS NULL %s
         GROUP BY ia_task.id
         ORDER BY ia_task.`order`", $user_id, $where);
 
@@ -242,9 +242,9 @@
 function user_submitted_rounds($user_id) {
     // FIXME: Find a way to remove the hard-coded "<> 'arhiva'"
     $query = "SELECT *
-        FROM ia_score
-        LEFT JOIN ia_round ON ia_round.id = ia_score.round_id
-        WHERE ia_score.`name` = 'score' AND ia_score.user_id = '%s'
+        FROM ia_score_user_round_task
+        LEFT JOIN ia_round ON ia_round.id = ia_score_user_round_task.round_id
+        WHERE ia_score_user_round_task.user_id = '%s'
               AND NOT ia_round.id IS NULL AND ia_round.id <> 'arhiva'
         GROUP BY ia_round.id";
     $query = sprintf($query, $user_id);
Index: scripts/migrate-ia_score.php
===================================================================
--- scripts/migrate-ia_score.php	(revision 0)
+++ scripts/migrate-ia_score.php	(revision 0)
@@ -0,0 +1,90 @@
+#! /usr/bin/env php
+<?
+    require_once('utilities.php');
+    require_once(IA_ROOT_DIR . "common/db/db.php");
+    ini_set("memory_limit", "128M");
+    db_connect();
+    
+    $query = "CREATE TABLE `ia_score_user_round` (
+                user_id int,
+                round_id varchar(64) CHARACTER SET latin1 COLLATE latin1_general_ci,
+                score decimal(11, 4),
+                CONSTRAINT user_round UNIQUE (user_id, round_id)
+                )";
+    db_query($query);
+
+    $query = "CREATE TABLE `ia_score_user_round_task` (
+                user_id int,
+                round_id varchar(64) CHARACTER SET latin1 COLLATE latin1_general_ci,
+                task_id varchar(64) CHARACTER SET latin1 COLLATE latin1_general_ci,
+                score decimal(11, 4),
+                CONSTRAINT user_round_task UNIQUE (user_id, round_id, task_id)
+                )";
+    db_query($query);
+
+    $query = "CREATE TABLE `ia_rating` (
+                user_id int,
+                round_id varchar(64) CHARACTER SET latin1 COLLATE latin1_general_ci,
+                deviation decimal(11, 4),
+                rating decimal(11, 4),
+                CONSTRAINT user_round UNIQUE (user_id, round_id)
+                )";
+    db_query($query);
+
+    $query = "SELECT * FROM `ia_score`";
+    $result = db_fetch_all($query);
+
+    foreach ($result as $score) {
+        if ($score['name'] == 'deviation' || $score['name'] == 'rating') {
+            $where = '`user_id` = '. db_quote($score['user_id']) ." && `round_id` = " . db_quote($score['round_id']);
+
+            $query = "SELECT * FROM `ia_rating` WHERE ".$where;
+            $result = db_fetch_all($query);
+            if (!$result) {
+                 $query = "INSERT INTO `ia_rating`(`user_id`, `round_id`, `deviation`, `rating`)
+                            VALUES (".db_quote($score['user_id']).", ".db_quote($score['round_id']).", '0', '0')";
+                 db_query($query);
+            }
+ 
+            $query = "UPDATE `ia_rating` SET `".$score['name']."` = ".db_quote($score['score'])." WHERE ".$where;
+            db_query($query);
+        } else if ($score['name'] == 'score') {
+            $query = "INSERT INTO `ia_score_user_round_task` (`user_id`, `round_id`, `task_id`, `score`)
+                        VALUES (".implode(',',
+                            array(
+                                db_quote($score['user_id']),
+                                db_quote($score['round_id']), 
+                                db_quote($score['task_id']),
+                                db_quote($score['score']))
+                            ).")";
+            db_query($query);
+
+            $query = "SELECT `score` FROM `ia_score_user_round` WHERE
+                        `user_id` = ".db_quote($score['user_id'])." &&
+                        `round_id` = ".db_quote($score['round_id']);
+            $result = db_fetch_all($query);
+
+            if (!$result) {
+                $query = "INSERT INTO `ia_score_user_round` (`user_id`, `round_id`, `score`)
+                        VALUES (".implode(',',
+                            array(
+                                db_quote($score['user_id']),
+                                db_quote($score['round_id']),
+                                db_quote($score['score'])
+                                )
+                            ).")";
+            } else {
+                $query = "UPDATE `ia_score_user_round` SET `score` = `score` + ".$score['score']." WHERE
+                         `user_id` = ".db_quote($score['user_id'])." &&
+                        `round_id` = ".db_quote($score['round_id']);
+            }
+            db_query($query);
+        } else echo implode(' | ', $score)." dumped\n";
+    }
+
+    $query = "SELECT * FROM `ia_round`";
+    $rounds = db_fetch_all($query);
+
+//    $query = "DROP TABLE `ia_score`";
+//    db_query($query)
+?>
Index: scripts/update-ratings
===================================================================
--- scripts/update-ratings	(revision 1009)
+++ scripts/update-ratings	(working copy)
@@ -79,7 +79,7 @@
 
 // read round scores
 log_print("Reading round scores...");
-$round_rows = score_get_range("score", null, null, $round_id, "user_id", 0, $usercount);
+$round_rows = score_get_range(null, null, $round_id, "user_id", 0, $usercount);
 log_print(count($round_rows) . " users were scored in this round.");
 foreach ($round_rows as $row) {
     log_assert(isset($row['user_name']) && isset($row['score']));
Index: www/macros/macro_rankings.php
===================================================================
--- www/macros/macro_rankings.php	(revision 1009)
+++ www/macros/macro_rankings.php	(working copy)
@@ -11,17 +11,31 @@
 // Arguments:
 //     rounds   (required) a | (pipe) separated list of round names.
 //     count    (optional) how many to display at once, defaults to infinity
-//
+//     detail   (optional) print score columns for each task 
+//  
 // Examples:
 //      Rankings(rounds="preONI2007/1/a | preONI2007/2/a")
 //      Rankings(rounds="preONI2007/1/a | preONI2007/2/a" count="10")
+//      Rankings(rounds="preONI2007/1/a | preONI2007/2/a" detail ="yes") 
+//      Rankings(rounds="preONI2007/1/a | preONI2007/2/a" detail ="no") 
 function macro_rankings($args) {
     $args['param_prefix'] = 'rankings_';
     if (isset($args['count'])) {
         $args['display_entries'] = $args['count'];
     }
+
+    if (isset($args['detail'])) {
+        if ($args['detail'] == "yes") {
+            $detail = 1;
+        } else {
+            $detail = 0;
+        }
+    } else {
+        $detail = 0;
+    }
+
     $options = pager_init_options($args);
-    $options['show_count'] = true;
+    $options['show_count'] = true;    
 
     // Rounds parameters
     $roundstr = getattr($args, 'rounds', '');
@@ -30,8 +44,11 @@
     }
     $rounds = preg_split('/\s*\|\s*/', $roundstr);
 
-    // FIXME: user / task parameters.
-    $rankings = score_get_range("score", null, null, $rounds, "user_id", $options['first_entry'], $options['display_entries'], true);
+    // Get tasks for rounds
+    $tasks = round_get_tasks($rounds, null, null, null, null, null);
+    if (count($tasks) > 20) {
+        $detail = 0;
+    }
 
     $column_infos = array(
         array(
@@ -46,14 +63,30 @@
             'rowform' => create_function_cached('$row',
                                          'return format_user_normal($row["user_name"], $row["user_full"], $row["user_rating"]);'),
         ),
-        array(
+    );
+
+    if ($detail == 1) {
+        foreach ($tasks as $task) {
+            array_push($column_infos, array(
+                'title' => $task['title'],
+                'key' => $task['task_id'],
+                'rowform' => create_function_cached('$row', 'return round($row[\''.$task['task_id'].'\']);'),
+                'css_class' => 'number score'
+                )
+            );
+        }
+    }
+
+    array_push($column_infos, array(
             'title' => 'Scor',
             'key' => 'score',
             'rowform' => create_function_cached('$row', 'return round($row[\'score\']);'),
             'css_class' => 'number score'
-        ),
+        )
     );
 
+    $rankings = get_rankings($rounds, $tasks, $options['first_entry'], $options['display_entries'], $detail);
+
     if (pager_needs_total_entries($options)) {
         $options['total_entries'] = score_get_count("score", null, null, $rounds, 'user_id');
     }
Index: www/macros/macro_tasks.php
===================================================================
--- www/macros/macro_tasks.php	(revision 1009)
+++ www/macros/macro_tasks.php	(working copy)
@@ -123,7 +123,7 @@
              $user_id, ($scores ? 'score' : null),
              $filter);
     $options['total_entries'] = round_get_task_count(
-             $round_id, $user_id, ($scores ? 'score' : null), $filter);
+             $round_id, $user_id, $filter);
     $options['row_style'] = 'task_row_style';
     $options['css_class'] = 'tasks';
 
