Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multiple-choice grading policy #784

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
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
@@ -0,0 +1,38 @@
import * as Knex from "knex"

export async function up(knex: Knex): Promise<void> {
await knex.schema.table("quiz_item", table => {
table
.enu(
"multiple_selected_options_grading_options",
["NeedToSelectAllCorrectOptions", "NeedToSelectNCorrectOptions"],
{
useNative: true,
enumName: "multiple_selected_options_grading_policy_enum",
},
)
.defaultTo("NeedToSelectAllCorrectOptions")

table.integer("multiple_selected_options_grading_policy_n").defaultTo(1)

// TODO: NeedToSelectAllCorrectOptions basically same
// table.dropColumn("multi")
})
}

export async function down(knex: Knex): Promise<void> {
await knex.schema.table("quiz_item", table => {
table.dropColumn("multiple_selected_options_grading_options")
table.dropColumn("multiple_selected_options_grading_policy_n")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drop enum


// TODO
// table
// .boolean("multi")
// .defaultTo(false)
// .notNullable()
})

await knex.schema.raw(
`drop type if exists multiple_selected_options_grading_policy_enum;`,
)
}
153 changes: 153 additions & 0 deletions packages/backendv2/database/seeds/multipleChoiceGradingPolicy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import * as Knex from "knex"

export async function seed(knex: Knex): Promise<void> {
await knex("language").insert([
{
id: "ab_BA",
country: "ab_BA",
name: "ab_BA",
},
])

await knex("course").insert([
{
id: "cd02cb32-d8d9-407f-b95f-4357864bee7a",
min_score_to_pass: null,
min_progress_to_pass: null,
min_peer_reviews_received: 2,
min_peer_reviews_given: 3,
min_review_average: 2,
max_spam_flags: 1,
organization_id: null,
moocfi_id: "f3e59b24-ff79-4f67-a9aa-21c94977240a",
max_review_spam_flags: 3,
},
])

await knex("course_translation").insert([
{
course_id: "cd02cb32-d8d9-407f-b95f-4357864bee7a",
language_id: "ab_BA",
title: "course 1",
body: "course",
abbreviation: "course",
},
])

await knex("quiz").insert([
{
id: "d7389c86-7a3a-4593-b810-b2be35319520",
course_id: "cd02cb32-d8d9-407f-b95f-4357864bee7a",
part: 1,
section: 1,
points: 1,
deadline: null,
open: null,
excluded_from_score: false,
auto_confirm: true,
tries: 1,
tries_limited: true,
award_points_even_if_wrong: false,
grant_points_policy: "grant_whenever_possible",
auto_reject: true,
},
])

await knex("quiz_translation").insert([
{
quiz_id: "d7389c86-7a3a-4593-b810-b2be35319520",
language_id: "ab_BA",
title: "quiz 1",
body: "body",
submit_message: "nice one!",
},
])

await knex("quiz_item").insert([
{
id: "40f7a704-fbbe-4411-8176-31449a5968fe",
quiz_id: "d7389c86-7a3a-4593-b810-b2be35319520",
type: "multiple-choice",
order: 1,
uses_shared_option_feedback_message: false,
multiple_selected_options_grading_options:
"NeedToSelectAllCorrectOptions",
multi: true,
},
{
id: "ae7cd864-236d-4294-a6d8-57cf8ab71383",
quiz_id: "d7389c86-7a3a-4593-b810-b2be35319520",
type: "multiple-choice",
order: 2,
uses_shared_option_feedback_message: false,
multiple_selected_options_grading_options: "NeedToSelectNCorrectOptions",
multiple_selected_options_grading_policy_n: 2,
multi: true,
},
])

await knex("quiz_item_translation").insert([
{
quiz_item_id: "40f7a704-fbbe-4411-8176-31449a5968fe",
language_id: "ab_BA",
title: "multiple-choice",
body: "item",
success_message: "yay!",
failure_message: "boo!",
shared_option_feedback_message: null,
},
])

await knex("quiz_option").insert([
{
id: "6b906647-7956-44b5-ac0f-77157c6c8a74",
quiz_item_id: "40f7a704-fbbe-4411-8176-31449a5968fe",
order: 1,
correct: false,
},
{
id: "12a56d49-1f21-46ba-bcf7-5e90da61ecd1",
quiz_item_id: "40f7a704-fbbe-4411-8176-31449a5968fe",
order: 2,
correct: false,
},
{
id: "08e648dd-176c-4ba9-a1e8-44231aef221f",
quiz_item_id: "40f7a704-fbbe-4411-8176-31449a5968fe",
order: 3,
correct: true,
},
{
id: "53c77121-daf7-485e-805d-78550b6e435d",
quiz_item_id: "40f7a704-fbbe-4411-8176-31449a5968fe",
order: 4,
correct: true,
},
{
id: "0862ddd4-e9d2-485b-b605-03cdfc94bcc4",
quiz_item_id: "ae7cd864-236d-4294-a6d8-57cf8ab71383",
order: 1,
correct: false,
},
{
id: "853e536a-a374-4e80-ba81-23c75f475529",
quiz_item_id: "ae7cd864-236d-4294-a6d8-57cf8ab71383",
order: 2,
correct: false,
},
{
id: "43142a08-2fd6-4356-b5cc-1a4b2d9ea085",
quiz_item_id: "ae7cd864-236d-4294-a6d8-57cf8ab71383",
order: 3,
correct: true,
},
{
id: "2f5ad9fd-59c2-4909-bf85-42931149e47c",
quiz_item_id: "ae7cd864-236d-4294-a6d8-57cf8ab71383",
order: 4,
correct: true,
},
])

await knex("user").insert([{ id: 1357 }])
}
1 change: 1 addition & 0 deletions packages/backendv2/knexfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ types.setTypeParser(types.builtins.INT8, value => parseInt(value))

const configOptions: { [env: string]: Config } = {
development: {
debug: true,
client: "pg",
connection: {
host: env.DB_HOST || "/var/run/postgresql",
Expand Down
12 changes: 5 additions & 7 deletions packages/backendv2/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion packages/backendv2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"migrate": "knex migrate:latest",
"seed": "knex seed:run --specific a.ts",
"update-expired-courses": "node ./dist/bin/update-expired-courses.js",
"background-producer": "node ./dist/bin/kafkaBackgroundProducer.js"
"background-producer": "node ./dist/bin/kafkaBackgroundProducer.js",
"rollback-latest": "knex migrate:down"
},
"devDependencies": {
"@types/ioredis": "^4.17.11",
Expand Down
3 changes: 2 additions & 1 deletion packages/backendv2/src/controllers/widget/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ const widget = new Router<CustomState, CustomContext>({
.post("/answer", accessControl(), async ctx => {
const user = ctx.state.user
const answer = ctx.request.body
ctx.body = await QuizAnswer.newAnswer(user.id, QuizAnswer.fromJson(answer))
const newQuizAnswer = QuizAnswer.fromJson(answer)
ctx.body = await QuizAnswer.newAnswer(user.id, newQuizAnswer)
})

.post("/answers/report-spam", accessControl(), async ctx => {
Expand Down
5 changes: 4 additions & 1 deletion packages/backendv2/src/models/course.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import { BadRequestError, NotFoundError } from "./../util/error"
import stringify from "csv-stringify"
import Quiz from "./quiz"
import Language from "./language"
import CourseTranslation from "./course_translation"
import CourseTranslation, { CourseTranslationType } from "./course_translation"
import knex from "../../database/knex"
import BaseModel from "./base_model"
import { ModelObject } from "objection"

class Course extends BaseModel {
id!: string
Expand Down Expand Up @@ -407,4 +408,6 @@ class Course extends BaseModel {
}
}

export type CourseType = ModelObject<Course>

export default Course
3 changes: 3 additions & 0 deletions packages/backendv2/src/models/course_translation.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ModelObject } from "objection"
import { EditCoursePayloadFields } from "./../types/index"
import BaseModel from "./base_model"
import Course from "./course"
Expand Down Expand Up @@ -47,4 +48,6 @@ class CourseTranslation extends BaseModel {
}
}

export type CourseTranslationType = ModelObject<CourseTranslation>

export default CourseTranslation
3 changes: 3 additions & 0 deletions packages/backendv2/src/models/kafka_message.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Knex from "knex"
import { ModelObject } from "objection"
import { ProgressMessage, QuizAnswerMessage, QuizMessage } from "../types"
import BaseModel from "./base_model"

Expand Down Expand Up @@ -45,4 +46,6 @@ class KafkaMessage extends BaseModel {
}
}

export type KafkaMessageType = ModelObject<KafkaMessage>

export default KafkaMessage
3 changes: 3 additions & 0 deletions packages/backendv2/src/models/language.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ModelObject } from "objection"
import BaseModel from "./base_model"

class Language extends BaseModel {
Expand All @@ -11,4 +12,6 @@ class Language extends BaseModel {
}
}

export type LanguageType = ModelObject<Language>

export default Language
12 changes: 9 additions & 3 deletions packages/backendv2/src/models/peer_review.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ import { BadRequestError, NotFoundError } from "./../util/error"
import QuizAnswer from "./quiz_answer"
import UserQuizState from "./user_quiz_state"
import Quiz from "./quiz"
import PeerReviewQuestionAnswer from "./peer_review_question_answer"
import PeerReviewQuestion from "./peer_review_question"
import PeerReviewQuestionAnswer, {
PeerReviewQuestionAnswerType,
} from "./peer_review_question_answer"
import PeerReviewQuestion, {
PeerReviewQuestionType,
} from "./peer_review_question"
import knex from "../../database/knex"
import BaseModel from "./base_model"
import softDelete from "objection-soft-delete"
import { mixin } from "objection"
import { mixin, ModelObject } from "objection"
import { Transaction } from "knex"

class PeerReview extends BaseModel {
Expand Down Expand Up @@ -182,4 +186,6 @@ class PeerReview extends BaseModel {
}
}

export type PeerReviewType = ModelObject<PeerReview>

export default PeerReview
12 changes: 9 additions & 3 deletions packages/backendv2/src/models/peer_review_collection.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import Quiz from "./quiz_item"
import PeerReviewCollectionTranslation from "./peer_review_collection_translation"
import PeerReviewQuestion from "./peer_review_question"
import PeerReviewCollectionTranslation, {
PeerReviewCollectionTranslationType,
} from "./peer_review_collection_translation"
import PeerReviewQuestion, {
PeerReviewQuestionType,
} from "./peer_review_question"
import BaseModel from "./base_model"
import { mixin } from "objection"
import { mixin, ModelObject } from "objection"
import softDelete from "objection-soft-delete"

export class PeerReviewCollection extends mixin(BaseModel, [
Expand Down Expand Up @@ -51,4 +55,6 @@ export class PeerReviewCollection extends mixin(BaseModel, [
}
}

export type PeerReviewCollectionType = ModelObject<PeerReviewCollection>

export default PeerReviewCollection
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ModelObject } from "objection"
import BaseModel from "./base_model"
import PeerReviewCollection from "./peer_review_collection"

Expand Down Expand Up @@ -25,4 +26,8 @@ class PeerReviewCollectionTranslation extends BaseModel {
}
}

export type PeerReviewCollectionTranslationType = ModelObject<
PeerReviewCollectionTranslation
>

export default PeerReviewCollectionTranslation
13 changes: 10 additions & 3 deletions packages/backendv2/src/models/peer_review_question.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import BaseModel from "./base_model"
import PeerReviewCollection from "./peer_review_collection"
import PeerReviewQuestionTranslation from "./peer_review_question_translation"
import { mixin } from "objection"
import PeerReviewCollection, {
PeerReviewCollectionType,
} from "./peer_review_collection"
import PeerReviewQuestionTranslation, {
PeerReviewQuestionTranslationType,
} from "./peer_review_question_translation"
import { mixin, ModelObject } from "objection"
import softDelete from "objection-soft-delete"

class PeerReviewQuestion extends mixin(BaseModel, [
Expand Down Expand Up @@ -41,4 +45,7 @@ class PeerReviewQuestion extends mixin(BaseModel, [
return await this.query().findById(id)
}
}

export type PeerReviewQuestionType = ModelObject<PeerReviewQuestion>

export default PeerReviewQuestion
Loading