Your IP : 216.73.216.130


Current Path : /home/forge/stage.sksb.smartcon-survey.com/app/Helpers/
Upload File :
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);
    }
}