@@ -3,6 +3,8 @@ defmodule Codebattle.GameProcess.TasksQueuesServer do
33
44 use GenServer
55
6+ @ reshuffle_timeout :timer . hours ( 7 )
7+
68 ## Client API
79
810 def start_link ( _ ) do
@@ -13,34 +15,74 @@ defmodule Codebattle.GameProcess.TasksQueuesServer do
1315 GenServer . call ( __MODULE__ , { :next_task , level } )
1416 end
1517
18+ def shuffle_task_ids do
19+ GenServer . cast ( __MODULE__ , :set_shuffled_task_ids )
20+ end
21+
22+ def reshuffle_task_ids do
23+ GenServer . cast ( __MODULE__ , :reshuffle_task_ids )
24+ end
25+
1626 ## Server callbacks
1727
1828 def init ( _ ) do
19- levels = [ "elementary" , "easy" , "medium" , "hard" ]
29+ initial_state = % {
30+ task_ids: % { } ,
31+ cursors: initial_cursors ( )
32+ }
33+
34+ Process . send_after ( self ( ) , :reshuffle_task_ids , @ reshuffle_timeout )
35+ { :ok , initial_state }
36+ end
2037
21- tasks_queues =
22- Enum . reduce ( levels , % { } , fn level , acc ->
23- Map . put ( acc , level , Codebattle.Task . get_shuffled_tasks ( level ) )
24- end )
38+ def handle_cast ( :set_shuffled_task_ids , state ) do
39+ { :noreply , % { state | task_ids: fetch_task_ids ( ) } }
40+ end
2541
26- { :ok , tasks_queues }
42+ def handle_cast ( :reshuffle_task_ids , state ) do
43+ Process . send_after ( self ( ) , :reshuffled_task_ids , @ reshuffle_timeout )
44+ { :noreply , % { state | task_ids: fetch_task_ids ( ) } }
2745 end
2846
29- def handle_call ( { :next_task , level } , _from , tasks_queues ) do
30- [ next_task , tail_tasks ] =
31- case Map . fetch! ( tasks_queues , level ) do
32- [ next_task | tail_tasks ] ->
33- [ next_task , tail_tasks ]
47+ def handle_call ( { :next_task , level } , _from , state ) do
48+ cursor = Map . get ( state . cursors , level )
49+
50+ case Map . get ( state . task_ids , level ) do
51+ [ ] ->
52+ case fetch_task_ids ( level ) do
53+ [ ] ->
54+ { :reply , nil , state }
3455
35- _ ->
36- [ next_task | tail_tasks ] = Codebattle.Task . get_shuffled_tasks ( level )
37- [ next_task , tail_tasks ]
38- end
56+ task_ids ->
57+ id = Enum . at ( task_ids , 0 )
58+ task = Codebattle.Task . get! ( id )
59+ new_cursors = Map . put ( state . cursors , level , 1 )
60+ new_task_ids = Map . put ( state . task_ids , level , task_ids )
3961
40- new_tasks_queues = Map . put ( tasks_queues , level , tail_tasks )
62+ { :reply , task , % { state | cursors: new_cursors , task_ids: new_task_ids } }
63+ end
4164
42- { :reply , next_task , new_tasks_queues }
65+ task_ids ->
66+ id = Enum . at ( task_ids , rem ( cursor , length ( task_ids ) ) )
67+ task = Codebattle.Task . get! ( id )
68+
69+ new_cursors = Map . put ( state . cursors , level , cursor + 1 )
70+ { :reply , task , % { state | cursors: new_cursors } }
71+ end
4372 end
4473
4574 ## Helpers
75+ defp initial_cursors do
76+ Enum . reduce ( Codebattle.Task . levels ( ) , % { } , fn level , acc ->
77+ Map . put ( acc , level , 1 )
78+ end )
79+ end
80+
81+ defp fetch_task_ids ( level ) , do: Codebattle.Task . get_shuffled_task_ids ( level )
82+
83+ defp fetch_task_ids do
84+ Enum . reduce ( Codebattle.Task . levels ( ) , % { } , fn level , acc ->
85+ Map . put ( acc , level , fetch_task_ids ( level ) )
86+ end )
87+ end
4688end
0 commit comments