Advertisement
Guest User

Untitled

a guest
Nov 24th, 2014
156
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.63 KB | None | 0 0
  1. // ==UserScript==
  2. // @name AugmentedPASS
  3. // @author the.dw.coder
  4. // @version 2.1
  5. // @description View PolyRatings in PASS
  6. // @include http://pass.calpoly.edu/main.html
  7. // @include http://pass.calpoly.edu/saved.html
  8. // @require http://code.jquery.com/jquery-1.9.0.min.js
  9. // @grant GM_getResourceText
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // ==/UserScript==
  13.  
  14. function main() {
  15. var COLOR = {
  16. 'SAFE': "#00CC00",
  17. 'WARN': "#FFDD00",
  18. 'FULL': "#CC0000",
  19. 'CNCL': "#AAAAAA"
  20. },
  21. PASS_PAGE = {
  22. '0': {
  23. 'finals': true
  24. },
  25. '1': {
  26. 'topSelector': 'div.select-course',
  27. 'selector': 'table.no-bg tbody tr',
  28. 'name': 4,
  29. 'avail': 5,
  30. 'taken': 6,
  31. 'length': 14,
  32. 'ignoreFirst': true,
  33. 'finals': false
  34. },
  35. '2': {
  36. 'topSelector': 'table.schedule-table',
  37. 'selector': 'tbody tr',
  38. 'name': 6,
  39. 'avail': 3,
  40. 'taken': 4,
  41. 'length': 11,
  42. 'ignoreFirst': false,
  43. 'finals': false,
  44. 'type': 2
  45. },
  46. '3': {
  47. 'topSelector': 'div.saveSchedule',
  48. 'selector': 'table.schedule-table tbody tr',
  49. 'name': 6,
  50. 'avail': 3,
  51. 'taken': 4,
  52. 'length': 11,
  53. 'ignoreFirst': false,
  54. 'finals': true,
  55. 'type': 2,
  56. 'days': 7,
  57. 'start': 8,
  58. 'classSelector': 'th:first-child',
  59. 'grid': 'div.largeScheduleTable',
  60. 'weekly': true
  61. },
  62. 'saved': {
  63. 'topSelector': 'div.savedSchedule',
  64. 'selector': 'table.schedule-table tbody tr',
  65. 'name': 6,
  66. 'avail': 3,
  67. 'taken': 4,
  68. 'length': 11,
  69. 'ignoreFirst': false,
  70. 'finals': true,
  71. 'type': 2,
  72. 'days': 7,
  73. 'start': 8,
  74. 'classSelector': 'th:first-child',
  75. 'grid': 'div.largeScheduleTable',
  76. 'weekly': true
  77. }
  78. },
  79. THRESHOLD = 0.25,
  80. professors = [],
  81. profArchive = [],
  82. xmlData = JSON.parse(GM_getValue("AugmentedPASS.database"));
  83.  
  84. if (document.URL.indexOf('saved.html') >= 0) {
  85. processPASS('saved');
  86. } else {
  87. processPASS($('.steps .list-plain .active').index());
  88. }
  89.  
  90. function fillRows(pageInfo) {
  91. var hook = $(pageInfo.topSelector),
  92. name = pageInfo.name,
  93. aval = pageInfo.avail,
  94. take = pageInfo.taken,
  95. leng = pageInfo.length,
  96. type = pageInfo.type,
  97. ignoreFirst = pageInfo.ignoreFirst,
  98. i,
  99. avail,
  100. taken,
  101. orig,
  102. process,
  103. str,
  104. color,
  105. merged,
  106. row,
  107. classes = [];
  108.  
  109. if (pageInfo.finals) {
  110. var INIT = 2013,
  111. Q_OFFSET = {'fall': 0, 'winter' : 1, 'spring' : 2},
  112. QUARTER = $('.pageTitleQuarter').text(),
  113. YEAR = new Date().getFullYear(),
  114. T_OFFSET;
  115.  
  116. YEAR = YEAR.toString().substring(0, 2) + QUARTER[2];
  117. QUARTER = QUARTER[1];
  118.  
  119. if (QUARTER == 'winter' || QUARTER == 'spring')
  120. YEAR--; // winter and spring quarter are within the same academic year
  121.  
  122. T_OFFSET = 3 * (YEAR - INIT) + Q_OFFSET[QUARTER]; // number of quarters since Fall 2013
  123.  
  124. mon = 2 * Q_OFFSET[QUARTER];
  125. tue = T_OFFSET % 2 == 0 ? 1 : 3;
  126. wed = T_OFFSET % 2 == 0 ? 2 - Q_OFFSET[QUARTER] : 4;
  127. thu = T_OFFSET % 2 == 0 ? 3 : 1;
  128. fri = T_OFFSET % 2 == 0 ? 4 - Q_OFFSET[QUARTER] : 0;
  129.  
  130. var day_offset = [mon, tue, wed, thu, fri],
  131. TIME = ['7','10','13','16','19'],
  132. REGEXES = [
  133. /^(?:M|W|F){2,3}7:(?:1|4)0 AM/, /^(?:M|W|F){2,3}10:10 AM/, /^(?:M|W|F){2,3}1:10 PM/, /^(?:M|W|F){2,3}4:(?:10|40) PM/, /^(?:M|W|F){2,3}(?:7|8):10 PM/,
  134. /^TR7:(?:1|4)0 AM/, /^TR9:(?:1|4)0 AM/, /^TR12:10 PM/,/^TR2:10 PM/, /^(?:T5:10 PM)|(?:TR?6:10 PM)|(TR?7:10 PM)/,
  135. /^(?:M|W|F){2,3}8:10 AM/, /^(?:M|W|F){2,3}11:10 AM/, /^(?:M|W|F){2,3}2:10 PM/, /^M(?:W|F){0,2}5:(?:1|4)0 PM/, /^(W(?:5|6|7|8):10 PM)|(?:TR8:10 PM)/,
  136. /^TR8:10 AM/ ,/^TR10:10 AM/ ,/^TR1:(?:1|4)0 PM/ ,/^TR3:10 PM/ ,/^T?R4:(?:1|4)0 PM/,
  137. /^(?:M|W|F){2,3}9:10 AM/ ,/^(?:M|W|F){2,3}12:10 PM/ ,/^(?:M|W|F){2,3}3:10 PM/ ,/^(?:M|W|F){1,3}6:10 PM/ ,/^(?:R(?:4|5|6|7):10 PM)|(?:TR5:(?:1|4)0 PM)/
  138. ];
  139. }
  140.  
  141. for (i = 0; i < hook.length; i++) {
  142. rows = $(hook[i]).find(pageInfo.selector);
  143. classes.push([]);
  144.  
  145. for (j = 0; j < rows.length; j++) {
  146. row = $(rows[j]).find('td')
  147.  
  148. if (row.length < pageInfo.length) {
  149. continue;
  150. } else if (pageInfo.ignoreFirst && row.length == pageInfo.length) {
  151. merged = $(rows[j - 1]).find('td:first-child');
  152. merged = $.merge(merged, row);
  153. row = merged;
  154. }
  155.  
  156. if (row[name].textContent.indexOf(',') != -1 || row[name].textContent == "STAFF") {
  157. avail = parseInt(row[aval].textContent);
  158. taken = parseInt(row[take].textContent);
  159.  
  160. if (row[name].textContent != 'STAFF') {
  161. orig = row[name].textContent;
  162. process = processName(orig);
  163.  
  164. if (professors.indexOf(process) == -1) {
  165. professors.push(process);
  166. str = buildString(findInfo(xmlData, orig), process, false);
  167. row[name].innerHTML = str;
  168. profArchive.push(str);
  169. } else {
  170. row[name].innerHTML = profArchive[professors.indexOf(process)];
  171. }
  172. }
  173.  
  174. if (avail == 0 && taken == 0) {
  175. color = COLOR.CNCL;
  176. $(row).css('opacity','.35');
  177. }
  178. else if (avail == 0)
  179. color = COLOR.FULL;
  180. else if ((avail/ (avail+taken)) >= THRESHOLD)
  181. color = COLOR.SAFE;
  182. else
  183. color = COLOR.WARN;
  184.  
  185. if (ignoreFirst) {
  186. row.splice(0, 1);
  187. }
  188.  
  189. $(row).css('background-color', color);
  190.  
  191. if (pageInfo.finals && row[type].textContent == 'LEC') {
  192. className = $(rows[j]).find(pageInfo.classSelector).text().replace(' ', '');
  193.  
  194. meeting = row[pageInfo.days].textContent
  195. starts = row[pageInfo.start].textContent
  196.  
  197. if (meeting.length >= 4)
  198. hash = "MWF" + starts
  199. else
  200. hash = meeting + starts
  201.  
  202. var ctr = 0;
  203. do {
  204. var res = REGEXES[ctr++].exec(hash);
  205. } while(res == undefined && ctr < REGEXES.length);
  206.  
  207. if (res) {
  208. begin = TIME[(-1 + ctr)%5]
  209. if (begin == 19)
  210. wod = parseInt((ctr - 1) / 5)
  211. else
  212. wod = day_offset[parseInt((ctr - 1) / 5)]
  213.  
  214. classes[i].push([className, begin, wod])
  215. }
  216. }
  217. }
  218. }
  219. }
  220.  
  221. return classes;
  222. }
  223.  
  224. function processPASS(page) {
  225. var pageInfo = PASS_PAGE[page],
  226. classes;
  227.  
  228. classes = fillRows(PASS_PAGE[page]);
  229.  
  230. if (pageInfo.finals) {
  231. var DAYS = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
  232. HOUR_RANGE_LOW = 7,
  233. HOUR_RANGE_HIGH = 22,
  234. FINAL_LENGTH = 6,
  235. wrapper,
  236. finals;
  237.  
  238. weeklySchedules = $(pageInfo.topSelector);
  239.  
  240. wrapper = $('<div class="largeScheduleTable clearfix"></div>');
  241. finals = $('<table><thead><tr><th></th></tr></thead></table>').attr('class', 'finals-schedule');
  242.  
  243. for (i = 0, hdr = finals.find('thead tr'); i < DAYS.length; i++) {
  244. hdr.append('<th>' + DAYS[i] + '</th>')
  245. }
  246.  
  247. finalsBody = $('<tbody></tbody>')
  248. curHour = formattedHour(HOUR_RANGE_LOW)
  249.  
  250. for (hour = HOUR_RANGE_LOW; hour < HOUR_RANGE_HIGH; hour++) {
  251. nextHour = formattedHour(hour + 1)
  252.  
  253. hourRow = $('<tr><td>'+curHour[0]+':00'+curHour[1]+' - '+curHour[0]+':30'+curHour[1]+
  254. '</td><td><td></td><td></td><td></td><td></td></tr>')
  255. finalsBody.append(hourRow)
  256.  
  257. hourRow = $('<tr><td>'+curHour[0]+':30'+curHour[1]+' - '+nextHour[0]+':00'+nextHour[1]+
  258. '</td><td></td><td></td><td></td><td></td><td></td></tr>')
  259. finalsBody.append(hourRow)
  260. curHour = nextHour
  261. }
  262.  
  263. finals.append(finalsBody);
  264. wrapper.append(finals);
  265.  
  266. var btnList = $('<div style="padding-top:20px;">' +
  267. '<a class="btn weekly no-select" href="javascript:;" style="border:1px solid gray; margin-right:10px;">WEEKLY</a>' +
  268. '<a class="btn finals no-select" href="javascript:;" style="border:1px solid gray;">FINALS</a>' +
  269. '</div>');
  270.  
  271. for (i = 0; i < classes.length; i++) {
  272. section = $(weeklySchedules[i])
  273. section.find('p.grid-view-toggle').remove();
  274.  
  275. weeklySchedule = section.find(pageInfo.grid)
  276. $(weeklySchedule).attr('id', 'weekly-' + i);
  277.  
  278. gridView = wrapper.clone();
  279. $(gridView).attr('id', 'finals-' + i);
  280. allTd = $(gridView.find('td'));
  281.  
  282. for (exam = 0; exam < classes[i].length; exam++) {
  283. time = 2*(classes[i][exam][1] - HOUR_RANGE_LOW)
  284. day = classes[i][exam][2] + 1
  285. for (dur = 0; dur < FINAL_LENGTH; dur++) {
  286. location = day + ((time+dur)*(DAYS.length + 1))
  287. $(allTd[location]).text(classes[i][exam][0]).attr('class', 'filled')
  288. }
  289. }
  290.  
  291. buttons = btnList.clone();
  292. section.append(buttons);
  293. section.append(gridView);
  294. section.append(weeklySchedule);
  295.  
  296. wkly = buttons.find('.weekly').attr('id', 'weekly-view-' + i);
  297. fnls = buttons.find('.finals').attr('id', 'finals-view-' + i);
  298.  
  299. (function(i) {
  300. $('#weekly-view-' + i).on("click", function() {
  301. if (!$(this).hasClass('btn-gray')) {
  302. $(this).addClass('btn-gray');
  303. $('#finals-view-' + i).removeClass('btn-gray');
  304. $('#finals-' + i).hide();
  305. $('#weekly-' + i).show();
  306. }
  307. else {
  308. $(this).removeClass('btn-gray');
  309. $('#weekly-' + i).hide();
  310. }
  311. return false;
  312. });
  313.  
  314. $('#finals-view-' + i).on("click", function() {
  315. if (!$(this).hasClass('btn-gray')) {
  316. $(this).addClass('btn-gray');
  317. $('#weekly-view-' + i).removeClass('btn-gray');
  318. $('#weekly-' + i).hide();
  319. $('#finals-' + i).show();
  320. }
  321. else {
  322. $(this).removeClass('btn-gray');
  323. $('#finals-' + i).hide();
  324. }
  325. return false;
  326. });
  327. })(i);
  328.  
  329. weeklySchedule.hide();
  330. gridView.hide();
  331. }
  332. }
  333. }
  334.  
  335. function formattedHour(num) {
  336. var h = num > 12 ? num % 12 : num;
  337. var t = num >= 12 ? " pm" : " am";
  338. return [h, t];
  339. }
  340.  
  341. function buildString(data, name, oneLine) {
  342. var str;
  343.  
  344. if (data != undefined) {
  345. str = "<a href=\"http://www.polyratings.com/eval.phtml?profid="+data.i+"\" target=\"_blank\">"+name+"</a>";
  346. if (!oneLine) {
  347. str += "<br>";
  348. }
  349. str += "&nbsp<b><font size=2>" + data.g + "</b> (" + data.e + ")</font>";
  350. } else {
  351. str = "<a href=\"https://www.google.com/search?btnI=I%27m+Feeling+Lucky&q="+name+"+site:polyratings.com\" target=\"_blank\">"+name+"</a>";
  352. }
  353.  
  354. return str;
  355. }
  356.  
  357. function processName(name) {
  358. var idx = name.indexOf(",");
  359. var sp = name.indexOf(" ");
  360. if (sp != -1) {
  361. if (sp < idx) {
  362. name = name.substring(idx+1) + " " + name.substring(0,idx);
  363. }
  364. else {
  365. name = name.substring(idx+1,sp+1) + name.substring(0,idx);
  366. }
  367. }
  368. else {
  369. name = name.substring(idx+1) + " " + name.substring(0,idx);
  370. }
  371. return name;
  372. }
  373.  
  374. function findInfo(xmlData, name) {
  375. name = name.toLowerCase()
  376.  
  377. var loc = name.indexOf(','),
  378. lookup;
  379.  
  380. do {
  381. lookup = name.substring(0, ++loc);
  382. } while (xmlData[lookup] == undefined && loc < name.length);
  383.  
  384. return xmlData[lookup];
  385. }
  386. }
  387.  
  388. function updateDatabase(forceUpdate) {
  389. response = updateDatabaseHelper(forceUpdate);
  390. if (response) {
  391. $('#update-overlay').fadeOut(2000);
  392. footer = $('<span id="this-thing"></span>');
  393. footer.text(response);
  394. footer.css({'background-color':'#006400',
  395. 'color':'white',
  396. 'padding':'7px',
  397. 'position':'fixed',
  398. 'bottom':0,
  399. 'left':0,
  400. 'right':0});
  401. $('body').append(footer);
  402. $(document).ready(function() {
  403. footer.fadeOut(15000);
  404. })
  405. }
  406. }
  407.  
  408. function updateDatabaseHelper(forceUpdate) {
  409. if (GM_getValue("AugmentedPASS.databaseVersion") == undefined) {
  410. GM_setValue("AugmentedPASS.databaseVersion", -1);
  411. }
  412.  
  413. if (GM_getValue("AugmentedPASS.lastCheck") == undefined) {
  414. GM_setValue("AugmentedPASS.lastCheck", -1);
  415. }
  416.  
  417. var time = new Date().getTime(),
  418. lastCheck = GM_getValue("AugmentedPASS.lastCheck");
  419.  
  420. if (forceUpdate || time - lastCheck > 604800000) {
  421. $('body').append('<div id="update-overlay" style="position:fixed;top:0;left:0;bottom:0;right:0;background-color:rgba(0,0,0,.5);">'+
  422. '<span style="position:fixed;color:white;font-size:100px;">Updating...</span>'+
  423. '</div>');
  424.  
  425. GM_setValue("AugmentedPASS.lastCheck", time.toString());
  426.  
  427. var req = new XMLHttpRequest();
  428. req.open("GET", "https://dl.dropboxusercontent.com/s/ox38v18b03ktzcg/prversion.txt", false);
  429. req.send();
  430.  
  431. if (req.status != 200) {
  432. return 'There were problems trying to get the latest version';
  433. }
  434.  
  435. var version = JSON.parse(req.response)['version'];
  436.  
  437. if (forceUpdate || version > GM_getValue("AugmentedPASS.databaseVersion")) {
  438. req = new XMLHttpRequest();
  439. req.open("GET","https://dl.dropboxusercontent.com/s/7jcutcmreqothv2/polyratings.json",false);
  440. req.send();
  441.  
  442. if (req.status != 200) {
  443. return 'There were problems trying to update to the latest version';
  444. }
  445.  
  446. GM_setValue("AugmentedPASS.databaseVersion", version);
  447. GM_setValue("AugmentedPASS.database", req.responseText);
  448.  
  449. return "The ratings have been updated";
  450. }
  451. else {
  452. return "No new version";
  453. }
  454. }
  455. else {
  456. return false;
  457. }
  458. }
  459.  
  460. $(document).ready(function() {
  461. $('head').append('<style> .qtip-content { font-family:Arial; font-size:9pt; } .no-select { user-select:none; -moz-user-select:none; -webkit-user-select:none; }</style>');
  462. updateDatabase(false);
  463. main();
  464. });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement