From 9c8a5bc657f4a6fb3d21cff8306a542301bcff63 Mon Sep 17 00:00:00 2001 From: Seth Bernstein Date: Mon, 16 Mar 2026 10:45:50 -0400 Subject: [PATCH 1/3] fix next question placement/style --- .../runestone/views/peer/peer_async.html | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/bases/rsptx/web2py_server/applications/runestone/views/peer/peer_async.html b/bases/rsptx/web2py_server/applications/runestone/views/peer/peer_async.html index 764cb6bb..8ffc20d6 100644 --- a/bases/rsptx/web2py_server/applications/runestone/views/peer/peer_async.html +++ b/bases/rsptx/web2py_server/applications/runestone/views/peer/peer_async.html @@ -105,6 +105,15 @@

Congratulations, you have completed this assignment!

{{pass}} + {{ if all_done == "false": }} +
+
+ + + +
+
+ {{ pass }} {{ if has_vote1 and has_reflection and llm_reply: }}
@@ -113,16 +122,6 @@

Congratulations, you have completed this assignment!

{{=llm_reply}}

{{ pass }} - -{{ if all_done == "false": }} -
-
- - - -
-
-{{ pass }} From c76b918fd5178ece2538bf317f2fdf2af6b82f77 Mon Sep 17 00:00:00 2001 From: Seth Bernstein Date: Mon, 16 Mar 2026 13:22:28 -0400 Subject: [PATCH 2/3] update prompt --- .../runestone/controllers/peer.py | 19 +++++++++---------- .../applications/runestone/static/js/peer.js | 1 - 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/bases/rsptx/web2py_server/applications/runestone/controllers/peer.py b/bases/rsptx/web2py_server/applications/runestone/controllers/peer.py index eea019d6..b3e9038c 100644 --- a/bases/rsptx/web2py_server/applications/runestone/controllers/peer.py +++ b/bases/rsptx/web2py_server/applications/runestone/controllers/peer.py @@ -938,23 +938,22 @@ def get_async_llm_reflection(): "do not sound like a teacher.\n" "do not explain step by step.\n" "never say something is right or wrong.\n" - "your answer can shift throughout the conversation\n" + "do not pretend to have picked an answer yourself.\n" "never mention a choice letter as the correct answer.\n" "never clearly describe the final result of the code.\n" "never fully state what the program prints.\n" - "use common misconceptions relating to the specific problem.\n" + "be aware of common misconceptions but do not introduce them yourself.\n" "refer to code loosely like 'that line' or 'the loop' or 'the head' or 'the print'.\n" "often hedge with uncertainty.\n" #"never agree with the other student's interpretation even if it sounds correct.\n" #porter found when PI is adversarial students disengage - "use content from the other multiple choice options in your reponses when needed\n" - "let your mental model shift slightly under pressure but keep reasoning partial and never fully resolve\n" - "if the other student clearly sounds confident or repeats the same answer twice stop debating and tell them to vote again or submit it.\n" + "ask the other student to explain why they picked their answer and how they reasoned through it.\n" + "ask follow up questions about their reasoning like 'what makes you think that' or 'how did you trace through it'.\n" + "do not push them toward a different answer or imply their answer is wrong.\n" + "do not make up what the code does or claim it produces output that it doesn't.\n" + "if you are unsure about something say so honestly instead of guessing.\n" + "if the other student clearly sounds confident or repeats the same answer twice tell them to vote again or submit it.\n" "do not continue reasoning after telling them to vote again.\n" - "sometimes question whether you even read the code correctly before forming an opinion.\n" - "occasionally bring up a wrong answer option as if it might be right without committing to it.\n" - "pick an answer choice different than the one the student selected and ask the student to explain why it cannot be correct.\n" - "show reasoning process not conclusions, think out loud rather than arriving anywhere.\n" - "focus on reasoning not teaching.\n\n" + "focus on getting them to think through the problem not on changing their mind.\n\n" ) if question: diff --git a/bases/rsptx/web2py_server/applications/runestone/static/js/peer.js b/bases/rsptx/web2py_server/applications/runestone/static/js/peer.js index b671d16b..938a0f83 100644 --- a/bases/rsptx/web2py_server/applications/runestone/static/js/peer.js +++ b/bases/rsptx/web2py_server/applications/runestone/static/js/peer.js @@ -1,5 +1,4 @@ // Configuration for the PI steps and helper functions to handle step progression in the instructor's interface -console.log("PEER JS VERSION TEST 12345"); const STEP_CONFIG = { vote1: { next: ['makep', 'facechat', 'makeabgroups'], From e7e0e99fed5a9adf61827883aa7fd09b34eb0cfa Mon Sep 17 00:00:00 2001 From: Seth Bernstein Date: Mon, 16 Mar 2026 13:51:47 -0400 Subject: [PATCH 3/3] Add step banner to async PI and improve voting stage clarity --- .../runestone/controllers/peer.py | 3 ++ .../runestone/views/peer/peer_async.html | 44 ++++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/bases/rsptx/web2py_server/applications/runestone/controllers/peer.py b/bases/rsptx/web2py_server/applications/runestone/controllers/peer.py index b3e9038c..6f437019 100644 --- a/bases/rsptx/web2py_server/applications/runestone/controllers/peer.py +++ b/bases/rsptx/web2py_server/applications/runestone/controllers/peer.py @@ -724,6 +724,7 @@ def peer_async(): question_num = int(request.vars.question_num) current_question, all_done = _get_numbered_question(assignment_id, question_num - 1) + total_questions = len(_get_assignment_questions(assignment_id)) assignment = db(db.assignments.id == assignment_id).select().first() @@ -762,6 +763,8 @@ def peer_async(): assignment_id=assignment_id, assignment_name=assignment.name, nextQnum=question_num + 1, + total_questions=total_questions, + is_last_question=(question_num >= total_questions), all_done=all_done, has_vote1=has_vote1, has_reflection=has_reflection, diff --git a/bases/rsptx/web2py_server/applications/runestone/views/peer/peer_async.html b/bases/rsptx/web2py_server/applications/runestone/views/peer/peer_async.html index 8ffc20d6..a9e335b6 100644 --- a/bases/rsptx/web2py_server/applications/runestone/views/peer/peer_async.html +++ b/bases/rsptx/web2py_server/applications/runestone/views/peer/peer_async.html @@ -33,6 +33,21 @@

Peer Instruction Question (After Class)

+ +{{ if all_done == "false": }} +
+ Step 1 of 3: Answer the question +
+{{ pass }} +

This page is meant for you to use after the inclass peer instruction is over.

    @@ -42,7 +57,7 @@

    Peer Instruction Question (After Class)

  1. Answer the question again. Even if you are not changing your answer from the first time.

-
+
{{ if all_done == "false": }} @@ -110,7 +125,7 @@

Congratulations, you have completed this assignment!

- +
{{ pass }} @@ -156,6 +171,28 @@

Congratulations, you have completed this assignment!

if (btn) btn.disabled = true; } + function updateStepBanner(step) { + const banner = document.getElementById("stepBanner"); + if (!banner) return; + if (step === 1) { + banner.textContent = "Step 1 of 3: Answer the question"; + banner.style.background = "#337ab7"; + } else if (step === 2) { + banner.textContent = "Step 2 of 3: Explain your answer and discuss"; + banner.style.background = "#f0ad4e"; + banner.style.color = "#333"; + } else if (step === 3) { + banner.textContent = "Step 3 of 3: Vote again — you may keep or change your answer"; + banner.style.background = "#427e44"; + banner.style.color = "#fff"; + } else if (step === 4) { + const hasNextQ = document.querySelector('form[action="/peer/peer_async"]'); + banner.textContent = hasNextQ ? "Done! Move to the next question." : "Done! You have completed this assignment."; + banner.style.background = "#427e44"; + banner.style.color = "#fff"; + } + } + function setReflectionPanelEnabled(enabled) { const panel = document.getElementById("reflectionPanel"); if (!panel) return; @@ -173,6 +210,7 @@

Congratulations, you have completed this assignment!

alert("Please submit your first vote before voting again."); return; } + updateStepBanner(3); window._vote2Enabled = true; window._vote1Locked = false; @@ -630,6 +668,7 @@

Congratulations, you have completed this assignment!

if (studentVoteCount === 1 && !window._vote2Enabled) { hasVote1 = true; console.log("vote 1 submitted"); + updateStepBanner(2); const vote2Btn = document.getElementById("readyVote2Btn"); if (vote2Btn) { @@ -647,6 +686,7 @@

Congratulations, you have completed this assignment!

studentVoteCount = 2; studentSubmittedVote2 = true; window._vote2Enabled = false; + updateStepBanner(4); } if (studentSubmittedVote2) { try {