user->identity) && Yii::$app->user->identity->isInRole(\common\models\User::ROLE_STUDENT)) { $this->role = \common\models\User::ROLE_STUDENT; } elseif (isset(Yii::$app->user->identity) && Yii::$app->user->identity->isInRole(\common\models\User::ROLE_TEACHER)) { $this->role = \common\models\User::ROLE_TEACHER; } return parent::beforeAction($action); } public function actionIndex() { $recordbooks = []; $recordbook_id = null; if (Yii::$app->request->isPost) { $buffer = Yii::$app->request->post('recordbook_id'); if (isset($buffer)) { $recordbook_id = $buffer; } } $portfolioLoader = Yii::$app->getModule('student')->portfolioLoader; if ($this->role == User::ROLE_STUDENT) { $recordbooks = $portfolioLoader->loadRecordbooks(); if (!is_array($recordbooks)) { $recordbooks = [$recordbooks]; } if (!empty($recordbooks) && empty($recordbook_id)) { $recordbook_id = $recordbooks[0]->RecordbookId; } } $userId = ArrayHelper::getValue(Yii::$app->user->identity, 'userRef.reference_id'); $result = Yii::$app->soapClientStudent->load( 'GetCurriculumPerfomance', [ 'UserId' => $userId, 'RecordbookId' => $recordbook_id, ] ); $hasError = $this->errorManager($result, $userId, $recordbook_id); if (!$hasError) { $convertedResponse = $this->convertSoapResponse($result); return $this->render( '@common/modules/student/components/chart/views/chart', [ 'hasError' => $hasError, 'recordbooks' => $recordbooks, 'recordbook_id' => $recordbook_id, 'length' => count($convertedResponse['fullDisciplineArray']), 'array' => $this->makeChartSet($convertedResponse['competencyArray'], $convertedResponse['fullDisciplineArray'], 'Результаты освоения основной образовательной программы') ] ); } else { return $this->render( '@common/modules/student/components/chart/views/chart', [ 'hasError' => $hasError, 'recordbooks' => $recordbooks, 'recordbook_id' => $recordbook_id ] ); } } private function errorManager($response, $userId, $recordbook_id) { if (isset($response->return->Error) && count($response->return->Error) > 0) { $errorArray = []; $message = 'Ошибка при выполнении метода GetCurriculumPerfomance: '; $message = str_replace('.', '. ', $message); \Yii::$app->session->setFlash('chartErrorFrom1C', $message); Yii::error("Ошибка выполнения метода GetCurriculumPerfomance ('UserId' = {$userId}, 'RecordbookId = {$recordbook_id})" . PHP_EOL . print_r($errorArray, true)); return true; } return false; } public function convertSoapResponse($response) { $competencyArray = []; $fullDisciplineArray = []; if (isset($response, $response->return->Competencies)) { if (!is_array($response->return->Competencies)) { $response->return->Competencies = [$response->return->Competencies]; } foreach ($response->return->Competencies as $competency) { if (!is_array($competency->Subjects->SubjectCompetenceInfo)) { $competency->Subjects->SubjectCompetenceInfo = [$competency->Subjects->SubjectCompetenceInfo]; } $competencyArray[$competency->CompetenceCode] = []; foreach ($competency->Subjects->SubjectCompetenceInfo as $discipline) { $name = $discipline->Subject->ReferenceName; if ($discipline->Completed == 'true') { $name .= '+'; } else { $name .= '-'; } $competencyArray[$competency->CompetenceCode][] = $name; if (!in_array($name, $fullDisciplineArray)) { if ($discipline->Completed == 'true') { array_unshift($fullDisciplineArray, $name); } else { $fullDisciplineArray[] = $name; } } } } } return ['competencyArray' => $competencyArray, 'fullDisciplineArray' => $fullDisciplineArray]; } public function makeChartSet( $competencyArray = [], $fullDisciplineArray = [], $xAxisLabel = '', $yAxisLabel = '' ): array { $labels = []; $datasets = []; $colorMap = $this->colorGenerator($fullDisciplineArray); if (count($competencyArray) > 0) { $labels = array_keys($competencyArray); foreach ($fullDisciplineArray as $i => $discipline) { $datasets[$i] = []; $datasets[$i]['data'] = []; $datasets[$i]['borderWidth'] = 3; $datasets[$i]['borderSkipped'] = false; $datasets[$i]['backgroundColor'] = $this->chooseColor($discipline, $colorMap[$discipline]); $datasets[$i]['borderColor'] = $colorMap[$discipline]; $datasets[$i]['label'] = substr($discipline, 0, -1); foreach ($competencyArray as $competency) { if (in_array($discipline, $competency)) { $datasets[$i]['data'][] = 100 / count($competency); } else { $datasets[$i]['data'][] = null; } } } } return [ 'type' => 'bar', 'options' => ['id' => 'chart_canvas'], 'clientOptions' => [ 'responsive' => true, 'maintainAspectRatio' => true, 'aspectRatio' => 1.85, 'scales' => [ 'xAxes' => [[ 'stacked' => true, 'scaleLabel' => [ 'display' => true, 'labelString' => $xAxisLabel ] ]], 'yAxes' => [[ 'id' => 'chart_yAxes', 'stacked' => true, 'scaleLabel' => [ 'display' => false, 'labelString' => $yAxisLabel ], 'ticks' => [ 'callback' => new JsExpression('function(value) {return value + " %";}'), 'max' => '100', 'min' => '0' ] ]] ], 'legend' => [ 'display' => false, ], 'tooltips' => [ 'callbacks' => [ 'label' => new JsExpression(' function(tooltipItem, data) { var label = data.datasets[tooltipItem.datasetIndex].label || ""; if (label) { label += ": "; } label += Math.round(tooltipItem.yLabel * 100) / 100 + " %"; return label; } ') ] ] ], 'data' => [ 'labels' => $labels, 'datasets' => $datasets ] ]; } private function colorGenerator($wordsArray, $start = 250, $finish = 800) { $defaultBackgroundColor = ['#024bfd', '#5bb864', '#abc632', '#eb2db8', '#8f70d9', '#0ef7c9', '#a7b149', '#cb6645', '#5813de', '#287c83', '#24e50a', '#b74b3d', '#ad348b', '#1494f1', '#7dd176', '#e3d827', '#d03fc0', '#805ecf', '#07f782', '#958936', '#cc3033', '#331dcc', '#297695', '#65f706', '#c45e6d', '#c03dbe', '#27d0f1', '#76da89', '#f3b014', '#9f3ead', '#534bc0', '#0de53f', '#837c26', '#de0f3d', '#454fc2', '#3f9da7', '#acf60e', '#dd708f', '#d12df0', '#39c6c3', '#64c46e', '#fd6a02']; $H = 0; $colorMap = []; $delta = ($finish - $start) / abs(count($wordsArray) - count($defaultBackgroundColor)); for ($i = 0; $i < count($wordsArray); $i++) { if ($i < count($defaultBackgroundColor)) { $color = $defaultBackgroundColor[$i]; } else { $color = $this->hslToHex([$H, 0.5, $start / 1000]); $start += $delta; $H += 0.618033988749895; $H = $H > 1 ? $H - 1 : $H; } $colorMap[$wordsArray[$i]] = $color; } return $colorMap; } private function chooseColor($choose = '', $color = '') { if (substr($choose, -1) == '+') { return $color; } return '#fff'; } private function hslToHex($hsl) { list($h, $s, $l) = $hsl; if ($s == 0) { $r = $g = $b = 1; } else { $q = $l < 0.5 ? $l * (1 + $s) : $l + $s - $l * $s; $p = 2 * $l - $q; $g = $this->hue2rgb($p, $q, $h); $r = $this->hue2rgb($p, $q, $h + 1 / 3); $b = $this->hue2rgb($p, $q, $h - 1 / 3); } return "#{$this->rgb2hex($r)}{$this->rgb2hex($g)}{$this->rgb2hex($b)}"; } private function hue2rgb($p, $q, $t) { if ($t < 0) { $t += 1; } if ($t > 1) { $t -= 1; } if ($t < 1 / 6) { return $p + ($q - $p) * 6 * $t; } if ($t < 1 / 2) { return $q; } if ($t < 2 / 3) { return $p + ($q - $p) * (2 / 3 - $t) * 6; } return $p; } private function rgb2hex($rgb) { return str_pad(dechex($rgb * 255), 2, '0', STR_PAD_LEFT); } }