@universis/percentile-ranking
Version:
Percentile ranking is a vital part of any student information system. It indicates how well a student performed in comparison to the students in the specific norm group, for example, in the same grade, class, or graduation event. This package implements t
160 lines (158 loc) • 6.44 kB
JavaScript
class PercentileRanking {
constructor(grades) {
this.grades = grades;
this._gradeRank = new Map();
}
get grades() {
return this._grades;
}
set grades(gradeArray) {
this._grades = gradeArray;
}
/**
* This calculates the simple percentile rank of all the
* grades that were provided during the initialization
* of the object
*/
simplePercentileCalculation() {
this.grades.map(grade => {
this.calculateSingleSimpleRank(grade);
});
}
/**
* This calculates the complex percentile rank of all the
* grades that were provided during the initialization
* of the object
*/
complexPercentileCalculation() {
this.grades.map(grade => {
this.calculateSingleComplexRank(grade);
});
}
/**
* Given a grade, calculate the simple percentile rank for that grade
* It checks to see if the grade is already included in the initial grade
* array and if it is, it checks if there is already a value in the cached
* map. If not, it calculates the rank treating smaller and equal grades with
* the same coefficient.
* If the item isn't included in the initial array, it just creates a new array
* and adds the new item to that array instead of overwriting the initial and
* proceeds with the same calculation
* @param {Grades} item
*/
calculateSingleSimpleRank(item) {
if (this.grades.map(x => x.student).includes(item.student)) {
if (this._gradeRank.has(item.grade)) {
item.percentileRank = this._gradeRank.get(item.grade);
}
else {
item.percentileRank = this.grades.filter(x => x.grade <= item.grade).length / this.grades.length;
}
}
else {
let _grades = [...this.grades, item];
item.percentileRank = _grades.filter(x => x.grade <= item.grade).length / _grades.length;
}
this._gradeRank.set(item.grade, item.percentileRank);
}
/**
* Given a grade, calculate the simple percentile rank for that grade
* It checks to see if the grade is already included in the initial grade
* array and if it is, it checks if there is already a value in the cached
* map. If not, it calculates the rank treating smaller grades with
* the coefficient equal to 1 and the equal grades with a coefficient of 0.5.
* If the item isn't included in the initial array, it just creates a new array
* and adds the new item to that array instead of overwriting the initial and
* proceeds with the same calculation
* @param {Grades} item
*/
calculateSingleComplexRank(item) {
if (this.grades.map(x => x.student).includes(item.student)) {
if (this._gradeRank.has(item.grade)) {
item.percentileRank = this._gradeRank.get(item.grade);
}
else {
item.percentileRank = (this.grades.filter(x => x.grade < item.grade).length + (0.5 * this.grades.filter(x => x.grade === item.grade).length)) / this.grades.length;
}
}
else {
let _grades = [...this.grades, item];
item.percentileRank = (_grades.filter(x => x.grade < item.grade).length + (0.5 * _grades.filter(x => x.grade === item.grade).length)) / _grades.length;
}
this._gradeRank.set(item.grade, item.percentileRank);
}
/**
* Given a grades array, this calculates the simple percentile
* rank of all the grades that were provided
* @param {Array<Grades>} grades
*/
static simplePercentileCalculation(grades) {
let _gradeRank = new Map();
grades.map(grade => {
this.calculateSingleSimpleRank(grades, grade, _gradeRank);
});
}
/**
* Given a grades array, this calculates the complex percentile
* rank of all the grades that were provided
* @param {Array<Grades>} grades
*/
static complexPercentileCalculation(grades) {
let _gradeRank = new Map();
grades.map(grade => {
this.calculateSingleComplexRank(grades, grade, _gradeRank);
});
}
/**
* Given an array of grades, a grade, and an optional cache map,
* calculate the simple percentile rank of the given grade and
* save the result to the cache map.
* @param {Array<Grades>} grades
* @param {Grades} item
* @param {Map<number,number>} _gradeRank
*/
static calculateSingleSimpleRank(grades, item, _gradeRank) {
if (grades.map(x => x.student).includes(item.student)) {
if (_gradeRank && _gradeRank.has(item.grade)) {
item.percentileRank = _gradeRank.get(item.grade);
}
else {
item.percentileRank = grades.filter(x => x.grade <= item.grade).length / grades.length;
}
}
else {
let _grades = [...grades, item];
item.percentileRank = _grades.filter(x => x.grade <= item.grade).length / _grades.length;
}
if (_gradeRank) {
_gradeRank.set(item.grade, item.percentileRank);
}
}
/**
* Given an array of grades, a grade, and an optional cache map,
* calculate the complex percentile rank of the given grade and
* save the result to the cache map.
* @param {Array<Grades>} grades
* @param {Grades} item
* @param {Map<number, number>} _gradeRank
*/
static calculateSingleComplexRank(grades, item, _gradeRank) {
if (grades.map(x => x.student).includes(item.student)) {
if (_gradeRank && _gradeRank.has(item.grade)) {
item.percentileRank = _gradeRank.get(item.grade);
}
else {
item.percentileRank = (grades.filter(x => x.grade < item.grade).length + (0.5 * grades.filter(x => x.grade === item.grade).length)) / grades.length;
}
}
else {
let _grades = [...grades, item];
item.percentileRank = (_grades.filter(x => x.grade < item.grade).length + (0.5 * _grades.filter(x => x.grade === item.grade).length)) / _grades.length;
}
if (_gradeRank) {
_gradeRank.set(item.grade, item.percentileRank);
}
}
}
export { PercentileRanking };
//# sourceMappingURL=index.esm.js.map