GPA meter

A user script to show GPA on aims page

  1. // ==UserScript==
  2. // @name GPA meter
  3. // @namespace https://greasyfork.org/en/users/674736-jatin-sharma
  4. // @description A user script to show GPA on aims page
  5. // @include https://aims.iith.ac.in/aims/courseReg/myCrsHistoryPage*
  6. // @author Jatin Sharma (jatin.earth+greasyfork@gmail.com)
  7. // @version 0.4
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. /* jshint esversion: 6 */
  12. /* global $ */
  13.  
  14. (function () {
  15. 'use strict';
  16.  
  17. let exclude_list = [
  18. 'Minor Core',
  19. 'Honors Core',
  20. 'Honours project',
  21. 'Honours coursework',
  22. 'FCC',
  23. 'Additional',
  24. 'Audit',
  25. ];
  26.  
  27. const grade_values = {
  28. 'A+': 10,
  29. 'A' : 10,
  30. 'A-': 9,
  31. 'B' : 8,
  32. 'B-': 7,
  33. 'C' : 6,
  34. 'C-': 5,
  35. 'D' : 4,
  36. 'FR': 0,
  37. 'FS': 0
  38. };
  39. // console.log('Student ID: ', studentId);
  40.  
  41. let append_checkbox = (parent, is_checked) => {
  42. parent.append('<input style="float:right" class="cgpa-cal-check" type="checkbox" ' + (is_checked ? 'checked' : '') + ' />');
  43. };
  44.  
  45. let add_checkboxes = () => {
  46. let courses_checked = new Set();
  47. $(".cgpa-cal-check").remove();
  48. let elems = $(".hierarchyLi.dataLi").not(".hierarchyHdr, .hierarchySubHdr");
  49. elems.each((i, el) => {
  50. let course_id = el.children[0].textContent.trim();
  51. let type = el.children[4].textContent.trim();
  52. let grade = el.children[7].textContent.trim();
  53. let is_checked = !(courses_checked.has(course_id) || exclude_list.includes(type) || grade == "" || grade == "I");
  54. if (is_checked) courses_checked.add(course_id);
  55. append_checkbox($(el.children[0]), is_checked);
  56. });
  57. }
  58.  
  59. let add_courseCategoryDropdown = () => {
  60. let courseCategoryDropDown = `
  61. <select class="catSel" style="width: auto; background: aliceblue; border-radius: 5px">
  62. <option value="Additional">Additional</option>
  63. <option value="Audit">Audit</option>
  64. <option value="Liberal Arts Elective">Liberal Arts Elective</option>
  65. <option value="Departmental Core Laboratory">Departmental Core Laboratory</option>
  66. <option value="Departmental Elective">Departmental Elective</option>
  67. <option value="Departmental Core Theory">Departmental Core Theory</option>
  68. <option value="Basic Sciences">Basic Sciences</option>
  69. <option value="Professional Ethics">Professional Ethics</option>
  70. <option value="Seminar">Seminar</option>
  71. <option value="Thesis">Thesis</option>
  72. <option value="Basic Engineering Skills">Basic Engineering Skills</option>
  73. <option value="Free Elective">Free Elective</option>
  74. <option value="FCC">FCC</option>
  75. <option value="Creative Arts">Creative Arts</option>
  76. </select>`;
  77.  
  78. let elems = $(".hierarchyLi.dataLi").not(".hierarchyHdr, .hierarchySubHdr").children('.col5');
  79. $('.col5').css({ "width": "220px" });
  80. $('.col1').css({ "width": "75px" });
  81. $('.col4').css({ "width": "80px" });
  82. elems.each((i, el) => {
  83. let origCategory = el.innerText.trim();
  84. el.dataset.origCategory = origCategory;
  85. el.innerHTML = '';
  86. el.insertAdjacentHTML('afterbegin', courseCategoryDropDown);
  87. $(el.children[0]).val(origCategory).change();
  88. });
  89. $('.catSel').on('change', (e) => {
  90. let origCategory = e.target.parentElement.dataset.origCategory;
  91. if (e.target.value === origCategory) {
  92. e.target.style.backgroundColor = "aliceblue";
  93. e.target.removeAttribute('title');
  94. } else {
  95. e.target.style.backgroundColor = "mistyrose";
  96. e.target.title = `Orig: ${origCategory}`;
  97. }
  98.  
  99. });
  100. $('.catSel').tooltip();
  101. $('.catSel').tooltip('option', 'track', true);
  102. $('#courseHistoryUI .col8').attr('contenteditable','true');
  103. };
  104.  
  105.  
  106. let show_total_gpa = () => {
  107. $('#gpa_button').val('Calculating');
  108. $('#gpa_bar').remove();
  109. let cg_total_grades = 0;
  110. let cg_total_credits = 0;
  111. let total_credits = 0;
  112.  
  113. if ($(".cgpa-cal-check").length == 0) {
  114. add_checkboxes();
  115. add_courseCategoryDropdown();
  116. }
  117. let elems = $('.cgpa-cal-check:checked').parent().parent()
  118.  
  119. let categoryMap = {
  120. 'Departmental Core Theory': 0,
  121. 'Departmental Elective': 0,
  122. 'Free Elective': 0,
  123. 'Liberal Arts Elective': 0,
  124. 'Creative Arts': 0,
  125. 'Basic Sciences': 0,
  126. 'Basic Engineering Skills': 0,
  127. 'Additional': 0
  128. };
  129.  
  130.  
  131. let deptMap = {};
  132.  
  133. elems.each((i, el) => {
  134. let type = el.children[4].children[0].value;
  135.  
  136. let course_id = el.children[0].textContent.trim();
  137. let grade = el.children[7].textContent.trim();
  138. let credits = Number(el.children[2].textContent.trim());
  139. total_credits += credits;
  140. categoryMap[type] = credits + (categoryMap[type] || 0);
  141.  
  142. let deptId = course_id.slice(0, 2);
  143. deptMap[deptId] = credits + (deptMap[deptId] || 0);
  144.  
  145. if (grade in grade_values) {
  146. grade = grade_values[grade];
  147. cg_total_grades += credits * grade;
  148. cg_total_credits += credits;
  149. }
  150. });
  151. let gpa = (cg_total_grades / cg_total_credits).toFixed(2);
  152.  
  153. console.log(categoryMap);
  154. console.log(deptMap);
  155.  
  156. let generateRow = (title, val) => `<li class="hierarchyLi">
  157. <span class="" style="margin-left: 100px; width:300px">${title}</span>
  158. <span class="" style="margin-left: 400px;">${val}</span>
  159. </li>`;
  160.  
  161. $('#gpa_button').val('Show Gpa');
  162. $('#courseHistoryUI').before(
  163. `<ul id="gpa_bar" class="subCnt">
  164. <li class="hierarchyLi hierarchyHdr changeHdrCls">TOTAL GPA</li>
  165. ${generateRow('Total GPA of graded courses', gpa)}
  166. ${Object.entries(categoryMap).map((entry) => generateRow(entry[0], entry[1])).join('\n')}
  167. ${generateRow('Total credits', total_credits)}
  168. </ul>`);
  169. }
  170.  
  171. let get_course_changes_csv = () => `Course Code,Course Name,Credits,From Course Type,To Course Type,Semester\n`+
  172. $('.catSel')
  173. .filter( (i, el) => el.value !== el.parentElement.dataset.origCategory )
  174. .map((i, el) => ``+
  175. `${el.parentElement.parentElement.children[0].textContent.trim()},`+
  176. `${el.parentElement.parentElement.children[1].textContent.trim()},`+
  177. `${Number(el.parentElement.parentElement.children[2].textContent.trim())},`+
  178. `${el.parentElement.dataset.origCategory},`+
  179. `${el.value},`+
  180. `${el.parentElement.parentElement.parentElement.children[0].children[0].textContent.trim()}`)
  181. .get().reverse().join('\n');
  182.  
  183. $("#studentCourseSearch").before(
  184. `<input id="getcoursechanges_button" class="btn" title="Copy CSV of Course Type Changes to clipboard"`+
  185. `value="Copy Changes" style="padding: 5px 7px; margin-right:10px;" type="button"></input>`
  186. );
  187. $('#getcoursechanges_button').click(() => {
  188. let text = get_course_changes_csv();
  189. console.log(text);
  190. navigator.clipboard.writeText(text).then(function() {
  191. console.log('CSV Copied to clipboard');
  192. }, function(err) {
  193. console.error('Async: Could not copy text: ', err);
  194. alert('Could not copy to clipboard. Please find the CSV in your browser console');
  195. });
  196. });
  197.  
  198.  
  199. $("#studentCourseSearch").before(
  200. '<input id="gpa_button" class="btn" value="Show Gpa" style="padding: 5px 7px; margin-right:10px;" type="button"></input>'
  201. );
  202. $('#gpa_button').click(show_total_gpa);
  203. // console.log('All assets are loaded')
  204. })();