Skip to content

Commit 9387f29

Browse files
committed
fix(teacher_tab): Fix Open/Close handling w.r.t. Assignments
* Refactor and fix "Open"/"Closed"/… display code, Put function `is_open_or_assigned_globally` in `Learnocaml_data`, returning ( GloballyOpen | GloballyOpenOrAssigned | GloballyClosedOrAssigned | GloballyClosed ) * Make invariants explicit in OCaml comments Close ocaml-sf#534 Close ocaml-sf#558
1 parent 48583ba commit 9387f29

File tree

4 files changed

+96
-22
lines changed

4 files changed

+96
-22
lines changed

src/app/learnocaml_teacher_tab.ml

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -299,13 +299,12 @@ let rec teacher_tab token _select _params () =
299299
H.td [stars_div meta.Exercise.Meta.stars];
300300
H.td [
301301
let cls, text =
302-
match Token.Map.is_empty ES.(st.assignments.token_map),
303-
ES.(st.assignments.default) with
304-
| true, ES.Open -> "exo_open", [%i"Open"]
305-
| true, ES.Closed -> "exo_closed", [%i"Closed"]
306-
| _, (ES.Assigned _ | ES.Closed) ->
307-
"exo_assigned", [%i"Assigned"]
308-
| false, ES.Open -> "exo_assigned", [%i"Open/Assg"]
302+
let open ES in
303+
match is_open_or_assigned_globally st.assignments with
304+
| GloballyOpen -> "exo_open", [%i"Open"]
305+
| GloballyOpenOrAssigned -> "exo_assigned", [%i"Open/Assigned"]
306+
| GloballyClosedOrAssigned -> "exo_assigned", [%i"Assigned"]
307+
| GloballyClosed -> "exo_closed", [%i"Closed"]
309308
in
310309
H.span ~a:[H.a_class [cls]] [H.txt text]
311310
];
@@ -856,17 +855,12 @@ let rec teacher_tab token _select _params () =
856855
let ids = htbl_keys selected_exercises in
857856
let fstat =
858857
if List.exists (fun id ->
859-
let st = get_status id in
860-
ES.(default_assignment st.assignments = Open))
858+
let st = get_status id in
859+
let open_assg = ES.is_open_or_assigned_globally st.ES.assignments in
860+
open_assg = ES.GloballyOpen || open_assg = ES.GloballyOpenOrAssigned)
861861
ids
862-
then ES.(fun assg ->
863-
match default_assignment assg with
864-
| Open -> set_default_assignment assg Closed
865-
| _ -> assg)
866-
else ES.(fun assg ->
867-
match default_assignment assg with
868-
| Closed -> set_default_assignment assg Open
869-
| _ -> assg)
862+
then ES.set_close_or_assigned_globally
863+
else ES.set_open_or_assigned_globally
870864
in
871865
!exercise_status_change (htbl_keys selected_exercises) fstat;
872866
true)
@@ -1330,7 +1324,11 @@ let rec teacher_tab token _select _params () =
13301324
in
13311325
let open_exercises =
13321326
SMap.fold (fun ex st acc ->
1333-
if ES.(st.assignments.default = Open) then ex::acc else acc)
1327+
let open ES in
1328+
let global_st = is_open_or_assigned_globally st.assignments in
1329+
if global_st = GloballyOpen
1330+
|| global_st = GloballyOpenOrAssigned
1331+
then ex :: acc else acc)
13341332
!status_map []
13351333
|> List.rev
13361334
in

src/state/learnocaml_data.ml

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,54 @@ module Exercise = struct
513513
| Some a -> a
514514
| None -> a.default
515515

516+
type global_status =
517+
| GloballyOpen (** "Open" *)
518+
| GloballyClosed (** "Closed" *)
519+
| GloballyOpenOrAssigned (** "Open/Assigned" *)
520+
| GloballyClosedOrAssigned (** "Assigned" *)
521+
522+
let is_open_or_assigned_globally a =
523+
match a.default with
524+
| Open ->
525+
if Token.Map.exists (fun _tok -> function Assigned _ -> true | _ -> false) a.token_map
526+
then GloballyOpenOrAssigned
527+
else GloballyOpen
528+
| Closed ->
529+
if Token.Map.exists (fun _tok -> function Assigned _ -> true | _ -> false) a.token_map
530+
then GloballyClosedOrAssigned
531+
else GloballyClosed
532+
| Assigned _ ->
533+
if Token.Map.exists (fun _tok -> (=) Open) a.token_map
534+
then GloballyOpenOrAssigned
535+
else GloballyClosedOrAssigned
536+
537+
let make_assignments token_map default =
538+
{ token_map; default }
539+
540+
let set_close_or_assigned_globally a =
541+
match is_open_or_assigned_globally a with
542+
| GloballyOpen -> make_assignments Token.Map.empty Closed
543+
| GloballyOpenOrAssigned ->
544+
make_assignments
545+
(Token.Map.map (function Open -> Closed | st -> st) a.token_map)
546+
(match a.default with Open -> Closed | a -> a)
547+
(* otherwise, maybe: forget the map and re-add all tokens ? *)
548+
| GloballyClosedOrAssigned -> a
549+
| GloballyClosed -> a
550+
551+
let set_open_or_assigned_globally a =
552+
match is_open_or_assigned_globally a with
553+
| GloballyClosed -> make_assignments Token.Map.empty Open
554+
| GloballyClosedOrAssigned ->
555+
make_assignments
556+
(Token.Map.map (function Closed -> Open | st -> st) a.token_map)
557+
(match a.default with Closed -> Open | a -> a)
558+
(* otherwise, maybe: forget the map and re-add all tokens ? *)
559+
| GloballyOpenOrAssigned -> a
560+
| GloballyOpen -> a
561+
562+
(* Note/Erik: we may also want to implement set_assigned_globally *)
563+
516564
let is_open_assignment token a =
517565
match get_status token a with
518566
| Assigned a ->
@@ -640,9 +688,6 @@ module Exercise = struct
640688
skills_focus;
641689
assignments = { default; token_map } }
642690

643-
let make_assignments token_map default =
644-
{ token_map; default }
645-
646691
let enc =
647692
let status_enc =
648693
J.union [

src/state/learnocaml_data.mli

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,37 @@ module Exercise: sig
206206
val get_status:
207207
Token.t -> assignments -> status
208208

209+
(** Global assignment status, w.r.t. all students as a whole
210+
211+
Invariants: forall exo_status : t,
212+
213+
1.(REQUIRED):
214+
(exo_status.assignments.default <> Open && Token.Map.for_all (fun _ st -> st <> Open))
215+
|| (exo_status.assignments.default <> Closed && Token.Map.for_all (fun _ st -> st <> Closed))
216+
217+
2.(IfNormalized):
218+
is_open_assigned_globally exo_status.assignments \in \{GloballyOpen, GloballyClosed\} ->
219+
exo_status.assignments.token_map = Token.Map.empty *)
220+
type global_status =
221+
| GloballyOpen (** "Open" *)
222+
| GloballyClosed (** "Closed" *)
223+
| GloballyOpenOrAssigned (** "Open/Assigned" *)
224+
| GloballyClosedOrAssigned (** "Assigned" *)
225+
226+
val is_open_or_assigned_globally: assignments -> global_status
227+
228+
(** Close assignments status globally (for all unassigned students), namely:
229+
- GloballyOpen -> GloballyClosed
230+
- GloballyOpenOrAssigned -> GloballyClosedOrAssigned
231+
- other -> no-op *)
232+
val set_close_or_assigned_globally: assignments -> assignments
233+
234+
(** Open assignments status globally (for all unassigned students), namely:
235+
- GloballyClosed -> GloballyOpen
236+
- GloballyClosedOrAssigned -> GloballyOpenOrAssigned
237+
- other -> no-op *)
238+
val set_open_or_assigned_globally: assignments -> assignments
239+
209240
val is_open_assignment:
210241
Token.t -> assignments -> [> `Open | `Closed | `Deadline of float]
211242

translations/fr.po

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ msgid "Assigned"
633633
msgstr "Devoir"
634634

635635
#: File "src/app/learnocaml_teacher_tab.ml", line 308, characters 57-68
636-
msgid "Open/Assg"
636+
msgid "Open/Assigned"
637637
msgstr "Ouvert/Devoir"
638638

639639
#: File "src/app/learnocaml_teacher_tab.ml", line 368, characters 49-61 391,

0 commit comments

Comments
 (0)