Автоматизация проверки знаний и навыков студентов в области прикладной математики и информатики

 

Содержание


Введение

1. Обоснование разработки системы

1.1 Описание предметной области

1.2 Анализ аналогов и прототипов

1.3 Подтверждение необходимости и актуальности проектирования

1.4 Анализ и выбор средств решения поставленной задачи

1.5 Перечень функций разрабатываемой системы

2. Разработка проекта системы

2.1 Разработка структурной схемы системы

2.2 Проектирование баз данных

2.3 Разработка и описание рабочих алгоритмов

2.4 Требования к системам передачи информации

2.5 Описание технологии обработки информации

2.6 Разработка интерфейса взаимодействия пользователя с системой

3.1 Разработка рабочей программы

3.2 Реализация графа диалога пользователей

3.3 Тестирование программных средств

3.4 Оценка надежности

3.5 Разработка сопроводительных документов

4. Технико-экономическое обоснование разработки

5. Рекомендации по безопасности жизнедеятельности и экологии

Заключение

Список использованных источников

ПРИЛОЖЕНИЕ А

ПРИЛОЖЕНИЕ Б

ПРИЛОЖЕНИЕ В


Введение


Современный период развития высших учебных заведений характеризуется значительным увеличением числа студентов, в том числе обучающихся по заочной и дистанционной формам обучения. Эта общемировая тенденция усугубляется также высоким уровнем нагрузки на преподавательский состав в вузах РФ. В результате процесс обучения становится все более сложным и менее надежным: решение острых проблем обучения в высших учебных заведениях традиционными методами все чаще не дает удовлетворительных результатов, т.е. страдает качество обучения.

В оценке качества обучения выделяется три основных показателя:

) Общее состояние качества обучения в целом по учебному заведению;

) Качество учебной работы преподавателей;

) Качество знаний и навыков студентов.

Здесь каждый показатель зависит от предыдущего. Ясно, что качество учебной работы преподавателей зависит от общего состояния качества обучения в вузе, а качество знаний и умений студентов (помимо личностно-психологических характеристик конкретного студента) - и от качества их обучения преподавателем, и от общего состояния качества обучения в вузе.

Несомненно, качество учебной работы преподавателей зависит от учебной нагрузки, при возрастании нагрузки на преподавателя качество его работы снижается. Одним из путей снижения учебной нагрузки является автоматизация отдельных функций преподавателя.

Рассматривая высшее учебное заведение как систему управления, необходимо особо отметить область проверки знаний и навыков студентов. Принятие решений в данной области традиционно практически целиком возлагается на преподавателя, несмотря на возможность частичной автоматизации этого процесса. Широкое внедрение инструментальных средств, позволяющих автоматизировать процесс проверки знаний и навыков, помогло бы решить часть проблем системы высшего образования.

Таким образом, автоматизация процесса принятия решений в области проверки знаний и навыков в высшем образовании позволит освободить время преподавателя для творческой деятельности и сократить расходы вузов.

Чаще всего автоматизация принятия решений в области оценки знаний обеспечивается средствами тестирования, и наибольшее распространение получило компьютерное тестирование.

Также стоит отметить, что сегодня многие компании и некоммерческие организации достаточно часто сталкиваются с необходимостью проведения того или иного тестирования. Например, тестирование соискателей на открывшуюся в компании вакансию, или регулярное психологическое тестирование, которое позволяет выявить "климат" в офисе и определить людей, которые являются источниками напряжения и мешают нормально работать другим. А ведь еще есть тесты по технике безопасности, профессиональные тесты для подтверждения права заниматься той или иной деятельностью, различные аттестации и т. п. Для этого очень удобно использовать компьютерное тестирование. Это позволяет ускорить проведение опросов и существенно облегчить обработку результатов.

Стоит отметить, что сейчас на рынке ПО, предназначенного для реализации тестирования, наблюдается некоторый перекос в количественном отношении в сторону относительно простых утилит, функциональных возможностей которых зачастую не хватает для решения всех задач. Они либо вообще представляют собой один скомпилированный тест на определенную тему(Cosmix Test, МanTest и др.), или же в них отсутствует возможность настройки процедуры тестирования. Но есть также и системы с большей, с виду достаточной, функциональностью, у которых и совершенно иной порядок цен. Однако, при детальном рассмотрении, и они порой не лишены недостатков. Так, у продукта фирмы Sun Rav Test Office Pro имеется возможность проводить тестирование только в пределах локальной сети. Кроме того, у него была отмечена высокая требовательность к ресурсам сервера. Продукт Test Office Pro.Web той же фирмы уже может работать и в условиях глобальной сети, однако у него, как и у предшественника, отсутствует защита от несанкционированного доступа к файлу теста. Также встречаются продукты, такие, как Ebol Testdesk, у которых недостаточно функций управления процессом тестирования.

Таким образом, актуальность разработки обусловлена:

) требованиями повышения качества обучения студентов;

) значительным возрастанием нагрузки на преподавательский состав;

) наличием возможности для улучшения существующих комплексов.

Цель данной работы состоит в повышении эффективности проверки знаний студентов технических и иных вузов. Поставленная цель достигается с помощью моделей, алгоритмов и системы автоматизированного тестирования знаний.

Для достижения поставленной цели были решены следующие задачи:

) обоснована целесообразность автоматизации процесса тестирования знаний.

) разработаны модели и алгоритмы проверки знаний.

) разработан автоматизированный комплекс, позволяющий проводить тестирование знаний студентов, а также всевозможные психологические тесты и опросы иного характера.

При программной реализации полученных концепций использовались методы теории алгоритмов, структурного и объектно-ориентированного программирования.

Порядок построения работы следующий: вначале рассматриваются общие принципы проведения компьютерного тестирования и обработки результатов с учетом особенностей применения системы в локальной и глобальных сетях. Далее производится обзор аналогов, выявляются их сильные и слабые стороны. Исходя из полученных данных, делается вывод о конкретных функциях разрабатываемого комплекса, который должен устранить недостатки рассмотренных аналогов, не растеряв их достоинств. Определяются методы реализации.

Во втором разделе разрабатывается структура системы, структура базы данных и обоснование ее введения, разработка алгоритмов, сред передачи данных, технологий обработки выходной информации и интерфейса пользователя.

В третьем разделе решаются вопросы, связанные с конкретной реализацией проекта, такие, как непосредственно разработка программных средств, их тестирование, оценка надежности и разработка сопроводительной документации на проект, а также рекомендации к его использованию.

В четвертом разделе производится технико-экономическое обоснование разработки: просчитывается общая стоимость проектирования и исполнения комплекса.

В пятом разделе приводятся рекомендации по безопасному использованию комплекса, а именно порядок аттестации рабочего места по условиям освещенности.


1. Обоснование разработки системы


1.1 Описание предметной области


В последние годы в сфере образования наблюдается стремительное увеличение интереса к автоматизации контроля результатов обучения. Самым популярным видом такого контроля является тестирование, основанное на диалоге вычислительной системы с пользователем.

Также стоит отметить, что сегодня многие компании и некоммерческие организации достаточно часто сталкиваются с необходимостью проведения того или иного тестирования. Например, тестирование соискателей на открывшуюся в компании вакансию, или регулярное психологическое тестирование, которое позволяет выявить "климат" в офисе и определить людей, которые являются источниками напряжения и мешают нормально работать другим. А ведь еще есть тесты по технике безопасности, профессиональные тесты для подтверждения права заниматься той или иной деятельностью, различные аттестации и т. п. Для этого очень удобно использовать компьютерное тестирование. Это позволяет ускорить проведение опросов и существенно облегчить обработку результатов.

Целью данной работы является разработка и реализация программного комплекса для обеспечения возможности проведения тестирования как в образовательной среде, так и в любой другой, где применима автоматизированная обработка результатов. Под обработкой результатов подразумевается подсчет общего количества баллов, начисляемых за каждый правильный вопрос в случае контрольного тестирования, или за каждый вариант ответов, в случае психологического или иного подобного тестирования, а также подведение частной и общей статистики по результатам. Так, в случае применения продукта в образовательной среде, необходимо иметь возможность просмотра статистики по какой-то конкретной группе, курсу или вузу в целом. Конкретному пользователю также полезно видеть его личную статистику.

Для обработки результатов наиболее подходит централизованная схема организации системы, т.е. клиент-сервер. Причем клиентов одновременно может работать несколько. Данная схема позволяет проводить тестирование одновременно для нескольких людей, например, целой учебной группы, и по окончании процедуры последним тестирующимся получить конечную статистику.

Наилучшим применением схемы клиент-сервер будет реализация ее как в локальной, так и в глобальной сетях. Так, в локальной сети удобно проводить тестирование на лабораторном занятии в компьютерном классе сразу всей группы. Вариант с глобальной сетью подойдет для тестирования знаний и навыков при дистанционном обучении, получившем широкое распространение в последнее время, а также для тестирования знаний обучающихся, которые по некоторым причинам (например, по состоянию здоровья) не могут присутствовать в компьютерном классе или офисе. Актуальность использования глобальной сети в качестве среды передачи данных подтверждает также ее повсеместное распространение и доступность.

Существует пять разновидностей вопросов для тестовых наборов:

1.Одиночный выбор. Пользователю предоставляется возможность выбора из нескольких вариантов единственного верного.

2.Множественный выбор. Из нескольких вариантов выбирается несколько верных.

.Свободный ввод. Пользователь вводит ответ в поле для ввода. Имеет известные сложности с обработкой результатов. С успехом может быть заменен другой разновидностью вопросов без ущерба для общих показателей.

.На соответствие. Пользователь должен сопоставить между собой варианты ответов. Вариант - события и даты.

.Упорядоченный список. Упорядочивание вариантов ответов. Вариант - расположить события в хронологической последовательности.

Статистика подводится как для конкретного пользователя, так и для каких-либо групп пользователей. В случае контрольного теста в статистике приводится процентное соотношение правильных и неправильных ответов на вопросы, исходя из которого преподаватель делает вывод о оценке знаний.

Взаимодействующими сущностями, в порядке убывания иерархической значимости, являются:

1.Преподаватель (администратор);

2.Серверная часть системы;

.Среда передачи данных;

.Клиентская часть системы;

.Пользователь (тестирующийся);


Рисунок 1.1 - Схема взаимодействия сущностей


Пользователь имеет возможность создать для себя учетную запись, к которой впоследствии будет привязываться статистика, выбрать тест для прохождения и просмотреть свои результаты.

Администратор же, в свою очередь, имеет возможность редактировать тестовые наборы, изменять, т.е. настраивать, процедуру тестирования, вносить изменения в список зарегистрированных пользователей, а также просматривать детальную статистику необходимого вида, получение которой и является окончательной целью.


.2 Анализ аналогов и прототипов


Учитывая небольшое количество методик тестирования, целесообразно разработать универсальную программу, которая позволила бы преподавателям различных дисциплин создавать свои базы данных и быстро получать контрольные задания для своего предмета. На рынке предлагается несколько подобных программ, и вот их обзор.

SunRav TestOfficePro

Разработчик: SunRav Software (#"309" src="doc_zip2.jpg" />

Рисунок 1.2 - Набор программ пакета SunRav TestOfficePro


Все тесты и результаты тестирования шифруются методами стойкой криптографии, что исключает возможность подделки результатов. Кроме того, на тест можно установить пароли: на редактирование - защищает тест от просмотра его структуры, правильных ответов и т.д.; на просмотр - предотвращает пробное тестирование с целью выяснения правильных ответов.

Вопросы и варианты ответа можно форматировать, используя для этого встроенный текстовый редактор, близкий по своим функциям к MS WORD. В редакторе можно вставлять изображения, формулы, схемы, таблицы, аудио- и видеофайлы, HTML-документы и любые OLE-документы.

В тестах возможно использование пяти вышеперечисленных типов вопросов.

Тест может быть разделен на несколько тем. При этом возможно оценивать знания тестируемого как по каждой теме в отдельности, так и по тесту в целом.


Рисунок 1.3 - Схема взаимодействия компонентов пакета SunRav TestOfficePro


Вопросы в тесте можно перемешивать. Более того, создатель теста может определить, сколько вопросов из каждой темы получит пользователь для тестирования. Допустим, каждая тема состоит из 100 вопросов. Если выбрать случайным образом только 10 вопросов, то тестируемые получат совершенно разные наборы вопросов из одного и того же теста. Варианты ответов также можно перемешать.

Порядок следования вопросов может быть не только линейным, но и зависеть от ответов пользователя.

Каждый вопрос и вариант ответа может иметь свой «вес». Это позволяет начислять пользователю больше баллов за правильные ответы на сложные вопросы и меньше баллов за ответы на легкие вопросы.

Каждый вопрос может быть снабжен комментарием, содержащим информацию о правильном ответе и т.п.

Возможна следующая реакция на ответ пользователя:

·предложение пользователю ответить на следующий вопрос;

·сообщение о том, что пользователь ответил правильно/неправильно;

·показ любого документа, связанного с вопросом. В нем, в частности, можно подробно объяснить, почему данный ответ неправильный, предоставить дополнительный материал, который позволит глубже изучить вопрос.

Тестирование можно ограничить по времени - как для теста, так и для каждого вопроса. При этом количество времени, выделяемое для каждого вопроса, может быть разным.

В пакет SunRav TestOfficePro входят следующие программы:

·tMaker - программа, позволяющая создавать и редактировать тесты. Возможно импортирование тестов, созданных в текстовом редакторе или в редакторе электронных таблиц;

·tTester - программа для проведения тестирования;

·tAdmin - программа для удаленного администрирования пользователей и обработки результатов тестирования. Позволяет просматривать/печатать результаты тестирования, а также создавать, печатать, редактировать, экспортировать отчеты по тестированию групп пользователей. Возможно создание матрицы ответов.

Технические данные SunRav TestOfficePro:

·количество вопросов - не ограничено;

·количество ответов - не ограничено;

·количество пользователей - не ограничено;

·количество тестов - не ограничено;

·количество тем в тесте - до 256;

·тесты и результаты хранятся в файлах.

В настоящее время для данного пакета подготовлено большое количество тестов. В частности, имеются образовательные тесты по информатике, экономике, английскому языку, истории, обществознанию.TestOfficePro.WEB

Разработчик: SunRav Software (#"261" src="doc_zip4.jpg" />

Рисунок 1.4 - Пакет SunRav TestOfficePro.WEB


Пакет подходит для тестирования удаленных сотрудников, студентов, школьников и т.д. Пользователю для тестирования ничего на своем компьютере устанавливать не нужно - достаточно браузера (Microsoft Internet Explorer, Opera, Mozilla и т.п.).

Возможности тестов аналогичны возможностям тестов из программы SunRav TestOfficePro, которые можно использовать и в программе SunRav TestOfficePro.WEB.

Для организации тестирования требуются:

·Web-сервер - в качестве такового можно использовать Apache или и MS IIS. По сведениям авторов программы, разработка велась с использованием бесплатного сервера Apache версии 1.3 и 2.0. Его можно свободно скачать с сайта #"justify">Если у пользователя нет собственного Web-сервера, можно использовать обычный хостинг, который предоставляет услуги по применению БД MySQL и PHP.

С помощью SunRav TestOfficePro.WEB можно:

·организовывать тесты в разделы;

·регистрировать импортировать, редактировать пользователей;

·проводить тестирование как зарегистрированных, так и не зарегистрированных пользователей;

·просматривать результаты тестирования по индивидуальному пользователю и по группе пользователей (отчеты);

·просматривать результаты рейтинга по данному тесту;

·сохранять результаты тестирования в базе данных.

Конструктор тестов Keepsoft

Разработчик: Keepsoft

Сайт программы: #"242" src="doc_zip5.jpg" />

Рисунок 1.5 - Конструктор тестов Keepsoft


Возможности программы:

·вопросы могут содержать музыку (файлы WAV, MID. RMI), изображения (файлы JPG, BMP, ICO, EMF, WMF), видеоролики (файлы AVI);

·поддерживаются вопросы всех пяти вышеперечисленных типов;

·печать на принтере и сохранение в файл тем, вопросов и ответов;

·печать на принтере и сохранение в файл результатов тестирования;

·экспорт тем, вопросов и ответов в файлы различных форматов (MS Excel, MS Word, MS Access, Paradox, DBase, текстовый файл, HTML, XML, RTF (RichText format), PDF (Adobe Acrobat), буфер обмена MS Windows, Lotus 1-2-3 и др.);

·тестирование на одном компьютере нескольких пользователей. Для каждого пользователя заводится персональная карточка пользователя, поля в которой являются настраиваемыми;

·установка различных прав доступа к редактированию базы данных в «Редакторе» для разных пользователей;

·задание вопросов в произвольном порядке;

·задание цены каждому вопросу в баллах;

·ограничение времени на ответ;

·возможность прервать тестирование и продолжить его в другое время;

·выставление оценки по окончании тестирования. Система оценок настраивается в «Редакторе». Шкалу оценок можно настроить от 2- до 100-балльной системы;

·синхронизация базы данных; при помощи этой функции можно легко обмениваться данными с другими пользователями и переносить данные с компьютера на компьютер;

·проверка орфографии в «Редакторе»;

·поиск по базе данных в «Редакторе»;

·сжатие базы данных;

·настраиваемый интерфейс;

·функция проверки обновления через Интернет.

«Конструктор тестов» можно загрузить с сайта разработчика и ознакомиться с программой бесплатно в течение 30 дней. Для дальнейшей работы с программой необходима регистрация с оплатой. Зарегистрированным пользователям предоставляются персональный регистрационный ключ и бесплатная техническая поддержка по e-mail.

Конструктор тестов «Техносервис плюс»

Разработчик: ООО «Техносервис плюс»

Сайт программы: #"279" src="doc_zip6.jpg" />

Рисунок 1.6 - Главное окно Конструктора тестов «Техносервис плюс»


Программный комплекс содержит три модуля:

·конструктор, позволяющий создавать тесты, учебники, а также модули закрепления материала. В конструкторе предусмотрена возможность использования текстового формата, формул, звукозаписи, видеороликов и изображений;

·учебник - он создается в конструкторе и может иметь неограниченное количество разделов, параграфов и страниц;

·тест, который также может быть приравнен к экзамену, поскольку исключает возможность пользоваться учебником во время проверки знаний, как при закреплении материала.

В этом модуле создаются новые разделы и вопросы, а также указываются ответы на вопросы. При этом в свойствах вопроса необходимо указать количество баллов, начисляемых за правильный ответ на него.

Программа позволяет:

·самостоятельно создавать тесты для контроля знаний учащихся. Разработка теста автоматизирована и выполняется быстро, предусмотрена возможность использования не только текста и рисунков, но и звукозаписи, видео, формул, графиков, сложных графических объектов и пр.;

·с легкостью импортировать в конструктор материалы, по которым построены текущие электронные учебники;

·производить проверку учащихся с целью выявления их уровня знаний при поступлении в учреждение (при переходе в следующий класс (курс);

·производить внутренние плановые/внеплановые проверки знаний после прохождения нового материала для оценки усвоения материала;

·создавать электронные учебники, инструкции, методические материалы;

·в режиме обучения производить опрос учащегося по выбранным вопросам; в случае неверного ответа программа укажет на ошибку и порекомендует еще раз прочитать соответствующий раздел учебника.

В пакет программ «Конструктор тестов» входят:

·модуль создания тестов и учебников;

·модуль тестирования;

·модуль обучения;

·модуль для просмотра учебников.

Ограничений по количеству компьютеров, на которые устанавливается программа, нет.


.3 Подтверждение необходимости и актуальности проектирования


В образовательном процессе очень большую роль играют контроль и оценка знаний. Они одновременно выполняют функции усвоения и практического применения знаний, которые были получены студентами и учениками в ходе учебного процесса. На данный момент можно выделить 2 типа систем контроля знаний:

·ориентированные на прохождение тестов в письменной или устной форме с последующей проверкой преподавателем. Частным случаем такого тестирования является традиционный экзамен;

·системы компьютерного тестирования с правильно подобранными тестами;

Системы первого типа существуют уже длительное время и имеют ряд недостатков: невозможность автоматической обработки результатов тестирования, большое количество рутинной работы, которая ложится на плечи организаторов тестирования, небольшая скорость обработки результатов, а также возможная необъективность оценки тестирования.

Принятие решений об окончательной оценке традиционно практически целиком возлагается на преподавателя, несмотря на возможность частичной автоматизации этого процесса. Широкое внедрение инструментальных средств, позволяющих автоматизировать процесс проверки знаний и навыков, помогло бы решить часть проблем системы высшего образования.

Таким образом, автоматизация процесса принятия решений в области проверки знаний и навыков в высшем образовании позволит освободить время преподавателя для творческой деятельности и сократить расходы вузов.

Чаще всего автоматизация принятия решений в области оценки знаний обеспечивается средствами тестирования, и наибольшее распространение получило компьютерное тестирование.

Среди преимуществ компьютерных систем тестирования можно выделить:

·автоматизацию обработки результатов;

·освобождение преподавателя от проведения традиционных экзаменов;

·обеспечение объективности контроля знаний; - повышение оперативности тестирования;

·возможность централизованного анализа качества подготовки тестирующихся по большому кругу различных вопросов;

·уменьшение затрат на организацию и проведение тестирования;

Создание систем тестирования, использующих в качестве среды передачи информации глобальную сеть Internet, является крайней перспективной и актуальной научной задачей, так как территориальная рассосредоточенность высших учебных заведений и международная интеграция учебного процесса приводят к тому, что любые локальные модели системы тестирования оказываются малоэффективными. Но для использования системы в стенах вуза необходимо предусмотреть также возможность использования в качестве среды передачи информации локальную сеть.

Таким образом, актуальность разработки обусловлена:

) требованиями повышения качества обучения студентов;

) значительным возрастанием нагрузки на преподавательский состав;

) наличием возможности для улучшения существующих комплексов.

Цель данной работы состоит в повышении эффективности проверки знаний студентов технических и иных вузов. Поставленная цель достигается с помощью моделей, алгоритмов и системы автоматизированного тестирования знаний.


.4 Анализ и выбор средств решения поставленной задачи


Архитектура разрабатываемого комплекса подразумевает наличие в ней централизованного хранилища данных о тестовых наборах (тестах), пользователях, группах пользователей и результатах тестирования знаний пользователей. Эти хранилищем данных будет реляционная база данных, находящаяся под управлением систему управления базой данных (СУБД) Microsoft SQL Server 2005. Данные в базу помещаются и считываться модулями, которые будут разработаны в ходе выполнения дипломного проекта.

Наиболее популярными моделями доступа к данным являются клиент-серверная и многозвенная архитектуры доступа к базам данных. Рассмотрим каждую из этих архитектур.


Архитектура «клиент-сервер»

Было бы неверно думать, что локальные приложения БД работают только на одном компьютере и в этом состоит их главная особенность. На самом деле такая программа вполне может функционировать в локальной сети и обслуживать нескольких клиентов одновременно.

Основное же отличие между локальными и клиент/серверными приложениями заключается в четком разграничении функций приложения и их распределении по различным компьютерам. При этом говорят о серверной и клиентской частях приложения. На сервер ложится обязанность по управлению базой данных и обслуживанию многочисленных клиентских запросов, а клиент обслуживает отдельного пользователя и "умеет" связываться с сервером, отправлять запросы и получать результаты.

Таким образом, архитектура клиент/сервер обеспечивает одновременное обслуживание множества пользователей. Естественно, что применяются они на больших промышленных предприятиях, в крупных компаниях и корпорациях и т. д.

Архитектура клиент/сервер предъявляет очень высокие требования к серверной части, которая строится на основе специальных программных комплексов, которые так и называются серверами БД или серверами SQL, так как при работе с ними используется специальный язык запросов к базам данных SQL (Structured Query Language).

В настоящее время распространена классификация приложений баз данных в соответствии с уровнями обработки данных. В соответствии с ней простые однопользовательские программы, работающие с маломощными локальными СУБД, являются одноуровневыми. В таких приложениях вся обработка данных ведется самой программой, а СУБД лишь обеспечивает доступ к таблицам.

Двухуровневые приложения соответствуют архитектуре клиент/сервер и организуют обработку как на стороне сервера БД, так и на стороне клиентского приложения. В зависимости от распределения функций обработки данных, различают системы клиент/сервер с "тонким" или "толстым" клиентом.

Важнейшей частью приложений в архитектуре клиент/сервер является сервер. Сервер базы данных представляет собой мощную систему управления базой данных, основанную на использовании SQL. Бизнес по разработке и эксплуатации промышленных серверов БД ежегодно имеет оборот в десятки миллиардов долларов. Подавляющее большинство крупных и средних компаний имеют собственные корпоративные базы данных, с которыми работают многоуровневые приложения на самых разных платформах. Серверы Oracle, Informix, Sybase управляют базами данных объемом десятки и сотни гигабайт. Для управления меньшими корпоративными базами данных применяются программные продукты MS SQL Server и InterBase.

Сервер как часть приложения, предназначенная для обеспечения работы клиентов с БД в целом, решает три основных задачи.

·Администрирование базы данных

·Контроль доступа к данным и разграничение доступа

·Управление и манипулирование потоками данных

Связь между клиентскими приложениями и сервером осуществляется на двух уровнях. Во-первых, должна существовать связь между операционными системами компьютеров клиентов и сервера. Это вопрос создания и администрирования компьютерных сетей. Во-вторых, части многоуровневого приложения должны уметь взаимодействовать между собой. Сервер имеет встроенные программные средства, обеспечивающие взаимодействие с клиентами на уровне данных. На клиентской стороне устанавливается специальное ПО клиента.

При формировании запросов в многоуровневых приложениях используется язык SQL. Каждый тип сервера работает на собственном диалекте языка, который в большей или меньшей степени соответствует стандарту ANSI 92. Сервер InterBase имеют немного дополнений. А диалекты серверов Sybase и MS SQL отличаются от стандарта довольно сильно.

Организация обработки данных в приложениях клиент/сервер имеет ряд. особенностей. Поля таблиц базы данных сервера создаются с использованием не стандартных типов данных, а доменов - создаваемых пользователем типов данных с дополнительными ограничениями.

Все операции с данными должны выполняться сервером по заявке клиента. Для этого используются хранимые процедуры - наиболее распространенные запросы, которые хранятся на сервере и выполняются по требованию клиентов. Хранимые процедуры оптимизированы для выполнения на сервере.

Некоторые хранимые процедуры должны выполняться автоматически при возникновении той или иной ситуации. В частности, они используются для поддержания ссылочной целостности данных. Такие запросы называются триггерами.

Объединяя данные из различных таблиц, можно создавать совокупности столбцов из разных таблиц, которые называются просмотрами. Структуру просмотра можно сохранить и использовать в дальнейшем.

Выполнение наборов операций выполняется сервером при помощи механизма транзакций. Транзакция - это группа операторов SQL, все команды которой должны быть успешно выполнены. В этом случае изменения фиксируются на сервере. В противном случае все команды отменяются. Транзакции обеспечивают сохранение целостности данных при работе с сервером многих клиентов одновременно.

Так как с базой данных сервера одновременно работает множество клиентов, поэтому весьма высока вероятность возникновения конфликтов при попытках модификации одних и тех же данных. Чтобы обеспечить целостность данных, серверы вынуждены осуществлять блокировку данных не отдельными записями, как в локальных СУБД, а страницами или даже таблицами. Размер страниц зависит от типа сервера. Табличная блокировка применяется при выполнении запросов модификации данных к целым таблицам (без использования оператора where).

Клиентская часть приложения может создаваться как при помощи специализированных программных сред, поставляемых совместно с сервером, так и при помощи обычных средств разработки программ. Delphi позволяет создавать клиентские приложения на любой вкус и любой степени сложности.

В целом, клиентские приложения обеспечивают выполнение следующих стандартных функций:

·обеспечение сеанса связи с сервером, при этом одно приложение может одновременно поддерживать несколько соединений;

·формирование запросов и передача их серверу;

·получение результатов выполнения запросов и их отображение при помощи стандартных интерфейсных элементов;

·обеспечение редактирования, дополнительной обработки, преобразования данных и т. д.

Многозвенная архитектура баз данных

Многозвенная архитектура приложений баз данных вызвана к жизни необходимостью обрабатывать на стороне сервера запросы от большого числа удаленных клиентов. Казалось бы, с этой задачей вполне могут справиться и приложения «клиент-сервер», однако в этом случае при большом числе клиентов вся вычислительная нагрузка ложится на сервер БД, который обладает довольно скудным набором средств для реализации сложной бизнес-логики (хранимые процедуры, триггеры, просмотры и т. д.). И разработчики вынуждены существенно усложнять программный код клиентского ПО, а это крайне нежелательно при наличии большого Числа удаленных клиентских компьютеров. Ведь с усложнением клиентского ПО возрастает вероятность ошибок и усложняется его обслуживание.

Многозвенная архитектура приложений БД призвана исправить перечисленные недостатки.

Итак, в рамках этой архитектуры "тонкие" клиенты представляют собой простейшие приложения, обеспечивающие лишь передачу данных, их локальное кэширование, представление средствами пользовательского интерфейса, редактирование и простейшую обработку.

Клиентские приложения обращаются не к серверу БД напрямую, а к специализированному ПО промежуточного слоя. Это может быть и одно звено (простейшая трехзвенная модель) и более сложная структура.

ПО промежуточного слоя называется сервером приложений, принимает запросы клиентов, обрабатывает их в соответствии с запрограммированными правилами бизнес-логики, при необходимости преобразует в форму, удобную для сервера БД и отправляет серверу. Сервер БД выполняет полученные запросы и отправляет результаты серверу приложений, который адресует данные клиентам.


Рисунок 1.7 - Многозвенная архитектура приложений БД

Таким образом, многозвенное приложение БД состоит из:

·"тонких" клиентских приложений, обеспечивающих лишь передачу, представление, редактирование и простейшую обработку данных;

·одного или нескольких звеньев ПО промежуточного слоя (сервер приложений), которые могут функционировать как на одном компьютере, так и распределенно - в локальной сети;

·сервера БД (Oralce, Sybase, MS SQL, InterBase и т. д.), поддерживающего функционирование базы данных и обрабатывающего запросы.

Более простая трехзвенная модель содержит следующие элементы:

·Клиентское приложение обеспечивает интерфейс пользователя на пользовательской машине.

·Сервер приложений находится в доступном для всех клиентов месте и обеспечивает общую передачу данных. Управление передачей данных обеспечивает так называемый брокер данных.

·Удаленный сервер базы данных обеспечивает систему управления базой данных (удаленная СУБД).

Взаимодействие этих уровней осуществляется следующим образом. Пользователь запускает клиентское приложение. Клиент соединяется с сервером приложений (который может определяться как во время исполнения, так и во время создания приложения). Запускается сервер приложений. Клиент получает интерфейс IAppServer от сервера приложений.

Затем клиент запрашивает данные от сервера приложений. В свою очередь сервер приложений запрашивает данные (устанавливая, если необходимо, соединение) в базе данных, упаковывает их для клиента, и возвращает пакет данных клиенту. Клиент расшифровывает пакеты данных и предоставляет их пользователю. Пользователь взаимодействует с клиентским приложением, и данные изменяются. Клиент упаковывает измененные данные в пакеты и отсылает их на сервер приложений.

Сервер приложений расшифровывает пакеты и сохраняет изменения в контексте транзакции. Если запись не может быть сохранена на сервере, сервер пытается согласовать изменения с текущими данными и отделяет данные, которые не могут быть сохранены. Когда процесс обработки измененных данных закончен, сервер возвращает все несохраненные данные клиенту для дальнейшего уточнения.

Клиент уточняет необработанные данные, после чего посылает их снова серверу приложений. Затем клиент обновляет свои данные с сервером.

Обе описанных архитектуры обладают как преимуществами, так и недостатками. Так «клиент серверные» приложения относительно просты в разработке и тестировании, но имеют плохую масштабируемость. Многозвенные приложении хорошо масштабируются, клиенты многозвенной архитектура платформонезависимы от используемой СУБД. Платой за эти преимущества многозвенной архитектуры является сложность разработки и тестирования такой системы.

Разрабатываемый программный комплекс будем строить, основываясь на клиент-серверной архитектуре приложений бах данных в силу легкости разработки и тестирования таких приложений.


.5 Перечень функций разрабатываемой системы


В техническом задании были поставлены следующие требования к разрабатываемой системе:

1.Функции пользователя:

а)создание учетной записи для последующего использования ее в системе;

б)возможность выбора типа теста;

в)прохождение тестирования;

г)просмотр результатов сеанса тестирования;

2.Функции разработчика тестов

а)создание и редактирование тестов;

б)управление порядком следования вопросов и ответов;

в)создание бумажной версии теста;

3.Функции администратора:

а)создание, редактирование и удаление пользователей и групп;

б)просмотр и печать результатов тестирования.

Также были приведены требования к структуре системы. Так, согласно техническому заданию, система должна состоять из:

модуля тестирования, с которым работает конечный пользователь;

модуля создания и редактирования тестов;

модуля администрирования.

Проанализировав предметную область и аналоги разрабатываемого проекта, требования к нему приняли более конкретизированную форму. Окончательный набор функций и требований к проекту:

·основная функция - обеспечение эффективного тестирования знаний; Обеспечивается при реализации всех нижеприведенных функций.

·Точная оценка результатов тестирования. Критериями при решении вопроса об оценке, которую заслуживает испытуемый, являются процент правильных ответов и количество набранных баллов. Количество баллов используется, если вопросы имеют различную сложность и им сопоставлено различное количество баллов, получаемых в случае правильного ответа. Для выставления оценки, скажем, по пятибалльной системе, преподавателем задаются пороги, либо диапазоны, критериев, которым однозначно соответствует некоторая оценка.

·Возможность использования, как для внутреннего, так и открытого тестирования в сети Internet. Обеспечивается клиент-серверной архитектурой системы.

·Удобство и легкость создания и модификации тестов.

·Отсутствие твердой привязки к какому-нибудь предмету, области знаний. Реализуется возможностью добавлять и редактировать тестовые наборы, тематика которых напрямую зависит от человека, их составлявшего.

·Сбор, сохранение и представление в удобной форме разнообразной статистической информации относительно процесса тестирования. Для вывода частных и групповых отчетов, наряду с необходимостью хранить тестовые наборы, информацию о пользователях и другую информацию, необходимую системе, целесообразно ввести в состав проекта базу данных, которая бы позволяла проводить выборки необходимого вида и хранение данных в защищенном виде.

·Возможность одновременного тестирования неограниченного количества пользователей. Количество пользователей, одновременно работающих с системой, ограничено лишь пропускной способностью канала передачи информации от сервера к клиенту, и, в некоторой степени, от аппаратных ресурсов сервера.

·Легкая наращиваемость, масштабируемость системы.

·Контроль времени тестирования и сохранение информации относительно прерванного сеанса тестирования.

·Поддержка безопасного и универсального механизма управления пользователями с распределением прав доступа.

·Возможность самостоятельной регистрации пользователей.

·Возможность настройки процедуры тестирования, как для отдельного тестового набора, так и в целом.



Выводы


В первом разделе было произведено описание и анализ предметной области дипломного проекта. Были рассмотрены аналоги и прототипы разрабатываемого программного комплекса, проанализированы их возможности, преимущества и недостатки. На основании этих данных была разработана концептуальная модель разрабатываемой системы, сформулированы основные требования к системе, выделены основные структурные элементы. В первом был произведен анализ существующих архитектуры приложений баз данных: клиент-серверных и многозвенных. В проекте решено использовать архитектуру «клиент-сервер» Так же была подтверждена актуальность разработки. Сформулирован перечень задач, подлежащих решению для обеспечения разрабатываемого программного продукта требуемой функциональностью.

программный комплекс база данные


2. Разработка проекта системы


2.1 Разработка структурной схемы системы


Согласно техническому заданию программный комплекс должен обеспечивать следующие возможности:

-создание и редактирование тестовых наборов (тестов), настройка процедуры тестирования;

-администрирование пользователей и групп пользователей, работающих с элементами комплекса, просмотр результатов тестирования знаний пользователей;

-создание учетной записи тестирующегося пользователя с целью последующего прохождения процедуры тестирования и просмотра результатов сеанса тестирования.

Таким образом, анализируя перечень требуемых возможностей, целесообразно произвести логическую декомпозицию программного комплекса на отдельные функционально законченные программные модули:

1.Модуль создания, редактирования и настройки тестов - модуль преподавателя;

2.Модуль тестирования. С ним осуществляет работу тестирующийся пользователя;

.Модуль администрирования и вывода отчетов.

Каждый и описанных выше модулей в свою очередь состоит из подмодулей, отвечающих за решение конкретной задачи.

Модуль создания, редактирования и настройки тестов состоит из следующих блоков:

-блок авторизации пользователей. Здесь пользователь вводит имя своей ученой записи с соответствующими правами доступа и пароль. В случае если введены некорректные данные, доступ к модулю должен быть закрыт.

-блок управления разделами тестов. Производит редактирование списка разделов, а также распределение тестов по разделам.;

-блок выбора тестов и настройки процедуры тестирования. В этом блоке может быть дано краткое описание теста, введены сведения об авторе теста, выбран тип теста (контрольный или психологический), настроено временное ограничение на тест, настроен порядок следования вопросов в тесте;

-блок выбора и настройки вопросов теста. В данном блоке должна быть предусмотрена возможность создания, редактирования и удаления вопросов выбранного теста. Необходимо предусмотреть возможность выбора типа вопроса (одиночный выбор, множественный выбор, на соответствии, упорядоченный список, свободный ввод). Текст вопроса должен содержать элементы форматирования. Необходимо предусмотреть возможность поддержки стандартных OLE-объектов в формулировке вопроса;

-блок редактирования ответов. Должен предоставлять возможность по добавлению, изменению и удалению ответов на выбранный вопрос. В данном блоке необходимо осуществлять контроль за вводимой пользователем информацией и предупреждать о выявленных ошибках.

В модуле тестирования выделим следующие блоки:

-блок авторизации пользователя;

-блок выбора теста;

-блок тестирования. В данном блоке производится выборка из базы данных вопросов с вариантами ответов, получение от пользователя ответа на вопрос, анализ и занесение полученных данных в базу;

-блок просмотра результатов сеанса тестирования.

Модуль администрирования состоит из следующих функциональных частей:

-блок авторизации пользователя;

-блок управления группами пользователей. Производит распределение пользователей по группам, а также сопоставление группам разделов тестов.

-блок управления пользователями. Производит редактирование личных данных пользователей и прав доступа.

-блок вывода отчетов. Позволяет выводить отчеты разнообразного вида как по отдельно взятому пользователю, так и по целым группам, с возможностью фильтрации выводимых записей по диапазону дат, набранным баллам и др. Целесообразна также функция сохранения отчета в файл.

Основываясь на описанной выше декомпозиции программного комплекса на модули, была разработана структурная схема комплекса, представленная на рисунке 2.1.

Как видно из рисунка составляющие комплекс программные модули не имеют функциональных связей, благодаря чему упрощается разработка и сопровождение конечного продукта. Кроме этого из рисунка видно, что в каждом модуле имеются одинаковые блоки, отвечающие за авторизацию пользователя, что так же упрощает разработку путем дублирования повторяющихся кусков кода.



Рисунок 2.1 - Структурная схема программного комплекса

2.2 Проектирование баз данных


Для обеспечения требуемой функциональности, разрабатываемый программный комплекс должен обрабатывать большие объемы данных, таких как тестовые наборы данных, данные о группах, пользователях и результатах прохождения тестов пользователями, различные служебные данные. По этой причине к среде хранения данных предъявляются жесткие требования: обеспечение целостности и непротиворечивости хранимых данных, высокая скорость обработки данных, высокая степень защищенности данных от посягательств со стороны злоумышленников, поддержка многопользовательского доступа к данным с функциями разрешения или исключения конфликтных ситуаций. Всем описанным требованиям отвечают реляционные базы данных. В качестве целевой системы управления базой данных (СУБД) выбран Microsoft SQL Server 2005(Standard Edition), который полностью обеспечивает выполнение поставленных выше требования к среде хранения данных. Кроме этого выбранный программный продукт обладает достаточно удобными средствами администрирования баз данных, что существенно упрощает разработку программного комплекса в целом.

Несмотря на то, что проектируемая база данных состоит из взаимосвязанных сущностей, в ней можно выделить две основные подгруппы сущностей. К первой подгруппе отнесем сущности, описывающие хранилища данных о тестах, вопросах и ответах к этим вопросам. Ко второй - сущности пользователей, групп пользователей и результатов прохождения пользователями тестов. На рисунке 2.х представлена ER-модель разрабатываемой базы данных.


Рисунок 2.2 - ER-модель базы данных


Опишем входящие в базу данных сущности и их атрибуты

Сущность Sections. Информация о разделах тестов.

Атрибуты:

·Section_id. Тип: integer. Первичный ключ.

·Section_name.Тип: text. Наименование раздела тестов.

·Section_hidden. Тип: bit. Флаг сокрытия раздела тестов. Принимает значения «1» и «0». При значении «1» раздел тестов удаляется из списка видимых. Информация не удаляется.

Сущность Tests. Информация и параметры теста.

Атрибуты:

·Test_id. Тип: integer. Первичный ключ таблицы.

·Test_description. Тип: text. Описание теста.

·Test_section_id. Тип: integer. Хранится идентификатор из сущности Sections. Определяет принадлежность теста к разделу.

·Test_name. Тип: text. Имя теста.

·Test_type. Тип: integer. Тип теста. Принимает значения «0» и «1». «0» - контрольный тест, «1» - психологический (подсчет баллов).

·Test_author. Тип: varchar(128). Автор теста.

·Test_questions_count. Тип: integer. Количество вопросов в тесте.

·Test_questions_limit. Тип: integer. Определяет то количество из общего числа вопросов в тесте, которое будет задано пользователю.

·Test_is_random_answers. Тип: bit. Флаг перемешивания вариантов ответов. Принимает значения «1» и «0».

·Tests_is_time_limit. Тип: bit. Флаг ограничения времени на тест. Принимает значения «1» и «0».

·Test_time_limit. Тип: char(8). Ограничение времени на тест.

·Test_is_back. Тип: bit. Флаг возможности возврата на предыдущий вопрос. Принимает значения «1» и «0».

Сущность Questions. Вопросы тестов.

Атрибуты:

·Question_id. Тип: integer. Первичный ключ.

·Question_test_id. Тип: integer. Хранится идентификатор из сущности Tests. Определяет принадлежность вопроса к тесту.

·Question_number. Тип: integer. Локальный номер вопроса. Нумерация начинается с единицы.

·Question_header. Тип: varchar(1024). Заголовок вопроса. Может дублироваться текст вопроса. Используется при ведении истории ответов пользователя.

·Question_Text. Тип: text. Текст вопроса. Поддерживается возможность форматирования текста и использования стандартных OLE-объектов.

·Question_time. Тип: char(8). Время на ответ.

·Questin_type. Тип: integer. Тип вопроса. «0» - одиночный выбор, «1» - множественный выбор, «2» -соответствие , «3» - упорядоченный список. «4» - свободный ввод.

·Question_weight. Тип: integer. Количество начисляемых баллов в случае правильного ответа на вопрос.

Сущность Answers. Варианты ответов к вопросам.

Атрибуты:

·Answer_id. Тип: integer. Первичный ключ.

·Answer_question_id. Тип: integer. Хранится идентификатор из сущности Questions. Определяет принадлежность варианта ответа к вопросу.

·Answer_number. Тип: integer. Локальный номер ответа. Нумерация начинается с единицы. Используется только для ответов на вопрос типа «упорядоченный список»

·Answer_text. Тип: varchar(512). Текст варианта ответа. Возможность форматирования текста отсутствует.

·Answer_score. Тип: integer. Количество баллов, начисляемых за ответ. Используется при типе теста «Психологический».

·Answer_right. Тип: bit. Флаг правильности ответа. Принимает значения «0» и «1». При типах вопроса «упорядоченный список», «на соответствие» и «свободный ввод» - всегда устанавливается значение «1»

·Answer_corresp. Тип: varchar(512). Применяется для определения правильного ответа в вопросах на соответствие.

·Answer_picture. Тип: image. Может храниться изображение с вариантом ответа

Сущность Groups. Информация о группах пользователей.

Атрибуты:

·Group_id. Тип: integer. Первичный ключ.

·Group_name. Тип: varchar(512). Наименование группы.

·Group_description. Тип: varchar(512). Описание группы.

·Group_hidden. Тип: bit. Флаг сокрытия группы. Принимает значения «1» и «0». При значении «1» группа удаляется из списка видимых. Информация не удаляется.

Сущность Groupsections. Информация о соответствии группам разделов тестов.

Атрибуты:

·Id. Тип: integer. Первичный ключ.

·Gs_group_id. Тип: integer. Идентификатор группы.

·Gs_section_id. Тип: integer. Идентификатор раздела тестов.


Сущность Users. Информация о пользователях.

Атрибуты:

·User_id. Тип: integer. Первичный ключ.

·User_group_id. Тип: integer. Хранится идентификатор из сущности Groups. Определяет принадлежность пользователя к группе.

·User_name. Тип: varchar(512). Имя пользователя в формате ФИО.

·User_code. Тип: varchar(128). Дополнительное поле для идентификатора пользователя (например, номера зачетной книжки).

·User_password. Тип: varchar(128). Пароль пользователя. Хранится в закодированном виде. Алгоритм кодирования - md5.

·User_desable_test. Тип: bit. Флаг, позволяющий временно запретить данному пользователю тестироваться

·User_garants. Тип: integer. Кодирует права доступа пользователя. «0» - тестирующийся, «1» - редактор тестов, «2» - администратор

·User_info. Тип: varchar(512). Информация о пользователе.

·User_deleted. . Тип: bit. Флаг удаления пользователя. Принимает значения «1» и «0». При значении «1» становится невозможным использование учетной записи, данные сохраняются.

·User_mail. Тип: varchar(128). Адрес e-mail пользователя.

Сущность User_results. Хранение результатов тестирования.

Атрибуты:

·User_result_id. Тип: integer. Первичный ключ.

·User_result_completed. Тип: bit. Флаг окончания теста (ответ на все имеющиеся вопросы). Принимает значения «1» и «0».

·User_result_time_begin. Тип: smalldatetime. Время начала тестирования.

·User_result_time_end. Тип: smalldatetime. Время окончания тестирования.

·User_result_cmpleted_questions. Тип: integer. Количество пройденных вопросов.

·User_result_right_questions. Тип: integer. Количество правильных ответов.

·User_result_score. Тип: integer. Количество заработанных баллов.

·User_result_percent_right. Тип: real. Процент правильных ответов.

·User_result_total_questions. Тип: integer. Всего вопросов в тесте.

·User_result_test_title. Тип: varchar(128). Название теста

·User_id. Тип: integer. Хранится идентификатор из сущности Users. Определяет принадлежность результата к конкретному пользователю.

Сущность User_answers. Лог прохождения теста, может быть показан в отчете.

Атрибуты:

·User_answer_user_result_id. Тип: integer. Первичный ключ.

·User_answer_qnumber. Тип: integer. Номер вопроса.

·User_answer_question. Тип: varchar(512). Текст вопроса с элементами разметки гипертекста для корректного вывода в поле отчета.

·User_answer_answer. Тип: varchar(512). Текст ответа с элементами разметки гипертекста для корректного вывода в поле отчета.

·User_answer_time. Тип: char(8). Время ответа на вопрос.

·User_answer_is_right. Тип: bit. Флаг правильности ответа. Принимает значения «T» и «F».

·User_answer_score. Тип: integer. Полученные баллы.

·User_answer_answerd. Тип: bit. Флаг ответа на вопрос. Принимает значения «1» и «0».

Поддержка целостности и непротиворечивости данных осуществляется средствами целевой СУБД MS SQL Server 2005. При возникновении конфликтной ситуации СУБД генерирует соответствующее сообщение, которое автоматически будет транслировано в клиентское приложение и показано пользователю. Вызвавшая исключительную ситуацию транзакция выполнена не будет, а набор данных будет возвращен в предыдущее непротиворечивое состояние.

Резервное копирование данных, настройка и иные административные функции выполняются средствами администрирования, такими, как SQL Server Management Studio и SQL Server Business Intelligence Development Studio.

Наличие описанных механизмов поддержки целостности и непротиворечивости данных, а так же средств администрирования базы данных, делает обоснованным использование SQL Server 2005 в качестве целевой СУБД.


.3 Разработка и описание рабочих алгоритмов


В виду того, что модули разрабатываемого программного комплекса должны работать в многопользовательской среде, алгоритмы их работы должны обладать низкой ресурсоемкостью и малым временем выполнения.

Необходимо отметить, что в модуле редактирования тестов и модуле администрирования наличие каких-либо сложных вычислительных алгоритмов не предполагается. По сути, эти модули являются средствами просмотра и редактирования содержимого базы данных. Возникающие в процессе работы этих модулей задержки обусловлены лишь задержкой, связанной с пересылкой результатов запроса от СУБД к программному модулю, которая в свою очередь может меняться в зависимости от условий эксплуатации модулей: параметров сервера базы данных и качества линии связи между программным модулем и сервером базы данных.

В модуле тестирования пользователя помимо задержек, связанных с пересылкой запросов от сервера к клиенту, дополнительно могут возникнуть задержки при обработке и анализе ответа пользователя. Рассмотрим общий алгоритм работы модуля тестирования пользователей.


Рисунок 2.3 - Алгоритм работы модуля тестирования

Рисунок 2.4 - Алгоритм работы модуля тестирования (продолжение)


С целью приблизительной оценки задержки при работе модуля тестирования в многопользовательском режиме был произведен эксперимент, результаты которого приведенные в таблице 2.1


Таблица 2.1 Результаты тестирования на быстродействие в многопользовательском режиме.

№Тестовый серверКол-во пользователейВремя выполнения, с1 Intel Celeron2000, 2Гб ОЗУ PC-3200 100,013-0,015200,012-0,016

Количество замеров для обоих случаев равно пяти. Как видим, полученные задержки малы, что обусловлено малой вероятностью выполнения сервером одновременно нескольких запросов к базе данных. Для этого нужно было бы, чтобы запросы пришли одновременно с точностью 0.01с.


.4 Требования к системам передачи информации


Разрабатываемая система может использовать в качестве среды передачи данных как локальную, так и глобальные сети, в независимости от их топологии.

Основной объем пересылаемых данных составляют запросы клиентского модуля на выборку вопросов, относящихся к текущему тесту, и результат их выполнения. Пакет ответа на запрос с формулировкой вопроса в текстовом виде с элементами форматирования текста имеет размер 2-8 Кб. Размер пакетов во многом зависит от содержимого формулировки вопроса. Так использование различных мультимедейных объектов в формулировке вопроса может существенно увеличить время передачи вопроса в удаленный клиентский модуль, если последний подключен к базе посредствам низкоскоростного модемного соединения. Грамотное планирование структуры и содержания вопросов позволяет избежать подобных проблем.

Для осуществления работы клиентского модуля достаточно модемного соединения на скорости 33600 Кбит/сек., однако, использование в вопросе мультмедийных файлов больших размеров, может замедлить выдачу очередного вопроса. С точки зрения логики работы модуля это не критично, поскольку отсчет времени ответа на вопрос начинается с момента вывода формулировки вопроса на экран клиентского компьютера.

Для комфортной работы со всеми модулями комплекса достаточно использования высокоскоростного соединения 64 Кб/сек., что делает возможным использование комплекса, как в локальных, так и в глобальных сетях.


.5 Описание технологии обработки информации


Входными данными для разрабатываемой системы являются файл тестового набора и реакции пользователя. Тестовый набор представляет собой результат выполнения запроса на выборку вопросов, относящихся к выбранному тесту, и ответов к ним. Механизм пересылки запросов и их обработки реализован средствами технологии Microsoft ActiveX Data Objects (ADO), которая основана на возможностях СОМ, а именно интерфейсов OLE DB.

Технология Microsoft ActiveX Data Objects обеспечивает универсальный доступ к источникам данных из приложений БД. Такую возможность предоставляют функции набора интерфейсов, созданные на основе общей модели объектов СОМ и описанные в спецификации OLE DB.

Технология ADO и интерфейсы OLE DB обеспечивают для приложений единый способ доступа к источникам данных различных типов (рис. 19.1). Например, приложение, использующее ADO, может применять одинаково сложные операции и к данным, хранящимся на корпоративном сервере SQL, и к электронным таблицам, и локальным СУБД. Запрос SQL, направленный любому источнику данных через ADO, будет выполнен.


Рисунок 2.5 - Схема доступа к данным через ADO

DB представляет собой набор специализированных объектов СОМ, инкапсулирующих стандартные функции обработки данных, и специализированные функции конкретных источников данных и интерфейсов, обеспечивающих передачу данных между объектами.

Согласно терминологии ADO, любой источник данных (база данных, электронная таблица, файл) называется хранилищем данных, с которым при помощи провайдера данных взаимодействует приложение. Минимальный набор компонентов приложения может включать объект соединения, объект набора данных, объект процессора запросов.

Объекты OLE DB создаются и функционируют так же, как и другие объекты СОМ. Каждому объекту соответствует идентификатор класса CLSID, хранящийся в системном реестре. Для создания объекта используется метод CoCreateinstance и соответствующая фабрика класса. Объекту соответствует набор интерфейсов, к методам которых можно обращаться после создания объекта.

В результате приложение обращается не прямо к источнику данных, а к объекту OLE DB, который "умеет" представить данные (например, из файла электронной почты) в виде таблицы БД или результата выполнения запроса SQL.

Технология ADO в целом включает в себя не только сами объекты OLE DB, но и механизмы, обеспечивающие взаимодействие объектов с данными и приложениями. На этом уровне важнейшую роль играют провайдеры ADO, координирующие работу приложений с хранилищами данных различных типов.

Такая архитектура позволяет сделать набор объектов и интерфейсов открытым и расширяемым. Набор объектов и соответствующий провайдер может быть создан для любого хранилища данных без внесения изменений в исходную структуру ADO. При этом существенно расширяется само понятие данных - ведь можно разработать набор объектов и интерфейсов и для нетрадиционных табличных данных. Например, это могут быть графические данные геоинформационных систем, древовидные структуры из системных реестров, данные CASE-инструментов и т. д.

Так как технология ADO основана на стандартных интерфейсах СОМ, которые являются системным механизмом Windows, это сокращает общий объем работающего программного кода и позволяет распространять приложения БД без вспомогательных программ и библиотек.

Спецификация OLE DB различает следующие типы объектов, которые будут рассмотрены ниже.

-Перечислитель (Enumerator) выполняет поиск источников данных или других перечислителей. Используется для обеспечения функционирования провайдеров ADO.

-Объект-источник данных (Data Source Object) представляет хранилище данных.

-Сессия (Session) объединяет совокупность объектов, обращающихся к одному хранилищу данных.

-Транзакция (Trasaction) инкапсулирует механизм выполнения транзакции.

-Команда (Command) содержит текст команды и обеспечивает ее выполнение. Командой может быть запрос SQL, обращение к таблице БД и т. д.

-Набор рядов (Rowset) представляет собой совокупность строк данных, являющихся результатом выполнения команды ADO.

-Объект-ошибка (Error) содержит информацию об исключительной ситуации.

Все описанные качества делают оправданным использование технологии Microsoft ADO в проекте, в качестве технологии доступа и обработки данных.


.6 Разработка интерфейса взаимодействия пользователя с системой


Поскольку разрабатываемый программный комплекс в своем составе имеет модуль создания, редактирования тестов, модуль просмотра результатов тестирования и модуль тестирования знаний, то целесообразно наделять пользователей, работающих с разными модулями, разными правами доступа. Это позволит защитить тестовые наборы от посягательства злоумышленников и реализовать идеологию честного тестирования, при которой тестирующийся пользователь проходит тест, основываясь только на своих знаниях предмета тестирования.

Пользователи системы - сотрудники и студенты высших учебных заведений. Всех пользователей системы можно, как будет показано ниже, разделить на несколько категорий, принадлежность к которым конкретизирует требования. Однако все пользователи должны иметь навыки работы с персональным компьютером. Выделим следующие категории пользователей комплекса:

Администратор выполняет функции управления группами и пользователями, а так же правами в системе, просматривает и распечатывает отчеты с результатами тестирования отдельных пользователей или групп, устанавливает соответствие между разделами тестов и группами. Администратор может при необходимости выполнять функции всех нижеследующих типов пользователей. Администратор должен иметь глубокие познания в сфере установки, конфигурирования и работы с ОС и программным обеспечением, используемым системой. Также ему необходимо знать основы администрирования СУБД вообще и SQL Server 2005 в частности. Желательно, чтобы администратор имел хотя бы общие познания в языках программирования и описания данных, используемых в системе (SQL DDL/DML, PL/SQL, и др.). Одной из задач администрирования является консультация пользователей системы в случае возникновения у них каких-либо вопросов.

Преподаватель. Вводит в систему новые тестовые задания и редактирует существующие, устанавливает временные границы тестирования.

Тестируемый. Эта категория пользователей добровольно или принудительно проверяет свои знания с помощью тестов. Перед началом тестирования пользователь входит под своей учетной записью. Затем он выбирает доступный для своей группы тест и проходит тестирование. По завершению тестирования пользователь имеет возможность просмотреть результаты сеанса тестирования.

Каждой категории пользователей соответствует отдельный программный модуль. Доступ к модулям редактирования тестов и администрирования возможен только после аутентификации пользователя. Доступ к модулю тестирования возможен без аутентификации, однако, полноценная работа с модулем возможна только после регистрации пользователя в системе.

Интерфейс всех модулей имеет академический стиль, отличающийся минимальными визуальными эффектами и интуитивной понятностью конечному пользователю. Экранные формы всех модулей представлены в приложении Б.

На рисунках 2.6, 2.7 и 2.8 представлены графы диалога пользователей категории «администратор», «преподаватель» и «тестирующийся» соответственно.


Рисунок 2.6 - Граф диалога администратора с системой

Рисунок 2.7 - Граф диалога преподавателя с системой


Рисунок 2.8 - Граф диалога тестирующегося с системой

Выводы


Во втором разделе была произведена разработка проекта системы. Структура комплекса состоит из трех модулей: модуля администрирования, модуля редактирования тестов и модуля тестирования. Каждый из модулей независим от остальных. В данном разделе была спроектирована ER-модель базы данных с подробным описанием всех ее сущностей и входящих в них атрибутов. На основе ER-модели была разработана реальная модель в целевой СУБД Microsoft SQL Server 2005. Затем были разработаны рабочие алгоритмы функционирования элементов системы. После определили требования к системе передачи информации. Для комфортной работы со всеми модулями комплекса достаточно использования высокоскоростного соединения 64 Кб/сек. Так же во втором разделе была описана технология доступа и обработки данных Microsoft ADO. Был обоснован ее выбор в качестве технологии обработки информации. Затем были выделены три категории пользователей, работающих с модулями комплекса. Для каждой категории был разработан граф диалога пользователя с системой. Работа над вторым разделом стала основой для разработки рабочих программ.


3. Реализация проекта системы


.1 Разработка рабочей программы


Рабочая программа разрабатывалась в среде программирования Borland Delphi 7.0. Эта среда обладает удобным набором средств проектирования пользовательского интерфейса и работы с базами данных. В частности в Delphi 7 имеется коллекция компонентов, инкапсулирующих свойства и методы технологии доступа к данным Microsoft ADO. Так же при использовании Delphi 7 в качестве среды разработки, проектирование пользовательского интерфейса уходит на второй план, а на первое место выходит разработка и реализация алгоритмов работы системы. Все это послужило причиной выбора данной среды для разработки программного комплекса.

Весь комплекс разделен на три законченных программных модуля: модуль администрирования, модуль редактирования тестов и модуль тестирования. Доступ к каждому из модулей осуществляется запуском соответствующего приложения.

На рисунке 3.1 представлена модульная структура блока администрирования


Рисунок 3.1 - Модульная структура блока администратора


Как видно из рисунка данный блок содержит в себе четыре модуля:

1.uAdmDataModule. Состоит из компонентов доступа и отображения данных. В данном модуле реализованы SQL-запросы и реакции системы на изменение состояния наборов данных.

2.uAuthentification. Модуль аутентификации пользователя. Отображается непосредственно после запуска приложения. При успешном входе наборы данных будут открыты и отображены на главной форме приложения. В противном случае приложение будет закрыто автоматически.

3.uUserGrioup. Этот модуль предназначен для управления пользователями и группами. Здесь производится сопоставление разделов тестов и групп пользователей, создаются пользователи с правами администратора и редактора тестов.

4.uReporting. Модуль статистики и отчетов. Отображается статистика, как по отдельным пользователям, так и по группам пользователей.

На рисунке 3.2 представлена модульная структура модуля редактирования тестов


Рисунок 3.2 - Модульная структура редактора тестов


Редактор тестов состоит из трех модулей:

1.uEditorMain. Главный модуль программы. Содержит обработчики действий пользователя. Производит управление интерфейсом программы в зависимости от действий пользователя

2.uAuthentification. Назначение и функционирование такое же, как и в модуле администрирования.

3.uEditorDataModule. Состоит из компонентов доступа и отображения данных. В данном модуле реализованы SQL-запросы и реакции системы на изменение состояния наборов данных. В данном модуле реализуется поддержка целостности и непротиворечивости данных в базе.

Модульная структура блока тестирования представлена на рисунке 3.3.

Рисунок 3.3 - Модульная структура блока тестирования


Назначение модулей следующее:

uTestAuthentification. Модуль, осуществляющий аутентификацию пользователя в системе. В случае, если введенная учетная запись отсутствует в базе, пользователь может зарегистрировать новую учетную запись.

uNewUser. Модуль регистрации нового пользователя. Вызывается из модуля аутентификации. Добавляет нового пользователя с правами тестирующегося.

uSelectTest. Модуль выбора теста. данный модуль становится доступным после прохождения процедуры аутентификации. Если этого не сделано, то перед открытием модуля выбора теста, пользователю будет предложено войти в систему со своей учетной записью. На выбор доступны только тесты из разделов, разрешенных для группы, в которой зарегистрирован вошедший пользователь.

uTestDataModule. Состоит из компонентов доступа и отображения данных. В данном модуле реализованы SQL-запросы и реакции системы на изменение состояния наборов данных. В данном модуле реализуется поддержка целостности и непротиворечивости данных в базе.

uTestMain. Главный модуль программы. Осуществляет выдачу вопросов и вариантов ответов к ним. Вопросы и ответы имеют случайный порядок следования, что исключает механическое угадывание пользователем правильных ответов. Так же данный модуль принимает, анализирует ответы пользователей, заносит результаты в базу.

Тексты всех модулей представлены в приложении В.

3.2 Реализация графа диалога пользователей


При работе пользователей с компонентами программного комплекса должны быть выполнены следующие требования: первое - интерфейс модулей должен быть простым и понятным пользователям; второе - пользователи, не имеющие соответствующие права, не должны иметь возможности работать с модулями системы.

Первое требование выполняется при помощи интуитивно понятных элементов управления, системы подсказок и системы помощи при работе с системой. На рисунке 3.4 представлена главная форма модуля тестирования.


Рисунок 3.4 - Главная форма модуля тестирования


Из рисунка видно, что интерфейс прост и понятен. В верхней части окна помещается вопрос. В нижней - варианты ответа, которые вводит пользователь. После ответа на вопрос пользователь переходит к следующему вопросу. Если это разрешено, то возможен переход к предыдущему вопросу.

Кнопки инструментальной панели продублированы пунктами главного меню. Такое построение интерфейса используется мо многих известных приложениях, поэтому работа с модулями программного комплекса не должна вызвать затруднения даже у начинающих пользователей компьютера.

Чтобы предупредить возможные ошибки пользователя, связанные, например, с преждевременным пользователем из сеанса тестирования, реализована система информирования пользователя (рисунок 3.5)


Рисунок 3.5 - Реакция программы на преждевременное завершение работы


Чтобы предотвратить несанкционированный доступ пользователей не имеющих на это право к модулям редактирования тестов и администрирования реализована принудительная аутентификация при входе в приложение.


Рисунок 3.6 - Пример запуска редактора тестов


Интерфейс приложения фактически не скрыт, но загрузка данных в компоненты отображения не производится. Если вход в систему успешный, то все необходимы данные будут загружены в компоненты отображения.

Примеры остальных форм и реакции на действия пользователей представлены в приложении Б.


.3 Тестирование программных средств


В настоящее время разработано достаточно много разнообразных методов отладки программного обеспечения. Выделим некоторые:

. Синтаксическая и семантическая отладка.

. Тестирование программ как "черного" или "белого" ящика.

. Статическое и динамическое тестирование.

. Разрушающие и неразрушающие методы.

. Методологические способы отладки.

. Другие приемы отладки.

В зависимости от объекта отладки методы и системы отладки можно разделить на две части: синтаксическую и семантическую.

Синтаксическая отладка начинается при первом вводе программы в ЭВМ для трансляции или сразу для выполнения и заканчивается получением текста программы, не содержащего конструкций языка программирования, противоречащих его синтаксису.

Семантическая отладка начинается в тот момент, когда программа стала синтаксически правильной и пригодна для выполнения на ЭВМ. Целью семантической отладки является поиск и корректировка программы таким образом, чтобы она выполняла заданную функцию (преобразование входных данных в выходные) в соответствии с требованиями к программе.

Наиболее распространенным и традиционным методом отладки программ является тестирование программ.

Подходы к решению задачи тестирования в зависимости от того, каким образом они учитывают или рассматривают структуру исследуемой программы, можно разделить на два направления:

. Тестирование программы как "черного ящика" (при тестировании не учитывается внутренняя структура программы, а принимаются во внимание лишь значения входных и выходных данных);

. Тестирование программы как "белого ящика" (при тестировании принимается во внимание также и внутренняя структура программы).

При тестировании программ по методу "белого ящика" тестовые данные для программы формируются с учетом ее внутренней структуры. При этом задача тестирования преобразуется в задачу обеспечения полноты проверки внутренней структуры, которая отражает алгоритм функционирования. Внутренняя структура может быть представлена в виде управляющего ориентированного графа, где вершины - это отдельные операторы, а дуги - возможные передачи управления между операторами.

Тогда тестирование может заключаться в проверке всех дуг такого графа, всех выходов из каждой вершины графа, маршрутов обработки инфоpмации внутри программы. При тестировании по этому методу программист располагает информацией о пути прохождения вычислительного процесса по графу и выбирает тесты таким образом, чтобы обеспечить проверку графа по заданному критерию. Также проверяются значения выходных данных, вырабатываемых программой. Поэтому тестирование по методу "белого" ящика в общем случае более глубокое и эффективное, чем по методу "черного" ящика.

Можно указать три вида тестирования, учитывающего внутреннюю структуру программы:

тестирование путей;

тестирование ветвей;

тестирование операторов.

Тестирование путей программы предполагает выполнение всех возможных или подмножеств путей, существующих в программе, по крайней мере один раз. Путь программы определяется значениями входных данных. Каждый путь программы состоит из последовательности линейных участков, на которых расположены только безусловно выполняемые команды; линейные участки связаны командами условного перехода. Если команды условного перехода не коppелиpуют друг с другом по данным, то число различных реализуемых путей программы может достигать числа 2 в степени n, где n - число команд условных переходов, каждая из которых имеет два выхода ("да" и "нет"). Ясно, что даже для небольших программ достичь полного тестирования путей невозможно.

Тестирование ветвей предполагает, по крайней мере, однократное выполнение каждой ветви отлаживаемой программы. Ветвь программы - это последовательность безусловно выполняемых команд, заканчивающихся командой условного перехода (максимальный участок с одним входом и одним выходом). При тестировании ветвей можно достичь полного перекрытия всех ветвей относительно небольшим числом тестов.

Тестирование операторов состоит в выполнении, по крайней мере, один раз каждого оператора программы независимо от пути или ветви программы, на которых он находится. Это наиболее простой из трех перечисленных способов тестирования.

В зависимости от способа получения результатов выполнения программы все подходы к тестированию можно также разделить на два направления.

. Если программа во время отладки непосредственно не выполняется, то такой подход называется статическим. При этом исследуется текст или код программы с целью выявления конструкций, которые можно интерпретировать как неправильные, для их последующего исправления;

. Если программа в процессе отладки выполняется, то такой подход называется динамическим. При этом исследуются выходные и промежуточные значения переменных, и если они отличаются от предполагаемых, то делаются необходимые корректировки в программе, и процесс выполнения программы повторяется.

При статическом тестировании проводится достаточно глубокий и полный анализ управляющих и информационных связей программы. Такой анализ основан на исследовании преобразований управления и данных, выполняемых каждым оператором программы, и затем объединении этих преобразований в единую цепочку. В результате формируются единые потоки управления и данных, а сам метод анализа назван потоковым.

Потоки управления и данных представляются в виде управляющего и информационного графов соответственно.

По характеру воздействия на текст программы методы отладки классифицируются как неразрушающие и разрушающие.

неразрушающий метод не предполагает модификации программы во время отладки. Это, как правило, все статические методы и часть динамических. При статических методах отладки нет в принципе необходимости во внесении изменений в отлаживаемую программу, т.к.

всегда можно имитировать такое изменение с помощью других программ, обеспечивающих процесс отладки.

разрушающий метод отладки предполагает модифицирование программы на время отладки. примерами такой модификации могут быть:

расширение программы макрокоманды отладки;

добавление в программу отладочных операторов;

создание контрольных точек;

включение в текст операторов распечатки промежуточных данных;

изменение участков программы или отдельных команд.

После завершения процесса отладки такие модифицированные участки программ необходимо восстанавливать. В случае обнаружения новых ошибок необходимо снова модифицировать программу и т.д. Таким образом, разрушающие методы отладки "провоцируют" внесение ошибок в программу в процессе отладки, хотя и позволяют эффективно исследовать программу.

Одной из наиболее распространенных и эффективных дисциплин является разработка программ методом сверху вниз, или нисходящая разработка.

При нисходящей разработке первоначально создаются подпрограммы, находящиеся на верхних "этажах" схемы иерархии (схемы связи) подпрограмм, т.е. те, которые включают в работу весь программный комплекс и осуществляют вызов других подпрограмм.

Существует также разработка программ методом снизу вверх или восходящая разработка, которая предполагает вначале разработку и отладку подпрограмм самых низких уровней, затем более высоких. Однако этот подход имеет более узкую область эффективного применения, чем нисходящая разработка.

Кроме рассмотренных, существуют и другие приемы отладки программ.

Объект испытаний. Объектом испытаний является система удаленного тестирования знаний, применяемая для тестирования пользователей по сети.

Цель испытаний. Целью проведения испытаний является выявление случаев некорректной работы системы и их устранение. Испытания проводятся согласно с ГОСТ 19.301-79 «Программа и методика испытаний».

Требования к программе. Программный комплекс проверки знаний должен выполнять обозначенные в техническом задании функции и не приводить к сбоям в случае ввода пользователем некорректной информации.

Состав и порядок испытаний.

Порядок и результаты испытаний приведены в таблице 3.1.


Таблица 3.1 Состав, порядок и результаты испытаний

№ДействиеОжидаемый результатДействительный результат1Ввод неверного пароляОтказ в доступеОтказ в доступе2Попытка входа без пароляОтказ в доступеОтказ в доступе3Ввод неверного логинаОтказ в доступеОтказ в доступе4Попытка тестирования пользователем, не имеющим на это правОтказ в доступеОтказ в доступе5Попытка входа в модуль администрирования или редактор тестов пользователя, не имеющего на это правОтказ в доступе, предложения повторного входаОтказ в доступе, закрытие приложения6Попытка добавления в БД некорректного файла тестового набораВывод сообщения об ошибкеВывод сообщения об ошибке

Таблица 3.1(продолжение)

№ДействиеОжидаемый результатДействительный результат7 Удаление пользователяБудет удален только пользователь, результаты останутсяУдалены и пользователь, и результаты8Закрытие модуля тестирования во время сеансаВывод предупреждения о незаконченном сеансеВывод предупреждения о незаконченном сеансе9Переход пользователя при тестировании к следующему вопросу без ответа на текущийПереход к следующему вопросу, занесение в базу ответа как неправильныйОшибка доступа к базе данных

Выявленное в ходе тестирования несоответствие ожидаемого результата и действительного по пунктам 5 и 9 были устранены, ошибки исправлены.

Проведенное тестирование компонентов программного комплекса позволило выявить и исправить существующие ошибки в работе. В конечном итоге получен готовый работоспособный продукт.


.4 Оценка надежности


Надежность разрабатываемой системы складывается из двух составляющих: надежность базы данных и надежность программного комплекса. Надежность базы данных обеспечивается ее внутренними механизмами. В частности выделим поддержку устойчивых к сбоям кластеров (Failover Clustering), в основе функционирования которых лежат средства оперативного переноса данных на запасное аппаратное обеспечение в случае аппаратного сбоя основного сервера. Размер подобных кластеров может достигать восьми узлов в зависимости от того, какая именно редакция Windows Server 2003 установлена на сервере баз данных. Отметим, что кластеры, устойчивые к сбоям, могут быть созданы и для аналитических служб, служб уведомлений, средств репликации данных. Еще одно средство повышения надежности SQL Server 2005 - зеркалирование баз данных, основанное на постоянной передаче журнала транзакций с основного сервера на запасной, что позволяет в случае сбоя основного сервера немедленно переключить клиентские приложения на запасной сервер без задержки, поскольку состояние данных на нем синхронно с состоянием данных основного сервера.

Надежность программных модулей обусловлена их защитой двоичным кодом приложения. В модулях реализован механизм проверки вводимых пользователем данных, что так же увеличивает надежность системы. Аутентификация пользователей при входе в редактор тестов и модуль администрирования повышает защищенность данных от несанкционированного чтения и изменения.

В совокупности, оценка надежности базы данных и программного комплекса говорит о высокой надежности всей системы в целом.


.5 Разработка сопроводительных документов


Для обеспечения работоспособности компонентов комплекса необходимо подключить базу данных к серверу СУБД SQL server 2005. Предполагается, что SQL server 2005 установлен на сервер и сконфигурирован нужным образом. Для подключения базы данных необходимо предпринять следующие действия:

1.Запускаем SQL Server Management Studio

2.Выбираем пункт контекстного меню объекта Databases->Attach…


Рисунок 3.7 - Подключение базы данных


В появившемся окне нажимаем кнопку Add и добавляем файл DB_test.mdf из корневого каталога установочного диска.


Рисунок 3.8 - Подключение базы данных (продолжение)


По желанию можно изменить настройки размещения файлов базы данных на сервере. Необходимо помнить, что размер базы постоянно увеличивается, поэтому на диске должно быть достаточное свободное пространство. После завершения подключения базы данных объект с ее именем должен появиться в дереве объектов SQL Server Management Studio в разделе Databases. Это является признаком успешного подключения базы.

Если по каким либо причинам подключить базу не удастся, то можно воспользоваться скриптом, который сгенерирует новую пустую базу данных. Для этого необходимо загрузить файл db_generation_script.sql из корневого каталога установочного диска в среду SQL Server Management Studio и запустить запрос на выполнение. Текст скрипта приведен в приложении А.

После подключения базы необходимо настроить подключение модулей редактора тестов и администрирования к базе данных. Для этого скопируйте файл connection.udl из корневого каталога установочного диска в каьалог %System Drive%\ Program Files\Common Files\System\Ole DB\Data Links\. После этого двойным щелчком по файлу запустите редактор строки подключения Microsoft. На странице «Подключение» введите IP-адрес или имя сервера, на который была установлена база данных DB_test. Выберите пункт «учетные сведения Windows NT» и имя базы данных. Если все сделано правильно, то после нажатия на кнопку «Проверить подключение» появится сообщения об успешном подключении.


Рисунок 3.9 - Настройка подключения базы


Нажмите кнопку «ОК», настройка соединения закончена. После можно приступать к работе с редактором тестов и модулем администрирования.


4. Технико-экономическое обоснование разработки


.1 Расчет себестоимости разрабатываемой системы


Затраты на выполнение проекта состоят из затрат на заработную плату исполнителям, затрат на закупку или аренду оборудования и затрат на накладные расходы (4.1).


К = Сзарп + Соб + Снакл 4.1


где СЗАРП - заработная плата исполнителей, СОБ -затраты на обеспечение необходимым оборудованием, СНАКЛ- накладные расходы.


.2 Затраты на выплату исполнителям заработной платы.


Определяется следующим соотношением:


4.2


где СЗ.ОСН - основная заработанная плата, СЗ.ДОП - дополнительная заработная плата, СЗ.ОТЧ - отчисление с заработанной платы.


.3 Расчет основной заработанной платы.

При дневной оплате труда исполнителей проводится на основе данных по окладам и графику занятости исполнителей (4.3):


4.3


где ТЗАН - число дней, отработанных исполнителем проекта, ОДН - дневной оклад исполнителя. При 8-и часовом рабочем дне он рассчитывается по соотношению 4.4.


4.4


где ОМЕС - месячный оклад, FM - месячный фонд рабочего времени (4.5).


4.5


где tp - продолжительность рабочего дня, DK - общее число дней в году, DB - число выходных дней в году, DП - число праздничных дней в году.

Для 2007 года количество рабочих дней (с учетом праздников и выходных) 249, продолжительность рабочего дня составляет 8 часов. Учитывая полученные данные и формулу (4.5), получим:

FМ = 8*249/12 = 166

Оклад программиста в компании «Этна IT» составляет 14970 р.

С учетом налога на доходы физических лиц размер месячного оклада увеличивается, что отражено в формуле 4.6:


4.6


где О - оклад, НДФЛ - налог на доходы с физических лиц (13%).

Таким образом, месячный оклад составляет:

OМ = 14970(1+0,13) = 16 916 р.

Тогда дневной оклад составляет:

ОДН = 16916*8/166 = 815 р.

Расчет затрат рабочего времени (при 8-ми часовом рабочем дне) на выполнение программного продукта, представлен в таблице 4.1.


Таблица 4.1 - Затраты рабочего времени на разработку системы

ЭтапСодержание работыТрудозатратыЧел.-часЧел.-дни1Разработка структуры функционирования системы136171.1Разработка алгоритма функционирования системы1621.2Разработка структуры базы данных4051.3Разработка алгоритма прохождения теста4051.4Разработка алгоритма кодирования фалов теста4052Реализация проекта системы320402.1Реализация структуры базы данных 120152.2Реализация программного модуля120152.3Реализация интерфейса системы для пользователей80103Проведение тестирования разработанного программного модуля 243ИТОГО48060

Таким образом, число дней, затраченных на разработку составляет 60.

Рассчитаем Сизарп в соответствии с формулой (4.3):

Сизарп = 60*815 = 48 900 р.


.4 Расходы на дополнительную заработанную плату


Учитывают все выплаты непосредственно исполнителям за время не проработанное на производстве, но предусмотренное законодательством, в том числе: оплата очередных отпусков, компенсация за недоиспользованный отпуск, и др. Величина этих выплат составляет 20% от размера основной заработной платы:


4.7


Получаем:

Сз.доп = 0,2*48900 = 9 780 р.


.5 Отчисления с заработанной платы.


Состоят в настоящее время в уплате единого социального налога. Согласно налоговому кодексу РФ применяются ставки налога для отчисления в федеральный бюджет РФ, фонд социального страхования, фонды обязательного медицинского страхования (федеральный и территориальный фонды).

Отчисления с заработанной платы составляют:


4.8


где НСОЦ - отчисления с заработанной платы в виде единого социального налога.

С 1 января 2006 года ставка единого социального налога составляет:

) отчисления в федеральный бюджет - 20%;

) отчисления в фонд социального страхования - 3,2%;

) отчисления в фонд обязательного медицинского страхования:

.1) федеральный фонд обязательного медицинского страхования - 0,8%;

.2) территориальный фонд обязательного медицинского страхования - 2,0%.

Таким образом, ставка единого социального налога составляет 26%.

Тогда отчисления с заработанной платы составят:

Сз.от = (48900+9780)*0,26 = 15 257 р.


4.6 Затраты, связанные с обеспечением работ оборудованием.


В таблице 4.2 представлено оборудование, необходимое для разработки проекта и стоимость этого оборудования.


Таблица 4.2 - Затраты, связанные с обеспечением работ оборудованием

№ОборудованиеСтоимость, руб1Системный блок15 0002Монитор7 0003Клавиатура5004Манипулятор «Мышь»250Итого:22 750

4.7 Расходы на приобретение программного обеспечения.


Для осуществления разработки программного комплекса необходимы следующие программные продукты Microsoft Windows 2003 Server, Microsoft SQL Server 2005 (SE), Borland Delphi 7.0 Enterprise Edition, CA ERwin Data Modeler 7.0. Затраты на программное обеспечение приведены в таблице 4.3


№Название программного продуктаСтоимость, руб1Microsoft Windows 2003 Server16 5102Microsoft SQL Server 2005 (SE)143 8503Borland Delphi 7.0 Enterprise Edition30 8694CA ERwin Data Modeler 7.0.60 000Итого:251 229

4.8 Накладные расходы, связанные с выполнением проекта.

Накладные расходы составляют 60% от основной заработной платы (4.11)


4.11


Получаем: Снакл = 0,6*48900 = 29 340 р.


Калькуляция стоимости программного продукта.

Калькуляция себестоимости разрабатываемой системы приведена в таблице 4.3.


Таблица 4.3 - Калькуляция стоимости разрабатываемой системы

№Статьи затратСтоимость, руб1Основная заработная плата48 9002Дополнительная заработная плата97803Отчисления на социальные нужды15 2574Затраты на оборудование22 7505Накладные расходы29 3406Расходы на приобретение ПО251 229Итого:377 256

5. Рекомендации по безопасности жизнедеятельности и экологии


Порядок аттестации рабочего места по условию освещенности регламентируется в МУ 2.2.4.706-98/МУ ОТ РМ 01-98. Согласно им, аттестация рабочих мест по условиям освещения выполняется в несколько этапов:

) работа с нормативной документацией (см. табл.5.1.);

) оценка соответствия исполнения применяемых в осветительной установке (ОУ) светильников требованиям по защите от воздействия среды в помещении (табл. 5.3);

) обследование условий освещения рабочих мест (табл. 5.2);

) обработка результатов обследования и оформление протокола (приложение В);

) проверка соответствия показателей освещения нормативным требованиям;

) оценка условий освещения по гигиеническим критериям в соответствии с руководством Р 2.2.013-94;

) анализ причин несоответствия условий освещения рабочих мест требованиям нормативных документов и разработка предложений по совершенствованию ОУ с целью приведения условий освещения в соответствие с нормативной документацией.

Работа с нормативной документацией заключается в определении нормативных требований к освещению аттестуемых рабочих мест.

Проверка соответствия исполнения светильников требованиям по защите от воздействия среды в помещении обязательна, если аттестуемые рабочие места расположены в помещениях с тяжелыми условиями среды (взрывоопасных, пожароопасных, с химически активной средой и т. п.).

При несоответствии исполнения светильников требованиям по защите от воздействия среды в помещении аттестация не проводится и дается предписание о необходимости реконструкции ОУ.

Обследование условий освещения заключается в замерах, визуальной оценке или определении расчетным путем следующих показателей:

) коэффициента естественной освещенности;

) освещенности рабочей поверхности;

) показателя ослепленности;

) коэффициента пульсации освещенности;

) отраженной блескости (наличия эффективных мероприятий по ее ограничению).

Проверка перечисленных показателей на соответствие их требованиям норм осуществляется путем сопоставления результатов обследования с нормативными величинами, указанными в отраслевых (ведомственных) нормативных документах по искусственному освещению или в СНиП 23-05-95.

При отсутствии для отдельных видов работ отраслевых (ведомственных) норм искусственного освещения нормируемые показатели освещения определяются в зависимости от разряда и подразряда зрительных работ по СНиП 23-05-95.

По результатам аттестации на основе анализа причин неудовлетворительных условий освещения отдельных рабочих мест разрабатываются предложения по совершенствованию ОУ.


Таблица 5.1 - Перечень основных нормативных документов, необходимых для оценки условий освещения

№№ п/п Статус (ГОСТ, СН, СНиП, МУ и т. д.) и № документа, дата утверждения, ведомство Наименование (полное)1 СНиП 23-05-95, 02.08.95, Минстрой России Строительные нормы и правила Российской Федерации. Естественное и искусственное освещение 2 Отраслевые (ведомственные) нормативные документы по искусственному освещению утверждены в разное время соответствующими министерствами и ведомствами Отраслевые (ведомственные) нормы искусственного освещения предприятий различных отраслей промышленности, правила техники безопасности и производственной санитарии предприятий агропромышленного комплекса №№ п/п Статус (ГОСТ, СН, СНиП, МУ и т. д.) и № документа, дата утверждения, ведомство Наименование (полное)3 ГОСТ 24940-96, 20.10.96, Минстрой России Здания и сооружения. Методы измерения освещенности 4 ГОСТ 26824-86, 30.01.86, Госстрой СССР Здания и сооружения. Методы измерения яркости 5 Р 2.2.013-94, 12.07.94, Госкомсанэпиднадзор России Гигиенические критерии оценки условий труда по показателям вредности и опасности факторов производственной среды, тяжести и напряженности трудового процесса 6 ГОСТ 17677-82, 29.06.87, Госстандарт СССР Светильники, общие технические условия

Таблица 5.2 -Перечень средств измерения для оценки условий освещения

№№ п/п Наименование (тип) прибора Техническая характеристика Пределы и единицы измерений Питание Масса, кг 1 Люксметр типа "Кварц-21"0,1-100000 лк Сеть 220 В, 50 Гц; автономное0,6 2Люксметр типа "Аргус-01"5-200000 лк Автономное 0,25 3Люксметр типа Ю-116 5-100000 лк Автономное 1,75 4Люксметр типа Ю-117 0,1-100000 лк Автономное 2,0 №№ п/п Наименование (тип) прибора Техническая характеристика 5Люксметр-яркомер типа "ТКА-04/3"10-200000 лк 10-200000 кд/м Автономное 0,39 6 Яркомер типа "Аргус-02"5-200000 кд/м Автономное 0,35 7 Яркомер типа ФПЧ 0,2-50000 кд/м Сеть 220 В, 50 Гц; 12 В 14,5


Таблица 5.3. - Рекомендуемые типы светильников для помещений с различными условиями среды

Типовые кривые силы светаТипы светильников Светильники для нормальных, пожароопасных класса П-11а* и жарких** помещений. Степень защиты не менее 1 Р20М НСП04 Д1 ГВП02, ЛВП02, ЛВП05, ЛВП06 Д2 ЛД, ЛДОР, ЛСП02, ЛСП06, ГСП18, НСП01, НСП21 ДЗ РСП05, РСП08, РСП18, РСП21, ЛСП02, ЛСП0б Г1 РСП05, ГСП18, ЛСП13 Г2 НСП17, РСП08, РСП18, ГСП18 ГЗ ГСП17, РСП05 К1 РСП05, РСП08, РСП18, ГСП17, ГСП18, НСП17 КЗ ГСП17 Ш1 РСП08, ЛСП13, НСП17 Светильники для пыльных*** помещений. Степень защиты не менее 5Х, IP5XМ РПП05, ППР Д1 ЛВП02, ПВЛП, ПВЛ1, ППР, НСП11, НСП21, РСП11 Д2 НСП21, ЖСП20 Типовые кривые силы светаТипы светильников ДЗ ПВЛМ-Д, ПВЛМ-ДО, РСП05, РСП08, РСП12, РСП13, РСП14, РСП16, РСП20 Г1 РСП05, РСП13, ГСП18 Г2 РСП08, РСП13, ГСП18, НСП17 Г3 РСП05, ЖСП01 К1 РСП05, РСП08, РСП13, НСП17, ЖСП01 Ш1 РСП08, РСП11, РСП20; НСП17 НТ РСП11, ЛСП18, НСП02, НСП09 Светильники для помещений с химически активной средой**** Степень защиты не менее 5 4; IP53М НСП02, НСП03 Д1 ЛСП16, ЛСП18, ПВЛП, ПВЛ1, ЛВП02, ЛВП04 Д2 ВЛВ, ЖСП21, РСП21 ДЗ ЖПП01 Г1 ЛВП02, ЛВП04, ЛВП33, РСП13, РСП16 Г3 РСП13 К1 РСП13 НТ ЛСП18 Светильники для пожароопасных помещений классов П-I, П-II. Степень защиты не менее 5 X (с ЛЛ), IP5X (с ГЛВД и ЛН) М РСП27, НСП11, ППР Д1 РСП11, РСП12, РСП13, НСП11, НСП22, ППР Д2 ЖСП21, РСП21, НСП20, ПВЛМ-ДР, ПВЛМ-ДОР ДЗ ПВЛМ-Д, ПВЛМ-ДО, НСП20, РСП20, РСП21 НТ ЛСП18, ЛСП22, ПВЛМ, НСП02, НСП09, КОУ1 Светильники для взрывоопасных помещений класса В-1. Степень защиты не менее IP5X (взрывонепроницаемое)М ВЗГ, ВЗГ/В4А, РСП25 Д1 РСП25, ВЗГ, ВЗГ/В4А Д2 ГСП25, РСП25 ДЗ ГСП25 НТ КОУ1 Типовые кривые силы светаТипы светильников Светильники для взрывоопасных помещений классов В-Ia, B-II. Степень защиты не менее IP5X (повышенной надежности против взрыва)М НОДЛ, НОГЛ, Н4Т4Л, Н4Т5Л, Н4Б, Н4Т2Н, Н4БН Д1 НОДЛ, НОГЛ, Н4Т4Л, Н4Т5Л, Н4Б, Н4Т2Н, Н4БН НТ КОУ1 * Для помещений класса П-IIа допускается использование светильников в исполнении IР2Х: с ГЛВД - при наличии приспособлений, препятствующих выпадению ламп (РСП18, ГСП18); с ЛЛ - при выполнении ввода в светильник проводом с негорючей оболочкой или в стальной трубе; светильников исполнения 2 X с ЛН при наличии сплошного защитного стекла или рассеивателя из силикатного стекла.** Рекомендуется применение амальгамных люминесцентных ламп.*** Не рекомендуется применение светильников с решетками, сетками и другими элементами, собирающими пыль.**** Рекомендуется применение светильников, детали которых не подвержены действию данной химически активной среды, желательно с корпусами и отражателями из влагостойкой пластмассы, фарфора или покрытые силикатной эмалью.

Заключение


В итоге выполнения дипломного проекта были получены следующие основные результаты и выводы:

·Обоснована целесообразность и актуальность разработки системы удаленного тестирования знаний.

·Изучена предметная область вопроса, рассмотрены существующие решения проблемы.

·Рассмотрены и изучены существующие аналоги системы, выявлены их достоинства и недостатки, конкретизированы данные технического задания

·Разработана структура системы в целом и отдельных модулей в частности.

·Разработаны и описаны рабочие алгоритмы системы

·Разработана структура базы данных, используемой системой

·Конкретизированы требования к средам передачи информации

·Описана технология обработки входной информации

·Разработан интерфейс пользователя

Наряду с этим, в итоге выполнения дипломного проекта были разработаны:

·Рабочие программы на языках Delphi, удовлетворяющие всем требованиям технического задания.

·Форма выходных документов, коими являются групповые и частные отчеты.

·Инструкция по установке и пользованию системой.

Были проведены:

·Процедура тестирования, согласно ГОСТ 19.301-79 «Программа и методика испытаний». Были исправлены выявленные в процессе тестирования ошибки и недочеты.

·Оценка надежности и качества функционирования системы

Наряду с этим, был проведен расчет себестоимости и технико-экономическое обоснование разработки, приведены рекомендации по безопасности жизнедеятельности и экологии.

Возможным путем развития проекта может стать переход от клиент-серверной к многозвенной архитектуре приложения баз данных. При этом вся обработка данных будет производиться на сервере приложений. На сторону клиента будут приходить лишь результаты запросов. Введение в многозвенную архитектуру ВЕБ-сервера позволит осуществлять работу компонентов системы с помощью Интернет-технологий.

В результате выполнения дипломного проекта был получен полностью функциональный программный комплекс, сочетающий в себе редактор тестов, модуль администрирования пользователей и просмотра отчетов, модуль тестирования знаний. Разработанный комплекс удовлетворяет всем требованиям технического задания и готов к применению на практике.


Список использованных источников


1.Нильсен, Пол. Microsoft SQL Server 2005. Библия пользователя/ Пол Нильсен М.: ООО «И.Д. Вильямс», 2008. - 1232с.:ил.

2.Губер, Мартин. Понимание SQL/Мартин Губер - М.: 1993

.Архангельский, А.Я. Программирование в Delphi 7/А. Я. Архангельский -М.: ООО «Бином-Пресс», 2003г.-1152с.:ил.

.Дарахвелидзе, П. Г. Программирование в Delphi 7/ П. Г. Дарахвелизде, Е. П. Марков - СПб.: БХВ-Петербург, 2003.-784с.:ил.

.Липаев, В.В. Отладка сложных программных комплексов / В.В. Липаев - М.: Энергоатомиздат, 1993 - 251 с.

.Липаев, В.В. Методы обеспечения качества крупномасштабных программных средств / В.В. Липаев - М.: СИНТЕГ, 2003 - 350 с.

.Меняев М.Ф. Содержание организационно-экономической части дипломного проекта (для проектов, связанных с разработкой программного обеспечения): Учеб. пособие / М.Ф. Меняев - М.: МГТУ им. Н.Э. Баумана, 2002.- 24 с.

.Кэнту, М. Delphi 7 для профессионалов/ М. Кэнту.-СПб.:Питер,2004.-1101с.:ил.

.МУ 2.2.4.706-98/МУ ОТ РМ 01-98.


Приложение А


Скрипт генерации новой базы данных

CREATE TABLE Answers

(

Answer_id int IDENTITY (1,1) ,

Answer_question_id int NOT NULL ,_number integer NULL ,_text text NULL ,_score integer NULL ,_is_right bit NULL ,_corresp integer NULL ,_picture image NULL

)

TABLE AnswersCONSTRAINT XPKAnswers PRIMARY KEY NONCLUSTERED (Answer_id ASC)TABLE Group_sections

(_id int IDENTITY (1,1) ,_groupe_id int NOT NULL ,_section_id int NOT NULL

)

TABLE Group_sectionsCONSTRAINT XPKGroup_sections PRIMARY KEY NONCLUSTERED (Gs_id ASC)


TABLE Groups

(_id int IDENTITY (1,1) ,_name varchar(512) NULL ,_description varchar(512) NULL ,_hidden bit NULL

)


TABLE GroupsCONSTRAINT XPKGroups PRIMARY KEY NONCLUSTERED (Groupe_id ASC)

TABLE Questions

(_id int IDENTITY (1,1) ,_test_id int NOT NULL ,_number integer NULL ,_time char(8) NULL ,_type integer NULL ,_weigth integer NULL ,_Text text NULL ,_picture image NULL

)

TABLE QuestionsCONSTRAINT XPKQuestions PRIMARY KEY NONCLUSTERED (Question_id ASC)


TABLE Sections

(_id int IDENTITY (1,1) ,_name varchar(512) NULL ,_hidden bit NULL

)

TABLE SectionsCONSTRAINT XPKSections PRIMARY KEY NONCLUSTERED (Section_id ASC)

TABLE Tests

(_ID int IDENTITY (1,1) ,_description varchar(512) NULL ,_section_ID int NOT NULL ,_name varchar(512) NULL ,_type integer NULL ,_author varchar(512) NULL ,_question_count integer NULL ,_is_random_answers bit NULL ,_is_time_limit bit NULL ,_time_limit char(8) NULL ,_is_back bit NULL ,_question_limit integer NULL

)

TABLE TestsCONSTRAINT XPKTests PRIMARY KEY NONCLUSTERED (Test_ID ASC)

TABLE User_answers

(_answer_ID int IDENTITY (1,1) ,_answer_qnumber integer NULL ,_answer_question text NULL ,_answer_answer text NULL ,_answer_time char(8) NULL ,_answer_is_right bit NULL ,_answer_score integer NULL ,_answer_answered bit NULL ,_answer_user_result_id int NOT NULL

)

TABLE User_answersCONSTRAINT XPKUser_answers PRIMARY KEY NONCLUSTERED (User_answer_ID ASC)

TABLE User_results

(_result_id int IDENTITY (1,1) ,_result_comleted bit NULL ,_result_time_begin datetime NULL ,_result_time_end datetime NULL ,_result_completed_questions integer NULL ,_result_right_questions integer NULL ,_result_score integer NULL ,_result_percent_right float NULL ,_result_total_questions integer NULL ,_result_test_title varchar(128) NULL ,_result_User_id int NOT NULL ,_result_test_id int NOT NULL

)

TABLE User_resultsCONSTRAINT XPKUser_results PRIMARY KEY NONCLUSTERED (User_result_id ASC)

TABLE Users

(_id int IDENTITY (1,1) ,_group_id int NOT NULL ,_name varchar(512) NULL ,_code varchar(128) NULL ,_password varchar(128) NULL ,_info varchar(512) NULL ,_deleted bit NULL ,_mail varchar(128) NULL ,_grants integer NULL ,_disable_test bit NULL

)

TABLE UsersCONSTRAINT XPKUsers PRIMARY KEY NONCLUSTERED (User_id ASC)

TABLE AnswersCONSTRAINT R_6 FOREIGN KEY (Answer_question_id) REFERENCES Questions(Question_id)DELETE CASCADEUPDATE NO ACTION

TABLE Group_sectionsCONSTRAINT R_9 FOREIGN KEY (Gs_section_id) REFERENCES Sections(Section_id)DELETE CASCADEUPDATE NO ACTION

TABLE Group_sectionsCONSTRAINT R_10 FOREIGN KEY (Gs_groupe_id) REFERENCES Groups(Groupe_id)DELETE NO ACTIONUPDATE NO ACTION

TABLE QuestionsCONSTRAINT R_5 FOREIGN KEY (Question_test_id) REFERENCES Tests(Test_ID)DELETE CASCADEUPDATE NO ACTION

TABLE TestsCONSTRAINT R_8 FOREIGN KEY (Test_section_ID) REFERENCES Sections(Section_id)DELETE CASCADEUPDATE NO ACTION

TABLE User_answersCONSTRAINT R_16 FOREIGN KEY (User_answer_user_result_id) REFERENCES User_results(User_result_id)DELETE NO ACTIONUPDATE NO ACTION

TABLE User_resultsCONSTRAINT R_14 FOREIGN KEY (User_result_User_id) REFERENCES Users(User_id)DELETE NO ACTIONUPDATE NO ACTION

TABLE User_resultsCONSTRAINT R_15 FOREIGN KEY (User_result_test_id) REFERENCES Tests(Test_ID)DELETE NO ACTIONUPDATE NO ACTION

TABLE UsersCONSTRAINT R_7 FOREIGN KEY (User_group_id) REFERENCES Groups(Groupe_id)DELETE CASCADEUPDATE NO ACTION

TRIGGER tD_Answers ON Answers FOR DELETE AS

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* DELETE trigger on Answers */@errno int,

@errmsg varchar(255)

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Questions R/6 Answers on child delete no action */

/* ERWIN_RELATION:CHECKSUM="000139e1", PARENT_OWNER="", PARENT_TABLE="Questions"_OWNER="", CHILD_TABLE="Answers"C_VERB_PHRASE="R/6", C2P_VERB_PHRASE="R/6", _CONSTRAINT="R_6", FK_COLUMNS="Answer_question_id" */EXISTS (SELECT * FROM deleted,Questions

/* %JoinFKPK(deleted,Questions," = "," AND") */.Answer_question_id = Questions.Question_id ANDEXISTS (* FROM Answers

/* %JoinFKPK(Answers,Questions," = "," AND") */.Answer_question_id = Questions.Question_id

)

)@errno = 30010,

@errmsg = 'Cannot delete last Answers because Questions exists.'ERROR



/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */:@errno @errmsgtransaction

TRIGGER tU_Answers ON Answers FOR UPDATE AS

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* UPDATE trigger on Answers */@NUMROWS int,

@nullcnt int,

@validcnt int,

@insAnswer_id int,

@errno int,

@errmsg varchar(255)

@NUMROWS = @@rowcount

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Questions R/6 Answers on child update no action */

/* ERWIN_RELATION:CHECKSUM="000157da", PARENT_OWNER="", PARENT_TABLE="Questions"_OWNER="", CHILD_TABLE="Answers"C_VERB_PHRASE="R/6", C2P_VERB_PHRASE="R/6", _CONSTRAINT="R_6", FK_COLUMNS="Answer_question_id" */

/* %ChildFK(" OR",UPDATE) */(Answer_question_id)@nullcnt = 0@validcnt = count(*)inserted,Questions

/* %JoinFKPK(inserted,Questions) */.Answer_question_id = Questions.Question_id

/* %NotnullFK(inserted," IS NULL","select @nullcnt = count(*) from inserted where"," AND") */

@validcnt + @nullcnt != @NUMROWS@errno = 30007,

@errmsg = 'Cannot update Answers because Questions does not exist.'ERROR

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */:@errno @errmsgtransaction

TRIGGER tD_Group_sections ON Group_sections FOR DELETE AS

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* DELETE trigger on Group_sections */@errno int,

@errmsg varchar(255)

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Sections R/9 Group_sections on child delete no action */

/* ERWIN_RELATION:CHECKSUM="0002881c", PARENT_OWNER="", PARENT_TABLE="Sections"_OWNER="", CHILD_TABLE="Group_sections"C_VERB_PHRASE="R/9", C2P_VERB_PHRASE="R/9", _CONSTRAINT="R_9", FK_COLUMNS="Gs_section_id" */EXISTS (SELECT * FROM deleted,Sections

/* %JoinFKPK(deleted,Sections," = "," AND") */.Gs_section_id = Sections.Section_id ANDEXISTS (* FROM Group_sections

/* %JoinFKPK(Group_sections,Sections," = "," AND") */_sections.Gs_section_id = Sections.Section_id

)

)@errno = 30010,

@errmsg = 'Cannot delete last Group_sections because Sections exists.'ERROR


/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Groups R/10 Group_sections on child delete no action */

/* ERWIN_RELATION:CHECKSUM="00000000", PARENT_OWNER="", PARENT_TABLE="Groups"_OWNER="", CHILD_TABLE="Group_sections"C_VERB_PHRASE="R/10", C2P_VERB_PHRASE="R/10", _CONSTRAINT="R_10", FK_COLUMNS="Gs_groupe_id" */EXISTS (SELECT * FROM deleted,Groups

/* %JoinFKPK(deleted,Groups," = "," AND") */.Gs_groupe_id = Groups.Groupe_id ANDEXISTS (* FROM Group_sections

/* %JoinFKPK(Group_sections,Groups," = "," AND") */_sections.Gs_groupe_id = Groups.Groupe_id

)

)@errno = 30010,

@errmsg = 'Cannot delete last Group_sections because Groups exists.'ERROR



/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */:@errno @errmsgtransactionTRIGGER tU_Group_sections ON Group_sections FOR UPDATE AS

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* UPDATE trigger on Group_sections */@NUMROWS int,

@nullcnt int,

@validcnt int,

@insGs_id int,

@errno int,

@errmsg varchar(255)

@NUMROWS = @@rowcount

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Sections R/9 Group_sections on child update no action */

/* ERWIN_RELATION:CHECKSUM="0002f0e4", PARENT_OWNER="", PARENT_TABLE="Sections"_OWNER="", CHILD_TABLE="Group_sections"C_VERB_PHRASE="R/9", C2P_VERB_PHRASE="R/9", _CONSTRAINT="R_9", FK_COLUMNS="Gs_section_id" */

/* %ChildFK(" OR",UPDATE) */(Gs_section_id)@nullcnt = 0@validcnt = count(*)inserted,Sections

/* %JoinFKPK(inserted,Sections) */.Gs_section_id = Sections.Section_id

/* %NotnullFK(inserted," IS NULL","select @nullcnt = count(*) from inserted where"," AND") */@nullcnt = count(*) from inserted where.Gs_section_id IS NULL@validcnt + @nullcnt != @NUMROWS@errno = 30007,

@errmsg = 'Cannot update Group_sections because Sections does not exist.'ERROR


/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Groups R/10 Group_sections on child update no action */

/* ERWIN_RELATION:CHECKSUM="00000000", PARENT_OWNER="", PARENT_TABLE="Groups"_OWNER="", CHILD_TABLE="Group_sections"C_VERB_PHRASE="R/10", C2P_VERB_PHRASE="R/10", _CONSTRAINT="R_10", FK_COLUMNS="Gs_groupe_id" */

/* %ChildFK(" OR",UPDATE) */(Gs_groupe_id)@nullcnt = 0@validcnt = count(*)inserted,Groups

/* %JoinFKPK(inserted,Groups) */.Gs_groupe_id = Groups.Groupe_id

/* %NotnullFK(inserted," IS NULL","select @nullcnt = count(*) from inserted where"," AND") */@nullcnt = count(*) from inserted where.Gs_groupe_id IS NULL@validcnt + @nullcnt != @NUMROWS@errno = 30007,

@errmsg = 'Cannot update Group_sections because Groups does not exist.'ERROR



/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */:@errno @errmsgtransactionTRIGGER tD_Groups ON Groups FOR DELETE AS

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* DELETE trigger on Groups */@errno int,

@errmsg varchar(255)

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Groups R/7 Users on parent delete cascade */

/* ERWIN_RELATION:CHECKSUM="0001bdd4", PARENT_OWNER="", PARENT_TABLE="Groups"_OWNER="", CHILD_TABLE="Users"C_VERB_PHRASE="R/7", C2P_VERB_PHRASE="R/7", _CONSTRAINT="R_7", FK_COLUMNS="User_group_id" */UsersUsers,deleted

/* %JoinFKPK(Users,deleted," = "," AND") */.User_group_id = deleted.Groupe_id


/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Groups R/10 Group_sections on parent delete no action */

/* ERWIN_RELATION:CHECKSUM="00000000", PARENT_OWNER="", PARENT_TABLE="Groups"_OWNER="", CHILD_TABLE="Group_sections"C_VERB_PHRASE="R/10", C2P_VERB_PHRASE="R/10", _CONSTRAINT="R_10", FK_COLUMNS="Gs_groupe_id" */EXISTS (* FROM deleted,Group_sections

/* %JoinFKPK(Group_sections,deleted," = "," AND") */_sections.Gs_groupe_id = deleted.Groupe_id

)@errno = 30001,

@errmsg = 'Cannot delete Groups because Group_sections exists.'ERROR

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */:@errno @errmsgtransaction

TRIGGER tU_Groups ON Groups FOR UPDATE AS

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* UPDATE trigger on Groups */@NUMROWS int,

@nullcnt int,

@validcnt int,

@insGroupe_id int,

@errno int,

@errmsg varchar(255)

@NUMROWS = @@rowcount

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Groups R/7 Users on parent update no action */

/* ERWIN_RELATION:CHECKSUM="00022ae6", PARENT_OWNER="", PARENT_TABLE="Groups"_OWNER="", CHILD_TABLE="Users"C_VERB_PHRASE="R/7", C2P_VERB_PHRASE="R/7", _CONSTRAINT="R_7", FK_COLUMNS="User_group_id" */

/* %ParentPK(" OR",UPDATE) */(Groupe_id)EXISTS (* FROM deleted,Users

/* %JoinFKPK(Users,deleted," = "," AND") */.User_group_id = deleted.Groupe_id

)@errno = 30005,

@errmsg = 'Cannot update Groups because Users exists.'ERROR


/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Groups R/10 Group_sections on parent update no action */

/* ERWIN_RELATION:CHECKSUM="00000000", PARENT_OWNER="", PARENT_TABLE="Groups"_OWNER="", CHILD_TABLE="Group_sections"C_VERB_PHRASE="R/10", C2P_VERB_PHRASE="R/10", _CONSTRAINT="R_10", FK_COLUMNS="Gs_groupe_id" */

/* %ParentPK(" OR",UPDATE) */(Groupe_id)EXISTS (* FROM deleted,Group_sections

/* %JoinFKPK(Group_sections,deleted," = "," AND") */_sections.Gs_groupe_id = deleted.Groupe_id

)@errno = 30005,

@errmsg = 'Cannot update Groups because Group_sections exists.'ERROR

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */:@errno @errmsgtransaction

TRIGGER tD_Questions ON Questions FOR DELETE AS

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* DELETE trigger on Questions */@errno int,

@errmsg varchar(255)

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Questions R/6 Answers on parent delete cascade */

/* ERWIN_RELATION:CHECKSUM="0001fbb8", PARENT_OWNER="", PARENT_TABLE="Questions"_OWNER="", CHILD_TABLE="Answers"C_VERB_PHRASE="R/6", C2P_VERB_PHRASE="R/6", _CONSTRAINT="R_6", FK_COLUMNS="Answer_question_id" */AnswersAnswers,deleted

/* %JoinFKPK(Answers,deleted," = "," AND") */.Answer_question_id = deleted.Question_id


/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Tests R/5 Questions on child delete no action */

/* ERWIN_RELATION:CHECKSUM="00000000", PARENT_OWNER="", PARENT_TABLE="Tests"_OWNER="", CHILD_TABLE="Questions"C_VERB_PHRASE="R/5", C2P_VERB_PHRASE="R/5", _CONSTRAINT="R_5", FK_COLUMNS="Question_test_id" */EXISTS (SELECT * FROM deleted,Tests

/* %JoinFKPK(deleted,Tests," = "," AND") */.Question_test_id = Tests.Test_ID ANDEXISTS (* FROM Questions

/* %JoinFKPK(Questions,Tests," = "," AND") */.Question_test_id = Tests.Test_ID

)

)@errno = 30010,

@errmsg = 'Cannot delete last Questions because Tests exists.'ERROR



/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */:@errno @errmsgtransaction

TRIGGER tU_Questions ON Questions FOR UPDATE AS

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* UPDATE trigger on Questions */@NUMROWS int,

@nullcnt int,

@validcnt int,

@insQuestion_id int,

@errno int,

@errmsg varchar(255)

@NUMROWS = @@rowcount

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Questions R/6 Answers on parent update no action */

/* ERWIN_RELATION:CHECKSUM="00026fe1", PARENT_OWNER="", PARENT_TABLE="Questions"_OWNER="", CHILD_TABLE="Answers"C_VERB_PHRASE="R/6", C2P_VERB_PHRASE="R/6", _CONSTRAINT="R_6", FK_COLUMNS="Answer_question_id" */

/* %ParentPK(" OR",UPDATE) */(Question_id)EXISTS (* FROM deleted,Answers

/* %JoinFKPK(Answers,deleted," = "," AND") */.Answer_question_id = deleted.Question_id

)@errno = 30005,

@errmsg = 'Cannot update Questions because Answers exists.'ERROR

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Tests R/5 Questions on child update no action */

/* ERWIN_RELATION:CHECKSUM="00000000", PARENT_OWNER="", PARENT_TABLE="Tests"_OWNER="", CHILD_TABLE="Questions"C_VERB_PHRASE="R/5", C2P_VERB_PHRASE="R/5", _CONSTRAINT="R_5", FK_COLUMNS="Question_test_id" */

/* %ChildFK(" OR",UPDATE) */(Question_test_id)@nullcnt = 0@validcnt = count(*)inserted,Tests

/* %JoinFKPK(inserted,Tests) */.Question_test_id = Tests.Test_ID

/* %NotnullFK(inserted," IS NULL","select @nullcnt = count(*) from inserted where"," AND") */

@validcnt + @nullcnt != @NUMROWS@errno = 30007,

@errmsg = 'Cannot update Questions because Tests does not exist.'ERROR

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */:@errno @errmsgtransaction

TRIGGER tD_Sections ON Sections FOR DELETE AS

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* DELETE trigger on Sections */@errno int,

@errmsg varchar(255)

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Sections R/8 Tests on parent delete cascade */

/* ERWIN_RELATION:CHECKSUM="00019e4b", PARENT_OWNER="", PARENT_TABLE="Sections"_OWNER="", CHILD_TABLE="Tests"C_VERB_PHRASE="R/8", C2P_VERB_PHRASE="R/8", _CONSTRAINT="R_8", FK_COLUMNS="Test_section_ID" */TestsTests,deleted

/* %JoinFKPK(Tests,deleted," = "," AND") */.Test_section_ID = deleted.Section_id


/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Sections R/9 Group_sections on parent delete cascade */

/* ERWIN_RELATION:CHECKSUM="00000000", PARENT_OWNER="", PARENT_TABLE="Sections"_OWNER="", CHILD_TABLE="Group_sections"C_VERB_PHRASE="R/9", C2P_VERB_PHRASE="R/9", _CONSTRAINT="R_9", FK_COLUMNS="Gs_section_id" */Group_sectionsGroup_sections,deleted

/* %JoinFKPK(Group_sections,deleted," = "," AND") */_sections.Gs_section_id = deleted.Section_id

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */:@errno @errmsgtransactionTRIGGER tU_Sections ON Sections FOR UPDATE AS

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* UPDATE trigger on Sections */@NUMROWS int,

@nullcnt int,

@validcnt int,

@insSection_id int,

@errno int,

@errmsg varchar(255)

@NUMROWS = @@rowcount

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Sections R/8 Tests on parent update no action */

/* ERWIN_RELATION:CHECKSUM="00022bb1", PARENT_OWNER="", PARENT_TABLE="Sections"_OWNER="", CHILD_TABLE="Tests"C_VERB_PHRASE="R/8", C2P_VERB_PHRASE="R/8", _CONSTRAINT="R_8", FK_COLUMNS="Test_section_ID" */

/* %ParentPK(" OR",UPDATE) */(Section_id)EXISTS (* FROM deleted,Tests

/* %JoinFKPK(Tests,deleted," = "," AND") */.Test_section_ID = deleted.Section_id

)@errno = 30005,

@errmsg = 'Cannot update Sections because Tests exists.'ERROR

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Sections R/9 Group_sections on parent update no action */

/* ERWIN_RELATION:CHECKSUM="00000000", PARENT_OWNER="", PARENT_TABLE="Sections"_OWNER="", CHILD_TABLE="Group_sections"C_VERB_PHRASE="R/9", C2P_VERB_PHRASE="R/9", _CONSTRAINT="R_9", FK_COLUMNS="Gs_section_id" */

/* %ParentPK(" OR",UPDATE) */(Section_id)EXISTS (* FROM deleted,Group_sections

/* %JoinFKPK(Group_sections,deleted," = "," AND") */_sections.Gs_section_id = deleted.Section_id

)@errno = 30005,

@errmsg = 'Cannot update Sections because Group_sections exists.'ERROR

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */:@errno @errmsgtransaction

TRIGGER tD_Tests ON Tests FOR DELETE AS

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* DELETE trigger on Tests */@errno int,

@errmsg varchar(255)

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Tests R/5 Questions on parent delete cascade */

/* ERWIN_RELATION:CHECKSUM="0002ff97", PARENT_OWNER="", PARENT_TABLE="Tests"_OWNER="", CHILD_TABLE="Questions"C_VERB_PHRASE="R/5", C2P_VERB_PHRASE="R/5", _CONSTRAINT="R_5", FK_COLUMNS="Question_test_id" */QuestionsQuestions,deleted

/* %JoinFKPK(Questions,deleted," = "," AND") */.Question_test_id = deleted.Test_ID


/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Tests R/15 User_results on parent delete no action */

/* ERWIN_RELATION:CHECKSUM="00000000", PARENT_OWNER="", PARENT_TABLE="Tests"_OWNER="", CHILD_TABLE="User_results"C_VERB_PHRASE="R/15", C2P_VERB_PHRASE="R/15", _CONSTRAINT="R_15", FK_COLUMNS="User_result_test_id" */EXISTS (* FROM deleted,User_results

/* %JoinFKPK(User_results,deleted," = "," AND") */_results.User_result_test_id = deleted.Test_ID

)@errno = 30001,

@errmsg = 'Cannot delete Tests because User_results exists.'ERROR

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Sections R/8 Tests on child delete no action */

/* ERWIN_RELATION:CHECKSUM="00000000", PARENT_OWNER="", PARENT_TABLE="Sections"_OWNER="", CHILD_TABLE="Tests"C_VERB_PHRASE="R/8", C2P_VERB_PHRASE="R/8", _CONSTRAINT="R_8", FK_COLUMNS="Test_section_ID" */EXISTS (SELECT * FROM deleted,Sections

/* %JoinFKPK(deleted,Sections," = "," AND") */.Test_section_ID = Sections.Section_id ANDEXISTS (* FROM Tests

/* %JoinFKPK(Tests,Sections," = "," AND") */.Test_section_ID = Sections.Section_id

)

)@errno = 30010,

@errmsg = 'Cannot delete last Tests because Sections exists.'ERROR



/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */:@errno @errmsgtransactionTRIGGER tU_Tests ON Tests FOR UPDATE AS

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* UPDATE trigger on Tests */@NUMROWS int,

@nullcnt int,

@validcnt int,

@insTest_ID int,

@errno int,

@errmsg varchar(255)@NUMROWS = @@rowcount

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Tests R/5 Questions on parent update no action */

/* ERWIN_RELATION:CHECKSUM="0003c096", PARENT_OWNER="", PARENT_TABLE="Tests"_OWNER="", CHILD_TABLE="Questions"C_VERB_PHRASE="R/5", C2P_VERB_PHRASE="R/5", _CONSTRAINT="R_5", FK_COLUMNS="Question_test_id" */

/* %ParentPK(" OR",UPDATE) */(Test_ID)EXISTS (* FROM deleted,Questions

/* %JoinFKPK(Questions,deleted," = "," AND") */.Question_test_id = deleted.Test_ID

)@errno = 30005,

@errmsg = 'Cannot update Tests because Questions exists.'ERROR


/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Tests R/15 User_results on parent update no action */

/* ERWIN_RELATION:CHECKSUM="00000000", PARENT_OWNER="", PARENT_TABLE="Tests"_OWNER="", CHILD_TABLE="User_results"C_VERB_PHRASE="R/15", C2P_VERB_PHRASE="R/15", _CONSTRAINT="R_15", FK_COLUMNS="User_result_test_id" */

/* %ParentPK(" OR",UPDATE) */(Test_ID)EXISTS (* FROM deleted,User_results

/* %JoinFKPK(User_results,deleted," = "," AND") */_results.User_result_test_id = deleted.Test_ID

)@errno = 30005,

@errmsg = 'Cannot update Tests because User_results exists.'ERROR


/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Sections R/8 Tests on child update no action */

/* ERWIN_RELATION:CHECKSUM="00000000", PARENT_OWNER="", PARENT_TABLE="Sections"_OWNER="", CHILD_TABLE="Tests"C_VERB_PHRASE="R/8", C2P_VERB_PHRASE="R/8", _CONSTRAINT="R_8", FK_COLUMNS="Test_section_ID" */

/* %ChildFK(" OR",UPDATE) */(Test_section_ID)@nullcnt = 0@validcnt = count(*)inserted,Sections

/* %JoinFKPK(inserted,Sections) */.Test_section_ID = Sections.Section_id

/* %NotnullFK(inserted," IS NULL","select @nullcnt = count(*) from inserted where"," AND") */@nullcnt = count(*) from inserted where.Test_section_ID IS NULL@validcnt + @nullcnt != @NUMROWS@errno = 30007,

@errmsg = 'Cannot update Tests because Sections does not exist.'ERROR

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */:@errno @errmsgtransactionTRIGGER tD_User_answers ON User_answers FOR DELETE AS

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* DELETE trigger on User_answers */@errno int,

@errmsg varchar(255)

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* User_results R/16 User_answers on child delete no action */

/* ERWIN_RELATION:CHECKSUM="00017376", PARENT_OWNER="", PARENT_TABLE="User_results"_OWNER="", CHILD_TABLE="User_answers"C_VERB_PHRASE="R/16", C2P_VERB_PHRASE="R/16", _CONSTRAINT="R_16", FK_COLUMNS="User_answer_user_result_id" */EXISTS (SELECT * FROM deleted,User_results

/* %JoinFKPK(deleted,User_results," = "," AND") */.User_answer_user_result_id = User_results.User_result_id ANDEXISTS (* FROM User_answers

/* %JoinFKPK(User_answers,User_results," = "," AND") */_answers.User_answer_user_result_id = User_results.User_result_id

)

)@errno = 30010,

@errmsg = 'Cannot delete last User_answers because User_results exists.'ERROR

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */:@errno @errmsgtransactionTRIGGER tU_User_answers ON User_answers FOR UPDATE AS

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* UPDATE trigger on User_answers */@NUMROWS int,

@nullcnt int,

@validcnt int,

@insUser_answer_ID int,

@errno int,

@errmsg varchar(255)@NUMROWS = @@rowcount

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* User_results R/16 User_answers on child update no action */

/* ERWIN_RELATION:CHECKSUM="0001ac05", PARENT_OWNER="", PARENT_TABLE="User_results"_OWNER="", CHILD_TABLE="User_answers"C_VERB_PHRASE="R/16", C2P_VERB_PHRASE="R/16", _CONSTRAINT="R_16", FK_COLUMNS="User_answer_user_result_id" */

/* %ChildFK(" OR",UPDATE) */(User_answer_user_result_id)@nullcnt = 0@validcnt = count(*)inserted,User_results

/* %JoinFKPK(inserted,User_results) */.User_answer_user_result_id = User_results.User_result_id

/* %NotnullFK(inserted," IS NULL","select @nullcnt = count(*) from inserted where"," AND") */@nullcnt = count(*) from inserted where.User_answer_user_result_id IS NULL@validcnt + @nullcnt != @NUMROWS@errno = 30007,

@errmsg = 'Cannot update User_answers because User_results does not exist.'ERROR

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */:@errno @errmsgtransactionTRIGGER tD_User_results ON User_results FOR DELETE AS

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* DELETE trigger on User_results */@errno int,

@errmsg varchar(255)

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* User_results R/16 User_answers on parent delete no action */

/* ERWIN_RELATION:CHECKSUM="0003a738", PARENT_OWNER="", PARENT_TABLE="User_results"_OWNER="", CHILD_TABLE="User_answers"C_VERB_PHRASE="R/16", C2P_VERB_PHRASE="R/16", _CONSTRAINT="R_16", FK_COLUMNS="User_answer_user_result_id" */EXISTS (* FROM deleted,User_answers

/* %JoinFKPK(User_answers,deleted," = "," AND") */_answers.User_answer_user_result_id = deleted.User_result_id

)@errno = 30001,

@errmsg = 'Cannot delete User_results because User_answers exists.'ERROR

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Users R/14 User_results on child delete no action */

/* ERWIN_RELATION:CHECKSUM="00000000", PARENT_OWNER="", PARENT_TABLE="Users"_OWNER="", CHILD_TABLE="User_results"C_VERB_PHRASE="R/14", C2P_VERB_PHRASE="R/14", _CONSTRAINT="R_14", FK_COLUMNS="User_result_User_id" */EXISTS (SELECT * FROM deleted,Users

/* %JoinFKPK(deleted,Users," = "," AND") */.User_result_User_id = Users.User_id ANDEXISTS (* FROM User_results

/* %JoinFKPK(User_results,Users," = "," AND") */_results.User_result_User_id = Users.User_id

)

)@errno = 30010,

@errmsg = 'Cannot delete last User_results because Users exists.'ERROR

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Tests R/15 User_results on child delete no action */

/* ERWIN_RELATION:CHECKSUM="00000000", PARENT_OWNER="", PARENT_TABLE="Tests"_OWNER="", CHILD_TABLE="User_results"C_VERB_PHRASE="R/15", C2P_VERB_PHRASE="R/15", _CONSTRAINT="R_15", FK_COLUMNS="User_result_test_id" */EXISTS (SELECT * FROM deleted,Tests

/* %JoinFKPK(deleted,Tests," = "," AND") */.User_result_test_id = Tests.Test_ID ANDEXISTS (* FROM User_results

/* %JoinFKPK(User_results,Tests," = "," AND") */_results.User_result_test_id = Tests.Test_ID

)

)@errno = 30010,

@errmsg = 'Cannot delete last User_results because Tests exists.'ERROR

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */:@errno @errmsgtransactionTRIGGER tU_User_results ON User_results FOR UPDATE AS

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* UPDATE trigger on User_results */@NUMROWS int,

@nullcnt int,

@validcnt int,

@insUser_result_id int,

@errno int,

@errmsg varchar(255)

@NUMROWS = @@rowcount

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* User_results R/16 User_answers on parent update no action */

/* ERWIN_RELATION:CHECKSUM="000452af", PARENT_OWNER="", PARENT_TABLE="User_results"_OWNER="", CHILD_TABLE="User_answers"C_VERB_PHRASE="R/16", C2P_VERB_PHRASE="R/16", _CONSTRAINT="R_16", FK_COLUMNS="User_answer_user_result_id" */

/* %ParentPK(" OR",UPDATE) */(User_result_id)EXISTS (* FROM deleted,User_answers

/* %JoinFKPK(User_answers,deleted," = "," AND") */_answers.User_answer_user_result_id = deleted.User_result_id

)@errno = 30005,

@errmsg = 'Cannot update User_results because User_answers exists.'ERROR

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Users R/14 User_results on child update no action */

/* ERWIN_RELATION:CHECKSUM="00000000", PARENT_OWNER="", PARENT_TABLE="Users"_OWNER="", CHILD_TABLE="User_results"C_VERB_PHRASE="R/14", C2P_VERB_PHRASE="R/14", _CONSTRAINT="R_14", FK_COLUMNS="User_result_User_id" */

/* %ChildFK(" OR",UPDATE) */(User_result_User_id)@nullcnt = 0@validcnt = count(*)inserted,Users

/* %JoinFKPK(inserted,Users) */.User_result_User_id = Users.User_id

/* %NotnullFK(inserted," IS NULL","select @nullcnt = count(*) from inserted where"," AND") */@nullcnt = count(*) from inserted where.User_result_User_id IS NULL@validcnt + @nullcnt != @NUMROWS@errno = 30007,

@errmsg = 'Cannot update User_results because Users does not exist.'ERROR

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Tests R/15 User_results on child update no action */

/* ERWIN_RELATION:CHECKSUM="00000000", PARENT_OWNER="", PARENT_TABLE="Tests"_OWNER="", CHILD_TABLE="User_results"C_VERB_PHRASE="R/15", C2P_VERB_PHRASE="R/15", _CONSTRAINT="R_15", FK_COLUMNS="User_result_test_id" */

/* %ChildFK(" OR",UPDATE) */(User_result_test_id)@nullcnt = 0@validcnt = count(*)inserted,Tests

/* %JoinFKPK(inserted,Tests) */.User_result_test_id = Tests.Test_ID

/* %NotnullFK(inserted," IS NULL","select @nullcnt = count(*) from inserted where"," AND") */@nullcnt = count(*) from inserted where.User_result_test_id IS NULL@validcnt + @nullcnt != @NUMROWS@errno = 30007,

@errmsg = 'Cannot update User_results because Tests does not exist.'ERROR

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */:@errno @errmsgtransactionTRIGGER tD_Users ON Users FOR DELETE AS

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* DELETE trigger on Users */@errno int,

@errmsg varchar(255)

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Users R/14 User_results on parent delete no action */

/* ERWIN_RELATION:CHECKSUM="00023254", PARENT_OWNER="", PARENT_TABLE="Users"_OWNER="", CHILD_TABLE="User_results"C_VERB_PHRASE="R/14", C2P_VERB_PHRASE="R/14", _CONSTRAINT="R_14", FK_COLUMNS="User_result_User_id" */EXISTS (* FROM deleted,User_results

/* %JoinFKPK(User_results,deleted," = "," AND") */_results.User_result_User_id = deleted.User_id

)@errno = 30001,

@errmsg = 'Cannot delete Users because User_results exists.'ERROR


/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Groups R/7 Users on child delete no action */

/* ERWIN_RELATION:CHECKSUM="00000000", PARENT_OWNER="", PARENT_TABLE="Groups"_OWNER="", CHILD_TABLE="Users"C_VERB_PHRASE="R/7", C2P_VERB_PHRASE="R/7", _CONSTRAINT="R_7", FK_COLUMNS="User_group_id" */EXISTS (SELECT * FROM deleted,Groups

/* %JoinFKPK(deleted,Groups," = "," AND") */.User_group_id = Groups.Groupe_id ANDEXISTS (* FROM Users

/* %JoinFKPK(Users,Groups," = "," AND") */.User_group_id = Groups.Groupe_id

)

)@errno = 30010,

@errmsg = 'Cannot delete last Users because Groups exists.'ERROR

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */:@errno @errmsgtransactionTRIGGER tU_Users ON Users FOR UPDATE AS

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* UPDATE trigger on Users */@NUMROWS int,

@nullcnt int,

@validcnt int,

@insUser_id int,

@errno int,

@errmsg varchar(255)@NUMROWS = @@rowcount

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Users R/14 User_results on parent update no action */

/* ERWIN_RELATION:CHECKSUM="00026ae8", PARENT_OWNER="", PARENT_TABLE="Users"_OWNER="", CHILD_TABLE="User_results"C_VERB_PHRASE="R/14", C2P_VERB_PHRASE="R/14", _CONSTRAINT="R_14", FK_COLUMNS="User_result_User_id" */

/* %ParentPK(" OR",UPDATE) */(User_id)EXISTS (* FROM deleted,User_results

/* %JoinFKPK(User_results,deleted," = "," AND") */_results.User_result_User_id = deleted.User_id

)@errno = 30005,

@errmsg = 'Cannot update Users because User_results exists.'ERROR


/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */

/* Groups R/7 Users on child update no action */

/* ERWIN_RELATION:CHECKSUM="00000000", PARENT_OWNER="", PARENT_TABLE="Groups"_OWNER="", CHILD_TABLE="Users"C_VERB_PHRASE="R/7", C2P_VERB_PHRASE="R/7", _CONSTRAINT="R_7", FK_COLUMNS="User_group_id" */

/* %ChildFK(" OR",UPDATE) */(User_group_id)@nullcnt = 0@validcnt = count(*)inserted,Groups

/* %JoinFKPK(inserted,Groups) */.User_group_id = Groups.Groupe_id

/* %NotnullFK(inserted," IS NULL","select @nullcnt = count(*) from inserted where"," AND") */

@validcnt + @nullcnt != @NUMROWS@errno = 30007,

@errmsg = 'Cannot update Users because Groups does not exist.'ERROR

/* ERwin Builtin 2 февраля 2009 г. 2:18:54 */:@errno @errmsgtransaction

go


ПРИЛОЖЕНИЕ Б

Образцы экранных форм


Рисунок Б.1 - Главная форма редактора тестов


Рисунок Б.2 - Реакция системы на потенциальную логическую ошибку


Рисунок Б.3 - Главная форма модуля администрирования пользователей


Рисунок Б.4 - Окно аутентификации пользователя модуля тестирования


Рисунок Б.5 - Окно выбора теста модуля тестирования


Приложение В


Текст программных модулей

Модуль редактора тестов

unit uEditorDataModule;

, Windows, Dialogs, Messages, Classes, DB, ADODB;= class(TDataModule): TADOConnection;: TADOTable;: TADOTable;: TADOTable;: TADOTable;: TDataSource;: TDataSource;: TDataSource;: TDataSource;_ID: TAutoIncField;_section_ID: TIntegerField;_name: TStringField;_description: TStringField;_author: TStringField;_type: TIntegerField;_question_count: TIntegerField;_question_limit: TIntegerField;_is_random_answers: TBooleanField;_is_time_limit: TBooleanField;_time_limit: TStringField;_is_back: TBooleanField;: TADOQuery;: TADOQuery;: TDataSource;: TADOQuery;: TDataSource;dsSectionsDataChange(Sender: TObject; Field: TField);dsTestsDataChange(Sender: TObject; Field: TField);dsQuestionsDataChange(Sender: TObject; Field: TField);dsQuestionsStateChange(Sender: TObject);

{ Private declarations }

{ Public declarations };

: TDataModule1;


uEditorMain, StdCtrls, Controls;


{$R *.dfm}

TDataModule1.dsSectionsDataChange(Sender: TObject;: TField);(@currentSection, sizeof(TSection));.ID := tabelSections.FieldByName('Section_ID').AsInteger;.Name := tabelSections.FieldByName('Section_name').AsString;;

TDataModule1.dsTestsDataChange(Sender: TObject; Field: TField);tabelTests.State = dsBrowse then.testTypeCB.ItemIndex := tabelTests.FieldByName('Test_type').AsInteger;.timeLimitEdit.Text := tabelTests.FieldByName('Test_Time_limit').AsString;;;

TDataModule1.dsQuestionsDataChange(Sender: TObject;: TField);tabelQuestions.State = dsBrowse then.questionTypeCB.ItemIndex := tabelQuestions.FieldByName('Question_type').AsInteger;.questionTimLimitEdit.Text := tabelQuestions.FieldByName('Question_time').AsString;;teacherForm doquestionTypeCB.ItemIndex in [0, 1, 4] then.Visible := false;.Visible := false;.Visible := false;.Visible := false;.Visible := false;.Visible := false;

//--------------------------------.Visible := true;.Left := answerPanel.Left + 5;.Left :=answerDBCtrlGrid.Left + 5;.Width := answerDBCtrlGrid.Width - 80;.Refresh;if questionTypeCB.ItemIndex = 2 then.Visible := false;.Visible := false;.Visible := false;.Visible := false;

//---------------------------------------.Visible := true;.Left := answerDBCtrlGrid.Left + 5;.Left :=answerDBCtrlGrid.Left + 5;.Width := (answerDBCtrlGrid.Width - 80) div 2;.Visible := true;.Left := answerDBCtrlGrid.Left + answerTextMemo.Width + 20;.Visible := true;.Left := answerCorrespLabel.Left;.Width := answerTextMemo.Width - 30;.Refresh;if questionTypeCB.ItemIndex = 3 then.Visible := false;.Visible := false;.Visible := false;.Visible := false;

//---------------------------------.Visible := true;.Visible := true;.Left := answerDBCtrlGrid.Left + 5;.Left := answerNumberLabel.Left;.Left := answerDBCtrlGrid.Left + 70;.Left := answerTextLabel.Left;.Width := answerDBCtrlGrid.Width - answerTextMemo.Left - 80;.Refresh;;;

TDataModule1.dsQuestionsStateChange(Sender: TObject);tabelQuestions.State = dsEdit then.answerPanel.Enabled := false.answerPanel.Enabled := true;;.

uEditorAutentification;


, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,, StdCtrls, Buttons;

= class(TForm): TEdit;: TEdit;: TLabel;: TLabel;: TBitBtn;: TBitBtn;FormCloseQuery(Sender: TObject; var CanClose: Boolean);

{ Private declarations }

{ Public declarations };

: TautentificationForm;


uEditorDataModule, uEditorMain;


{$R *.dfm}

TautentificationForm.FormCloseQuery(Sender: TObject;CanClose: Boolean);: string; begin(Sender as TautentificationForm).ModalResult = mrOk then((loginEdit.Text = '') and (passwordEdit.Text = '')) then(Handle,'Введите имя учетной записи и пароль','Ошибка!!!',MB_OK or MB_ICONERROR);:= false;.ADOConnection.Open;:= 'SELECT * from Users Where (User_group_id=1 or User_group_id=2)' +

' and (User_name=''' + loginEdit.Text + ''' and User_password=''' +.Text + ''')';

//ShowMessage(sqlStr);.ADOConnection.Open;.groupQuery.Open;.userQuery.Close;.userQuery.SQL.Text := sqlStr;.userQuery.Open;;DataModule1.userQuery.RecordCount = 1 then.tabelSections.Open;.tabelTests.Open;.tabelQuestions.Open;.tabelAnswers.Open;(Handle,'Доступ запрещен!!!','Ошибка!!!',MB_OK or MB_ICONERROR);.Close;;;.Close;;;

.


uEditorMain;


, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,, Menus, ToolWin, ComCtrls, ExtCtrls, StdCtrls, DBCtrls, Grids,, Mask, Buttons, dbcgrids, ActnList, XPStyleActnCtrls, ActnMan,, ExtActns, ActnCtrls, XPMan, ImgList, RxCombos, RxRichEd,, AppEvent, SpeedBar, RxLookup, ToolEdit, RXDBCtrl;

= class(TForm): TMainMenu;: TMenuItem;: TMenuItem;: TMenuItem;: TMenuItem;: TMenuItem;: TMenuItem;: TMenuItem;: TMenuItem;: TMenuItem;: TMenuItem;: TMenuItem;: TMenuItem;: TMenuItem;: TMenuItem;: TMenuItem;: TMenuItem;: TStatusBar;: TToolBar;: TXPManifest;: TImageList;: TActionList;: TColorDialog;: TRichEditBold;: TRichEditItalic;: TRichEditUnderline;: TRichEditStrikeOut;: TRichEditBullets;: TRichEditAlignLeft;: TRichEditAlignRight;: TRichEditAlignCenter;: TPageControl;: TTabSheet;: TSplitter;: TSplitter;: TPanel;: TSplitter;: TPanel;: TLabel;: TLabel;: TLabel;: TDBMemo;: TDBEdit;: TGroupBox;: TDBCheckBox;: TDBCheckBox;: TDBCheckBox;: TComboEdit;: TComboBox;: TBitBtn;: TBitBtn;: TBitBtn;: TBitBtn;: TBitBtn;: TPanel;: TGroupBox;: TRxDBLookupList;: TGroupBox;: TRxDBLookupCombo;: TPanel;: TSplitter;: TPanel;: TLabel;: TLabel;: TLabel;: TLabel;: TLabel;: TDBCtrlGrid;: TDBCheckBox;: TDBMemo;: TDBEdit;: TDBEdit;: TDBMemo;: TDBNavigator;: TPanel;: TLabel;: TLabel;: TLabel;: TLabel;: TDBEdit;: TComboBox;: TDBEdit;: TToolBar;: TFontComboBox;: TToolButton;: TComboBox;: TToolButton;: TToolButton;: TToolButton;: TToolButton;: TToolButton;: TToolButton;: TToolButton;: TToolButton;: TToolButton;: TToolButton;: TToolButton;: TBitBtn;: TBitBtn;: TRxDBRichEdit;: TRxDBComboEdit;: TPanel;: TDBGrid;: TDBNavigator;isTimeLimitCBClick(Sender: TObject);btnTestAcceptClick(Sender: TObject);btnNewSectionClick(Sender: TObject);btnNewTestClick(Sender: TObject);btnDelTestClick(Sender: TObject);answerNavigatorClick(Sender: TObject; Button: TNavigateBtn);fontsComboBoxChange(Sender: TObject);fontSizeComboBoxChange(Sender: TObject);ToolButton11Click(Sender: TObject);btnTestCancelClick(Sender: TObject);btnQuestAcceptClick(Sender: TObject);btnQuestCancelClick(Sender: TObject);questionTextEditEnter(Sender: TObject);tbBoldClick(Sender: TObject);tbItalicClick(Sender: TObject);tbUnderlineClick(Sender: TObject);questionTextEditSelectionChange(Sender: TObject);tbLeftClick(Sender: TObject);tbCenterClick(Sender: TObject);tbInsertObjectClick(Sender: TObject);questionNavigatorClick(Sender: TObject;: TNavigateBtn);FormActivate(Sender: TObject);CurrText: TRxTextAttributes;

{ Private declarations }

{ Public declarations };

= record: integer;: string;;

= record: integer;: integer;: string;: string;: string;: integer;: integer;: integer;: boolean;: boolean;: string;: boolean;;

= record: integer;: integer;: integer;: string;: integer;: integer;: integer;: string;: TMemoryStream;;

= record: integer;: integer;: integer;: string;: integer;: boolean;: array [1..10,1..10] of integer;: TMemoryStream;;

: TteacherForm;, newSection : TSection;, newTest : TTest;, newQuestion : TQuestion;, newAnswer : TAnswer;: string;


uEditorDataModule, DB, ADODB, Math, uEditorAutentification;


{$R *.dfm}

TteacherForm.CurrText: TRxTextAttributes;questionTextEdit.SelLength > 0 then:= questionTextEdit.SelAttributes:= questionTextEdit.DefAttributes;;

TteacherForm.isTimeLimitCBClick(Sender: TObject);isTimeLimitCB.Checked = true then.Enabled := True.Enabled := False;;

TteacherForm.btnTestAcceptClick(Sender: TObject);DataModule1.tabelTests do;('Test_type').AsInteger := testTypeCB.ItemIndex;('Test_time_limit').AsString := timeLimitEdit.Text;;;;;;

TteacherForm.btnNewSectionClick(Sender: TObject);

begin.Name := InputBox('Создание нового раздела','Введите название раздела','');

if newSection.Name <> '' then:= 'INSERT INTO Sections (Section_name)' +

'VALUES (''' + newSection.Name + ''')';.universalQuery.SQL.Clear;.universalQuery.SQL.Text := sqlString;.universalQuery.ExecSQL;.tabelSections.Close;.tabelSections.Open;exception do(Handle, 'Ошибка создания раздела', 'Ошибка', MB_OK or MB_ICONERROR);;;

TteacherForm.btnNewTestClick(Sender: TObject);

begin.name := InputBox('Создание нового теста','Введите название теста','');

if newTest.name <> '' then:= 'INSERT INTO Tests (Test_section_ID,Test_name)' +

'VALUES (' + DataModule1.tabelSections.FieldByName('Section_ID').AsString +

',''' + newTest.name + ''')';DataModule1.universalQuery do.Clear;.Text := sqlString;;;.tabelTests.Close;.tabelTests.Open;exception do(Handle, 'Ошибка создания теста', 'Ошибка', MB_OK or MB_ICONERROR);;;;

TteacherForm.btnDelTestClick(Sender: TObject);:= 'DELETE FROM Tests WHERE Test_ID = '+.tabelTests.FieldByName('Test_ID').AsString;DataModule1.universalQuery do.Clear;.Text := sqlString;;;.tabelTests.Close;.tabelTests.Open;;

TteacherForm.answerNavigatorClick(Sender: TObject;: TNavigateBtn);Button = nbInsert then((teacherForm.questionTypeCB.ItemIndex = 4) and (DataModule1.tabelAnswers.RecordCount = 1)) then(teacherForm.Handle,'На вопрос типа "Свободный ввод" разрешен только один ответ','Добавление ответа невозможно',MB_OK or MB_ICONASTERISK);.tabelAnswers.First;.Refresh;;;

.tabelAnswers.Append;questionTypeCB.ItemIndex in [2, 3, 4] then.DataSource.DataSet.FieldByName('Answer_is_right').AsBoolean := true;.Refresh;;;;

TteacherForm.fontsComboBoxChange(Sender: TObject);.Name := fontsComboBox.FontName;;

TteacherForm.fontSizeComboBoxChange(Sender: TObject);.Size := StrToInt(fontSizeComboBox.Text);;

TteacherForm.ToolButton11Click(Sender: TObject);ColorDialog1.Execute then.Color := ColorDialog1.Color;;

TteacherForm.btnTestCancelClick(Sender: TObject);.tabelTests.Cancel;;

TteacherForm.btnQuestAcceptClick(Sender: TObject);DataModule1.tabelQuestions do;('Question_Type').AsInteger := questionTypeCB.ItemIndex;('Question_time').AsString := questionTimLimitEdit.Text;;;;;;

TteacherForm.btnQuestCancelClick(Sender: TObject);.tabelQuestions.Cancel;;

TteacherForm.questionTextEditEnter(Sender: TObject);.tabelQuestions.Edit;

TteacherForm.tbBoldClick(Sender: TObject);fsBold in CurrText.Style then.Down := false;.Style := CurrText.Style - [fsBold].Down := true;.Style := CurrText.Style + [fsBold];;;

TteacherForm.tbItalicClick(Sender: TObject);fsItalic in CurrText.Style then.Down := false;.Style := CurrText.Style - [fsItalic].Down := true;.Style := CurrText.Style + [fsItalic];;;

TteacherForm.tbUnderlineClick(Sender: TObject);fsUnderline in CurrText.Style then.Down := false;.Style := CurrText.Style - [fsUnderline].Down := true;.Style := CurrText.Style + [fsUnderline];;;

TteacherForm.questionTextEditSelectionChange(Sender: TObject);fsBold in CurrText.Style then.Down := true.Down := false;

fsItalic in CurrText.Style then.Down := true.Down := false;

fsUnderline in CurrText.Style then.Down := true.Down := false;;

TteacherForm.tbLeftClick(Sender: TObject);

// questionTextEdit.Alignment;;

TteacherForm.tbCenterClick(Sender: TObject);.Alignment := taCenter;;

TteacherForm.tbInsertObjectClick(Sender: TObject);questionTextEdit.InsertObjectDialog = true then.tabelQuestions.Edit;;

TteacherForm.questionNavigatorClick(Sender: TObject;: TNavigateBtn);Button = nbInsert then.tabelQuestions.Append;;

TteacherForm.FormActivate(Sender: TObject);.ADOConnection.Close;.tabelSections.Close;.tabelTests.Close;.tabelQuestions.Close;.tabelAnswers.Close;.ShowModal;;

.







Модуль администрированияuEditorAutentification;


, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,, StdCtrls, Buttons;

= class(TForm): TEdit;: TEdit;: TLabel;: TLabel;: TBitBtn;: TBitBtn;FormCloseQuery(Sender: TObject; var CanClose: Boolean);

{ Private declarations }

{ Public declarations };

: TautentificationForm;


uEditorDataModule, uEditorMain;


{$R *.dfm}

TautentificationForm.FormCloseQuery(Sender: TObject;CanClose: Boolean);: string;(Sender as TautentificationForm).ModalResult = mrOk then((loginEdit.Text = '') and (passwordEdit.Text = '')) then(Handle,'Введите имя учетной записи и пароль','Ошибка!!!',MB_OK or MB_ICONERROR);:= false;.ADOConnection.Open;:= 'SELECT * from Users Where (User_group_id=1 or User_group_id=2)' +

' and (User_name=''' + loginEdit.Text + ''' and User_password=''' +.Text + ''')';

//ShowMessage(sqlStr);.ADOConnection.Open;.groupQuery.Open;.userQuery.Close;.userQuery.SQL.Text := sqlStr;.userQuery.Open;;DataModule1.userQuery.RecordCount = 1 then.tabelSections.Open;.tabelTests.Open;.tabelQuestions.Open;.tabelAnswers.Open;(Handle,'Доступ запрещен!!!','Ошибка!!!',MB_OK or MB_ICONERROR);.Close;;;.Close;;;

.


uDataModule;

, Classes, DB, ADODB;

= class(TDataModule): TADOConnection;: TADOTable;: TADOTable;: TADOTable;: TDataSource;: TDataSource;: TDataSource;: TADOTable;: TDataSource;: TADOQuery;groupsDSDataChange(Sender: TObject; Field: TField);

{ Private declarations }

{ Public declarations };: TDataModule1;


{$R *.dfm}TDataModule1.groupsDSDataChange(Sender: TObject; Field: TField);: string;:= 'Select * from Sections,Group_sections where Group_sections.Gs_group_id=' +.FieldByName('Group_id').AsString +

' AND Group_sections.Gs_section_id = Sections.Section_ID';.Close;.SQL.Text := sqlStr;.Open;;

.

Модуль тестированияuClinetLogin;


, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,, StdCtrls, DBCtrls, ExtCtrls, Buttons, Mask, RxLookup;

= class(TForm): TPanel;: TPanel;: TSplitter;: TBitBtn;: TBitBtn;: TLabel;: TLabel;: TLabel;: TBitBtn;: TEdit;: TMaskEdit;: TRxDBLookupCombo;: TEdit;: TLabel;btnNewClick(Sender: TObject);FormShow(Sender: TObject);groupNameDBLoocupCBChange(Sender: TObject);FormCloseQuery(Sender: TObject; var CanClose: Boolean);

{ Private declarations }

{ Public declarations };

TUser = record: integer;_ID : integer;: string;: string;: string;: integer;: string;: string;;

: TautentificationForm;: TUser;

uClientNewUser, uClientDataModule, DB, uClientMain;


{$R *.dfm}

TautentificationForm.btnNewClick(Sender: TObject);.ShowModal;;

TautentificationForm.FormShow(Sender: TObject);(@currentUser,sizeof(TUser));.Text := '';.Text := '';.StatusBar.Panels[0].Text := '';;

TautentificationForm.groupNameDBLoocupCBChange(Sender: TObject);: string;DataModule1 do.Open;.Open;:= 'SELECT Section_ID, Section_name FROM Sections, Group_sections' +

' WHERE Group_sections.Gs_group_id = ' + groupQuery.FieldByName('Group_id').AsString +

' AND Group_sections.Gs_section_id = Sections.Section_ID';.Close;.SQL.Text := sqlStr;.Open;;;

TautentificationForm.FormCloseQuery(Sender: TObject;CanClose: Boolean);: WideString;(Sender as TautentificationForm).ModalResult = mrOk then((userNameEdit.Text = '') or (userPasswordEdit.Text = '')) then(Handle,'Не введен логин или пароль!','Ошибка входа',MB_OK or MB_ICONERROR);:= false;:= 'SELECT * FROM Users' +

' WHERE User_group_id = ' + DataModule1.groupQuery.FieldByName('Group_ID').AsString +

'AND User_name =' + '''' + userNameEdit.Text +

''' AND User_password = ' + '''' + userPasswordEdit.Text + ''';';

.userQuery.Close;.userQuery.SQL.Text := sqlStr;.userQuery.Open;Exception do

ShowMessage('Ошибка выполнения запроса к базе');

exit;;;DataModule1.userQuery.RecordCount = 1 thenDataModule1.userQuery do.ID := FieldByName('User_ID').AsInteger;.grope_ID := FieldByName('User_group_ID').AsInteger;.name := FieldByName('User_name').AsString;.code := FieldByName('User_code').AsString;.password := FieldByName('User_password').AsString;.grants := FieldByName('User_grants').AsInteger;.info := FieldByName('User_info').AsString;.email := FieldByName('User_mail').AsString;

.userID := currentUser.ID;

//выводим информацию для пользователя

testingForm.StatusBar.Panels[0].Text := 'Вы вошли как ' + currentUser.name +

' (Группа : ' + DataModule1.groupQuery.FieldByName('Group_name').AsString + ')';;('Ошибка аутентификации! Пользователь не найден',mtError,mbOKCancel,-1);

CanClose := false;;;;;

.


uClientSelectTest;


, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,, ExtCtrls, StdCtrls, DBCtrls, Buttons, RxLookup, Grids, DBGrids;

= class(TForm): TPanel;: TSplitter;: TPanel;: TPanel;: TSplitter;: TGroupBox;: TGroupBox;: TSplitter;: TGroupBox;: TGroupBox;: TSplitter;: TBitBtn;: TBitBtn;: TDBMemo;: TDBMemo;: TRxDBLookupCombo;: TRxDBLookupList;testSectionDBLBChange(Sender: TObject);RxDBLookupList1Click(Sender: TObject);FormShow(Sender: TObject);FormCloseQuery(Sender: TObject; var CanClose: Boolean);

{ Private declarations }

{ Public declarations };

: TtestSelectForm;


uClientDataModule, uClinetLogin, uClientMain;


{$R *.dfm}

TtestSelectForm.FormShow(Sender: TObject);: string;;currentUser.ID = 0 then:= 'Сначала необходимо пройти процедурц аутентификации' + #10#13 +

'Зарегистрироваться сейчас?';MessageBox(Handle,PChar(errorMessage),'Ошибка!!!',MB_YESNO or MB_ICONWARNING) = mrYes then.ShowModal;.Close;;;

TtestSelectForm.testSectionDBLBChange(Sender: TObject);: string;:= 'SELECT * FROM Tests WHERE Test_section_ID = ' +.sectionQuery.FieldByName('Section_id').AsString;.testQuery.Close;.testQuery.SQL.Text := sqlStr;.testQuery.Open;


// ShowMessage(sqlStr);;

TtestSelectForm.RxDBLookupList1Click(Sender: TObject);: string;:= 'SELECT * FROM Questions WHERE Question_test_id = ' +.testQuery.FieldByName('Test_ID').AsString;.questionQuery.Close;.questionQuery.SQL.Text := sqlStr;

//набор данных откроем после того как пользователь подтвердит выбор

// ShowMessage(sqlStr);;


TtestSelectForm.FormCloseQuery(Sender: TObject;CanClose: Boolean);, sqlInsert : string;(Sender as TtestSelectForm).ModalResult = mrOk thenDataModule1.testQuery do.ID := FieldByName('Test_ID').AsInteger;.name := FieldByName('Test_Name').AsString;.testType := FieldByName('Test_type').AsInteger;.quistionLimit := FieldByName('Test_question_limit').AsInteger;.isRandomAnswer := FieldByName('Test_is_random_answers').AsBoolean;.isTimeLimit := FieldByName('Test_is_time_limit').AsBoolean;.timeLimit := FieldByName('Test_time_limit').AsString;.isBack := FieldByName('Test_is_back').AsBoolean;.StatusBar.Panels[1].Text := 'Выбран тест: ' + selectedTest.name;

selectedTest.ID <> 0 then:= 'SELECT Count(*) FROM Questions WHERE Question_test_id = ' +(selectedTest.ID);.universalQuery.Close;.universalQuery.SQL.Text := sqlStr;.universalQuery.Open;.questionCount := DataModule1.universalQuery.Fields[0].AsInteger;

.testID := selectedTest.ID;.complited := 0;.userComplitedQuestion := 1;.userRightAnswerQuestion := 0;selectedTest.questionCount = 0 then

begin(Handle,'В выбранном тесте отсутствуют вопросы','Тестирование невозможно',MB_OK or MB_ICONWARNING);:= false;

//формируем массим случайной последовательности вопросов

SetLength(GquestionOrderArray, selectedTest.questionCount); //тут получим размерность массива

testingForm.FillArray(GquestionOrderArray);


//открываем набор данных с вопросами

DataModule1.questionQuery.Open;.totalQuestion := selectedTest.questionCount;.timeBegin := now;

:= 'INSERT INTO User_results (User_result_User_id,User_result_test_id,' +

'User_result_test_title,User_result_time_begin,User_result_comleted,' +

'User_result_total_questions) VALUES(' + IntToStr(userResult.userID) +

',' + IntToStr(userResult.testID) + ',''' + selectedTest.name + ''',''' +.toSQLDateTime(userResult.timeBegin) +

''',0,' + IntToStr(userResult.totalQuestion) +');';.userResultQuery.Close;.userResultQuery.SQL.Text := sqlInsert;.userResultQuery.ExecSQL;

.universalQuery.Close;.universalQuery.SQL.Text := 'Select max(user_result_id) from user_results' +

' where user_result_user_id=' + intToStr(currentUser.ID);.universalQuery.Open;.id := DataModule1.universalQuery.Fields[0].AsInteger;

//ShowMessage(sqlInsert);;;

;;.uClientDataModule;


, StdCtrls, Dialogs, Classes, Controls, DB, ADODB, DBClient, MConnect,;

= class(TDataModule): TDataSource;: TDataSource;: TDataSource;: TDataSource;: TDataSource;: TDataSource;: TDataSource;: TDataSource;: TDataSource;: TADOConnection;: TADOQuery;: TADOQuery;: TADOQuery;: TADOQuery;: TADOQuery;: TADOQuery;: TADOQuery;: TADOQuery;: TADOQuery;: TADOQuery;questionQueryAfterScroll(DataSet: TDataSet);questionQueryBeforeScroll(DataSet: TDataSet);questionQueryAfterOpen(DataSet: TDataSet);


{ Private declarations }setSingleChoicePanelActive;setMultiChoicePanelActive;setRandomChoicePanelActive;setConformPanelActive;setOrderPanelActive;isUserAnswerRight(var answerText : string; questionType : integer) : boolean;;

: TDataModule1;


uClientMain, Forms, CheckLst, ExtCtrls, Grids;


{$R *.dfm}


TDataModule1.setSingleChoicePanelActive;testingForm do.Visible := true;.Align := alClient;.Visible := False;.Visible := false;.Visible := false;.Visible := false;;;

TDataModule1.setMultiChoicePanelActive;testingForm do.Visible := true;.Align := alClient;.Visible := False;.Visible := false;.Visible := false;.Visible := false;;;

TDataModule1.setRandomChoicePanelActive;testingForm do.Visible := true;.Align := alClient;.Visible := False;.Visible := false;.Visible := false;.Visible := false;;;

TDataModule1.setConformPanelActive;testingForm do.Visible := true;.Align := alClient;.Visible := False;.Visible := false;.Visible := false;.Visible := false;;;

TDataModule1.setOrderPanelActive;testingForm do.Visible := true;.Align := alClient;.Visible := False;.Visible := false;.Visible := false;.Visible := false;;;



//--Процедура форимрования понели для ответа пользователя--------


procedure setAnswer(questionType : integer);, index : integer;: array of integer;

//перемешиваем ответы если необходимоselectedTest.isRandomAnswer = true then(answerArray,DataModule1.answerQuery.RecordCount);.FillArray(answerArray);index := 0 to DataModule1.answerQuery.RecordCount - 1 do[index] := index;

DataModule1.answerQuery.RecordCount > 0 then

//одиночный выбор--------------------------------------------------questionType = 0 then.SingleChoiceRG.Items.Clear;index := 0 to DataModule1.answerQuery.RecordCount - 1 do.answerQuery.RecNo := answerArray[index];.SingleChoiceRG.Items.Add(DataModule1.answerQuery.FieldByName('Answer_text').AsString);;.setSingleChoicePanelActive;


//множественный выбор----------------------------------------------if questionType = 1 then.MultiChoiceCLB.Items.Clear;index := 0 to DataModule1.answerQuery.RecordCount - 1 do.answerQuery.RecNo := answerArray[index];.MultiChoiceCLB.Items.Add(DataModule1.answerQuery.FieldByName('Answer_text').AsString);;.setMultiChoicePanelActive;


//соответствие --------------------------------------------------if questionType = 2 thenlineIndex := 0 to testingForm.conformStringGrid.RowCount - 1 do.conformStringGrid.Rows[lineIndex].Clear;

.conformStringGrid.RowCount := 1;.conformStringGrid.ColWidths[0] := 40;.conformStringGrid.ColWidths[2] := 40;.conformStringGrid.ColWidths[1] := (testingForm.PanelAnswer.Width - 100) div 2;.conformStringGrid.ColWidths[3] := (testingForm.PanelAnswer.Width - 100) div 2;

index := 0 to DataModule1.answerQuery.RecordCount - 1 do.answerQuery.RecNo := answerArray[index];.conformStringGrid.Cells[1, index] := DataModule1.answerQuery.FieldByName('Answer_text').AsString;.conformStringGrid.RowCount := (index + 1);;

.answerQuery.First;:= 0;not DataModule1.answerQuery.Eof do.conformStringGrid.Cells[2, index] := IntToStr(index + 1);.conformStringGrid.Cells[3, index] := DataModule1.answerQuery.FieldByName('Answer_corresp').AsString;.answerQuery.Next;(index);;.setConformPanelActive


//упорядоченный список-------------------------------------------if questionType = 3 thenlineIndex := 0 to testingForm.orderStringGrid.RowCount - 1 do.orderStringGrid.Rows[lineIndex].Clear;

.orderStringGrid.RowCount := 1;.orderStringGrid.ColWidths[0] := 40;.orderStringGrid.ColWidths[1] := testingForm.PanelAnswer.Width - 50;

index := 0 to DataModule1.answerQuery.RecordCount - 1 do.answerQuery.RecNo := answerArray[index];.orderStringGrid.Cells[1,index] := DataModule1.answerQuery.FieldByName('Answer_text').AsString;.orderStringGrid.RowCount := (index + 1);;.setOrderPanelActive;


//свободный ввод--------------------------------------------------if questionType = 4 then.RandomChoiceEdit.Text := '';.setRandomChoicePanelActive;;;


//---------------------------------------------------------------

//--Получаем и анализируем ответ пользователяTDataModule1.isUserAnswerRight(var answerText : string; questionType : integer) : boolean;,primaryIndex : integer;,correspIsRignt : boolean;

sqlStr : string;


//выборка правильных ответов для текущего вопроса

sqlStr := 'SELECT Answer_number, Answer_text, Answer_corresp From Answers Where Answer_question_id = ' +.questionQuery.FieldByName('Question_id').AsString + ' AND Answer_is_right = 1';

.universalQuery.Close;.universalQuery.SQL.Text := sqlStr;.universalQuery.Open;:= false;


//одиночный выбор--------------------------------------------------questionType = 0 then:= '';:= false;testingForm.SingleChoiceRG doItemIndex <> -1 then:= Items.Strings[ItemIndex];((ItemIndex <> -1) and (Items.Strings[ItemIndex] = DataModule1.universalQuery.Fields[1].AsString)) then:= True;;


//множественный выбор----------------------------------------------if questionType = 1 then:= '';lineIndex := 0 to testingForm.MultiChoiceCLB.Items.Count - 1 dotestingForm.MultiChoiceCLB.Checked[lineIndex] then:= answerText + #10#13 + testingForm.MultiChoiceCLB.Items.Strings[lineIndex];

:= false;.universalQuery.First;not DataModule1.universalQuery.Eof dotestingForm.MultiChoiceCLB doChecked[Items.IndexOf(DataModule1.universalQuery.FieldByName('Answer_text').AsString)] = true then:= true:= false;;.universalQuery.Next;;


//соответствие --------------------------------------------------if questionType = 2 then:= '';testingForm.conformStringGrid dolineIndex := 0 to RowCount - 1 doCells[0,lineIndex] = '' then:= '';;:= answerText + #10#13 + Cells[1, lineIndex] + '-' + Cells[3, StrToInt(Cells[0,lineIndex])];;;

:= true;.answerQuery.First;:= 0;not answerQuery.Eof dotestingForm.conformStringGrid dolineIndex := 0 to RowCount - 1 do:= false;((Cells[0, lineIndex] = Cells[2,primaryIndex])(Cells[1, lineIndex] = DataModule1.answerQuery.FieldByName('Answer_text').AsString)) then:= true;;;;;:= Result and correspIsRignt;.answerQuery.Next;(primaryIndex);;


//упорядоченный список-------------------------------------------if questionType = 3 then:= '';testingForm.orderStringGrid dolineIndex := 0 to RowCount - 1 doCells[0,lineIndex] = '' then:= '';;:= answerText + #10#13 + Cells[0,lineIndex] + '-' + Cells[1, lineIndex];;;

:= true;lineIndex := 0 to testingForm.orderStringGrid.RowCount - 1 do.answerQuery.First;testingForm.orderStringGrid donot DataModule1.answerQuery.Eof do((Cells[0,lineIndex] = DataModule1.answerQuery.FieldByName('Answer_number').AsString)

(Cells[1,lineIndex] = DataModule1.answerQuery.FieldByName('Answer_text').AsString)) then:= true;;:= false;.answerQuery.Next;;;:= Result and lineIsRight;;


//свободный ввод--------------------------------------------------if questionType = 4 then:= testingForm.RandomChoiceEdit.Text;:= false;AnsiLowerCase(testingForm.RandomChoiceEdit.Text) =(DataModule1.answerQuery.FieldByName('Answer_text').AsString) then:= true;;

//---------------------------------------------------------------

TDataModule1.questionQueryAfterScroll(DataSet: TDataSet);: string;:= 'SELECT * FROM Answers WHERE Answer_question_id = ' +.FieldByName('Question_id').AsString;answerQuery do;.Text := sqlStr;;;

(questionQuery.FieldByName('Question_type').AsInteger);;

TDataModule1.questionQueryBeforeScroll(DataSet: TDataSet);

{var: string;: string;, isAnswered : integer;}

{ answerIsRight := 0;:= 0;DataModule1.isUserAnswerRight(answerText,questionQuery.FieldByName('Question_type').AsInteger) = true then(userResult.userRightAnswerQuestion);:= 1;;((answerText <> '') or (answerText <> ' ')) then:= 1;

:= 'INSERT INTO User_answers (User_answer_user_result_id, User_answer_qnumber,' +

'User_answer_question, User_answer_answer, User_answer_time, User_answer_is_right, '+

'User_answer_score, User_answer_answered) VALUES (' + intToStr(userResult.id) +

',' + IntToStr(GquestionNumber) + ',' + DataModule1.questionQuery.FieldByName('Question_text').AsString +

',' + answerText + ',00:00,'+ IntToStr(answerIsRight) + ',0,' + IntToStr(isAnswered) + ')';(insertSql);};

TDataModule1.questionQueryAfterOpen(DataSet: TDataSet);:= 0;.questionQuery.RecNo := GquestionOrderArray[GquestionNumber];;.

uClientMain;


, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,, Menus, ComCtrls, ExtCtrls, ToolWin, StdCtrls, ImgList, CheckLst,, RxRichEd, DBRichEd, DBCtrls, RXCtrls, Grids, RXGrids;

= class(TForm): TStatusBar;: TMainMenu;: TMenuItem;: TMenuItem;: TMenuItem;: TMenuItem;: TMenuItem;: TMenuItem;: TMenuItem;: TMenuItem;: TMenuItem;: TPanel;: TPanel;: TToolBar;: TSplitter;: TPanel;: TPanel;: TPanel;: TPanel;: TPanel;: TRadioGroup;: TLabeledEdit;: TImageList;: TToolButton;: TToolButton;: TToolButton;: TToolButton;: TToolButton;: TToolButton;: TToolButton;: TMenuItem;: TToolButton;: TToolButton;: TCheckListBox;: TLabel;: TRxDBRichEdit;: TTimer;: TStringGrid;: TLabel;: TStringGrid;: TLabel;MtestLoginClick(Sender: TObject);MtestStopClick(Sender: TObject);MtestBeginClick(Sender: TObject);MquestionNextClick(Sender: TObject);PanelAnswerDblClick(Sender: TObject);FormCreate(Sender: TObject);RandomChoicePanelResize(Sender: TObject);MquestionPrevClick(Sender: TObject);FormCloseQuery(Sender: TObject; var CanClose: Boolean);


{ Private declarations }FillArray(var A: array of Integer);toSQLDateTime(dateTime : TDateTime) : string;

{ Public declarations };

= record: integer;: integer;: string;: string;: string;: integer;: integer;: integer;: boolean;: boolean;: string;: boolean;

;

= record: integer;: integer;: integer;: TDateTime;: TDateTime;: integer;: integer;: integer;: integer;: integer;: real;;

= record: integer;: integer;: integer;: string;: integer;: integer;: integer;: string;;

= record: integer;: integer;: integer;: string;: integer;: boolean;: array [1..10,1..10] of integer;;

: TtestingForm;: TTest; : TUserResult;

// currentAnswer : TAnswer;


//массив случайных неповторяющихся порядковых номеров вопросов: array of integer;

//текущий индекс массиве номеров вопросов

GquestionNumber : integer;

uClinetLogin, uClientSelectTest, uClientDataModule;


{$R *.dfm}

//----функция для заполнения массива номеров вопросов--------------

procedure TtestingForm.FillArray(var A: array of Integer);, S, R: Integer;I := 0 to High(A) do[I] := I + 1;i := High(A) downto 0 do:= Random(I);:= A[R];[R] := A[I];[I] := S;;

end;

//-----------------------------------------------------------------


//Преобразуем дату и время в формат SQL Server

function TtestingForm.toSQLDateTime(dateTime : TDateTime) : string;: TFormatSettings;(0,formatSetting);.ShortDateFormat:='mm/dd/yyyy';.DateSeparator := '/';:= DateTimeToStr(dateTime,formatSetting);;

toSQLFloat(realDigit : real) : string;: TFormatSettings;(0,formatSetting);.DecimalSeparator := '.';:= FormatFloat('0.00',realDigit,formatSetting);;

TtestingForm.MtestLoginClick(Sender: TObject);.ShowModal;;

TtestingForm.MtestStopClick(Sender: TObject);.Close;;

TtestingForm.MtestBeginClick(Sender: TObject);.ShowModal;;

TtestingForm.MquestionNextClick(Sender: TObject);: string;

// answerText : string;

: string;: string;, isAnswered : integer;

begin

//получение ответа пользователя и занесение его в БД--

answerIsRight := 0;:= 0;DataModule1.isUserAnswerRight(answerText,DataModule1.questionQuery.FieldByName('Question_type').AsInteger) = true then(userResult.userRightAnswerQuestion);:= 1;;(answerText <> '') then:= 1;

:= 'INSERT INTO User_answers (User_answer_user_result_id, User_answer_qnumber,' +

'User_answer_question, User_answer_answer, User_answer_time, User_answer_is_right, '+

'User_answer_score, User_answer_answered) VALUES (' + intToStr(userResult.id) +

',' + IntToStr(GquestionNumber) + ',''' + DataModule1.questionQuery.FieldByName('Question_header').AsString +

''',''' + answerText + ''',''00:00'','+ IntToStr(answerIsRight) + ',0,' + IntToStr(isAnswered) + ')';.userAnswerQuery.Close;.userAnswerQuery.SQL.Text := insertSql;.userAnswerQuery.ExecSQL;

//ShowMessage(insertSql);

//---------------------------------------------

GquestionNumber < selectedTest.questionCount - 1 then(GquestionNumber);(userResult.userComplitedQuestion);.Panels[2].Text := 'Вопрос: ' + IntToStr(GquestionNumber + 1) +

' из ' + IntToStr(selectedTest.questionCount);.questionQuery.RecNo := GquestionOrderArray[GquestionNumber];.complited := 0;DataModule1.isUserAnswerRight(answerText, DataModule1.questionQuery.FieldByName('Question_type').AsInteger) = true then

//ShowMessage('pravilno');

//inc(userResult.userComplitedQuestion);(userResult.userRightAnswerQuestion);;.complited := 1;.timeEnd := now;('Тест окончен');;

.percentRight := (userResult.userRightAnswerQuestion/userResult.totalQuestion)*100;

//Заносим обновления в базу:= 'Update User_results Set User_result_completed_questions=' + IntToStr(userResult.userComplitedQuestion) +

',User_result_right_questions=' + IntToStr(userResult.userRightAnswerQuestion) +

',User_result_percent_right=' + toSQLFloat(userResult.percentRight)+

',User_result_comleted=' + IntToStr(userResult.complited) +

' where User_result_id=' + IntToStr(userResult.id);.userResultQuery.Close;.userResultQuery.SQL.Text := updateSql;.userResultQuery.ExecSQL;

userResult.complited = 1 then:= 'Update User_results Set User_result_time_end=''' +.toSQLDateTime(userResult.timeEnd) +

''' where User_result_id=' + IntToStr(userResult.id);.userResultQuery.Close;.userResultQuery.SQL.Text := updateSql;.userResultQuery.ExecSQL;;;

TtestingForm.MquestionPrevClick(Sender: TObject);((selectedTest.isBack = true) and (GquestionNumber > 0)) then(GquestionNumber);(userResult.userComplitedQuestion);.Panels[2].Text := 'Вопрос: ' + IntToStr(GquestionNumber + 1) +

' из ' + IntToStr(selectedTest.questionCount);.questionQuery.RecNo := GquestionOrderArray[GquestionNumber];(Handle,'Возврат невозможен','Ошибка!',MB_OK or MB_ICONWARNING);;

TtestingForm.PanelAnswerDblClick(Sender: TObject);.Align := alClient;;

TtestingForm.FormCreate(Sender: TObject);.Visible := false;.Visible := false;.Visible := false;.Visible := false;.Visible := false;;

TtestingForm.RandomChoicePanelResize(Sender: TObject);.Left := RandomChoicePanel.Left + 5;.Top := RandomChoicePanel.Top + 20;.Width := RandomChoicePanel.Width - 13;;


TtestingForm.FormCloseQuery(Sender: TObject;CanClose: Boolean);userResult.userComplitedQuestion < userResult.totalQuestion then

beginMessageBox(handle,'Вы ответили не на все вопросы. Закрыть приложение?','Внимание!!!',MB_YESNO or MB_ICONWARNING) = mrYes then

CanClose := true:= false;

end;;.


Содержание Введение 1. Обоснование разработки системы 1.1 Описание предметной области 1.2 Анализ аналогов и прототипов 1.3 Подтверждение необ

Больше работ по теме:

КОНТАКТНЫЙ EMAIL: [email protected]

Скачать реферат © 2017 | Пользовательское соглашение

Скачать      Реферат

ПРОФЕССИОНАЛЬНАЯ ПОМОЩЬ СТУДЕНТАМ