Skip to content
Snippets Groups Projects
Commit b6389b54 authored by Marcus Eibrink-Lunzenauer's avatar Marcus Eibrink-Lunzenauer
Browse files

Courseware-Fortschrittseite beschleunigen (SORMless edition)

parent 27d90b64
No related branches found
No related tags found
No related merge requests found
......@@ -131,7 +131,7 @@ class Course_CoursewareController extends AuthenticatedController
return array_combine(array_column($elements, 'id'), $elements);
}
private function computeChildrenOf(iterable $elements): iterable
private function computeChildrenOf(iterable &$elements): iterable
{
$childrenOf = [];
foreach ($elements as $elementId => $element) {
......@@ -149,19 +149,28 @@ class Course_CoursewareController extends AuthenticatedController
private function computeSelfProgresses(
Instance $instance,
User $user,
iterable $elements,
iterable &$elements,
bool $showProgressForAllParticipants
): iterable {
$progress = [];
/** @var \Course $course */
$course = $instance->getRange();
$allBlocks = $instance->findAllBlocksGroupedByStructuralElementId();
$allBlockIds = $instance->findAllBlocksGroupedByStructuralElementId(function ($row) {
return $row['id'];
});
$courseMemberIds = $showProgressForAllParticipants
? array_column($course->getMembersWithStatus('autor'), 'user_id')
: [$user->getId()];
$userProgresses = UserProgress::findBySQL('user_id IN (?)', [$courseMemberIds]);
$sql =
'SELECT block_id, COUNT(grade) as count, SUM(grade) as grade ' .
'FROM cw_user_progresses ' .
'WHERE block_id IN (?) AND user_id IN (?) ' .
'GROUP BY block_id';
$userProgresses = \DBManager::get()->fetchGrouped($sql, [$allBlockIds, $courseMemberIds]);
foreach ($elements as $elementId => $element) {
$selfProgress = $this->getSelfProgresses($allBlocks, $elementId, $userProgresses, $courseMemberIds);
$selfProgress = $this->getSelfProgresses($allBlockIds, $elementId, $userProgresses, $courseMemberIds);
$progress[$elementId] = [
'self' => $selfProgress['counter'] ? $selfProgress['progress'] / $selfProgress['counter'] : 1,
];
......@@ -171,31 +180,35 @@ class Course_CoursewareController extends AuthenticatedController
}
private function getSelfProgresses(
array $allBlocks,
array &$allBlockIds,
string $elementId,
array $userProgresses,
array $courseMemberIds
array &$userProgresses,
array &$courseMemberIds
): array {
$blks = $allBlocks[$elementId] ?: [];
$blks = $allBlockIds[$elementId] ?: [];
if (!count($blks)) {
return [
'counter' => 0,
'progress' => 1,
];
}
$data = [
'counter' => count($blks),
'progress' => 0,
];
$usersCounter = count($courseMemberIds);
foreach ($blks as $blk) {
$progresses = array_filter($userProgresses, function ($progress) use ($blk, $courseMemberIds) {
return $progress->block_id === $blk->getId() && in_array($progress->user_id, $courseMemberIds);
});
$usersProgress = count($progresses) ? array_sum(array_column($progresses, 'grade')) : 0;
$progresses = $userProgresses[$blk];
$usersProgress = $progresses['count'] ? (float) $progresses['sum'] : 0;
$data['progress'] += $usersProgress / $usersCounter;
}
return $data;
}
private function computeCumulativeProgresses(Instance $instance, iterable $elements, iterable $progress): iterable
private function computeCumulativeProgresses(Instance $instance, iterable &$elements, iterable &$progress): iterable
{
$childrenOf = $this->computeChildrenOf($elements);
......@@ -225,7 +238,7 @@ class Course_CoursewareController extends AuthenticatedController
return $progress;
}
private function prepareProgressData(iterable $elements, iterable $progress): iterable
private function prepareProgressData(iterable &$elements, iterable &$progress): iterable
{
$data = [];
foreach ($elements as $elementId => $element) {
......@@ -246,7 +259,7 @@ class Course_CoursewareController extends AuthenticatedController
return $data;
}
private function getChapterCounter(array $chapters): array
private function getChapterCounter(array &$chapters): array
{
$finished = 0;
$started = 0;
......
......@@ -37,12 +37,19 @@ class Instance
$range->getConfiguration()->delete('COURSEWARE_SEQUENTIAL_PROGRESSION');
$range->getConfiguration()->delete('COURSEWARE_EDITING_PERMISSION');
$last_element_configs = \ConfigValue::findBySQL('field = ? AND value LIKE ?', ['COURSEWARE_LAST_ELEMENT', '%'.$range->getRangeId().'%']);
$last_element_configs = \ConfigValue::findBySQL('field = ? AND value LIKE ?', [
'COURSEWARE_LAST_ELEMENT',
'%' . $range->getRangeId() . '%',
]);
foreach ($last_element_configs as $config) {
$arr = json_decode($config->value, true);
$arr = array_filter($arr, function ($key) use ($range) {
return $key !== $range->id;
}, ARRAY_FILTER_USE_KEY);
$arr = array_filter(
$arr,
function ($key) use ($range) {
return $key !== $range->id;
},
ARRAY_FILTER_USE_KEY
);
\UserConfig::get($config->range_id)->unsetValue('COURSEWARE_LAST_ELEMENT');
\UserConfig::get($config->range_id)->store('COURSEWARE_LAST_ELEMENT', $arr);
}
......@@ -270,8 +277,23 @@ class Instance
return $data;
}
public function findAllBlocksGroupedByStructuralElementId(): iterable
/**
* Find all blocks of this instance and group them by their structural element's ID.
* You may specify your own `$formatter` instead of the default one which stores the blocks as instances of \Courseware\Block.
*
* @param ?callable(array $row): mixed $formatter Provide your own callable if you need something else instead of
* full-blown instances of \Courseware\Block.
* @return iterable all the (optionally formatted) blocks grouped by the IDs of the structural element containing
* that block.
*/
public function findAllBlocksGroupedByStructuralElementId(callable $formatter = null): iterable
{
if (!$formatter) {
$formatter = function ($row) {
return \Courseware\Block::build($row, false);
};
}
$sql = 'SELECT se.id AS structural_element_id, b.*
FROM cw_structural_elements se
JOIN cw_containers c ON se.id = c.structural_element_id
......@@ -286,11 +308,10 @@ class Instance
$structuralElementId = $row['structural_element_id'];
unset($row['structural_element_id']);
$block = \Courseware\Block::build($row, false);
if (!isset($data[$structuralElementId])) {
$data[$structuralElementId] = [];
}
$data[$structuralElementId][] = $block;
$data[$structuralElementId][] = $formatter($row);
}
return $data;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment