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