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