convert score to letter grade correctly
closes EVAL-3896 flag=none Test Plan: - Create a points based grading scheme with a range of A: 15 <= 13 B: < 13 <= 10 C: < 10 <= 7 D: < 7 <= 0 - Set a letter graded assignment ot that scheme and ensure a 13 is an A and a 12.999 is a B and a 10 is a B and a 9.999 is a C and a 7 is a C - Ensure this works for all places grades are displayed like: -gradebook -individual gradebook -student grades page -etc Change-Id: Icdf901c42c8c9ce45abe2943e6a073045fca56db Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/343681 QA-Review: Rohan Chugh <rohan.chugh@instructure.com> Product-Review: Melissa Kruger <melissa.kruger@instructure.com> Reviewed-by: Derek Williams <derek.williams@instructure.com> Reviewed-by: Christopher Soto <christopher.soto@instructure.com> Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
This commit is contained in:
parent
5c4848a1a9
commit
f44c9b6896
|
@ -83,7 +83,8 @@ class AssignmentsController < ApplicationController
|
|||
newquizzes_on_quiz_page: @context.root_account.feature_enabled?(:newquizzes_on_quiz_page),
|
||||
show_additional_speed_grader_link: Account.site_admin.feature_enabled?(:additional_speedgrader_links),
|
||||
},
|
||||
grading_scheme: @context.grading_standard_or_default.data
|
||||
grading_scheme: @context.grading_standard_or_default.data,
|
||||
points_based: @context.grading_standard_or_default.points_based?,
|
||||
}
|
||||
|
||||
set_default_tool_env!(@context, hash)
|
||||
|
@ -148,7 +149,8 @@ class AssignmentsController < ApplicationController
|
|||
peer_display_name: @assignment.anonymous_peer_reviews? ? I18n.t("Anonymous student") : submission&.user&.name,
|
||||
originality_reports_for_a2_enabled: Account.site_admin.feature_enabled?(:originality_reports_for_a2),
|
||||
restrict_quantitative_data: @assignment.restrict_quantitative_data?(@current_user),
|
||||
grading_scheme: @context.grading_standard_or_default.data
|
||||
grading_scheme: @context.grading_standard_or_default.data,
|
||||
points_based: @context.grading_standard_or_default.points_based?,
|
||||
})
|
||||
|
||||
if peer_review_mode_enabled
|
||||
|
|
|
@ -2391,6 +2391,7 @@ class CoursesController < ApplicationController
|
|||
TAB_CONTENT_ONLY: embed_mode,
|
||||
SHOW_IMMERSIVE_READER: show_immersive_reader?,
|
||||
GRADING_SCHEME: @context.grading_standard_or_default.data,
|
||||
POINTS_BASED: @context.grading_standard_or_default.points_based?,
|
||||
RESTRICT_QUANTITATIVE_DATA: @context.restrict_quantitative_data?(@current_user)
|
||||
)
|
||||
|
||||
|
|
|
@ -279,6 +279,7 @@ class UsersController < ApplicationController
|
|||
end
|
||||
grade_data[:restrict_quantitative_data] = enrollment.course.restrict_quantitative_data?(@current_user)
|
||||
grade_data[:grading_scheme] = enrollment.course.grading_standard_or_default.data
|
||||
grade_data[:points_based_grading_scheme] = enrollment.course.grading_standard_or_default.points_based?
|
||||
|
||||
render json: grade_data
|
||||
end
|
||||
|
|
|
@ -194,6 +194,9 @@ class GradingStandard < ActiveRecord::Base
|
|||
score = 0 if score < 0
|
||||
# assign the highest grade whose min cutoff is less than the score
|
||||
# if score is less than all scheme cutoffs, assign the lowest grade
|
||||
if points_based
|
||||
score = score.round(2) # round to 2 decimal places because points based grading schemes lower bounds are rounded to 2 decimal places
|
||||
end
|
||||
score = BigDecimal(score.to_s) # Cast this to a BigDecimal too or comparisons get wonky
|
||||
ordered_scheme.max_by { |_, lower_bound| (score >= lower_bound * BigDecimal("100.0")) ? lower_bound : -lower_bound }[0]
|
||||
end
|
||||
|
|
|
@ -169,6 +169,7 @@ module Api::V1::Course
|
|||
end
|
||||
|
||||
hash["grading_scheme"] = course.grading_standard_or_default.data if includes.include?("grading_scheme")
|
||||
hash["points_based_grading_scheme"] = course.grading_standard_or_default.points_based? if includes.include?("grading_scheme")
|
||||
hash["restrict_quantitative_data"] = course.restrict_quantitative_data?(user) if includes.include?("restrict_quantitative_data")
|
||||
|
||||
# return hash from the block for additional processing in Api::V1::CourseJson
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
import {describe, test, expect} from '@jest/globals'
|
||||
import {scoreToGrade, scoreToLetterGrade} from '../index.js'
|
||||
import {scoreToGrade, scoreToLetterGrade} from '../index'
|
||||
|
||||
describe('index', () => {
|
||||
describe('scoreToGrade', () => {
|
||||
|
@ -81,6 +81,20 @@ describe('index', () => {
|
|||
expect(scoreToGrade(0, gradingScheme)).toBe('M')
|
||||
expect(scoreToGrade(-100, gradingScheme)).toBe('M')
|
||||
})
|
||||
|
||||
test('rounds point based grading schemes to appropriate precision to ensure bottom limit is ', () => {
|
||||
const gradingScheme = [
|
||||
{name: 'A', value: 0.8667},
|
||||
{name: 'B', value: 0.6667},
|
||||
{name: 'C', value: 0.4667},
|
||||
{name: 'D', value: 0},
|
||||
]
|
||||
|
||||
expect(scoreToGrade(86.6666666666667, gradingScheme, true)).toBe('A')
|
||||
expect(scoreToGrade(66.6666666666667, gradingScheme, true)).toBe('B')
|
||||
expect(scoreToGrade(46.6666666666667, gradingScheme, true)).toBe('C')
|
||||
expect(scoreToGrade(45, gradingScheme, true)).toBe('D')
|
||||
})
|
||||
})
|
||||
|
||||
describe('scoreToLetterGrade', () => {
|
||||
|
@ -129,5 +143,19 @@ describe('index', () => {
|
|||
expect(scoreToLetterGrade(90, gradingScheme)).toBe('A')
|
||||
expect(scoreToLetterGrade(89.999, gradingScheme)).toBe('B+')
|
||||
})
|
||||
|
||||
test('rounds point based grading schemes to appropriate precision to ensure bottom limit is ', () => {
|
||||
const gradingScheme = [
|
||||
{name: 'A', value: 0.8667},
|
||||
{name: 'B', value: 0.6667},
|
||||
{name: 'C', value: 0.4667},
|
||||
{name: 'D', value: 0},
|
||||
]
|
||||
|
||||
expect(scoreToLetterGrade(86.6666666666667, gradingScheme, true)).toBe('A')
|
||||
expect(scoreToLetterGrade(66.6666666666667, gradingScheme, true)).toBe('B')
|
||||
expect(scoreToLetterGrade(46.6666666666667, gradingScheme, true)).toBe('C')
|
||||
expect(scoreToLetterGrade(45, gradingScheme, true)).toBe('D')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
// @ts-ignore
|
||||
import Big from 'big.js';
|
||||
import Big from 'big.js'
|
||||
|
||||
/**
|
||||
* @typedef {[string, number]} GradingStandard
|
||||
|
@ -30,44 +30,50 @@ import Big from 'big.js';
|
|||
*/
|
||||
|
||||
/**
|
||||
* @deprecated Use scoreToLetterGrade(score: number, gradingSchemeDataRows: GradingSchemeDataRow[]) instead, which takes
|
||||
* @deprecated Use scoreToLetterGrade(score: number, gradingSchemeDataRows: GradingSchemeDataRow[], points_based) instead, which takes
|
||||
* a more reasonably typed object model than the 2d array that this function takes in for gradingScheme data rows.
|
||||
* @param {number} score
|
||||
* @param {GradingStandard[]} gradingSchemes
|
||||
* @param {boolean} pointsBased
|
||||
* @returns {?string}
|
||||
*/
|
||||
export function scoreToGrade(score, gradingSchemes) {
|
||||
export function scoreToGrade(score, gradingSchemes, pointsBased = false) {
|
||||
// Because scoreToGrade is being used in a non typescript file, ui/features/grade_summary/jquery/index.js,
|
||||
// score can be NaN despite its type being declared as a number
|
||||
if (typeof score !== 'number' || Number.isNaN(score) || gradingSchemes == null) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
// convert deprecated 2d array format to newer GradingSchemeDataRow[] format
|
||||
const gradingSchemeDataRows = gradingSchemes.map(row => ({ name: row[0], value: row[1] }));
|
||||
return scoreToLetterGrade(score, gradingSchemeDataRows);
|
||||
const gradingSchemeDataRows = gradingSchemes.map(row => ({name: row[0], value: row[1]}))
|
||||
|
||||
return scoreToLetterGrade(score, gradingSchemeDataRows, pointsBased)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} score
|
||||
* @param {GradingSchemeDataRow[]} gradingSchemeDataRows
|
||||
* @param {boolean} pointsBased
|
||||
* @returns {string}
|
||||
*/
|
||||
export function scoreToLetterGrade(score, gradingSchemeDataRows) {
|
||||
export function scoreToLetterGrade(score, gradingSchemeDataRows, pointsBased = false) {
|
||||
// Because scoreToGrade is being used in a non typescript file, ui/features/grade_summary/jquery/index.js,
|
||||
// score can be NaN despite its type being declared as a number
|
||||
if (typeof score !== 'number' || Number.isNaN(score) || gradingSchemeDataRows == null) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
const roundedScore = parseFloat(Big(score).round(4));
|
||||
const scoreWithLowerBound = Math.max(roundedScore, 0);
|
||||
const roundedScore = pointsBased
|
||||
? parseFloat(Big(score).round(2)) // round to 2 decimal places because points based grading schemes lower bounds are rounded to 2 decimal places
|
||||
: parseFloat(Big(score).round(4))
|
||||
const scoreWithLowerBound = Math.max(roundedScore, 0)
|
||||
const letter = gradingSchemeDataRows.find((row, i) => {
|
||||
const schemeScore = (row.value * 100).toPrecision(4);
|
||||
return scoreWithLowerBound >= parseFloat(schemeScore) || i === gradingSchemeDataRows.length - 1;
|
||||
});
|
||||
const schemeScore = (row.value * 100).toPrecision(4)
|
||||
return scoreWithLowerBound >= parseFloat(schemeScore) || i === gradingSchemeDataRows.length - 1
|
||||
})
|
||||
if (!letter) {
|
||||
throw new Error('grading scheme not found');
|
||||
throw new Error('grading scheme not found')
|
||||
}
|
||||
return letter.name;
|
||||
|
||||
return letter.name
|
||||
}
|
||||
|
|
|
@ -266,6 +266,17 @@ describe GradingStandard do
|
|||
expect(standard.score_to_grade(-100)).to eql("M")
|
||||
end
|
||||
|
||||
it "computes correct grades for points based grading scemes" do
|
||||
input = [["A", 0.8667], ["B", 0.6667], ["C", 0.4667], ["D", 0]]
|
||||
standard = GradingStandard.new
|
||||
standard.data = input
|
||||
standard.points_based = true
|
||||
expect(standard.score_to_grade(86.66666666667)).to eql("A")
|
||||
expect(standard.score_to_grade(66.66666666667)).to eql("B")
|
||||
expect(standard.score_to_grade(46.66666666667)).to eql("C")
|
||||
expect(standard.score_to_grade(0)).to eql("D")
|
||||
end
|
||||
|
||||
it "assigns the lowest grade to below-scale scores" do
|
||||
input = [["A", 0.90], ["B", 0.80], ["C", 0.70], ["D", 0.60], ["E", 0.50]]
|
||||
standard = GradingStandard.new
|
||||
|
|
|
@ -797,13 +797,14 @@ export default AssignmentListItemView = (function () {
|
|||
if (json.pointsPossible === 0 && json.submission.score < 0) {
|
||||
grade = json.submission.score
|
||||
} else if (json.pointsPossible === 0 && json.submission.score > 0) {
|
||||
grade = scoreToGrade(100, ENV.grading_scheme)
|
||||
grade = scoreToGrade(100, ENV.grading_scheme, ENV.points_based)
|
||||
} else if (json.pointsPossible === 0 && json.submission.score === 0) {
|
||||
grade = 'complete'
|
||||
} else {
|
||||
grade = scoreToGrade(
|
||||
scoreToPercentage(json.submission.score, json.pointsPossible),
|
||||
ENV.grading_scheme
|
||||
ENV.grading_scheme,
|
||||
ENV.points_based
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,6 +109,7 @@ export default ({
|
|||
score: ENV.restrict_quantitative_data && submission.score != null ? submission.score : null,
|
||||
restrict_quantitative_data: ENV.restrict_quantitative_data,
|
||||
grading_scheme: ENV.grading_scheme,
|
||||
points_based_grading_scheme: ENV.points_based,
|
||||
})
|
||||
|
||||
return (
|
||||
|
|
|
@ -96,6 +96,7 @@ export default function PointsDisplay(props) {
|
|||
formatType: 'points_out_of_fraction',
|
||||
restrict_quantitative_data: ENV.restrict_quantitative_data,
|
||||
grading_scheme: ENV.grading_scheme,
|
||||
points_based_grading_scheme: ENV.points_based,
|
||||
})
|
||||
|
||||
if (
|
||||
|
|
|
@ -60,7 +60,9 @@ export default function RowScore({gradingScheme, name, possible, score, weight}:
|
|||
const letterGradeScore = isPercentInvalid
|
||||
? '-'
|
||||
: gradingScheme
|
||||
? GradeFormatHelper.replaceDashWithMinus(getLetterGrade(possible, score, gradingScheme.data))
|
||||
? GradeFormatHelper.replaceDashWithMinus(
|
||||
getLetterGrade(possible, score, gradingScheme.data, gradingScheme.pointsBased)
|
||||
)
|
||||
: '-'
|
||||
|
||||
const weightText = weight ? I18n.n(weight, {percentage: true}) : '-'
|
||||
|
|
|
@ -211,7 +211,7 @@ export default function StudentInformation({
|
|||
|
||||
const letterGradeText = gradingStandard
|
||||
? ` - ${GradeFormatHelper.replaceDashWithMinus(
|
||||
getLetterGrade(possible, score, gradingStandard)
|
||||
getLetterGrade(possible, score, gradingStandard, gradingStandardPointsBased)
|
||||
)}`
|
||||
: ''
|
||||
|
||||
|
|
|
@ -406,14 +406,15 @@ export function scoreToScaledPoints(score: number, pointsPossible: number, scali
|
|||
export function getLetterGrade(
|
||||
possible?: number,
|
||||
score?: number,
|
||||
gradingStadards?: GradingStandard[] | null
|
||||
gradingStandards?: GradingStandard[] | null,
|
||||
pointsBased?: boolean
|
||||
) {
|
||||
if (!gradingStadards || !gradingStadards.length || !possible || !score) {
|
||||
if (!gradingStandards || !gradingStandards.length || !possible || !score) {
|
||||
return '-'
|
||||
}
|
||||
const rawPercentage = scoreToPercentage(score, possible)
|
||||
const percentage = parseFloat(Number(rawPercentage).toPrecision(4))
|
||||
return scoreToGrade(percentage, gradingStadards)
|
||||
return scoreToGrade(percentage, gradingStandards, pointsBased)
|
||||
}
|
||||
|
||||
type CalculateGradesForUserProps = {
|
||||
|
|
|
@ -474,7 +474,12 @@ function calculateTotals(calculatedGrades, currentOrFinal, groupWeightingScheme)
|
|||
: calculatePercentGrade(finalScore, finalPossible)
|
||||
|
||||
const grading_scheme = ENV.course_active_grading_scheme?.data
|
||||
const letterGrade = scoreToLetterGrade(scoreToUse, grading_scheme) || I18n.t('N/A')
|
||||
const letterGrade =
|
||||
scoreToLetterGrade(
|
||||
scoreToUse,
|
||||
grading_scheme,
|
||||
ENV.course_active_grading_scheme?.points_based
|
||||
) || I18n.t('N/A')
|
||||
|
||||
$('.final_grade .letter_grade').text(GradeFormatHelper.replaceDashWithMinus(letterGrade))
|
||||
}
|
||||
|
|
|
@ -3581,6 +3581,7 @@ class Gradebook extends React.Component<GradebookProps, GradebookState> {
|
|||
!!(submissionState != null ? submissionState.locked : undefined) || student.isConcluded
|
||||
),
|
||||
gradingScheme: this.getAssignmentGradingScheme(assignmentId)?.data || null,
|
||||
pointsBasedGradingScheme: this.getAssignmentGradingScheme(assignmentId)?.pointsBased || false,
|
||||
isFirstAssignment,
|
||||
isInOtherGradingPeriod: !!(submissionState != null
|
||||
? submissionState.inOtherGradingPeriod
|
||||
|
|
|
@ -58,6 +58,8 @@ type Props = {
|
|||
|
||||
gradingScheme: [name: string, value: number][]
|
||||
|
||||
pointsBasedGradingScheme: boolean
|
||||
|
||||
onGradeSubmission: (submission: Submission, grade: string) => void
|
||||
|
||||
onToggleSubmissionTrayOpen: (assignmentId: string, userId: string) => void
|
||||
|
@ -228,6 +230,7 @@ export default class AssignmentRowCell extends Component<Props> {
|
|||
enterGradesAs={this.props.enterGradesAs}
|
||||
disabled={this.props.submissionIsUpdating}
|
||||
gradingScheme={this.props.gradingScheme}
|
||||
pointsBasedGradingScheme={this.props.pointsBasedGradingScheme}
|
||||
pendingGradeInfo={this.props.pendingGradeInfo}
|
||||
ref={this.bindGradeInput}
|
||||
submission={this.props.submission}
|
||||
|
|
|
@ -86,6 +86,8 @@ export default class AssignmentRowCellPropFactory {
|
|||
gradeIsEditable: this.gradebook.isGradeEditable(student.id, assignment.id),
|
||||
gradeIsVisible: this.gradebook.isGradeVisible(student.id, assignment.id),
|
||||
gradingScheme: this.gradebook.getAssignmentGradingScheme(assignment.id)?.data,
|
||||
pointsBasedGradingScheme: this.gradebook.getAssignmentGradingScheme(assignment.id)
|
||||
?.pointsBased,
|
||||
isSubmissionTrayOpen: isTrayOpen(this.gradebook, student, assignment),
|
||||
|
||||
onToggleSubmissionTrayOpen: () => {
|
||||
|
|
|
@ -36,11 +36,18 @@ const componentOverrides = {
|
|||
},
|
||||
}
|
||||
|
||||
function formatGrade(submission, assignment, gradingScheme, enterGradesAs) {
|
||||
function formatGrade(
|
||||
submission,
|
||||
assignment,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
enterGradesAs
|
||||
) {
|
||||
const formatOptions = {
|
||||
defaultValue: '–',
|
||||
formatType: enterGradesAs,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
pointsPossible: assignment.pointsPossible,
|
||||
version: 'final',
|
||||
}
|
||||
|
@ -83,6 +90,7 @@ export default class ReadOnlyCell extends Component {
|
|||
enterGradesAs: oneOf(['gradingScheme', 'passFail', 'percent', 'points']).isRequired,
|
||||
gradeIsVisible: bool.isRequired,
|
||||
gradingScheme: instanceOf(Array).isRequired,
|
||||
pointsBasedGradingScheme: bool,
|
||||
onToggleSubmissionTrayOpen: func.isRequired,
|
||||
student: shape({
|
||||
id: string.isRequired,
|
||||
|
@ -141,14 +149,29 @@ export default class ReadOnlyCell extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const {assignment, enterGradesAs, gradeIsVisible, gradingScheme, submission} = this.props
|
||||
const {
|
||||
assignment,
|
||||
enterGradesAs,
|
||||
gradeIsVisible,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
submission,
|
||||
} = this.props
|
||||
|
||||
let content = ''
|
||||
if (gradeIsVisible) {
|
||||
if (enterGradesAs === 'passFail' && !submission.excused) {
|
||||
content = renderCompleteIncompleteGrade(submission.rawGrade)
|
||||
} else {
|
||||
content = renderTextGrade(formatGrade(submission, assignment, gradingScheme, enterGradesAs))
|
||||
content = renderTextGrade(
|
||||
formatGrade(
|
||||
submission,
|
||||
assignment,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
enterGradesAs
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,13 @@ import {hasGradeChanged, parseTextValue} from '@canvas/grading/GradeInputHelper'
|
|||
|
||||
const I18n = useI18nScope('gradebook')
|
||||
|
||||
function formatGrade(submission, assignment, gradingScheme, pendingGradeInfo) {
|
||||
function formatGrade(
|
||||
submission,
|
||||
assignment,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
pendingGradeInfo
|
||||
) {
|
||||
if (pendingGradeInfo) {
|
||||
return GradeFormatHelper.formatGradeInfo(pendingGradeInfo, {defaultValue: ''})
|
||||
}
|
||||
|
@ -38,6 +44,7 @@ function formatGrade(submission, assignment, gradingScheme, pendingGradeInfo) {
|
|||
defaultValue: '',
|
||||
formatType: 'gradingScheme',
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
pointsPossible: assignment.pointsPossible,
|
||||
version: 'entered',
|
||||
}
|
||||
|
@ -49,6 +56,7 @@ function getGradeInfo(value, props) {
|
|||
return parseTextValue(value, {
|
||||
enterGradesAs: 'gradingScheme',
|
||||
gradingScheme: props.gradingScheme,
|
||||
pointsBasedGradingScheme: props.pointsBasedGradingScheme,
|
||||
pointsPossible: props.assignment.pointsPossible,
|
||||
})
|
||||
}
|
||||
|
@ -60,6 +68,7 @@ export default class GradingSchemeInput extends Component {
|
|||
}).isRequired,
|
||||
disabled: bool,
|
||||
gradingScheme: instanceOf(Array).isRequired,
|
||||
pointsBasedGradingScheme: bool,
|
||||
label: element.isRequired,
|
||||
menuContentRef: Menu.propTypes.menuRef,
|
||||
messages: arrayOf(
|
||||
|
@ -88,6 +97,7 @@ export default class GradingSchemeInput extends Component {
|
|||
onMenuDismiss() {},
|
||||
onMenuShow() {},
|
||||
pendingGradeInfo: null,
|
||||
pointsBasedGradingScheme: false,
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
|
@ -105,24 +115,50 @@ export default class GradingSchemeInput extends Component {
|
|||
this.handleTextChange = this.handleTextChange.bind(this)
|
||||
this.handleToggle = this.handleToggle.bind(this)
|
||||
|
||||
const {assignment, gradingScheme, pendingGradeInfo, submission} = props
|
||||
const value = formatGrade(submission, assignment, gradingScheme, pendingGradeInfo)
|
||||
const {assignment, gradingScheme, pointsBasedGradingScheme, pendingGradeInfo, submission} =
|
||||
props
|
||||
const value = formatGrade(
|
||||
submission,
|
||||
assignment,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
pendingGradeInfo
|
||||
)
|
||||
|
||||
this.state = {
|
||||
gradeInfo: pendingGradeInfo || getGradeInfo(submission.excused ? 'EX' : value, this.props),
|
||||
menuIsOpen: false,
|
||||
value: formatGrade(submission, assignment, gradingScheme, pendingGradeInfo),
|
||||
value: formatGrade(
|
||||
submission,
|
||||
assignment,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
pendingGradeInfo
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||
if (this.textInput !== document.activeElement) {
|
||||
const {assignment, gradingScheme, pendingGradeInfo, submission} = nextProps
|
||||
const value = formatGrade(submission, assignment, gradingScheme, pendingGradeInfo)
|
||||
const {assignment, gradingScheme, pointsBasedGradingScheme, pendingGradeInfo, submission} =
|
||||
nextProps
|
||||
const value = formatGrade(
|
||||
submission,
|
||||
assignment,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
pendingGradeInfo
|
||||
)
|
||||
|
||||
this.setState({
|
||||
gradeInfo: pendingGradeInfo || getGradeInfo(submission.excused ? 'EX' : value, nextProps),
|
||||
value: formatGrade(submission, assignment, gradingScheme, pendingGradeInfo),
|
||||
value: formatGrade(
|
||||
submission,
|
||||
assignment,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
pendingGradeInfo
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -191,8 +227,13 @@ export default class GradingSchemeInput extends Component {
|
|||
return this.state.value.trim() !== this.props.pendingGradeInfo.grade
|
||||
}
|
||||
|
||||
const {assignment, gradingScheme, submission} = this.props
|
||||
const formattedGrade = formatGrade(submission, assignment, gradingScheme)
|
||||
const {assignment, gradingScheme, pointsBasedGradingScheme, submission} = this.props
|
||||
const formattedGrade = formatGrade(
|
||||
submission,
|
||||
assignment,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme
|
||||
)
|
||||
|
||||
if (formattedGrade === this.state.value.trim()) {
|
||||
return false
|
||||
|
|
|
@ -28,6 +28,7 @@ function formatGrade(
|
|||
submission,
|
||||
assignment,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
enterGradesAs,
|
||||
pendingGradeInfo: PendingGradeInfo
|
||||
) {
|
||||
|
@ -39,6 +40,7 @@ function formatGrade(
|
|||
defaultValue: '',
|
||||
formatType: enterGradesAs,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
pointsPossible: assignment.pointsPossible,
|
||||
version: 'entered',
|
||||
}
|
||||
|
@ -50,6 +52,7 @@ function getGradeInfo(value, props) {
|
|||
return parseTextValue(value, {
|
||||
enterGradesAs: props.enterGradesAs,
|
||||
gradingScheme: props.gradingScheme,
|
||||
pointsBasedGradingScheme: props.pointsBasedGradingScheme,
|
||||
pointsPossible: props.assignment.pointsPossible,
|
||||
})
|
||||
}
|
||||
|
@ -61,6 +64,7 @@ type Props = {
|
|||
disabled: boolean
|
||||
enterGradesAs: 'gradingScheme' | 'passFail' | 'percent' | 'points'
|
||||
gradingScheme: DeprecatedGradingScheme[]
|
||||
pointsBasedGradingScheme: boolean
|
||||
label: React.ReactElement
|
||||
messages: Array<{
|
||||
text: string
|
||||
|
@ -102,11 +106,19 @@ export default class TextGradeInput extends Component<Props, State> {
|
|||
this.handleKeyDown = this.handleKeyDown.bind(this)
|
||||
this.handleTextChange = this.handleTextChange.bind(this)
|
||||
|
||||
const {assignment, enterGradesAs, gradingScheme, pendingGradeInfo, submission} = props
|
||||
const {
|
||||
assignment,
|
||||
enterGradesAs,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
pendingGradeInfo,
|
||||
submission,
|
||||
} = props
|
||||
const value = formatGrade(
|
||||
submission,
|
||||
assignment,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
enterGradesAs,
|
||||
pendingGradeInfo
|
||||
)
|
||||
|
@ -119,10 +131,24 @@ export default class TextGradeInput extends Component<Props, State> {
|
|||
|
||||
UNSAFE_componentWillReceiveProps(nextProps: Props) {
|
||||
if (!this.isFocused()) {
|
||||
const {assignment, enterGradesAs, gradingScheme, pendingGradeInfo, submission} = nextProps
|
||||
const {
|
||||
assignment,
|
||||
enterGradesAs,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
pendingGradeInfo,
|
||||
submission,
|
||||
} = nextProps
|
||||
|
||||
this.setState({
|
||||
grade: formatGrade(submission, assignment, gradingScheme, enterGradesAs, pendingGradeInfo),
|
||||
grade: formatGrade(
|
||||
submission,
|
||||
assignment,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
enterGradesAs,
|
||||
pendingGradeInfo
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -149,8 +175,15 @@ export default class TextGradeInput extends Component<Props, State> {
|
|||
return this.state.grade.trim() !== this.props.pendingGradeInfo.grade
|
||||
}
|
||||
|
||||
const {assignment, enterGradesAs, gradingScheme, submission} = this.props
|
||||
const formattedGrade = formatGrade(submission, assignment, gradingScheme, enterGradesAs)
|
||||
const {assignment, enterGradesAs, gradingScheme, pointsBasedGradingScheme, submission} =
|
||||
this.props
|
||||
const formattedGrade = formatGrade(
|
||||
submission,
|
||||
assignment,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
enterGradesAs
|
||||
)
|
||||
|
||||
if (formattedGrade === this.state.grade.trim()) {
|
||||
return false
|
||||
|
|
|
@ -41,6 +41,7 @@ type Props = {
|
|||
disabled: boolean
|
||||
enterGradesAs: 'gradingScheme' | 'passFail' | 'percent' | 'points'
|
||||
gradingScheme: [name: string, value: number][]
|
||||
pointsBasedGradingScheme: boolean
|
||||
pendingGradeInfo: {
|
||||
excused: boolean
|
||||
grade: string
|
||||
|
|
|
@ -47,6 +47,7 @@ type Getters = {
|
|||
getAssignment(assignmentId: string): ReturnType<Gradebook['getAssignment']>
|
||||
getEnterGradesAsSetting(assignmentId: string): ReturnType<Gradebook['getEnterGradesAsSetting']>
|
||||
getGradingSchemeData(assignmentId: string): undefined | GradingStandard[]
|
||||
getPointsBasedGradingScheme(assignmentId: string): undefined | boolean
|
||||
getPendingGradeInfo(submission: {
|
||||
assignmentId: string
|
||||
userId: string
|
||||
|
@ -88,6 +89,7 @@ function formatGrade(submissionData: SubmissionData, assignment: Assignment, opt
|
|||
const formatOptions = {
|
||||
formatType: options.getEnterGradesAsSetting(assignment.id),
|
||||
gradingScheme: options.getGradingSchemeData(assignment.id),
|
||||
pointsBasedGradingScheme: options.getPointsBasedGradingScheme(assignment.id),
|
||||
pointsPossible: assignment.points_possible,
|
||||
version: 'final',
|
||||
}
|
||||
|
@ -170,6 +172,9 @@ export default class AssignmentCellFormatter {
|
|||
getGradingSchemeData(assignmentId: string): undefined | GradingStandard[] {
|
||||
return gradebook.getAssignmentGradingScheme(assignmentId)?.data
|
||||
},
|
||||
getPointsBasedGradingScheme(assignmentId: string): undefined | boolean {
|
||||
return gradebook.getAssignmentGradingScheme(assignmentId)?.pointsBased
|
||||
},
|
||||
getPendingGradeInfo(submission: {assignmentId: string; userId: string}) {
|
||||
return gradebook.getPendingGradeInfo(submission)
|
||||
},
|
||||
|
|
|
@ -178,7 +178,9 @@ export default class TotalGradeCellFormatter {
|
|||
let letterGrade
|
||||
const scheme = this.options.getGradingStandard()
|
||||
if (grade.possible && scheme) {
|
||||
letterGrade = GradeFormatHelper.replaceDashWithMinus(scoreToGrade(percentage, scheme.data))
|
||||
letterGrade = GradeFormatHelper.replaceDashWithMinus(
|
||||
scoreToGrade(percentage, scheme.data, scheme.pointsBased)
|
||||
)
|
||||
}
|
||||
|
||||
let displayAsScaledPoints = false
|
||||
|
|
|
@ -42,7 +42,13 @@ type Message = {
|
|||
}
|
||||
|
||||
function normalizeSubmissionGrade(props: Props) {
|
||||
const {submission, assignment, enterGradesAs: formatType, gradingScheme} = props
|
||||
const {
|
||||
submission,
|
||||
assignment,
|
||||
enterGradesAs: formatType,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
} = props
|
||||
const gradeToNormalize = submission.enteredGrade
|
||||
|
||||
if (props.pendingGradeInfo && props.pendingGradeInfo.excused) {
|
||||
|
@ -59,6 +65,7 @@ function normalizeSubmissionGrade(props: Props) {
|
|||
defaultValue: '',
|
||||
formatType,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
pointsPossible: assignment.pointsPossible,
|
||||
version: 'entered',
|
||||
}
|
||||
|
@ -132,6 +139,7 @@ type Props = {
|
|||
disabled: boolean
|
||||
enterGradesAs: GradeEntryMode
|
||||
gradingScheme: GradingStandard[] | null
|
||||
pointsBasedGradingScheme: boolean
|
||||
onSubmissionUpdate: (submission: SubmissionData, gradeInfo: GradeResult) => void
|
||||
pendingGradeInfo: PendingGradeInfo
|
||||
submission: SubmissionData
|
||||
|
@ -147,6 +155,7 @@ export default class GradeInput extends Component<Props, State> {
|
|||
static defaultProps = {
|
||||
disabled: false,
|
||||
gradingScheme: null,
|
||||
pointsBasedGradingScheme: false,
|
||||
onSubmissionUpdate() {},
|
||||
pendingGradeInfo: null,
|
||||
submissionUpdating: false,
|
||||
|
@ -208,6 +217,7 @@ export default class GradeInput extends Component<Props, State> {
|
|||
const gradeInfo = parseTextValue(this.state.grade, {
|
||||
enterGradesAs: this.props.enterGradesAs,
|
||||
gradingScheme: this.props.gradingScheme,
|
||||
pointsBasedGradingScheme: this.props.pointsBasedGradingScheme,
|
||||
pointsPossible: this.props.assignment.pointsPossible,
|
||||
})
|
||||
|
||||
|
@ -241,6 +251,7 @@ export default class GradeInput extends Component<Props, State> {
|
|||
currentGradeInfo = parseTextValue(this.state.grade, {
|
||||
enterGradesAs: this.props.enterGradesAs,
|
||||
gradingScheme: this.props.gradingScheme,
|
||||
pointsBasedGradingScheme: this.props.pointsBasedGradingScheme,
|
||||
pointsPossible: this.props.assignment.pointsPossible,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ type Props = {
|
|||
}
|
||||
enterGradesAs: 'points' | 'percent' | 'passFail' | 'gradingScheme'
|
||||
gradingScheme: Array<Array<string | number>>
|
||||
pointsBasedGradingScheme: boolean
|
||||
submission: SubmissionData
|
||||
}
|
||||
|
||||
|
@ -40,6 +41,7 @@ export default function LatePolicyGrade(props: Props) {
|
|||
formatType: props.enterGradesAs,
|
||||
pointsPossible: props.assignment.pointsPossible,
|
||||
gradingScheme: props.gradingScheme,
|
||||
pointsBasedGradingScheme: props.pointsBasedGradingScheme,
|
||||
version: 'final',
|
||||
}
|
||||
const finalGrade = GradeFormatHelper.formatSubmissionGrade(props.submission, formatOptions)
|
||||
|
|
|
@ -116,6 +116,7 @@ export type SubmissionTrayProps = {
|
|||
onClose: () => void
|
||||
requireStudentGroupForSpeedGrader: boolean
|
||||
gradingScheme: null | GradingStandard[]
|
||||
pointsBasedGradingScheme: boolean
|
||||
onGradeSubmission: (submission: CamelizedSubmission, gradeInfo: GradeResult) => void
|
||||
onRequestClose: () => void
|
||||
selectNextAssignment: () => void
|
||||
|
@ -475,6 +476,7 @@ export default class SubmissionTray extends React.Component<
|
|||
disabled={this.props.gradingDisabled}
|
||||
enterGradesAs={this.props.enterGradesAs}
|
||||
gradingScheme={this.props.gradingScheme}
|
||||
pointsBasedGradingScheme={this.props.pointsBasedGradingScheme}
|
||||
pendingGradeInfo={this.props.pendingGradeInfo}
|
||||
onSubmissionUpdate={this.props.onGradeSubmission}
|
||||
submission={this.props.submission}
|
||||
|
@ -486,6 +488,7 @@ export default class SubmissionTray extends React.Component<
|
|||
assignment={this.props.assignment}
|
||||
enterGradesAs={this.props.enterGradesAs}
|
||||
gradingScheme={this.props.gradingScheme}
|
||||
pointsBasedGradingScheme={this.props.pointsBasedGradingScheme}
|
||||
submission={this.props.submission}
|
||||
/>
|
||||
</View>
|
||||
|
|
|
@ -63,6 +63,7 @@ ready(() => {
|
|||
isMasterCourse={ENV.BLUEPRINT_COURSES_DATA?.isMasterCourse}
|
||||
showImmersiveReader={ENV.SHOW_IMMERSIVE_READER}
|
||||
gradingScheme={ENV.GRADING_SCHEME}
|
||||
pointsBasedGradingScheme={ENV.POINTS_BASED}
|
||||
restrictQuantitativeData={ENV.RESTRICT_QUANTITATIVE_DATA}
|
||||
/>,
|
||||
courseContainer
|
||||
|
|
|
@ -54,6 +54,7 @@ const GradeDetails = ({
|
|||
userIsCourseAdmin,
|
||||
observedUserId,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
restrictQuantitativeData,
|
||||
}) => {
|
||||
const [loadingTotalGrade, setLoadingTotalGrade] = useState(true)
|
||||
|
@ -74,7 +75,8 @@ const GradeDetails = ({
|
|||
selectedGradingPeriodId,
|
||||
observedUserId,
|
||||
restrictQuantitativeData,
|
||||
gradingScheme
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme
|
||||
)
|
||||
const grades = getAssignmentGrades(assignmentGroups, observedUserId)
|
||||
const totalGrade = getTotalGradeStringFromEnrollments(
|
||||
|
@ -82,7 +84,8 @@ const GradeDetails = ({
|
|||
currentUser.id,
|
||||
observedUserId,
|
||||
restrictQuantitativeData,
|
||||
gradingScheme
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme
|
||||
)
|
||||
const include = ['assignments', 'submission', 'read_state', 'submission_comments']
|
||||
if (selectedGradingPeriodId) {
|
||||
|
@ -267,6 +270,7 @@ GradeDetails.propTypes = {
|
|||
userIsCourseAdmin: PropTypes.bool.isRequired,
|
||||
observedUserId: PropTypes.string,
|
||||
gradingScheme: PropTypes.array,
|
||||
pointsBasedGradingScheme: PropTypes.bool,
|
||||
restrictQuantitativeData: PropTypes.bool,
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ export const GradesPage = ({
|
|||
outcomeProficiency,
|
||||
observedUserId,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
restrictQuantitativeData,
|
||||
}) => {
|
||||
const [loadingGradingPeriods, setLoadingGradingPeriods] = useState(true)
|
||||
|
@ -119,6 +120,7 @@ export const GradesPage = ({
|
|||
userIsCourseAdmin={userIsCourseAdmin}
|
||||
observedUserId={observedUserId}
|
||||
gradingScheme={gradingScheme}
|
||||
pointsBasedGradingScheme={pointsBasedGradingScheme}
|
||||
restrictQuantitativeData={restrictQuantitativeData}
|
||||
/>
|
||||
</>
|
||||
|
@ -188,6 +190,7 @@ GradesPage.propTypes = {
|
|||
outcomeProficiency: outcomeProficiencyShape,
|
||||
observedUserId: PropTypes.string,
|
||||
gradingScheme: PropTypes.array,
|
||||
pointsBasedGradingScheme: PropTypes.bool,
|
||||
restrictQuantitativeData: PropTypes.bool,
|
||||
}
|
||||
|
||||
|
|
|
@ -451,6 +451,7 @@ export function K5Course({
|
|||
isMasterCourse,
|
||||
showImmersiveReader,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
restrictQuantitativeData,
|
||||
}) {
|
||||
const initialObservedId = observedUsersList.find(o => o.id === savedObservedId(currentUser.id))
|
||||
|
@ -667,6 +668,7 @@ export function K5Course({
|
|||
outcomeProficiency={outcomeProficiency}
|
||||
observedUserId={showObserverOptions ? observedUserId : null}
|
||||
gradingScheme={gradingScheme}
|
||||
pointsBasedGradingScheme={pointsBasedGradingScheme}
|
||||
restrictQuantitativeData={restrictQuantitativeData}
|
||||
/>
|
||||
)}
|
||||
|
@ -732,6 +734,7 @@ K5Course.propTypes = {
|
|||
isMasterCourse: PropTypes.bool.isRequired,
|
||||
showImmersiveReader: PropTypes.bool.isRequired,
|
||||
gradingScheme: PropTypes.array,
|
||||
pointsBasedGradingScheme: PropTypes.bool,
|
||||
restrictQuantitativeData: PropTypes.bool,
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ const GradeSummaryShape = {
|
|||
showTotalsForAllGradingPeriods: PropTypes.bool,
|
||||
showingAllGradingPeriods: PropTypes.bool,
|
||||
gradingScheme: PropTypes.array,
|
||||
pointsBasedGradingScheme: PropTypes.bool,
|
||||
restrictQuantitativeData: PropTypes.bool,
|
||||
}
|
||||
|
||||
|
@ -99,12 +100,13 @@ export const GradeSummaryLine = ({
|
|||
showTotalsForAllGradingPeriods,
|
||||
showingAllGradingPeriods,
|
||||
gradingScheme,
|
||||
pointsBasedGradingScheme,
|
||||
restrictQuantitativeData,
|
||||
}) => {
|
||||
let gradeText = grade
|
||||
let isPercentage = false
|
||||
if (restrictQuantitativeData) {
|
||||
gradeText = scoreToGrade(score, gradingScheme)
|
||||
gradeText = scoreToGrade(score, gradingScheme, pointsBasedGradingScheme)
|
||||
} else if (!grade) {
|
||||
if (score || score === 0) {
|
||||
gradeText = I18n.toPercentage(score, {
|
||||
|
|
|
@ -50,7 +50,7 @@ $(document).ready(function () {
|
|||
gradeToShow = '--'
|
||||
} else if (totals.grade || totals.grade === 0) {
|
||||
gradeToShow = totals.restrict_quantitative_data
|
||||
? scoreToGrade(totals.grade, totals.grading_scheme)
|
||||
? scoreToGrade(totals.grade, totals.grading_scheme, totals.points_based_grading_scheme)
|
||||
: totals.grade + '%'
|
||||
} else {
|
||||
gradeToShow = I18n.t('no grade')
|
||||
|
|
|
@ -62,7 +62,7 @@ export function FinalGradeOverrideTextBox({
|
|||
setFinalGradeOverridePercentage('')
|
||||
setInputValue('')
|
||||
} else if (gradingScheme && gradingScheme.data.length > 0) {
|
||||
const grade = scoreToGrade(percentage, gradingScheme.data)
|
||||
const grade = scoreToGrade(percentage, gradingScheme.data, gradingScheme.pointsBased)
|
||||
const inputVal = GradeFormatHelper.replaceDashWithMinus(grade)
|
||||
setInputValue(inputVal || '')
|
||||
if (!gradingScheme.pointsBased) {
|
||||
|
|
|
@ -39,6 +39,7 @@ export interface EnvAssignmentsA2StudentView {
|
|||
originality_reports_for_a2_enabled: boolean
|
||||
restrict_quantitative_data: boolean
|
||||
grading_scheme: any
|
||||
points_based: boolean
|
||||
|
||||
// Peer review data
|
||||
peer_review_available: boolean
|
||||
|
|
|
@ -31,7 +31,7 @@ import type {GradeType, DeprecatedGradingScheme, GradeEntryMode} from '../gradin
|
|||
|
||||
function schemeKeyForPercentage(percentage, gradingScheme: DeprecatedGradingScheme) {
|
||||
if (gradingScheme) {
|
||||
const grade = scoreToGrade(percentage, gradingScheme.data)
|
||||
const grade = scoreToGrade(percentage, gradingScheme.data, gradingScheme.pointsBased)
|
||||
return GradeFormatHelper.replaceDashWithMinus(grade)
|
||||
}
|
||||
return null
|
||||
|
|
|
@ -131,14 +131,14 @@ function formatPercentageGrade(score, options) {
|
|||
function formatGradingSchemeGrade(score, grade, options = {}) {
|
||||
let formattedGrade
|
||||
if (options?.restrict_quantitative_data && options.pointsPossible === 0 && score >= 0) {
|
||||
formattedGrade = scoreToGrade(100, options.gradingScheme)
|
||||
formattedGrade = scoreToGrade(100, options.gradingScheme, options.pointsBasedGradingScheme)
|
||||
} else if (options.pointsPossible) {
|
||||
const percent = scoreToPercentage(score, options.pointsPossible)
|
||||
formattedGrade = scoreToGrade(percent, options.gradingScheme)
|
||||
formattedGrade = scoreToGrade(percent, options.gradingScheme, options.pointsBasedGradingScheme)
|
||||
} else if (grade != null) {
|
||||
formattedGrade = grade
|
||||
} else {
|
||||
formattedGrade = scoreToGrade(score, options.gradingScheme)
|
||||
formattedGrade = scoreToGrade(score, options.gradingScheme, options.pointsBasedGradingScheme)
|
||||
}
|
||||
|
||||
return replaceDashWithMinus(formattedGrade)
|
||||
|
@ -219,6 +219,7 @@ const GradeFormatHelper = {
|
|||
// at this stage, gradingType is either points or percent, or the passed grade is a number
|
||||
formattedGrade = formatGradingSchemeGrade(options.score, null, {
|
||||
gradingScheme: options.grading_scheme,
|
||||
pointsBasedGradingScheme: options.points_based_grading_scheme,
|
||||
pointsPossible: options.pointsPossible,
|
||||
restrict_quantitative_data: options.restrict_quantitative_data,
|
||||
})
|
||||
|
@ -242,6 +243,7 @@ const GradeFormatHelper = {
|
|||
) {
|
||||
formattedGrade = formatGradingSchemeGrade(options.score, null, {
|
||||
gradingScheme: options.grading_scheme,
|
||||
pointsBasedGradingScheme: options.points_based_grading_scheme,
|
||||
pointsPossible: options.pointsPossible,
|
||||
restrict_quantitative_data: options.restrict_quantitative_data,
|
||||
})
|
||||
|
@ -255,6 +257,7 @@ const GradeFormatHelper = {
|
|||
) {
|
||||
formattedGrade = formatGradingSchemeGrade(options.score, null, {
|
||||
gradingScheme: options.grading_scheme,
|
||||
pointsBasedGradingScheme: options.points_based_grading_scheme,
|
||||
pointsPossible: options.pointsPossible,
|
||||
restrict_quantitative_data: options.restrict_quantitative_data,
|
||||
})
|
||||
|
|
|
@ -74,7 +74,7 @@ function parseAsGradingScheme(value: number, options): null | GradeInput {
|
|||
enteredAs: 'gradingScheme',
|
||||
percent: options.pointsPossible ? percentage : 0,
|
||||
points: options.pointsPossible ? pointsFromPercentage(percentage, options.pointsPossible) : 0,
|
||||
schemeKey: scoreToGrade(percentage, options.gradingScheme),
|
||||
schemeKey: scoreToGrade(percentage, options.gradingScheme, options.pointsBasedGradingScheme),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ function parseAsPercent(value: string, options): null | GradeInput {
|
|||
enteredAs: 'percent',
|
||||
percent,
|
||||
points,
|
||||
schemeKey: scoreToGrade(percent, options.gradingScheme),
|
||||
schemeKey: scoreToGrade(percent, options.gradingScheme, options.pointsBasedGradingScheme),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ function parseAsPoints(value: string, options): null | GradeInput {
|
|||
enteredAs: 'points',
|
||||
percent: null,
|
||||
points,
|
||||
schemeKey: scoreToGrade(percent, options.gradingScheme),
|
||||
schemeKey: scoreToGrade(percent, options.gradingScheme, options.pointsBasedGradingScheme),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -341,6 +341,7 @@ export type FormatGradeOptions = {
|
|||
score?: number | null
|
||||
restrict_quantitative_data?: boolean
|
||||
grading_scheme?: DeprecatedGradingScheme[]
|
||||
points_based_grading_scheme?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -52,6 +52,7 @@ export const transformGrades = courses =>
|
|||
isHomeroom: course.homeroom_course,
|
||||
enrollments: course.enrollments,
|
||||
gradingScheme: course.grading_scheme,
|
||||
pointsBasedGradingScheme: course.points_based_grading_scheme,
|
||||
restrictQuantitativeData: course.restrict_quantitative_data,
|
||||
}
|
||||
return getCourseGrades(basicCourseInfo)
|
||||
|
@ -173,7 +174,8 @@ export const getAssignmentGroupTotals = (
|
|||
gradingPeriodId,
|
||||
observedUserId,
|
||||
restrictQuantitativeData = false,
|
||||
gradingScheme = []
|
||||
gradingScheme = [],
|
||||
pointsBasedGradingScheme = false
|
||||
) => {
|
||||
if (gradingPeriodId) {
|
||||
data = data.filter(group =>
|
||||
|
@ -207,7 +209,7 @@ export const getAssignmentGroupTotals = (
|
|||
} else {
|
||||
const tempScore = (groupScores.current.score / groupScores.current.possible) * 100
|
||||
score = restrictQuantitativeData
|
||||
? scoreToGrade(tempScore, gradingScheme)
|
||||
? scoreToGrade(tempScore, gradingScheme, pointsBasedGradingScheme)
|
||||
: I18n.n(tempScore, {percentage: true, precision: 2})
|
||||
}
|
||||
|
||||
|
@ -232,6 +234,7 @@ const formatGradeToRQD = (assignment, submission) => {
|
|||
score: submission?.score,
|
||||
restrict_quantitative_data: ENV.RESTRICT_QUANTITATIVE_DATA,
|
||||
grading_scheme: ENV.GRADING_SCHEME,
|
||||
points_based_grading_scheme: ENV.POINTS_BASED,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -285,7 +288,8 @@ export const getTotalGradeStringFromEnrollments = (
|
|||
userId,
|
||||
observedUserId,
|
||||
restrictQuantitativeData = false,
|
||||
gradingScheme = []
|
||||
gradingScheme = [],
|
||||
pointsBasedGradingScheme
|
||||
) => {
|
||||
let grades
|
||||
if (observedUserId) {
|
||||
|
@ -300,7 +304,7 @@ export const getTotalGradeStringFromEnrollments = (
|
|||
return I18n.t('n/a')
|
||||
}
|
||||
if (restrictQuantitativeData) {
|
||||
return scoreToGrade(grades.current_score, gradingScheme)
|
||||
return scoreToGrade(grades.current_score, gradingScheme, pointsBasedGradingScheme)
|
||||
}
|
||||
const score = I18n.n(grades.current_score, {percentage: true, precision: 2})
|
||||
return grades.current_grade == null
|
||||
|
|
Loading…
Reference in New Issue