ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
All Data Structures Namespaces Files Functions Variables Modules Pages
class.SurveyQuestionEvaluation.php
Go to the documentation of this file.
1 <?php
2 
3 /* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
4 
11 {
15  protected $lng;
16 
20  protected $db;
21 
22  protected $question; // [SurveyQuestion]
23  protected $finished_ids; // [array]
24  protected $chart_width = 400;
25  protected $chart_height = 300;
26 
34  public function __construct(SurveyQuestion $a_question, array $a_finished_ids = null)
35  {
36  global $DIC;
37 
38  $this->lng = $DIC->language();
39  $this->db = $DIC->database();
40  $this->question = $a_question;
41  $this->finished_ids = $a_finished_ids;
42  }
43 
44 
45  //
46  // RESULTS
47  //
48 
54  public function getResults()
55  {
56  $results = new ilSurveyEvaluationResults($this->question);
57  $answers = $this->getAnswerData();
58 
59  $this->parseResults(
60  $results,
61  (array) $answers[0],
62  method_exists($this->question, "getCategories")
63  ? $this->question->getCategories()
64  : null
65  );
66 
67  return $results;
68  }
69 
77  protected function parseResults(ilSurveyEvaluationResults $a_results, array $a_answers, SurveyCategories $a_categories = null)
78  {
79  $num_users_answered = sizeof($a_answers);
80 
81  $a_results->setUsersAnswered($num_users_answered);
82  $a_results->setUsersSkipped($this->getNrOfParticipants() - $num_users_answered);
83 
84  // parse answers
85  $has_multi = false;
86  $selections = array();
87  foreach ($a_answers as $active_id => $answers) {
88  // :TODO:
89  if (sizeof($answers) > 1) {
90  $has_multi = true;
91  }
92  foreach ($answers as $answer) {
93  // map selection value to scale/category
94  if ($a_categories &&
95  $answer["value"] != "") {
96  $scale = $a_categories->getCategoryForScale($answer["value"] + 1);
97  if ($scale instanceof ilSurveyCategory) {
98  $answer["value"] = $scale->scale;
99  }
100  }
101 
102  $parsed = new ilSurveyEvaluationResultsAnswer(
103  $active_id,
104  $answer["value"],
105  $answer["text"]
106  );
107  $a_results->addAnswer($parsed);
108 
109  if ($answer["value"] != "") {
110  $selections[$answer["value"]]++;
111  }
112  }
113  }
114 
115  $total = array_sum($selections);
116 
117  if ($total) {
118  // mode
119  $mode_nr = max($selections);
120  $tmp_mode = $selections;
121  asort($tmp_mode, SORT_NUMERIC);
122  $mode = array_keys($tmp_mode, $mode_nr);
123  $a_results->setMode($mode, $mode_nr);
124 
125  if (!$has_multi) {
126  // median
127  ksort($selections, SORT_NUMERIC);
128  $median = array();
129  foreach ($selections as $value => $count) {
130  for ($i = 0; $i < $count; $i++) {
131  $median[] = $value;
132  }
133  }
134  if ($total % 2 == 0) {
135  $lower = $median[($total / 2) - 1];
136  $upper = $median[($total / 2)];
137  $median_value = 0.5 * ($lower + $upper);
138  if ($a_categories &&
139  round($median_value) != $median_value) {
140  // mapping calculated value to scale values
141  $median_value = array($lower, $upper);
142  }
143  } else {
144  $median_value = $median[(($total + 1) / 2) - 1];
145  }
146  $a_results->setMedian($median_value);
147  }
148  }
149 
150  if ($a_categories) {
151  // selections by category
152  for ($c = 0; $c < $a_categories->getCategoryCount(); $c++) {
153  $cat = $a_categories->getCategory($c);
154  $scale = $cat->scale;
155 
157  $cat,
158  $selections[$scale],
159  $total
160  ? $selections[$scale] / $total
161  : null
162  );
163  $a_results->addVariable($var);
164  }
165  }
166  }
167 
168  public function parseUserSpecificResults($a_qres, $a_user_id)
169  {
170  $parsed_results = array();
171 
172  if (is_array($a_qres)) {
173  foreach ($a_qres as $row_idx => $row_results) {
174  $row_title = $row_results[0];
175  $user_results = $row_results[1]->getUserResults($a_user_id);
176  if ($user_results) {
177  foreach ($user_results as $item) {
178  // :TODO: layout
179  $tmp = $row_title . ": ";
180  if ($item[0] !== "") {
181  $tmp .= $item[0];
182  }
183  if ($item[1] && $item[0]) {
184  $tmp .= ", \"" . nl2br($item[1]) . "\"";
185  } elseif ($item[1]) {
186  $tmp .= "\"" . nl2br($item[1]) . "\"";
187  }
188  $parsed_results[$row_idx . "-" . $item[2]] = $tmp;
189  }
190  }
191  }
192  } else {
193  $user_results = $a_qres->getUserResults($a_user_id);
194  if ($user_results) {
195  foreach ($user_results as $item) {
196  // :TODO: layout
197  if ($item[0] !== "") {
198  $tmp = $item[0];
199  }
200  if ($item[1] && $item[0]) {
201  $tmp .= ", \"" . nl2br($item[1]) . "\"";
202  } elseif ($item[1]) {
203  $tmp = "\"" . nl2br($item[1]) . "\"";
204  }
205  $parsed_results[$item[2]] = $tmp;
206  }
207  }
208  }
209 
210  return $parsed_results;
211  }
212 
213 
214  //
215  // DETAILS
216  //
217 
226  public function getGrid($a_results, $a_abs = true, $a_perc = true)
227  {
228  $lng = $this->lng;
229 
230  if ((bool) $a_abs && (bool) $a_perc) {
231  $cols = array(
232  $lng->txt("category_nr_selected"),
233  $lng->txt("svy_fraction_of_selections")
234  );
235  } elseif ((bool) $a_abs) {
236  $cols = array(
237  $lng->txt("category_nr_selected")
238  );
239  } else {
240  $cols = array(
241  $lng->txt("svy_fraction_of_selections")
242  );
243  }
244 
245  $res = array(
246  "cols" => $cols,
247  "rows" => array()
248  );
249 
250  $vars = $a_results->getVariables();
251  if ($vars) {
252  foreach ($vars as $var) {
253  $perc = $var->perc
254  ? sprintf("%.2f", $var->perc * 100) . "%"
255  : "0%";
256 
257  if ((bool) $a_abs && (bool) $a_perc) {
258  $res["rows"][] = array(
259  $var->cat->title,
260  $var->abs,
261  $perc
262  );
263  } elseif ((bool) $a_abs) {
264  $res["rows"][] = array(
265  $var->cat->title,
266  $var->abs
267  );
268  } else {
269  $res["rows"][] = array(
270  $var->cat->title,
271  $perc
272  );
273  }
274  }
275  }
276 
277  return $res;
278  }
279 
286  public function getTextAnswers($a_results)
287  {
288  return $a_results->getMappedTextAnswers();
289  }
290 
291  protected function getChartColors()
292  {
293  return array(
294  // flot "default" theme
295  "#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed",
296  // http://godsnotwheregodsnot.blogspot.de/2012/09/color-distribution-methodology.html
297  "#1CE6FF", "#FF34FF", "#FF4A46", "#008941", "#006FA6", "#A30059",
298  "#FFDBE5", "#7A4900", "#0000A6", "#63FFAC", "#B79762", "#004D43", "#8FB0FF", "#997D87",
299  "#5A0007", "#809693", "#FEFFE6", "#1B4400", "#4FC601", "#3B5DFF", "#4A3B53", "#FF2F80",
300  "#61615A", "#BA0900", "#6B7900", "#00C2A0", "#FFAA92", "#FF90C9", "#B903AA", "#D16100",
301  "#DDEFFF", "#000035", "#7B4F4B", "#A1C299", "#300018", "#0AA6D8", "#013349", "#00846F",
302  "#372101", "#FFB500", "#C2FFED", "#A079BF", "#CC0744", "#C0B9B2", "#C2FF99", "#001E09",
303  "#00489C", "#6F0062", "#0CBD66", "#EEC3FF", "#456D75", "#B77B68", "#7A87A1", "#788D66",
304  "#885578", "#FAD09F", "#FF8A9A", "#D157A0", "#BEC459", "#456648", "#0086ED", "#886F4C",
305  "#34362D", "#B4A8BD", "#00A6AA", "#452C2C", "#636375", "#A3C8C9", "#FF913F", "#938A81",
306  "#575329", "#00FECF", "#B05B6F", "#8CD0FF", "#3B9700", "#04F757", "#C8A1A1", "#1E6E00",
307  "#7900D7", "#A77500", "#6367A9", "#A05837", "#6B002C", "#772600", "#D790FF", "#9B9700",
308  "#549E79", "#FFF69F", "#201625", "#72418F", "#BC23FF", "#99ADC0", "#3A2465", "#922329",
309  "#5B4534", "#FDE8DC", "#404E55", "#0089A3", "#CB7E98", "#A4E804", "#324E72", "#6A3A4C"
310  );
311  }
312 
319  public function getChart($a_results)
320  {
321  $chart = ilChart::getInstanceByType(ilChart::TYPE_GRID, $a_results->getQuestion()->getId());
322  $chart->setYAxisToInteger(true);
323 
324  $colors = $this->getChartColors();
325  $chart->setColors($colors);
326 
327  // :TODO:
328  $chart->setsize($this->chart_width, $this->chart_height);
329 
330  $vars = $a_results->getVariables();
331 
332  $legend = $labels = array();
333  foreach ($vars as $idx => $var) {
334  $data = $chart->getDataInstance(ilChartGrid::DATA_BARS);
335  $data->setBarOptions(0.5, "center");
336  $data->setFill(1);
337  $chart->addData($data);
338 
339  // labels
340  $labels[$idx] = "";
341  $legend[] = array(
342  $var->cat->title,
343  $colors[$idx]
344  );
345  $data->setLabel($var->cat->title);
346 
347  $data->addPoint($idx, $var->abs);
348  }
349 
350  $chart->setTicks($labels, false, true);
351 
352  return array(
353  $chart->getHTML(),
354  $legend
355  );
356  }
357 
358 
359  //
360  // USER-SPECIFIC
361  //
362 
368  public function getSkippedValue()
369  {
371  }
372 
373 
374  //
375  // HELPER
376  //
377 
378  protected function getSurveyId()
379  {
380  $ilDB = $this->db;
381 
382  // #18968
383  $set = $ilDB->query("SELECT survey_fi" .
384  " FROM svy_svy_qst" .
385  " WHERE question_fi = " . $ilDB->quote($this->question->getId(), "integer"));
386  $row = $ilDB->fetchAssoc($set);
387  return $row["survey_fi"];
388  }
389 
390 
396  protected function getNrOfParticipants()
397  {
398  $ilDB = $this->db;
399 
400  if (is_array($this->finished_ids)) {
401  return sizeof($this->finished_ids);
402  }
403 
404  $set = $ilDB->query("SELECT finished_id FROM svy_finished" .
405  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer"));
406  return $set->numRows();
407  }
408 
409  protected function getAnswerData()
410  {
411  $ilDB = $this->db;
412 
413  $res = array();
414 
415  $sql = "SELECT svy_answer.* FROM svy_answer" .
416  " JOIN svy_finished ON (svy_finished.finished_id = svy_answer.active_fi)" .
417  " WHERE svy_answer.question_fi = " . $ilDB->quote($this->question->getId(), "integer") .
418  " AND svy_finished.survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer");
419  if (is_array($this->finished_ids)) {
420  $sql .= " AND " . $ilDB->in("svy_finished.finished_id", $this->finished_ids, "", "integer");
421  }
422  $set = $ilDB->query($sql);
423  while ($row = $ilDB->fetchAssoc($set)) {
424  $res[(int) $row["rowvalue"]][(int) $row["active_fi"]][] = array(
425  "value" => $row["value"],
426  "text" => $row["textanswer"]
427  );
428  }
429 
430  return $res;
431  }
432 
433 
434  //
435  // EXPORT
436  //
437 
438  public function exportResults($a_results, $a_do_title, $a_do_label)
439  {
440  $question = $a_results->getQuestion();
441 
442  $res = array();
443 
444  if ($a_do_title) {
445  $res[] = $question->getTitle();
446  }
447  if ($a_do_label) {
448  $res[] = $question->label;
449  }
450 
451  $res[] = $question->getQuestiontext();
452  $res[] = SurveyQuestion::_getQuestionTypeName($question->getQuestionType());
453 
454  $res[] = (int) $a_results->getUsersAnswered();
455  $res[] = (int) $a_results->getUsersSkipped();
456 
457  // :TODO:
458  $res[] = is_array($a_results->getModeValue())
459  ? implode(", ", $a_results->getModeValue())
460  : $a_results->getModeValue();
461 
462  $res[] = $a_results->getModeValueAsText();
463  $res[] = (int) $a_results->getModeNrOfSelections();
464 
465  // :TODO:
466  $res[] = $a_results->getMedianAsText();
467 
468  $res[] = $a_results->getMean();
469 
470  return array($res);
471  }
472 
479  public function getExportGrid($a_results)
480  {
481  $lng = $this->lng;
482 
483  $res = array(
484  "cols" => array(
485  $lng->txt("title"),
486  $lng->txt("value"),
487  $lng->txt("category_nr_selected"),
488  $lng->txt("svy_fraction_of_selections")
489  ),
490  "rows" => array()
491  );
492 
493  $vars = $a_results->getVariables();
494  if ($vars) {
495  foreach ($vars as $var) {
496  $res["rows"][] = array(
497  $var->cat->title,
498  $var->cat->scale,
499  $var->abs,
500  $var->perc
501  ? sprintf("%.2f", $var->perc * 100) . "%"
502  : "0%"
503  );
504  }
505  }
506 
507  return $res;
508  }
509 
518  public function getUserSpecificVariableTitles(array &$a_title_row, array &$a_title_row2, $a_do_title, $a_do_label)
519  {
520  // type-specific
521  }
522 
530  abstract public function addUserSpecificResults(array &$a_row, $a_user_id, $a_results);
531 }
getExportGrid($a_results)
Get grid data.
$data
Definition: storeScorm.php:23
static getSurveySkippedValue()
exportResults($a_results, $a_do_title, $a_do_label)
static _getQuestionTypeName($type_tag)
Return the translation for a given question type tag.
getUserSpecificVariableTitles(array &$a_title_row, array &$a_title_row2, $a_do_title, $a_do_label)
Get title columns for user-specific export.
$total
Definition: Utf8Test.php:87
getNrOfParticipants()
Returns the number of participants for a survey.
getGrid($a_results, $a_abs=true, $a_perc=true)
Get grid data.
Class SurveyCategories.
foreach($_POST as $key=> $value) $res
Basic class for all survey question types.
addVariable(ilSurveyEvaluationResultsVariable $a_variable)
setMode($a_value, $a_nr_of_selections)
$results
const TYPE_GRID
parseResults(ilSurveyEvaluationResults $a_results, array $a_answers, SurveyCategories $a_categories=null)
Parse answer data into results instance.
__construct(SurveyQuestion $a_question, array $a_finished_ids=null)
Constructor.
getSkippedValue()
Get caption for skipped value.
global $ilDB
addUserSpecificResults(array &$a_row, $a_user_id, $a_results)
$DIC
Definition: xapitoken.php:46
addAnswer(ilSurveyEvaluationResultsAnswer $a_answer)
Survey category class.
$cols
Definition: xhr_table.php:11
static getInstanceByType($a_type, $a_id)
Get type instance.
$i
Definition: metadata.php:24
getTextAnswers($a_results)
Get text answers.