Skip to content

Commit

Permalink
edu teacher mental map history
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexandr Karachev committed Oct 15, 2024
1 parent 17a3ab9 commit e9703d5
Show file tree
Hide file tree
Showing 8 changed files with 553 additions and 152 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

declare(strict_types=1);

namespace backend\MentalMap\FetchMentalMapUserHistory;

use yii\db\Expression;
use yii\db\Query;

class MentalMapUserHistoryFetcher
{
public function fetch(int $storyId, int $userId): array
{
$subQuery = (new Query())
->select([
'userId' => 'h.user_id',
'mentalMapId' => 'h.mental_map_id',
'imageFragmentId' => 'h.image_fragment_id',
'maxHistoryItemId' => new Expression(
"SUBSTRING_INDEX(GROUP_CONCAT(h.id ORDER BY h.overall_similarity DESC), ',', 1)",
),
])
->from(['h' => 'mental_map_history'])
->where([
'h.story_id' => $storyId,
'h.user_id' => $userId,
])
->groupBy(['h.mental_map_id', 'h.image_fragment_id']);

$historyQuery = (new Query())
->select([
'userId' => 'h.user_id',
'slideId' => 'h.slide_id',
'mentalMapId' => 'h.mental_map_id',
'imageFragmentId' => 'h.image_fragment_id',
'all' => 'h2.overall_similarity',
'hiding' => 'h2.text_hiding_percentage',
'target' => 'h2.text_target_percentage',
'content' => 'h2.content',
'createdAt' => 'h2.created_at',
])
->distinct()
->from(['h' => 'mental_map_history'])
->innerJoin(['t' => $subQuery],
't.userId = h.user_id AND t.mentalMapId = h.mental_map_id AND t.imageFragmentId = h.image_fragment_id')
->innerJoin(['h2' => 'mental_map_history'], 'h2.id = t.maxHistoryItemId')
->where([
'h.story_id' => $storyId,
'h.user_id' => $userId,
])
->groupBy(['h.slide_id', 'h.mental_map_id', 'h.image_fragment_id']);

$query = (new Query())
->select([
't.*',
'userName' => new Expression(
"CASE WHEN p.id IS NULL THEN u.email ELSE CONCAT(p.last_name, ' ', p.first_name) END",
),
'slideNumber' => 's.number',
])
->from(['t' => $historyQuery])
->innerJoin(['s' => 'story_slide'], 't.slideId = s.id')
->innerJoin(['u' => 'user'], 't.userId = u.id')
->leftJoin(['p' => 'profile'], 'u.id = p.user_id');

return array_map(static function (array $row): MentalMapUserHistoryItem {
return new MentalMapUserHistoryItem(
$row['mentalMapId'],
$row['imageFragmentId'],
(int) $row['all'],
(int) $row['hiding'],
(int) $row['target'],
$row['content'],
(int) $row['createdAt'],
);
}, $query->all());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

declare(strict_types=1);

namespace backend\MentalMap\FetchMentalMapUserHistory;

class MentalMapUserHistoryItem
{
/**
* @var string
*/
private $mentalMapId;
/**
* @var string
*/
private $imageFragmentId;
/**
* @var int
*/
private $all;
/**
* @var int
*/
private $hiding;
/**
* @var int
*/
private $target;
/**
* @var string
*/
private $content;
/**
* @var int
*/
private $createdAt;

public function __construct(
string $mentalMapId,
string $imageFragmentId,
int $all,
int $hiding,
int $target,
string $content,
int $createdAt
) {
$this->mentalMapId = $mentalMapId;
$this->imageFragmentId = $imageFragmentId;
$this->all = $all;
$this->hiding = $hiding;
$this->target = $target;
$this->content = $content;
$this->createdAt = $createdAt;
}

public function getMentalMapId(): string
{
return $this->mentalMapId;
}

public function getImageFragmentId(): string
{
return $this->imageFragmentId;
}

public function getAll(): int
{
return $this->all;
}

public function getHiding(): int
{
return $this->hiding;
}

public function getTarget(): int
{
return $this->target;
}

public function getContent(): string
{
return $this->content;
}

public function getCreatedAt(): int
{
return $this->createdAt;
}
}
31 changes: 31 additions & 0 deletions backend/components/story/StoryMentalMapFetcher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace backend\components\story;

use backend\components\story\reader\HTMLReader;

class StoryMentalMapFetcher
{
/**
* @param string $storyData
* @return array<array-key, string>
*/
public function fetch(string $storyData): array {
$story = (new HTMLReader($storyData))->load();
$mentalMapIds = [];
foreach ($story->getSlides() as $slide) {
foreach ($slide->getBlocks() as $block) {
if ($block->isMentalMap()) {
/** @var $block MentalMapBlock */
$content = $block->getContent();
$fragment = \phpQuery::newDocumentHTML($content);
$mentalMapId = $fragment->find('.mental-map')->attr('data-mental-map-id');
$mentalMapIds[] = $mentalMapId;
}
}
}
return $mentalMapIds;
}
}
19 changes: 19 additions & 0 deletions modules/edu/assets/css/edu.css
Original file line number Diff line number Diff line change
Expand Up @@ -408,3 +408,22 @@ a.lesson-item__wrap:hover .lesson-name span {
padding: 0;
height: 100%;
}

.detail-text {

}
.text-item-word {
display: inline-block;
white-space: nowrap;
margin-right: 8px;
user-select: none;
cursor: pointer;
margin-bottom: 6px;
}
.word-target {
font-weight: 600;
}
.text-item-word.selected {
color: #fff;
border: 1px #808080 solid;
}
39 changes: 39 additions & 0 deletions modules/edu/controllers/teacher/DefaultController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

namespace modules\edu\controllers\teacher;

use backend\components\story\StoryMentalMapFetcher;
use backend\MentalMap\FetchMentalMapUserHistory\MentalMapUserHistoryFetcher;
use backend\MentalMap\MentalMap;
use common\models\Story;
use common\models\UserStudent;
use common\rbac\UserRoles;
Expand Down Expand Up @@ -146,4 +149,40 @@ public function actionDetail(int $test_id, int $student_id)
'rows' => $rows,
]);
}

/**
* @throws NotFoundHttpException
*/
public function actionStoryMentalMaps(int $story_id, int $student_id): string
{
if (($story = Story::findOne($story_id)) === null) {
throw new NotFoundHttpException('История не найдена');
}

if (($student = UserStudent::findOne($student_id)) === null) {
throw new NotFoundHttpException('Ученик не найден');
}

$mentalMapIds = (new StoryMentalMapFetcher())->fetch($story->slidesData());

if (count($mentalMapIds) === 0) {
return 'В истории нет ментальных карт';
}

$data = [];
$mentalMaps = [];
foreach ($mentalMapIds as $mentalMapId) {
$mentalMap = MentalMap::findOne($mentalMapId);
if ($mentalMap !== null) {
$mentalMaps[] = $mentalMap;
}
}

$historyData = (new MentalMapUserHistoryFetcher())->fetch($story->id, $student->user_id);

return $this->renderAjax('_mental_maps', [
'mentalMaps' => $mentalMaps,
'historyData' => $historyData,
]);
}
}
71 changes: 71 additions & 0 deletions modules/edu/views/teacher/default/_mental_maps.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

declare(strict_types=1);

use backend\MentalMap\FetchMentalMapUserHistory\MentalMapUserHistoryItem;
use backend\MentalMap\MentalMap;
use common\helpers\SmartDate;
use yii\web\View;

/**
* @var View $this
* @var MentalMap[] $mentalMaps
* @var MentalMapUserHistoryItem[] $historyData
*/
?>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
<h4 class="modal-title">Ментальные карты</h4>
</div>
<div class="modal-body">
<div>
<?php
foreach ($mentalMaps as $mentalMap): ?>
<h3 class="h4"><?= $mentalMap->name; ?></h3>
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<th style="width: 30%">Фрагмент</th>
<th style="width: 30%">Текст при ответе</th>
<th style="width: 10%">% сходства</th>
<th style="width: 10%">% закрытия текста</th>
<th style="width: 10%">% закрытия важного текста</th>
<th style="width: 10%">Дата</th>
</tr>
</thead>
<tbody>
<?php
foreach ($mentalMap->getImages() as $image): ?>
<?php
/** @var MentalMapUserHistoryItem|null $imageData */
$imageData = array_values(
array_filter(
$historyData,
static function (MentalMapUserHistoryItem $item) use ($mentalMap, $image): bool {
return $item->getMentalMapId() === $mentalMap->uuid && $item->getImageFragmentId(
) === $image['id'];
},
),
)[0] ?? null;
if ($imageData === null) {
continue;
}
?>
<tr>
<td><?= $image['text']; ?></td>
<td><?= $imageData->getContent() ?? '-'; ?></td>
<td><?= $imageData->getAll() ?? '-'; ?></td>
<td><?= $imageData->getHiding() ?? '-'; ?></td>
<td><?= $imageData->getTarget() ?? '-' ?></td>
<td><?= SmartDate::dateSmart($imageData->getCreatedAt(), true) ?></td>
</tr>
<?php
endforeach; ?>
</tbody>
</table>
</div>
<?php
endforeach ?>
</div>
</div>
Loading

0 comments on commit e9703d5

Please sign in to comment.