Документ взят из кэша поисковой машины. Адрес оригинального документа : http://www.abitu.ru/en2002/closed/viewwork.html?work=6
Дата изменения: Fri May 5 15:25:18 2006
Дата индексирования: Tue Oct 2 02:10:57 2012
Кодировка: koi8-r

|Сайт дистанционных тестирований и опросов. Программа генератор тестов. |
| |
| |
| |
| |
|"Создание сайта дистанционных тестирований и программы генератора тестов" |
| |
| |
| |
| |
| |
| |
|Авторы: Рубинштейн Кирилл |
|Резиков Пётр ученики 11Б |
|класса многопрофильной |
|гимназии ?13 |
|Руководитель: Коровкин С.О. |
|Учитель ИВТ многопрофильной |
|гимназии ?13 |
|[pic] |
|1. Введение. |
|В настоящее время во многих странах появилась необходимость в повышении уровня |
|образованности населения. Наряду с этим стоит проблема, заключающаяся в недостатке |
|учебного материала и учебных пособий. Предлагались различные решения этой проблемы. |
|Например, в Англии предлагалось вести уроки с помощью "виртуальных учителей". Но, как|
|вы понимаете, этот способ является недоступным многим странам в финансовом отношении.|
|В связи с этим, мы решили принять участие в разрешении выше обозначенной проблемы. |
|Наш способ решения этой проблемы заключается в создании образовательного Интернет |
|сайта. Выбор на "всемирную паутину" упал в связи с её всё большим распространением в |
|мире. Итак, перед нами стоит цель, заключающаяся в создании сайта, с помощью которого|
|учителя могли бы обмениваться опытом, получать методические пособия и обмениваться |
|ими. Для реализации проблемы, связанной с повышением образованности населения, на |
|сайте необходимо создать раздел с учебными материалами и пособиями и систему проверки|
|накопленных знаний (проведение дистанционного тестирования). На сайте необходимо |
|создать систему, позволяющую учителям создавать свои тесты, для прохождения их |
|учениками. В связи с этим возникает необходимость в создании системы, позволяющей |
|ученикам просматривать результаты своих работ, а учителям просматривать подробные |
|отчёты работ учеников, генерируемые специальной программой. Для того чтобы учителя и |
|любые другие пользователи сайта имели возможность создавать свои тесты, необходимо |
|разработать язык текстовой разметки вопросов (тесты в HTML занимают слишком много |
|места). Далее в таблице представлены цели и способы их реализации на сайте: |
| |
|Поставленная цель. |
|Реализация на сайте. |
| |
|Помощь учителям в обмене опытом и методическими пособиями. |
|Создание на сайте образовательного форума. Создание на сайте раздела, посвящённого |
|методическим пособиям. |
| |
|Помощь в повышении уровня образования. |
|Создание на сайте раздела с учебными пособиями и материалами. |
| |
|Система проверки знаний. |
|Создание на сайте системы дистанционного тестирования, состоящей из нескольких |
|программ, написанных на языке Perl. |
| |
|Система, позволяющая ученикам смотреть результаты тестирования, а учителям - |
|подробный отчёт о выполненных работах. |
|Создание на сайте системы анализаторов тестов (система написана на языке Perl). |
| |
|Возможность самостоятельного создания тестов. |
|На сайте размещены дистрибутивы специальной программы Qmaker, написанной на языке |
|Visual Basic. (коды программы можно посмотреть в приложении 1). |
| |
|Разработка языка текстовой разметки вопросов. |
|Разработка языка QML. (документацию языка QML можно посмотреть в приложении 2). |
| |
| |
|Необходимо так же провести анализ существующих методов решения этой проблемы. Ниже |
|перечислены недостатки альтернативных методов решения поставленной проблемы: |
|а) Дороговизна: многие учебные заведения не могут себе позволить купить |
|профессиональные системы тестирования. |
|б) Работа только с ASCII текстом: во многих программах нет поддержки таблиц, |
|поясняющих изображения формул, что делает невозможным проведение тестов по физике и |
|химии. |
|в) Требовательность к операционной системе: возможность запускать программу только в |
|данной ОС. |
|г) Ограниченность: имеется лимит количества вопросов или вариантов ответов. |
|д) Плохая документированность: отсутствие или малое количество документации. |
|е) Трудности при заполнении: плохо реализованная или отсутствующая система создания |
|тестов. |
|ж) Неудобный интерфейс: неудобный интерфейс многих программ раздражает и отвлекает |
|тестируемого от написания теста |
|2. Выбор методов решения. |
|Для написания программы-генератора тестов мы решили использовать язык Visual Basic. |
|Это объясняется простотой и понятность синтаксиса этого языка. Несмотря на |
|ограниченность возможностей этого языка, для написания подобного рода программ Visual|
|Basic подходит как нельзя лучше. |
|Для программного обеспечения сайта мы выбрали язык Perl. Выбор обусловлен тем, что : |
|а) Этот язык широко используется в интернет программировании. |
|б) В языке Perl очень хорошо реализована работа с текстом. |
|в) Язык отлично документирован, а также имеется огромное количество учебной |
|литературы. |
|г) Поддерживается многими серверами бесплатного хостинга. |
|д) Интерпретатор этого языка портирован практически на все операционные системы. |
|е) Он бесплатен и распространяется на условии лицензии GNU GPL. |
|3. Выполненная работа. |
|3.1. Программа-генератор тестов Qmaker. |
|Создана программа, позволяющая самостоятельно создавать тесты и опросы. Программа |
|обладает приятным и удобным интерфейсом и является полноценным средством для создания|
|нормальных тестов и опросов. Ниже следует подробное описание программы: |
|[pic] |
|В этой форме программы пользователь создаёт заголовок вопроса. В первом поле |
|необходимо выбрать тип теста: психологический тест, обычный тест, дипломная работа |
|или социологический опрос (об их различии написано немного ниже). Следующие два поля |
|понятны: в них нужно написать своё имя и тему теста. В поле описания теста вы пишете |
|комментарии (можно писать в формате HTML). Необходимо обратить особое внимание на |
|поле «имя файла». Его нужно заполнять маленькими английскими буквами. В дальнейшем |
|будет создано два файла: file_name.qml и file_name.ans. В первом храниться текст |
|теста, а во втором - варианты правильных ответов. |
|[pic] |
|В этой форме заполняется заголовок вопроса. Вопросы могут быть как с дополнениями, |
|так и без них. Вопросы так же могут содержать несколько правильных ответов. Эти |
|условия можно указать в соответствующих полях. Особенностью наших тестов является то,|
|что к ним можно добавлять рисунок, указав к нему путь в поле «путь к рисунку». |
| |
|[pic] |
|В этой форме создаются варианты ответов и количество баллов за каждый вариант. |
|Количество вариантов неограниченно. |
|В последней форме создаются комментарии к результатам теста. Эти комментарии будут |
|отображаться программой, обеспечивающей просмотр результатов теста. |
|Теперь необходимо сказать о типах тестов. Психологический тест и обычный тест ничем |
|не отличаются друг от друга. Создаётся два файла: с тестом и с ответами. В дипломной |
|работе не могут присутствовать комментарии и правильный ответ в вопросе должен быть |
|только один. Соответственно форма, в которой заполняется заголовок вопроса, будет |
|выглядеть иначе (слои «дополнения» и «количество вариантов» будут невидимыми). При |
|создании социологических опросов создаётся только один файл, содержащий текст опроса.|
|В связи с этим формы оценки результатов не будет. |
| |
|3.2. Сайт удалённых тестирований и опросов. |
| |
|Техническая часть |
| |
|Программа дистанционного тестирования и опросов является неотъемлемой частью сайта. |
|Она написана на языке Perl. Все файлы программы можно разбить на несколько категорий.|
| |
| |
|1) Основные скрипты. |
|Это несколько файлов, реализующих все главные функции программы: выбор теста или |
|опроса, получение данных и анализ результатов теста. Все эти файлы имеют расширение |
|cgi |
| |
|2) Дополнительные функции |
|Функции, которые часто используются в основных программах, занесены в отдельные |
|файлы. Это позволяет сократить код программы. Они находятся в отдельной директории и |
|имеют расширение pl. |
| |
|3) Конфигурационные файлы |
|Несколько файлов, содержащих информацию о структуре директорий, пути к основным |
|файлам, названию сервера, использованной кодировки и.т.д. Они очень сильно облегчают |
|настройку программы на разных серверах, с разными операционными системами. Эти файлы |
|имеют расширение pl. |
| |
|4) Специальные файлы |
|Эти файлы служат для хранения динамически обновляемой информации, такой как пароли, |
|файлы блокирования IP адреса и другие. Эти файлы начинаются со знака ".". |
| |
|5) Файлы HTML шаблонов |
|Это html странички, созданные для динамической вставки информации. Они содержат в |
|html коде специальные теги, ограниченные двойными знаками "<" и ">" (например - |
|<>). Программа, читая эти шаблоны, заменяет эти теги на некоторые |
|внутренние переменные программы. Это позволяет легко изменять дизайн, а также |
|минимизировать включение html кода в текст программы. Файлы имеют расширение html или|
|htm. |
|Кроме непосредственно файлов программы, есть и файлы контекста, то есть сами тесты |
|(опросы) и поясняющая их информация. Вся информация о тестах размещена в двух |
|идентичных по структуре папках. Эта папка находится в каталоге скриптов сервера |
|(cgi-bin). В ней находится та информация, которая передаётся пользователю после |
|обработки программой. |
| |
|Файлы тестов (с расширением qml). |
|Файлы написанные на специальном языке разметки QML(см. Приложение "Документация по |
|QML и ANS"). В них хранится информация о тесте - комментарии, объяснения, варианты |
|ответов. |
| |
|б) Файлы ответов (с расширением ans) |
|Это файлы таблиц ответов ANS(см. Приложение "Документация по QML и ANS "). В них |
|содержаться все ответы на данный тест, а также предварительные результаты(т.е. фразы |
|выдаваемые программой в зависимости от успешности написания теста) |
| |
|в) Папка works |
|В этой папке содержаться работы тестируемых в определённом формате. В работах, кроме |
|самих ответов, регистрируется IP адрес, имя и время тестирования. Имя файла работ |
|состоит из 12 случайных цифр, что практически исключает совпадение. |
| |
|2) Вторая папка находится в каталоге сервера, содержащим html страницы (html) в ней |
|хранятся: |
| |
|а) Поясняющие изображения. |
|б) Методические материалы по данному тесту. |
| |
|Описание функциональности скриптов и функций. |
|(Исходные тексты программ см. в приложении 3.) |
| |
|1. Файл spisok.cgi. |
|Этот скрипт предназначен для вывода списка тестов. Если вызвать его без параметров, |
|то он выведет страницу приветствия, а также список категорий тестов (опросов), |
|например: информатика, физика, опросы. После выбора категории (или ввода вручную в |
|строке URL) выводится список тестов в данной категории в виде таблицы. В ней указана |
|информация о тесте: название, имя автора, категория теста. Категория может принимать |
|значения: |
| |
|а) Обычный - полуоткрытый вид теста, может содержать вопросы, как с одним правильным |
|вариантом ответа, так и с несколькими. К этим тестам возможны дополнения. |
| |
|б) С выдачей диплома - тест включает вопросы только с одним правильным вариантом |
|ответа и не может включать дополнения к ответам. Но после написания теста у |
|тестируемого есть возможность получить диплом. |
| |
|в) Психологический - тест тоже не включает дополнений, но нельзя просмотреть и |
|подробный отчёт. Этот вид теста предназначен только для самого тестируемого. |
| |
|г) Опрос - этот вид предназначен для проведения социологических опросов. После ответа|
|на вопрос, можно посмотреть результаты опроса. |
| |
|При щелчке на название теста, вы перейдете непосредственно к тестированию. |
| |
|2. Файл read.cgi. |
|Этот скрипт предназначен для чтения теста. Он конвертирует язык QML в HTML по |
|специальным правилам. Если запустить скрипт без параметров или с неправильными |
|параметрами, он выдаст ошибку. Скрипт открывает файл QML и последовательно заносит |
|его в специальный хэш (вид массива). После этого обрабатывает хэш и выводит код. На |
|странице выводится: основная информация о тесте, описание теста, сами вопросы с |
|вариантами ответа, ссылка на методическую информацию о тесте и кнопку отправки. |
| |
|3. Файл write.cgi. |
|Этот файл принимает данные от скрипта read.cgi Проверяется правильность и записывает |
|файл работ. Если в папке с тестом существует файл .ip_lock, то программа проверяет IP|
|адрес, записанный в этом файле, и если он совпадает с IP адресом данной машины, и со |
|времени создания файла прошло меньше 7,5 минут, то программа не записывает данные, а |
|выводит соответствующее сообщение. Эта функция предусмотрена для того, чтобы |
|затруднить голосование по какому-нибудь опросу многократно. В зависимости от типа |
|теста программа выводит разный текст. |
|а) Если это тест, предлагает просмотреть ваши результаты. |
|б) Если опрос, предлагает ознакомиться с общими результатами опроса. |
|4. Файл rezult.cgi. |
|Этот скрипт выдаёт результаты тестов или опросов. Если запустить его без параметров, |
|он будет действовать так же, как скрипт spisok.cgi. То есть сначала выведет список |
|категорий, затем список теста в данной категории. После выбора теста: |
| |
|а) Если это обычный тест, выдаёт список протестировавшихся, выводит имя тестируемого,|
|IP адрес его компьютера, время, когда был отослан тест. Щёлкнув на имени |
|тестируемого, вы увидите страницу, которую увидел тестируемый после отсылки теста. |
|Здесь указано количество баллов, которые можно получить, сколько баллов набрал этот |
|человек, сколько отрицательных баллов он набрал (отрицательные баллы начисляются, |
|если в вопросе с несколькими правильными вариантами были введены неправильные |
|ответы), а также текст предварительного результата. В этом окне тестируемый может |
|получить диплом, если это предусмотрено тестом. Просмотрев предварительные результаты|
|тест, можно просмотреть полный отчёт о работе. Для этого нужно ввести пароль. Если |
|пароль введён правильно, то выведется страничка с подробным отчетом. На ней можно |
|увидеть, на какие вопросы и как ответил этот человек, а также просмотреть его |
|комментарии. |
| |
|б) Если это был опрос, то программа выдаёт полный отчёт по данному опросу: количество|
|проголосовавших, количество голосов и процент на каждый вариант ответа, а также |
|комментарии к этому опросу, отсортированные в порядке поступления. |
| |
|4. Функционирование сайта. |
|В настоящее время сайт уже размещён во всемирной сети Интернет и нормально |
|функционирует. Любой пользователь Интернета, набрав адрес www.csopros.hoha.ru попадёт|
|на наш сайт и сможет принять участие в тесте и, удачно пройдя его, получить диплом. У|
|посетителей нашего сайта так же есть возможность принимать участие в социологических |
|опросах. Ниже мы решили привести примеры отзывов посетителей нашего сайта, написанные|
|в гостевой книге: |
|12.03.2002. |
|Крутой сайт. Очень полезно для таких как я. |
|Skiff |
|skiff@mail.ru |
| |
|14.03.2002. |
|Круто!!! Халявные дипломы!!! |
|Madvis |
|madvis@hotbox.ru |
| |
|5. Вывод. |
|Итак, нами создан сайт, который позволяет проводить дистанционные тестирования. На |
|сайте есть форум, где учителя могут обмениваться опытом, задавая друг другу |
|интересующие их вопросы. У посетителей сайта есть возможность создать самостоятельно |
|свой тест и поместить его на сайте. Создана специальная программа, облегчающая работу|
|над созданием тестов. |
|Но на этом работа не заканчивается. В перспективе, на нашем сайте будет продолжена |
|работа над наполнением методическими пособиями и учебными материалами, |
|непосредственное участие в которой будут принимать пользователи сайта. По нашим |
|расчётам, в ближайшее время сайт превратится в большой образовательный портал, в |
|которых сейчас нуждаются многие учителя. |
|[pic] |
|Приложение 1. |
|Исходный текст программы Qmaker. |
| |
| |
|Form 1. |
|Private Sub escape1_Click() |
|tipcombo.Text = "(выберите тип)" |
|tematext.Text = "" |
|avtortext.Text = "" |
|opistext.Text = "" |
|fnametext.Text = "" |
|End Sub |
| |
|Private Sub exit_Click() |
|End |
|End Sub |
| |
|Private Sub Form_Load() |
|tipcombo.AddItem "Психологический" |
|tipcombo.AddItem "Дипломный" |
|tipcombo.AddItem "Обычный тест" |
|tipcombo.AddItem "Опрос" |
|End Sub |
| |
|Private Sub next1_Click() |
|'''''проверка на заполненность форм'''''' |
|If (tipcombo.Text = "(выберите тип)" Or tematext.Text = "" Or avtortext.Text = "" Or |
|opistext.Text = "" Or fnametext.Text = "") Then |
|MsgBox ("Заполните все поля") |
|End If |
|''''если всё нормально то поехали дальше''''' |
|If (tipcombo.Text <> "(выберите тип)" And tematext.Text <> "" And avtortext.Text <> |
|"" And opistext.Text <> "" And fnametext.Text <> "") Then |
|fnameqml = fnametext.Text + ".qml" |
|fnameans = fnametext.Text + ".ans" |
|''''''Определяем тип теста или опроса''''' |
|If tipcombo.Text = "Психологический" Then tip = "psy" |
|If tipcombo.Text = "Опрос" Then tip = "opros" |
|If tipcombo.Text = "Обычный тест" Then tip = "usual" |
|If tipcombo.Text = "Дипломный" Then tip = "diplom" |
|''''''''''''''''''''''Создаём два файла с тестом и с |
|ответами''''''''''''''''''''''''''''' |
|Open App.Path + "\tests\" + fnameqml For Output As #1 |
|'''''''если этот тест не опрос, то создадим файл ответов'''' |
|If tip <> "opros" Then Open App.Path + "\tests\" + fnameans For Output As #2 |
|''''''''записываем в файл теста заголовок'''''''''' |
|Print #1, "" |
|Print #1, "" |
|Print #1, "#" + opistext.Text |
|Print #1, "
" |
|''''''присваиваем переменной номера вопроса значение 0''''''' |
|nomervoprosa = 0 |
|'''''''''очистка полей формы'''''''' |
|tipcombo.Text = "(выберите тип)" |
|tematext.Text = "" |
|avtortext.Text = "" |
|opistext.Text = "" |
|fnametext.Text = "" |
|'''''''''''''закрываем эту форму и открываем другую''''''''''' |
|Unload zagolovok |
|vopros.Show |
|'''''''''''''''''''''''''''''''''''''' |
|End If |
|End Sub |
| |
|Form 2. |
|Private Sub escape2_Click() |
|voprtext.Text = "" |
|noopt.Value = False |
|yesopt.Value = False |
|oneopt.Value = False |
|neskolkoopt.Value = False |
|risunokcheck.Value = Unchecked |
|puttext.Text = "" |
|End Sub |
| |
| |
| |
|Private Sub next2_Click() |
|'''''''''''''''проверка форм на заполненность''''''' |
|If (voprtext.Text = "" Or (risunokcheck.Value = Checked And puttext.Text = "") Or |
|(tip <> "diplom" And ((yesopt.Value = False And noopt.Value = False) Or (oneopt.Value|
|= False And neskolkoopt.Value = False)))) Then |
|MsgBox ("Заполните все поля") |
|End If |
|'''''если всё нормально то поехали дальше''''''''''' |
|If (voprtext.Text <> "" And ((risunokcheck.Value = Checked And puttext.Text <> "") Or|
|risunokcheck.Value = Unchecked) And ((tip <> "diplom" And ((yesopt.Value = True Or |
|noopt.Value = True) And (oneopt.Value = True Or neskolkoopt.Value = True))) Or tip = |
|"diplom")) Then |
|'''''''''''определяем тип кнопок''''''''''''' |
|If (oneopt = True Or tip = "diplom") Then tipknopki = "radio" |
|If neskolkoopt = True Then tipknopki = "check" |
|''''''''''''''определяем есть дополнения, или нет'''''''' |
|If yesopt.Value = True Then dopolnenie = "yes" |
|If (noopt.Value = True Or tip = "diplom") Then dopolnenie = "no" |
|''''''''Пишем в файл теста заголовок вопроса''''''' |
|Print #1, "" |
|Print #1, "#" + voprtext.Text + "?" |
|If risunokcheck.Value = Checked Then Print #1, "" |
|''''''''''''присваиваем переменной номера варианта ответа значение 0''''' |
|nomerotveta = 0 |
|''''''''''''очищаем поля формы''''''''' |
|voprtext.Text = "" |
|noopt.Value = False |
|yesopt.Value = False |
|oneopt.Value = False |
|neskolkoopt.Value = False |
|risunokcheck.Value = Unchecked |
|puttext.Text = "" |
|''''''''переходим к другой форме'''''''' |
|Unload vopros |
|vari.Show |
|End If |
|End Sub |
| |
|Private Sub putris_DragDrop(Source As Control, X As Single, Y As Single) |
|If risunokcheck.Value = Unchecked Then |
|putris.Visible = False |
|End If |
|End Sub |
| |
|Form 3. |
|Private Sub Form_Load() |
|''''''''если этот тест является опросом, то баллы не пишем'''' |
|If tip = "opros" Then |
|ballcap.Visible = False |
|next3.Caption = "Конец" |
|Else |
|next3.Caption = "Дальше" |
|End If |
|End Sub |
|Private Sub escape3_Click() |
|''''''очищаем форму'''''''' |
|varianttext.Text = "" |
|balltext.Text = "" |
|End Sub |
| |
| |
| |
|Private Sub newvopros_Click() |
|ball = balltext.Text |
|''''если много вариантов и этот не правильный то за него -1 балл (00)''''' |
|If (tipknopki = "check" And ball = "0") Then ball = "00" |
| |
|''''''переводим цифры в символы''''' |
|Nvopr = Str(nomervoprosa) |
|Nvopr = Right$(Nvopr, Len(Nvopr) - 1) |
|Notvet = Str(nomerotveta) |
|Notvet = Right$(Notvet, Len(Notvet) - 1) |
|'''''''проверяем, сохранён ли последний вариант отета'''''' |
|If (varianttext.Text <> "" And balltext.Text <> "") Then |
|Print #1, "<" + tipknopki + " text='" + varianttext.Text + "'>" |
|If tip <> "opros" Then Print #2, Nvopr + ":" + Notvet + "~" + ball |
|End If |
|Print #1, "
" |
|''''''очищаем форму'''''''' |
|varianttext.Text = "" |
|balltext.Text = "" |
|''''''''''''''прибавляем к переменной номера вопроса единицу''' |
|nomervoprosa = nomervoprosa + 1 |
|''''''идём к форме вопросов'''' |
|Unload vari |
|vopros.Show |
| |
|End Sub |
| |
|Private Sub next3_Click() |
|ball = balltext.Text |
|''''если много вариантов и этот не правильный то за него -1 балл (00)''''' |
|If (tipknopki = "check" And ball = "0") Then ball = "00" |
|If tip = "opros" Then |
|''''''переводим цифры в символы''''' |
|Nvopr = Str(nomervoprosa) |
|Nvopr = Right$(Nvopr, Len(Nvopr) - 1) |
|Notvet = Str(nomerotveta) |
|Notvet = Right$(Notvet, Len(Notvet) - 1) |
|'''''''проверяем, сохранён ли последний вариант отета'''''' |
|If (varianttext.Text <> "" And balltext.Text <> "") Then |
|Print #1, "<" + tipknopki + " text='" + varianttext.Text + "'>" |
|If tip <> "opros" Then Print #2, Nvopr + ":" + Notvet + "~" + ball |
|End If |
|Print #1, "" |
|Print #1, "
" |
|Close #1 |
|''''''очищаем форму'''''''' |
|varianttext.Text = "" |
|balltext.Text = "" |
|'''''Идёи в начало'''' |
|Unload vari |
|zagolovok.Show |
|Else |
|''''''переводим цифры в символы''''' |
|Nvopr = Str(nomervoprosa) |
|Nvopr = Right$(Nvopr, Len(Nvopr) - 1) |
|Notvet = Str(nomerotveta) |
|Notvet = Right$(Notvet, Len(Notvet) - 1) |
|'''''''проверяем, сохранён ли последний вариант отета'''''' |
|If (varianttext.Text <> "" And balltext.Text <> "") Then |
|Print #1, "<" + tipknopki + " text='" + varianttext.Text + "'>" |
|If tip <> "opros" Then Print #2, Nvopr + ":" + Notvet + "~" + ball |
|End If |
|Print #1, "" |
|Print #1, "" |
|Close #1 |
|''''''очищаем форму'''''''' |
|varianttext.Text = "" |
|balltext.Text = "" |
|'''''''Идём оценивать ответы''''''' |
|Unload vari |
|ozenka.Show |
|End If |
|End Sub |
| |
|Private Sub nextvariant_Click() |
|'''''''''''проверяем поля на заполненность'''''''' |
|If (varianttext.Text = "" Or (tip <> "opros" And balltext.Text = "")) Then |
|MsgBox ("Заполните все поля") |
|End If |
|'''''''если всё хорошо то поехали дальше'''''''' |
|If (varianttext.Text <> "" And (tip = "opros" Or (tip <> "opros" And balltext.Text <>|
|""))) Then |
|ball = balltext.Text |
|''''если много вариантов и этот не правильный то за него -1 балл (00)''''' |
|If (tipknopki = "check" And ball = "0") Then ball = "00" |
|''''''переводим цифры в символы''''' |
|Nvopr = Str(nomervoprosa) |
|Nvopr = Right$(Nvopr, Len(Nvopr) - 1) |
|Notvet = Str(nomerotveta) |
|Notvet = Right$(Notvet, Len(Notvet) - 1) |
|''''''''''''''Записываем в файлы''''''' |
|Print #1, "<" + tipknopki + " text='" + varianttext.Text + "'>" |
|If tip <> "opros" Then Print #2, Nvopr + ":" + Notvet + "~" + ball |
|''''''очищаем форму'''''''' |
|varianttext.Text = "" |
|balltext.Text = "" |
|''''''''прибавляем к переменной варианта ответа единицу'''' |
|variantotveta = variantotveta + 1 |
|End If |
|End Sub |
| |
|Form 4. |
|Private Sub dobavit_Click() |
|'''''''''проверка на заполненность''''''' |
|If (ottext.Text = "" Or dotext.Text = "" Or ozenkatext.Text = "") Then MsgBox |
|("Заполните все поля") |
|If (ottext.Text <> "" And dotext.Text <> "" And ozenkatext.Text <> "") Then |
|Print #2, "~" + ottext.Text + "~" + dotext.Text + "~" + ozenkatext.Text |
|'''''очистка полей формы''''''' |
|ottext.Text = "" |
|dotext.Text = "" |
|ozenkatext.Text = "" |
|End If |
|End Sub |
| |
|Private Sub end_Click() |
|'''''''''''Если поля не пустые, то зделать запись'''''' |
|If (ottext.Text <> "" And dotext.Text <> "" And ozenkatext.Text <> "") Then |
|Print #2, "~" + ottext.Text + "~" + dotext.Text + "~" + ozenkatext.Text |
|'''''очистка полей формы''''''' |
|ottext.Text = "" |
|dotext.Text = "" |
|ozenkatext.Text = "" |
|End If |
|Close #2 |
|'''''''идём в начало''''''' |
|Unload ozenka |
|zagolovok.Show |
|End Sub |
| |
|Private Sub escape4_Click() |
|ottext.Text = "" |
|dotext.Text = "" |
|ozenkatext.Text = "" |
|End Sub |
| |
|Приложение 2. |
|Документация языка разметки вопросов QML. |
| |
| |
|Начнём с того, что же такое QML. Итак, QML - это абривиатура и расшифровывается как |
|Question Marktup Language. На русском это звучит как язык разметки вопросов. Этот |
|язык был "разработан" Резиковым Петром и Рубинштейном Кириллом специально для сайта |
|дистанционного тестирований и дистанционных опросов. Он включает в себя всего |
|несколько тегов. Дальше рассмотрим спецификацию языка на простом примере |
|(договоримся, что комментарии будем заключать в символы {}): |
| |
| |
|{все теги МАЛЕНЬКИМИ буквами Y-имя автора Z-тема} |
|{X: usual- обычный тест; opros- опрос(файл ответов(см. про него ниже) не создаётся), |
| |
|diplom - выдаётся диплом(комментарии не допускаются, тэг check не допускается), |
|psy - писихологический тест} |
| |
|{opis-Тег после которого идёт описание теста в HTML} |
|#

Тест про что-нибудь


|
|#HI! |
|{Если строка начинается с символа '#'(именно с # НЕ С ПРОБЕЛА ИЛИ любого другого} |
|знака!!!!) то дальше идёт HTML до конца строки} |
|
|
|{тег opis закрывется} |
| |
|{Тег vop - начало нового вопроса yes-ученик добовляет комментарий к вопросу} |
|#Здесь идёт сам вопрос в HTML {пишите здес сам вопрос в HTML} |
| |
|{Тег pic src - картинка, которая находится в папке теста} |
| |
| |
|{Тег radio и check - выбор варианта ответа text-текст варианта check - возможно |
|несколько вариантов radio - только один} |
|
|
|{Тег вопрос закрывается} |
|Описания файлов *.ans |
| |
|{Расширение файла пишется маленькими буквами} |
|0:0~0 |
|{За первый вариант первого вопроса 0 балов} |
|0:1~1 |
|{За второй вариант первого вопроса 1 балл} |
|1:0~3 |
|{За первый вариант второго опроса 3 балла} |
|1:1~00 |
|{Используется с тег check - ВСЕ неправильные ответы в теге check должны помечаться |
|00} |
|~0~5~Слабо |
|{Если зароботал от 0 до 5 баллов то прогамма выводит "Слабо"} |
|~6~8~Круто |
|{От 6 до 8 - Круто} |
| |
|spisok.cgi |
|#!/usr/bin/perl |
|#spisok.cgi |
|#Программа чтения и активации тестов |
|#Атор - Rezikov Peter Mihalich aka CrazyPit 2002 г. |
|#Включаем конфигурацию |
|require './config.pl'; |
|#Включаем общие функции |
|require $perl_dir.'get_data.pl';#Обработка данных |
|#Включаем локальные функции |
|require $func_dir.'print_file.pl';#Функция вывода html файла-шаблона |
|require $func_dir.'data_error.pl';#Вывод ошибки данных |
|require $func_dir.'check_data.pl';#Обработка данных |
|require $func_dir.'get_cfg.pl';#Получение имени предмета теста |
|require $func_dir.'get_qml_head.pl';#Получение заголовка qml файла |
|require $func_dir.'first_vivod.pl';#Вывод ссылок на группы тестов/опросов |
|require $func_dir.'second_vivod.pl';#Вывод ссылок на тесты/опросы в данной категрии |
|#Получаем и декодируем данные запроса |
|$qvr=&urldecode(&get_data); |
|#Выводим заголовок ответа сервера |
|&content; |
|#Функция начального вывода стрницы |
|if ($qvr eq ''){ |
|#Если запрос нулевой выводим страничку со всеми видами |
|#тестов/опросов |
|&first_vivod('spisok',$spisok_html); |
|} |
|else{ |
|#Если есть запрос проверяам на правильность и |
|#выводим страницу с тестами/опросами в данной |
|#категории |
|&check_data($qvr); |
|&second_vivod($qvr,$spisok2_html, 'read'); |
|} |
|result.cgi |
|#!/usr/bin/perl |
|#rezult.cgi |
|#Программа анализа ответов тестируемых |
|#Атор - Rezikov Peter Mihalich aka CrazyPit 2002 г. |
|#Включаем конфигурацию |
|require './config.pl'; |
|#Включаем общие функции |
|require $perl_dir.'get_data.pl';#Обработка данных |
|#Включаем локальные функции |
|require $func_dir.'print_file.pl';#Функция вывода html файла-шаблона |
|require $func_dir.'data_error.pl';#Вывод ошибки данных |
|require $func_dir.'check_data.pl';#Обработка данных |
|require $func_dir.'get_qml_head.pl';#Получение заголовка qml файла |
|require $func_dir.'get_qml.pl';#Получение параметров всего qml файла |
|require $func_dir.'get_cfg.pl';#Получение имени предмета теста |
|require $func_dir.'first_vivod.pl';#Получение и вывод всех ссылок на группы тестов |
|require $func_dir.'second_vivod.pl';#Вывод ссылок на тесты/опросы в данной категрии |
|require $func_dir.'time_make.pl';#Вывод форматированной даты создания файла даты |
|require $func_dir.'opros_analiz.pl';#Функция анализа опросов |
|require $func_dir.'podrob_och.pl';#Вывад подробного отчёта |
|#Объявляем имена html файлов |
|$write1='write1.html'; |
|$write2='write2.html'; |
|$otchet='otchet.html'; |
|#Печатаем заголовок ответа сервера |
|&content; |
|#Получаем данные |
|$qvr= &get_data; |
|$first_rez='1st_rez.html'; |
| |
| |
| |
| |
|sub get_all_ans{ |
|foreach (@work){ |
|s/\n//g; |
|} |
|foreach (@ans){ |
|s/\n//g; |
| |
|if (/(\d*):(\d*)~(\d*)/){ |
|$balls[$1][$2]=$3; |
|$VAR{'all_ball'}+=$3; |
|} |
|if (/~(\d*)~(\d*)~(.*)/){ |
|push(@rezul, "$1~$2~$3"); |
|} |
|} |
|foreach (@work){ |
|if ($dop==1){ |
|if (/~$/){ |
|$dop=0; |
|} |
|} |
|else{ |
|if (/~(\d*)/){ |
|$dop=1; |
|} |
|elsif (/(\d*):(\d*)/){ |
|if ($balls[$1][$2] eq '00'){ |
|$VAR{'false_balls'}++; |
|} |
|else{ |
|$VAR{'true_balls'}+=$balls[$1][$2]; |
|} |
|} |
|} |
|} |
|if ($VAR{'false_balls'}){ |
|$VAR{'false_balls'}="
Минус баллов: $VAR{'false_balls'}"; |
|} |
|#" |
|if ($VAR{'true_balls'}==0){ |
|$VAR{'true_balls'}='0 '; |
|} |
|foreach(@rezul){ |
|@rezult_part=split /~/, $_; |
|if (($VAR{'true_balls'} >= $rezult_part[0]) && ($VAR{'true_balls'} <= |
|$rezult_part[1])){ |
|$VAR{'pred_rezult'}=$rezult_part[2]; |
|} |
|} |
|} |
|#END |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|if ($qvr eq ''){ |
|#Если запрос нулевой выводим страничку с списком всех тестов/опросов |
|&first_vivod('rezult',$first_rez, 'type=0&'); |
|} |
|else{ |
|#Запрос проверяем на правильность |
|&check_data($qvr); |
|} |
|#Разбиваем запрос на части |
|@qvr=split /&/,$qvr; |
|sub this_work{ |
|local($first_addr)=$_[0]; |
|@work_addr= split /\+/, $first_addr; |
|if (!(-e $data_dir.$work_addr[0].'/'.$work_addr[1].'/works/'.$work_addr[2])){ |
|&data_error; |
|} |
|open WORK, $data_dir.$work_addr[0].'/'.$work_addr[1].'/works/'.$work_addr[2] || die |
|$open_err; |
|@work=; |
|close WORK; |
|open ANS, $data_dir.$work_addr[0].'/'.$work_addr[1].'/'.$work_addr[1].'.ans' || die |
|$open_err; |
|@ans=; |
|close ANS; |
|#Находим вермя отправки теста |
|$VAR{'time_make'}=&time_make($data_dir.$work_addr[0].'/'.$work_addr[1].'/works/'.$wor|
|k_addr[2]); |
|%head_qml=&get_qml_head($work_addr[0],$work_addr[1]); |
|$VAR{'theme'}=$head_qml{'theme'};#Тема |
|$this_type=$head_qml{'type'};#Тип в qml языке |
|$VAR{'user_ip'}=$work[0];#IP адрес тестируемого |
|$VAR{'user_name'}=$work[2];#Имя тестируемого |
|$VAR{'user_name'}=~s/\"//gi;#Убираем нежелательные кавычки в имени |
|$VAR{'predmet_name'}=&get_cfg($work_addr[0]);#Название категории |
|&get_all_ans; |
|if ($this_type =~ /psy/i){ |
|$VAR{'rezult_comment'}='Ваш результат'; |
|} |
|else{ |
|$VAR{'rezult_comment'}='Предварительный результат'; |
|$VAR{'spec_otch'}= < |
|
|
|
|Введите пароль для доступа к полному отчёту
|
| |
| |
|
|
| |
|
|
|fuck_html |
|} |
|if ($this_type =~ /diplom/i){ |
|$VAR{'diplom'}= < |
|
| |value="$VAR{'user_name'}&$VAR{'true_balls'}&$VAR{'all_ball'}&$VAR{'theme'}& |
|$VAR{'predmet_name'}"> |
|
|
|fuck_html |
|} |
|&print_file($otchet); |
|} |
|#Функция вывода работ в данном тесте |
|#' |
|sub this_test{ |
|#Получаем путь к тесту |
|local($qml_addr)=$_[0]; |
|#Разбиваем на части |
|@all_addr= split /\+/, $qml_addr; |
|#Если такой файл не существует - выводим ошибку |
|if (!(-e $data_dir.$all_addr[0].'/'.$all_addr[1])){ |
|&data_error; |
|} |
|else{ |
|#Если всё ОК |
|#Заносим в переменную спец-тегов категорию теста/опроса |
|$VAR{'predmet_name'}=&get_cfg($all_addr[0]); |
|#Получаем заголовок qml |
|%this_head=&get_qml_head($all_addr[0],$all_addr[1]); |
|#Заносим в переменную спец тегов тему теста |
|$VAR{'file_name'}=$this_head{'theme'}; |
|if($this_head{'type'} =~ /opros/){ |
|&opros_analiz($all_addr[0],$all_addr[1]); |
|exit; |
|} |
|#Получаем список работ для данного теста/опроса |
|@all_works=glob($data_dir.$all_addr[0].'/'.$all_addr[1].'/works/*'); |
|#Обрабатываем каждую работу |
|foreach(@all_works){ |
|#Открываем файл работы |
|open WORK , "$_" || die $open_err; |
|#Записываем его в массив |
|@all_work=; |
|#Закрываем |
|close WORK; |
|#Заносим в переменную имя файла |
|$link=$_; |
|#Убираем ненужную часть (дириктории) |
|$link=~s/$data_dir$all_addr[0]\/$all_addr[1]\/works\///gi; |
|#Получаем форматированную дату и время создания файла |
|$timeoffilemake=&time_make($_); |
|#Добавляем в переменную спец тего html код, с таблицей по данной работе |
|$VAR{'works_table'}.= < | |
|$all_work[2] |
|
|
|$timeoffilemake |
|$all_work[0] |
| |
|fuck_html |
|} |
|#Выводим html файл |
|&print_file('ansread.html'); |
|} |
|} |
| |
|#Если первый параметр не type выводим ошибку |
|if ($qvr[0]!~/type=/i){ |
|&data_error; |
|} |
|else{ |
|if ($' == 0){ |
|#type=0 выводим список тестов в данной категории |
| |
|&second_vivod($qvr[1],$spisok2_html,'rezult','type=1&'); |
|} |
|elsif ($' == 1){ |
|#type=1 выводим список работ в данном тесте |
|&this_test($qvr[1]); |
|} |
|elsif ($' == 2){ |
|#Анализ данной работы |
|&this_work($qvr[1]); |
|} |
|elsif ($' == 3){ |
|#Подробный отчёт |
|&podrob_och($qvr); |
|} |
|else{ |
|&data_error; |
|} |
|} |
|write.cgi |
|#!/usr/bin/perl |
|#write.cgi |
|#Программа преобразования qml в HTML тестов |
|#Атор - Rezikov Peter Mihalich aka CrazyPit 2002 г. |
|#Включаем конфигурацию |
|require './config.pl'; |
|#Включаем общие функции |
|require $perl_dir.'get_data.pl';#Обработка данных |
|#Включаем локальные функции |
|require $func_dir.'print_file.pl';#Функция вывода html файла-шаблона |
|require $func_dir.'data_error.pl';#Вывод ошибки данных |
|require $func_dir.'check_data.pl';#Обработка данных |
|require $func_dir.'random_file.pl';#Обработка данных |
|require $func_dir.'get_qml_head.pl';#Получение заголовка qml файла |
|#Объявляем имена html файлов |
|$write1='write1.html'; |
|$write2='write2.html'; |
|#Печатаем заголовок ответа сервера |
|&content; |
|#Получаем данные |
|$qvr= urldecode(&get_data); |
|#Функция печати ответа в файл |
|sub write_file{ |
|#Разбиваем запрос |
|@qvr= split /&/,$qvr; |
|#Проверяем правильность запроса и в случае ошибки выводим страницу ошибки |
|if (($qvr[0]!~/predmet=/i) || ($qvr[1]!~/fio=/i)){ |
|&data_error; |
|} |
|#Если всй ОК печатаем файл |
|else{ |
|#Убираем ненужные части |
|$qvr[0]=~s/predmet=//i; |
|$qvr[1]=~s/fio=//i; |
|$qvr[1]=~s/&/&/g; |
|$qvr[1]=~s/ |$qvr[1]=~s/>/>/g; |
|#Получаем путь к папке теста/опроса |
|@ans_addr=split /\+/,$qvr[0]; |
|#Получаем заголовок qml файла |
|%head_this=&get_qml_head($ans_addr[0], $ans_addr[1]); |
|#Получаем тип теста/опроса |
|$type_this_file=$head_this{'type'}; |
|#Открываем файл с случайным именем длинной 12 цифр |
|$rand_file=&random_file; |
|open ANS, '>'.$data_dir.$ans_addr[0].'/'.$ans_addr[1].'/works/'.$rand_file; |
|$VAR{'rand_file'}=$ans_addr[0].'+'.$ans_addr[1].'+'.$rand_file; |
|$VAR{'rez_op_link'}=$ans_addr[0].'+'.$ans_addr[1]; |
|#Для каждой части запроса делаем обработку |
|print ANS $ENV{'REMOTE_ADDR'}."\n"; |
|foreach(@qvr){ |
|#Преобразуем знак ~ в тег [til] |
|s/~/[til]/g; |
|#ответы представляем в виде X:Y |
|#где X-номер вопроса Y- номер ответа |
|s/chek_(\d*)_(\d*)=true/$1:$2/g; |
|s/opt_(\d*)=radio_(\d*)/$1:$2/g; |
|#Ограничиваем текст пояснения тильдами(~) |
|#начало текста ~X, где X номер вопроса |
|#конец текста просто тильда |
|s/doptext_(\d*)=([^&]*)/~$1\n$2\n~/g; |
|print ANS "$_\n"; |
|} |
|if ($type_this_file=~/opros/i){ |
|#Если это опрос выводим страничу с надписью "Спасибо за ваше мнение" |
|&print_file($write2); |
|} |
|else{ |
|#Если это тест выводи страничку где предлагаем проверить ваш результат |
|&print_file($write1); |
|} |
|} |
|} |
|if ($qvr eq ''){ |
|#Если запрос нулевой выводим страничку с ошибкой |
|&data_error; |
|} |
|else{ |
|#Запрос проверяам на правильность и |
|#в случае удачи запускаем основную функцию |
|&write_file; |
|} |
|diplom.cgi |
|#!/usr/bin/perl |
|##########стандартная функция############ |
|#Включаем конфигурацию |
|require './config.pl'; |
|#Включаем общие функции |
|require $perl_dir.'get_data.pl';#Обработка данных |
|#Включаем локальные функции |
|require $func_dir.'print_file.pl';#Функция вывода html файла-шаблона |
|require $func_dir.'data_error.pl';#Вывод ошибки данных |
|require $func_dir.'check_data.pl';#Обработка данных |
|&content; |
|############################### |
|$qvr=urldecode(&get_data); |
|if ($qvr eq ''){ |
|&data_error; |
|} |
|$qvr=~s/hid=//; |
|@qvr=split /&/,$qvr; |
|################################### |
|$VAR{'user_name'}=$qvr[0]; |
|$prav=$qvr[1]; |
|$vsego=$qvr[2]; |
|$VAR{'test_name'}=$qvr[3]; |
|$VAR{'predmet_name'}=$qvr[4]; |
|$VAR{'procent'}=int($prav/$vsego*100); |
|################################## |
| |
|################################## |
|if($VAR{'procent'}<80){ |
|&print_file('fig.html'); |
|exit; |
|} |
|###################3############### |
|if(($VAR{'procent'}>=80) and ($VAR{'procent'}<90)){ |
|$VAR{'color'}='#006600'; |
|&print_file('diplom.html'); |
|exit; |
|} |
|################################### |
|if(($VAR{'procent'}>=90) and ($VAR{'procent'}<=99)){ |
|$VAR{'color'}='#3300CC'; |
|&print_file('diplom.html'); |
|exit; |
|} |
|################################## |
|if($VAR{'procent'}=100){ |
|$VAR{'color'}='#FF0000'; |
|&print_file('diplom.html'); |
|exit; |
|} |
|################################## |
| |
| |
| |
| |
| |
| |