Главная Рефераты по сексологии Рефераты по информатике программированию Рефераты по биологии Рефераты по экономике Рефераты по москвоведению Рефераты по экологии Краткое содержание произведений Рефераты по физкультуре и спорту Топики по английскому языку Рефераты по математике Рефераты по музыке Остальные рефераты Рефераты по авиации и космонавтике Рефераты по административному праву Рефераты по безопасности жизнедеятельности Рефераты по арбитражному процессу Рефераты по архитектуре Рефераты по астрономии Рефераты по банковскому делу Рефераты по биржевому делу Рефераты по ботанике и сельскому хозяйству Рефераты по бухгалтерскому учету и аудиту Рефераты по валютным отношениям Рефераты по ветеринарии Рефераты для военной кафедры Рефераты по географии Рефераты по геодезии Рефераты по геологии Рефераты по геополитике Рефераты по государству и праву Рефераты по гражданскому праву и процессу Рефераты по делопроизводству Рефераты по кредитованию Рефераты по естествознанию Рефераты по истории техники Рефераты по журналистике Рефераты по зоологии Рефераты по инвестициям Рефераты по информатике Исторические личности Рефераты по кибернетике Рефераты по коммуникации и связи |
Дипломная работа: Обучающе-контроллирующая система для подготовки студентовДипломная работа: Обучающе-контроллирующая система для подготовки студентовСОДЕРЖАНИЕ ВВЕДЕНИЕ 1. ПОСТАНОВКА ЗАДАЧИ 2. ОБЗОР ЛИТЕРАТУРЫ 3. ПРОЕКТИРОВАНИЕ БАЗЫ ДАННЫХ 3.1 Концептуальная модель базы данных 3.2 Логическая модель базы данных 3.3 Структура файлов базы данных 4. ОПИСАНИЕ ПРОГРАММНЫХ МОДУЛЕЙ 4.1 Описание программы создания и модификации тестов 4.2 Описание программы администрирования 4.3 Описание программы контроля знаний 5. Руководство пользователЯ 5.1 Общие сведения 5.2 Установка файлов баз данных 5.3 Использование программы создания и модификации тестов 5.4 Использование программы администрирования 5.5 Использование программы контроля знаний 6. ОХРАНА ТРУДА 6.1 Техника безопасности и производственная санитария 6.1.1 Электрический ток и статическое электричество 6.1.2 Излучения 6.1.3 Шум 6.1.4 Вибрация. 6.1.5 Метеоусловия 6.1.6 Освещение 6.1.7 Расчет естественного освещения 6.1.8 Организация рабочего места 6.2 Пожарная безопасность 7. ЭКОНОМИЧЕСКИЙ РАЗДЕЛ ЗАКЛЮЧЕНИЕ. ЛИТЕРАТУРА Приложение 1 Приложение 2 Приложение 3 ВВЕДЕНИЕ Развитие вычислительной техники, создание вычислительных систем, одновременно обслуживающих десятки и сотни пользователей, открывают новые возможности применения ЭВМ в качестве высокоэффективного средства обучения. Такое обучение, управляемое учащимся, создает необходимые предпосылки для развития критического мышления и творческих способностей. Обучающие системы на базе вычислительных машин являются достаточно эффективными не только для подготовки пользователей ЭВМ, но и специалистов других профилей. Такие системы регламентируют и контролируют учебную деятельность обучаемых, обеспечивают свободно-конструируемую форму ответов обучаемых в сочетании с различными видами обмена информацией между обучаемым и ЭВМ, регистрируют ход процесса обучения и обрабатывают необходимые статистические данные, облегчая принятие решений преподавателями и администрацией учебного заведения. ЭВМ как обучающее устройство позволяет обеспечить гибкое управление познавательной деятельностью обучаемых, адаптацию к его индивидуальным особенностям на основе автоматического сбора и обработки данных о ходе процесса его обучения, позволяет создавать проблемные, игровые, соревновательные ситуации для повышения уровня мотивации обучаемых, заставляя их учиться приобретать необходимые навыки с целью обыграть партнера-машину. В плане общеобразовательной подготовки кадров создание автоматизированных обучающих, имитационных и тренирующих систем на базе ЭВМ становится одним из главных средств, обеспечивающих эффективную профессиональную подготовку специалистов различного профиля, студентов Вузов и техникумов, учащихся средних школ. Работы в данной области уже давно вышли за рамки экспериментов как у нас в стране, так и за рубежом. В частности в США обучающие системы на базе ЭВМ прошли путь развития от частных реализаций, работающих с 2-3 пользователями по 1-2 предметам, до вычислительных сетей учебного назначения, обслуживающих сотни удаленных терминалов и располагающих банками обучающих программ самого различного назначения. Примерами этих сетей являются система PLATO- IV фирмы CDC, автоматизированные обучающие системы фирм IBM, DEC, Hewlett Packard. 1. ПОСТАНОВКА ЗАДАЧИ Разработать универсальную обучающе-контролирующую систему для подготовки студентов по курсам: менеджмент, маркетинг, оценка имущества ( оборудования ), микропроцессоры и программирование, электротехника и электроника. К разрабатываемому программному обеспечению предъявляются следующие требования: 1) Язык программирования - Object Pascal. 2) Система должна быть открыта для модернизации и пополнения БД по другим предметам. 3) Основные критерии формирования комплекса вопросов (билетов): · билет состоит из 10-50 вопросов; · количество вопросов в билете определяет преподаватель при загрузке БД. 4) Критерий оценки ответов студентов: · 90-100% правильных ответов -отлично; · 70-90% правильных ответов -хорошо; · 60-70% правильных ответов - удовл.; · < 60% правильных ответов - неудовл. 5) Обучающе-контролирующая система должна предоставлять следующие возможности: · возможность работы системы в ЛВС с распечаткой результатов (протокола) на принтере сервера; · возможность задания времени ответа. 6) Обеспечение дружественного интерфейса. 2. ОБЗОР ЛИТЕРАТУРЫ В учебном пособии «Система программирования обучающих курсов» рассматриваются вопросы создания и использования обучающих курсов с помощью СПОК(системы программирования обучающих курсов) на базе ЕС ЭВМ или М-4030. Основные концепции, заложенные в СПОК, достаточно универсальны, так что описание ее организации является также хорошим руководством по системам реального времени. Данное учебное пособие содержит как описание структуры СПОК, так и материалы конструктивного типа, позволяющие основным категориям пользователей СПОК быстро освоить работу с этой системой. Т.о.,помимо пользователей СПОК - обучаемых, педагогов, разработчиков прикладных обучающих программ данное пособие может быть полезно специалистам и студентам Вузов и техникумов как основа проектирования и реализации широкого класса систем реального времени и диалоговых систем. Авторы учебного пособия стремились показать достаточно полно основные особенности функционирования СПОК под управлением различных ОС и в разных режимах, не рассматривая конкретных характеристик системы. Примеры, на которых иллюстрируется работа операторов языка обучающих курсов и директив, выбраны несложными, чтобы не затруднять читателю понимания основного материала пособия. В статье [2] приводится описание функциональных возможностей генератора тестов «Россь-2». Заложенные в нем возможности позволяют использовать «Россь-2» при изучении практически любого учебного предмета. Программа обладает следующими возможностями: · создание на основе имеющихся баз знаний тестов по различным предметам; · использование готовых систем тестов по различным учебным предметам и курсам; · использование при изучении учебного материала и тестировании контекстных учебников и системы подсказок; · использование различных параметров тестирования; · использование различных учебных режимов; · использование при обучении мультимедийных возможностей. Генератор тестов «Россь-2» включает следующие части: 1) тестирующую оболочку; 2) сервисную программу настройки. Дополнительно поставляется комплект утилит и сервисных программ для создания новых и редактирования имеющихся баз знаний, подключения к базам знаний графики, аудио- и видео-сопровождения, распечатки баз знаний и готовых тестов в различных вариантах в качестве раздаточных дидактических материалов. В поставку с ГТ «Россь-2» входит база знаний «компьютерная терминология», которая предназначена для: 1) изучения основных терминов, встречающихся в базовом курсе информатики; 2) изучения русских и английских терминов по компьютерной тематике для изучающих информатику и(или) английский язык на углубленном уровне. База знаний охватывает три основные темы: · аппаратное обеспечение; · основные термины информатики; · словарь Windows. По первой теме база знаний имеет библиотеку более чем из 80 графических изображений основных узлов и элементов ПК, периферийных устройств и компьютерных аксессуаров. По третьей теме база знаний имеет библиотеку более чем из 40 графических изображений элементов интерфейса Windows 3.X. В докладе [3] рассматриваются принципы и особенности построения курсов по информатике. Предлагаемые курсы реализованы, как средствами специальной поддерживающей системы, так и с использованием языков высокого уровня. Приведены типы вопросов и способы реализации контроля, средства индивидуализации хода обучения. Доклад иллюстрируется, в частности, курсом по булевой алгебре и курсом по внешним запоминающим устройствам ЭВМ. Одним из используемых методов индивидуализации процесса освоения материала является использование в курсе расширяемого словаря терминов. Книга [4] посвящена программному пакету Delphi компании Borland - мощному средству создания приложений для Windows, продолжающему линию компиляторов языка Pascal на качественно новом уровне. · В первой главе рассмотрены составные части интегрированной среды разработчика и их взаимодействие между собой в процессе создания приложений. · Говорить о серьезных проектах в Delphi можно, лишь договорившись о смысле, вкладываемом в понятие объекта, его свойств и связанных с ним событий. Поэтому вторая глава посвящена языку Object Pascal. Пропускать эту главу не стоит и знатокам Паскаля, т.к. в языке появились новые возможности. · Третья глава описывает библиотеку визуальных компонентов VCL. По сути дела, это первая революционная попытка не просто упростить, а полностью скрыть от разработчика программный интерфейс Windows. Помня о судьбе библиотеки Object Windows Library (OWL), которая тоже начиналась в Borland Pascal и стала со временем законодателем стандарта, можно предсказать идеям VCL счастливую судьбу. Ее компоненты - это специальная разновидность объектов Delphi, т.е. те «кирпичики», из которых строится новое приложение. В главе рассмотрены методы и свойства всех компонентов(за исключением вынесенных в следующую главу). Они сгруппированы по функциональному назначению и проиллюстрированы примерами. · Наконец, в четвертой главе разбираются вопросы работы с базами данных. Здесь описаны специальные компоненты доступа к данным, а также компоненты отображения и управления данными. Рассматриваются способы использования этих компонентов в приложениях, предназначенных как для работы с локальными базами данных, так и для систем клиент/сервер. Отдельные разделы посвящены ядру процессора баз данных Borland Database Engine, драйверам SQL Links, локальному серверу InterBase. В главу включен пример связывания приложения-клиента с сервером Informix. Для усвоения материала книги требуется понимание основ объектно-ориентированного программирования и принципов построения программ, управляемых событиями. Какую-то часть кода сгенерирует за вас Delphi, но для серьезной работы потребуется и серьезное знание языка Паскаль. Некоторые неосновные свойства компонентов, описанных в книге, ссылаются напрямую на программный интерфейс Windows. Его знание, конечно, не будет лишним, но и не является обязательным. Та часть книги, которая посвящена работе Delphi с базами данных, требует наличия у читателя основ знаний в этой области. 3. ПРОЕКТИРОВАНИЕ БАЗЫ ДАННЫХ 3.1 Концептуальная модель базы данных Первый шаг процесса проектирования состоит в определении всех атрибутов, включаемых в базу, и в определении связей между ними. Наш набор атрибутов - следующий: ТЕМА№ - порядковый номер темы с вопросами; ТЕМА - название раздела(темы); ВОПРОС№ - уникальный номер вопроса; ВОПРОС - текст вопроса; ОТВЕТ№ - уникальный номер варианта ответа на вопрос; ОТВЕТ - текст варианта ответа на вопрос; ИСТИННОСТЬ - истинность варианта ответа на вопрос(правда или ложь). Сведем все атрибуты и принимаемые ими на некоторый момент времени значения в следующую таблицу: Таблица 3.1 Сводная таблица атрибутов ПРО и их значений
Эта таблица не является отношением, так как значения первых четырех полей в ней - атомарные, а значения оставшихся трех - множественные. Чтобы таблица стала отношением, ее нужно реконструировать таким образом, чтобы каждый элемент кортежа имел атомарное значение. Это делается с помощью простого процесса вставки (табл.3.2.). Хотя вставка добавила большой объем избыточных данных, новая таблица получает статус отношения, которое называют универсальным отношением проектируемой БД. Такое отношение включает все представляющие интерес атрибуты и все данные, которые предполагается размещать в БД. Таким образом, получена концептуальная модель проектируемой БД. Таблица 3.2 Концептуальная модель БД
3.2 Логическая модель базы данных Проектирование реализации БД(логическое проектирование) представляет собой трансформацию концептуальной модели в набор отношений в нормальной форме Бойса-Кодда(НФБК). Для приведения спроектированного универсального отношения в НФБК воспользуемся декомпозиционным методом проектирования, содержанием которого является описание семантики универсального отношения в терминах функциональных зависимостей(ФЗ) и использование последних для нормализации отношения. Введем следующие понятия: функциональная зависимость, ключ, первичный ключ, детерминант, НФБК. Если даны два атрибута A и B, то говорят, что B функционально зависит от A (обозначается A à B), если для каждого A существует ровно одно связанное с ним значение B. A и B могут быть не только единичными атрибутами, но и группами из двух и более атрибутов. Ключом называется атрибут или совокупность атрибутов, которые используются для идентификации записи и обнаружения ее на ЗУ. Ключей может быть несколько. Первичный ключ используется для уникальной идентификации кортежа. Детерминант. Если в ФЗ A à B B не зависит от любого подмножества A(т.е. функциональная зависимость полна), то A является детерминантом B. НФБК определяется следующим образом: отношение находится в НФБК, если каждый детерминант отношения является ключом. Проверим находится ли универсальное отношение R(ТЕМА№, ТЕМА, ВОПРОС№, ВОПРОС, ОТВЕТ№, ОТВЕТ, ИСТИННОСТЬ) в НФБК. Выпишем ФЗ для универсального отношения: ТЕМА№ à ТЕМА, ТЕМА№, ВОПРОС№ à ВОПРОС, ВОПРОС№, ОТВЕТ№ à ОТВЕТ, ВОПРОС№, ОТВЕТ№ à ИСТИННОСТЬ. Из записанных ФЗ видно, что рассматриваемое отношение имеет только один ключ, а именно набор атрибутов < ТЕМА№, ВОПРОС№, ОТВЕТ№>. То есть это минимальный набор значений атрибутов, которые, если они известны, определяют значения других атрибутов кортежа. Детерминантами отношения являются левые части всех ФЗ, а именно: <ТЕМА№>, <ТЕМА№, ВОПРОС№>, <ВОПРОС№, ОТВЕТ№>. Легко обнаружить, что ни один детерминант не является ключом. Из чего следует, что рассматриваемое отношение не находится в НФБК и подлежит декомпозиции. Алгоритм декомпозиционного проектирования выглядит так: 1) разрабатывается универсальное отношение для БД; 2) определяются все ФЗ между атрибутами отношения; 3) определяется, находится ли отношение в НФБК. Если ДА, то проектирование завершено, если НЕТ, отношение должно быть разложено на два; 4) шаги 2 и 3 повторяются для каждого нового отношения, полученного в результате декомпозиции. Проектирование завершается, когда все отношения будут находиться в НФБК. Детерминант <ВОПРОС№, ОТВЕТ№> не является ключом и имеет два зависимых от него атрибута ВОПРОС№, ОТВЕТ№ à ОТВЕТ ВОПРОС№, ОТВЕТ№ à ИСТИННОСТЬ, что можно рассматривать в качестве единичной ФЗ с составными правой и левой частями ВОПРОС№, ОТВЕТ№ à ОТВЕТ,ИСТИННОСТЬ. Таким образом, получаются два новых отношения R1 и R2: R1(ТЕМА№, ТЕМА, ВОПРОС№, ВОПРОС) ФЗ: ТЕМА№ à ТЕМА, ТЕМА№, ВОПРОС№ à ВОПРОС. Возможные ключи: <ТЕМА№, ВОПРОС№>. Детерминанты:<ТЕМА№>,< ТЕМА№,ВОПРОС№>. R2(ВОПРОС№, ОТВЕТ№, ОТВЕТ, ИСТИННОСТЬ) ФЗ: ВОПРОС№, ОТВЕТ№ à ОТВЕТ,ИСТИННОСТЬ. Возможные ключи: <ВОПРОС№, ОТВЕТ№>. Детерминанты: <ВОПРОС№, ОТВЕТ№>. Отношение R2(ВОПРОС№, ОТВЕТ№, ОТВЕТ, ИСТИННОСТЬ) находится в НФБК, т.к. его детерминант является ключом, а потому в дальнейшей декомпозиции не нуждается. В отношении R1(ТЕМА№, ТЕМА, ВОПРОС№, ВОПРОС) детерминант <ТЕМА№> не является возможным ключом, поэтому R1 не находится в НФБК и подлежит дальнейшему расщеплению. Результатом расщепления отношения R1 являются отношения R3,R4: R3(ТЕМА№, ВОПРОС№, ВОПРОС) ФЗ: ТЕМА№, ВОПРОС№ à ВОПРОС. Возможные ключи: <ТЕМА№, ВОПРОС№ >. Детерминанты: <ТЕМА№, ВОПРОС№ >. R4(ТЕМА№, ТЕМА) ФЗ: ТЕМА№ à ТЕМА. Возможные ключи: <ТЕМА№>. Детерминанты: <ТЕМА№>. Эти два отношения находятся в НФБК, следовательно проектирование завершается и его результатом является логическая модель БД в НФБК: R2(ВОПРОС№, ОТВЕТ№, ОТВЕТ, ИСТИННОСТЬ), R3(ТЕМА№, ВОПРОС№, ВОПРОС), R4(ТЕМА№, ТЕМА). 3.3 Структура файлов базы данных В качестве формата для разрабатываемой базы данных был избран Paradox, т.к. он предоставляет следующие возможности: · Широкий выбор типов полей, включая авто-инкремент, BLOBs и т.п. · Соблюдение целостности данных, контроля данных, обновления индексов на уровне ядра BDE. · Первичный индекс таблицы автоматически соблюдает уникальность записей, вторичные индексы обеспечивают отсортированный «вид» на записи таблицы. В результате анализа поставленной задачи были разработаны следующие файлы данных: 1) TEMA - содержит информацию о имеющихся разделах(темах); 2) QUESTION - предназначен для хранения вопросов к темам из таблицы TEMA; 3) ANSWER - содержит варианты ответов на вопросы из таблицы QUESTION; 4) TICKETS - предназначен для хранения информации о билетах; 5) CONTROL - содержит информацию о результатах тестирования; 6) RESULT - предназначен для сбора информации об истинности ответов студента. Структуры файлов данных приводятся ниже в табличной форме. Таблица 3.3 Структура файла данных TEMA.DB
Таблица 3.4 Структура файла данных QUESTION.DB
Таблица 3.5 Структура файла данных TICKETS.DB
Таблица 3.6 Структура файла данных ANSWER.DB
Таблица 3.7 Структура файла данных CONTROL.DB
Таблица 3.8 Структура файла данных RESULT.DB
4. ОПИСАНИЕ ПРОГРАММНЫХ МОДУЛЕЙ Разработанная универсальная обучающе-контролирующая система содержит следующие части: 1) программу для создания и модификации тестов; 2) сервисную программу настройки параметров контроля знаний, формирования билетов, просмотра и распечатки результатов тестирования; 3) программу контроля знаний и предназначен для разработки, модификации и эффективного использования тестов в процессе обучения практически по любой дисциплине. Описание основных принципов функционирования программ, входящих в состав системы, приведено ниже. 4.1 Описание программы создания и модификации тестов Программа создания и модификации тестов, являясь составной частью универсальной обучающе-контролирующей системы, предназначена для создания и модификации контрольных вопросов, объединенных в разделы по тематическому признаку, а также таких разделов и предоставляет пользователю следующие возможности: · создание, модификация и удаление тематических разделов; · создание, модификация и удаление контрольных вопросов; · создание для любого вопроса произвольного числа вариантов ответа; · модификация и удаление вариантов ответа на вопрос. Программа реализована на языке Object Pascal в среде визуального программирования Delphi 2.0 фирмы Borland International. Текст программы и используемых ею модулей приведен в прил.1. Программой используются следующие файлы БД: Tema.db, Question.db, Answer.db. Схема связей файлов БД, используемая рассматриваемой программой, приведена на рис.4.1.
Рис.4.1. Схема связей файлов БД для программы создания тестов Так как программа разрабатывалась в системе визуального программирования Borland Delphi в соответствии с принципом модульности, то в каждом модуле объявляется отдельный класс, который содержит данные и методы работы с ними а также методы работы с данными из других классов. Ниже приведены описания классов, используемых в рассматриваемой программе. 1. Класс TTreeForm ( модуль S2) ‑ отображает главное окно программы. Переменные класса: - x1,x2 - вспомогательные переменные; - CreateMainForm - индикатор создания формы (True,если выполняется метод FormCreate). Методы класса: - AddDocButClick() - выполняет добавление нового контрольного вопроса в текущую тему; - MainTreeClick() - изменяет положение указателей в файлах БД Tema.db,Question.db; - DeleteButClick() - выполняет удаление текущего вопроса или темы; - FullExpButClick() - производит полное раскрытие тематического дерева; - FullColButClick() - выполняет полное сворачивание тематического дерева; - ExitButClick() - производит закрытие программы; - FormClose( ) - выполняет все необходимые действия перед закрытием программы; - AddTemaButClick() - выводит диалог добавления новой темы; - FormShow() - выполняет инициализацию данных при запуске программы; - FormResize() - производит действия по изменению размеров объектов окна; - FormCreate() - выполняет инициализацию переменных x1,x2; - AppendQuestion() - добавляет в таблицу Question.db новый вопрос; - ClearQuestion() - осуществляет логическое удаление текущего вопроса из БД. 2. Класс TEditForm (модуль DB_Unit) - отображает окно редактирования контрольных вопросов. Переменные класса: - x1,x2 - вспомогательные переменные. Методы класса: - FormClose( )- производит выход из программы; - DBEditTemaChange() - сохраняет в БД изменения в названии темы; - AddAnswerButClick() - добавляет новый вариант ответа на текущий вопрос; - DelAnswerButClick() - удаляет текущий вариант ответа на вопрос; - FormCreate() - выполняет инициализацию переменных; - AppendAnswer() - производит добавление в БД нового ответа; - ClearAnswer() - выполняет удаление из БД текущего ответа; - FormResize() - изменяет размер объектов окна; - MemoScrollResize() - изменяет размер объектов в области модификации ответов. 3. Класс TAnswer (модуль DBUnit) - отвечает за отображение вариантов ответа на вопрос. Переменные класса: - nocreate - индикатор создания объекта(False,если выполняется метод Create). Методы класса: - Create() - создает объект типа TAnswer; - Free() - освобождает память занятую объектом; - CheckClick() - заносит в файл БД Answer.db состояние флажка правильности ответа; - MemoChange() - сохраняет текст ответа в файле БД Answer.db; - DeleteAnswer() - производит перерисовку области вывода вариантов ответа на вопрос после удаления одного из ответов. 4. Класс TWinEditTema(модуль AddTema) - отображает диалог добавления новой темы. Методы класса: - butCancelClick() - добавляет новую тему в файл БД Teма.db. - butOkClick() - закрывает диалог добавления новой темы. 4.2 Описание программы администрирования Программа администрирования, являясь составной частью универсальной обучающе-контролирующей системы, предназначена для использования в сочетании с программой создания тестов и предоставляет пользователю следующие возможности: · формирование билетов; · задание времени ответа на вопросы билета; · задание системы оценки результатов тестирования; · просмотр и распечатка результатов (протокола) тестирования на принтере. Программа реализована на языке Object Pascal в среде визуального программирования Delphi 2.0 фирмы Borland International. Текст программы и используемых ею модулей приведен в прил.2. Программой используются следующие файлы БД: Control.db, Tema.db, Question.db, Tickets.db. Схема связей файлов БД, используемая рассматриваемой программой, приведена на рис.4.2. Программа создает файл Test.ini и записывает в раздел Options следующие параметры:
Рис.4.2. Схема связей файлов БД для программы администрирования Так как программа разрабатывалась в системе визуального программирования Borland Delphi в соответствии с принципом модульности, то в каждом модуле объявляется отдельный класс, который содержит в себе данные и методы работы с ними а также методы работы с данными из других классов. Ниже приведены описания классов, используемых в рассматриваемой программе. 1. Класс TAdminForm (модуль Main) ‑ отображает главное окно программы. Переменные класса: - CreateForm - индикатор создания формы (True,если выполняется метод FormCreate); - IniFile - используется для работы с INI-файлом. Методы класса: - ShowHint() - отображает подсказку в строке состояния; - DBControlCalcFields() - производит пересчет оценок в соответсвии с текущей системой оценки результатов; - FormClose() - выполняет все необходимые действия перед закрытием программы; - TestTimeChange() - сохраняет в файле TEST.INI значение параметра TestTime; - MaxmarkChange() - сохраняет в файле TEST.INI значение параметра MaxMark; - CreateTicketBtnClick() - выводит диалог параметров формирования билетов; - FormShow() - открывает таблицы Question.db, Tema.db; - QuitBtnClick() - завершает выполнение программы; - CreateNewDBControl() - создает новую таблицу Control.db; - ClearBtnClick() - очищает таблицу результатов тестирования; - PrintBtnClick() - выводит на принтер таблицу с результатами тестирования. 2. Класс TCreateTickDlg(модуль TQDialog) Методы класса: - QuestCountEnter() - производит инициализацию переменных; - OKBtnClick() - выполняет формирование билетов из контрольных вопросов заданной темы; - FormClose() - закрывает файлы БД Question.db, Tema.db; - FormShow() - считывает параметры TestTime и MaxMark из файла Test.ini. 4.3 Описание программы контроля знаний Тестирующая оболочка, являясь составной частью универсальной обучающе-контролирующей системы, предназначена для контроля знаний по выбранной администратором системы дисциплине и предоставляет пользователю следующие возможности: · просмотр вопросов билета в произвольном порядке; · возможность ответа на вопросы в произвольном порядке; · возможность корректировки ответов на вопрос. Программа реализована на языке Object Pascal в среде визуального программирования Delphi 2.0 фирмы Borland International. Текст программы и используемых ею модулей приведен в прил.3. Программой используются следующие файлы БД: Control.db, Question.db, Answer.db, Result.db, Tickets.db. Схема связей файлов БД, используемая рассматриваемой программой, приведена на рис.4.3.
Рис.4.3. Схема связей файлов БД для программы контроля знаний При запуске программы происходит считывание параметров TestTime и MaxTicket из раздела Options файла Test.ini. Программа производит также расчет и запись оценки ответа на вопросы билета. Запись результатов производится в БД Control.db. Так как программа разрабатывалась в системе визуального программирования Borland Delphi в соответствии с принципом модульности, то в каждом модуле объявляется отдельный класс, который содержит в себе данные и методы работы с ними а также методы работы с данными из других классов. Ниже приведены описания классов, используемых в рассматриваемой программе. 1. Класс TClientForm = (модуль SDIMain) ‑ отображает главное окно программы. Переменные класса: - x1,x2 - вспомогательные переменные; - CreateMainForm - индикатор создания формы (True,если выполняется метод FormCreate); - TestTime - время тестирования в миллисекундах; - MaxMark - система оценки(балл); - ticket - номер билета, по которому проводится тестирование; - StudentName - фамилия студента. Методы класса: - ShowHint()- отображает подсказку в строке состояния; - QuestListClick() - производит переход к следующему вопросу; - FormClose() - записывает результаты тестирования в Control.db; - FormShow() - выводит диалог ввода исходных данных; - FormCreate()- выполняет инициализацию переменных; - ExitButClick() - завершает работу программы; - PrevButClick() - делает текущим предыдущий вопрос; - NextButClick() - делает текущим следующий вопрос; - TimerTimer() - завершает работу программы по истечении контрольного времени; - RefreshAnswers - обновляет содержимое области вывода ответов; - DeleteAnswer() - удаленние из списка ответов одного варианта ответа; - FormResize() - производит действия по изменению размеров объектов окна; - MemoScrollResize() - изменяет размер объектов в области вывода ответов. 2. Класс TAnswer (модуль SDIMain) - отвечает за отображение вариантов ответа на вопрос. Переменные класса: - nocreate - индикатор создания объекта(False,если выполняется метод Create). Методы класса: - Create() - создает объект типа TAnswer; - Free() - освобождает память занятую объектом; - CheckClick() - заносит в файл БД Result.db состояние флажка правильности ответа; - MemoClick() - устанавливает фокус на область выбора текущего вопроса. 3. Класс TBeginDataDlg(модуль DLGUnit) - отображает диалог ввода исходных данных. Методы класса: - ShowHint() - отображает подсказку в строке состояния; - OkButClick() - создает файл БД Result.db и инициализирует переменные; - FormClose() - выполняет необходимые действия перед закрытием диалога; - FormShow() - считывает параметры MaxTicket,TestTime и MaxMark из файла Test.ini. 4. Класс TPathDlg (модуль PathDialog) Методы класса: - DriveBoxChange() - изменяет текущий диск; - FormClose() - выполняет необходимые действия перед закрытием диалога; - DirectoryListChange() - выводит название текущего каталога; - FormActivate() - выводит название текущего каталога при появлении диалога ввода пути к каталогу БД. 5. Руководство пользователЯ 5.1 Общие сведения Разработанная универсальная обучающе-контролирующая система предназначена для разработки, модификации и эффективного использования тестов в процессе обучения практически по любой дисциплине. Комплекс программ содержит следующие части: 1) программу для создания и модификации тестов; 2) сервисную программу настройки параметров контроля знаний, формирования билетов, просмотра и распечатки результатов тестирования; 3) программу контроля знаний. Универсальная обучающе-контролирующая система обладает следующими возможностями: · создание на основе имеющихся баз знаний тестов по различным предметам; · модификация созданных тестов; · формирование билетов; · задание времени ответа на вопросы билета; · задание системы оценки результатов тестирования; · контроль знаний обучаемых посредством тестирования; · возможность работы системы в ЛВС; · просмотр и распечатка результатов (протокола) тестирования на принтере. Для функционирования программного обеспечение необходимо наличие на ПК операционной системы Windows-95 или Windows NT а также сетевого ПО, если будет использоваться многопользовательский режим работы программ. Перед запуском любой из программ системы на компьютере должен быть установлен BDE(комплекс программ и.DLL - библиотек для работы с БД), входящий в комплект поставки универсальной обучающе-контролирующей системы. После установки BDE необходимо запустить программу BDECFG32.EXE и, выбрав закладку «Aliases», добавить новый алиас с именем «Common_base» и параметрами: TYPE = «STANDARD», DEFAULT DRIVER = «PARADOX», PATH = <путь к каталогу БД, установка которых рассматривается в п.5.2.>. 5.2 Установка файлов баз данных Для обеспечения нормального функционирования универсальной обучающе-контролирующей системы необходимо перед ее использованием установить в отдельный каталог на диске следующие файлы: Answer.db, Answer.mb, Answer.px, Answer.xg0, Answer.yg0, Question.db, Question.mb, Question.px, Question.xg0, Question.yg0, Tema.db, Tema.px. Если используется многопользовательский вариант работы с программами комплекса, то вышеуказанные файлы БД должны быть установлены на сервере. 5.3 Использование программы создания и модификации тестов Программа предназначена для создания и модификации контрольных вопросов, объединенных в разделы по тематическому признаку, а также таких разделов и предоставляет пользователю следующие возможности: · создание, модификация и удаление тематических разделов; · создание, модификация и удаление контрольных вопросов; · создание для любого вопроса произвольного числа вариантов ответа; · модификация и удаление вариантов ответа на вопрос. Для функционирования программы необходимо наличие 600K свободного дискового пространства. Исполняемый файл программы - TestBuilder.exe может располагаться в любом каталоге произвольного диска. Чтобы начать работу с программой необходимо запустить файл TestBuilder.exe на выполнение. После запуска программы на экране появляются два окна, размеры которых можно изменять при помощи мыши. В окне, расположенном в левой части экрана (рис.5.1.), находятся кнопки для осуществления операций над разделами и вопросами и дерево, отображающее названия имеющихся тематических разделов и номера вопросов. Рассмотрим операции, которые позволяет производить программа с данными. Т.к. операции удаления и модификации производятся над объектами, которые являются в данный момент времени текущими, то введем понятие текущего объекта. Текущим объектом (вопросом/разделом/вариантом ответа) будем называть объект, который в данный момент выделен(например, номер вопроса или название темы в дереве) или на нем находится курсор(например, курсор находится в поле редактирования варианта ответа). Чтобы сделать объект текущим достаточно щелкнуть на нем мышью.
Рис.5.1. Окно выбора текущего контрольного вопроса n Добавление нового тематического раздела Для того чтобы создать новый раздел необходимо щелкнуть мышью на кнопке . При этом на экран будет выведен диалог запроса названия раздела(рис.5.2.). После того как вы введете название новой темы, необходимо нажать кнопку «Добавить», если вы хотите чтобы созданная тема была добавлена в список существующих тем, и кнопку «Отмена» - в противном случае. Рис.5.2. Диалоговое окно ввода названия новой темы n Добавление нового вопроса Для добавления нового вопроса в какую-либо тему необходимо сначала сделать эту тему текущей а затем нажать кнопку . После этого можно вводить и корректировать текст вопроса в области редактирования, над которой находится надпись «Текст вопроса». n Удаление разделов и вопросов Для того, чтобы удалить текущий раздел либо вопрос необходимо нажать кнопку . При этом на экран будет выведен диалог подтверждения удаления с соответствующим случаю текстом (рис.5.3.). Рис.5.3. Запрос подтверждения удаления вопроса В окне, расположенном в правой части экрана (рис.5.4), можно производить модификацию названий тематических разделов, текста контрольных вопросов и операции создания, модификации, удаления над вариантами ответов на вопросы. Рис.5.4. Окно модификации данных n Редактирование названия раздела Модифицировать название текущего раздела можно в области редактирования, над которой имеется надпись «Название темы». n Редактирование текста вопроса Модифицировать текст текущего вопроса можно в области редактирования, над которой имеется надпись «Текст вопроса». n Добавление нового варианта ответа Для добавления нового варианта ответа в текущий вопрос необходимо нажать кнопку После этого в появившейся области ввода можно вводить и модифицировать текст варианта ответа на вопрос. Истинность текущего варианта ответа отмечается пометкой в квадратике, который расположен правее соответствующего варианта ответа. n Удаление варианта ответа на вопрос Чтобы удалить текущий вариант ответа необходимо нажать кнопку . n Редактирование варианта ответа Чтобы модифицировать текст варианта ответа на вопрос необходимо сделать его текущим а затем производить корректировку текста. Истинность варианта ответа можно изменить, установив флажок, который расположен правее соответствующего варианта ответа. Если эта область имеет пометку, то данный вариант ответа на вопрос является правильным. Назначение 3-ех вспомогательных кнопок следующее: - разворачивает все темы; - сворачивает все темы; - выход из программы. 5.5 Использование программы администрирования Программа предназначена для использования в сочетании с программой создания тестов и предоставляет пользователю следующие возможности: · формирование билетов; · задание времени ответа на вопросы билета; · задание системы оценки результатов тестирования; · просмотр и распечатка результатов (протокола) тестирования на принтере. Для функционирования программы необходимо наличие 600K свободного дискового пространства. Исполняемый файл программы - TestAdmin.exe может располагаться в любом каталоге произвольного диска. Чтобы начать работу с программой необходимо запустить файл TestAdmin.exe на выполнение. После запуска программы на экране появляется главное окно программы (рис.5.5.), в котором в табличной форме выводятся сведения о результатах предыдущего тестирования. Рис.5.5. Главное окно программы администрирования В этом окне задаются параметры тестирования: время тестирования(в минутах) и система оценки(в баллах). Когда параметры тестирования заданы, можно приступать к формированию билетов. Для этого необходимо нажать кнопку «Создать», следствием чего будет появление диалогового окна задания параметров формирования билетов(рис.5.6.). Рис.5.6. Диалог задания параметров формирования билетов Перед формированием билетов необходимо задать следующие параметры: 1) тема, из вопросов которой будут формироваться билеты; 2) количество вопросов в билете; 3) число билетов, которое вы желаете получить. Если вы нажмете кнопку создать, то по завершению формирования билетов на экран будет выдано сообщение «Формирование билетов завершено!» (рис.5.7.). Рис.5.7. Сообщение о завершении формирования билетов При формировании билетов вопросы заданной темы распределяются по билетам случайным образом. Кнопка «Выход» служит для завершения работы программы. Кнопка «Очистить» предназначена для удаления всех записей из таблицы результатов тестирования. Кнопка «Печать» предназначена для получения твердой копии результатов тестирования. Пример распечатанных результатов приведен на рис.5.8. Рис.5.8. Распечатка результатов тестирования 5.3 Использование программы контроля знаний Тестирующая оболочка предназначена для контроля знаний по выбранной администратором системы дисциплине. Для функционирования программы необходима ОС Windows95 или Windows NT и наличие не менее 1M свободного дискового пространства. Исполняемый файл программы - TestClient.exe может располагаться в любом каталоге произвольного диска. Чтобы начать сеанс тестирования необходимо запустить файл TestClient.exe на выполнение. Если программа запускается впервые, то на экран будет выдан запрос на ввод имени каталога БД, т.е. того каталога, где хранятся установленные ранее файлы Tickets.db, Tema.db, Question.db, Answer.db (рис.5.9). Рис.5.9. Диалог установки каталога файлов БД Когда каталог файлов БД выбран, необходимо нажать кнопку «Все» чтобы продолжить выполнение программы либо кнопку «Отмена» для ее завершения. Если вы ввели верное имя каталога файлов БД, то на экране появится диалог, в котором необходимо ввести фамилию и выбрать номер билета для тестирования (рис.5.10). Рис.5.10. Диалог запроса исходных данных для тестирования Переход по полям ввода данных и кнопкам осуществляется с помощью клавиши ‘Tab’, а в обратном порядке при помощи ‘Shift-Tab’. Для подтверждения введенных данных нажмите кнопку «Все». Для выхода из программы нажмите кнопку «Выход» либо клавишу Esc. После подтверждения введенных данных на экране появится окно(рис.5.11.), в котором вы сможете в произвольном порядке просматривать вопросы билета и отвечать на них. Рис.5.11. Основное окно программы контроля знаний В верхней части окна расположена область, в которой выводится текст вопроса. Ниже располагаются варианты ответов на вопрос. Чтобы отметить правильный ответ достаточно установить флажок, который находится справа от соответствующего варианта ответа. При этом в указанной области должен появится значок пометки. При повторном щелчке пометка снимается. Для любого вопроса могут быть одновременно верными несколько вариантов ответа. Можно отвечать на вопросы в произвольном порядке, производить корректировку ответов на вопросы и просматривать вопросы в произвольном порядке. Номер текущего вопроса отображается выделением в вертикальном списке номеров вопросов, расположеннном в левой части окна программы. Для перехода к следующему вопросу необходимо нажать кнопку «Следующий», а к предыдущему - «Предыдущий». Перейти к произвольному вопросу можно щелкнув на его номере мышью в списке вопросов. Время, истекшее с начала момента тестирования, отображается с помощью индикатора, расположенного над текстом вопроса. По истечении времени, заданного администратором системы для ответов на вопросы, либо при нажатии кнопки «Завершить», программа завершает свою работу и выводит на экран сообщение о результатах тестирования (рис.5.12.). Рис.5.12. Сообщение о результатах тестирования 6. ОХРАНА ТРУДА В связи с автоматизацией процессов производства и управления, развитием вычислительной техники и разработкой систем автоматизации проектных, исследовательских и технологических работ широкое распространение получили видеотерминалы (ВТ) - устройства, отображающие информацию о ходе процесса или состояние объекта наблюдения на экране индикатора. Видеотерминалы используются в информационных и вычислительных центрах, на предприятиях связи, полиграфии, в диспетчерских пунктах управления технологическими процессами и транспортными перевозками и т.д. Использование ВТ в различных сферах производственной деятельности выдвигает проблему оздоровления и оптимизации условий труда операторов ввиду формирования при этом целого ряда неблагоприятных факторов: высокая интенсивность труда, монотонность производственного процесса, гипокинезия и гиподинамия, специфические условия зрительной работы, наличие электромагнитных излучений, тепловыделений и шума от технологического оборудования. 6.1 Техника безопасности и производственная санитария Условия труда операторов ВТ характеризуется возможностью воздействия на них комплекса опасных и вредных производственных факторов: · электрический ток и статическое электричество; · ионизирующих и неионизирующих излучений; · шума; · тепловыделений и вредных веществ; · специфических условий зрительной работы, параметров технологического оборудования и рабочего места шума; · вибрации. 6.1.1 Электрический ток и статическое электричество Эксплуатация вычислительной техники связана с применением электрической энергии. Электрический ток, проходя через организм, оказывает термическое, электролитическое и биологическое действие, вызывая местные и общие электротравмы. Местные травмы подразделяются на: - электрические ожоги; - электрические знаки; - металлизацию кожи; - механические повреждения; - электроофтальмию. Общие электротравмы или электрические удары по степени тяжести делятся на четыре степени. Основными причинами воздействия тока на человека являются: - случайное прикосновение или приближение на опасное расстояние к токоведущим частям; - появление напряжения на металлических частях оборудования в результате повреждения изоляции или ошибочных действий персонала. Основные меры защиты от поражения током: - изоляция; - недоступность токоведущих частей; - электрическое разделение сети с помощью специальных разделяющих трансформаторов; - применение малого напряжения; использование двойной изоляции; - защитное заземление; - защитное отключение. Опасность возникновения статического электричества проявляется в возможности образования электрической искры и вредном действии его на организм человека. Эта искра может служить причиной воспламенения горючих или взрывоопасных газов, паров или пыли с воздухом. Статическое электричество оказывает вредное воздействие на организм человека, причем не только при непосредственном контакте с зарядом, но и за счет действия электрического поля, возникающего вокруг заряженных поверхностей. Основные способы защиты от статического электричества: - заземление оборудования; - увеличение поверхностей проводимости диэлектриков; - увлажнение окружающего воздуха; - ионизация воздуха или среды нейтрализаторами статического электричества. 6.1.2 Излучения При работе с дисплеем могут возникнуть следующие опасные факторы: - электромагнитные поля; - рентгеновское излучение; - ультрафиолетовое и инфракрасное излучение. Воздействие электромагнитных полей на человека зависит от напряжённостей электрического и магнитного полей, потока энергии, частоты колебаний, размера облучаемой поверхности тела и индивидуальных особенностей организма. Наиболее эффективным и часто применяемым из названных методов защиты от электромагнитных излучений является установка экранов. Экранируют либо источник излучения, либо рабочее место. Экраны бывают отражающие и поглощающие. Индивидуальные экранирующие комплексы предназначены для защиты от воздействия электрического поля, напряженность которого не превышает 60 кВ/м. Для обеспечения безопасности работ с источниками электромагнитных волн (в данном случае с ПЭВМ) производится систематический контроль фактических значений нормируемых параметров на рабочих местах. Контроль осуществляется измерением напряжения электрического и магнитного полей, а также измерением плотности потока энергии. Для экранов применяют материалы с высокой электрической проводимость (сталь, медь, алюминий, латунь) в виде листов толщиной не менее 0,5 мм или сетки с ячейками не более 4x4 мм. Небольшие отверстия в экране, предусматриваемые для осей штурвалов, кнопок и других приспособлений, экранируют густой металлической сеткой с ячейками не более 4x4 мм. Каждый экран обязательно заземляют. Защита с помощью экранов выполняется многоступенчатой, включая экранирования генераторного (первичного) контура, рабочих контуров (плавильных, нагревательных и др.) и установки в целом. Степень ослабления электромагнитного поля экраном характеризуется величиной, условно называемой глубиной проникновения электромагнитного поля в материал экрана, толщина которого должна быть больше глубины проникновения поля. Эластичные экраны (из специальной ткани с вплетенной тонкой металлической сеткой) применяют для изготовления экранных штор, чехлов, спецодежды и т.п. Для экранов применяют и оптически прозрачное стекло, покрытое полупроводником - двуокисью олова; оно также обеспечивает ослабление электромагнитного поля. Основными мероприятиями, направленными на снижение опасности воздействия инфракрасного излучения являются: - снижение интенсивности источника; - защитное экранирование источника и рабочего места; - использование средств индивидуальной защиты; - лечебно-профилактические мероприятия. Необходимо также в целях предосторожности ограничить продолжительность работы с экраном ВТ, не размещать ВТ концентрированно в рабочей зоне и выключать их, если на них не работают, использовать защитные экраны. 6.1.3 Шум По своему происхождению шум делится на механический, обусловленный колебаниями деталей машины, аэродинамический(гидравлический), возникающий в упругих конструкциях, в газе или жидкости, и шумы электрических машин. Для рабочих мест ВЦ характерно наличие всех видов шумов. Основными источниками шума в помещениях, оборудованных ВТ, являются пишущие машинки, принтеры, множительная техника и оборудование для кондиционирования воздуха, в самих ВТ вентиляторы систем охлаждения и трансформаторы. Уровень шума в таких помещениях иногда достигает 85 дБА. Согласно ГОСТ 12.1.003-83 ССБТ уровень шума на рабочих местах операторов не должен превышать 50 дБА (см. табл. 6.1). Таблица 6.1 Уровень шума на рабочих местах
Нормированные уровни шума обеспечиваются путем использования малошумного оборудования, применением звукопоглощающих материалов для облицовки помещений а также различных звукопоглощающих устройств (перегородки, кожухи, прокладки и т.д.). Шум не превышает допустимых пределов, так как в вычислительной технике нет вращающихся узлов и механизмов (за исключением вентилятора), а наиболее шумное оборудование (модем) находится в специально отведенном помещении. 6.1.4 Вибрация Вибрация - это колебательное движение механической системы. Она характеризуется частотой f, Гц; смещением A(t), м; скорость V(t), м/с; ускорением a(t), м/с2. Источником вибрации являются механизмы, машины, механизированный инструмент. Вибрация по способу передачи телу человека подразделяется на общую (воздействие на все тело через опорные поверхности) и локальную (воздействие на отдельные части тела: руки или ноги). Вибрация относится к факторам обладающим большой биологической активностью. Как общая, так и локальная вибрация оказывает неблагоприятное влияние на организм человека, вызывают изменения в функциональном состоянии вестибулярного анализатора, центральной нервной, сердечно‑сосудистой и других систем, приводят к утомлению, снижают работоспособность, ухудшают самочувствие и могут привести к развитию профессионального заболевания — вибрационной болезни, сопровождаемой стойкими паталогоческими нарушениями в организме работающего (поражение мышц, изменение в костях и суставах, смещение внутренних органов). Согласно ГОСТ 12.1.012-90 ССБТ уровень вибрации на рабочих местах операторов не должен превышать 75 дБ (по виброскорости). Нормированные уровни вибрации обеспечиваются путем использования виброизоляторов из материалов с большим внутренним трением (резины, пробки, войлока, асбеста или стальных пружин). При работе с вычислительной техникой уровень вибрации не превышает допустимых пределов, так как в вычислительной технике нет вращающихся узлов и механизмов (за исключением вентилятора). 6.1.5 Метеоусловия С целью обеспечения комфортных условий для обслуживающего персонала и надежности технологического процесса согласно ГОСТ 12.1.005-88, п.1.4 устанавливают следующие требования к микроклиматическим условиям (см. табл. 6.2.) Таблица 6.2 Требования к микроклиматическим условиям
Согласно ГОСТ 12.1.005-88 п.1.8 интенсивность теплового излучения работающих от нагретых поверхностей технологического оборудования, осветительных приборов, инсоляции на постоянных местах не должна превышать 35 Вт/м2 при облучении 50% поверхности тела и более. Для создания нормальных микроклиматических условий наиболее целесообразно уменьшить тепловыделения от самого источника — монитора, что должно предусматриваться при разработке его конструкции. Кроме того, это достигается также обеспечением соответствующей площади и объема производственного помещения, устройством эффективной системы вентиляции и кондиционирования. Кондиционеры — это вентиляционные установки, которые с помощью приборов автоматического регулирования поддерживают в помещении заданные параметры воздушной среды. Кондиционеры бывают двух видов: - установки полного кондиционирования воздуха, обеспечивающие постоянство температуры, относительной влажности, скорости движения и чистоты воздуха; - установки неполного кондиционирования, обеспечивающие постоянство только части этих параметров или одного параметра, чаще всего температуры. Контроль параметров микроклимата осуществляется с помощью приборов непрерывного и периодического измерения. Измерения производятся пять раз в смену на высоте 1.5 метра от пола. Приборы непрерывного измерения: термографы, барографы. Они измеряют соответственно температуру, относительную влажность, атмосферное давление. Для обеспечения требуемых метеорологических условий труда принимают системы отопления, вентиляции и кондиционирования. Для очищения воздуха пыли в местах забора устанавливают фильтры 2-го и 3-го класса типов ФППУ, ФСВУ, ФЯЛ, ФВН. Для эксплуатации ЭВМ предусматривается три типа помещений: - основные - к ним относятся: машинный зал, помещения для размещения сервисной и периферийной аппаратуры; - вспомогательные - помещения для хранения носителей информации, помещения для размещения приточно-вытяжных вентиляторов и устройств кондиционирования воздуха; - производственные- помещения для приема и выдачи информации, помещения для обслуживающего персонала ЭВМ. Помещения ВЦ, их размеры(площадь, объем) выбираются в соответствии количеством работающих и размещенном в них оборудованием. Для обеспечения нормальных условий труда в санитарных нормах устанавливают на одного работающего объем производственного помещения не менее 15 м. К основным помещениям предъявляются особые требования. Площадь машинного зала соответствует площади, необходимой по заводским техническим условиям для данного типа ЭВМ: - высота зала под техническим полом до подвесного потолка 3-3.5 метра, - расстояние между подвесным и основным потолком при этом должно быть 0.5-0.8 метра, - габариты дверей машинного зала принимаются не менее 1.8 х 1.1 метра. Площадь помещения для хранения магнитных носителей информации составляет не менее 16 м. Пол, потолок и стены хранилища покрывают несгораемыми материалами. Двери должны быть металлическими или деревянными, обитые листовым железом по войлоку, смоченному раствором глины, или асбесту. Все вспомогательные помещения ВЦ расположены в нижних и цокольных этажах, их высота - 3.3 метра. 6.1.6 Освещение Важное место в комплексе мероприятий по охране труда и оздоровлению условий труда работающих с ВТ занимает создание оптимальной световой среды, т.е. рациональная организация естественного и искусственного освещения помещения и рабочих мест. Согласно СНиП II-4-79 п.1.2 помещения для работы с дисплеями и видеотерминалами относятся к I группе по задачам зрительной работы. Нормированный уровень освещенности для работы с ВТ принят 400 лк (см. табл. 6.3) Таблица 6.3 Нормирование уровня освещенности
В этих случаях предусматриваются меры для ограничения слепящего воздействия светопроемов, имеющих высокую яркость (8000 кд/м2 и более), и прямых солнечных лучей для обеспечения благоприятного распределения светового потока в помещении и исключения на рабочих поверхностях ярких и темных пятен, засветки экранов посторонним светом, а так же для снижения теплового эффекта от инсоляции. Это достигается путем соответствующей ориентации светопроемов, правильного размещения рабочих мест и использования солнцезащитных средств. Требования к снижению дискомфортной блескости и зеркального отражения в экранах удовлетворяются путем использования светильников с комбинированным прямым и отраженным направлением света, которое осуществляется с помощью двойной крестовой оптики. Часть прямого светового потока лампы направляется через параболический зеркальный растр таким образом, что ограничивается слепящее действие прямого и отраженного света; отраженная часть излучения лампы направляется широким потоком на потолок (рис. 6.1.) Рис 6.1. Кривая силы света светильника с двойной крестовой оптикой. Благодаря такому светораспределению в верхней полусфере яркость потолка в любом месте, в том числе и непосредственно под светильником, не превышает 200 кд/м2. Габаритная яркость светильников в зоне углов излучения более 50 ° от вертикали ограничивается в обеих плоскостях 200 кд/м2. (рис. 6.2.) Рис.6.2. Ограничение яркости (L) светильников общего освещения для работы с видеотерминалом В ВЦ применяют одностороннее естественное освещение. В машинных залах рабочие места операторов, работающих с дисплеями, располагают подальше от окон и таким образом, чтобы оконные проемы находились сбоку от работающих. В случае если экран ВТ обращен к оконному проему, должны быть предусмотрены специальные экранирующие устройства. Окна рекомендуется снабжать светорассеивающими шторами (r=0,5-0,7), регулируемыми жалюзи или солнцезащитной пленкой с металлическим покрытием. В тех случаях когда одного естественного освещения в помещении недостаточно, устраивают совмещенное освещение. При этом дополнительное искусственное освещение в помещении и рабочих местах должно создавать хорошую видимость информации на экране ВТ, машинописного и рукописного текста и других рабочих материалов. При этом в поле зрения работающих должны быть обеспечены оптимальные соотношения яркости рабочих и окружающих поверхностей, исключена или максимально ограничена отраженная блеклость от экрана и клавиатуры в результате отражения в них световых потоков от светильников и источников света. Для искусственного освещения помещений ВЦ следует использовать главным образом, люминесцентные лампы белого света (ЛБ) и темно-белого цвета (ЛТБ) мощностью 20,40 или 80 Вт. Планировка рабочего места должна удовлетворять требованиям удобства выполнения работ и экономии энергии оператора, рационального использования площадей и удобства обслуживания устройств ЭВМ. Кнопки для включения, ручки управления средств сигнализации должны обеспечивать минимальные затраты. 6.1.7 Расчет естественного освещения Помещения с постоянным пребыванием людей должны иметь, как правило, естественное освещение. Естественное освещение подразделяется на боковое, верхнее и комбинированное. При одностороннем боковом освещении нормируется минимальное значение КЕО в точке, расположенной на расстоянии 1 метра от стены, наиболее удалённой от световых проёмов, на пересечении вертикальной плоскости характерного разреза помещения и условной рабочей поверхности (или пола). При двухстороннем боковом освещении нормируется минимальное значение КЕО в точке посередине помещения на пересечении вертикальной плоскости характерного разреза помещения и условной рабочей поверхности (или пола). Исходные данные для расчета: - размер помещения — 15 * 17 * 4, м; - два окна с двойным остеклением и металлическими переплетами выходят на восток; - площадь остекления — 4 м2; - размеры остекления — 240*200, см. Нормируемое значение КЕО eн определяется по формуле
где = 1,5% для бокового освещения, m - коэффициент светового климата, принят 0,9, C - коэффициент солнечности климата, принят 0,8. Получаем = 1.5×0.9×0.8 = 0.1. Предварительный расчёт площади боковых проёмов производится по формуле
где S0 - площадь световых проёмов в свету, Sn - площадь пола помещения, eH - нормированное значение КЕО, Кз - коэффициент запаса, принят 1,2, h0 - световая характеристика окно, принят 15, Кзд - коэффициент, учитывающий затенение окон противостоящими зданиями, принят 1,2, t0 - коэффициент светопропускания материала, определяется по формуле
гдеt1 - коэффициент светопропускания материала, принят 0,8, t2 - коэффициент, учитывающий потери света в переплётах светопроёмов, принят 0,6, t3 - коэффициент, учитывающий потери света в несущих конструкциях при боковом освещении, принят 1, t4 - коэффициент, учитывающий потери света в солнцезащитных устройствах, принят 1, t5 - коэффициент, учитывающий потери света в защитной сетке, устанавливаемой под фонарями, принимается равным 0,9. Отсюда = 0,4. r1 - коэффициент, учитывающий повышение КЕО при боковом освещении, принят 1,25. При выборе коэффициентов использовались значения для лаборатории центра ИТ. Расчёт коэффициента естественной освещённости (КЕО) производится по формуле
где - геометрический КЕО в расчётной точке при боковом освещении, учитывающий свет неба, q - коэффициент, учитывающий неравномерную яркость облачного неба, принят 0,91 при угловой высоте светопроёма над рабочей поверхностью 34 град, - геометрический КЕО в расчётной точке при боковом освещении, учитывающий свет, отражённый от противостоящих зданий, R - коэффициент, учитывающий относительную яркость противостоящих зданий, принят 0,15 при Z1 = 0,5, Z2 = 1. Геометрические коэффициенты естественной освещенности, учитывающие прямой свет неба, в какой-либо точке помещения определяются по формуле
где n1 - количество лучей проходящих от неба через световые проёмы в расчётную точку на поперечном разрезе помещения, принято 7, n2 - количество лучей проходящих от неба через световые проёмы в расчётную точку на плане помещения, принято 8. Геометрические коэффициенты естественной освещенности, учитывающие свет, отражённый от противостоящего здания при боковом освещении определяется по формуле
где - количество лучей проходящих от противостоящего здания через световые проёмы в расчётную точку на поперечном разрезе помещения, принято 5, - количество лучей проходящих от противостоящего здания через световые проёмы в расчётную точку на плане помещения, принято 6. Расчёт: = 0,56, = 0,42, = 0,239. Расчётное значение КЕО больше нормируемого, поэтому при заданных размерах оконных проёмов обеспечивается достаточная освещённость рабочего места. 6.1.8 Организация рабочего места При размещении ВТ на рабочем месте согласно ГОСТ 12.2.032-78 учитываются границы полей зрения оператора, которые определяются движениями глаз и головы. Различают зоны зрительного наблюдения в вертикальной плоскости, ограниченные определенными углами, в которых располагаются экран ВТ (40-60 °), пюпитр (35-45 °) и клавиатура. (рис. 6.3.) Рис.6.3. Зоны зрительного наблюдения в вертикальной плоскости При организации рабочего места учитываются антропометрические данные операторов, а также предусматривается соответствующие размещение элементов оборудования в зависимости от характера выполняемой работы. Зоны для выполнения ручных операций и размещения органов управления показаны на рис.6.4. Высота сидения от пола должна регулироваться в пределах 42-55 см. Зависимость высоты рабочей поверхности от роста человека показана на рис.6.5. По желанию оператора устанавливается подставка для ног размером 40х30х15 см и углом наклона 0-20° с нескользящим покрытием и неперемещаемая по полу.
При постоянной работе (рис.6.6) экран должен быть расположен в центре поля обзора, документы слева на столе или на специальной подставке. Рабочий стол должен иметь стабильную конструкцию. Плоскость стола выбирают в зависимости от размера документов. При больших размерах документов она должна быть 160х90 см. Плоскость стола, а также сидение оператора должны регулироваться по высоте. Высоту плоскости стола необходимо регулировать в диапазоне 65-85 см или 68-84 см. При этом высота от горизонтальной линии зрения до рабочей поверхности стола при выпрямленной рабочей позе должна быть 45-50 см. Рис. 6.6. Расположение элементов оборудования ВТ при постоянной работе с экраном 6.2 Пожарная безопасность В современных ЭВМ имеется высокая плотность размещения элементов электронных схем. В непосредственной близости друг от друга располагаются соединительные провода, коммуникационные кабели. При протекании по ним электрического тока выдается значительное количество теплоты, что может привести к повышению температуры отдельных узлов до 80-100 °С, при этом возможно отклонение изоляции соединительных проводов что, как правило приводит к короткому замыканию, которое сопровождается искрением и ведет к недостаточной надежности и перегрузке элементов электронных схем. В последствии перегреваясь, сгорают с разбрызгиванием искр. Для отбора избыточной теплоты от ЭВМ служат системы вентиляции и кондиционирования воздуха. Однако, мощные разветвления, постоянно действующие системы вентиляции и кондиционирования представляют дополнительную пожарную опасность для ВЦ, так как с одной стороны оно обеспечивает подачи кислорода - окислителя во все помещения, а с другой - при возникновении пожара быстро распространяют огонь и продукты горения во всем помещении и устройствам, с которым связаны воздуховоды. Напряжение к электроустановкам ВЦ подается по кабельным линиям, которые представляют особую пожарную опасность. Наличие горючего изоляционного материала, вероятных источников зажигания в виде электрических дуг и искр, разветвленности, труднодоступность делают кабельные линии местом наиболее вероятного возникновения и развития пожара. По взрывной и пожарной опасности помещения и здания подразделяются на категории А,Б,В,Г,Д в зависимости от выполняемых в них технологических процессов, свойств применяемых веществ и материалов, а так же условиями их обработки. Так как в процессе производства используются горючие вещества и материалы (бумага, магнитные ленты, порошковые картриджи для множительной и оргтехники), которые при взаимодействии с кислородом воздуха могут гореть, то назначаем категорию пожарной безопасности В (ОНТП 24-86, табл.1). Одной из важных задач пожарной профилактики является защита строительных конструкций от разрушений и обеспечение их достаточной прочности в условиях воздействия высоких температур при пожаре. Учитывая высокую стоимость электронного оборудования ВЦ, а так же категорию их пожарной опасности, здания для ВЦ и части зданий другого назначения, в которых предусмотрено размещение ЭВМ относятся к 1 или 2 ступени стойкости. Для изготовления строительных конструкций используют, как правило кирпич, железобетон, стекло и другие негорючие материалы. Для предотвращения распространения огня во время пожара с одной части здания на другую устраивают противопожарные преграды в виде стен, перегородок, дверей, окон, люков, клапанов. Особое требование предъявляется к устройству и размещению кабельных коммуникаций. Все виды кабелей прокладываются в металлических газовых агрегатов до распределительных щитов или стоек питания. Для ликвидации пожаров в начальной стадии применяются первичные средства пожаротушения: - внутренние пожарные водопроводы, - огнетушители типа ОХП-10, ОХП-11, - сухой песок, - асбестовые одеяла и др. В здании ВЦ краны устанавливают в коридорах, на площадках лестничных клеток, у входа, т.е. в доступных и защитных местах. На каждые 100 квадратных метра пола производственных помещений обычно требуется 1-2 огнетушителя (табл. 6.4.). Время действия пенных огнетушителей 50-70с, длина струи 6-8м, кратность пены 5, стойкость 40 мин. Углекислые огнетушители наполнены сжиженным углекислым газом, находящемся под давлением 6МПа. Для приведения их в действие достаточно открыть вентиль. Углекислый газ выходит в виде снега и сразу превращается в газ. Таблица 6.4 Примерные нормы первичных средств пожаротушения на действующих промышленных предприятиях и складах
Порошковые огнетушители применяются для тушения горящих щелочных металлов. Выброс порошкового заряда из баллона производится с помощью сжатого воздуха, подаваемого из баллончика. Стационарные пожаротушительные установки представляют собой неподвижно смонтированные аппараты, трубопроводы и оборудование, которые предназначаются для подачи огнегасительных средств к местам загорания. 7. ЭКОНОМИЧЕСКИЙ РАЗДЕЛ При расчете экономической эффективности разработки программного обеспечения “Универсальной обучающе-контролирующей системы” необходимо сопоставить затраты на решение задачи при ручном методе ее решения с затратами, связанными с ее автоматизацией. Определение годового экономического эффекта от сокращения ручного труда при обработке информации производится в описанной ниже последовательности. Годовые эксплуатационные расходы при ручной обработке информации определяются по формуле
гдеТр трудоемкость разового решения задачи вручную, чел-ч. (Тр = 3.5), к — периодичность решения задачи в течение года (к = 200), tчр среднечасовая ставка работника, осуществляющего ручной расчет задачи, руб., q — коэффициент, учитывающий процент премий (q = 0.4), а — коэффициент, учитывающий дополнительную заработную плату (а = 0.15), b — коэффициент, учитывающий начисления на заработную плату, включая отчисления в фонд социальной защиты населения — 35%, детских учреждений — 5% и чрезвычайный чернобыльский налог — 12% (b = 0.52). Трудоемкость разового решения задачи вручную определяется по нормам времени на разработку конструкторской или технологической документации [19]. Среднечасовая ставка работника определяется исходя из Единой тарифной системы оплаты труда в Республике Беларусь по следующей формуле
гдеО1 среднемесячная заработная плата работника 1 разряда (по состоянию на 01.04.97 170000 руб.), kт — тарифный коэффициент работника соответствующего разряда (kт = 4.06), 167 — нормативное количество рабочих часов в месяце. Разряд работника, выполняющего ручной расчет задачи, и соответствующий ему тарифный коэффициент выбирается из табл.7.1. Таблица 7.1 Тарифные коэффициенты специалистов с высшим образованием
Годовые текущие затраты, связанные с эксплуатацией задачи, определяются по формуле
гдеЗп затраты на заработную плату пользователя программы, За — затраты на оплату аренды ЭВМ при решении задачи. Затраты на заработную плату пользователя программы определяются по формуле
гдеТз — время решения задачи на ЭВМ, час., tчп среднечасовая ставка пользователя программы, руб. (определяется аналогично ставке работника, осуществляющего ручной расчет, кт = 3.69). Время решения задачи на ЭВМ определяется по формуле
гдеТвв — время ввода в ЭВМ исходных данных, необходимых для решения задачи, мин., Тр — время вычислений, мин.( Тр = 0.1), Твыв — время вывода результатов решения задачи (включая время распечатки на принтере и графопостроителе), мин. (Твыв = 4), dпз коэффициент, учитывающий подготовительно-заключительное время (dпз = 0.20). Время ввода в ЭВМ исходных данных может быть определено по формуле
гдеКz среднее количество знаков, набираемых с клавиатуры при вводе исходных данных (Кz = 250), Hz — норматив набора 100 знаков, мин. (Hz = 2). Время вычислений и время вывода информации может быть определено экспериментальным путем при отладке контрольного примера.
Затраты на оплату аренды ЭВМ для решения задачи определяются по следующей формуле
гдеSмч стоимость одного машино-часа работы ЭВМ, руб. Стоимость машино-часа работы ЭВМ определяется по формуле
гдеСэ расходы на электроэнергию за час работы ЭВМ, руб., Аэвм — годовая величина амортизационных отчислений на реновацию ЭВМ, руб., Рэвм — годовые затраты на ремонт и техническое обслуживание ЭВМ, руб., Апл — годовая величина амортизационных отчислений на реновацию производственных площадей, занимаемых ЭВМ, руб., Рпл — годовые затраты на ремонт и содержание производственных площадей, руб., Нн — годовая величина налога на недвижимость, руб., Фэвм — годовой фонд времени работы ЭВМ, час. Расходы на электроэнергию за час работы ЭВМ определяются по формуле
гдеNэ установленная мощность электродвигателя ЭВМ, кВт (Nэ = 0.2), kис коэффициент использования энергоустановок по мощности (kис = 0.9), Цэ — стоимость 1 кВт-часа электроэнергии, руб. (Цэ = 690), Чэл среднечасовое потребление электроэнергии ЭВМ, кВт.
Годовая величина амортизационных отчислений на реновацию ЭВМ определяется по формуле
гдеЦэвм — цена ЭВМ на момент ее выпуска, руб. (Цэвм = 17500000), kу коэффициент удорожания ЭВМ (зависит от года выпуска). В том случае, когда в качестве цены используется цена 1997г., коэффициент удорожания kу = 1, kм коэффициент, учитывающий затраты на монтаж и транспортировку ЭВМ (kм = 1.1), Наэвм — норма амортизационных отчислений на ЭВМ, % (Наэвм = 10), Цбэвм балансовая стоимость ЭВМ, руб.
Годовые затраты на ремонт и техническое обслуживание ЭВМ укрупненно могут быть определены по формуле
гдеkро коэффициент, учитывающий затраты на ремонт и техническое обслуживание ЭВМ, в том числе затраты на запчасти, зарплату ремонтного персонала и др. (kро = 0.1).
Годовая величина амортизационных отчислений на реновацию производственных площадей, занятых ЭВМ определяется по формуле
гдеЦбпл балансовая стоимость площадей, руб., Напл — норма амортизационных отчислений на производственные площади, % (Напл = 1.2 ), Sэвм площадь, занимаемая ЭВМ, кв. м. (Sэвм = 1 кв. м.), kд коэффициент, учитывающий дополнительную площадь (kд = 3), Цпл — цена 1 квадратного метра площади, руб. (Цпл = 4363837.5).
Годовые затраты на ремонт и содержание производственных площадей укрупненно могут быть определены по формуле
гдеkрэ коэффициент, учитывающий затраты на ремонт и эксплуатацию производственных площадей (kрэ = 0.05).
Величина налога на недвижимость определяется по формуле
гдеСнн ставка налога на недвижимость (Снн = 0.01).
Годовой фонд времени работы ЭВМ определяется исходя из режима ее работы и может быть рассчитан по формуле
гдеtсс среднесуточная фактическая загрузка ЭВМ, час. (tсс = 8), Тсг — среднее количество дней работы ЭВМ в год (Тсг = 250).
Прирост условной прибыли в результате внедрения задачи определяется по формуле
гдеСнп ставка налога на прибыль (Снп = 0.3).
Для определения годового экономического эффекта от разработанной программы необходимо определить суммарные капитальные затраты на разработку и внедрение программы по формуле
гдеКз капитальные и приравненные к ним затраты, руб., Цпр отпускная цена программы, руб., Капитальные и приравненные к ним затраты определяются по формуле
гдеХ — количество лет выработки ЭВМ, лет.
Отпускная цена программы определяется по формуле
гдеЦо оптовая цена программы, руб., Зрз — затраты на заработную плату разработчиков программы, руб., Пр — размер плановой прибыли на программу, руб., Ндоб — ставка налога на добавленную стоимость (Ндоб = 0.20). Затраты на заработную плату разработчиков программы определяются по формуле
гдеТрз трудоемкость разработки программы, час., tчрз среднечасовая ставка работника, осуществляющего разработку программы, руб. Трудоемкость разработки программы включает время на постановку задачи и время на программирование задачи и определяется по формуле
гдеnэ — количество этапов разработки программы, Тпосi трудоемкость постановки задачи на i-м этапе разработки программы, дней, Тпргi трудоемкость программирования задачи на i-м этапе разработки программы, дней. Разработка пакета программ, представленного в настоящем проекте, включала в себя 4 этапа: 1. Проектирование структур баз данных (Тпос = 1, Тпрг = 3); 2. Разработка программы создания и модификации тестов (Тпос = 0.4, Тпрг = 18); 3. Разработка программы контроля знаний (Тпос = 0.3, Тпрг = 15); 4. Разработка программы администрирования (Тпос = 0.3, Тпрг = 11);
Нормы времени учитывают ряд факторов, наибольшим образом влияющих на трудоемкость разработки проекта: · количество разновидностей форм входной информации; · количество разновидностей форм выходной информации; · степень новизны задачи; · сложность алгоритма; · вид используемой информации; · сложность контроля входной и выходной информации; · язык программирования; · объем входной информации; · использование типовых решений, типовых проектов и программ, · стандартных модулей. Предусмотрено четыре степени новизны разрабатываемых задач: · А — разработка задач, предусматривающая применение принципиально новых методов разработки, проведение научно-исследовательских работ; · Б — разработка типовых проектных решений, оригинальных задач и систем, не имеющих аналогов; · В — разработка проекта с использованием типовых проектных решений при условии их изменения, разработка проектов, имеющих аналогичные решения; · Г — привязка типовых проектных решений. Сложность алгоритма представлена тремя группами: · 1 — алгоритмы оптимизации и моделирования систем и объектов; · 2 — алгоритмы учета, отчетности, статистики и поиска; · 3 — алгоритмы, реализующие стандартные методы решения, а также не предусматривающие применения сложных численных и логических методов. Пакет программ, представленный в настоящем проекте, относится к степени В новизны разрабатываемой задачи. Сложность алгоритма решаемой задачи — 3. Плановая прибыль на программу определяется по формуле
гдеСпр себестоимость программы, руб., Нп — норма прибыли проектной организации (Нп = 0.25). Себестоимость программы определяется по формуле
гдеF — коэффициент накладных расходов проектной организации без учета эксплуатации ЭВМ (F = 1.15), Зот — затраты на отладку программы. Затраты на отладку программы определяются по формуле
гдеТотл трудоемкость отладки программы, час. (Тотл = 32).
Оптовая цена программы определяется по формуле
Ожидаемый годовой экономический эффект от сокращения ручного труда при обработке информации определяется по формуле
гдеЕ — коэффициент эффективности, равный ставке за кредиты на рынке долгосрочных кредитов (Е = 0.25).
Срок возврата инвестиций определяется по формуле
Результаты расчета сведены в табл. 7.2. Таблица 7.2 Технико‑экономические показатели проекта
Разработанная «Обучающе-контролирующая система» обеспечивает получение годового экономического эффекта в сумме 2.952 млн. рублей. Прирост условной прибыли составляет 4.658 млн. рублей. При отпускной цене программы в 6.647 млн. рублей проект обеспечивает возврат инвестиций за 1.46 года. ЗАКЛЮЧЕНИЕ В результате дипломного проектирования разработана универсальная обучающе-контролирующая система, состоящая из следующих функциональных частей: 1) программа для создания и модификации тестов; 2) сервисная программа администрирования; 3) программа контроля знаний. Разработанная универсальная обучающе-контролирующая система обладает следующими возможностями: · создание на основе имеющихся баз знаний тестов по различным предметам; · модификация созданных тестов; · формирование билетов; · задание времени ответа на вопросы билета; · задание системы оценки результатов тестирования; · контроль знаний обучаемых посредством тестирования; · возможность работы системы в ЛВС; · просмотр и распечатка результатов (протокола) тестирования на принтере и может быть использована в учебном процессе преподавателями вузов, техникумов и средних школ. Перспективным направлением дальнейших разработок по проблематике обучающе-контролирующих систем может служить применение в таких системах OLE и мультимедиа технологий. Все задачи, поставленные при постановке задания, выполнены. Проведенный расчет говорит о экономической целесообразности разработки системы и возможности использования ее в учебном процессе. Приложение 1 ТЕКСТ ПРОГРАММЫ TESTBUILDER program TestBuilder; uses Forms, S2 in 'S2.PAS' {TreeForm}, db_unit in 'db_unit.pas' {EditForm}, addtema in 'addtema.pas' {WinEditTema}, progrInd in 'progrInd.pas' {ProcessForm}; {$R *.RES} begin Application.Title:= 'TestBuilder'; Application.CreateForm(TTreeForm, TreeForm); Application.CreateForm(TEditForm, EditForm); Application.CreateForm(TWinEditTema, WinEditTema); Application.CreateForm(TProcessForm, ProcessForm); Application.Run; end. Текст модуля DB_Unit unit S2; interface uses SysUtils, WinTypes,{ Windows,} Messages, Classes, Graphics, Controls, Forms, Dialogs, Buttons, StdCtrls, Grids, Outline, ComCtrls, DBCtrls, DBTables, DB; type TTreeForm = class(TForm) MainTree: TOutline; AddDocBut: TSpeedButton; DeleteBut: TSpeedButton; FullExpBut: TSpeedButton; FullColBut: TSpeedButton; ExitBut: TSpeedButton; AddTemaBut: TSpeedButton; TemaSource: TDataSource; QuestSource: TDataSource; DBTema: TTable; DBTemaTema_id: TAutoIncField; DBTemaTema_name: TStringField; DBQuest: TTable; DBQuestTema_id: TIntegerField; DBQuestQuest_id: TAutoIncField; DBQuestQuest_name: TMemoField; procedure AddDocButClick(Sender: TObject); procedure MainTreeClick(Sender: TObject); procedure DeleteButClick(Sender: TObject); procedure FullExpButClick(Sender: TObject); procedure FullColButClick(Sender: TObject); procedure ExitButClick(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure AddTemaButClick(Sender: TObject); procedure FormShow(Sender: TObject); procedure FormResize(Sender: TObject); procedure FormCreate(Sender: TObject); procedure AppendQuestion(temaId: longint); procedure ClearQuestion; private { Private declarations } x1,x2: integer; {вспомогательные переменные} CreateMainForm: boolean; public { Public declarations } end; var TreeForm: TTreeForm; implementation uses db_unit, addtema, progrInd; {$R *.DFM} procedure TTreeForm.AddDocButClick(Sender: TObject); var Nodename: string; number,ind,docindex: longint; begin If MainTree.Items[MainTree.SelectedItem].Level = 1 then Exit; If MainTree.Items[MainTree.SelectedItem].Level = 2 then {в NUMBER заносится номер темы } begin number:= longint(MainTree.Items[MainTree.SelectedItem].Data);{в NUMBER заносится номер темы} ind:= MainTree.SelectedItem; end else begin number:= longint(MainTree[MainTree.SelectedItem].Parent.Data); ind:= MainTree[MainTree.SelectedItem].Parent.Index; end; AppendQuestion(number); {добавление нового вопроса в БД вопросов} With MainTree.Items[ind] do If HasItems then number:= GetLastChild - GetFirstChild + 2 {определение числа потомков + 2} else number:= 1; Str(number,Nodename); {номер вопроса в теме} If MainTree.Items[MainTree.SelectedItem].Level = 2 then begin docIndex:= MainTree.AddChildObject(MainTree.SelectedItem,NodeName, pointer(DBQuest.Fields[1].AsInteger)); MainTree.Items[MainTree.SelectedItem].Expand; end else {if... = 3} docIndex:= MainTree.AddObject(MainTree.SelectedItem,NodeName, pointer(DBQuest.Fields[1].AsInteger)); MainTree.Selecteditem:= docIndex; {установление фокуса на new вопрос} end; procedure TTreeForm.MainTreeClick(Sender: TObject); Var cur_id: longint; NewAnswer: TAnswer; del_count,i: integer; begin if MainTree.Items[MainTree.SelectedItem].Level = 1 then begin EditForm.QuestLabel.Hide; EditForm.DBEditTema.Hide; EditForm.MemoQuest.Hide; EditForm.MemoScroll.Enabled:= False; EditForm.AddAnswerBut.Enabled:= False; EditForm.DelAnswerBut.Enabled:= False; Exit; end; cur_id:= Longint(MainTree.Items[MainTree.SelectedItem].Data); EditForm.QuestLabel.Show; if MainTree.Items[MainTree.SelectedItem].Level = 3 then begin With TreeForm.DBQuest do begin {установка фильтра на БД вопросов } SetKey; Fields[1].AsInteger:= cur_id; GotoKey; end; EditForm.DBEditTema.Hide; EditForm.QuestLabel.Caption:= 'Текст вопроса'; EditForm.MemoQuest.Show; EditForm.MemoScroll.Enabled:= True; EditForm.AddAnswerBut.Enabled:= True; EditForm.DelAnswerBut.Enabled:= True; i:= 0; {индекс ДЛЯ ОБЪЕКТА TMemo в списке} EditForm.DBAnswer.First; {чтобы не было глюков при повторном щелчке на вопросе} while NOT EditForm.DBAnswer.Eof do begin If (i+1) > EditForm.MemoScroll.ComponentCount then NewAnswer:= TAnswer.Create(EditForm.MemoScroll,100); {добавление new варианта ответа в список} TMemo(EditForm.MemoScroll.Components[i]).Text:= EditForm.DBAnswer.Fields[2].AsString; {Otvet_name} TCheckBox(EditForm.MemoScroll.Components[i+1]).Checked:= EditForm.DBAnswer.Fields[3].AsBoolean; {Otvet_name} inc(i,2); // <--- увеличение индекса ДЛЯ ОБЪЕКТА TMemo в списке EditForm.DBAnswer.Next; end; While i< EditForm.MemoScroll.ComponentCount do {удаление из списка лишних вариантов ответа} TAnswer.DeleteAnswer(EditForm.MemoScroll,EditForm.MemoScroll.ComponentCount - 2); If EditForm.MemoScroll.ComponentCount > 0 then TMemo(EditForm.MemoScroll.Components[0]).SetFocus; {Set focus on first answer.} end else {if level = 2, т.е. выбрана тема} begin With TreeForm.DBTema do begin {установка фильтра на БД тем } SetKey; Fields[0].AsInteger:= cur_id; GotoKey; end; EditForm.AddAnswerBut.Enabled:= False; EditForm.DelAnswerBut.Enabled:= False; EditForm.MemoScroll.Enabled:= False; EditForm.MemoQuest.Hide; EditForm.QuestLabel.Caption:= 'Название темы'; EditForm.DBEditTema.Show; end; end; procedure TTreeForm.DeleteButClick(Sender: TObject); begin If Maintree.SelectedItem = 1 then Exit; If MainTree.Items[MainTree.SelectedItem].Level = 3 then begin If Application.MessageBox('Удалить вопрос ?','Удаление вопроса', mb_YesNo+mb_IconQuestion+MB_DEFBUTTON2) = IdYes then begin ClearQuestion; // логическое удаление вопроса из БД MainTree.Delete(MainTree.SelectedItem); {удаление текущего узла дерева} end; end else If Application.MessageBox('Удалить раздел ?','Удаление раздела', mb_YesNo+mb_IconQuestion+MB_DEFBUTTON2) = IdYes then begin DBQuest.IndexName:= 'tema_ind'; DBQuest.SetKey; DBQuest.Fields[0].AsInteger:= DBTema.Fields[0].AsInteger; // Fields[0] - Tema_Id While DBQuest.GotoKey do ClearQuestion; // логическое удаление всех вопросов, принадлежащих теме DBQuest.IndexName:= ''; DBTema.Delete; { Удаление выбранной темы } { DBTema.Edit; DBTema.Fields[1].Clear; DBTema.Post; // logical delete } MainTree.Delete(MainTree.SelectedItem); {удаление текущего узла дерева} end; end; procedure TTreeForm.FullExpButClick(Sender: TObject); begin MainTree.FullExpand; end; procedure TTreeForm.FullColButClick(Sender: TObject); begin MainTree.FullCollapse; end; procedure TTreeForm.ExitButClick(Sender: TObject); begin TreeForm.Close; end; procedure TTreeForm.FormClose(Sender: TObject; var Action: TCloseAction); begin Action:= caFree; EditForm.DBAnswer.Active:= False; DBQuest.Active:= False; DBTema.Active:= False; end; procedure TTreeForm.AddTemaButClick(Sender: TObject); var index: Longint; FoundEmpty: boolean; begin WinEditTema.ShowModal; If WinEditTema.ModalResult = mrOk then begin FoundEmpty:= False; DBTema.First; While (not DBTema.EOF) and (not FoundEmpty) do {поиск записи в DBTEMA с пустым полем Tema_name} begin If DBTema.Fields[1].IsNull Then FoundEmpty:= True else DBTema.Next; end; If FoundEmpty then DBTema.Edit else DBTema.Append; {добавление новой темы в БД, если не найдено пустой} DBTema['Tema_name']:= WinEditTema.TemaEdit.Text; DBTema.Post; AppendQuestion(DBTema.Fields[0].AsInteger); {добавление нового вопроса в БД } index:= MainTree.AddChildObject(1, DBTema.Fields[1].AsString, pointer(DBTema.Fields[0].AsInteger)); {добавление new темы} MainTree.AddChildObject(index,'1', pointer(DBQuest.Fields[1].AsInteger)); {добавление пустого вопроса в тему} If not MainTree.Items[1].Expanded then MainTree.Items[1].Expand; {раскрытие корневого узла} MainTree.Items[index].Expand; {раскрытие узла темы} MainTree.Selecteditem:= index; {установление фокуса на new тему} end; end; procedure TTreeForm.FormShow(Sender: TObject); Var cur_node,i: Longint; node_name: string; begin if CreateMainForm then begin ProcessForm.Show; DBTema.Active:= True; {Открытие БД тем и вопросов} DBQuest.Active:= True; ProcessForm.ProgressBar.Max:= DBTema.RecordCount + DBQuest.RecordCount; While not DBTema.EOF do begin {загрузка дерева из БД} ProcessForm.ProgressBar.StepIt; If not DBTema.Fields[1].IsNull then begin cur_node:= MainTree.AddChildObject(1, DBTema.Fields[1].AsString, pointer(DBTema.FieldByName('Tema_id').AsInteger)); {добавление темы в дерево} i:= 1; While not DBQuest.EOF do begin ProcessForm.ProgressBar.StepIt; Str(i,node_name); MainTree.AddChildObject(cur_node,node_name, pointer(DBQuest.Fields[1].AsInteger));{добавление вопроса в тек.тему} DBQuest.Next; inc(i); end; end; DBTema.Next; end; {while} DBQuest.IndexName:= ''; {отключение связи между DBTema и DBQuest} DBQuest.MasterFields:= ''; ProcessForm.Close; CreateMainForm:= False; end; EditForm.Show; end; procedure TTreeForm.FormResize(Sender: TObject); begin if TreeForm.Height >= 300 then MainTree.Height:= TreeForm.ClientHeight - Maintree.Top - x1 else TreeForm.Height:= 300; IF TreeForm.Width >= 263 then MainTree.Width:= TreeForm.ClientWidth - MainTree.Left - x2 else TreeForm.Width:= 263; end; procedure TTreeForm.FormCreate(Sender: TObject); begin CreateMainForm:= True; x1:= ClientHeight - MainTree.Top - MainTree.Height; x2:= ClientWidth - MainTree.Left - Maintree.Width; TreeForm.Height:= GetSystemMetrics(SM_CYMAXIMIZED) - 10; end; procedure TTreeForm.AppendQuestion(temaId: longint); { Добавляет в таблицу DBQuest новый вопрос. temaId - содержит значение темы, которой принадлежит вопрос } begin DBQuest.IndexName:= 'tema_ind'; {подключение вторичного индекса} DBQuest.SetKey; {поиск записи с 0-ым значением DBQuest.Tema_id} DBQuest.Fields[0].AsInteger:= 0; If DBQuest.GotoKey then {если найдена запись, то редактируем ее поля} begin DBQuest.IndexName:= ''; {отключение вторичного индекса} DBQuest.Edit; end else {если не найдена такая запись, то добавляем новую} begin DBQuest.IndexName:= ''; {отключение вторичного индекса} DBQuest.Append; end; DBQuest['Tema_id']:= TemaId; DBQuest.Post; end; procedure TTreeForm.ClearQuestion; {осуществляет логическое удаление текущего вопроса из БД} begin {обнуление параметра Quest_id во всех связанных записях БД answer.db} EditForm.DBAnswer.First; While not EditForm.DBAnswer.Eof do EditForm.ClearAnswer; {обнуление tema_id текущего вопроса} DBQuest.Edit; DBQuest.Fields[0].AsInteger:= 0; // DBQUEST.Tema_id DBQuest.Fields[2].AsString:= ''; // DBQUEST.QUest_name DBQuest.Post; end; end. Текст модуля DB_Unit unit db_unit; interface uses SysUtils, Windows, Messages, Classes, Graphics, Controls, StdCtrls, Forms, Mask, Buttons, DBTables, DB, DBCtrls; type TEditForm = class(TForm) MemoQuest: TDBMemo; QuestName: TLabel; QuestLabel: TLabel; DBEditTema: TDBEdit; MemoScroll: TScrollBox; AddAnswerBut: TSpeedButton; DelAnswerBut: TSpeedButton; DBAnswer: TTable; AnswerSource: TDataSource; DBAnswerOtvet_id: TAutoIncField; DBAnswerQuest_id: TIntegerField; DBAnswerOtvet_name: TMemoField; DBAnswerTrued: TBooleanField; procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure DBEditTemaChange(Sender: TObject); procedure AddAnswerButClick(Sender: TObject); procedure DelAnswerButClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure AppendAnswer(QuestId: longint); procedure ClearAnswer; procedure FormResize(Sender: TObject); procedure MemoScrollResize(Sender: TObject); private x1,x2: integer; {вспомогательные переменные} public end; TAnswer = Class(TObject) memo: TMemo; check: TCheckBox; constructor Create(AOwner:TComponent;Height_: Integer); procedure Free; procedure CheckClick(Sender: TObject); procedure MemoChange(Sender: TObject); class procedure DeleteAnswer(AOwner: TComponent;Number: integer); private nocreate: boolean; {TRUE - if don't run the CREATE-constructor} end; var EditForm: TEditForm; implementation uses S2; {$R *.DFM} procedure TEditForm.AppendAnswer(QuestId: longint); { Добавляет в таблицу DBQuest новый вопрос. temaId - содержит значение темы, которой принадлежит вопрос } Var i: integer; Isinsert: boolean; NewAnswer: TAnswer; begin IsInsert:= false; {True if NOT APPEND new record into database} DBAnswer.MasterFields:= ''; DBAnswer.SetKey; {поиск записи с 0-ым значением DBAnswer.Tema_id} DBAnswer.Fields[1].AsInteger:= 0; If DBAnswer.GotoKey then begin DBAnswer.Edit; IsInsert:= True; end else DBAnswer.Append;{если не найдена запись, то добавляем новую} DBAnswer.Fields[1].AsInteger:= QuestId; DBAnswer.Post; DBAnswer.MasterFields:= 'Quest_id'; NewAnswer:= TAnswer.Create(MemoScroll,100); {добавление new варианта ответа в список} If IsInsert then begin DBAnswer.First; i:=0; While i < MemoScroll.ComponentCount do begin DBAnswer.Edit; DBAnswerOtvet_name.Assign(Tmemo(MemoScroll.Components[i]).Lines); DBAnswer.Fields[3].AsBoolean:= TCheckBox(MemoScroll.Components[i+1]).Checked; DBAnswer.Post; DBAnswer.Next; inc(i,2); end; end; {endif} end; procedure TEditForm.ClearAnswer; {логическое удаление из БД текущего варианта ответа для текущнго вопроса} begin DBAnswer.Edit; DBAnswer['Quest_id']:= 0; DBAnswer.Fields[2].Clear; { Otvet_name } DBAnswer['Trued']:= False; DBAnswer.Post; end; constructor TAnswer.Create(AOwner:TComponent;Height_: Integer); begin NoCreate:= False; memo:= TMemo.Create(Aowner); memo.Parent:= TWinControl(AOwner); With memo do begin If ComponentIndex = 0 then begin Left:= 0; Top:= 0; end else begin Left:= 0; Top:= TMemo(AOwner.Components[ComponentIndex-2]).Top + TMemo(AOwner.Components[ComponentIndex-2]).Height; end; Width:= TScrollBox(AOwner).Width - 60; Height:= Height_; If (ComponentIndex div 2 + 1)*Height > TScrollBox(AOwner).VertScrollBar.Range then TScrollBox(AOwner).VertScrollBar.Range:= (ComponentIndex div 2 + 1)*Height; OnChange:= MemoChange; SetFocus; end; {end Init Memo} check:= TCheckBox.Create(AOwner); check.Parent:= TWinControl(AOwner); With check do begin Left:= Memo.Left + Memo.Width + 15; Top:= Memo.Top + Memo.Height div 2; Height:= 17; Width:= 17; OnClick:= CheckClick; end; NoCreate:= True; end; procedure TAnswer.Free; begin check.Free; memo.Free; end; procedure TAnswer.CheckClick(Sender: TObject); begin If nocreate then begin EditForm.DBAnswer.First; EditForm.DBAnswer.MoveBy((Check.Componentindex-1) div 2); EditForm.DBAnswer.Edit; EditForm.DBAnswer['Trued']:= check.checked; EditForm.DBAnswer.Post; end; end; procedure TAnswer.MemoChange(Sender: TObject); begin If memo.Modified then begin EditForm.DBAnswer.First; EditForm.DBAnswer.MoveBy(Memo.Componentindex div 2); EditForm.DBAnswer.Edit; EditForm.DBAnswerOtvet_name.Assign(Memo.Lines); EditForm.DBAnswer.Post; end; end; class procedure TAnswer.DeleteAnswer(AOwner: TComponent;Number: integer); Var i: integer; {удаленние из списка объекта NUMBER и NUMBER+1} begin TCheckBox(AOwner.Components[number+1]).Free; TMemo(AOwner.Components[number]).Free; For i:= Number to AOwner.ComponentCount-1 do {перерисовка компонентов в ScrollBox} If AOwner.Components[i] is TMemo then TMemo(AOwner.Components[i]).Top:= TMemo(AOwner.Components[i]).Top - TMemo(AOwner.Components[i]).Height else TCheckBox(AOwner.Components[i]).Top:= TCheckBox(AOwner.Components[i]).Top - TMemo(AOwner.Components[i-1]).Height; If AOwner.ComponentCount > 0 then TScrollBox(AOwner).VertScrollBar.Range:= (AOwner.ComponentCount div 2)* TMemo(AOwner.Components[0]).Height; end; procedure TEditForm.FormClose(Sender: TObject; var Action: TCloseAction); begin TreeForm.Close; {закрыть окно, содержащее дерево} end; procedure TEditForm.DBEditTemaChange(Sender: TObject); begin If DBEditTema.Modified Then begin TreeForm.DBTema.Post; TreeForm.MainTree.Items[TreeForm.MainTree.SelectedItem].Text:= TreeForm.DBTema.Fields[1].AsString; {модификация названия узла дерева, содержащего тему} end; end; procedure TEditForm.AddAnswerButClick(Sender: TObject); begin AppendAnswer(TreeForm.DBQuest.Fields[1].AsInteger); end; procedure TEditForm.DelAnswerButClick(Sender: TObject); var CurAnswer,i: integer; begin {удаленние из списка CURRENT ANSWER, если на нем стоит курсор} i:= 0; CurAnswer:= -1; While i < MemoScroll.ComponentCount do begin If TMemo(MemoScroll.Components[i]).Focused then CurAnswer:= TMemo(MemoScroll.Components[i]).ComponentIndex; inc(i,2); end; if CurAnswer > -1 then begin EditForm.DBAnswer.First; EditForm.DBAnswer.MoveBy(CurAnswer div 2); ClearAnswer; TAnswer.DeleteAnswer(MemoScroll,CurAnswer); end; end; procedure TEditForm.FormCreate(Sender: TObject); begin EditForm.DBAnswer.Active:= True; {Открытие БД ответов} x1:= ClientHeight - MemoScroll.Top - MemoScroll.Height; x2:= ClientWidth - MemoScroll.Left - MemoScroll.Width; EditForm.Height:= GetSystemMetrics(SM_CYMAXIMIZED) - 10; end; procedure TEditForm.FormResize(Sender: TObject); begin if EditForm.Height >= 300 then MemoScroll.Height:= EditForm.ClientHeight - MemoScroll.Top - x1 else EditForm.Height:= 300; IF EditForm.Width >= 300 then begin MemoScroll.Width:= EditForm.ClientWidth - MemoScroll.Left - x2; MemoQuest.Width:= EditForm.ClientWidth - MemoQuest.Left - x2; DBEditTema.Width:= EditForm.ClientWidth - DBEditTema.Left - x2; end else EditForm.Width:= 300; end; procedure TEditForm.MemoScrollResize(Sender: TObject); var i: integer; begin i:= 0; While i < (MemoScroll.ComponentCount-1) do begin TMemo(MemoScroll.Components[i]).Width:= MemoScroll.Width - 60; TCheckBox(MemoScroll.Components[i+1]).Left:= TMemo(MemoScroll.Components[i]).Left + TMemo(MemoScroll.Components[i]).Width + 15; inc(i,2); end; end; end. Текст модуля AddTema unit addtema; interface uses Windows, SysUtils, Classes, Graphics, Forms, Controls, StdCtrls, Buttons, ExtCtrls; type TWinEditTema = class(TForm) TemaEdit: TEdit; TemaNameLabel: TLabel; OkBtn: TBitBtn; CancelBtn: TBitBtn; procedure butCancelClick(Sender: TObject); procedure butOkClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var WinEditTema: TWinEditTema; implementation {$R *.DFM} procedure TWinEditTema.butCancelClick(Sender: TObject); begin Modalresult:= mrCancel; end; procedure TWinEditTema.butOkClick(Sender: TObject); begin Modalresult:= mrOk; end; end. Текст модуля ProgrInd unit progrInd; interface uses Windows, SysUtils, Classes, Graphics, Forms, Controls, StdCtrls, Buttons, ExtCtrls, ComCtrls; type TProcessForm = class(TForm) Bevel1: TBevel; ProgressBar: TProgressBar; private { Private declarations } public { Public declarations } end; var ProcessForm: TProcessForm; implementation {$R *.DFM} end. Приложение 2 ТЕКСТ ПРОГРАММЫ TESTADMIN program TestAdmin; uses Forms, main in 'main.pas' {AdminForm}, TQDialog in 'TQDialog.pas' {CreateTickDlg}, ResultReport in 'ResultReport.pas' {ReportForm}; {$R *.RES} begin Application.Title:= 'TestAdmin'; Application.CreateForm(TAdminForm, AdminForm); Application.CreateForm(TCreateTickDlg, CreateTickDlg); Application.CreateForm(TReportForm, ReportForm); Application.Run; end. Текст модуля Main unit main; interface uses Dialogs,IniFiles,SysUtils,Forms, DB, DBTables, Classes, Controls, Grids, DBGrids, StdCtrls, Spin, ExtCtrls,Windows, Buttons, ComCtrls; type TAdminForm = class(TForm) ControlSource: TDataSource; DBControl: TTable; DBControlId: TAutoIncField; DBControlName: TStringField; DBControlMark: TFloatField; DBControlDate: TDateField; DBControlTime: TTimeField; Journal: TDBGrid; DBControlTicket_num: TIntegerField; DBControlOcenka: TFloatField; Maxmark: TSpinEdit; TestTime: TSpinEdit; TimeLabel: TLabel; MarkLabel: TLabel; CreateTicketBtn: TBitBtn; Bevel1: TBevel; QuitBtn: TBitBtn; ClearBtn: TBitBtn; PrintBtn: TBitBtn; Bevel2: TBevel; Label1: TLabel; StatusBar: TStatusBar; procedure ShowHint(Sender: TObject); procedure DBControlCalcFields(DataSet: TDataSet); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure TestTimeChange(Sender: TObject); procedure MaxmarkChange(Sender: TObject); procedure CreateTicketBtnClick(Sender: TObject); procedure FormShow(Sender: TObject); procedure FormCreate(Sender: TObject); procedure QuitBtnClick(Sender: TObject); procedure CreateNewDBControl; procedure ClearBtnClick(Sender: TObject); procedure PrintBtnClick(Sender: TObject); private CreateForm: boolean; public IniFile: TIniFile; end; var AdminForm: TAdminForm; implementation uses TQDialog, PathDialog, ResultReport; {$R *.DFM} procedure TAdminForm.ShowHint(Sender: TObject); begin StatusBar.SimpleText:= Application.Hint; end; procedure TAdminForm.DBControlCalcFields(DataSet: TDataSet); begin DBControl.Fields[3].AsFloat:= DBControl.Fields[2].AsFloat * MaxMark.Value; // fields[2] - 'Mark' end; procedure TAdminForm.FormClose(Sender: TObject; var Action: TCloseAction); begin IniFile.Free; Action:= caFree; end; procedure TAdminForm.TestTimeChange(Sender: TObject); begin IniFile.WriteInteger('Options', 'TestTime', TestTime.Value * 60000); end; procedure TAdminForm.MaxmarkChange(Sender: TObject); begin IniFile.WriteInteger('Options', 'MaxMark',MaxMark.Value); end; procedure TAdminForm.CreateTicketBtnClick(Sender: TObject); begin CreateTickDlg.ShowModal; end; procedure TAdminForm.CreateNewDBControl; {создает новую таблицу DBControl. изменяет состояние DBControl.Active:= False} begin //--------- Create new local table CONTROL.DB -------------- with DBControl do begin Active:= False; DatabaseName:= 'Common_base'; TableName:= 'Control'; TableType:= ttParadox; with FieldDefs do begin Clear; Add('Id',ftAutoInc, 0, False); Add('Ticket_num', ftInteger, 0, False); Add('Name',ftString, 40, False); Add('Mark',ftFloat, 0, False); Add('Date',ftDate, 0, False); Add('Time',ftTime, 0, False); end; with IndexDefs do begin Clear; Add('Id', 'Id', [ixPrimary, ixUnique]); end; CreateTable; end; //--------- end of create ------------------------- end; procedure TAdminForm.FormShow(Sender: TObject); Var List: TStrings; AliasPath: string; begin If CreateForm then begin Session.ConfigMode:= cmAll; {Global and local aliases !!!} try List:= TStringList.Create; Session.GetAliasParams('Common_base',List); // may be occurs an error AliasPath:= List.Values['PATH']; List.Free; except end; IniFile:= TIniFile.Create(AliasPath+'\Test.INI'); TestTime.Value:= IniFile.ReadInteger('Options', 'TestTime', 600000{10 min})div 60000; MaxMark.Value:= IniFile.ReadInteger('Options', 'MaxMark', 5); // CreateTickDlg.MaxTicket.Value:= IniFile.ReadInteger('Options', 'MaxTicket', 1); try DBControl.Active:= True; except CreateNewDBControl; DBControl.Active:= True; end; CreateForm:= False; end; end; procedure TAdminForm.FormCreate(Sender: TObject); begin CreateForm:= True; Application.OnHint:= ShowHint; end; procedure TAdminForm.QuitBtnClick(Sender: TObject); begin Close; end; procedure TAdminForm.ClearBtnClick(Sender: TObject); begin CreateNewDBControl; DBControl.Active:= True; end; procedure TAdminForm.PrintBtnClick(Sender: TObject); begin ReportForm.QuickReport.Preview; end; end. Текст модуля TQDialog unit TQDialog; interface uses Windows, SysUtils, Classes, Graphics, Forms, Controls, StdCtrls, Buttons, ExtCtrls, Spin, DB, DBTables, Grids, DBGrids; type TCreateTickDlg = class(TForm) OKBtn: TBitBtn; CancelBtn: TBitBtn; Bevel1: TBevel; QuestCount: TSpinEdit; MaxTicket: TSpinEdit; TickLabel: TLabel; QuestLabel: TLabel; DBGrid1: TDBGrid; DBTicket: TTable; TicketSource: TDataSource; TemaSource: TDataSource; DBTema: TTable; DBQuest: TTable; QuestSource: TDataSource; procedure QuestCountEnter(Sender: TObject); procedure OKBtnClick(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormShow(Sender: TObject); private { Private declarations } public { Public declarations } end; var CreateTickDlg: TCreateTickDlg; implementation uses main; {$R *.DFM} procedure TCreateTickDlg.QuestCountEnter(Sender: TObject); begin QuestCount.MaxValue:= DBQuest.RecordCount; If QuestCount.MaxValue >1 then QuestCount.Increment:=1 else begin QuestCount.Value:= QuestCount.MaxValue; QuestCount.Increment:= 0; end; end; procedure TCreateTickDlg.OKBtnClick(Sender: TObject); Var List,List2: TList; i,j,n: longint; begin //--------- Create new empty table TICKETS.DB -------------- with DBTicket do begin Active:= False; DatabaseName:= 'Common_base'; TableName:= 'Tickets'; TableType:= ttParadox; IndexName:= 'many_ind'; with FieldDefs do begin Clear; Add('Ticket_id', ftAutoInc, 0, False); Add('Ticket_num', ftInteger, 0, False); Add('Quest_id', ftInteger, 0, False); end; with IndexDefs do begin Clear; Add('', 'Ticket_id', [ixPrimary, ixUnique]); Add('many_ind','Ticket_num;Quest_id',[ixCaseInsensitive]); end; CreateTable; end; //--------- end of create ------------------------- DBTicket.Active:= True; DBQuest.First; List:= TList.Create; List2:= TList.Create; for i:=1 to CreateTickDlg.QuestCount.Value do begin for j:=1 to CreateTickDlg.MaxTicket.Value do List.Add(pointer(j)); // fill list randomize; repeat n:= random(List.Count-1); DBTicket.SetKey; DBTicket['Ticket_num']:= longint(List.Items[n]); DBTicket['Quest_id']:= DBQuest['Quest_id']; If DBTicket.GotoKey then begin List2.Add(List.Items[n]); List.Delete(n); Continue; end else begin DBTicket.Append; DBTicket['Ticket_num']:= longint(List.Items[n]); DBTicket['Quest_id']:= DBQuest['Quest_id']; DBTicket.Post; DBQuest.Next; If DBQuest.EOF then DBQuest.First; List.Delete(n); //List.Pack; While (List2.count > 0) do begin List.Add(List2.Items[0]); List2.Delete(0); end; end; until List.Count = 0; end; DBTicket.IndexName:= ''; DBTicket.DeleteIndex('many_ind'); DBTicket.AddIndex('tick_ind','Ticket_num',[ixCaseInsensitive]); DBTicket.Active:= False; List.Free; List2.Free; AdminForm.IniFile.WriteInteger('Options', 'MaxTicket',MaxTicket.Value); Application.MessageBox('Формирование билетов завершено!','',MB_ICONINFORMATION); end; procedure TCreateTickDlg.FormClose(Sender: TObject; var Action: TCloseAction); begin DBQuest.Active:= False; DBTema.Active:= False; end; procedure TCreateTickDlg.FormShow(Sender: TObject); begin DBTema.Active:= True; DBQuest.Active:= True; end; end. Текст модуля ResultReport unit ResultReport; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Quickrep, StdCtrls, ExtCtrls; type TReportForm = class(TForm) QuickReport: TQuickReport; PageHeader: TQRBand; Detail: TQRBand; QRLabel1: TQRLabel; TicketField: TQRDBText; NameField: TQRDBText; OcenkaField: TQRDBText; DateField: TQRDBText; ColumnHeader: TQRBand; QRLabel2: TQRLabel; QRLabel3: TQRLabel; CurrentNum: TQRSysData; QRLabel4: TQRLabel; QRLabel5: TQRLabel; QRLabel6: TQRLabel; QRBand1: TQRBand; QRLabel7: TQRLabel; PageNum: TQRSysData; private { Private declarations } public { Public declarations } end; var ReportForm: TReportForm; implementation uses main; {$R *.DFM} end. Приложение 3 ТЕКСТ ПРОГРАММЫ TESTCLIENT program TestClient; uses Forms, Sdimain in 'SDIMAIN.PAS' {ClientForm}, DlgUnit in 'DlgUnit.pas' {BeginDataDlg}, PathDialog in '\$$$\ADMIN\PathDialog.pas' {PathDlg}; {$R *.RES} begin Application.Title:= 'TestClient'; Application.CreateForm(TClientForm, ClientForm); Application.CreateForm(TBeginDataDlg, BeginDataDlg); Application.Run; end. Текст модуля SdiMain unit Sdimain; interface uses Windows,DBTables, DB, ExtCtrls, StdCtrls, Forms, Classes, Controls, ComCtrls,SysUtils, Gauges, DBCtrls,Graphics; type TClientForm = class(TForm) QuestList: TListBox; Timer: TTimer; TicketSource: TDataSource; DBTicket: TTable; DBTicketTicket_id: TAutoIncField; DBTicketTicket_num: TIntegerField; DBTicketQuest_id: TIntegerField; AnswerSource: TDataSource; DBAnswer: TTable; DBAnswerOtvet_id: TAutoIncField; DBAnswerQuest_id: TIntegerField; DBAnswerOtvet_name: TMemoField; DBAnswerTrued: TBooleanField; ResultSource: TDataSource; DBResult: TTable; DBResultAnswer_id: TIntegerField; DBResultTrued: TBooleanField; MemoScroll: TScrollBox; PrevBut: TButton; NextBut: TButton; ExitBut: TButton; TestGauge: TGauge; ControlSource: TDataSource; DBControl: TTable; QuestName: TDBMemo; QuestSource: TDataSource; DBQuest: TTable; StatusBar: TStatusBar; procedure ShowHint(Sender: TObject); procedure QuestListClick(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormShow(Sender: TObject); procedure FormCreate(Sender: TObject); procedure ExitButClick(Sender: TObject); procedure PrevButClick(Sender: TObject); procedure NextButClick(Sender: TObject); procedure TimerTimer(Sender: TObject); procedure RefreshAnswers; procedure DeleteAnswer(AOwner: TComponent;Number: integer); procedure FormResize(Sender: TObject); procedure MemoScrollResize(Sender: TObject); private x1,x2: integer; public CreateMainForm: boolean; TestTime: LongInt; {время тестирования в миллисекундах } MaxMark: LongInt; {система оценки(балл)} ticket: longint; {Users ticket} StudentName: string[40]; end; TAnswer = Class(TObject) memo: TMemo; check: TCheckBox; constructor Create(AOwner:TComponent;Height_: Integer); procedure Free; procedure CheckClick(Sender: TObject); procedure MemoClick(Sender: TObject); private nocreate: boolean; {TRUE - if don't run the CREATE-constructor} end; var ClientForm: TClientForm; implementation uses DlgUnit, PathDialog; {$R *.DFM} {----------------------------------} procedure TClientForm.RefreshAnswers; {Изменяет размеры области вывода ответов,содержимое ответов,число ответов в зависимости от выбранного вопроса.} Var NewAnswer: TAnswer; i: integer; begin DBTicket.First; DBTicket.MoveBy(QuestList.ItemIndex); {Go to the selected Question} i:= 0; {индекс ДЛЯ ОБЪЕКТА TMemo в списке} DBAnswer.First; {чтобы не было глюков при повторном щелчке на вопросе} while NOT DBAnswer.Eof do begin If (i+1) > MemoScroll.ComponentCount then NewAnswer:= TAnswer.Create(MemoScroll,100); {добавление new варианта ответа в список} TMemo(MemoScroll.Components[i]).Text:= DBAnswer['Otvet_name']; {Otvet_name} TCheckBox(MemoScroll.Components[i+1]).Checked:= DBResult['Trued']; inc(i,2); // <--- увеличение индекса ДЛЯ ОБЪЕКТА TMemo в списке DBAnswer.Next; end; While i< MemoScroll.ComponentCount do {удаление из списка лишних вариантов ответа} DeleteAnswer(MemoScroll,MemoScroll.ComponentCount - 2); If MemoScroll.ComponentCount > 0 then begin TMemo(MemoScroll.Components[0]).SetFocus; {Set focus on first answer.} QuestList.SetFocus; {and tnen set focus on questions-list} end; ClientForm.MemoScrollResize(MemoScroll); {изменение размеров областей вывода ответов} end; {----------------------------------} constructor TAnswer.Create(AOwner:TComponent;Height_: Integer); begin NoCreate:= False; memo:= TMemo.Create(Aowner); with memo do begin Parent:= TWinControl(AOwner); ReadOnly:= True; TabStop:= False; Left:= 0; OnClick:= MemoClick; end; check:= TCheckBox.Create(AOwner); With check do begin Parent:= TWinControl(AOwner); Height:= 17; Width:= 17; TabStop:= False; OnClick:= CheckClick; end; NoCreate:= True; end; procedure TAnswer.Free; begin check.Free; memo.Free; end; procedure TAnswer.MemoClick(Sender: TObject); begin ClientForm.QuestList.SetFocus; end; procedure TAnswer.CheckClick(Sender: TObject); begin If nocreate then begin ClientForm.DBAnswer.First; {передвигаем указатель в DBAnswer и вместе с ним в DBResult} ClientForm.DBAnswer.MoveBy((Check.Componentindex-1) div 2); ClientForm.DBResult.Edit; ClientForm.DBResult['Trued']:= Check.Checked; ClientForm.DBResult.Post; ClientForm.QuestList.SetFocus; end; end; procedure TClientForm.DeleteAnswer(AOwner: TComponent;Number: integer); Var i: integer; {удаленние из списка объекта NUMBER и NUMBER+1} begin TCheckBox(AOwner.Components[number+1]).Free; TMemo(AOwner.Components[number]).Free; For i:= Number to AOwner.ComponentCount-1 do {перерисовка компонентов в ScrollBox} If AOwner.Components[i] is TMemo then TMemo(AOwner.Components[i]).Top:= TMemo(AOwner.Components[i]).Top - TMemo(AOwner.Components[i]).Height else TCheckBox(AOwner.Components[i]).Top:= TCheckBox(AOwner.Components[i]).Top - TMemo(AOwner.Components[i-1]).Height; If AOwner.ComponentCount > 0 then TScrollBox(AOwner).VertScrollBar.Range:= (AOwner.ComponentCount div 2)* TMemo(AOwner.Components[0]).Height; end; procedure TClientForm.ShowHint(Sender: TObject); begin StatusBar.SimpleText:= Application.Hint; end; procedure TClientForm.FormShow(Sender: TObject); begin If CreateMainForm then BeginDataDlg.ShowModal; end; procedure TClientForm.QuestListClick(Sender: TObject); begin RefreshAnswers; end; procedure TClientForm.FormClose(Sender: TObject; var Action: TCloseAction); Var Quest_cnt, {всего вопросов} MyAnswerTrued, {1 - если ответ правильный} TruedCnt: word; {количество правильных ответов} SumTrued: real; {относительная оценка} S: string; begin {действия по получению оценки и выводу ее на экран и в БД} If BeginDataDlg.ModalResult <> mrOk then Exit; quest_cnt:= 0; SumTrued:= 0; MyAnswerTrued:= 0; TruedCnt:= 0; DBTicket.First; while not DBTicket.EOF do begin inc(quest_cnt); DBAnswer.First; while not DBAnswer.EOF do begin If DBResult['Trued'] = DBAnswer['Trued'] then MyAnswerTrued:= 1 else begin MyAnswerTrued:= 0; {Ответ на вопрос неверен.} Break; {выход из цикла} end; DBAnswer.Next; end; DBTicket.Next; TruedCnt:= TruedCnt + MyAnswerTrued; end; SumTrued:= TruedCnt / quest_cnt; {средний бал 0..1} Str((SumTrued*ClientForm.MaxMark):5:2,S); Application.MessageBox(PChar('Правильных ответов: '+ IntToStr(TruedCnt)+' из '+IntToStr(Quest_cnt)+ #13+'Оценка: ' + s), 'Результат тестирования',MB_ICONINFORMATION); DBResult.Active:= False; {Close databases} DBAnswer.Active:= False; DBQuest.Active:= False; DBTicket.Active:= False; DBControl.Active:= True; {Save info of current user in CONTROL.DB} DBControl.Append; DBControl['Date']:= Date; DBControl['Time']:= Time; DBControl['Ticket_num']:= ticket; DBControl['Mark']:= SumTrued; DBControl['Name']:= StudentName; DBControl.Post; DBControl.Active:= False; end; procedure TClientForm.FormCreate(Sender: TObject); begin CreateMainForm:= True; x1:= ClientHeight - MemoScroll.Top - MemoScroll.Height; x2:= ClientWidth - MemoScroll.Left - MemoScroll.Width; ClientForm.Height:= GetSystemMetrics(SM_CYMAXIMIZED) - 10; end; procedure TClientForm.ExitButClick(Sender: TObject); begin Close; end; procedure TClientForm.PrevButClick(Sender: TObject); begin QuestList.ItemIndex:= QuestList.ItemIndex - 1; RefreshAnswers; end; procedure TClientForm.NextButClick(Sender: TObject); begin QuestList.ItemIndex:= QuestList.ItemIndex + 1; RefreshAnswers; end; procedure TClientForm.TimerTimer(Sender: TObject); begin TestGauge.AddProgress(Timer.Interval); TestTime:= TestTime - Timer.Interval; If TestGauge.PercentDone > 75 then TestGauge.BackColor:= clYellow; If TestTime = 0 then Close; {в OnClose д/б предусмотрен расчет оценки и запись ее в БД} end; procedure TClientForm.FormResize(Sender: TObject); begin if ClientForm.Height >= 400 then begin MemoScroll.Height:= ClientForm.ClientHeight - MemoScroll.Top - x1; QuestList.Height:= ClientForm.ClientHeight - QuestList.Top - x1; StatusBar.Top:= ClientForm.ClientHeight - StatusBar.Height; PrevBut.Top:= StatusBar.Top - PrevBut.Height - 6; {modify buttons place} NextBut.Top:= PrevBut.Top; ExitBut.Top:= NextBut.Top; end else ClientForm.Height:= 400; IF ClientForm.Width >= 440 then begin MemoScroll.Width:= ClientForm.ClientWidth - MemoScroll.Left - x2; QuestName.Width:= ClientForm.ClientWidth - QuestName.Left - x2; TestGauge.Width:= ClientForm.ClientWidth - TestGauge.Left - x2; StatusBar.Width:= ClientForm.ClientWidth; end else ClientForm.Width:= 440; end; procedure TClientForm.MemoScrollResize(Sender: TObject); {этот обработчик вызывается также в RefreshAnswers} var i,CommonHeight: integer; begin i:= 0; CommonHeight:= 0; While i < (MemoScroll.ComponentCount-1) do begin If i>0 then TMemo(MemoScroll.Components[i]).Top:= TMemo(MemoScroll.Components[i-2]).Top + TMemo(MemoScroll.Components[i-2]).Height; TMemo(MemoScroll.Components[i]).Width:= MemoScroll.Width - 60; TMemo(MemoScroll.Components[i]).Height:= Trunc((2-1/3)*Abs(TMemo(MemoScroll.Components[i]).Font.Height)* TMemo(MemoScroll.Components[i]).Lines.Count); TCheckBox(MemoScroll.Components[i+1]).Left:= TMemo(MemoScroll.Components[i]).Left + TMemo(MemoScroll.Components[i]).Width + 15; TCheckBox(MemoScroll.Components[i+1]).Top:= TMemo(MemoScroll.Components[i]).Top + (TMemo(MemoScroll.Components[i]).Height- TCheckBox(MemoScroll.Components[i+1]).Height) div 2; CommonHeight:= CommonHeight + TMemo(MemoScroll.Components[i]).Height; inc(i,2); end; MemoScroll.VertScrollBar.Range:= CommonHeight; end; end. Текст модуля DlgUnit unit DlgUnit; interface uses Db,Windows, SysUtils, Classes, Graphics, Forms, Controls, StdCtrls, IniFiles,Buttons, ExtCtrls, Spin, ComCtrls; type TBeginDataDlg = class(TForm) EditName: TEdit; Label1: TLabel; TicketEdit: TSpinEdit; Label2: TLabel; Bevel1: TBevel; OkBut: TBitBtn; QuitBut: TBitBtn; StatusBar: TStatusBar; procedure ShowHint(Sender: TObject); procedure OkButClick(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormShow(Sender: TObject); private { Private declarations } public { Public declarations } end; var BeginDataDlg: TBeginDataDlg; implementation uses Sdimain, PathDialog; {$R *.DFM} procedure TBeginDataDlg.ShowHint(Sender: TObject); begin StatusBar.SimpleText:= Application.Hint; end; procedure TBeginDataDlg.OkButClick(Sender: TObject); Var i: integer; begin with ClientForm do begin StudentName:= EditName.Text; Ticket:= TicketEdit.Value; DBTicket.Active:= True; {Выбор номера билета. Выбранный номер билета заносим в Ticket} DBTicket.SetRangeStart; {установка фильтра} DBTicket['Ticket_num']:= ticket; DBTicket.SetRangeEnd; DBTicket['Ticket_num']:= ticket; DBTicket.ApplyRange; DBQuest.Active:= True; with DBResult do //--------- Create new local table RESULT.DB ---------- begin Active:= False; DatabaseName:= ''; TableName:= 'Result'; TableType:= ttParadox; with FieldDefs do begin Clear; Add('Answer_id', ftInteger, 0, False); Add('Trued', ftBoolean, 0, False); end; with IndexDefs do begin Clear; Add('Answer_ind', 'Answer_id', [ixPrimary, ixUnique]); end; CreateTable; end; //--------- end of create ------------------------- DBAnswer.Active:= True; DBresult.Active:= True; i:=0; {заполнение QuestList номерами вопросов} While not DBTicket.EOF do begin inc(i); QuestList.Items.Add(IntToStr(i)); While not DBAnswer.EOF do {Fill RESULT-table} begin DBResult.Append; DBResult['Answer_id']:= DBAnswer['Otvet_id']; DBResult['Trued']:= False; DBResult.Post; DBAnswer.Next; end; DBTicket.Next; end; RefreshAnswers; WindowState:= wsNormal; Application.OnHint:= ShowHint; TestGauge.MaxValue:= TestTime; {Set max value of indicator } Timer.Enabled:= True; { Activate the timer.} CreateMainForm:= False; end; { of with ClientForm} end; procedure TBeginDataDlg.FormClose(Sender: TObject; var Action: TCloseAction); begin If Modalresult <> mrOk then ClientForm.Close; Action:= caFree; end; procedure TBeginDataDlg.FormShow(Sender: TObject); Var IniFile: TIniFile; List: TStringList; AliasPath: string; begin Application.OnHint:= ShowHint; Session.ConfigMode:= cmAll; {Global and local aliases !!!} try List:= TStringList.Create; Session.GetAliasParams('Common_base',List); // may be occurs an error AliasPath:= List.Values['PATH']; List.Free; except Application.CreateForm(TPathDlg, PathDlg); PathDlg.ShowModal; If PathDlg.Modalresult = mrOk then begin AliasPath:= PathDlg.DirectoryList.Directory; Session.AddStandardAlias('Common_base',AliasPath,'PARADOX'); {add NEW alias if none} Session.SaveConfigFile; end else Modalresult:= mrCancel; end; IniFile:= TIniFile.Create(AliasPath+'\Test.INI'); ClientForm.TestTime:= IniFile.ReadInteger('Options', 'TestTime', 600000{10 min}); TicketEdit.MaxValue:= IniFile.ReadInteger('Options', 'MaxTicket', 1); If TicketEdit.MaxValue = 1 then TicketEdit.Increment:= 0; IniFile.Free; end; end. Текст модуля PathDialog unit PathDialog; interface uses Windows, SysUtils, Classes, Graphics, Forms, Controls, StdCtrls, Buttons, ExtCtrls, FileCtrl; type TPathDlg = class(TForm) OKBtn: TButton; CancelBtn: TButton; DirectoryList: TDirectoryListBox; DriveBox: TDriveComboBox; PathLabel: TEdit; Label1: TLabel; procedure DriveBoxChange(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure DirectoryListChange(Sender: TObject); procedure FormActivate(Sender: TObject); private { Private declarations } public { Public declarations } end; var PathDlg: TPathDlg; implementation {$R *.DFM} procedure TPathDlg.DriveBoxChange(Sender: TObject); begin DirectoryList.Drive:= DriveBox.Drive; end; procedure TPathDlg.FormClose(Sender: TObject; var Action: TCloseAction); begin Action:= caFree; end; procedure TPathDlg.DirectoryListChange(Sender: TObject); begin PathLabel.Text:= DirectoryList.Directory; end; procedure TPathDlg.FormActivate(Sender: TObject); begin PathLabel.Text:= DirectoryList.Directory; end; end. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||