|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Функция электронного деканата состоит в хранении и обработке информации о ходе учебного процесса и его участниках, а также автоматизации взаимодействия между тремя участниками учебного процесса по электронной форме обучения: администрация – преподаватель – студент. Электронный деканат должен обеспечивать организацию процесса обучения, а именно:
Задачи электронного деканата:
Начальным этапом разработки системы «Электронный деканат» является, во-первых, определение целей и задач, выполняемых системой, во-вторых, разработка плана действий по их достижению. Имея точно сформулированные цели и задачи, можно приступать к проектированию структуры базы данных и всей системы в целом. Рассмотрим этапы создания программы на ступени разработки алгоритмов. База данных представляет собой книгу формата Excel, в которой для каждого студента заводится запись, содержащая разрешенную личную информацию, накапливающаяся в процессе прохождения обучения (учебный план, оценки за сессию, результаты аттестаций, приказы и даты приказов об отчислении, восстановлении, академическом отпуске, переводе) (см. рис. 2). Рисунок 2. Общая схема работы приложения Уделим особое внимание основным алгоритмам, разработанным для реализации описанной системы. Формирование отчета об успеваемости студентовФормирование отчета об успеваемости студентов состоит из двух этапов: обработка информации, предварительное формирование отчета об успеваемости (анализ электронных ведомостей и оценок) и файлов в формате Excel на основе полученных данных. На первом этапе происходит анализ всех электронных ведомостей за запрашиваемый период, проверяется каждая оценка у всех студентов. Если оценка не является удовлетворительной, то информация о студенте и предмете заносится в переменную формата json, она представляет собой «дерево» со следующей структурой:
Запись о студенте удаляется, если он получил оценку удовлетворительно и выше. На втором этапе обрабатывается полученный результат, каждый студент из списка проверяется, был ли он отчислен, на какой основе обучается студент (платной или бюджетной), создаются файлы формата excel для каждой кафедры. В каждый из файлов записывается информация о группах и студентах, имеющих академические задолженности. Студенты, находящиеся в академическом отпуске, и отчисленные студенты в отчет не попадают. Для написания программ электронного документооборота используются объектно-ориентированные языки программирования с использованием программной платформы Microsoft .NET Framework, такие как C++, Python и Java. В таблице 1 приведено сравнение возможностей этих языков. Таблица 1. Сравнение возможностей языков программирования
Все выбранные языки программирования являются объектно-ориентированными. Поддержка динамической и неявной типизации необходима, так как при динамической типизации переменные и параметры методов/функций связываются с типами в момент присваивания значения, а не в момент объявления переменной или параметра. Одна и та же переменная в разные моменты может хранить значения разных типов. При неявной типизации типы переменных и параметров не указываются явно. Неявная типизация может быть и статической, в таком случае типы переменных и параметров вычисляются компилятором. Следующая возможность, как сборка мусора, является нужной для использования, можно будет автоматически освобождать память в куче, занятой неиспользуемыми объектами. Поддержка try/catch является необходимой потому, что при возникновении ошибок они будут перехвачены в блоке catch. Наличие блока finally также важно, так как он выполняется после выхода из блока try/catch, и, как было указано ранее, если подключение не произошло и соединение с ним осталось открытым, то в блоке finally обрабатывается закрытие соединения с базой данных. Его преимуществом является то, что он выполняется всякий раз, когда происходит выход из блока try/catch. Конструкция foreach предоставляет простой способ перебора массивов. Foreach работает только с массивами и объектами и будет генерировать ошибку при попытке использования с переменными других типов или неинициализированными переменными. В программе этот цикл используется для перебора элементов списка. Возможность именованных параметров была выбрана для того, чтобы можно было менять местами параметры при передаче их методу, указывая имя того параметра, которому присваивается значение. Значение параметров по умолчанию было выбрано для того, чтобы задавать по умолчанию некоторые параметры методов и опускать их при вызове этих методов. Статическая типизация и перегрузка функций были не так важны при выборе языка программирования. Исходя из анализируемых данных из таблицы сделаем предварительный вывод, что для решения поставленной задачи целесообразно использовать язык программирования Python. Java и C++ можно рассматривать как два языка – потомка C, разработанных из различных соображений и пошедших вследствие этого по разным путям. В связи с этим представляет интерес сравнение данных языков. СинтаксисC++ сохраняет совместимость с C, насколько это возможно. Java сохраняет внешнее подобие C и C++, но в действительности сильно отличается от них – из языка удалено большое число синтаксических средств, объявленных необязательными. В результате программы на Java бывают более громоздки по сравнению с их аналогами на С++. С другой стороны, Java проще, что облегчает как изучение языка, так и создание трансляторов для него. Исполнение программыJava-код компилируется в промежуточный код, который в дальнейшем интерпретируется или компилируется, тогда как C++ изначально ориентирован на компиляцию в машинный код заданной платформы. Это уже определяет разницу в сферах применения языков: Java вряд ли может быть использован при написании таких специфических программ, как драйверы устройств или низкоуровневые системные утилиты. Механизм исполнения Java делает программы, даже откомпилированные, полностью переносимыми. Стандартное окружение и среда исполнения позволяют выполнять программы на Java на любой аппаратной платформе и в любой ОС без каких-либо изменений, усилия по портированию программ минимальны. Ценой переносимости становится потеря эффективности – работа среды исполнения приводит к дополнительным накладным расходам. УказателиC++ сохраняет возможность работы с низкоуровневыми указателями. В Java указателей нет. Использование указателей часто является причиной труднообнаруживаемых ошибок, но необходимо для низкоуровневого программирования. В принципе C++ обладает набором средств (конструкторы и деструкторы, стандартные шаблоны, ссылки), позволяющих почти полностью исключить выделение и освобождение памяти вручную и опасные операции с указателями. Однако такое исключение требует определенной культуры программирования, в то время как в языке Java оно реализуется автоматически. А теперь сравним языки Java и Python:
Эти особенности Python делают развертку приложений чрезвычайно быстрой. Это не необычно для написания программы на языке Python, что время загрузки этого приложения в пять раз меньше. Это зависит от приложения. Конечно, для численного алгоритма, выполняющего обычную арифметику целого числа в цикле ‘for’, неважно, на каком языке вы будете писать код. Но для «среднего» приложения увеличение производительности может быть просто удивительно. Один недостаток Python состоит в том, что это не полностью компилируемый язык; вместо этого он частично транслирует к внутренней форме кода байта, и этот код байта выполнен интерпретатором Python. Однако в перспективе современные компьютеры имеют так много неиспользуемого вычислительного потенциала, что для 90% приложений быстродействие связано с выбором языка. Java – компилируемый кодом байта язык (подобно Python), но в настоящее время работает медленнее, чем Python, в большинстве примеров. На основании проведенного анализа для написания программы нами выбран объектно-ориентированный язык программирования Python. Преимуществами выбранного языка являются:
Рассмотрим небольшие моменты разработки программы на языке Python. def gen_spisok_dolgnikov(self, js, predmet, group, gen_date, type_pred, prepod, group_):
gen_date = int((datetime(int(gen_date[2]), int(gen_date[1]), int(gen_date[0]), 0, 0) - datetime(1970, 1, 1)).total_seconds())
for y in xrange(0, len(js)):
dolg_flag = False
fio = js[y][u'ФИО']
if self.spisochnyi.check_student (fio_student = fio, group = group_):
self.tryez['1'] = js[y][u'Оценки']['1'][u'Оценка']
self.tryez['2'] = js[y][u'Оценки']['2'][u'Оценка']
self.tryez['3'] = js[y][u'Оценки']['3'] [u'Оценка']
for z in xrange(1, 4):
grade = js[y][u'Оценки'][str(z)][u'Оценка']
if grade in self.dolg and not grade == 'empty' or grade == 'empty' and z == 1 and not js[y][u'Оценки'][str(z)] [u'Дата'] == 'empty':
try:
dolg_date = js[y][u'Оценки'][str(z)] v[u'Дата'].split('.')
dolg_date = int((datetime(int(dolg_date[2]), int(dolg_date[1]), int(dolg_date[0]), 0, 0) - datetime(1970, 1, 1)).total_seconds())
except:
print predmet
print group
print str(js[y][u'Оценки'][str(z)][u'Дата'])
if dolg_date <= gen_date:
if not self.kaf[group] in self.js_dolgs[u'Должники']:
self.js_dolgs[u'Должники'] [self.kaf[group]] = copy.deepcopy(json.loads(u'{}'))
if not group in self.js_dolgs[u'Должники'] [self.kaf[group]]:
self.js_dolgs[u'Должники'] [self.kaf[group]][group] = copy.deepcopy(json.loads(u'{}'))
if not fio in self.js_dolgs[u'Должники'] [self.kaf[group]][group]:
self.js_dolgs[u'Должники'] [self.kaf[group]][group][fio] = copy.deepcopy(json.loads(u'[]'))
if dolg_flag == True:
del self.js_dolgs[u'Должники']
[self.kaf [group]][group][fio][index]
self.js_dolgs[u'Должники'][self.kaf[group]] [group][fio].append(copy.deepcopy(self.dolgs_part))
index = len(self.js_dolgs[u'Должники'][self.kaf[group]][group][fio]) - 1
self.js_dolgs[u'Должники'][self.kaf[group]][group][fio][index][u'Преподаватель'] = prepod
self.js_dolgs[u'Должники'][self.kaf[group]][group][fio][index][u'Предмет'] = predmet
self.js_dolgs[u'Должники'][self.kaf[group]][group][fio] [index][u'Тип'] = type_pred
self.js_dolgs[u'Должники'][self.kaf[group]][group][fio][index][u'Попытки'] = copy.deepcopy(self.tryez)
if self.tryez['1'] == '2' and self.tryez['2'] == '2' and self.tryez['3'] == '2':
if fio not in self.js_dolgs[u'three_two']:
self.js_dolgs[u'three_two'].append (fio)
self.js_dolgs[u'Должники'][self.kaf[group]][group][fio][index][u'group_id'] = js[y]['group_id'] if grade == u'н/я':
self.js_dolgs[u'Должники'][self.kaf[group]][group][fio][index][u'Не явился'] = True
dolg_flag = True
else:
dolg_flag = False
else:
if dolg_flag == True and not grade == 'empty':
try:
try_date = js[y][u'Оценки'][str(z)][u'Дата'].split('.')
except:
print u'Ошибка в дате!'
print group
print predmet
print js[y][u'ФИО'], js[y][u'Оценки'][str(z)][u'Дата']
try:
try_date = int((datetime(int(try_date[2]), int(try_date[1]), int(try_date[0]), 0, 0) - datetime(1970, 1, 1)). total_seconds())
except:
print u'Ошибка в дате!'
print group
print predmet
print js[y][u'ФИО'], js[y][u'Оценки'][str(z)][u'Дата']
#raw_input()
if try_date <= gen_date:
del self.js_dolgs [u'Должники'][self.kaf[group]][group][fio][index]
if len(self.js_dolgs[u'Должники'][self.kaf[group]][group][fio]) == 0:
del self.js_dolgs[u'Должники'][self.kaf[group]][group][fio]
Здесь представлен программный код, реализующий алгоритм создания отчета по успеваемости студентов, на вход функция принимает массив js, содержащий в себе информацию об оценках и датах, полученных из электронной ведомости. Также в данную функцию передаются имя преподавателя, тип предмета type_pred (зачет, экзамен, курсовая), название предмета predmet, название группы group, ее идентификатор в базе данных group_ и дата, на которую нужно сгенерировать отчет gen_date. Код, представленный ниже, реализует ввод оценок из электронных ведомостей в систему электронного обучения. Функция принимает название группы group, массив с оценками js, имя преподавателя prepod и идентификатор группы в базе данных group_id. def grade_submit(self, js, group, prepod, period, predmet, file_path, group_id):
type_p = {u'зачет' : u' з', u'экзамен' : u' э', u'дифф. зачет' : u' дз', u'курсовой проект' : u' кп', u'курсовая работа' : u' кр'}
grade = {u'зач' : u'Зачтено', u'н/д' : u'Не аттестован', u'н/я' : u'Не явился', u'н/а' : u'Не аттестован', u'незач' :u'Не аттестован',
u'2' : u'Неудовлетворительно', u'3' : u'Удовлетворительно', u'4' : u'Хорошо', u'5' : u'Отлично'}
months = {u'01' : u'Январь', u'02' : u'Февраль', u'03' : u'Март', u'04' : u'Апрель', u'05' : u'Май', u'06' : u'Июнь', u'07' : u'Июль',
u'08' : u'Август', u'09' : u'Сентябрь', u'10' : u'Октябрь', u'11' : u'Ноябрь', u'12' : u'Декабрь'}
day = {'01' : '1', '02' : '2', '03' : '3', '04' : '4', '05' : '5', '06': '6', '07' : '7', '08' : '8', '09' : '9'}
Так как формат даты и оценок в системе электронного обучения отличается от формата в электронных ведомостях, были объявлены переменные type_p (тип предмета), grade (оценка), months (месяц), day (день), которые представляют собой ассоциативный массив (словарь), с помощью которого данные преобразуются в нужный формат для сайта. driver = webdriver.Firefox()
print u'\nГруппа:', group
print u'Предмет:', predmet
print u'Преподаватель:', prepod
try:
driver.get('http://lms.mai.ru')
driver.find_element_by_name('username') .send_keys('login')
driver.find_element_by_name('password') .send_keys('password')
driver.find_element_by_name('password').submit()
driver.get('http://lms.mai.ru/blocks/iis/ index.php?m=conduit&a=grades')
Select(driver.find_element_by_id('menufgroup_id')) .select_by_value(self.groups[group])
Select(driver.find_element_by_id('menufperiod_id')). select_by_visible_text(period)
predmets = {}
submitted = []
soup = BeautifulSoup(driver.page_source)
Здесь происходит:
selects = soup.findAll('select')
for option in selects[5].findAll('option'):
p = option.text[option.text.find(' ') + 3 : option.text.find('(') - 1]
if u'\u2014' in p:
p = p[p.find(' ') + 3:]
predmets.setdefault(p + type_p[option.text[:option.text.find(u'\u2014') - 1]], option.get('value'))
type_predmet = type_p[option.text[:option.text.find(u'\u2014') - 1]]
else:
predmets.setdefault(p + type_p[option.text[:option.text.find(' ')]], option.get('value'))
type_predmet = type_p[option.text[:option.text.find(u'\u2014') - 1]]
Select(driver.find_element_by_id('id_subject_id')) .select_by_value(predmets[predmet])
driver.find_element_by_id('id_load').submit()
type_predmet = predmet[len(predmet) - 3:]
soup = BeautifulSoup(driver.page_source)
tables = soup.findAll('table')[0].findAll('tr')
fio_list = []
В этом участке программного кода выполняются переход к нужному предмету и загрузка страницы со списком студентов и полями для ввода оценок. Ключевые слова: электронный документооборот, программное обеспечение, компьютеризация документооборота, автоматизация документооборота, Excel, сервер, клиент, json, С++, Java, Python, клиент-приложение. Комментарии отсутствуют
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|