journal.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /**
  2. * ЭЛЕКТРОННЫЙ ЖУРНАЛ «ШКАЛА»: ДНЕВНИК УЧАЩЕГОСЯ
  3. * Copyright © 2021, А.М.Гольдин. Modified BSD License
  4. */
  5. "use strict";
  6. // Объекты с предметами и учителями (подгружаются в конце страницы)
  7. let jrnSbList = {}, jrnThList = {};
  8. // Контент страницы - объект jrnArr:
  9. // {
  10. // "8Б-мальч_s410_ivanov": {
  11. // d601: ["Африка", "Учить реки", 8, "нн5"],
  12. // ...
  13. // }
  14. // ...
  15. // }
  16. // Для внеурочной деятельности (предмет s000) вместо кода предмета
  17. // в ключе будет код групы типа "23Б"
  18. let jrnArr = {};
  19. // Отображение контента по данному предмету-учителю на странице,
  20. // либо по всем предметам, если grSbTh == '' (первая опция селекта)
  21. const jrnContLoad = async () => {
  22. let cont;
  23. let grSbTh = dqs("#jrnSubj").value;
  24. // Если grSbTh == '', выдаем таблицу текущих отметок по всем предметам
  25. if (!grSbTh) {
  26. cont = "<table id='allSb'><tr><th>Предмет,&nbsp;учитель</th>";
  27. // Формируем заголовочную строку со списком учебных периодов,
  28. // заодно массив pers ключей нужных нам учебных периодов
  29. // (без дублирующих типа полугодия или учебного года)
  30. let pers = [], perstart = [];
  31. for (let period in DTSIT) {
  32. if (perstart.includes(DTSIT[period][2])) continue;
  33. perstart.push(DTSIT[period][2]);
  34. pers.push(period);
  35. cont += `<th>${DTSIT[period][0]}</th>`;
  36. }
  37. cont += "</tr>";
  38. // Цикл по всем предметам (один предмет - одна строка таблицы)
  39. for (let sbCode of Object.keys(jrnArr).sort((a,b) => {
  40. let x = a.split('_')[1].slice(1),
  41. y = b.split('_')[1].slice(1);
  42. return Number(x)-Number(y);
  43. })) {
  44. let sbCont = jrnArr[sbCode];
  45. let [grName, sbName, tchName] = sbCode.split('_'),
  46. gruppa = grName.includes('-') ? `${grName.split('-')[1]}; ` : '',
  47. subjStr = `${jrnSbList[sbName]}<br>${gruppa + jrnThList[tchName]}`;
  48. cont += `<tr><td>${subjStr}</td>`;
  49. // Объект отметок по данному предмету с ключами - кодами периодов
  50. let grads = {};
  51. for (let perCod of pers) grads[perCod] = '';
  52. for (let dtCod of Object.keys(sbCont).sort()) {
  53. let grArr = sbCont[dtCod];
  54. if (dtCod.length > 4) continue; // только текущие отметки
  55. if (grArr[3] == undefined) continue;
  56. let otm = grArr[3].toString().replace(/^999$/, "зач") + ' ';
  57. if (grArr[0].includes("Экзамен")) otm = `<b>${otm}</b>`;
  58. let perNum = whereis(dtCod); // число! whereis - в ini.js
  59. if (perNum == 99) continue;
  60. let period = Object.keys(DTSIT)[perNum - 1];
  61. if (grads[period] !== undefined) grads[period] += otm;
  62. }
  63. // Подписываем ячейки с отметками в строку таблицы
  64. for (let perCod of pers) cont += `<td>${grads[perCod].trim()}</td>`;
  65. cont += "</tr>";
  66. }
  67. dqs("#jrnCont").innerHTML = cont + "</table>";
  68. return;
  69. }
  70. // Если grSbTh != '', выдаем таблицу по выбранному предмету
  71. let grades = jrnArr[grSbTh] || {},
  72. wArr = ['0', '0.5', '', '1.5', '2.0', '2.5', '3.0', '3.5', '4.0'];
  73. cont = "<table><tr><th>Дата</th><th>Вес</th><th>Тема урока</th>"
  74. + "<th>Дом.&nbsp;задание</th><th>Отм.</th></tr>";
  75. if (!Object.keys(grades).length) {
  76. dqs("#jrnCont").innerHTML = "<b>Пока ничего нет.</b>";
  77. return;
  78. }
  79. let dates = Object.keys(grades).sort();
  80. for (let d of dates) {
  81. // Пропущенные (учителем) уроки не показываем
  82. if (grades[d][2] > 8) continue;
  83. let dt = dateConv(d), cls = '', stTd = '';
  84. let otm = (typeof grades[d][3] != "undefined") ? grades[d][3] : '';
  85. otm = otm.replace(/^999$/, "зач");
  86. if (grades[d][0].includes("Экзамен")) {
  87. cls = " class='it'";
  88. stTd = " style='color:black'";
  89. }
  90. if (d.length > 4) {
  91. dt = DTSIT[d][0];
  92. cls = " class='it'";
  93. otm = otm.toString().replace(/^0$/, "н/а");
  94. }
  95. cont += `<tr${cls}>`
  96. + `<td>${dt}</td><td${stTd}>${wArr[grades[d][2]]}</td>`
  97. + `<td>${grades[d][0]}</td><td>${grades[d][1]}</td>`
  98. + `<td>${otm}</td></tr>`;
  99. }
  100. dqs("#jrnCont").innerHTML = cont + "</table>";
  101. // Выводим статистику
  102. let stat = `<h3>Статистика</h3><table id="jrnStat"><tr><th> </th>`
  103. + `<th>Сумма баллов<br>(с учетом весов)</th>`
  104. + `<th>Средне&shy;взвешенный<br>балл</th>`
  105. + `<th>Пропущено<br>уроков</th></tr>`;
  106. // Цикл по периодам учебного года
  107. for (let itDate of Object.keys(DTSIT)) {
  108. // Cумма весов, сумма отметок с весами, среднее, пропуски
  109. let wSum = 0, sum = 0, av = 0, abs = 0;
  110. // Цикл по всем темам d601: ["Африка", "Учить реки", 8, "нн5"]
  111. for (let dt of Object.keys(grades)) {
  112. // Если дата хорошая и за эту дату есть отметки
  113. if (dt >= DTSIT[itDate][2] && dt <= DTSIT[itDate][3])
  114. if (grades[dt][3]) {
  115. let w = grades[dt][2], gFull = grades[dt][3];
  116. let gClear = gFull.replace(/н/g, ''); // без «н»
  117. abs += gFull.length - gClear.length; // к-во пропусков
  118. gClear = gClear.replace(/\s{2,}/g, ' ').trim();
  119. if (gClear) if (gClear != "999") {
  120. let gArr = gClear.split(' ');
  121. for (let x of gArr) {sum += Number(x) * w; wSum += w;}
  122. }
  123. }
  124. }
  125. if (wSum) av = (sum / wSum).toFixed(2);
  126. stat += `<tr><td>${DTSIT[itDate][1]}</td><td>${sum/2}</td>`
  127. + `<td>${av}</td><td>${abs}</td></tr>`;
  128. }
  129. dqs("#jrnCont").innerHTML += stat;
  130. }
  131. // Формирование контента страницы (селект для начала невидим в css)
  132. createSection("journal", `
  133. <select id="jrnSubj" onChange="jrnContLoad();"></select>
  134. <div id="jrnCont"><img src='static/preloader.gif'></div>
  135. `);
  136. // Динамически подгружаем контент страницы (имя метода = имени пункта меню!)
  137. getContent.journal = async () => {
  138. // Получаем глобальный объект со списком всех предметов
  139. // jrnSbList = {"s110": "Русский язык", ...}
  140. let apiResp = await apireq("subjList");
  141. let subjListDop = JSON.parse(apiResp);
  142. jrnSbList = {...subjDef, ...subjListDop};
  143. // Получаем глобальный объект с логинами и ФИО учителей
  144. // jrnThList = {"pupkin": "Пупкин В. И.", "ivanov": "Иванов И. И.", ...}
  145. apiResp = await apireq("teachList");
  146. let teachList = JSON.parse(apiResp);
  147. for (let teach of teachList) jrnThList[teach.login] = teach.fio;
  148. // Загружаем все отметки и пр. ученика с помощью API в массив jrnArr
  149. // (логин юзера не передаем, он подписывается API из данных авторизации)
  150. info(0, "Пожалуйста, дождитесь<br>загрузки данных.");
  151. apiResp = await apireq("jrnGet", []);
  152. info(2);
  153. if (apiResp == "none") {
  154. dqs("#jrnCont").innerHTML = "<b>Дневник пока пуст.</b>";
  155. return;
  156. }
  157. jrnArr = JSON.parse(apiResp);
  158. // Формируем список предметов и учителей в селекте и делаем его видимым
  159. let keysArr = Object.keys(jrnArr);
  160. if (!keysArr.length) {
  161. dqs("#jrnCont").innerHTML = "<b>Дневник пока пуст.</b>";
  162. return;
  163. }
  164. keysArr.sort((a, b) => {
  165. let aSb = a.split('_')[1], bSb = b.split('_')[1];
  166. if (aSb.length != bSb.length) return aSb.length < bSb.length ? 1 : -1;
  167. else if (aSb.length == 3) return aSb > bSb ? 1 : -1;
  168. else return aSb.substr(1, 3) > bSb.substr(1, 3) ? 1 : -1;
  169. });
  170. let selInn = "<option value=''>Текущие отметки (все предметы)</option>";
  171. for (let k of keysArr) {
  172. let kArr = k.split('_'),
  173. grName = kArr[0],
  174. subj = jrnSbList[kArr[1]],
  175. teach = jrnThList[kArr[2]];
  176. teach = grName.includes('-') ?
  177. `(${grName.split('-')[1]}; ${teach})` : `(${teach})`;
  178. selInn += `<option value="${k}">${subj} ${teach}</option>`;
  179. }
  180. dqs("#jrnSubj").innerHTML = selInn;
  181. dqs("#jrnSubj").style.display = "block";
  182. // Формируем контент страницы по данному предмету и учителю,
  183. // либо по всем предметам, если выбрана первая опция селекта
  184. jrnContLoad();
  185. }