Newer
Older
const singleNumRegexp = /\w_(\d+)/;
const doubleNumReg = /.*_(\d+)_(\d+)$/;
class Base {
let found = singleNumRegexp.exec($cell.attr('id'));
return found ? parseInt(found[1]) : 0;
}
let found = singleNumRegexp.exec($cell.attr('class'));
return found ? parseInt(found[1]) : 0;
}
let [col, row] = doubleNumReg.exec($cell.attr('id')).splice(1, 2);
return [ parseInt(col), parseInt(row) ];
}
static parseSettings() {
let $discipline = $('#json_discipline');
settings.discipline = {};
let disciplineRaw = $.parseJSON($discipline.html() || '{}');
Object.keys(disciplineRaw).forEach((keyRaw) => {
let key = keyRaw.slice(0, 1).toLowerCase() + keyRaw.slice(1);
if (keyRaw == "ID") key = 'id';
let value = disciplineRaw[keyRaw];
settings.discipline[key] = value;
});
$discipline.remove();
return parseInt($cell.children('input').val() || def);
static filterNumbers($input) {
let scoreInputVal = $input.val();
let numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
scoreInputVal = Array.prototype.filter.call(scoreInputVal, chr => chr in numbers).join('');
$input.val(scoreInputVal);
}
}
class Cursor {
constructor() {
this.col = 0;
this.row = 0;
}
update(col, row) {
this.col = col;
this.row = row;
}
get() {
return [this.col, this.row];
}
parseLocation($cell) {
let [col, row] = Base.parsePosition($cell);
this.update(col, row);
}
isEmpty() {
return (this.col == 0) && (this.row == 0);
}
}
class Cell {
constructor() {
this.update(0, 0, 0);
}
update(student, submodule, maxRate) {
this.student = student;
this.submodule = submodule;
this.maxRate = maxRate;
}
}
class CellInfo {
constructor(cursor, cell) {
this.cursor = cursor;
this.cell = cell;
this.$modulesHead = $('#modulesHead');
this.$submodulesHead = $('#submodulesHead');
this.$submodulesMaxRate = $('#submodulesHeadMaxRate');
}
select($cell) {
this.cursor.parseLocation($cell);
let [col] = this.cursor.get();
let $curModuleHead = this.$modulesHead.children(`.col_${col}`);
let $curSubmoduleHead = this.$submodulesHead.children(`.col_${col}`);
let $curSubmoduleMaxRate = this.$submodulesMaxRate.children(`.col_${col}`);
let student = Base.parseid($cell.siblings('.name'));
let submodule = Base.parseid($curSubmoduleMaxRate);
let maxRate = parseInt($curSubmoduleMaxRate.text());
if ($cell.hasClass('extra')) {
maxRate -= Base.parseRate($cell.siblings('.semester'));
maxRate -= Base.parseRate($cell.prev('.extra'));
maxRate = Math.max(0, maxRate);
}
this.cell.update(student, submodule, maxRate);
}
reset() {
this.cell.update(0, 0, 0);
}
}
class RateInfo {
constructor(cursor, cell) {
this.cursor = cursor;
this.cell = cell;
this.$modulesHead = $('#modulesHead');
this.$submodulesHead = $('#submodulesHead');
this.$submodulesMaxRate = $('#submodulesHeadMaxRate');
this.$cellInfo = $('#cellInfo');
this.$studentInfo = this.$cellInfo.find('#student .value');
this.$submoduleInfo = this.$cellInfo.find('#submodule .value');
this.$rateInfo = this.$cellInfo.find('#maxRate .value');
}
let studentName = $cell.siblings('.name').text();
let submoduleTitle = this.$submodulesHead.children(`.col_${col}`).text();
this.$studentInfo.html(studentName);
this.$submoduleInfo.html(submoduleTitle);
this.$rateInfo.html(this.cell.maxRate);
this.$cellInfo.show();
}
hide() {
this.$cellInfo.hide();
}
}
class GroupFilter {
constructor(settings, $table, $selector) {
this.settings = settings;
this.$table = $table.children('tbody');
let groupFilter = JSON.parse(localStorage.groupFilter || "{}");
let groupid = groupFilter[this.settings.discipline.id] || 0;
$selector.children('[value=' + groupid + ']').prop('selected', true);
this.filterGroups(groupid);
let $trs = this.$table.children();
$trs.show();
if (groupid) {
$trs.not(`.group_${groupid}`).hide();
}
}
listen($selector) {
$selector.change(() => {
let groupid = parseInt($selector.val());
let groupFilter = JSON.parse(localStorage.groupFilter || "{}");
groupFilter[this.settings.discipline.id] = groupid;
localStorage.groupFilter = JSON.stringify(groupFilter);
});
}
}
class Rating {
constructor() {
this.settings = Base.parseSettings();
this.cell = new Cell();
this.cursor = new Cursor();
this.cellInfo = new CellInfo(this.cursor, this.cell);
this.rateInfo = new RateInfo(this.cursor, this.cell);
this.filter = new GroupFilter(this.settings, $('#studentsRate'), $('#groupSelector'));
this.Direction = {
Up: 0,
Right: 1,
Down: 2,
Left: 3
};
let keyDirs = {
13: this.Direction.Down, // enter
40: this.Direction.Down, // down arrow
38: this.Direction.Up, // up arrow
39: this.Direction.Right, // right arrow
37: this.Direction.Left // left arrow
};
let self = this;
let oldInputVal = '';
$('#studentsRate tbody').on('focusin', '.rate', function () {
$(this).children('input').select();
self.cellInfo.select($(this));
self.rateInfo.show($(this));
$(this).parents('tr').addClass('focus');
oldInputVal = $(this).children('input').val();
}).on('focusout', '.rate', function () {
self.rateInfo.hide($(this));
self.cellInfo.reset();
$(this).parents('tr').removeClass('focus');
}).on('keydown', '.rate', function (event) {
// Разрешаем нажимать только цифры
keyDownOnlyNumber(event);
if (key === 27) {
$(this).children('input').val(oldInputVal);
$(this).children('input').blur();
}
if (!(key in keyDirs)) {
return;
}
let direction = keyDirs[key];
let $cell = self.getDesiredCell(direction);
if ($cell.length !== 0) { // Если ячейка найдена
self.selectCell($cell);
$cell = $(this);
let scoreInputVal = $cell.children('input').val();
if (scoreInputVal !== oldInputVal) {
$cell.one('turnOn', () => self.selectCell($cell));
$cell.chlidren('input').blur();
} else {
self.selectCell($cell);
}
}
}).on('change', '.rate', function () {
Base.filterNumbers($(this).children('input'));
self.setRate($(this), oldInputVal);
}).on('change', '.checkbox', function () {
self.cellInfo.select($(this));
self.cellInfo.reset();
}).on('click', '.download button', function () {
$.fileDownload(URLdir + 'handler/FileCreator/GenerateFinalForm', {
httpMethod: 'POST',
data: {
'disciplineID': self.settings.discipline.id,
'groupID': Base.parseid($(this)),
'stage': parseInt($(this).siblings('select').val()),
},
});
});
}
getDesiredCell(direction) {
let [col, row] = this.cursor.get();
let $cell;
do {
if (direction == this.Direction.Left) col--;
if (direction == this.Direction.Right) col++;
if (direction == this.Direction.Up) row--;
if (direction == this.Direction.Down) row++;
$cell = $(`#col_row_${col}_${row}`);
} while ($cell.length && !$cell.hasClass('rate'));
selectCell($cell) {
$cell.children('input').focus();
// Выбрать весь текст в ячейке
setTimeout(() => $cell.children('input').select(), 0);
}
setRate($cell, oldInputVal) {
let scoreInputVal = $cell.children('input').val();
if (scoreInputVal == oldInputVal) return;
let rate = Base.parseRate($cell, true);
let successText;
let errorText;
if (scoreInputVal != '' && oldInputVal != '') {
successText = 'Балл обновлен';
errorText = 'Не удалось обновить балл';
} else if (scoreInputVal != '' && oldInputVal == '') {
successText = 'Балл добавлен';
errorText = 'Не удалось добавить балл';
} else {
successText = 'Балл удален';
errorText = 'Не удалось удалить балл';
}
this.sendRate($cell, 'handler/rating/SetRate', { rate }, $input => $input.val(oldInputVal),
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
setExam($cell) {
let optionVal;
if ($cell.hasClass('absence')) optionVal = 'absence';
if ($cell.hasClass('autopass')) optionVal = 'pass';
if (!$cell.children('input').prop('checked')) optionVal = `drop_${optionVal}`;
let successText;
let errorText;
let option;
switch (optionVal) {
case 'absence':
successText = 'Неявка установлена';
errorText = 'Не удалось установить неявку';
option = 'absence';
break;
case 'drop_absence':
successText = 'Неявка удалена';
errorText = 'Не удалось удалить неявку';
option = 'null';
break;
case 'pass':
successText = 'Автомат установлен';
errorText = 'Не удалось установить автомат';
option = 'pass';
break;
case 'drop_pass':
successText = 'Автомат удален';
errorText = 'Не удалось удалить автомат';
option = 'null';
break;
}
this.sendRate($cell, 'handler/rating/SetExamPeriodOption', { option },
$input => $input.prop("checked", !$input.prop("checked")), successText, errorText);
}
sendRate($cell, url, data, reset, successText, errorText) {
let $input = $cell.children('input');
data.studentID = this.cell.student;
data.disciplineID = this.settings.discipline.id;
data.submoduleID = this.cell.submodule;
$.postJSON(URLdir + url, data).success(() => {
this.recountScores($cell, data.submoduleID);
Popup.success(successText);
if (status != 400) throw null;
let message = JSON.parse(jqXHR.responseText).message;
if (!message) throw null;
Popup.error(message);
} catch (error) {
Popup.error(errorText);
recountScores($cell, submoduleID) {
let $сells = $cell.parent().children();
let [col, row] = Base.parsePosition($cell);
let examCol = Base.parseClass($(`#exam_${submoduleID}`));
let absenceCol = Base.parseClass($(`#absence_${submoduleID}`));
let autopassCol = Base.parseClass($(`#autopass_${submoduleID}`));
$сells.filter(`#col_row_${absenceCol}_${row}`).children('input').prop('checked', false);
$сells.filter(`#col_row_${autopassCol}_${row}`).children('input').prop('checked', false);
}
$сells.filter(`#col_row_${examCol}_${row}`).children('input').val('');
$сells.filter(`#col_row_${autopassCol}_${row}`).children('input').prop('checked', false);
}
$сells.filter(`#col_row_${examCol}_${row}`).children('input').val('');
$сells.filter(`#col_row_${absenceCol}_${row}`).children('input').prop('checked', false);
}
let $regularCells = $сells.filter('.regular');
if ($regularCells.length) {
let semesterRate = $regularCells.aggregate((init, elem) => init + Base.parseRate($(elem)));
$сells.filter('.semester').text(semesterRate);
}
let semesterRate = Base.parseRate($сells.filter('.semester'));
let bonusRate = Base.parseRate($сells.filter('.bonus'));
let extraRate = $сells.filter('.extra').aggregate((init, elem) => init + Base.parseRate($(elem)));
let examRate = $сells.filter('.exam').aggregate((init, elem) => Math.max(init, Base.parseRate($(elem))));
let rateResult = semesterRate + bonusRate + extraRate + examRate;
let rateResultText = (rateResult > 100) ? '100+' : rateResult;
$сells.filter('.result').text(rateResultText);
if ($cell.hasClass('extra')) {
let $nextExtraCell = $cell.next('.extra');
if ($nextExtraCell.length) {
let maxExtraRate = this.settings.discipline.type == 'exam' ? 38 : 60;
let curRate = Base.parseRate($cell, true);
let maxVal = maxExtraRate - semesterRate - curRate;
if (maxVal > 0 && curRate != -1) {
$nextExtraCell.find('input').attr('placeholder', 'макс. ' + maxVal);
} else {
$nextExtraCell.find('input').attr('placeholder', '–').val('');
}
}