             )
           )
         })
-      ).coerceTo('array').run con
-
+      ).run con
+
+    # Store just one solution, does not perform checkings and is meant to be used for admins.
+    storeSolution: (sid) ->
+      rdb.table("Solutions").eqJoin("exercise", rdb.table("Exercises"))
+      .filter((solution) -> solution("left")("id").eq(sid))
+      .map( (solution) ->
+        solution.merge({
+          #finalSolutionStored: rdb.table("Exercises").get(solution("right")("id")),
+          finalSolutionStored: solution("right")("dueDate").lt(rdb.now()),
+          tasks: solution("right")("tasks").map( (task) ->
+            rdb
+            .db(config.sharejs.rethinkdb.db)
+            .table(config.sharejs.tableName)
+            .get(
+              rdb.add(
+                solution("left")("group").coerceTo("string"),
+                ":",
+                solution("left")("exercise").coerceTo("string"),
+                ":",
+                task("number").coerceTo("string")
+              )
+            )
+          )
+        })
+      ).coerceTo('array')
+
+    ############################################################################
+    # UpdateOldestSolution copies the sharejs data over into the solution table
+    # for the solution that hasn't been updated the longest.
+    #
+    # In order to update this solution, the stored solution must not be final
+    # and older than minAge seconds.
+    ############################################################################
     updateOldestSolution: (minAge) ->
       minAge = minAge or 300
       if !config.sharejs?.rethinkdb?.db?
         return Promise.reject "No sharejs database defined"
+
+      rdb.do(
+        rdb.table("Solutions")
+          .orderBy({index: "lastStore"})
+          .filter(
+            rdb.row("lastStore").add(minAge).lt(rdb.now()).and(
+              rdb.row("finalSolutionStored").default(false).eq(false)
+            )
+          )
+          .eqJoin('exercise', rdb.table("Exercises")).nth(0).default(null),
+        (oldest) ->
+          rdb.branch(
+            rdb.expr(oldest).ne(null),
+            rdb.table("Solutions").get(oldest("left")("id")).update({
+              lastStore: rdb.now()
+              finalSolutionStored: oldest("right")("dueDate").lt(rdb.now())
+              tasks: oldest("right")("tasks").map( (task) ->
+                # left = Solutions
+                # right = Exercises
+                # id = group : exercise : task("number")
+                rdb.db(config.sharejs.rethinkdb.db)
+                  .table(config.sharejs.tableName)
+                  .get(
+                    rdb.add(oldest("left")("group").coerceTo("string"),":",oldest("right")("id").coerceTo("string"),":",task("number").coerceTo("string"))
+                  ).pluck("_data")
+              ).map (s) ->
+                s.merge({"solution": s("_data")}).without("_data")
+              } , {nonAtomic: true}
+            ),
+            {} # noop
+          )
+      ).run con
+
+      # old less robust and slower implementation, kept in case something was missed
+      ###
       rdb.do(
         rdb.table("Solutions")
           .orderBy({index: "lastStore"})

        })
      )).coerceTo("array").run con

    # Store just one solution, does not perform checkings and is meant to be used for admins.
    storeSolution: (sid) ->
      rdb.table("Solutions").eqJoin("exercise", rdb.table("Exercises"))
      .filter(rdb.row("left")("id").eq(sid))
      .map( (solution) ->
        solution.merge({
          finalSolutionStored: rdb.table("Exercises").get(solution("right")("id")),
          tasks: solution("right")("tasks").map( (task) ->
            rdb
            .db(config.sharejs.rethinkdb.db)


  # For pdfs
  API =
    storeTutor: (tutor) ->
      if !tutor.name? or !tutor.password? or !tutor.contingent?
        Promise.reject("You must provide a name, password and contingent field")
