254 lines
6.5 KiB
TypeScript
254 lines
6.5 KiB
TypeScript
import JsonUtils from '@/logic/utils/json-utils';
|
|
import {FormatUtils} from '@/logic/utils/format-utils';
|
|
import {CourseUtils} from '@/logic/utils/course-utils';
|
|
import Navigation from '@/components/navigation/navigation';
|
|
import {GPAUtils} from '@/logic/utils/gpa-utils';
|
|
import CacheUtils from '@/logic/utils/cache-utils';
|
|
|
|
/**
|
|
* Objects of this interface represent assignment grades.
|
|
*/
|
|
export interface Assignment
|
|
{
|
|
id: number
|
|
scoreId: number
|
|
type: string
|
|
typeId: number
|
|
description: string
|
|
time: number
|
|
complete: string
|
|
include: boolean
|
|
display: boolean
|
|
|
|
unread: boolean
|
|
|
|
scoreMax: number
|
|
score: number
|
|
|
|
gradingPeriod: number
|
|
}
|
|
|
|
export interface AssignmentType
|
|
{
|
|
id: number
|
|
name: string
|
|
|
|
weight: number
|
|
scoreMax: number
|
|
score: number
|
|
percent: number
|
|
assignmentCount: number
|
|
}
|
|
|
|
export default class Course
|
|
{
|
|
id: number;
|
|
assignmentsId: number;
|
|
name: string;
|
|
teacherName: string;
|
|
status: string;
|
|
rawAssignments: Assignment[];
|
|
|
|
rawLetterGrade?: string;
|
|
rawNumericGrade?: number;
|
|
|
|
level: string;
|
|
scaleUp: number;
|
|
|
|
grading:
|
|
{
|
|
method: string
|
|
weightingMap: {[index: string]: number}
|
|
}[];
|
|
|
|
computed:
|
|
{
|
|
termAssignments: Assignment[][]
|
|
allYearGrade: number
|
|
};
|
|
|
|
cache: CacheUtils = new CacheUtils();
|
|
|
|
/**
|
|
* Construct a course with a course json object
|
|
*
|
|
* @param courseJson Course json object
|
|
*/
|
|
constructor(courseJson: any)
|
|
{
|
|
this.id = courseJson.id;
|
|
this.assignmentsId = courseJson.assignmentsId;
|
|
this.name = FormatUtils.parseText(courseJson.name).trim();
|
|
this.teacherName = courseJson.teacherName;
|
|
this.status = courseJson.status;
|
|
|
|
this.rawLetterGrade = courseJson.letterGrade;
|
|
this.rawNumericGrade = courseJson.numericGrade;
|
|
|
|
// Other api issue
|
|
if (this.rawLetterGrade == '')
|
|
{
|
|
this.rawNumericGrade = undefined;
|
|
this.rawLetterGrade = undefined;
|
|
}
|
|
|
|
// Level and scaleUp
|
|
let level = CourseUtils.detectLevel(this.name);
|
|
if (level != undefined)
|
|
{
|
|
this.level = level.level;
|
|
this.scaleUp = level.scaleUp;
|
|
}
|
|
else this.level = 'Unknown';
|
|
|
|
this.grading = new Array(4);
|
|
}
|
|
|
|
/**
|
|
* Load in assignments data
|
|
*
|
|
* @param data Assignments data
|
|
*/
|
|
loadAssignments(data: any)
|
|
{
|
|
// Load assignments
|
|
// Parse json and filter it
|
|
this.rawAssignments = JsonUtils.filterAssignments(data);
|
|
|
|
// Sort by date (Latest is at 0)
|
|
this.rawAssignments.sort((a, b) => b.time - a.time);
|
|
|
|
// Filter assignments into terms
|
|
let termAssignments: Assignment[][] = [[], [], [], []];
|
|
let currentTerm = 0;
|
|
|
|
// Loop through it by time order
|
|
this.rawAssignments.forEach(a => termAssignments[a.gradingPeriod].push(a));
|
|
|
|
// Set computed data
|
|
this.computed = {termAssignments: termAssignments, allYearGrade: -1};
|
|
}
|
|
|
|
/**
|
|
* Is graded or not
|
|
*/
|
|
get isGraded(): boolean
|
|
{
|
|
// Skip future or past courses
|
|
if (this.status != 'active') return false;
|
|
|
|
// Skip courses without levels TODO: Ask for user input
|
|
if (this.level == 'None' || this.level == 'Unknown' || this.scaleUp == -1) return false;
|
|
|
|
// Skip courses without graded assignments
|
|
if (this.assignments.length == 0) return false;
|
|
|
|
// Skip if there are no grading scale
|
|
// if (course.grading.method == 'NOT_GRADED') return;
|
|
|
|
// Is graded
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Get assignments of the selected time
|
|
*/
|
|
get rawSelectedAssignments(): Assignment[]
|
|
{
|
|
let timeCode = Navigation.instance.getSelectedGradingPeriod();
|
|
|
|
// All year
|
|
if (timeCode == -1)
|
|
{
|
|
return this.rawAssignments;
|
|
}
|
|
|
|
// Specific time
|
|
return this.computed.termAssignments[timeCode];
|
|
}
|
|
|
|
/**
|
|
* Get graded assignments
|
|
*/
|
|
get assignments(): Assignment[]
|
|
{
|
|
return this.cache.get('Assignments', () =>
|
|
{
|
|
return this.rawSelectedAssignments.filter(a => a.complete == 'Complete');
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get letter grade
|
|
*/
|
|
get letterGrade(): string
|
|
{
|
|
return this.cache.get('LetterGrade', () =>
|
|
{
|
|
// Get scale
|
|
let scale = GPAUtils.findScale(this.numericGrade);
|
|
|
|
// Scale not found
|
|
return scale == undefined ? '--' : scale.letter;
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Get numeric grade
|
|
*/
|
|
get numericGrade(): number
|
|
{
|
|
return this.cache.get('NumericGrade', () =>
|
|
{
|
|
// Calculate
|
|
if (this.grading.method == 'PERCENT_TYPE')
|
|
{
|
|
return GPAUtils.getPercentTypeAverage(this, this.assignments);
|
|
}
|
|
else if (this.grading.method == 'TOTAL_MEAN')
|
|
{
|
|
return GPAUtils.getTotalMeanAverage(this.assignments);
|
|
}
|
|
else return -1;
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Get assignment types
|
|
*/
|
|
get assignmentTypes(): AssignmentType[]
|
|
{
|
|
return this.cache.get('AssignmentTypes', () =>
|
|
{
|
|
// Get all types
|
|
let types = this.assignments.map(a => a.type);
|
|
|
|
// Remove duplicates
|
|
types = types.filter((type, i, a) => a.indexOf(type) == i);
|
|
|
|
// Get total possible score for weight calculation
|
|
let totalScoreMax = this.assignments.reduce((sum, a) => sum + a.scoreMax, 0);
|
|
|
|
// For every type...
|
|
return types.map(type =>
|
|
{
|
|
// Get assignments of the type
|
|
let typeAssignments = this.assignments.filter(a => a.type == type);
|
|
|
|
// Count scores and max scores
|
|
let score = typeAssignments.reduce((sum, a) => sum + a.score, 0);
|
|
let scoreMax = typeAssignments.reduce((sum, a) => sum + a.scoreMax, 0);
|
|
|
|
// Calculate weight
|
|
let weight = this.grading.method == 'PERCENT_TYPE'
|
|
? this.grading.weightingMap[type] : scoreMax / totalScoreMax;
|
|
|
|
// Return
|
|
return {name: type, id: typeAssignments[0].typeId, weight: +(weight * 100).toFixed(2),
|
|
scoreMax: scoreMax, score: score, percent: +(score / scoreMax * 100).toFixed(2),
|
|
assignmentCount: typeAssignments.length}
|
|
})
|
|
})
|
|
}
|
|
}
|