From 8a0582726e917c8dc551d50526f3a8fb7843d762 Mon Sep 17 00:00:00 2001 From: facundoy Date: Sun, 22 Sep 2024 15:04:23 -0400 Subject: [PATCH 01/12] Added relevant update actions --- src/haz3lweb/Log.re | 2 ++ src/haz3lweb/Update.re | 4 +++- src/haz3lweb/UpdateAction.re | 10 +++++++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/haz3lweb/Log.re b/src/haz3lweb/Log.re index eb9b8a7100..ca8f04a3ec 100644 --- a/src/haz3lweb/Log.re +++ b/src/haz3lweb/Log.re @@ -25,6 +25,8 @@ let is_action_logged: UpdateAction.t => bool = | Redo | UpdateResult(_) | UpdatePrompt(_) + | UpdatePointDist(_) + | UpdateTestReq(_) | ToggleStepper(_) | StepperAction(_, StepForward(_) | StepBackward) | UpdateExplainThisModel(_) => true; diff --git a/src/haz3lweb/Update.re b/src/haz3lweb/Update.re index 4216806eea..b3b123d9c4 100644 --- a/src/haz3lweb/Update.re +++ b/src/haz3lweb/Update.re @@ -568,7 +568,9 @@ let apply = Model.save_and_return({ ...model, editors: Editors.update_exercise_prompt(model.editors, new_prompt), - }) + }); + | UpdatePointDist(_) => Ok(model) + | UpdateTestReq(_) => Ok(model) }; m |> Result.map(~f=update_cached_data(~schedule_action, update)); }; diff --git a/src/haz3lweb/UpdateAction.re b/src/haz3lweb/UpdateAction.re index bb5c131c90..e27814f6c9 100644 --- a/src/haz3lweb/UpdateAction.re +++ b/src/haz3lweb/UpdateAction.re @@ -89,7 +89,9 @@ type t = | ToggleStepper(ModelResults.Key.t) | StepperAction(ModelResults.Key.t, stepper_action) | UpdateResult(ModelResults.t) - | UpdatePrompt(string); + | UpdatePrompt(string) + | UpdatePointDist(int) + | UpdateTestReq(int); module Failure = { [@deriving (show({with_path: false}), sexp, yojson)] @@ -143,6 +145,8 @@ let is_edit: t => bool = | FinishImportScratchpad(_) | ResetCurrentEditor | UpdatePrompt(_) + | UpdatePointDist(_) + | UpdateTestReq(_) | Reset | TAB => true | UpdateResult(_) @@ -195,6 +199,8 @@ let reevaluate_post_update: t => bool = | Export(_) | UpdateResult(_) | UpdatePrompt(_) + | UpdatePointDist(_) + | UpdateTestReq(_) | SwitchEditor(_) | DebugConsole(_) | Benchmark(_) => false @@ -238,6 +244,8 @@ let should_scroll_to_caret = | UpdateResult(_) | ToggleStepper(_) | UpdatePrompt(_) + | UpdatePointDist(_) + | UpdateTestReq(_) | StepperAction(_, StepBackward | StepForward(_)) => false | FinishImportScratchpad(_) | FinishImportAll(_) From bb114757546fa8a705d7ee4642bfae8b31cc429e Mon Sep 17 00:00:00 2001 From: facundoy Date: Sun, 22 Sep 2024 16:26:04 -0400 Subject: [PATCH 02/12] Added functionality to toggle between editing and finalized states --- src/haz3lschool/Exercise.re | 75 ++++++++++++++++++++++++++++++++++++ src/haz3lweb/Editors.re | 36 +++++++++++++++++ src/haz3lweb/Init.ml | 2 + src/haz3lweb/Log.re | 2 +- src/haz3lweb/Settings.re | 2 + src/haz3lweb/Update.re | 37 ++++++++++++++++-- src/haz3lweb/UpdateAction.re | 18 ++++++--- src/haz3lweb/view/Page.re | 7 +++- 8 files changed, 168 insertions(+), 11 deletions(-) diff --git a/src/haz3lschool/Exercise.re b/src/haz3lschool/Exercise.re index 9875928566..2398fd2718 100644 --- a/src/haz3lschool/Exercise.re +++ b/src/haz3lschool/Exercise.re @@ -493,6 +493,81 @@ module F = (ExerciseEnv: ExerciseEnv) => { }, }; + let set_editing_test_num = ({eds, _} as state: state, editing: bool) => { + ...state, + eds: { + ...eds, + prelude: Editor.set_read_only(eds.prelude, editing), + correct_impl: Editor.set_read_only(eds.correct_impl, editing), + your_tests: { + let tests = Editor.set_read_only(eds.your_tests.tests, editing); + { + tests, + required: eds.your_tests.required, + provided: eds.your_tests.provided, + }; + }, + your_impl: Editor.set_read_only(eds.your_impl, editing), + }, + }; + + let update_test_num = ({eds, _} as state: state, new_test_num: int) => { + ...state, + eds: { + ...eds, + your_tests: { + ...eds.your_tests, + required: new_test_num, + }, + }, + }; + + let set_editing_point_dist = ({eds, _} as state: state, editing: bool) => { + ...state, + eds: { + ...eds, + prelude: Editor.set_read_only(eds.prelude, editing), + correct_impl: Editor.set_read_only(eds.correct_impl, editing), + your_tests: { + let tests = Editor.set_read_only(eds.your_tests.tests, editing); + { + tests, + required: eds.your_tests.required, + provided: eds.your_tests.provided, + }; + }, + your_impl: Editor.set_read_only(eds.your_impl, editing), + }, + }; + + let update_point_dist = + ({eds, _} as state: state, new_point_dist: int, dist: string) => { + let updated_point_distribution = + switch (dist) { + | "test_validation" => { + ...eds.point_distribution, + test_validation: new_point_dist, + } + | "mutation_testing" => { + ...eds.point_distribution, + mutation_testing: new_point_dist, + } + | "impl_grading" => { + ...eds.point_distribution, + impl_grading: new_point_dist, + } + | _ => eds.point_distribution + }; + + { + ...state, + eds: { + ...eds, + point_distribution: updated_point_distribution, + }, + }; + }; + let visible_in = (pos, ~instructor_mode) => { switch (pos) { | Prelude => instructor_mode diff --git a/src/haz3lweb/Editors.re b/src/haz3lweb/Editors.re index 401d945742..589aea305e 100644 --- a/src/haz3lweb/Editors.re +++ b/src/haz3lweb/Editors.re @@ -137,6 +137,42 @@ let update_exercise_prompt = (editors: t, new_prompt: string): t => ) }; +let set_editing_test_num = (editors: t, editing: bool): t => + switch (editors) { + | Scratch(_) + | Documentation(_) => editors + | Exercises(n, specs, exercise) => + Exercises(n, specs, Exercise.set_editing_test_num(exercise, editing)) + }; + +let update_test_num = (editors: t, new_test_num: int): t => + switch (editors) { + | Scratch(_) + | Documentation(_) => editors + | Exercises(n, specs, exercise) => + Exercises(n, specs, Exercise.update_test_num(exercise, new_test_num)) + }; + +let set_editing_point_dist = (editors: t, editing: bool): t => + switch (editors) { + | Scratch(_) + | Documentation(_) => editors + | Exercises(n, specs, exercise) => + Exercises(n, specs, Exercise.set_editing_point_dist(exercise, editing)) + }; + +let update_point_dist = (editors: t, new_point_dist: int, dist: string): t => + switch (editors) { + | Scratch(_) + | Documentation(_) => editors + | Exercises(n, specs, exercise) => + Exercises( + n, + specs, + Exercise.update_point_dist(exercise, new_point_dist, dist), + ) + }; + let reset_nth_slide = (~settings: CoreSettings.t, n, slides): list(Editor.t) => { let (_, init_editors, _) = Init.startup.scratch; let data = List.nth(init_editors, n); diff --git a/src/haz3lweb/Init.ml b/src/haz3lweb/Init.ml index ffc7e1d294..ee90bc0429 100644 --- a/src/haz3lweb/Init.ml +++ b/src/haz3lweb/Init.ml @@ -27,6 +27,8 @@ let startup : PersistentData.t = context_inspector = false; instructor_mode = true; editing_prompt = false; + editing_point_dist = false; + editing_test_num = false; benchmark = false; explainThis = { show = true; show_feedback = false; highlight = NoHighlight }; diff --git a/src/haz3lweb/Log.re b/src/haz3lweb/Log.re index ca8f04a3ec..619bc94317 100644 --- a/src/haz3lweb/Log.re +++ b/src/haz3lweb/Log.re @@ -26,7 +26,7 @@ let is_action_logged: UpdateAction.t => bool = | UpdateResult(_) | UpdatePrompt(_) | UpdatePointDist(_) - | UpdateTestReq(_) + | UpdateTestNum(_) | ToggleStepper(_) | StepperAction(_, StepForward(_) | StepBackward) | UpdateExplainThisModel(_) => true; diff --git a/src/haz3lweb/Settings.re b/src/haz3lweb/Settings.re index 0e9af6bbc5..a17a44208f 100644 --- a/src/haz3lweb/Settings.re +++ b/src/haz3lweb/Settings.re @@ -23,6 +23,8 @@ type t = { context_inspector: bool, instructor_mode: bool, editing_prompt: bool, + editing_point_dist: bool, + editing_test_num: bool, benchmark: bool, explainThis: ExplainThisModel.Settings.t, mode, diff --git a/src/haz3lweb/Update.re b/src/haz3lweb/Update.re index b3b123d9c4..7baae1e2a4 100644 --- a/src/haz3lweb/Update.re +++ b/src/haz3lweb/Update.re @@ -176,6 +176,8 @@ let update_settings = ...settings, instructor_mode: !settings.instructor_mode, editing_prompt: false, + editing_test_num: false, + editing_point_dist: false, }, }; | EditingPrompt => @@ -188,6 +190,26 @@ let update_settings = editing_prompt: editing, }, }; + | EditingTestNum => + let editing = !settings.editing_test_num; + { + ...model, + editors: Editors.set_editing_test_num(model.editors, editing), + settings: { + ...settings, + editing_test_num: editing, + }, + }; + | EditingPointDist => + let editing = !settings.editing_point_dist; + { + ...model, + editors: Editors.set_editing_test_num(model.editors, editing), + settings: { + ...settings, + editing_point_dist: editing, + }, + }; | Mode(mode) => { ...model, settings: { @@ -568,9 +590,18 @@ let apply = Model.save_and_return({ ...model, editors: Editors.update_exercise_prompt(model.editors, new_prompt), - }); - | UpdatePointDist(_) => Ok(model) - | UpdateTestReq(_) => Ok(model) + }) + | UpdatePointDist(new_point_dist, dist) => + Model.save_and_return({ + ...model, + editors: + Editors.update_point_dist(model.editors, new_point_dist, dist), + }) + | UpdateTestNum(new_test_num) => + Model.save_and_return({ + ...model, + editors: Editors.update_test_num(model.editors, new_test_num), + }) }; m |> Result.map(~f=update_cached_data(~schedule_action, update)); }; diff --git a/src/haz3lweb/UpdateAction.re b/src/haz3lweb/UpdateAction.re index e27814f6c9..4bed091537 100644 --- a/src/haz3lweb/UpdateAction.re +++ b/src/haz3lweb/UpdateAction.re @@ -25,6 +25,8 @@ type settings_action = | ContextInspector | InstructorMode | EditingPrompt + | EditingPointDist + | EditingTestNum | Evaluation(evaluation_settings_action) | ExplainThis(ExplainThisModel.Settings.action) | Mode(Settings.mode); @@ -90,8 +92,8 @@ type t = | StepperAction(ModelResults.Key.t, stepper_action) | UpdateResult(ModelResults.t) | UpdatePrompt(string) - | UpdatePointDist(int) - | UpdateTestReq(int); + | UpdatePointDist(int, string) + | UpdateTestNum(int); module Failure = { [@deriving (show({with_path: false}), sexp, yojson)] @@ -126,6 +128,8 @@ let is_edit: t => bool = | ContextInspector | InstructorMode | EditingPrompt + | EditingPointDist + | EditingTestNum | Evaluation(_) => false } | SetMeta(meta_action) => @@ -146,7 +150,7 @@ let is_edit: t => bool = | ResetCurrentEditor | UpdatePrompt(_) | UpdatePointDist(_) - | UpdateTestReq(_) + | UpdateTestNum(_) | Reset | TAB => true | UpdateResult(_) @@ -183,6 +187,8 @@ let reevaluate_post_update: t => bool = | Dynamics | InstructorMode | EditingPrompt + | EditingPointDist + | EditingTestNum | Mode(_) => true } | SetMeta(meta_action) => @@ -200,7 +206,7 @@ let reevaluate_post_update: t => bool = | UpdateResult(_) | UpdatePrompt(_) | UpdatePointDist(_) - | UpdateTestReq(_) + | UpdateTestNum(_) | SwitchEditor(_) | DebugConsole(_) | Benchmark(_) => false @@ -232,6 +238,8 @@ let should_scroll_to_caret = | ContextInspector | InstructorMode | EditingPrompt + | EditingPointDist + | EditingTestNum | Evaluation(_) => false } | SetMeta(meta_action) => @@ -245,7 +253,7 @@ let should_scroll_to_caret = | ToggleStepper(_) | UpdatePrompt(_) | UpdatePointDist(_) - | UpdateTestReq(_) + | UpdateTestNum(_) | StepperAction(_, StepBackward | StepForward(_)) => false | FinishImportScratchpad(_) | FinishImportAll(_) diff --git a/src/haz3lweb/view/Page.re b/src/haz3lweb/view/Page.re index 15d872ba2c..68eae653e8 100644 --- a/src/haz3lweb/view/Page.re +++ b/src/haz3lweb/view/Page.re @@ -24,9 +24,12 @@ let key_handler = switch (Keyboard.handle_key_event(key)) { | None => Ignore | Some(action) => - get_settings(model).editing_prompt + let settings = get_settings(model); + settings.editing_prompt + || settings.editing_test_num + || settings.editing_point_dist ? Many([inject(action)]) - : Many([Prevent_default, Stop_propagation, inject(action)]) + : Many([Prevent_default, Stop_propagation, inject(action)]); } }; }; From c44374d5d8fc6967107f6558fb2675728a3494bc Mon Sep 17 00:00:00 2001 From: facundoy Date: Sun, 22 Sep 2024 17:16:13 -0400 Subject: [PATCH 03/12] Adding code that got deleted during the merge --- src/haz3lweb/Main.re | 1 + 1 file changed, 1 insertion(+) diff --git a/src/haz3lweb/Main.re b/src/haz3lweb/Main.re index 194e46f820..0b90e99d7f 100644 --- a/src/haz3lweb/Main.re +++ b/src/haz3lweb/Main.re @@ -83,6 +83,7 @@ module App = { schedule_action(Haz3lweb.Update.SetMeta(FontMetrics(fm))) ); + NinjaKeys.initialize(NinjaKeys.options(schedule_action)); JsUtil.focus_clipboard_shim(); /* initialize state. */ From 49d91b41a04af30dd0226f615d3d340a6173f254 Mon Sep 17 00:00:00 2001 From: facundoy Date: Sun, 22 Sep 2024 17:23:41 -0400 Subject: [PATCH 04/12] Solved bug where editing mode persisted between exercises --- src/haz3lweb/Update.re | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/haz3lweb/Update.re b/src/haz3lweb/Update.re index 7baae1e2a4..0c252fe39f 100644 --- a/src/haz3lweb/Update.re +++ b/src/haz3lweb/Update.re @@ -497,13 +497,15 @@ let apply = | SwitchScratchSlide(n) => let instructor_mode = model.settings.instructor_mode; let editors = Editors.set_editing_prompt(model.editors, false); - let settings = {...model.settings, editing_prompt: false}; + let settings = {...model.settings, editing_prompt: false, editing_point_dist: false, editing_test_num: false}; switch ( switch_scratch_slide( editors, ~settings=model.settings.core, ~instructor_mode, ~editing_prompt=false, + ~editing_point_dist=false, + ~editing_test_num=false, n, ) ) { From 5514fc575cf448e85f6455e4315e79e27224bf71 Mon Sep 17 00:00:00 2001 From: facundoy Date: Sat, 28 Sep 2024 17:53:02 -0400 Subject: [PATCH 05/12] Implemented the storing/exporting of new changes --- src/haz3lschool/Exercise.re | 24 +++++++++++++++++++++--- src/haz3lschool/Gradescope.re | 2 ++ src/haz3lweb/Export.re | 4 ++++ src/haz3lweb/Model.re | 6 ++++++ src/haz3lweb/Store.re | 34 ++++++++++++++++++++++++++++++++-- src/haz3lweb/Update.re | 11 ++++++++++- 6 files changed, 75 insertions(+), 6 deletions(-) diff --git a/src/haz3lschool/Exercise.re b/src/haz3lschool/Exercise.re index 2398fd2718..15264bd8e4 100644 --- a/src/haz3lschool/Exercise.re +++ b/src/haz3lschool/Exercise.re @@ -603,6 +603,8 @@ module F = (ExerciseEnv: ExerciseEnv) => { ~spec: spec, ~instructor_mode: bool, ~editing_prompt: bool, + ~editing_point_dist: bool, + ~editing_test_num: bool, ~settings: CoreSettings.t, ) : state => { @@ -658,7 +660,9 @@ module F = (ExerciseEnv: ExerciseEnv) => { }, instructor_mode, ); - set_editing_prompt(state, editing_prompt); + let state = set_editing_prompt(state, editing_prompt); + let state = set_editing_point_dist(state, editing_point_dist); + set_editing_test_num(state, editing_test_num); }; // # Stitching @@ -1039,11 +1043,25 @@ module F = (ExerciseEnv: ExerciseEnv) => { |> Sexplib.Sexp.to_string; }; - let deserialize_exercise = (data, ~spec, ~instructor_mode, ~editing_prompt) => { + let deserialize_exercise = + ( + data, + ~spec, + ~instructor_mode, + ~editing_prompt, + ~editing_point_dist, + ~editing_test_num, + ) => { data |> Sexplib.Sexp.of_string |> persistent_state_of_sexp - |> unpersist_state(~spec, ~instructor_mode, ~editing_prompt); + |> unpersist_state( + ~spec, + ~instructor_mode, + ~editing_prompt, + ~editing_point_dist, + ~editing_test_num, + ); }; let deserialize_exercise_export = data => { diff --git a/src/haz3lschool/Gradescope.re b/src/haz3lschool/Gradescope.re index 2320051936..a7834b65b4 100644 --- a/src/haz3lschool/Gradescope.re +++ b/src/haz3lschool/Gradescope.re @@ -118,6 +118,8 @@ module Main = { ~spec, ~instructor_mode=true, ~editing_prompt=false, + ~editing_point_dist=false, + ~editing_test_num=false, ); let report = exercise |> gen_grading_report; {id, report}; diff --git a/src/haz3lweb/Export.re b/src/haz3lweb/Export.re index 9c684397b7..f5de47ad69 100644 --- a/src/haz3lweb/Export.re +++ b/src/haz3lweb/Export.re @@ -56,6 +56,8 @@ let import_all = (data, ~specs) => { Store.ExplainThisModel.import(all.explainThisModel); let instructor_mode = settings.instructor_mode; let editing_prompt = settings.editing_prompt; + let editing_point_dist = settings.editing_point_dist; + let editing_test_num = settings.editing_test_num; Store.Scratch.import(~settings=settings.core, all.scratch); Store.Exercise.import( ~settings=settings.core, @@ -63,6 +65,8 @@ let import_all = (data, ~specs) => { ~specs, ~instructor_mode, ~editing_prompt, + ~editing_point_dist, + ~editing_test_num, ); Log.import(all.log); }; diff --git a/src/haz3lweb/Model.re b/src/haz3lweb/Model.re index d4bb5cfdc1..301463c86a 100644 --- a/src/haz3lweb/Model.re +++ b/src/haz3lweb/Model.re @@ -59,6 +59,8 @@ let load_editors = ~mode: Settings.mode, ~instructor_mode: bool, ~editing_prompt: bool, + ~editing_point_dist: bool, + ~editing_test_num: bool, ) : (Editors.t, ModelResults.t) => switch (mode) { @@ -75,6 +77,8 @@ let load_editors = ~specs=ExerciseSettings.exercises, ~instructor_mode, ~editing_prompt, + ~editing_point_dist, + ~editing_test_num, ); (Exercises(n, specs, exercise), ModelResults.empty); }; @@ -99,6 +103,8 @@ let load = (init_model: t): t => { ~mode=settings.mode, ~instructor_mode=settings.instructor_mode, ~editing_prompt=settings.editing_prompt, + ~editing_point_dist=settings.editing_point_dist, + ~editing_test_num=settings.editing_test_num, ); let ui_state = init_model.ui_state; {editors, settings, results, explainThisModel, ui_state}; diff --git a/src/haz3lweb/Store.re b/src/haz3lweb/Store.re index 8458f6643a..3411efa608 100644 --- a/src/haz3lweb/Store.re +++ b/src/haz3lweb/Store.re @@ -280,7 +280,14 @@ module Exercise = { }; let load_exercise = - (~settings: CoreSettings.t, spec, ~instructor_mode, ~editing_prompt) + ( + ~settings: CoreSettings.t, + spec, + ~instructor_mode, + ~editing_prompt, + ~editing_point_dist, + ~editing_test_num, + ) : Exercise.state => { let keystring = Id.to_string(spec.id); switch (JsUtil.get_localstore(keystring)) { @@ -292,6 +299,8 @@ module Exercise = { ~spec, ~instructor_mode, ~editing_prompt, + ~editing_point_dist, + ~editing_test_num, ~settings, ) ) { @@ -325,7 +334,14 @@ module Exercise = { }; let load = - (~settings: CoreSettings.t, ~specs, ~instructor_mode, ~editing_prompt) + ( + ~settings: CoreSettings.t, + ~specs, + ~instructor_mode, + ~editing_prompt, + ~editing_point_dist, + ~editing_test_num, + ) : (int, list(p(ZipperBase.t)), state) => { switch (JsUtil.get_localstore(cur_exercise_key)) { | Some(keystring) => @@ -342,6 +358,8 @@ module Exercise = { ~spec, ~instructor_mode, ~editing_prompt, + ~editing_point_dist, + ~editing_test_num, ~settings, ) ) { @@ -365,6 +383,8 @@ module Exercise = { first_spec, ~instructor_mode, ~editing_prompt, + ~editing_point_dist, + ~editing_test_num, ~settings, ), ); @@ -381,6 +401,8 @@ module Exercise = { ~instructor_mode: bool, ~settings: CoreSettings.t, ~editing_prompt, + ~editing_point_dist, + ~editing_test_num, ) : exercise_export => { { @@ -400,6 +422,8 @@ module Exercise = { ~instructor_mode, ~settings, ~editing_prompt, + ~editing_point_dist, + ~editing_test_num, ) |> Exercise.persistent_state_of_state(~instructor_mode); (key, exercise); @@ -414,6 +438,8 @@ module Exercise = { ~instructor_mode, ~settings, ~editing_prompt=false, + ~editing_point_dist=false, + ~editing_test_num=false, ) |> sexp_of_exercise_export |> Sexplib.Sexp.to_string; @@ -430,6 +456,8 @@ module Exercise = { ~instructor_mode: bool, ~settings: CoreSettings.t, ~editing_prompt, + ~editing_point_dist, + ~editing_test_num, ) => { let exercise_export = data |> deserialize_exercise_export; save_exercise_id(exercise_export.cur_exercise); @@ -446,6 +474,8 @@ module Exercise = { ~spec, ~instructor_mode, ~editing_prompt, + ~editing_point_dist, + ~editing_test_num, ~settings, ), ~instructor_mode, diff --git a/src/haz3lweb/Update.re b/src/haz3lweb/Update.re index 0c252fe39f..d6f514bf61 100644 --- a/src/haz3lweb/Update.re +++ b/src/haz3lweb/Update.re @@ -285,6 +285,8 @@ let switch_scratch_slide = ~instructor_mode, idx: int, ~editing_prompt, + ~editing_point_dist, + ~editing_test_num, ) : option(Editors.t) => switch (editors) { @@ -301,6 +303,8 @@ let switch_scratch_slide = ~instructor_mode, ~settings, ~editing_prompt, + ~editing_point_dist, + ~editing_test_num, ); Some(Exercises(idx, specs, exercise)); }; @@ -497,7 +501,12 @@ let apply = | SwitchScratchSlide(n) => let instructor_mode = model.settings.instructor_mode; let editors = Editors.set_editing_prompt(model.editors, false); - let settings = {...model.settings, editing_prompt: false, editing_point_dist: false, editing_test_num: false}; + let settings = { + ...model.settings, + editing_prompt: false, + editing_point_dist: false, + editing_test_num: false, + }; switch ( switch_scratch_slide( editors, From 824969a5d98eba3c3fbd7b413cf7666c9d38f40a Mon Sep 17 00:00:00 2001 From: facundoy Date: Sat, 28 Sep 2024 19:46:48 -0400 Subject: [PATCH 06/12] Changed actions from edited data to edited section --- src/haz3lschool/Exercise.re | 91 +++++++++++++++++++++-------------- src/haz3lschool/Gradescope.re | 5 +- src/haz3lweb/Editors.re | 40 ++++++++++----- src/haz3lweb/Export.re | 10 ++-- src/haz3lweb/Grading.re | 24 +++++++++ src/haz3lweb/Init.ml | 5 +- src/haz3lweb/Log.re | 5 +- src/haz3lweb/Model.re | 15 +++--- src/haz3lweb/Settings.re | 5 +- src/haz3lweb/Store.re | 50 +++++++++++-------- src/haz3lweb/Update.re | 64 +++++++++++++++--------- src/haz3lweb/UpdateAction.re | 45 +++++++++-------- src/haz3lweb/view/Page.re | 5 +- 13 files changed, 234 insertions(+), 130 deletions(-) diff --git a/src/haz3lschool/Exercise.re b/src/haz3lschool/Exercise.re index 15264bd8e4..be944f5323 100644 --- a/src/haz3lschool/Exercise.re +++ b/src/haz3lschool/Exercise.re @@ -493,7 +493,7 @@ module F = (ExerciseEnv: ExerciseEnv) => { }, }; - let set_editing_test_num = ({eds, _} as state: state, editing: bool) => { + let set_editing_test_val_rep = ({eds, _} as state: state, editing: bool) => { ...state, eds: { ...eds, @@ -511,7 +511,8 @@ module F = (ExerciseEnv: ExerciseEnv) => { }, }; - let update_test_num = ({eds, _} as state: state, new_test_num: int) => { + let update_test_val_rep = + ({eds, _} as state: state, new_test_num: int, new_dist: int) => { ...state, eds: { ...eds, @@ -519,10 +520,14 @@ module F = (ExerciseEnv: ExerciseEnv) => { ...eds.your_tests, required: new_test_num, }, + point_distribution: { + ...eds.point_distribution, + test_validation: new_dist, + }, }, }; - let set_editing_point_dist = ({eds, _} as state: state, editing: bool) => { + let set_editing_mut_test_rep = ({eds, _} as state: state, editing: bool) => { ...state, eds: { ...eds, @@ -540,32 +545,44 @@ module F = (ExerciseEnv: ExerciseEnv) => { }, }; - let update_point_dist = - ({eds, _} as state: state, new_point_dist: int, dist: string) => { - let updated_point_distribution = - switch (dist) { - | "test_validation" => { - ...eds.point_distribution, - test_validation: new_point_dist, - } - | "mutation_testing" => { - ...eds.point_distribution, - mutation_testing: new_point_dist, - } - | "impl_grading" => { - ...eds.point_distribution, - impl_grading: new_point_dist, - } - | _ => eds.point_distribution - }; + let update_mut_test_rep = ({eds, _} as state: state, new_dist: int) => { + ...state, + eds: { + ...eds, + point_distribution: { + ...eds.point_distribution, + mutation_testing: new_dist, + }, + }, + }; - { - ...state, - eds: { - ...eds, - point_distribution: updated_point_distribution, + let set_editing_impl_grd_rep = ({eds, _} as state: state, editing: bool) => { + ...state, + eds: { + ...eds, + prelude: Editor.set_read_only(eds.prelude, editing), + correct_impl: Editor.set_read_only(eds.correct_impl, editing), + your_tests: { + let tests = Editor.set_read_only(eds.your_tests.tests, editing); + { + tests, + required: eds.your_tests.required, + provided: eds.your_tests.provided, + }; }, - }; + your_impl: Editor.set_read_only(eds.your_impl, editing), + }, + }; + + let update_impl_grd_rep = ({eds, _} as state: state, new_dist: int) => { + ...state, + eds: { + ...eds, + point_distribution: { + ...eds.point_distribution, + impl_grading: new_dist, + }, + }, }; let visible_in = (pos, ~instructor_mode) => { @@ -603,8 +620,9 @@ module F = (ExerciseEnv: ExerciseEnv) => { ~spec: spec, ~instructor_mode: bool, ~editing_prompt: bool, - ~editing_point_dist: bool, - ~editing_test_num: bool, + ~editing_test_val_rep: bool, + ~editing_mut_test_rep: bool, + ~editing_impl_grd_rep: bool, ~settings: CoreSettings.t, ) : state => { @@ -661,8 +679,9 @@ module F = (ExerciseEnv: ExerciseEnv) => { instructor_mode, ); let state = set_editing_prompt(state, editing_prompt); - let state = set_editing_point_dist(state, editing_point_dist); - set_editing_test_num(state, editing_test_num); + let state = set_editing_test_val_rep(state, editing_test_val_rep); + let state = set_editing_mut_test_rep(state, editing_mut_test_rep); + set_editing_impl_grd_rep(state, editing_impl_grd_rep); }; // # Stitching @@ -1049,8 +1068,9 @@ module F = (ExerciseEnv: ExerciseEnv) => { ~spec, ~instructor_mode, ~editing_prompt, - ~editing_point_dist, - ~editing_test_num, + ~editing_test_val_rep, + ~editing_mut_test_rep, + ~editing_impl_grd_rep, ) => { data |> Sexplib.Sexp.of_string @@ -1059,8 +1079,9 @@ module F = (ExerciseEnv: ExerciseEnv) => { ~spec, ~instructor_mode, ~editing_prompt, - ~editing_point_dist, - ~editing_test_num, + ~editing_test_val_rep, + ~editing_mut_test_rep, + ~editing_impl_grd_rep, ); }; diff --git a/src/haz3lschool/Gradescope.re b/src/haz3lschool/Gradescope.re index a7834b65b4..dc113226fd 100644 --- a/src/haz3lschool/Gradescope.re +++ b/src/haz3lschool/Gradescope.re @@ -118,8 +118,9 @@ module Main = { ~spec, ~instructor_mode=true, ~editing_prompt=false, - ~editing_point_dist=false, - ~editing_test_num=false, + ~editing_test_val_rep=false, + ~editing_mut_test_rep=false, + ~editing_impl_grd_rep=false, ); let report = exercise |> gen_grading_report; {id, report}; diff --git a/src/haz3lweb/Editors.re b/src/haz3lweb/Editors.re index 589aea305e..3c8eb232aa 100644 --- a/src/haz3lweb/Editors.re +++ b/src/haz3lweb/Editors.re @@ -137,40 +137,56 @@ let update_exercise_prompt = (editors: t, new_prompt: string): t => ) }; -let set_editing_test_num = (editors: t, editing: bool): t => +let set_editing_test_val_rep = (editors: t, editing: bool): t => switch (editors) { | Scratch(_) | Documentation(_) => editors | Exercises(n, specs, exercise) => - Exercises(n, specs, Exercise.set_editing_test_num(exercise, editing)) + Exercises(n, specs, Exercise.set_editing_test_val_rep(exercise, editing)) }; -let update_test_num = (editors: t, new_test_num: int): t => +let update_test_val_rep = (editors: t, new_test_num: int, new_dist: int): t => switch (editors) { | Scratch(_) | Documentation(_) => editors | Exercises(n, specs, exercise) => - Exercises(n, specs, Exercise.update_test_num(exercise, new_test_num)) + Exercises( + n, + specs, + Exercise.update_test_val_rep(exercise, new_test_num, new_dist), + ) }; -let set_editing_point_dist = (editors: t, editing: bool): t => +let set_editing_mut_test_rep = (editors: t, editing: bool): t => switch (editors) { | Scratch(_) | Documentation(_) => editors | Exercises(n, specs, exercise) => - Exercises(n, specs, Exercise.set_editing_point_dist(exercise, editing)) + Exercises(n, specs, Exercise.set_editing_mut_test_rep(exercise, editing)) }; -let update_point_dist = (editors: t, new_point_dist: int, dist: string): t => +let update_mut_test_rep = (editors: t, new_dist: int): t => switch (editors) { | Scratch(_) | Documentation(_) => editors | Exercises(n, specs, exercise) => - Exercises( - n, - specs, - Exercise.update_point_dist(exercise, new_point_dist, dist), - ) + Exercises(n, specs, Exercise.update_mut_test_rep(exercise, new_dist)) + }; + +let set_editing_impl_grd_rep = (editors: t, editing: bool): t => + switch (editors) { + | Scratch(_) + | Documentation(_) => editors + | Exercises(n, specs, exercise) => + Exercises(n, specs, Exercise.set_editing_impl_grd_rep(exercise, editing)) + }; + +let update_impl_grd_rep = (editors: t, new_dist: int): t => + switch (editors) { + | Scratch(_) + | Documentation(_) => editors + | Exercises(n, specs, exercise) => + Exercises(n, specs, Exercise.update_impl_grd_rep(exercise, new_dist)) }; let reset_nth_slide = (~settings: CoreSettings.t, n, slides): list(Editor.t) => { diff --git a/src/haz3lweb/Export.re b/src/haz3lweb/Export.re index f5de47ad69..409d9d9faf 100644 --- a/src/haz3lweb/Export.re +++ b/src/haz3lweb/Export.re @@ -56,8 +56,9 @@ let import_all = (data, ~specs) => { Store.ExplainThisModel.import(all.explainThisModel); let instructor_mode = settings.instructor_mode; let editing_prompt = settings.editing_prompt; - let editing_point_dist = settings.editing_point_dist; - let editing_test_num = settings.editing_test_num; + let editing_test_val_rep = settings.editing_test_val_rep; + let editing_mut_test_rep = settings.editing_mut_test_rep; + let editing_impl_grd_rep = settings.editing_impl_grd_rep; Store.Scratch.import(~settings=settings.core, all.scratch); Store.Exercise.import( ~settings=settings.core, @@ -65,8 +66,9 @@ let import_all = (data, ~specs) => { ~specs, ~instructor_mode, ~editing_prompt, - ~editing_point_dist, - ~editing_test_num, + ~editing_test_val_rep, + ~editing_mut_test_rep, + ~editing_impl_grd_rep, ); Log.import(all.log); }; diff --git a/src/haz3lweb/Grading.re b/src/haz3lweb/Grading.re index e16827b918..d6ab057993 100644 --- a/src/haz3lweb/Grading.re +++ b/src/haz3lweb/Grading.re @@ -53,6 +53,18 @@ module TestValidationReport = { }; }; + // let update_requirements = _ => { + // let new_prompt = + // Obj.magic( + // Js_of_ocaml.Js.some(JsUtil.get_elem_by_id("prompt-input-box")), + // )##.value; + // let update_events = [ + // inject(Set(EditingPrompt)), + // inject(UpdatePrompt(new_prompt)), + // ]; + // Virtual_dom.Vdom.Effect.Many(update_events); + // }; + let view = (~inject, report: t, max_points: int) => { Cell.report_footer_view([ div( @@ -236,6 +248,18 @@ module MutationTestingReport = { // }; // }; + // let update_requirements = _ => { + // let new_prompt = + // Obj.magic( + // Js_of_ocaml.Js.some(JsUtil.get_elem_by_id("prompt-input-box")), + // )##.value; + // let update_events = [ + // inject(Set(EditingPrompt)), + // inject(UpdatePrompt(new_prompt)), + // ]; + // Virtual_dom.Vdom.Effect.Many(update_events); + // }; + let view = (~inject, report: t, max_points: int) => if (max_points == 0) { Node.div([]); diff --git a/src/haz3lweb/Init.ml b/src/haz3lweb/Init.ml index ee90bc0429..5d0db9162e 100644 --- a/src/haz3lweb/Init.ml +++ b/src/haz3lweb/Init.ml @@ -27,8 +27,9 @@ let startup : PersistentData.t = context_inspector = false; instructor_mode = true; editing_prompt = false; - editing_point_dist = false; - editing_test_num = false; + editing_test_val_rep = false; + editing_mut_test_rep = false; + editing_impl_grd_rep = false; benchmark = false; explainThis = { show = true; show_feedback = false; highlight = NoHighlight }; diff --git a/src/haz3lweb/Log.re b/src/haz3lweb/Log.re index 619bc94317..c72213c16c 100644 --- a/src/haz3lweb/Log.re +++ b/src/haz3lweb/Log.re @@ -25,8 +25,9 @@ let is_action_logged: UpdateAction.t => bool = | Redo | UpdateResult(_) | UpdatePrompt(_) - | UpdatePointDist(_) - | UpdateTestNum(_) + | UpdateTestValRep(_) + | UpdateMutTestRep(_) + | UpdateImplGrdRep(_) | ToggleStepper(_) | StepperAction(_, StepForward(_) | StepBackward) | UpdateExplainThisModel(_) => true; diff --git a/src/haz3lweb/Model.re b/src/haz3lweb/Model.re index 301463c86a..a515b08e6a 100644 --- a/src/haz3lweb/Model.re +++ b/src/haz3lweb/Model.re @@ -59,8 +59,9 @@ let load_editors = ~mode: Settings.mode, ~instructor_mode: bool, ~editing_prompt: bool, - ~editing_point_dist: bool, - ~editing_test_num: bool, + ~editing_test_val_rep: bool, + ~editing_mut_test_rep: bool, + ~editing_impl_grd_rep: bool, ) : (Editors.t, ModelResults.t) => switch (mode) { @@ -77,8 +78,9 @@ let load_editors = ~specs=ExerciseSettings.exercises, ~instructor_mode, ~editing_prompt, - ~editing_point_dist, - ~editing_test_num, + ~editing_test_val_rep, + ~editing_mut_test_rep, + ~editing_impl_grd_rep, ); (Exercises(n, specs, exercise), ModelResults.empty); }; @@ -103,8 +105,9 @@ let load = (init_model: t): t => { ~mode=settings.mode, ~instructor_mode=settings.instructor_mode, ~editing_prompt=settings.editing_prompt, - ~editing_point_dist=settings.editing_point_dist, - ~editing_test_num=settings.editing_test_num, + ~editing_test_val_rep=settings.editing_test_val_rep, + ~editing_mut_test_rep=settings.editing_mut_test_rep, + ~editing_impl_grd_rep=settings.editing_impl_grd_rep, ); let ui_state = init_model.ui_state; {editors, settings, results, explainThisModel, ui_state}; diff --git a/src/haz3lweb/Settings.re b/src/haz3lweb/Settings.re index a17a44208f..9840eb1de9 100644 --- a/src/haz3lweb/Settings.re +++ b/src/haz3lweb/Settings.re @@ -23,8 +23,9 @@ type t = { context_inspector: bool, instructor_mode: bool, editing_prompt: bool, - editing_point_dist: bool, - editing_test_num: bool, + editing_test_val_rep: bool, + editing_mut_test_rep: bool, + editing_impl_grd_rep: bool, benchmark: bool, explainThis: ExplainThisModel.Settings.t, mode, diff --git a/src/haz3lweb/Store.re b/src/haz3lweb/Store.re index 3411efa608..d5cbcf977e 100644 --- a/src/haz3lweb/Store.re +++ b/src/haz3lweb/Store.re @@ -285,8 +285,9 @@ module Exercise = { spec, ~instructor_mode, ~editing_prompt, - ~editing_point_dist, - ~editing_test_num, + ~editing_test_val_rep, + ~editing_mut_test_rep, + ~editing_impl_grd_rep, ) : Exercise.state => { let keystring = Id.to_string(spec.id); @@ -299,8 +300,9 @@ module Exercise = { ~spec, ~instructor_mode, ~editing_prompt, - ~editing_point_dist, - ~editing_test_num, + ~editing_test_val_rep, + ~editing_mut_test_rep, + ~editing_impl_grd_rep, ~settings, ) ) { @@ -339,8 +341,9 @@ module Exercise = { ~specs, ~instructor_mode, ~editing_prompt, - ~editing_point_dist, - ~editing_test_num, + ~editing_test_val_rep, + ~editing_mut_test_rep, + ~editing_impl_grd_rep, ) : (int, list(p(ZipperBase.t)), state) => { switch (JsUtil.get_localstore(cur_exercise_key)) { @@ -358,8 +361,9 @@ module Exercise = { ~spec, ~instructor_mode, ~editing_prompt, - ~editing_point_dist, - ~editing_test_num, + ~editing_test_val_rep, + ~editing_mut_test_rep, + ~editing_impl_grd_rep, ~settings, ) ) { @@ -383,8 +387,9 @@ module Exercise = { first_spec, ~instructor_mode, ~editing_prompt, - ~editing_point_dist, - ~editing_test_num, + ~editing_test_val_rep, + ~editing_mut_test_rep, + ~editing_impl_grd_rep, ~settings, ), ); @@ -401,8 +406,9 @@ module Exercise = { ~instructor_mode: bool, ~settings: CoreSettings.t, ~editing_prompt, - ~editing_point_dist, - ~editing_test_num, + ~editing_test_val_rep, + ~editing_mut_test_rep, + ~editing_impl_grd_rep, ) : exercise_export => { { @@ -422,8 +428,9 @@ module Exercise = { ~instructor_mode, ~settings, ~editing_prompt, - ~editing_point_dist, - ~editing_test_num, + ~editing_test_val_rep, + ~editing_mut_test_rep, + ~editing_impl_grd_rep, ) |> Exercise.persistent_state_of_state(~instructor_mode); (key, exercise); @@ -438,8 +445,9 @@ module Exercise = { ~instructor_mode, ~settings, ~editing_prompt=false, - ~editing_point_dist=false, - ~editing_test_num=false, + ~editing_test_val_rep=false, + ~editing_mut_test_rep=false, + ~editing_impl_grd_rep=false, ) |> sexp_of_exercise_export |> Sexplib.Sexp.to_string; @@ -456,8 +464,9 @@ module Exercise = { ~instructor_mode: bool, ~settings: CoreSettings.t, ~editing_prompt, - ~editing_point_dist, - ~editing_test_num, + ~editing_test_val_rep, + ~editing_mut_test_rep, + ~editing_impl_grd_rep, ) => { let exercise_export = data |> deserialize_exercise_export; save_exercise_id(exercise_export.cur_exercise); @@ -474,8 +483,9 @@ module Exercise = { ~spec, ~instructor_mode, ~editing_prompt, - ~editing_point_dist, - ~editing_test_num, + ~editing_test_val_rep, + ~editing_mut_test_rep, + ~editing_impl_grd_rep, ~settings, ), ~instructor_mode, diff --git a/src/haz3lweb/Update.re b/src/haz3lweb/Update.re index d6f514bf61..de0f121723 100644 --- a/src/haz3lweb/Update.re +++ b/src/haz3lweb/Update.re @@ -176,8 +176,9 @@ let update_settings = ...settings, instructor_mode: !settings.instructor_mode, editing_prompt: false, - editing_test_num: false, - editing_point_dist: false, + editing_test_val_rep: false, + editing_mut_test_rep: false, + editing_impl_grd_rep: false, }, }; | EditingPrompt => @@ -190,24 +191,34 @@ let update_settings = editing_prompt: editing, }, }; - | EditingTestNum => - let editing = !settings.editing_test_num; + | EditingTestValRep => + let editing = !settings.editing_test_val_rep; { ...model, - editors: Editors.set_editing_test_num(model.editors, editing), + editors: Editors.set_editing_test_val_rep(model.editors, editing), settings: { ...settings, - editing_test_num: editing, + editing_test_val_rep: editing, }, }; - | EditingPointDist => - let editing = !settings.editing_point_dist; + | EditingMutTestRep => + let editing = !settings.editing_mut_test_rep; { ...model, - editors: Editors.set_editing_test_num(model.editors, editing), + editors: Editors.set_editing_mut_test_rep(model.editors, editing), settings: { ...settings, - editing_point_dist: editing, + editing_mut_test_rep: editing, + }, + }; + | EditingImplGrdRep => + let editing = !settings.editing_impl_grd_rep; + { + ...model, + editors: Editors.set_editing_impl_grd_rep(model.editors, editing), + settings: { + ...settings, + editing_impl_grd_rep: editing, }, }; | Mode(mode) => { @@ -285,8 +296,9 @@ let switch_scratch_slide = ~instructor_mode, idx: int, ~editing_prompt, - ~editing_point_dist, - ~editing_test_num, + ~editing_test_val_rep, + ~editing_mut_test_rep, + ~editing_impl_grd_rep, ) : option(Editors.t) => switch (editors) { @@ -303,8 +315,9 @@ let switch_scratch_slide = ~instructor_mode, ~settings, ~editing_prompt, - ~editing_point_dist, - ~editing_test_num, + ~editing_test_val_rep, + ~editing_mut_test_rep, + ~editing_impl_grd_rep, ); Some(Exercises(idx, specs, exercise)); }; @@ -504,8 +517,9 @@ let apply = let settings = { ...model.settings, editing_prompt: false, - editing_point_dist: false, - editing_test_num: false, + editing_test_val_rep: false, + editing_mut_test_rep: false, + editing_impl_grd_rep: false, }; switch ( switch_scratch_slide( @@ -513,8 +527,9 @@ let apply = ~settings=model.settings.core, ~instructor_mode, ~editing_prompt=false, - ~editing_point_dist=false, - ~editing_test_num=false, + ~editing_test_val_rep=false, + ~editing_mut_test_rep=false, + ~editing_impl_grd_rep=false, n, ) ) { @@ -602,16 +617,21 @@ let apply = ...model, editors: Editors.update_exercise_prompt(model.editors, new_prompt), }) - | UpdatePointDist(new_point_dist, dist) => + | UpdateTestValRep(new_test_num, new_dist) => Model.save_and_return({ ...model, editors: - Editors.update_point_dist(model.editors, new_point_dist, dist), + Editors.update_test_val_rep(model.editors, new_test_num, new_dist), + }) + | UpdateMutTestRep(new_dist) => + Model.save_and_return({ + ...model, + editors: Editors.update_mut_test_rep(model.editors, new_dist), }) - | UpdateTestNum(new_test_num) => + | UpdateImplGrdRep(new_dist) => Model.save_and_return({ ...model, - editors: Editors.update_test_num(model.editors, new_test_num), + editors: Editors.update_impl_grd_rep(model.editors, new_dist), }) }; m |> Result.map(~f=update_cached_data(~schedule_action, update)); diff --git a/src/haz3lweb/UpdateAction.re b/src/haz3lweb/UpdateAction.re index 4bed091537..d23fa9b389 100644 --- a/src/haz3lweb/UpdateAction.re +++ b/src/haz3lweb/UpdateAction.re @@ -25,8 +25,9 @@ type settings_action = | ContextInspector | InstructorMode | EditingPrompt - | EditingPointDist - | EditingTestNum + | EditingTestValRep + | EditingMutTestRep + | EditingImplGrdRep | Evaluation(evaluation_settings_action) | ExplainThis(ExplainThisModel.Settings.action) | Mode(Settings.mode); @@ -48,11 +49,6 @@ type benchmark_action = | Start | Finish; -[@deriving (show({with_path: false}), sexp, yojson)] -type edit_prompt = - | Prompt - | Model; - [@deriving (show({with_path: false}), sexp, yojson)] type export_action = | ExportScratchSlide @@ -92,8 +88,9 @@ type t = | StepperAction(ModelResults.Key.t, stepper_action) | UpdateResult(ModelResults.t) | UpdatePrompt(string) - | UpdatePointDist(int, string) - | UpdateTestNum(int); + | UpdateTestValRep(int, int) + | UpdateMutTestRep(int) + | UpdateImplGrdRep(int); module Failure = { [@deriving (show({with_path: false}), sexp, yojson)] @@ -128,8 +125,9 @@ let is_edit: t => bool = | ContextInspector | InstructorMode | EditingPrompt - | EditingPointDist - | EditingTestNum + | EditingTestValRep + | EditingMutTestRep + | EditingImplGrdRep | Evaluation(_) => false } | SetMeta(meta_action) => @@ -149,8 +147,9 @@ let is_edit: t => bool = | FinishImportScratchpad(_) | ResetCurrentEditor | UpdatePrompt(_) - | UpdatePointDist(_) - | UpdateTestNum(_) + | UpdateTestValRep(_) + | UpdateMutTestRep(_) + | UpdateImplGrdRep(_) | Reset | TAB => true | UpdateResult(_) @@ -187,8 +186,9 @@ let reevaluate_post_update: t => bool = | Dynamics | InstructorMode | EditingPrompt - | EditingPointDist - | EditingTestNum + | EditingTestValRep + | EditingMutTestRep + | EditingImplGrdRep | Mode(_) => true } | SetMeta(meta_action) => @@ -205,8 +205,9 @@ let reevaluate_post_update: t => bool = | Export(_) | UpdateResult(_) | UpdatePrompt(_) - | UpdatePointDist(_) - | UpdateTestNum(_) + | UpdateTestValRep(_) + | UpdateMutTestRep(_) + | UpdateImplGrdRep(_) | SwitchEditor(_) | DebugConsole(_) | Benchmark(_) => false @@ -238,8 +239,9 @@ let should_scroll_to_caret = | ContextInspector | InstructorMode | EditingPrompt - | EditingPointDist - | EditingTestNum + | EditingTestValRep + | EditingMutTestRep + | EditingImplGrdRep | Evaluation(_) => false } | SetMeta(meta_action) => @@ -252,8 +254,9 @@ let should_scroll_to_caret = | UpdateResult(_) | ToggleStepper(_) | UpdatePrompt(_) - | UpdatePointDist(_) - | UpdateTestNum(_) + | UpdateTestValRep(_) + | UpdateMutTestRep(_) + | UpdateImplGrdRep(_) | StepperAction(_, StepBackward | StepForward(_)) => false | FinishImportScratchpad(_) | FinishImportAll(_) diff --git a/src/haz3lweb/view/Page.re b/src/haz3lweb/view/Page.re index 68eae653e8..be2e274f25 100644 --- a/src/haz3lweb/view/Page.re +++ b/src/haz3lweb/view/Page.re @@ -26,8 +26,9 @@ let key_handler = | Some(action) => let settings = get_settings(model); settings.editing_prompt - || settings.editing_test_num - || settings.editing_point_dist + || settings.editing_test_val_rep + || settings.editing_mut_test_rep + || settings.editing_impl_grd_rep ? Many([inject(action)]) : Many([Prevent_default, Stop_propagation, inject(action)]); } From ddd2b87d0831fad36c4455dded8dba7c1cff374d Mon Sep 17 00:00:00 2001 From: facundoy Date: Sat, 28 Sep 2024 21:56:05 -0400 Subject: [PATCH 07/12] Implemented text-box and icons for editing the test validation report. Fixed an issue that prevented saves between refreshes. --- src/haz3lschool/Exercise.re | 22 +++-- src/haz3lweb/Grading.re | 136 ++++++++++++++++++++++++++---- src/haz3lweb/view/ExerciseMode.re | 2 + src/haz3lweb/view/Page.re | 3 + src/haz3lweb/www/style.css | 5 ++ 5 files changed, 145 insertions(+), 23 deletions(-) diff --git a/src/haz3lschool/Exercise.re b/src/haz3lschool/Exercise.re index be944f5323..9fe25110d5 100644 --- a/src/haz3lschool/Exercise.re +++ b/src/haz3lschool/Exercise.re @@ -134,7 +134,13 @@ module F = (ExerciseEnv: ExerciseEnv) => { }; [@deriving (show({with_path: false}), sexp, yojson)] - type persistent_state = (pos, list((pos, PersistentZipper.t)), string); + type persistent_state = ( + pos, + list((pos, PersistentZipper.t)), + string, + point_distribution, + int, + ); let editor_of_state: state => Editor.t = ({pos, eds, _}) => @@ -611,12 +617,18 @@ module F = (ExerciseEnv: ExerciseEnv) => { |> List.map(((pos, editor)) => { (pos, PersistentZipper.persist(Editor.(editor.state.zipper))) }); - (pos, zippers, eds.prompt); + ( + pos, + zippers, + eds.prompt, + eds.point_distribution, + eds.your_tests.required, + ); }; let unpersist_state = ( - (pos, positioned_zippers, prompt): persistent_state, + (pos, positioned_zippers, prompt, point_distribution, required): persistent_state, ~spec: spec, ~instructor_mode: bool, ~editing_prompt: bool, @@ -659,12 +671,12 @@ module F = (ExerciseEnv: ExerciseEnv) => { version: spec.version, module_name: spec.module_name, prompt, - point_distribution: spec.point_distribution, + point_distribution, prelude, correct_impl, your_tests: { tests: your_tests_tests, - required: spec.your_tests.required, + required, provided: spec.your_tests.provided, }, your_impl, diff --git a/src/haz3lweb/Grading.re b/src/haz3lweb/Grading.re index d6ab057993..01c027275d 100644 --- a/src/haz3lweb/Grading.re +++ b/src/haz3lweb/Grading.re @@ -1,7 +1,9 @@ +open Util; open Virtual_dom.Vdom; open Node; include Haz3lschool.Grading.F(Exercise.ExerciseEnv); +include Update; let score_view = ((earned: points, max: points)) => { div( @@ -53,28 +55,126 @@ module TestValidationReport = { }; }; - // let update_requirements = _ => { - // let new_prompt = - // Obj.magic( - // Js_of_ocaml.Js.some(JsUtil.get_elem_by_id("prompt-input-box")), - // )##.value; - // let update_events = [ - // inject(Set(EditingPrompt)), - // inject(UpdatePrompt(new_prompt)), - // ]; - // Virtual_dom.Vdom.Effect.Many(update_events); - // }; - - let view = (~inject, report: t, max_points: int) => { + let view = + ( + ~inject, + report: t, + max_points: int, + max_tests: int, + settings: Settings.t, + ) => { Cell.report_footer_view([ div( ~attrs=[Attr.classes(["test-summary"])], [ - div( - ~attrs=[Attr.class_("test-text")], - [score_view(score_of_percent(percentage(report), max_points))] - @ textual_summary(report), - ), + settings.instructor_mode + ? settings.editing_test_val_rep + ? div( + ~attrs=[Attr.class_("test-val-rep-edit")], + [ + div( + ~attrs=[Attr.class_("input-field")], + [ + label([text("New point max:")]), + input( + ~attrs=[ + Attr.type_("number"), + Attr.class_("point-num-input"), + Attr.id("point-max-input"), + Attr.value(string_of_int(max_points)), + ], + (), + ), + ], + ), + div( + ~attrs=[Attr.class_("input-field")], + [ + label([text("Tests required:")]), + input( + ~attrs=[ + Attr.type_("number"), + Attr.class_("point-num-input"), + Attr.id("test-required-input"), + Attr.value(string_of_int(max_tests)), + ], + (), + ), + ], + ), + div( + ~attrs=[Attr.class_("edit-icon")], + [ + Widgets.button( + Icons.confirm, + _ => { + let new_dist = + Obj.magic( + Js_of_ocaml.Js.some( + JsUtil.get_elem_by_id("point-max-input"), + ), + )##.value; + let new_test_num = + Obj.magic( + Js_of_ocaml.Js.some( + JsUtil.get_elem_by_id( + "test-required-input", + ), + ), + )##.value; + + let update_events = [ + inject(Set(EditingTestValRep)), + inject( + UpdateTestValRep( + int_of_string(new_test_num), + int_of_string(new_dist), + ), + ), + ]; + Virtual_dom.Vdom.Effect.Many(update_events); + }, + ), + ], + ), + div( + ~attrs=[Attr.class_("edit-icon")], + [ + Widgets.button(Icons.cancel, _ => + inject(Set(EditingTestValRep)) + ), + ], + ), + ], + ) + : div( + ~attrs=[Attr.class_("test-text")], + [ + score_view( + score_of_percent(percentage(report), max_points), + ), + ] + @ textual_summary(report) + @ [ + div( + ~attrs=[Attr.class_("edit-icon")], + [ + Widgets.button(Icons.pencil, _ => + inject(Set(EditingTestValRep)) + ), + ], + ), + ], + ) + : div( + ~attrs=[Attr.class_("test-text")], + [ + score_view( + score_of_percent(percentage(report), max_points), + ), + ] + @ textual_summary(report), + ), ] @ Option.to_list( report.test_results diff --git a/src/haz3lweb/view/ExerciseMode.re b/src/haz3lweb/view/ExerciseMode.re index 75c065e94e..76158ac1cf 100644 --- a/src/haz3lweb/view/ExerciseMode.re +++ b/src/haz3lweb/view/ExerciseMode.re @@ -206,6 +206,8 @@ let view = ~inject, grading_report.test_validation_report, grading_report.point_distribution.test_validation, + eds.your_tests.required, + settings, ), ], ), diff --git a/src/haz3lweb/view/Page.re b/src/haz3lweb/view/Page.re index be2e274f25..aa0f20589e 100644 --- a/src/haz3lweb/view/Page.re +++ b/src/haz3lweb/view/Page.re @@ -71,6 +71,9 @@ let handlers = }), ]; model.settings.editing_prompt + || model.settings.editing_test_val_rep + || model.settings.editing_mut_test_rep + || model.settings.editing_impl_grd_rep ? attrs : attrs @ [Attr.on_keypress(_ => Effect.Prevent_default)]; }; diff --git a/src/haz3lweb/www/style.css b/src/haz3lweb/www/style.css index f666eaecba..728558d02d 100644 --- a/src/haz3lweb/www/style.css +++ b/src/haz3lweb/www/style.css @@ -180,4 +180,9 @@ ninja-keys { .edit-icon:hover { animation: wobble 0.6s ease 0s 1 normal forwards; +} + +.point-num-input { + width: 50px; + font-size: 12px; } \ No newline at end of file From 869917f4e230c5c03031bfdb2871dacc78e12ff7 Mon Sep 17 00:00:00 2001 From: facundoy Date: Sun, 6 Oct 2024 14:05:03 -0400 Subject: [PATCH 08/12] Implemented editable 'provided tests' in the Test Validation Report --- src/haz3lschool/Exercise.re | 8 +++++++- src/haz3lweb/Editors.re | 10 ++++++++-- src/haz3lweb/Grading.re | 25 +++++++++++++++++++++++++ src/haz3lweb/Update.re | 9 +++++++-- src/haz3lweb/UpdateAction.re | 2 +- src/haz3lweb/view/ExerciseMode.re | 5 +++-- 6 files changed, 51 insertions(+), 8 deletions(-) diff --git a/src/haz3lschool/Exercise.re b/src/haz3lschool/Exercise.re index 9fe25110d5..5015b3ff41 100644 --- a/src/haz3lschool/Exercise.re +++ b/src/haz3lschool/Exercise.re @@ -518,13 +518,19 @@ module F = (ExerciseEnv: ExerciseEnv) => { }; let update_test_val_rep = - ({eds, _} as state: state, new_test_num: int, new_dist: int) => { + ( + {eds, _} as state: state, + new_test_num: int, + new_dist: int, + new_prov: int, + ) => { ...state, eds: { ...eds, your_tests: { ...eds.your_tests, required: new_test_num, + provided: new_prov, }, point_distribution: { ...eds.point_distribution, diff --git a/src/haz3lweb/Editors.re b/src/haz3lweb/Editors.re index 3c8eb232aa..5fa0465d44 100644 --- a/src/haz3lweb/Editors.re +++ b/src/haz3lweb/Editors.re @@ -145,7 +145,8 @@ let set_editing_test_val_rep = (editors: t, editing: bool): t => Exercises(n, specs, Exercise.set_editing_test_val_rep(exercise, editing)) }; -let update_test_val_rep = (editors: t, new_test_num: int, new_dist: int): t => +let update_test_val_rep = + (editors: t, new_test_num: int, new_dist: int, new_prov: int): t => switch (editors) { | Scratch(_) | Documentation(_) => editors @@ -153,7 +154,12 @@ let update_test_val_rep = (editors: t, new_test_num: int, new_dist: int): t => Exercises( n, specs, - Exercise.update_test_val_rep(exercise, new_test_num, new_dist), + Exercise.update_test_val_rep( + exercise, + new_test_num, + new_dist, + new_prov, + ), ) }; diff --git a/src/haz3lweb/Grading.re b/src/haz3lweb/Grading.re index 01c027275d..a45bb90633 100644 --- a/src/haz3lweb/Grading.re +++ b/src/haz3lweb/Grading.re @@ -61,6 +61,7 @@ module TestValidationReport = { report: t, max_points: int, max_tests: int, + prov_tests: int, settings: Settings.t, ) => { Cell.report_footer_view([ @@ -102,6 +103,21 @@ module TestValidationReport = { ), ], ), + div( + ~attrs=[Attr.class_("input-field")], + [ + label([text("Tests provided:")]), + input( + ~attrs=[ + Attr.type_("number"), + Attr.class_("point-num-input"), + Attr.id("test-provided-input"), + Attr.value(string_of_int(prov_tests)), + ], + (), + ), + ], + ), div( ~attrs=[Attr.class_("edit-icon")], [ @@ -122,6 +138,14 @@ module TestValidationReport = { ), ), )##.value; + let new_prov_test = + Obj.magic( + Js_of_ocaml.Js.some( + JsUtil.get_elem_by_id( + "test-provided-input", + ), + ), + )##.value; let update_events = [ inject(Set(EditingTestValRep)), @@ -129,6 +153,7 @@ module TestValidationReport = { UpdateTestValRep( int_of_string(new_test_num), int_of_string(new_dist), + int_of_string(new_prov_test), ), ), ]; diff --git a/src/haz3lweb/Update.re b/src/haz3lweb/Update.re index de0f121723..67281e817b 100644 --- a/src/haz3lweb/Update.re +++ b/src/haz3lweb/Update.re @@ -617,11 +617,16 @@ let apply = ...model, editors: Editors.update_exercise_prompt(model.editors, new_prompt), }) - | UpdateTestValRep(new_test_num, new_dist) => + | UpdateTestValRep(new_test_num, new_dist, new_prov) => Model.save_and_return({ ...model, editors: - Editors.update_test_val_rep(model.editors, new_test_num, new_dist), + Editors.update_test_val_rep( + model.editors, + new_test_num, + new_dist, + new_prov, + ), }) | UpdateMutTestRep(new_dist) => Model.save_and_return({ diff --git a/src/haz3lweb/UpdateAction.re b/src/haz3lweb/UpdateAction.re index d23fa9b389..93a2ed0667 100644 --- a/src/haz3lweb/UpdateAction.re +++ b/src/haz3lweb/UpdateAction.re @@ -88,7 +88,7 @@ type t = | StepperAction(ModelResults.Key.t, stepper_action) | UpdateResult(ModelResults.t) | UpdatePrompt(string) - | UpdateTestValRep(int, int) + | UpdateTestValRep(int, int, int) | UpdateMutTestRep(int) | UpdateImplGrdRep(int); diff --git a/src/haz3lweb/view/ExerciseMode.re b/src/haz3lweb/view/ExerciseMode.re index 76158ac1cf..1de06c0b78 100644 --- a/src/haz3lweb/view/ExerciseMode.re +++ b/src/haz3lweb/view/ExerciseMode.re @@ -81,7 +81,7 @@ let view = let prompt_view = { let (msg, _) = ExplainThis.mk_translation(~inject=Some(inject), eds.prompt); - let msg = + let new_msg = msg @ [ div( @@ -119,7 +119,7 @@ let view = ), ], ) - : div(~attrs=[Attr.class_("prompt-content")], msg) + : div(~attrs=[Attr.class_("prompt-content")], new_msg) : div(~attrs=[Attr.class_("prompt-content")], msg), ], ), @@ -207,6 +207,7 @@ let view = grading_report.test_validation_report, grading_report.point_distribution.test_validation, eds.your_tests.required, + eds.your_tests.provided, settings, ), ], From e47f631daf35bd422620eb5cb8825f97f016efe1 Mon Sep 17 00:00:00 2001 From: facundoy Date: Sun, 6 Oct 2024 14:51:08 -0400 Subject: [PATCH 09/12] Implemented editable point distribution for the Mutation Testing Report --- src/haz3lweb/Grading.re | 78 ++++++++++++++++++++++++++++--- src/haz3lweb/view/ExerciseMode.re | 1 + 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/src/haz3lweb/Grading.re b/src/haz3lweb/Grading.re index a45bb90633..e85316b221 100644 --- a/src/haz3lweb/Grading.re +++ b/src/haz3lweb/Grading.re @@ -220,10 +220,73 @@ module MutationTestingReport = { include MutationTestingReport; open Haz3lcore; - let summary_message = (~score, ~total, ~found): Node.t => + let summary_message = + (~inject, ~score, ~total, ~found, ~max_points, settings: Settings.t) + : Node.t => div( - ~attrs=[Attr.classes(["test-text"])], - [score_view(score), text(summary_str(~total, ~found))], + ~attrs=[Attr.class_("test-text")], + settings.instructor_mode + ? settings.editing_mut_test_rep + ? [ + div( + ~attrs=[Attr.class_("input-field")], + [ + label([text("New point max:")]), + input( + ~attrs=[ + Attr.type_("number"), + Attr.class_("point-num-input"), + Attr.id("point-max-input"), + Attr.value(string_of_int(max_points)), + ], + (), + ), + ], + ), + div( + ~attrs=[Attr.class_("edit-icon")], + [ + Widgets.button( + Icons.confirm, + _ => { + let new_dist = + Obj.magic( + Js_of_ocaml.Js.some( + JsUtil.get_elem_by_id("point-max-input"), + ), + )##.value; + + let update_events = [ + inject(Set(EditingMutTestRep)), + inject(UpdateMutTestRep(int_of_string(new_dist))), + ]; + Virtual_dom.Vdom.Effect.Many(update_events); + }, + ), + ], + ), + div( + ~attrs=[Attr.class_("edit-icon")], + [ + Widgets.button(Icons.cancel, _ => + inject(Set(EditingMutTestRep)) + ), + ], + ), + ] + : [ + score_view(score), + text(summary_str(~total, ~found)), + div( + ~attrs=[Attr.class_("edit-icon")], + [ + Widgets.button(Icons.pencil, _ => + inject(Set(EditingMutTestRep)) + ), + ], + ), + ] + : [score_view(score), text(summary_str(~total, ~found))], ); let bar = (~inject, instances) => @@ -245,7 +308,7 @@ module MutationTestingReport = { ), ); - let summary = (~inject, ~report, ~max_points) => { + let summary = (~inject, ~report, ~max_points, settings: Settings.t) => { let total = List.length(report.results); let found = List.length( @@ -263,9 +326,12 @@ module MutationTestingReport = { ], [ summary_message( + ~inject, ~score=score_of_percent(percentage(report), max_points), ~total, ~found, + ~max_points, + settings, ), bar(~inject, report.results), ], @@ -385,7 +451,7 @@ module MutationTestingReport = { // Virtual_dom.Vdom.Effect.Many(update_events); // }; - let view = (~inject, report: t, max_points: int) => + let view = (~inject, report: t, max_points: int, settings: Settings.t) => if (max_points == 0) { Node.div([]); } else { @@ -398,7 +464,7 @@ module MutationTestingReport = { ), individual_reports(~inject, report.results), ], - ~footer=Some(summary(~inject, ~report, ~max_points)), + ~footer=Some(summary(~inject, ~report, ~max_points, settings)), ); }; }; diff --git a/src/haz3lweb/view/ExerciseMode.re b/src/haz3lweb/view/ExerciseMode.re index 1de06c0b78..bdc4a74063 100644 --- a/src/haz3lweb/view/ExerciseMode.re +++ b/src/haz3lweb/view/ExerciseMode.re @@ -234,6 +234,7 @@ let view = ~inject, grading_report.mutation_testing_report, grading_report.point_distribution.mutation_testing, + settings, ), ); let your_impl_view = { From c762c91e00e05ebaccc2e6dcfd2d32870c9a9b94 Mon Sep 17 00:00:00 2001 From: facundoy Date: Sun, 20 Oct 2024 13:48:34 -0400 Subject: [PATCH 10/12] style changes --- src/haz3lweb/Grading.re | 111 ++++++++++++++++++++++++++---- src/haz3lweb/view/ExerciseMode.re | 1 + 2 files changed, 100 insertions(+), 12 deletions(-) diff --git a/src/haz3lweb/Grading.re b/src/haz3lweb/Grading.re index e85316b221..5610c3d0f0 100644 --- a/src/haz3lweb/Grading.re +++ b/src/haz3lweb/Grading.re @@ -633,7 +633,13 @@ module ImplGradingReport = { }; let view = - (~inject, ~report: t, ~syntax_report: SyntaxReport.t, ~max_points: int) => { + ( + ~inject, + ~report: t, + ~syntax_report: SyntaxReport.t, + ~max_points: int, + ~settings: Settings.t, + ) => { Cell.panel( ~classes=["cell-item", "panel", "test-panel"], [ @@ -649,18 +655,99 @@ module ImplGradingReport = { div( ~attrs=[Attr.classes(["test-summary"])], [ - div( - ~attrs=[Attr.class_("test-text")], - [ - score_view( - score_of_percent( - percentage(report, syntax_report), - max_points, + settings.instructor_mode + ? settings.editing_impl_grd_rep + ? Node.div([ + div( + ~attrs=[Attr.class_("input-field")], + [ + label([text("New point max:")]), + input( + ~attrs=[ + Attr.type_("number"), + Attr.class_("point-num-input"), + Attr.id("point-max-input"), + Attr.value(string_of_int(max_points)), + ], + (), + ), + ], + ), + div( + ~attrs=[Attr.class_("edit-icon")], + [ + Widgets.button( + Icons.confirm, + _ => { + let new_dist = + Obj.magic( + Js_of_ocaml.Js.some( + JsUtil.get_elem_by_id( + "point-max-input", + ), + ), + )##.value; + + let update_events = [ + inject(Set(EditingImplGrdRep)), + inject( + UpdateImplGrdRep( + int_of_string(new_dist), + ), + ), + ]; + Virtual_dom.Vdom.Effect.Many(update_events); + }, + ), + ], + ), + div( + ~attrs=[Attr.class_("edit-icon")], + [ + Widgets.button(Icons.cancel, _ => + inject(Set(EditingImplGrdRep)) + ), + ], + ), + ]) + : Node.div([ + div( + ~attrs=[Attr.class_("test-text")], + [ + score_view( + score_of_percent( + percentage(report, syntax_report), + max_points, + ), + ), + ] + @ textual_summary(report) + @ [ + div( + ~attrs=[Attr.class_("edit-icon")], + [ + Widgets.button(Icons.pencil, _ => + inject(Set(EditingImplGrdRep)) + ), + ], + ), + ], + ), + ]) + : Node.div([ + div( + ~attrs=[Attr.class_("test-text")], + [ + score_view( + score_of_percent( + percentage(report, syntax_report), + max_points, + ), + ), + ] + @ textual_summary(report), ), - ), - ] - @ textual_summary(report), - ), + ]), ] @ Option.to_list( report.test_results diff --git a/src/haz3lweb/view/ExerciseMode.re b/src/haz3lweb/view/ExerciseMode.re index bdc4a74063..eb75dc1099 100644 --- a/src/haz3lweb/view/ExerciseMode.re +++ b/src/haz3lweb/view/ExerciseMode.re @@ -295,6 +295,7 @@ let view = ~report=grading_report.impl_grading_report, ~syntax_report=grading_report.syntax_report, ~max_points=grading_report.point_distribution.impl_grading, + ~settings, ), ); [score_view, title_view, prompt_view] From d26947cfcec18e5db20dc95fa34479b8ef10dce8 Mon Sep 17 00:00:00 2001 From: facundoy Date: Sun, 27 Oct 2024 13:48:37 -0400 Subject: [PATCH 11/12] Added relevant update actions and implemented the storing/exporting of new changes for the new module name --- src/haz3lschool/Exercise.re | 29 +++++++++++++++++++++++++++++ src/haz3lschool/Gradescope.re | 1 + src/haz3lweb/Editors.re | 20 ++++++++++++++++++++ src/haz3lweb/Export.re | 2 ++ src/haz3lweb/Init.ml | 1 + src/haz3lweb/Log.re | 1 + src/haz3lweb/Model.re | 3 +++ src/haz3lweb/Settings.re | 1 + src/haz3lweb/Store.re | 10 ++++++++++ src/haz3lweb/Update.re | 20 ++++++++++++++++++++ src/haz3lweb/UpdateAction.re | 10 +++++++++- src/haz3lweb/view/Page.re | 1 + 12 files changed, 98 insertions(+), 1 deletion(-) diff --git a/src/haz3lschool/Exercise.re b/src/haz3lschool/Exercise.re index 5015b3ff41..953a85fe7d 100644 --- a/src/haz3lschool/Exercise.re +++ b/src/haz3lschool/Exercise.re @@ -597,6 +597,33 @@ module F = (ExerciseEnv: ExerciseEnv) => { }, }; + let set_editing_module_name = ({eds, _} as state: state, editing: bool) => { + ...state, + eds: { + ...eds, + prelude: Editor.set_read_only(eds.prelude, editing), + correct_impl: Editor.set_read_only(eds.correct_impl, editing), + your_tests: { + let tests = Editor.set_read_only(eds.your_tests.tests, editing); + { + tests, + required: eds.your_tests.required, + provided: eds.your_tests.provided, + }; + }, + your_impl: Editor.set_read_only(eds.your_impl, editing), + }, + }; + + let update_module_name = + ({eds, _} as state: state, new_module_name: string) => { + ...state, + eds: { + ...eds, + module_name: new_module_name, + }, + }; + let visible_in = (pos, ~instructor_mode) => { switch (pos) { | Prelude => instructor_mode @@ -641,6 +668,7 @@ module F = (ExerciseEnv: ExerciseEnv) => { ~editing_test_val_rep: bool, ~editing_mut_test_rep: bool, ~editing_impl_grd_rep: bool, + ~editing_module_name: bool, ~settings: CoreSettings.t, ) : state => { @@ -699,6 +727,7 @@ module F = (ExerciseEnv: ExerciseEnv) => { let state = set_editing_prompt(state, editing_prompt); let state = set_editing_test_val_rep(state, editing_test_val_rep); let state = set_editing_mut_test_rep(state, editing_mut_test_rep); + let state = set_editing_module_name(state, editing_module_name); set_editing_impl_grd_rep(state, editing_impl_grd_rep); }; diff --git a/src/haz3lschool/Gradescope.re b/src/haz3lschool/Gradescope.re index dc113226fd..c8a8305995 100644 --- a/src/haz3lschool/Gradescope.re +++ b/src/haz3lschool/Gradescope.re @@ -121,6 +121,7 @@ module Main = { ~editing_test_val_rep=false, ~editing_mut_test_rep=false, ~editing_impl_grd_rep=false, + ~editing_module_name=false, ); let report = exercise |> gen_grading_report; {id, report}; diff --git a/src/haz3lweb/Editors.re b/src/haz3lweb/Editors.re index 5fa0465d44..a2ede71e4e 100644 --- a/src/haz3lweb/Editors.re +++ b/src/haz3lweb/Editors.re @@ -195,6 +195,26 @@ let update_impl_grd_rep = (editors: t, new_dist: int): t => Exercises(n, specs, Exercise.update_impl_grd_rep(exercise, new_dist)) }; +let set_editing_module_name = (editors: t, editing: bool): t => + switch (editors) { + | Scratch(_) + | Documentation(_) => editors + | Exercises(n, specs, exercise) => + Exercises(n, specs, Exercise.set_editing_module_name(exercise, editing)) + }; + +let update_module_name = (editors: t, new_module_name: string): t => + switch (editors) { + | Scratch(_) + | Documentation(_) => editors + | Exercises(n, specs, exercise) => + Exercises( + n, + specs, + Exercise.update_module_name(exercise, new_module_name), + ) + }; + let reset_nth_slide = (~settings: CoreSettings.t, n, slides): list(Editor.t) => { let (_, init_editors, _) = Init.startup.scratch; let data = List.nth(init_editors, n); diff --git a/src/haz3lweb/Export.re b/src/haz3lweb/Export.re index 409d9d9faf..d77ce204d6 100644 --- a/src/haz3lweb/Export.re +++ b/src/haz3lweb/Export.re @@ -59,6 +59,7 @@ let import_all = (data, ~specs) => { let editing_test_val_rep = settings.editing_test_val_rep; let editing_mut_test_rep = settings.editing_mut_test_rep; let editing_impl_grd_rep = settings.editing_impl_grd_rep; + let editing_module_name = settings.editing_module_name; Store.Scratch.import(~settings=settings.core, all.scratch); Store.Exercise.import( ~settings=settings.core, @@ -69,6 +70,7 @@ let import_all = (data, ~specs) => { ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, + ~editing_module_name, ); Log.import(all.log); }; diff --git a/src/haz3lweb/Init.ml b/src/haz3lweb/Init.ml index 5d0db9162e..effa6e12ad 100644 --- a/src/haz3lweb/Init.ml +++ b/src/haz3lweb/Init.ml @@ -30,6 +30,7 @@ let startup : PersistentData.t = editing_test_val_rep = false; editing_mut_test_rep = false; editing_impl_grd_rep = false; + editing_module_name = false; benchmark = false; explainThis = { show = true; show_feedback = false; highlight = NoHighlight }; diff --git a/src/haz3lweb/Log.re b/src/haz3lweb/Log.re index c72213c16c..ef8b70dfd5 100644 --- a/src/haz3lweb/Log.re +++ b/src/haz3lweb/Log.re @@ -28,6 +28,7 @@ let is_action_logged: UpdateAction.t => bool = | UpdateTestValRep(_) | UpdateMutTestRep(_) | UpdateImplGrdRep(_) + | UpdateModuleName(_) | ToggleStepper(_) | StepperAction(_, StepForward(_) | StepBackward) | UpdateExplainThisModel(_) => true; diff --git a/src/haz3lweb/Model.re b/src/haz3lweb/Model.re index a515b08e6a..5d4f6d36a7 100644 --- a/src/haz3lweb/Model.re +++ b/src/haz3lweb/Model.re @@ -62,6 +62,7 @@ let load_editors = ~editing_test_val_rep: bool, ~editing_mut_test_rep: bool, ~editing_impl_grd_rep: bool, + ~editing_module_name: bool, ) : (Editors.t, ModelResults.t) => switch (mode) { @@ -81,6 +82,7 @@ let load_editors = ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, + ~editing_module_name, ); (Exercises(n, specs, exercise), ModelResults.empty); }; @@ -108,6 +110,7 @@ let load = (init_model: t): t => { ~editing_test_val_rep=settings.editing_test_val_rep, ~editing_mut_test_rep=settings.editing_mut_test_rep, ~editing_impl_grd_rep=settings.editing_impl_grd_rep, + ~editing_module_name=settings.editing_module_name, ); let ui_state = init_model.ui_state; {editors, settings, results, explainThisModel, ui_state}; diff --git a/src/haz3lweb/Settings.re b/src/haz3lweb/Settings.re index 9840eb1de9..bded832645 100644 --- a/src/haz3lweb/Settings.re +++ b/src/haz3lweb/Settings.re @@ -26,6 +26,7 @@ type t = { editing_test_val_rep: bool, editing_mut_test_rep: bool, editing_impl_grd_rep: bool, + editing_module_name: bool, benchmark: bool, explainThis: ExplainThisModel.Settings.t, mode, diff --git a/src/haz3lweb/Store.re b/src/haz3lweb/Store.re index d5cbcf977e..973ebd0dc1 100644 --- a/src/haz3lweb/Store.re +++ b/src/haz3lweb/Store.re @@ -288,6 +288,7 @@ module Exercise = { ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, + ~editing_module_name: bool, ) : Exercise.state => { let keystring = Id.to_string(spec.id); @@ -303,6 +304,7 @@ module Exercise = { ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, + ~editing_module_name, ~settings, ) ) { @@ -344,6 +346,7 @@ module Exercise = { ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, + ~editing_module_name: bool, ) : (int, list(p(ZipperBase.t)), state) => { switch (JsUtil.get_localstore(cur_exercise_key)) { @@ -364,6 +367,7 @@ module Exercise = { ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, + ~editing_module_name, ~settings, ) ) { @@ -390,6 +394,7 @@ module Exercise = { ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, + ~editing_module_name, ~settings, ), ); @@ -409,6 +414,7 @@ module Exercise = { ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, + ~editing_module_name: bool, ) : exercise_export => { { @@ -431,6 +437,7 @@ module Exercise = { ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, + ~editing_module_name, ) |> Exercise.persistent_state_of_state(~instructor_mode); (key, exercise); @@ -448,6 +455,7 @@ module Exercise = { ~editing_test_val_rep=false, ~editing_mut_test_rep=false, ~editing_impl_grd_rep=false, + ~editing_module_name=false, ) |> sexp_of_exercise_export |> Sexplib.Sexp.to_string; @@ -467,6 +475,7 @@ module Exercise = { ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, + ~editing_module_name: bool, ) => { let exercise_export = data |> deserialize_exercise_export; save_exercise_id(exercise_export.cur_exercise); @@ -486,6 +495,7 @@ module Exercise = { ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, + ~editing_module_name, ~settings, ), ~instructor_mode, diff --git a/src/haz3lweb/Update.re b/src/haz3lweb/Update.re index 67281e817b..622382e07b 100644 --- a/src/haz3lweb/Update.re +++ b/src/haz3lweb/Update.re @@ -179,6 +179,7 @@ let update_settings = editing_test_val_rep: false, editing_mut_test_rep: false, editing_impl_grd_rep: false, + editing_module_name: false, }, }; | EditingPrompt => @@ -221,6 +222,16 @@ let update_settings = editing_impl_grd_rep: editing, }, }; + | EditingModuleName => + let editing = !settings.editing_module_name; + { + ...model, + editors: Editors.set_editing_module_name(model.editors, editing), + settings: { + ...settings, + editing_module_name: editing, + }, + }; | Mode(mode) => { ...model, settings: { @@ -299,6 +310,7 @@ let switch_scratch_slide = ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, + ~editing_module_name: bool, ) : option(Editors.t) => switch (editors) { @@ -318,6 +330,7 @@ let switch_scratch_slide = ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, + ~editing_module_name, ); Some(Exercises(idx, specs, exercise)); }; @@ -520,6 +533,7 @@ let apply = editing_test_val_rep: false, editing_mut_test_rep: false, editing_impl_grd_rep: false, + editing_module_name: false, }; switch ( switch_scratch_slide( @@ -530,6 +544,7 @@ let apply = ~editing_test_val_rep=false, ~editing_mut_test_rep=false, ~editing_impl_grd_rep=false, + ~editing_module_name=false, n, ) ) { @@ -638,6 +653,11 @@ let apply = ...model, editors: Editors.update_impl_grd_rep(model.editors, new_dist), }) + | UpdateModuleName(new_module_name) => + Model.save_and_return({ + ...model, + editors: Editors.update_module_name(model.editors, new_module_name), + }) }; m |> Result.map(~f=update_cached_data(~schedule_action, update)); }; diff --git a/src/haz3lweb/UpdateAction.re b/src/haz3lweb/UpdateAction.re index 93a2ed0667..86dc33bc12 100644 --- a/src/haz3lweb/UpdateAction.re +++ b/src/haz3lweb/UpdateAction.re @@ -28,6 +28,7 @@ type settings_action = | EditingTestValRep | EditingMutTestRep | EditingImplGrdRep + | EditingModuleName | Evaluation(evaluation_settings_action) | ExplainThis(ExplainThisModel.Settings.action) | Mode(Settings.mode); @@ -90,7 +91,8 @@ type t = | UpdatePrompt(string) | UpdateTestValRep(int, int, int) | UpdateMutTestRep(int) - | UpdateImplGrdRep(int); + | UpdateImplGrdRep(int) + | UpdateModuleName(string); module Failure = { [@deriving (show({with_path: false}), sexp, yojson)] @@ -128,6 +130,7 @@ let is_edit: t => bool = | EditingTestValRep | EditingMutTestRep | EditingImplGrdRep + | EditingModuleName | Evaluation(_) => false } | SetMeta(meta_action) => @@ -150,6 +153,7 @@ let is_edit: t => bool = | UpdateTestValRep(_) | UpdateMutTestRep(_) | UpdateImplGrdRep(_) + | UpdateModuleName(_) | Reset | TAB => true | UpdateResult(_) @@ -189,6 +193,7 @@ let reevaluate_post_update: t => bool = | EditingTestValRep | EditingMutTestRep | EditingImplGrdRep + | EditingModuleName | Mode(_) => true } | SetMeta(meta_action) => @@ -208,6 +213,7 @@ let reevaluate_post_update: t => bool = | UpdateTestValRep(_) | UpdateMutTestRep(_) | UpdateImplGrdRep(_) + | UpdateModuleName(_) | SwitchEditor(_) | DebugConsole(_) | Benchmark(_) => false @@ -242,6 +248,7 @@ let should_scroll_to_caret = | EditingTestValRep | EditingMutTestRep | EditingImplGrdRep + | EditingModuleName | Evaluation(_) => false } | SetMeta(meta_action) => @@ -257,6 +264,7 @@ let should_scroll_to_caret = | UpdateTestValRep(_) | UpdateMutTestRep(_) | UpdateImplGrdRep(_) + | UpdateModuleName(_) | StepperAction(_, StepBackward | StepForward(_)) => false | FinishImportScratchpad(_) | FinishImportAll(_) diff --git a/src/haz3lweb/view/Page.re b/src/haz3lweb/view/Page.re index aa0f20589e..d797cf0bc2 100644 --- a/src/haz3lweb/view/Page.re +++ b/src/haz3lweb/view/Page.re @@ -74,6 +74,7 @@ let handlers = || model.settings.editing_test_val_rep || model.settings.editing_mut_test_rep || model.settings.editing_impl_grd_rep + || model.settings.editing_module_name ? attrs : attrs @ [Attr.on_keypress(_ => Effect.Prevent_default)]; }; From 84849fb97329d08d630bde24a2e29fdbb93c96ed Mon Sep 17 00:00:00 2001 From: facundoy Date: Sun, 27 Oct 2024 16:05:43 -0400 Subject: [PATCH 12/12] Implemented the UI for the module_name and the textbox for the editing --- src/haz3lschool/Exercise.re | 15 ++++++- src/haz3lweb/Store.re | 8 ++-- src/haz3lweb/Update.re | 2 +- src/haz3lweb/view/ExerciseMode.re | 69 ++++++++++++++++++++++++++++++- src/haz3lweb/view/Page.re | 1 + 5 files changed, 87 insertions(+), 8 deletions(-) diff --git a/src/haz3lschool/Exercise.re b/src/haz3lschool/Exercise.re index 953a85fe7d..2bd7cfc53e 100644 --- a/src/haz3lschool/Exercise.re +++ b/src/haz3lschool/Exercise.re @@ -140,6 +140,7 @@ module F = (ExerciseEnv: ExerciseEnv) => { string, point_distribution, int, + string, ); let editor_of_state: state => Editor.t = @@ -656,12 +657,20 @@ module F = (ExerciseEnv: ExerciseEnv) => { eds.prompt, eds.point_distribution, eds.your_tests.required, + eds.module_name, ); }; let unpersist_state = ( - (pos, positioned_zippers, prompt, point_distribution, required): persistent_state, + ( + pos, + positioned_zippers, + prompt, + point_distribution, + required, + module_name, + ): persistent_state, ~spec: spec, ~instructor_mode: bool, ~editing_prompt: bool, @@ -703,7 +712,7 @@ module F = (ExerciseEnv: ExerciseEnv) => { id: spec.id, title: spec.title, version: spec.version, - module_name: spec.module_name, + module_name, prompt, point_distribution, prelude, @@ -1118,6 +1127,7 @@ module F = (ExerciseEnv: ExerciseEnv) => { ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, + ~editing_module_name, ) => { data |> Sexplib.Sexp.of_string @@ -1129,6 +1139,7 @@ module F = (ExerciseEnv: ExerciseEnv) => { ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, + ~editing_module_name, ); }; diff --git a/src/haz3lweb/Store.re b/src/haz3lweb/Store.re index 973ebd0dc1..b88cc5589b 100644 --- a/src/haz3lweb/Store.re +++ b/src/haz3lweb/Store.re @@ -288,7 +288,7 @@ module Exercise = { ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, - ~editing_module_name: bool, + ~editing_module_name, ) : Exercise.state => { let keystring = Id.to_string(spec.id); @@ -346,7 +346,7 @@ module Exercise = { ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, - ~editing_module_name: bool, + ~editing_module_name, ) : (int, list(p(ZipperBase.t)), state) => { switch (JsUtil.get_localstore(cur_exercise_key)) { @@ -414,7 +414,7 @@ module Exercise = { ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, - ~editing_module_name: bool, + ~editing_module_name, ) : exercise_export => { { @@ -475,7 +475,7 @@ module Exercise = { ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, - ~editing_module_name: bool, + ~editing_module_name, ) => { let exercise_export = data |> deserialize_exercise_export; save_exercise_id(exercise_export.cur_exercise); diff --git a/src/haz3lweb/Update.re b/src/haz3lweb/Update.re index 622382e07b..884204230c 100644 --- a/src/haz3lweb/Update.re +++ b/src/haz3lweb/Update.re @@ -310,7 +310,7 @@ let switch_scratch_slide = ~editing_test_val_rep, ~editing_mut_test_rep, ~editing_impl_grd_rep, - ~editing_module_name: bool, + ~editing_module_name, ) : option(Editors.t) => switch (editors) { diff --git a/src/haz3lweb/view/ExerciseMode.re b/src/haz3lweb/view/ExerciseMode.re index eb75dc1099..31571e1725 100644 --- a/src/haz3lweb/view/ExerciseMode.re +++ b/src/haz3lweb/view/ExerciseMode.re @@ -66,6 +66,73 @@ let view = }; let title_view = Cell.title_cell(eds.title); + let update_module_name = _ => { + let new_module_name = + Obj.magic( + Js_of_ocaml.Js.some(JsUtil.get_elem_by_id("module-name-input")), + )##.value; + let update_events = [ + inject(Set(EditingModuleName)), + inject(UpdateModuleName(new_module_name)), + ]; + Virtual_dom.Vdom.Effect.Many(update_events); + }; + + let module_name_view = { + settings.instructor_mode + ? Cell.narrative_cell([ + div( + ~attrs=[Attr.class_("cell-module-name")], + [ + settings.editing_module_name + ? div( + ~attrs=[Attr.class_("module-name-edit")], + [ + label([text("Module name:")]), + input( + ~attrs=[ + Attr.type_("text"), + Attr.class_("text-input"), + Attr.id("module-name-input"), + Attr.value(eds.module_name), + ], + (), + ), + div( + ~attrs=[Attr.class_("edit-icon")], + [Widgets.button(Icons.confirm, update_module_name)], + ), + div( + ~attrs=[Attr.class_("edit-icon")], + [ + Widgets.button(Icons.cancel, _ => + inject(Set(EditingModuleName)) + ), + ], + ), + ], + ) + : div( + ~attrs=[Attr.class_("prompt-content")], + [ + text("Module name: "), + text(eds.module_name), + div( + ~attrs=[Attr.class_("edit-icon")], + [ + Widgets.button(Icons.pencil, _ => + inject(Set(EditingModuleName)) + ), + ], + ), + ], + ), + ], + ), + ]) + : Node.none; + }; + let update_prompt = _ => { let new_prompt = Obj.magic( @@ -298,7 +365,7 @@ let view = ~settings, ), ); - [score_view, title_view, prompt_view] + [score_view, title_view, module_name_view, prompt_view] @ render_cells( settings, [ diff --git a/src/haz3lweb/view/Page.re b/src/haz3lweb/view/Page.re index d797cf0bc2..1d84c25ea8 100644 --- a/src/haz3lweb/view/Page.re +++ b/src/haz3lweb/view/Page.re @@ -29,6 +29,7 @@ let key_handler = || settings.editing_test_val_rep || settings.editing_mut_test_rep || settings.editing_impl_grd_rep + || settings.editing_module_name ? Many([inject(action)]) : Many([Prevent_default, Stop_propagation, inject(action)]); }