Index: common/db/round.php
===================================================================
--- common/db/round.php	(revision 1126)
+++ common/db/round.php	(working copy)
@@ -110,7 +110,7 @@
         $count = 666013;
     }
     $fields = "round_task.task_id AS id, ".
-              "task.`order` AS `order`, ".
+              "round_task.`order_id` AS `order`, ".
               "task.`title` AS `title`, ".
               "task.`page_name` AS `page_name`, ".
               "task.`source` AS `source`, ".
@@ -124,7 +124,7 @@
                           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'
-                          ORDER BY task.`order` LIMIT %d, %d",
+                          ORDER BY round_task.`order_id` LIMIT %d, %d",
                           db_escape($round_id), db_escape($first), db_escape($count));
     } else {
         $filter_clause = db_get_task_filter_clause($filter, 'score');
@@ -138,7 +138,7 @@
                                 score.user_id = '%s'
                           WHERE `round_task`.`round_id` = '%s'
                             AND %s
-                          ORDER BY task.`order` LIMIT %d, %d",
+                          ORDER BY round_task.`order_id` LIMIT %d, %d",
                          db_escape($user_id),
                          db_escape($round_id), db_escape($filter_clause),
                          db_escape($first), db_escape($count));
@@ -230,10 +230,13 @@
     if (count($tasks) > 0) {
         // insert new relations
         $values = array();
+        $order_id = 0;
         foreach ($tasks as $task_id) {
-            $values[] = "('".db_escape($round_id)."', '".db_escape($task_id)."')";
+            $order_id += 1;
+            $values[] = "('".db_escape($round_id)."', '".
+                        db_escape($task_id)."', '".db_escape($order_id)."')";
         }
-        $query = "INSERT INTO ia_round_task (round_id, task_id)
+        $query = "INSERT INTO ia_round_task (round_id, task_id, order_id)
                   VALUES ". implode(', ', $values);
         db_query($query);
         foreach($tasks as $task) {
Index: common/db/round_task.php
===================================================================
--- common/db/round_task.php	(revision 0)
+++ common/db/round_task.php	(revision 0)
@@ -0,0 +1,34 @@
+<?php
+
+require_once(IA_ROOT_DIR."common/db/db.php");
+
+// Updates the `order_id` for a (round, task) pair.
+function round_task_update_order_id($round_id, $task_id, $order_id) {
+    $query = sprintf(
+        "UPDATE ia_round_task
+         SET order_id = %s
+         WHERE round_id = %s AND task_id = %s",
+         db_quote($order_id), db_quote($round_id), db_quote($task_id));
+
+    db_query($query);
+}
+
+// Preserve consecutive numbers for `order_id`
+function round_task_recompute_order($round_id) {
+    $query = "SELECT task_id, order_id FROM ia_round_task
+              WHERE round_id = " . db_quote($round_id) .
+             "ORDER BY order_id";
+    $res = db_fetch_all($query);
+
+    $order_id = 0;
+    foreach ($res as $row) {
+        $order_id += 1;
+        $query = sprintf(
+            "UPDATE ia_round_task
+             SET order_id = %s
+             WHERE round_id = %s AND task_id = %s",
+             db_quote($order_id), db_quote($round_id),
+             db_quote($row['task_id']));
+        db_query($query);
+    }
+}
Index: common/db/task.php
===================================================================
--- common/db/task.php	(revision 1126)
+++ common/db/task.php	(working copy)
@@ -3,6 +3,7 @@
 require_once(IA_ROOT_DIR . "common/db/db.php");
 require_once(IA_ROOT_DIR . "common/task.php");
 require_once(IA_ROOT_DIR . "common/db/parameter.php");
+require_once(IA_ROOT_DIR . "common/db/round_task.php");
 
 // Add $task to cache if not null, return $task.
 function _task_cache_add($task) {
@@ -54,6 +55,22 @@
     return $res;
 }
 
+// Deletes a task from ia_round_task
+function task_delete_from_rounds($task_id) {
+    // Get all rounds for the task
+    $query = "SELECT DISTINCT round_id FROM ia_round_task
+              WHERE task_id = " . db_quote($task_id);
+    $res = db_fetch_all($query);
+
+    // Delete task
+    db_query("DELETE FROM ia_round_task WHERE task_id = ".db_quote($task_id));
+
+    // Repair rounds order
+    foreach ($res as $row) {
+        round_task_recompute_order($row['round_id']);
+    }
+}
+
 // Delete a task, including scores, jobs and page
 // WARNING: This is irreversible.
 function task_delete($task) {
@@ -79,8 +96,7 @@
     }
 
     // Remove task from all rounds
-    db_query("DELETE FROM `ia_round_task`
-              WHERE `task_id` = " . db_quote($task["id"]));
+    task_delete_from_rounds($task['id']);
 
     // Delete task jobs
     $job_ids_fetched = db_fetch_all("
Index: scripts/add-round-task-order
===================================================================
--- scripts/add-round-task-order	(revision 0)
+++ scripts/add-round-task-order	(revision 0)
@@ -0,0 +1,46 @@
+#! /usr/bin/env php
+<?php
+
+require_once(dirname($argv[0])."/utilities.php");
+require_once(dirname($argv[0])."/../common/task.php");
+
+db_connect();
+
+// Add new column in ia_round_task
+$query = "ALTER TABLE ia_round_task ADD COLUMN order_id INT";
+db_query($query);
+
+// Get all the round ids
+$query = "SELECT DISTINCT id FROM ia_round";
+$res = db_fetch_all($query);
+
+// Complete order_id column for each round
+foreach ($res as $row) {
+    $round_id = $row['id'];
+
+    // Get all tasks for a round
+    $query = sprintf(
+        "SELECT ia_round_task.task_id, ia_task.order
+         FROM ia_round_task
+         LEFT JOIN ia_task ON ia_round_task.task_id = ia_task.id
+         WHERE (round_id = %s)
+         ORDER BY ia_task.order",
+         db_quote($round_id));
+    $res = db_fetch_all($query);
+
+    $count = 1;
+    foreach ($res as $row) {
+        $task_id = $row['task_id'];
+
+        $query = sprintf(
+            "UPDATE ia_round_task
+             SET order_id = %s
+             WHERE (round_id = %s AND task_id = %s)",
+             db_quote($count), db_quote($round_id), db_quote($task_id));
+        db_query($query);
+
+        $count += 1;
+    }
+}
+
+?>

Property changes on: scripts/add-round-task-order
___________________________________________________________________
Added: svn:executable
   + *

Index: www/controllers/round.php
===================================================================
--- www/controllers/round.php	(revision 1126)
+++ www/controllers/round.php	(working copy)
@@ -2,6 +2,7 @@
 
 require_once(IA_ROOT_DIR."common/db/db.php");
 require_once(IA_ROOT_DIR."common/db/round.php");
+require_once(IA_ROOT_DIR."common/db/round_task.php");
 require_once(IA_ROOT_DIR."common/db/task.php");
 require_once(IA_ROOT_DIR."common/round.php");
 require_once(IA_ROOT_DIR."common/tags.php");
@@ -202,6 +203,84 @@
     execute_view_die("views/round_edit.php", $view);
 }
 
+function controller_round_task_order($round_id) {
+    // Validate round_id
+    if (!is_round_id($round_id)) {
+        flash_error('Identificatorul rundei este invalid');
+        redirect(url_home());
+    }
+
+    // Get round
+    $round = round_get($round_id);
+    if (!$round) {
+        flash_error("Runda nu exista");
+        redirect(url_home());
+    }
+
+    // Security check
+    identity_require('round-edit', $round);
+
+    if (request_is_post()) {
+        // Request a list of ids with the new task order
+        $task_order_strings = explode(';', request('task_order', ''));
+
+        // Evil users, abort post.
+        foreach ($task_order_strings as $order_string) {
+            if (!is_numeric($order_string)) {
+                redirect(url_round_edit_task_order($round_id));
+            }
+        }
+
+        // Parse the values
+        $task_order = array_map("intval", $task_order_strings);
+
+        // Increment by 1
+        foreach ($task_order as &$order_id) {
+            $order_id += 1;
+        }
+        unset($order_id);
+
+        // Get the tasks
+        $first = min($task_order) - 1;
+        $count = count($task_order);
+        $tasks = round_get_tasks($round_id, $first, $count);
+
+        $task_ids = array();
+        foreach ($tasks as $task) {
+            $task_ids[$task['order']] = $task['id'];
+        }
+
+        // Check each order_id has an associated task_id
+        // Another evil users check
+        foreach ($task_order as $order_id) {
+            if (!getattr($task_ids, $order_id)) {
+                redirect(url_round_edit_task_order($round_id));
+            }
+        }
+
+        $current_id = $first + 1;
+        foreach ($task_order as $order_id) {
+            $task_id = $task_ids[$order_id];
+
+            if ($current_id != $order_id) {
+                round_task_update_order_id($round_id, $task_id, $current_id);
+                task_update_forum_topic($task_id);
+            }
+
+            $current_id += 1;
+        }
+    }
+
+    // Create view.
+    $view = array();
+    $view['title'] = "Editare ordine probleme $round_id";
+    $view['page_name'] = url_round_edit_task_order($round_id);
+    $view['round_id'] = $round_id;
+    $view['round'] = $round;
+
+    execute_view_die("views/round_task_order.php", $view);
+}
+
 // Creates a round. Minimalist
 function controller_round_create()
 {
Index: www/index.php
===================================================================
--- www/index.php	(revision 1126)
+++ www/index.php	(working copy)
@@ -129,22 +129,35 @@
     controller_round_create();
 }
 
-// Round detail editor and deleter
-else if ($urlstart == 'admin' && getattr($pagepath, 1) == 'runda') {
-    $obj_id = implode("/", array_slice($pagepath, 2));
+// Round edit parameters
+else if ($urlstart == 'admin' && getattr($pagepath, 1) == 'runda' &&
+         $action == 'edit-params') {
     require_once(IA_ROOT_DIR.'www/controllers/round.php');
+    $round_id = implode("/", array_slice($pagepath, 2));
+    controller_round_details($round_id);
+}
+
+// Round edit task order
+else if ($urlstart == 'admin' && getattr($pagepath, 1) == 'runda' &&
+         $action == 'edit-task-order') {
+    require_once(IA_ROOT_DIR.'www/controllers/round.php');
+    $round_id = implode("/", array_slice($pagepath, 2));
+    controller_round_task_order($round_id);
+}
+
+// Round delete
+else if ($urlstart == 'admin' && getattr($pagepath, 1) == 'runda' &&
+         $action == 'sterge-runda') {
+    require_once(IA_ROOT_DIR.'www/controllers/round.php');
     require_once(IA_ROOT_DIR.'www/controllers/textblock.php');
-    if ($action == 'sterge-runda') {
-        if (request('delete-pages')) {
-            $v = request('textblocks');
-            controller_textblock_delete_many($v, url_round_delete($obj_id));
-        } elseif (request('delete-round')) {
-            controller_round_delete($obj_id);
-        } else {
-            controller_round_delete_view($obj_id);
-        }
+    $round_id = implode("/", array_slice($pagepath, 2));
+    if (request('delete-pages')) {
+        $v = request('textblocks');
+        controller_textblock_delete_many($v, url_round_delete($round_id));
+    } elseif (request('delete-round')) {
+        controller_round_delete($round_id);
     } else {
-        controller_round_details($obj_id);
+        controller_round_delete_view($round_id);
     }
 }
 
Index: www/static/css/screen.css
===================================================================
--- www/static/css/screen.css	(revision 1126)
+++ www/static/css/screen.css	(working copy)
@@ -1043,6 +1043,9 @@
 /* Basic table css */
 table {
     border-collapse: collapse;
+    line-height: 2em;
+    margin: 0.5em;
+    width: 99%;
 }
 
 table td, table th {
Index: www/url.php
===================================================================
--- www/url.php	(revision 1126)
+++ www/url.php	(working copy)
@@ -307,9 +307,16 @@
 
 function url_round_edit_params($round_id) {
     log_assert(is_round_id($round_id));
-    return url_complex("admin/runda/" . $round_id);
+    return url_complex("admin/runda/" . $round_id,
+                       array('action' => 'edit-params'));
 }
 
+function url_round_edit_task_order($round_id) {
+    log_assert(is_round_id($round_id));
+    return url_complex("admin/runda/" . $round_id,
+                       array('action' => 'edit-task-order'));
+}
+
 function url_round_create() {
     return url_complex("admin/runda-noua");
 }
Index: www/views/round_edit_header.php
===================================================================
--- www/views/round_edit_header.php	(revision 1126)
+++ www/views/round_edit_header.php	(working copy)
@@ -9,15 +9,18 @@
 
     $tab_names = array(
         'edit' => 'Pagină',
-        'round-edit-params' => 'Parametri');
+        'round-edit-params' => 'Parametri',
+        'round-edit-task-order' => 'Ordine probleme');
 
     $tab_urls = array(
         'edit' => url_round_edit($round_id),
-        'round-edit-params' => url_round_edit_params($round_id));
+        'round-edit-params' => url_round_edit_params($round_id),
+        'round-edit-task-order' => url_round_edit_task_order($round_id));
 
     $permissions = array(
         'edit' => 'round-edit',
-        'round-edit-params' => 'round-edit');
+        'round-edit-params' => 'round-edit',
+        'round-edit-task-order' => 'round-edit');
 
     $round = round_get($round_id);
 
Index: www/views/round_task_order.php
===================================================================
--- www/views/round_task_order.php	(revision 0)
+++ www/views/round_task_order.php	(revision 0)
@@ -0,0 +1,70 @@
+<?php
+require_once(IA_ROOT_DIR."common/round.php");
+require_once(IA_ROOT_DIR."www/format/form.php");
+require_once(IA_ROOT_DIR."www/views/round_edit_header.php");
+require_once(IA_ROOT_DIR."www/macros/macro_tasks.php");
+include("views/header.php");
+
+echo round_edit_tabs($view['round_id'], 'round-edit-task-order');
+?>
+
+<script type="text/javascript">
+    function do_post() {
+        var formElem = document.task_order_form;
+
+        var tables = formElem.getElementsByTagName("table");
+        if (tables.length == 0) {
+            formElem.submit();
+        }
+        var table = tables[0];
+
+        var tbodies = table.getElementsByTagName("tbody");
+        if (tbodies.length == 0) {
+            formElem.submit();
+        }
+        var tbody = tbodies[0];
+
+        var rows = tbody.getElementsByTagName("tr");
+        if (rows.length == 0) {
+            formElem.submit();
+        }
+
+        var order_id_list = "";
+        for (var i = 0; i < rows.length; ++i) {
+            var td = rows[i].childNodes[0];
+            order_id_list += (i > 0 ? ";" : "") + td.innerHTML;
+        }
+
+        formElem.task_order.value = order_id_list;
+        formElem.submit();
+    }
+</script>
+
+<h1>Editare ordine probleme <?= format_link(url_textblock($round['page_name']), $round['title']) ?></h1>
+
+<form name="task_order_form" action="<?= html_escape(url_round_edit_task_order($view['round_id']))?>" method="post">
+
+<input type="hidden" name="task_order">
+
+<?php
+$args = array(
+    'round_id' => $view['round_id'],
+    'drag_and_drop' => true,
+    'show_numbers' => true,
+    'show_ratings' => true,
+);
+echo macro_tasks($args);
+?>
+
+<div class="submit">
+    <ul class="form">
+        <li id="field_submit">
+            <input type="button" value="Salveaza modificari"
+             onclick="do_post()" class="button important" />
+        </li>
+    </ul>
+</div>
+
+</form>
+
+<?php include('footer.php'); ?>
