Опис інтерфейсу створення екземпляру анкети.

Спочатку обираємо у випадаючому списку завдання «Опитувальник».

Отримуємо наступне діалогове вікно:

Діалогове вікно редагування індентифікації екземпляру анкети.

Тут ми задаємо назву анкети та її короткий опис. Наступний крок – це встановлення строку існування анкети. Use Close Dateце дата коли екземпляр анкети буде блоковано для користування.

Наступна частина першого вікна редагування(параметри анкети).

Тип респонденту – параметр, що дозволяє анкетуватися як відкрито, так і анонімно.

Respondent Eligibilityякі групи можуть анкетуватися.

View responses – групи, що можуть проглядати результати.

Questionnaire Typeобираємо Private або Public.

Save/Resume answers - Надає можливість зберігати відповіді і продовжети проходження анкети у будь-який зручний час.

Наступне діалогове вікно редагування анкети(оформлення).

Заповнюємо поля оформення анкети. У графу Confirmation Page вводимо адрусу-посилання, куди необхідно повернутися після закінчення анкетування.

Кнопка Edit Questions – перехід до вікна редагування змісту питань анкети.

Кнопка Reorder Questions – перехід до вікна редагування позиції питань.

Finish - Закінчення створення екземпляру анкети.

Редагування змісту анкети.

Вікно виглядає так:

Question Text – тут через клавішу Enter вводимо(вважаючи специфіку анкети) два вирази, що формують питання. Далі з випадаючого списку Type обираємо, створений нами новий тип відповіді four scroll. Спираючись на специфіку анкети, заповнюємо чотири варіанти відповіді в наступному порядку: A, C, B ,D.

НЕ нашли? Не то? Что вы ищете?

Приклад виконання програми.

Загальні коментарі

Для реалізації поставленої задачі було взято найновішу версію модуля questionnaire для версії 1.8 і доповнено її новим типом питань – з чотирма скролами.

Структура БД

Модуль questionnaire використовує такі таблиці:

mdl_questionnaire – інформанія про опитувальники

mdl_questionnaire_attempts – інформація про спроби

mdl_questionnaire_question – інформація про питання

mdl_questionnaire_question_choice – варіанти відповідей до питань

mdl_questionnaire_question_type – типи питань (додали свій тип 4 Scrolls)

mdl_questionnaire_responseзаписи про відповіді

mdl_questionnaire_response_bool – самі відповіді на питання булівського типу

mdl_questionnaire_response_date – відповді на питання типу «дата»

mdl_questionnaire_response_multiple – відповіді на питання з декількома опціями

mdl_questionnaire_response_other – відповіді на інші питання

mdl_questionnaire_response_rank – відповіді на питання типу «ранг»

mdl_questionnaire_response_scrolls – відповіді на питання типу 4 Scrolls

mdl_questionnaire_response_singleвідповіді на питання, які вимагають однієї відповіді

mdl_questionnaire_response_text – відповіді на питання, які вимагають текстовоі відповіді

mdl_questionnaire_survey – інформація про самі анкети

Фактично, робота нашого доповнення базується на таблицях:

mdl_questionnaire_response_scrolls

mdl_questionnaire_response

Код програми

Практично вся робота модуля виконується в двох файлах:

locallib.php – опис загального класу опитувальника, виводу результатів, контролю, хто може проходити і скільки разі і т. ін.

questiontypes/questiontypes. class – опис типів питань, як вони виводять, яким чином зберігаються дані для кожного питання та як вони аналізуються.

В першому файлі було внесено такі зміни:

1. Додано функцію, яка видаляє пусті значення з масиву (буде використовуватися при виводу питання

/**

* Clears array from empty values

*

* @param array $arr Array to be cleared

* @return array

*/

function clear_array($arr)

{

if (!is_array($arr) || sizeof($arr) < 1) return $arr;

foreach ($arr as $key => $val)

{

if (empty($val)) unset($arr[$key]);

}

return array_merge($arr, array());

}

2. На строках 202-217 код змінено для того, щоб всі користувачі могли дивитися свої результати:

if (isteacher($this->course->id) || $this->has_4scrolls()) {

echo '<td align="right" valign="middle">';

if ($numresp = $this->count_submissions($USER->id)) {

$strviewresponses = get_string('viewyourresponses', 'questionnaire', $numresp);

echo '<span class="returnLink"><a href="myreport. php? instance='.$this->id.

'&user='.$USER->id.'">'.$strviewresponses.'</a></span>&nbsp;';

}

if ($this->is_survey_owner() && isteacher($this->course->id)) {

if ($numresp = $this->count_submissions()) {

$strviewresponses = get_string('viewresponses', 'questionnaire', $numresp);

echo '<span class="returnLink"><a href="report. php? instance='.$this->id.

'&sid='.$this->sid.'&qact=vresp">'.$strviewresponses.'</a></span>';

} else {

echo get_string('noresponses', 'questionnaire');

}

}

3. На строках 303-342 код змінено для того, щоб виводити результати опитування.

Тут за допомогою метода has_4scrolls() перевіряється, чи є в поточному опитувальнику питання з кривої акцентів. Якщо так – то обробляємо як криву акцентів. Якщо ні – то обробляємо як звичайний опитувальник

if (!$this->has_4scrolls())

{

switch ($this->qtype) {

case QUESTIONNAIREDAILY:

$msgstring = ' '.get_string('today', 'questionnaire');

break;

case QUESTIONNAIREWEEKLY:

$msgstring = ' '.get_string('thisweek', 'questionnaire');

break;

case QUESTIONNAIREMONTHLY:

$msgstring = ' '.get_string('thismonth', 'questionnaire');

break;

default:

$msgstring = '';

break;

}

echo ('<div class="message">'.get_string("alreadyfilled", "questionnaire", $msgstring).'</div>');

}

else

{

//get response id's user filled in

$rids = $this->get_rid_by_uid($USER->id);

if (is_array($rids))

{

echo '<br /><br /><br /><br />';

print_simple_box_start('center', '95%');

echo '<center><strong>Результати</strong>:<br />';

$captions = array('Зараз', 'Бажано', 'Перспектива');

$ridsNum = sizeof($rids);

//cycle through all of them and output a graph

for ($i = 0; $i < $ridsNum; $i++)

{

echo '<span>'.$captions[$i].'</span><br />';

$this->display_accent_curve_results($rids[$i]);

echo '<br /><br />';

}

echo '</center>';

print_simple_box_end();

}

}

4. В метод view_response() внесено аналогічні зміни (строки 362-393)

if (!$this->has_4scrolls())//if it is a regular survey

{

$this->print_survey_start('', 1, 1, 0, $rid);// JR

$data = new Object();

$i = 1;

echo '<div class="mainTable">';

if (!$blankquestionnaire) {

$this->response_import_all($rid, $data);

}

foreach ($this->questions as $question) {

if ($question->type_id < QUESPAGEBREAK) {

$question->response_display($data, $i++);

}

}

echo '</div>';

$this->print_survey_end(1, 1);

}

else //if it is an accent curve questionnaire

{

$data = $this->analyse_responses($rid);

foreach ($data as $key => $arr)

{

foreach ($arr as $sector => $value)

{

$dataStr[] = $key.$sector.'='.$value;

}

}

$dataStr = implode('&', $dataStr);

echo '<img src="graph. php?'.$dataStr.'" />';

}

5. В метод view_all_responses внесено зміни, щоб виводились всі відповіді (строки 410-470)

/**

* Added by Stepan

*/

if ($this->has_4scrolls())

{

//get response id's user filled in

if (is_array($resps))

{

echo '<center><strong>Результати</strong>:<br />';

$captions = array('Зараз', 'Бажано', 'Перспектива');

$respsNum = sizeof($resps);

//cycle through all of them and output a graph

$i = 0;

foreach ($resps as $rid => $_)

{

echo '<span>'.$captions[$i].'</span><br />';

$this->display_accent_curve_results($rid);

echo '<br /><br />';

$i++;

$rids[] = $rid;

}

if (sizeof($rids) == 3)

{

echo '<span>Еволюція поглядів</span><br />';

$this->display_accent_curve_user_desire($rids);

}

echo '</center>';

}

}

else

{

$this->print_survey_start('', 1, 1, 0);

foreach ($resps as $resp) {

$data[$resp->id] = new Object();

$this->response_import_all($resp->id, $data[$resp->id]);

}

$i = 1;

echo '<div class="mainTable">';

foreach ($this->questions as $question) {

if ($question->type_id < QUESPAGEBREAK) {

$method = $QTYPENAMES[$question->type_id].'_response_display';

if (method_exists($question, $method)) {

$question->questionstart_survey_display($i);

foreach ($data as $respid => $respdata) {

echo '<div class="respdate">'.userdate($resps[$respid]->submitted).'</div>';

$question->$method($respdata);

echo '<hr />';

}

$question->questionend_survey_display($i);

} else {

error(get_string('displaymethod', 'questionnaire'));

}

$i++;

}

}

echo '</div>';

$this->print_survey_end(1, 1);

}

6. В метод user_can_take внесені зміни, щоб виясняти, скільки разів користувач вже проходив тестування (строки 494-516)

/**

* Modified by Stepan.

* In original this brunch returned TRUE

*/

if ($this->has_4scrolls())

{

$sql = 'SELECT count(*) Attempts

FROM mdl_questionnaire_attempts a

WHERE a. qid='.$this->id.' AND a. userid='.$userid;

$res = get_record_sql($sql);

if ($res->Attempts < 3)

{

return true;

}

else

{

return false;

}

}

else

{

return true;

}

7. Додано метод has_4scrolls для того, щов вияснити, чи є в опитувальнику питання з кривої акцентів:

/**

* Checks if there is a field with 4 scrolls

*

* @author Stepan

* @return bool

*/

function has_4scrolls($section = 0)

{

if (empty($this->questions))

{

return false;

}

else if ($section <= 0)

{

foreach ($this->questions as $question)

{

if ($question->type == '4 Scrolls')

{

return true;

}

}

}

else

{

foreach ($this->questionsbysec[$section] as $question)

{

if ($question->type == '4 Scrolls')

{

return true;

}

}

}

return false;

}

8. Додано метод для в виведення результатів опитування у вигляді картинки. Він викликає функцію, яка зчитує з БД відповіді та обраховує середнє значення для A, B, C, D. Цей метод буд розглянуто далі.

/**

* Display result for the accent curve graph type

*

* @author Stepan

* @param int $rid

*/

function display_accent_curve_results($rid)

{

$data = $this->analyse_responses($rid);

foreach ($data as $key => $arr)

{

foreach ($arr as $sector => $value)

{

$dataStr[] = $key.$sector.'='.$value;

}

}

$dataStr = implode('&', $dataStr);

echo '<img src="graph. php?'.$dataStr.'" />';

}

/**

* Display sumary result for the user

*

* @author Stepan

* @param int $rid

*/

function display_accent_curve_user_desire($rids)

{

$data = $this->analyse_user_responses($rids);

foreach ($data as $key => $arr)

{

foreach ($arr as $sector => $value)

{

$dataStr[] = $key.$sector.'='.$value;

}

}

$dataStr = implode('&', $dataStr);

echo '<img src="user_graph. php?'.$dataStr.'" />';

}

9. В метод print_survey_end додано строки, які всталяють файли, які потрібні для віображення скролів (строки 957-963):

if($this->has_4scrolls())

{

echo '<!-- The slider javascript code -->

<script type="text/javascript" src="js/slider. js" ></script>

<!-- The default slider stylessheet -->

<link href="css/slider. css" rel="stylesheet" type="text/css" />';

}

10. Додано метод, який обраховує дані для A, B, C, D та повертає їх у вигляді масиву, зручного для використання:

/**

* Analyses results of the survey - accent curve type

*

* @param int $rid ID of the response. If empty, average is

* calculated for all responses in survey

* @return array

*/

function analyse_responses($rid)

{

if (empty($rid))

{

$sql = 'SELECT avg(r. ANow) ANow, avg(r. BNow) BNow, avg(r. CNow) CNow, avg(r. DNow) DNow,

avg(r. AFuture) AFuture, avg(r. BFuture) BFuture, avg(r. CFuture) CFuture, avg(r. DFuture) DFuture

FROM mdl_questionnaire_response_scrolls r

INNER JOIN mdl_questionnaire_response resp ON r. response_id=resp. id

WHERE resp. survey_id='.$this->survey->id;

}

else

{

$sql = 'SELECT avg(ANow) ANow, avg(BNow) BNow, avg(CNow) CNow, avg(DNow) DNow,

avg(AFuture) AFuture, avg(BFuture) BFuture, avg(CFuture) CFuture, avg(DFuture) DFuture

FROM mdl_questionnaire_response_scrolls

WHERE response_id='.$rid;

}

$row = get_record_sql($sql);

$result = array(

'Now' => array(

'A' => $row->ANow,

'B' => $row->BNow,

'C' => $row->CNow,

'D' => $row->DNow,

),

'Future' => array(

'A' => $row->AFuture,

'B' => $row->BFuture,

'C' => $row->CFuture,

'D' => $row->DFuture,

),

);

return $result;

}

11. Додано метод, який повертає ідентификатори відповідей за ідентификатором користувача, тобто відповідає напитання – а які відповіді дав даний користувач?

/**

* Returns response ids for the current survey for the specified user

*

* @param int $userid

* @return array

*/

function get_rid_by_uid($userid)

{

if (empty($userid)) return array();

$sql = 'SELECT id

FROM mdl_questionnaire_response

WHERE survey_id='.$this->survey->id.' AND username='.$userid;

$res = get_records_sql($sql);

if (is_array($res))

{

foreach ($res as $rid => $_)

{

$result[] = $rid;

}

}

return $result;

}

12. Додано метод, що повертає розрахунки для 3х ліній – стан «бажано» в перший, другий та третії раз:

/**

* Returns data for 3 lines - desirable now, desirable in the future, desirable in perspective

*

* @param int $uid

*/

function analyse_user_responses($rids)

{

if (sizeof($rids) != 3) return array();

$sql = 'SELECT response_id, avg(AFuture) AFuture, avg(BFuture) BFuture, avg(CFuture) CFuture, avg(DFuture) DFuture

FROM mdl_questionnaire_response_scrolls scrolls

INNER JOIN mdl_questionnaire_response resp ON scrolls. response_id=resp. id

WHERE response_id IN ('.implode(',', $rids).') GROUP BY scrolls. response_id

ORDER BY resp. submitted';

$res = get_records_sql($sql);

$keys = array('Now', 'Future', 'Perspective');

$i = 0;

foreach ($res as $row)

{

$result[$keys[$i]] = array(

'A' => $row->AFuture,

'B' => $row->BFuture,

'C' => $row->CFuture,

'D' => $row->DFuture,

);

$i++;

}

return $result;

}

13. Додано метод, який будує навігацію по користувачам:

function survey_results_navbar_by_user($curr_uid)

{

global $CFG;

$sql = 'SELECT u.*, r. id rid, r. submitted sdate

FROM mdl_user u

INNER JOIN mdl_questionnaire_response r ON u. id=r. username

WHERE r. survey_id = '.$this->survey->id.' AND plete=\'Y\'';

if (!($users = get_records_sql($sql)))

{

return;

}

$total = sizeof($users);

$uids = array();

$uidssub = array();

$username = array();

$i = 0;

$curr_pos = -1;

foreach ($users as $user) {

array_push($uids, $user->id);

array_push($uidssub, $user->sdate);

array_push($username, fullname($user));

if ($user->id == $curr_uid)

{

$curr_pos = $i;

}

$i++;

}

$prev_uid = ($curr_pos > 0) ? $uids[$curr_pos - 1] : null;

$next_uid = ($curr_pos < $total - 1) ? $uids[$curr_pos + 1] : null;

$rows_per_page = 1;

$pages = ceil($total / $rows_per_page);

$url = $CFG->wwwroot.'/mod/questionnaire/report. php? where=results&sid='.$this->survey->id;

$mlink = create_function('$i,$r', 'return "<a href=\"'.$url.'&uid=$r&qact=vuser\">$i</a>";');

$linkarr = array();

$display_pos = 1;

if ($prev_uid!= null)

{

array_push($linkarr, "<a href=\"$url&uid=$prev_uid&qact=vuser\">".get_string('previous').'</a>');

}

$ruser = '';

for ($i = 0; $i < $curr_pos; $i++)

{

$ruser = $username[$i];

$title = userdate($uidssub[$i]).' | ' .$ruser;

array_push($linkarr, '<a href="'.$url.'&uid='.$uids[$i].'&qact=vuser" title="'.$title.'">'.$ruser.'</a>');

// $display_pos++;

}

$cur_user = get_record('user', 'id', $uids[$curr_pos]);

array_push($linkarr, '<b>'.fullname($cur_user).'</b>');

for (++$i; $i < $total; $i++)

{

$ruser = $username[$i];

$title = userdate($uidssub[$i]).' | ' .$ruser;

array_push($linkarr, '<a href="'.$url.'&uid='.$uids[$i].'&qact=vuser" title="'.$title.'">'.$ruser.'</a>');

}

if ($next_uid!= null)

{

array_push($linkarr, "<a href=\"$url&uid=$next_uid&qact=vuser\">".get_string('next').'</a>');

}

echo implode(' | ', $linkarr);

}

14. Внесено зміни в метод survey_results для того, щоб показувати узагальнені результати опптування для всях студентів (строки ):

/**

* Added by Stepan

*/

if ($this->has_4scrolls())

{

$data = $this->analyse_responses($_);

foreach ($data as $key => $arr)

{

foreach ($arr as $sector => $value)

{

$dataStr[] = $key.$sector.'='.$value;

}

}

$dataStr = implode('&', $dataStr);

echo '<center><strong>Узагальнені результати</strong><br /><br />

<img src="graph. php?'.$dataStr.'" /></center>';

return;

}

//EOF - Added by Stepan

В файлі, який описує типи питань внесено такі зміни:

1. Додано константу для нового типу питань (строка 29):

define('QUES4SCROLLS', 11);

2. Додано елемент в масив для нового типу питань (строка 43):

QUES4SCROLLS => 'four_scrolls',

3. Додано властивість, в якій зберігається номер поточного питання

/**

* Number of the question. Needed for the 4scrolls type of question

* @var integer $qnum

*/

var $qnum;

4. Додано метод для збереження даних для питань кривої акцентів:

function insert_response_scrolls($rid, $formdata)

{

$data = $formdata->{'q'.$this->id};

$record = new Object();

$record->response_id = $rid;

$record->question_id = $this->id;

$record->ANow = $data['Now']['A'];

$record->BNow = $data['Now']['B'];

$record->CNow = $data['Now']['C'];

$record->DNow = $data['Now']['D'];

$record->AFuture = $data['Future']['A'];

$record->BFuture = $data['Future']['B'];

$record->CFuture = $data['Future']['C'];

$record->DFuture = $data['Future']['D'];

return insert_record('questionnaire_'.$this->response_table, $record);

}

5. Додано метод для відображення питаня кривої акцентів

/**

* Forms output for the 4 scrolls input field, for the accent curve.

*

* @param mixed $data

*/

function four_scrolls_survey_display($data)

{

if (stristr($this->content, '<ul>'))

{

preg_match_all('!<li>(.*?)</li>!is', $this->content, $matches);

$qParts = clear_array($matches[1]);

array_walk($qParts, 'strip_tags');

}

elseif (stristr($this->content, '<br />'))

{

$qParts = clear_array(explode('<br />', $this->content));

}

elseif (stristr($this->content, '<br>'))

{

$qParts = clear_array(explode('<br>', $this->content));

}

elseif (stristr($this->content, "\n"))

{

$qParts = clear_array(explode("\n", $this->content));

}

$i = 0;

if (!empty($data->rid))

{

$sql = "SELECT *

FROM mdl_questionnaire_response_scrolls

WHERE response_id=".$data->rid." AND question_id=".$this->id;

$res = get_record_sql($sql);

}

foreach ($this->choices as $chID => $chVal)

{

switch ($i)

{

case 0:

{

$qVariants[0]['A']['ID'] = $chID;

$qVariants[0]['A']['Text'] = $chVal->content;

$qVariants[0]['A']['Val'] = empty($res) ? array(50,50) : array($res->ANow, $res->AFuture);

break;

}

case 1:

{

$qVariants[0]['C']['ID'] = $chID;

$qVariants[0]['C']['Text'] = $chVal->content;

$qVariants[0]['C']['Val'] = empty($res) ? array(50,50) : array($res->CNow, $res->CFuture);

break;

}

case 2:

{

$qVariants[1]['B']['ID'] = $chID;

$qVariants[1]['B']['Text'] = $chVal->content;

$qVariants[1]['B']['Val'] = empty($res) ? array(50,50) : array($res->BNow, $res->BFuture);

break;

}

case 3:

{

$qVariants[1]['D']['ID'] = $chID;

$qVariants[1]['D']['Text'] = $chVal->content;

$qVariants[1]['D']['Val'] = empty($res) ? array(50,50) : array($res->DNow, $res->DFuture);

break;

}

}

$i++;

}

$output = '<table id="q'.$this->qnum.'" width="100%" border="1" bgcolor="#FFFFFF" bordercolor="#E0E0E0" cellspacing="0" cellpadding="3" align="center">';

foreach ($qParts as $k => $txt)

{

$output .= '<tr bgcolor="#EFEFEF">

<td align="center" width="25">'.$this->qnum.'.'.($k+1).'</td>

<td id="q'.$this->id.'"><strong>'.$txt.'</strong></td>

<td align="center">Зараз</td>

<td align="center">Бажано</td>

</tr>';

foreach ($qVariants[$k] as $sect => $data)

{

$output .= '

<tr>

<td align="center"><strong>'.$sect.'</strong></td>

<td>'.$data['Text'].'</td>'."\n";

if ($sect == 'A' || $sect == 'B')

{

$output.= '<td align="right" rowspan="2" width="70">

<div class="vslider_track"><div class="slider_slit">&nbsp;</div>

<div id="q'.$this->qnum.'_'.$k.'z'.$this->qnum.'" class="slider" orientation="vertical" distance="50"

display="q'.$this->qnum.'_'.$k.'z'.$this->qnum.'" style="top: '.(50-$data['Val'][0]/2).'px;">&nbsp;</div>

</div>

<input id="up_q'.$this->qnum.'_'.$k.'z'.$this->qnum.'" name="q'.$this->id.'[Now]['.$sect.']" value="'.$data['Val'][0].'" class="slider_display" type="text" from="0" to="100" valuecount="200" value="50" typelock="on" style="margin-top:7px;" />

<input id="dn_q'.$this->qnum.'_'.$k.'z'.$this->qnum.'" name="q'.$this->id.'[Now]['.($sect == 'A' ? 'C' : 'D').']" value="'.(100-$data['Val'][0]).'" class="slider_display" type="text" from="0" to="100" valuecount="200" value="50" typelock="on" />

</td>

<td align="right" rowspan="2" width="70">

<div class="vslider_track"><div class="slider_slit">&nbsp;</div>

<div id="q'.$this->qnum.'_'.$k.'b'.$this->qnum.'" class="slider" orientation="vertical" distance="50"

display="q'.$this->qnum.'_'.$k.'b'.$this->qnum.'" style="top: '.(50-$data['Val'][1]/2).'px;">&nbsp;</div>

</div>

<input id="up_q'.$this->qnum.'_'.$k.'b'.$this->qnum.'" name="q'.$this->id.'[Future]['.$sect.']" value="'.$data['Val'][1].'" class="slider_display" type="text" from="0" to="100" valuecount="200" value="50" typelock="on" style="margin-top:7px;" />

<input id="dn_q'.$this->qnum.'_'.$k.'b'.$this->qnum.'" name="q'.$this->id.'[Future]['.($sect == 'A' ? 'C' : 'D').']" value="'.(100-$data['Val'][1]).'" class="slider_display" type="text" from="0" to="100" valuecount="200" value="50" typelock="on" />

</td>

</tr>

';

}

}

}

$output .= "\n</table>";

echo $output;

}

6. Змінено метод questionstart_survey_display щоб не виводився стандартний початок питання (строкт 849-854):

if ($this->type_id == QUESSECTIONTEXT ||

$this->type_id == QUES4SCROLLS)

{

$this->qnum = $qnum;

return;

}

Крім цих двох файлів, було створен два файли, які малюють графіки засобами PHP, що дає можливість користувачу зберегти графік:

graph.php

<?php

$im = imagecreatefromjpeg('images/graph. jpg');

$red = imagecolorallocate($im, 0xFF, 0x00, 0x00);

$yellow = imagecolorallocate($im, 0xFF, 0xFF, 0x00);

extract($_GET);

//echo "<pre>";

//print_r($data);

//echo "</pre>";

$xAxis = 225;

$yAxis = 225;

$scale = 2.65;

$Now['A']['X'] = round(-$NowA*$scale/1.41+$xAxis);

$Now['A']['Y'] = round(-$NowA*$scale/1.41+$yAxis);

$Now['B']['X'] = round($NowB*$scale/1.41+$xAxis);

$Now['B']['Y'] = round(-$NowB*$scale/1.41+$yAxis);

$Now['C']['X'] = round($NowC*$scale/1.41+$xAxis);

$Now['C']['Y'] = round($NowC*$scale/1.41+$yAxis);

$Now['D']['X'] = round(-$NowD*$scale/1.41+$xAxis);

$Now['D']['Y'] = round($NowD*$scale/1.41+$yAxis);

$Future['A']['X'] = round(-$FutureA*$scale/1.41+$xAxis);

$Future['A']['Y'] = round(-$FutureA*$scale/1.41+$xAxis);

$Future['B']['X'] = round($FutureB*$scale/1.41+$xAxis);

$Future['B']['Y'] = round(-$FutureB*$scale/1.41+$xAxis);

$Future['C']['X'] = round($FutureC*$scale/1.41+$xAxis);

$Future['C']['Y'] = round($FutureC*$scale/1.41+$xAxis);

$Future['D']['X'] = round(-$FutureD*$scale/1.41+$xAxis);

$Future['D']['Y'] = round($FutureD*$scale/1.41+$xAxis);

//output current state

imagefilledrectangle($im, $Now['A']['X']-2, $Now['A']['Y']-2,$Now['A']['X']+2, $Now['A']['Y']+2, $red);

imagefilledrectangle($im, $Now['B']['X']-2, $Now['B']['Y']-2,$Now['B']['X']+2, $Now['B']['Y']+2, $red);

imagefilledrectangle($im, $Now['C']['X']-2, $Now['C']['Y']-2,$Now['C']['X']+2, $Now['C']['Y']+2, $red);

imagefilledrectangle($im, $Now['D']['X']-2, $Now['D']['Y']-2,$Now['D']['X']+2, $Now['D']['Y']+2, $red);

imageline($im, $Now['A']['X'],

$Now['A']['Y'],

$Now['B']['X'],

$Now['B']['Y'],

$red);

imageline($im, $Now['B']['X'],

$Now['B']['Y'],

$Now['C']['X'],

$Now['C']['Y'],

$red);

imageline($im, $Now['C']['X'],

$Now['C']['Y'],

$Now['D']['X'],

$Now['D']['Y'],

$red);

imageline($im, $Now['D']['X'],

$Now['D']['Y'],

$Now['A']['X'],

$Now['A']['Y'],

$red);

//output desirable state

imagefilledrectangle($im, $Future['A']['X']-2, $Future['A']['Y']-2,$Future['A']['X']+2, $Future['A']['Y']+2, $yellow);

imagefilledrectangle($im, $Future['B']['X']-2, $Future['B']['Y']-2,$Future['B']['X']+2, $Future['B']['Y']+2, $yellow);

imagefilledrectangle($im, $Future['C']['X']-2, $Future['C']['Y']-2,$Future['C']['X']+2, $Future['C']['Y']+2, $yellow);

imagefilledrectangle($im, $Future['D']['X']-2, $Future['D']['Y']-2,$Future['D']['X']+2, $Future['D']['Y']+2, $yellow);

imageline($im, $Future['A']['X'],

$Future['A']['Y'],

$Future['B']['X'],

$Future['B']['Y'],

$yellow);

imageline($im, $Future['B']['X'],

$Future['B']['Y'],

$Future['C']['X'],

$Future['C']['Y'],

$yellow);

imageline($im, $Future['C']['X'],

$Future['C']['Y'],

$Future['D']['X'],

$Future['D']['Y'],

$yellow);

imageline($im, $Future['D']['X'],

$Future['D']['Y'],

$Future['A']['X'],

$Future['A']['Y'],

$yellow);

imagepng($im);

?>

user_graph.php

<?php

$im = imagecreatefromjpeg('images/graph2.jpg');

$red = imagecolorallocate($im, 0xFF, 0x00, 0x00);

$yellow = imagecolorallocate($im, 0xFF, 0xFF, 0x00);

$green = imagecolorallocate($im, 0x00, 0xFF, 0x00);

extract($_GET);

//echo "<pre>";

//print_r($data);

//echo "</pre>";

$xAxis = 225;

$yAxis = 225;

$scale = 2.65;

$Now['A']['X'] = round(-$NowA*$scale/1.41+$xAxis);

$Now['A']['Y'] = round(-$NowA*$scale/1.41+$yAxis);

$Now['B']['X'] = round($NowB*$scale/1.41+$xAxis);

$Now['B']['Y'] = round(-$NowB*$scale/1.41+$yAxis);

$Now['C']['X'] = round($NowC*$scale/1.41+$xAxis);

$Now['C']['Y'] = round($NowC*$scale/1.41+$yAxis);

$Now['D']['X'] = round(-$NowD*$scale/1.41+$xAxis);

$Now['D']['Y'] = round($NowD*$scale/1.41+$yAxis);

$Future['A']['X'] = round(-$FutureA*$scale/1.41+$xAxis);

$Future['A']['Y'] = round(-$FutureA*$scale/1.41+$xAxis);

$Future['B']['X'] = round($FutureB*$scale/1.41+$xAxis);

$Future['B']['Y'] = round(-$FutureB*$scale/1.41+$xAxis);

$Future['C']['X'] = round($FutureC*$scale/1.41+$xAxis);

$Future['C']['Y'] = round($FutureC*$scale/1.41+$xAxis);

$Future['D']['X'] = round(-$FutureD*$scale/1.41+$xAxis);

$Future['D']['Y'] = round($FutureD*$scale/1.41+$xAxis);

$Perspective['A']['X'] = round(-$PerspectiveA*$scale/1.41+$xAxis);

$Perspective['A']['Y'] = round(-$PerspectiveA*$scale/1.41+$xAxis);

$Perspective['B']['X'] = round($PerspectiveB*$scale/1.41+$xAxis);

$Perspective['B']['Y'] = round(-$PerspectiveB*$scale/1.41+$xAxis);

$Perspective['C']['X'] = round($PerspectiveC*$scale/1.41+$xAxis);

$Perspective['C']['Y'] = round($PerspectiveC*$scale/1.41+$xAxis);

$Perspective['D']['X'] = round(-$PerspectiveD*$scale/1.41+$xAxis);

$Perspective['D']['Y'] = round($PerspectiveD*$scale/1.41+$xAxis);

//output current state

imagefilledrectangle($im, $Now['A']['X']-2, $Now['A']['Y']-2,$Now['A']['X']+2, $Now['A']['Y']+2, $red);

imagefilledrectangle($im, $Now['B']['X']-2, $Now['B']['Y']-2,$Now['B']['X']+2, $Now['B']['Y']+2, $red);

imagefilledrectangle($im, $Now['C']['X']-2, $Now['C']['Y']-2,$Now['C']['X']+2, $Now['C']['Y']+2, $red);

imagefilledrectangle($im, $Now['D']['X']-2, $Now['D']['Y']-2,$Now['D']['X']+2, $Now['D']['Y']+2, $red);

imageline($im, $Now['A']['X'],

$Now['A']['Y'],

$Now['B']['X'],

$Now['B']['Y'],

$red);

imageline($im, $Now['B']['X'],

$Now['B']['Y'],

$Now['C']['X'],

$Now['C']['Y'],

$red);

imageline($im, $Now['C']['X'],

$Now['C']['Y'],

$Now['D']['X'],

$Now['D']['Y'],

$red);

imageline($im, $Now['D']['X'],

$Now['D']['Y'],

$Now['A']['X'],

$Now['A']['Y'],

$red);

//output desirable state

imagefilledrectangle($im, $Future['A']['X']-2, $Future['A']['Y']-2,$Future['A']['X']+2, $Future['A']['Y']+2, $yellow);

imagefilledrectangle($im, $Future['B']['X']-2, $Future['B']['Y']-2,$Future['B']['X']+2, $Future['B']['Y']+2, $yellow);

imagefilledrectangle($im, $Future['C']['X']-2, $Future['C']['Y']-2,$Future['C']['X']+2, $Future['C']['Y']+2, $yellow);

imagefilledrectangle($im, $Future['D']['X']-2, $Future['D']['Y']-2,$Future['D']['X']+2, $Future['D']['Y']+2, $yellow);

imageline($im, $Future['A']['X'],

$Future['A']['Y'],

$Future['B']['X'],

$Future['B']['Y'],

$yellow);

imageline($im, $Future['B']['X'],

$Future['B']['Y'],

$Future['C']['X'],

$Future['C']['Y'],

$yellow);

imageline($im, $Future['C']['X'],

$Future['C']['Y'],

$Future['D']['X'],

$Future['D']['Y'],

$yellow);

imageline($im, $Future['D']['X'],

$Future['D']['Y'],

$Future['A']['X'],

$Future['A']['Y'],

$yellow);

//output perspective state

imagefilledrectangle($im, $Perspective['A']['X']-2, $Perspective['A']['Y']-2,$Perspective['A']['X']+2, $Perspective['A']['Y']+2, $green);

imagefilledrectangle($im, $Perspective['B']['X']-2, $Perspective['B']['Y']-2,$Perspective['B']['X']+2, $Perspective['B']['Y']+2, $green);

imagefilledrectangle($im, $Perspective['C']['X']-2, $Perspective['C']['Y']-2,$Perspective['C']['X']+2, $Perspective['C']['Y']+2, $green);

imagefilledrectangle($im, $Perspective['D']['X']-2, $Perspective['D']['Y']-2,$Perspective['D']['X']+2, $Perspective['D']['Y']+2, $green);

imageline($im, $Perspective['A']['X'],

$Perspective['A']['Y'],

$Perspective['B']['X'],

$Perspective['B']['Y'],

$green);

imageline($im, $Perspective['B']['X'],

$Perspective['B']['Y'],

$Perspective['C']['X'],

$Perspective['C']['Y'],

$green);

imageline($im, $Perspective['C']['X'],

$Perspective['C']['Y'],

$Perspective['D']['X'],

$Perspective['D']['Y'],

$green);

imageline($im, $Perspective['D']['X'],

$Perspective['D']['Y'],

$Perspective['A']['X'],

$Perspective['A']['Y'],

$green);

imagepng($im);

?>

Крім цього, змінено такі файли:

1. В файлі results.inc, строки 37-50:

elseif (!empty($uid))

{

echo '<div align="center">';

$questionnaire->survey_results_navbar_by_user($uid);

echo '</div>';

echo'<table class = "active"><tr><td>';

$select = 'survey_id = '.$sid.' AND username = '.$uid.' AND complete=\'Y\'';

$resps = get_records_select('questionnaire_response', $select, ‘submitted asc’);

$ret = $questionnaire->view_all_responses($resps);

echo '</td></tr></table>';

echo '<div align="center"><br />';

$questionnaire->survey_results_navbar_by_user($uid);

echo '</div>';

}

генерують сторінку коли обрана навігаця по користувачам.

2. Файл report. php

1. Строка 12. Додано необов'язковий параметр $uid:

$uid = optional_param('uid', false, PARAM_INT);

2. Строка 51. Отримання строки для конкретної мови:

$strviewbyuser = get_string('viewbyuser', 'questionnaire');

3. Строка 81-86. Обробка запиту на виведення відповідей на анаету за користувачами:

case 'viewbyuser':

$qact = 'vuser';

$byuser = true;

$byresponse = false;

$uid = false;

break;

4. Строка 280. Додана обробка запиту на виведення відповідей на анкету за користувачами

case 'vuser':

5. Строки 308-333. Отримання поточного ідентифікатора користувача та його повного імені. Якщо нічого не було передано, то беремо першого:

elseif ($byuser || $uid)

{

if ($uid === false)

{

$users = get_records_sql('SELECT DISTINCT username UID FROM mdl_questionnaire_response ORDER BY submitted');//('questionnaire_response', 'survey_id', $sid, 'id', '*', 0, 1);

$user = current($users);

$uid = $user->UID;

}

/*else

{

$resp = get_record('questionnaire_response', 'id', $rid);

}*/

if (is_numeric($uid)) {

if ($user = get_record('user', 'id', $uid)) {

$ruser = fullname($user);

}

else

{

$ruser = '- '.get_string('unknown', 'questionnaire').' -';

}

}

else

{

$ruser = $uid;

}

}

6. Строки 373-376. Виведення кнопки, яка дає можливість просмотри відповідей за користувачами, якщо це крива акцентів:

if ($questionnaire->has_4scrolls())

echo '<input type="submit" name="viewbyuser" value="'.$strviewbyuser.'" />';

else

echo '<input type="submit" name="viewbyresponse" value="'.$strviewbyresponse.'" />';

3. Файл myreport.php. Строка 103. При виведенні результатів сортуємо їх за датою проходження.

$resps = get_records_select('questionnaire_response', $select, 'submitted asc');

Загальне уявлення про роботу модуля.

I. Виведення опитування.

1. Визначається, чи проходив цей користувач опитування.

i) Якщо так, то скільки разів.

(1) Якщо пройшов 3 рази, то виводимо 3 графіки для кожного разу та еволюцію поглядів.

(2) Якщо менше 3х, то отримуємо всі питання і виводимо їх по черзі. Кожне питання виводиться за домогою класу questionnaire_question. Для кожного типу питання працюють свої методи

ii) Якщо ні, то також виводимо всі питання