Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > Пошаговый обход дерева нелинейный тест


Автор: PsiMagistr 18.8.2016, 15:25
Ребята. Помогите, кто чем сумеет. Встала такая задача. На PHP необходимо написать нелинейную систему тестирования. С линейной я справился давно.

Вот в чем суть проблемы.

1.
    1.1
        1.1.1
        1.1.2
    1.2
    1.3
    1.4

2.

    2.1
    2.2

3.

Если ответили на вопрос 1, то переходим к 1.1. Если ответили на вопрос 1.1 переходим к 1.1.1. Если не ответили идем к 1.1.2.

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

Как можно хотя бы примерно решить подобную задачу на связке PHP XML или на БД? 

Заранее спасибо всем.


Автор: ksnk 18.8.2016, 15:37
Вообще-то, если внимательно посмотреть на список вопросов - то система линейна. Нужно все вопросы перенумеровать с 1-цы и свести задачу к уже решенной  smile 
При чем тут рекурсия?

Автор: PsiMagistr 18.8.2016, 15:40
День Вам добрый. 

Каким образом свести к линейному типу?


 Ведь в зависимости от ответов приходится совершать прыжки к совсем другим вопросам.


Например: Гоголь великий писатель?. Ответ: Нет. И тогда отсекается вся ветка вопросов о Гоголе. Переходим к другим подтемам. Ответ "Да" - продолжаем спрашивать о Гоголе.

Автор: ksnk 18.8.2016, 16:25
Если
Цитата(PsiMagistr @  18.8.2016,  15:40 Найти цитируемый пост)
 Ведь в зависимости от ответов приходится совершать прыжки к совсем другим вопросам.

тогда в этом месте, вероятно
Цитата(PsiMagistr @  18.8.2016,  15:25 Найти цитируемый пост)
Если ответили на вопрос 1.1 переходим к 1.1.1. Если не ответили идем к 1.1.2.

должно быть 1.2?

Ok. Нужны более конкретные условия. Ответы на вопросы только да/нет или варианты?

Можно схематичненько набросать описание вопросов
Код

<q>О Гоголе поговорим?
    <a>Да
         <q>Год рождения<a>1809</a><a>x3</a></q>
    </a>
    <a>Нет</a>
</q>
<q>Может о Пушкине?
    <a>Да
         <q>Год рождения<a>1799</a><a>x3</a></q>
    </a>
    <a>Нет</a>
</q>

Такая схема подходит? Или что-то более сложное?

Автор: PsiMagistr 18.8.2016, 17:28
Попробую.


1. Кто написал повесть "Яма"?
          1.1 Как звали главную героиню повести "Яма"?
          1.2  Как звали главного антигероя повести "Яма"?
2. Кто написал "Тимур и его команда"?


Правильный ответ может быть только один из возможных вариантов... (radio - переключатели)

Итак. Если мы отвечаем правильно на первый вопрос, переходим к подпункту 1.1, Если правильно отвечаем переходим к 1.2. Если правильно отвечаем, переходим к вопросу о Тимуре.

Если же мы неправильно отвечаем на вопрос 1, либо на какой-то из подпунктов вопроса 1, сразу переходим к вопросу 2. О Тимуре.







Автор: ksnk 18.8.2016, 19:22
Код

$xml=<<<XML
<?xml version="1.0" encoding="utf-8"?>
<contents>
    <q>Кто написал повесть "Яма"?
        <a>Пушкин</a>
        <a>Лермонтов</a>
        <a>Куприн
            <q>Как звали главную героиню повести "Яма"?
                <a>Пушкин</a>
                <a>Лермонтов</a>
            </q>
            <q> Как звали главного антигероя повести "Яма"?
                <a>Пушкин</a>
                <a>Лермонтов</a>
            </q>
        </a>
    </q>
    <q>Кто написал "Тимур и его команда"?
        <a>Пушкин</a>
        <a>Лермонтов</a>
        <a>Гайдар
            <q>Как звали главного героя
                <a>Пушкин</a>
                <a>Лермонтов</a>
            </q>
        </a>
    </q>
</contents>
XML;

$reader = new XMLReader();
$reader->xml($xml);
$cnt=0;$number=array(0,0,0,0,0,0,0,0);
$level=0;
while($reader->read(1)) {
    if($reader->nodeType == XMLReader::ELEMENT) {
        if((string)$reader->name=='q'){
            $number[$level]++;
            $level++;
            $cnt++;
        }
        $nodeName = $reader->name;
    }

    if($reader->nodeType == XMLReader::TEXT && $nodeName=='q') {
        echo $cnt,' ',implode('.',array_diff($number,array(0))),' ',trim($reader->value),"\n";
    }

    if($reader->nodeType == XMLReader::END_ELEMENT) {
        if((string)$reader->name=='q'){
            $number[$level]=0;
            $level--;
        }
    }
}
$reader->close();


Вот так выводится нумерация и сплошная нумерация.

В точке echo '...' у нас есть номер вопроса.  Удобнее работать со всем набором ответ-вопрос с помощью SimpleXml. Например так
Код

$node = new SimpleXMLElement($reader->readOuterXML());


Если анализируем ответ -  корректный - переходим к следующему вопросу ($cnt+1), если ответ некорректный - ищем следующий вопрос с уровнем на 1 меньше.

Автор: PsiMagistr 18.8.2016, 20:05
Cпасибо большое. Посмотрю завтра покрупнее. Со смаптфона неудобно

Автор: ksnk 19.8.2016, 12:33
Очевидно, что в разметке не хватает информации о правильности ответа. В качестве флага - правильный ответ или нет можно либо завести атрибут (что будет более традиционным решением), либо поместить внутрь дополнительный фейковый элемент, тогда признаком корректности ответа будет наличие внутренних элементов.
Поведение экзаменационного автомата тоже можно определить через атрибуты вопросов.
Например, добавить атрибуты oncorrect="in" onfail="out" со значениями in, out, next. Next - следующий вопрос этого уровня, in - войти внутрь, out -  на уровень выше.
По умолчанию поведение будет oncorrect="in" onfail="out"
Код

    <q onfail="next">Кто написал повесть "Яма"?
        <a>Пушкин</a>
        <a>Лермонтов</a>
        <a>Куприн
            <q>Как звали главную героиню повести "Яма"?
                <a>Пушкин</a>
                <a>Лермонтов</a>
                <a>x3<correct/></a>
            </q>
            <q> Как звали главного антигероя повести "Яма"?
                <a>Пушкин<correct/></a>
                <a>Лермонтов</a>
                <a>x3</a>
            </q>
        </a>
    </q>
    <q onfail="next">Кто написал "Тимур и его команда"?
        <a>Пушкин</a>
        <a>Лермонтов</a>
        <a>Гайдар
            <q >Как звали главного героя
                <a>Пушкин</a>
                <a>Лермонтов</a>
                <a>x3<correct/></a>
            </q>
        </a>
    </q>


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)