| Current Path : /home/forge/stage.sksb.smartcon-survey.com/app/Helpers/ |
| Current File : /home/forge/stage.sksb.smartcon-survey.com/app/Helpers/SurveyJSHelper.php |
<?php
namespace App\Helpers;
use App\Models\Topic;
use Illuminate\Database\Eloquent\Collection;
// TODO: Refactor SurveyJSHelper
class SurveyJSHelper
{
private string $surveyJson;
private array $results = [];
private Topic $topic;
private Collection $interviews;
public function __construct(?Topic $topic = null)
{
if ($topic != null) {
$this->topic = $topic;
$this->setSurveyJson($topic->surveyJson);
}
}
/**
* @return mixed
*/
public function getSurveyJson(): string
{
return $this->surveyJson;
}
/**
* @param mixed $surveyJson
*/
public function setSurveyJson(string $surveyJson): void
{
$this->surveyJson = $surveyJson;
}
/**
* @return array Convert [1 => 10, 2 => 13, 3 => 5]
*
* Convert [1 => 10, 2 => 13, 3 => 5]
* to [
* ['name' => 1, data => [10]],
* ]
* For Frontend Chart Library
*/
public static function toSeries(array $results, ?array $labels = null, array $colors = ['#4CAF50', '#8BC34A', '#FFEB3B', '#FFC107', '#F44336']): array
{
$series = [];
foreach ($results as $key => $value) {
if ($labels === null) {
$series[] = [
'data' => [$value],
'name' => '',
'color' => $colors[$key - 1],
];
} else {
$series[] = [
'data' => [$value],
'name' => $labels[$key - 1],
'color' => $colors[$key - 1],
];
}
}
return $series;
}
public function setResults(Topic $topic, Collection $filteredInterviews): SurveyJSHelper
{
$this->topic = $topic;
$this->interviews = $filteredInterviews;
$this->setSurveyJson($this->topic->surveyJson);
$questions = $this->getQuestions();
$this->results['questions'] = $this->getQuestionsResults($questions, $this->interviews);
$this->results['index'] = $this->getIndexValues($this->results['questions']);
return $this;
}
public function addMessings(array &$results): array
{
// fill empty (e.g. nobody picked the 5 so its not in the $results] array
foreach (range(1, 5) as $value) {
if (! isset($results[$value])) {
$results[$value] = '0';
}
}
ksort($results);
return $results;
}
private function getQuestionsResults(array $questions, Collection $interviews): array
{
$results = array_map(function ($question) use ($interviews) {
if (str_contains($question['name'], 'question')) {
return null;
}
$question['results'] = $this->getQuestionResults($question['name'], $interviews);
return $question;
}, $questions);
return array_filter($results);
}
private function getQuestionResults(string $questionName, Collection $interviews): array
{
// collect values
$currentResult = $interviews->map(function ($interview) use ($questionName) {
$answers = json_decode($interview->answers, true);
return $answers[$questionName] ?? null; // e.g. "f1_3"
});
$results = $currentResult->filter()->countBy()->all();
$this->addMessings($results);
return $results;
}
private function getIndexValues(array $questions): array
{
$index = [
1 => '0',
2 => '0',
3 => '0',
4 => '0',
5 => '0',
99 => '0',
];
foreach ($questions as $question) {
foreach ($question['results'] as $key => $value) {
if ($value > 0) {
$index[$key] = (int) $index[$key] + $value;
}
}
}
return $index;
}
public function getResults(?Topic $topic = null, ?Collection $interviews = null): array
{
if (! is_null($topic) && ! is_null($interviews)) {
$this->setResults($topic, $interviews);
}
return $this->results;
}
public function getResultsForExcel(): array
{
$sheets = [];
if (count($this->results['questions']) > 1) {
$sheets['index'] = [
['Index', 'Sehr unzufrieden', 'Unzufrieden', 'Teils/Teils', 'Zufrieden', 'Sehr zufrieden', 'Average'],
['Percentage', ...$this->percentage($this->results['index'])],
['Total', ...$this->results['index'], $this->results['indexAverage']],
];
foreach ($this->results['departmentsIndex'] as $key => $depIndex) {
$sheets['index'][] = [$key, ...$depIndex];
}
}
$index = 1;
foreach ($this->results['questions'] as $question) {
$sheetName = 'Frage '.$index;
$sheets[$sheetName] = [
[$question['title'], ...$question['labels'], 'Average'],
['Percentage', ...$this->percentage($question['results'])],
['Total', ...$question['results'], $question['average']],
];
foreach ($question['departments'] as $dep) {
$sheets[$sheetName][] = [$dep['name'], ...$dep['results'], $dep['average']];
}
$index++;
}
return $sheets;
}
public function getCommentQuestions(): array
{
$surveyData = json_decode($this->surveyJson, true);
$questions = [];
foreach ($surveyData['pages'] as $page) {
foreach ($page['elements'] as $element) {
if ($element['type'] == 'comment') { // we don't need these two
$questions[] = [
'name' => $element['name'],
'title' => $element['title'], // e.g.: wie gefällt ihnen ihre Arbeit?
'type' => $element['type'], // e.g.: 1, 2, 3, 4, 5
];
}
}
}
return $questions;
}
public function getQuestions(): array
{
$surveyData = json_decode($this->surveyJson, true);
$questions = [];
foreach ($surveyData['pages'] as $page) {
foreach ($page['elements'] as $element) {
if (! in_array($element['type'], ['html', 'comment', 'expression']) && ! in_array($element['name'], ['f4a_1'])) { // we don't need these two
$questions[] = [
'name' => $element['name'],
'title' => $element['title'], // e.g.: wie gefällt ihnen ihre Arbeit?
'type' => $element['type'],
'labels' => array_map(fn ($choice) => $choice['text'] ?? '', $element['choices']), // e.g.: Sehr zufrieden, weniger zufrieden
'values' => array_map(fn ($choice) => $choice['value'] ?? $choice, $element['choices']), // e.g.: 1, 2, 3, 4, 5
];
}
}
}
return $questions;
}
public function addAverage(): SurveyJSHelper
{
$this->results['indexAverage'] = $this->getAverage($this->results['index']);
if (isset($this->results['departmentsIndex'])) {
$this->results['departmentsIndex'] = array_map(function ($dep) {
$dep['average'] = $this->getAverage($dep);
return $dep;
}, $this->results['departmentsIndex']);
}
$this->results['questions'] = array_map(function ($question) {
$question['average'] = $this->getAverage($question['results']);
if (isset($question['departments'])) {
$question['departments'] = array_map(function ($dep) {
$dep['average'] = $this->getAverage($dep['results']);
return $dep;
}, $question['departments']);
}
return $question;
}, $this->results['questions']);
return $this;
}
private function getAverage(array $values): string
{
$all_values = [];
foreach ($values as $key => $value) {
if ($value > 0) {
foreach (range(1, $value) as $count) {
$mappedKey = $key;
$all_values[] = $mappedKey;
}
}
}
return count($all_values) == 0 ? '0' : number_format((array_sum($all_values) / count($all_values)), 1, ',');
}
public function addDepartments(array $departments): SurveyJSHelper
{
$this->results['questions'] = array_map(function ($question) use ($departments) {
$question['departments'] = array_map(function ($dep) use ($question) {
$results = [
'id' => $dep['id'],
'name' => $dep['name'],
];
$interviews = $this->interviews->filter(fn ($interview) => in_array((int) $interview['department'], $dep['filters'], true));
$results['results'] = $this->getQuestionResults($question['name'], $interviews);
return $results;
}, $departments);
return $question;
}, $this->results['questions']);
$this->results['departmentsIndex'] = $this->getDepartmentsIndex($departments);
return $this;
}
private function getDepartmentsIndex(array $departments): array
{
$results = [];
foreach ($departments as $dep) {
$depIndex = [
1 => '0',
2 => '0',
3 => '0',
4 => '0',
5 => '0',
];
foreach ($this->results['questions'] as $question) {
foreach ($question['departments'] as $department) {
if ($dep['id'] === $department['id']) {
foreach ($department['results'] as $key => $value) {
if ($value > 0) {
$depIndex[$key] = (int) $depIndex[$key] + $value;
}
}
}
}
}
$results[$dep['name']] = $depIndex;
}
return $results;
}
private function percentage(array $array): array
{
$total = array_sum($array);
return array_map(fn ($value) => $total > 0 ? round((int) $value * 100 / $total).'%' : '0%', $array);
}
}