Skip to content
Draft
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
30 changes: 30 additions & 0 deletions src/components/AssessmentCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from "react";
import { LinkButton } from "./LinkButton";

export interface AssessmentCardProps {
assessmentHref: string;
readmoreHref: string;
title: string;
body: string;
}
export const AssessmentCard: React.FC<AssessmentCardProps> = ({
assessmentHref,
readmoreHref,
title,
body,
}) => (
<div className="card">
<div className="card-body d-flex flex-column">
<h3 className="card-title">{title}</h3>
<p className="card-text">{body}</p>
<div className="row justify-content-center mt-auto">
<div className="col-md-4 col-sm-4 col-xs-2 py-1 px-1">
<LinkButton label="Read more" href={readmoreHref} />
</div>
<div className="col-md-4 col-sm-4 col-xs-2 py-1 px-1">
<LinkButton label="Try it now!" href={assessmentHref} />
</div>
</div>
</div>
</div>
);
10 changes: 3 additions & 7 deletions src/components/LinkButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ export interface LinkButtonProps {
}

export const LinkButton: React.FC<LinkButtonProps> = ({ label, href }) => (
<div className="row justify-content-center my-2">
<div className="col-md-12 text-center py-3">
<Link href={href}>
<a className="btn btn-warning btn-md">{label}</a>
</Link>
</div>
</div>
<Link href={href}>
<a className="btn btn-warning btn-md">{label}</a>
</Link>
);
29 changes: 29 additions & 0 deletions src/components/QuestionCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from "react";
import Image from "../components/Image";

export interface QuestionCardProps {
title: string;
body: string;
image: string;
}
export const QuestionCard: React.FC<QuestionCardProps> = ({
title,
body,
image,
}) => (
<div className="container-sm border bg-white">
<div className="row">
<div className="col-md-4 order-1 py-3">
<a style={{ position: "relative" }}>
<Image src={image} alt="assessment page view" />
</a>
</div>
<div className="col-md-8 order-2 py-3 px-3">
<div className="row">
<h3> {title} </h3>
<p> {body} </p>
</div>
</div>
</div>
</div>
);
7 changes: 7 additions & 0 deletions src/lib/urls.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const plcourseURL = {
"exam_instantFeedback": "https://www.prairielearn.org/pl/course_instance/4970/assessment/2316935",
"homework_template": "https://www.prairielearn.org/pl/course_instance/4970/assessment/2316937",
"lecture_selfGuided": "https://www.prairielearn.org/pl/course_instance/4970/assessment/2316938",
"groupWork_jupyter": "https://www.prairielearn.org/pl/course_instance/4970/assessment/2316936"
};

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@import "~bootstrap/scss/_functions.scss";
@import "~bootstrap/scss/_variables.scss";

.container {
background-color: $gray-200;
}
196 changes: 196 additions & 0 deletions src/pages/gallery/assessments/autogradedExams/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
import React from "react";
import Head from "next/head";
import classnames from "classnames";
import { Heading } from "../../../../components/Heading";
import { PageBanner } from "../../../../components/Banner";
import { LinkButton } from "../../../../components/LinkButton";
import { QuestionCard } from "../../../../components/QuestionCard";

import Image from "../../../../components/Image";
import retryImage from "./student-retry.png";
import assessmentGenerator from "./assessment-generator.png";
import questionGenerator from "./question-generator.png";
import question1Image from "./question1.png"
import question2Image from "./question2.png"
import question3Image from "./question3.png"
import question4Image from "./question4.png"

import { plcourseURL } from "../../../../lib/urls";

import styles from "./index.module.scss";

export default function DefaultExam() {
return (
<React.Fragment>
<Head>
<title>Exams | PrairieLearn</title>
</Head>
<PageBanner
title="Randomized Autograded Exams"
subtitle="Instant feedback and option to retry questions for partial credit"
/>

<div className={classnames("container-fluid my-5")}>
<div className="container-md">
<p>
Studies have shown that learning and retention of knowledge is
enhanced through retrieval practice that incorporates feedback and
increased use of formative assessments. Here we describe how we use
PrairieLearn to create quizzes where students get immediate
feedback, shortening the feedback cycle between student learning and
assessment performance. This shorter cycle enables the use of
frequent and second-chance testing, especially in large courses,
which has been shown to lead to significant improvements in learning
outcomes and better final exam performance.
</p>

<Heading>Instant feedback with retry attempts</Heading>

<p>
Using the default <code>Exam</code> configuration in PrairieLearn,
students will receive a fixed question variant for each question
generator. This feature matches a traditional paper-and-pencil
experience, where the student receives one exam with fixed
parameters.
</p>
<p>
By default, PrairieLearn will auto-grade each question in real-time,
and provide students with the feedback about correctness. Depending
on how instructors define the question points, students can try to
fix incorrect answers for the same parameters, and submit other
attempts for reduced credit, mimicking the concept of partial
credit.
</p>

<Image
src={retryImage}
alt="student retry scheme"
/>

<p>
This short feedback cycle allows students to reach out to
instructors right after the test, enabling them to promptly review
and clarify any missed contepts, and consequently make adjustments
for upcoming assessments.
</p>

<Heading>Creating exams from question pools</Heading>

<p>
Exams that are delivered asynchronously or in online unproctored
environments create an opportunity for <i>collaborative cheating</i>
, where a student can gain advantage by receiving information about
the exam from another student. Generating random exams from pools of
problems has been shown to mitigate collaborative cheating. In
PrairieLearn, question generators can be selected from what we call
<strong>alternative groups or pools</strong>. For example, an
alternative group with 4 question generators can select 2 of them at
random to create a version of the exam. In the figure below, an exam
with 4 questions is created from a set of 8 question generators.
</p>

<Image
src={assessmentGenerator}
alt="student retry scheme"
/>

<p>
In addition, question generators will create different question
variants based on randomized parameters. These question variants
will finally build a student exam, where questions appear in random
order. Our studies indicate that pools of 3-4 question generators
are effective to mitigate cheating.
</p>

<Heading>Creating exams with reduced difficulty variance</Heading>

<p>
A concern with randomized exams is how one can ensure students
receive problems of roughly similar difficulty. Problems can be
binned into pools by topic coverage and difficulty, but it can be
challenging to generate problems of identical difficulty. When
creating question generators for the first time, a instructor can
use previous experiences to decide which ones should be combined in
an alternative group. PrairieLearn will collect data from these
questions, which later can be used by instructors to improve
fairness of these randomized exams.
</p>

<Image
src={questionGenerator}
alt="question generator scheme"
/>
</div>
</div>

<div className={classnames("container-fluid py-4", styles.container)}>
<div className="container-md">
<Heading>Example from demo course</Heading>

<div className={classnames("container-fluid py-2")}>
<QuestionCard
title="Question 1"
body="This question asks students to compute the solution to an equation
given two randomized parameters. The given formula is also randomized
(selected from a set of 4 different formulas). Students have two attempts to
complete this question: the first attempt for full credit and the
second attempt for partial credit (1/3 points)."
image = {question1Image}
/>
</div>

<div className={classnames("container-fluid py-2")}>
<QuestionCard
title="Question 2"
body="This question asks students to enter the matrix corresponding to a
displayed graph, which is generated in real-time based on randomized
parameters. Students have two attempts to complete the question.
They can also receive partial credit for each attempt, since each
entry of the matrix is graded separately."
image = {question2Image}
/>
</div>

<div className={classnames("container-fluid py-2")}>
<QuestionCard
title="Question 3"
body="Highly randomized, in essence mixing 4 different questions into one,
since the circuit diagram changes (parallel and series), and the
question prompt changes (compute current or resistance). Since the
solution involves multiple computation steps, students get 5
attempts to complete the question for reduced credit."
image = {question3Image}
/>
</div>

<div className={classnames("container-fluid py-2")}>
<QuestionCard
title="Question 4"
body="This question is randomly selected out of a pool of 3 question
generators, each one of them asking students to compute a different
matrix and/or vector operation, including matrix multiplication and
outer product. Each question generator also utilizes randomized
parameters. One of the advantages of keeping similar question
variants within separate question generators is the easy access to
statistics, providing information regarding question and exam
fairness. The disadvantage is the cumbersome bookkeeping of question
generators, since one may have to coordinate changes to many files
when updates are needed."
image = {question4Image}
/>
</div>

<div className="row justify-content-center my-4">
<div className="col-md-12 text-center">
<LinkButton
label="Check this assessment live in PrairieLearn!"
href={ plcourseURL.exam_instantFeedback }
/>
</div>
</div>

</div>
</div>
</React.Fragment>
);
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/pages/gallery/assessments/groupWork/index.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@import "~bootstrap/scss/_functions.scss";
@import "~bootstrap/scss/_variables.scss";

.container {
background-color: $gray-200;
}
Loading