Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const getDefaultFormData = (): Partial<CreateExerciseFormType> => ({
enableCodeTailor: false,
parsonspersonalize: "",
parsonsexample: "",
parsonsPersonalized: true,
enableCodelens: true
});

Expand Down Expand Up @@ -100,6 +101,7 @@ export const ActiveCodeExercise: FC<ExerciseComponentProps> = ({
enableCodeTailor: data.enableCodeTailor,
parsonspersonalize: data.parsonspersonalize,
parsonsexample: data.parsonsexample,
parsonsPersonalized: data.parsonsPersonalized,
enableCodelens: data.enableCodelens
}
);
Expand Down Expand Up @@ -237,6 +239,7 @@ export const ActiveCodeExercise: FC<ExerciseComponentProps> = ({
enableCodeTailor={formData.enableCodeTailor}
parsonspersonalize={formData.parsonspersonalize}
parsonsexample={formData.parsonsexample}
parsonsPersonalized={formData.parsonsPersonalized}
enableCodelens={formData.enableCodelens}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ export const ActiveCodeExerciseSettings: FC<ActiveCodeExerciseSettingsProps> = (
// Reset personalization level when disabling
parsonspersonalize: enabled ? "movable" : "",
// Reset parsons example when disabling
parsonsexample: enabled ? formData.parsonsexample : ""
parsonsexample: enabled ? formData.parsonsexample : "",
parsonsPersonalized: enabled ? (formData.parsonsPersonalized ?? true) : true
});
};

Expand Down Expand Up @@ -112,6 +113,25 @@ export const ActiveCodeExerciseSettings: FC<ActiveCodeExerciseSettingsProps> = (
<label htmlFor="parsonsexample">Backup Example Solution</label>
</span>
</div>

<div className={styles.formField}>
<div className="flex align-items-center gap-2">
<InputSwitch
id="parsonsPersonalized"
checked={formData.parsonsPersonalized ?? true}
onChange={(e) => onChange({ parsonsPersonalized: e.value })}
/>
<label htmlFor="parsonsPersonalized" className="font-medium">
Personalize to student's code (CodeTailor)
</label>
<i
className="pi pi-info-circle parsons-personalized-icon"
data-pr-tooltip="When off, 'Get Help' shows the example Parsons puzzle without adapting to the student's code."
data-pr-position="right"
/>
<Tooltip target=".parsons-personalized-icon" />
</div>
</div>
</div>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ interface ActiveCodePreviewProps {
enableCodeTailor?: boolean;
parsonspersonalize?: "movable" | "partial" | "";
parsonsexample?: string;
parsonsPersonalized?: boolean;
enableCodelens?: boolean;
}

Expand All @@ -32,6 +33,7 @@ export const ActiveCodePreview: FC<ActiveCodePreviewProps> = ({
enableCodeTailor,
parsonspersonalize,
parsonsexample,
parsonsPersonalized,
enableCodelens
}) => {
// Fetch datafiles list to get filenames for selected acids
Expand Down Expand Up @@ -64,6 +66,7 @@ export const ActiveCodePreview: FC<ActiveCodePreviewProps> = ({
enableCodeTailor,
parsonspersonalize,
parsonsexample,
parsonsPersonalized,
enableCodelens
}
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export type QuestionJSON = Partial<{
enableCodeTailor: boolean;
parsonspersonalize: "movable" | "partial" | "";
parsonsexample: string;
parsonsPersonalized: boolean;
enableCodelens: boolean;
iframeSrc: string;
// Parsons problem options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface CodeTailorOptions {
enableCodeTailor?: boolean;
parsonspersonalize?: "movable" | "partial" | "";
parsonsexample?: string;
parsonsPersonalized?: boolean;
enableCodelens?: boolean;
}

Expand Down Expand Up @@ -39,6 +40,9 @@ export const generateActiveCodePreview = (
// If parsonsexample is provided, use it; otherwise default to LLM-example
const parsonsExampleValue = codeTailorOptions.parsonsexample?.trim() || "LLM-example";
codeTailorAttrs += ` data-parsonsexample="${parsonsExampleValue}"`;
if (codeTailorOptions.parsonsPersonalized === false) {
codeTailorAttrs += ` data-parsons-personalized="false"`;
}
}

// Codelens attribute - defaults to true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const buildQuestionJson = (data: CreateExerciseFormType) => {
enableCodeTailor: data.enableCodeTailor,
parsonspersonalize: data.parsonspersonalize,
parsonsexample: data.parsonsexample,
parsonsPersonalized: data.parsonsPersonalized,
enableCodelens: data.enableCodelens
}),
...(data.question_type === "shortanswer" && {
Expand Down Expand Up @@ -103,6 +104,7 @@ export const getDefaultQuestionJson = (languageOptions: TableDropdownOption[]) =
enableCodeTailor: false,
parsonspersonalize: "",
parsonsexample: "",
parsonsPersonalized: true,
enableCodelens: true
});

Expand All @@ -112,7 +114,7 @@ export const mergeQuestionJsonWithDefaults = (
): QuestionJSON => {
const defaultQuestionJson = getDefaultQuestionJson(languageOptions);

return {
const merged = {
...defaultQuestionJson,
...questionJson,
optionList: questionJson?.optionList ?? defaultQuestionJson.optionList,
Expand All @@ -135,6 +137,8 @@ export const mergeQuestionJsonWithDefaults = (
questionJson?.parsonspersonalize ??
(defaultQuestionJson.parsonspersonalize as "" | "movable" | "partial"),
parsonsexample: questionJson?.parsonsexample ?? defaultQuestionJson.parsonsexample,
parsonsPersonalized: questionJson?.parsonsPersonalized ?? defaultQuestionJson.parsonsPersonalized,
questionLabels: questionJson?.questionLabels ?? {}
};
return merged;
};
63 changes: 63 additions & 0 deletions bases/rsptx/book_server_api/routers/coach.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ async def parsons_scaffolding(request: Request, course: Optional[str]):
internal_test_case = data.get(
"internal_test_case"
) # Capture the internal test case from the front end
parsons_personalized = data.get("parsons_personalized", True)
print("start_to: get_parsons_help", api_token, language, personalization_level)

adaptive_attr = 'data-adaptive="true"'
Expand Down Expand Up @@ -270,6 +271,68 @@ def parsons_help(
}
return get_parsons_help(api_token, language, input_dict, personalization_level)

if not parsons_personalized:
# Return example without CodeTailor personalization
if parsonsexample != "LLM-example" and parsonsexample_html:
parsons_html = f"""
<pre class="parsonsblocks" data-question_label="1" data-numbered="left" {parsons_attrs} style="visibility: hidden;">
{parsonsexample_code}
</pre>
"""
return (
parsonsexample_code
+ "||split||"
+ parsons_html
+ "||split||"
+ personalization_level
+ "||split||"
+ "example_solution"
)
else:
from .personalized_parsons.get_personalized_solution import (
get_example_solution,
)
from .personalized_parsons.generate_parsons_blocks import (
generate_Parsons_block,
)

example_code = get_example_solution(
api_token, language, problem_description, internal_test_case
)
if not example_code:
return (
"emptyHelpCode"
+ "||split||emptyHelpParsons"
+ "||split||"
+ personalization_level
+ "||split||example_solution"
)
example_block = generate_Parsons_block(
"Solution",
language,
"Full",
problem_description,
example_code,
[],
[],
{},
)
example_block = re.sub(r"<(?=\S)", "< ", example_block)
parsons_html = f"""
<pre class="parsonsblocks" data-question_label="1" data-numbered="left" {parsons_attrs} style="visibility: hidden;">
{example_block}
</pre>
"""
return (
example_code
+ "||split||"
+ parsons_html
+ "||split||"
+ personalization_level
+ "||split||"
+ "example_solution"
)

if personalization_level in ["Solution", "Multiple"]:
(
personalized_code_solution,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ export class ActiveCode extends RunestoneBase {
this.code = $(orig).text() || "\n\n\n\n\n";
this.parsonspersonalize = $(orig).data("parsonspersonalize"); // CodeTailor: <choose 1 out of two> Allows the instructor to choose personalization level: solution-level or block-and-solution level
this.parsonsexample = $(orig).data("parsonsexample"); // CodeTailor: <choose 1 out of two> Allows the instructor to choose an example Parsons problem or LLM-example (default auto-fill, means the example is generated by LLM)
// true by default; only false when explicitly set
this.parsonsPersonalized = $(orig).data("parsons-personalized") !== false
&& $(orig).data("parsons-personalized") !== "false";
this.puzzleScaffoldingDivid = `help_puzzle_${this.parsonspersonalize}_${this.divid}`; // CodeTailor: the div id for the puzzle scaffolding help window
this.language = $(orig).data("lang");
this.timelimit = $(orig).data("timelimit");
Expand Down Expand Up @@ -654,7 +657,8 @@ export class ActiveCode extends RunestoneBase {
personalization_level: personalization_level,
parsonsexample: parsonsexample,
problem_description: problem_description,
internal_test_case: internal_test_case
internal_test_case: internal_test_case,
parsons_personalized: this.parsonsPersonalized
};
console.log('body:', body)
// CodeTailor: create a promise that rejects if the fetch takes too long
Expand Down
Loading