questlab/models/QuestgroupsModel.inc

1048 lines
40 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Questlab
*
* @author Oliver Hanraths <oliver.hanraths@uni-duesseldorf.de>
* @copyright 2014 2016 Heinrich-Heine-Universität Düsseldorf
* @license http://www.gnu.org/licenses/gpl.html
* @link https://github.com/coderkun/questlab
*/
namespace hhu\z\models;
/**
* Model to interact with Questgroups-table.
*
* @author Oliver Hanraths <oliver.hanraths@uni-duesseldorf.de>
*/
class QuestgroupsModel extends \hhu\z\Model
{
/**
* Questgroup-status: Entered
*
* @var int;
*/
const QUESTGROUP_STATUS_ENTERED = 0;
/**
* Required models
*
* @var array
*/
public $models = array('questgroupshierarchy', 'questgrouptexts', 'quests', 'questtexts', 'media');
/**
* Construct a new QuestgroupsModel.
*/
public function __construct()
{
parent::__construct();
}
/**
* Get all Questgroups for a Questgroup hierarchy.
*
* @param int $hierarchyId ID of the Questgroup hierarchy to get Questgroups for
* @param int $parentQuestgroupId ID of the parent Questgroup hierarchy
* @return array Questgroups for the given hierarchy
*/
public function getQuestgroupsForHierarchy($hierarchyId, $parentQuestgroupId=null)
{
// Get Questgroups
$questgroups = array();
if(is_null($parentQuestgroupId))
{
$questgroups = $this->db->query(
'SELECT questgroups.id, questgroups_questgroupshierarchy.questgroupshierarchy_id, questgroups_questgroupshierarchy.pos, questgroups.title, questgroups.url, questgroups.questgroupspicture_id, questgroups.achievable_xps '.
'FROM questgroups_questgroupshierarchy '.
'INNER JOIN questgroups ON questgroups.id = questgroups_questgroupshierarchy.questgroup_id '.
'WHERE questgroups_questgroupshierarchy.questgroupshierarchy_id = ? AND questgroups_questgroupshierarchy.parent_questgroup_id IS NULL '.
'ORDER BY questgroups_questgroupshierarchy.pos ASC',
'i',
$hierarchyId
);
}
else
{
$questgroups = $this->db->query(
'SELECT questgroups.id, questgroups_questgroupshierarchy.questgroupshierarchy_id, questgroups_questgroupshierarchy.pos, questgroups.title, questgroups.url, questgroups.questgroupspicture_id, questgroups.achievable_xps '.
'FROM questgroups_questgroupshierarchy '.
'INNER JOIN questgroups ON questgroups.id = questgroups_questgroupshierarchy.questgroup_id '.
'WHERE questgroups_questgroupshierarchy.questgroupshierarchy_id = ? AND questgroups_questgroupshierarchy.parent_questgroup_id = ? '.
'ORDER BY questgroups_questgroupshierarchy.pos ASC',
'ii',
$hierarchyId, $parentQuestgroupId
);
}
// Return Questgroups
return $questgroups;
}
/**
* Get all Questgroups for a Seminary.
*
* @param int $seminaryId ID of Seminary
* @return array List of Questgroups
*/
public function getQuestgroupsForSeminary($seminaryId)
{
return $this->db->query(
'SELECT id, title, url, questgroupspicture_id, achievable_xps '.
'FROM questgroups '.
'WHERE seminary_id = ? '.
'ORDER BY title ASC',
'i',
$seminaryId
);
}
/**
* Get a Questgroup by its ID.
*
* @throws \nre\exceptions\IdNotFoundException
* @param int $questgroupId ID of a Questgroup
* @return array Questgroup data
*/
public function getQuestgroupById($questgroupId)
{
$data = $this->db->query(
'SELECT id, title, url, questgroupspicture_id, achievable_xps '.
'FROM questgroups '.
'WHERE questgroups.id = ?',
'i',
$questgroupId
);
if(empty($data)) {
throw new \nre\exceptions\IdNotFoundException($questgroupId);
}
return $data[0];
}
/**
* Get a Questgroup by its URL.
*
* @throws \nre\exceptions\IdNotFoundException
* @param int $seminaryId ID of the corresponding seminary
* @param string $questgroupUrl URL-title of a Questgroup
* @return array Questgroup data
*/
public function getQuestgroupByUrl($seminaryId, $questgroupUrl)
{
$data = $this->db->query(
'SELECT id, title, url, questgroupspicture_id, achievable_xps '.
'FROM questgroups '.
'WHERE seminary_id = ? AND url = ?',
'is',
$seminaryId, $questgroupUrl
);
if(empty($data)) {
throw new \nre\exceptions\IdNotFoundException($questgroupUrl);
}
return $data[0];
}
/**
* Get the next Questgroup.
*
* Determine the next Questgroup. If there is no next Questgroup
* on the same level as the given Quest then the followed-up
* Questgroup from a higher hierarchy level is returned.
*
* @param int $seminaryId ID of Seminary
* @param int $questgroupId ID of Questgroup to get next Questgroup of
* @return array Questgroup data
*/
public function getNextQuestgroup($seminaryId, $questgroupId)
{
$currentQuestgroup = $this->getQuestgroupById($questgroupId);
$currentQuestgroup['hierarchy'] = $this->Questgroupshierarchy->getHierarchyForQuestgroup($currentQuestgroup['id']);
if(empty($currentQuestgroup['hierarchy'])) {
return null;
}
$nextQuestgroup = $this->_getNextQuestgroup($seminaryId, $currentQuestgroup['hierarchy']['parent_questgroup_id'], $currentQuestgroup['hierarchy']['questgroup_pos']);
if(is_null($nextQuestgroup) && !is_null($currentQuestgroup['hierarchy']['parent_questgroup_id'])) {
$nextQuestgroup = $this->getNextQuestgroup($seminaryId, $currentQuestgroup['hierarchy']['parent_questgroup_id']);
}
return $nextQuestgroup;
}
/**
* Get the previous Questgroup.
*
* Determine the previous Questgroup. If there is no previous
* Questgroup on the same level as the given Quest then the
* followed-up Questgroup from a higher hierarchy level is
* returned.
*
* @param int $seminaryId ID of Seminary
* @param int $questgroupId ID of Questgroup to get previous Questgroup of
* @return array Questgroup data
*/
public function getPreviousQuestgroup($seminaryId, $questgroupId)
{
$currentQuestgroup = $this->getQuestgroupById($questgroupId);
$currentQuestgroup['hierarchy'] = $this->Questgroupshierarchy->getHierarchyForQuestgroup($currentQuestgroup['id']);
if(empty($currentQuestgroup['hierarchy'])) {
return null;
}
$previousQuestgroup = $this->_getPreviousQuestgroup($seminaryId, $currentQuestgroup['hierarchy']['parent_questgroup_id'], $currentQuestgroup['hierarchy']['questgroup_pos']);
if(is_null($previousQuestgroup) && !is_null($currentQuestgroup['hierarchy']['parent_questgroup_id'])) {
$previousQuestgroup = $this->getPreviousQuestgroup($seminaryId, $currentQuestgroup['hierarchy']['parent_questgroup_id']);
}
return $previousQuestgroup;
}
/**
* Mark a Questgroup as entered for a Character.
*
* @param int $questgroupId ID of Questgroup to mark as entered
* @param int $characterId ID of Character that entered the Quest
*/
public function setQuestgroupEntered($questgroupId, $characterId)
{
$this->setQuestgroupStatus($questgroupId, $characterId, self::QUESTGROUP_STATUS_ENTERED, false);
}
/**
* Determine if the given Character has entered a Questgroup.
*
* @param int $questgroupId ID of Questgroup to check
* @param int $characterId ID of Character to check
* @result boolean Whether Character has entered the Questgroup or not
*/
public function hasCharacterEnteredQuestgroup($questgroupId, $characterId)
{
$count = $this->db->query(
'SELECT count(id) AS c '.
'FROM questgroups_characters '.
'WHERE questgroup_id = ? AND character_id = ? AND status IN (?)',
'iii',
$questgroupId,
$characterId,
self::QUESTGROUP_STATUS_ENTERED
);
return (!empty($count) && intval($count[0]['c']) > 0);
}
/**
* Determine if the given Character has solved a Questgroup.
*
* @param int $questgroupId ID of Questgroup to check
* @param int $characterId ID of Character to check
* @result boolean Whether Character has solved the Questgroup or not
*/
public function hasCharacterSolvedQuestgroup($questgroupId, $characterId)
{
// Get data of Questgroup
$questgroup = $this->getQuestgroupById($questgroupId);
$questgroup['hierarchy'] = $this->Questgroupshierarchy->getHierarchyForQuestgroup($questgroup['id']);
// Check last Quest(s) of this Questgroup
$solvedLastQuest = false;
$lastQuests = $this->Quests->getLastQuestsOfQuestgroup($questgroup['id']);
// Check last Quest(s) of last child Questgroup
if(empty($lastQuests) && !empty($questgroup['hierarchy']))
{
$childQuestgroupshierarchy = $this->Questgroupshierarchy->getChildQuestgroupshierarchy($questgroup['hierarchy']['id']);
if(!empty($childQuestgroupshierarchy))
{
$childQuestgroupshierarchy = array_pop($childQuestgroupshierarchy);
$childQuestgroups = $this->getQuestgroupsForHierarchy($childQuestgroupshierarchy['id'], $questgroupId);
if(!empty($childQuestgroups))
{
$childQuestgroup = array_pop($childQuestgroups);
$lastQuests = $this->Quests->getLastQuestsOfQuestgroup($childQuestgroup['id']);
}
}
}
foreach($lastQuests as &$lastQuest)
{
if($this->Quests->hasCharacterSolvedQuest($lastQuest['id'], $characterId))
{
$solvedLastQuest = true;
break;
}
}
if(!$solvedLastQuest) {
return false;
}
// Check all child Questgroups
if(!empty($questgroup['hierarchy']))
{
$childQuestgroupshierarchy = $this->Questgroupshierarchy->getChildQuestgroupshierarchy($questgroup['hierarchy']['id']);
foreach($childQuestgroupshierarchy as &$hierarchy)
{
// Get Questgroups
$questgroups = $this->getQuestgroupsForHierarchy($hierarchy['id'], $questgroup['id']);
foreach($questgroups as &$group) {
if(!$this->hasCharacterSolvedQuestgroup($group['id'], $characterId)) {
return false;
}
}
}
}
return true;
}
/**
* Get all related Questgroups of a Questtext.
*
* @param int $questtextId ID of the Questtext
* @return array Related Questgroups for the Questtext
*/
public function getRelatedQuestsgroupsOfQuesttext($questtextId)
{
return $this->db->query(
'SELECT questgroups.id, questgroups_questtexts.questtext_id, questgroups.title, questgroups.url, questgroups_questtexts.entry_text '.
'FROM questgroups_questtexts '.
'INNER JOIN questgroups ON questgroups.id = questgroups_questtexts.questgroup_id '.
'WHERE questgroups_questtexts.questtext_id = ?',
'i',
$questtextId
);
}
/**
* Get all related Questgroups of a Quest.
*
* @param int $questId ID of the Quest
* @return array Related Quests for the Quest
*/
public function getRelatedQuestsgroupsOfQuest($questId)
{
return $this->db->query(
'SELECT questgroups_questtexts.questgroup_id AS id '.
'FROM quests '.
'INNER JOIN questtexts ON questtexts.quest_id = quests.id '.
'INNER JOIN questgroups_questtexts ON questgroups_questtexts.questtext_id = questtexts.id '.
'WHERE quests.id = ?',
'i',
$questId
);
}
/**
* Get all related Questgroups of a Questgroup.
*
* @param int $questgroupId ID of the Questgroup
* @return array Related Questgroups for the Questgroup
*/
public function getRelatedQuestsgroupsOfQuestgroup($questgroupId)
{
return $this->db->query(
'SELECT DISTINCT questgroups_questtexts.questgroup_id AS id '.
'FROM questgroups '.
'INNER JOIN quests ON quests.questgroup_id = questgroups.id '.
'INNER JOIN questtexts ON questtexts.quest_id = quests.id '.
'INNER JOIN questgroups_questtexts ON questgroups_questtexts.questtext_id = questtexts.id '.
'WHERE questgroups.id = ?',
'i',
$questgroupId
);
}
/**
* Summarize XPs of all Quests for a Questgroup and its
* sub-Questgroups solved by a Character.
*
* @param int $questgroupId ID of Questgroup
* @param int $characterId ID of Character
* @return int Sum of XPs
*/
public function getAchievedXPsForQuestgroup($questgroupId, $characterId)
{
// Questgroup
$xps = $this->_getAchievedXPsForQuestgroup($questgroupId, $characterId);
// Related Questgroups
foreach($this->getRelatedQuestsgroupsOfQuestgroup($questgroupId) as $relatedQuestgroup) {
$xps += $this->getAchievedXPsForQuestgroup($relatedQuestgroup['id'], $characterId);
}
// XPs of child Questgroups
$questgroupHierarchy = $this->Questgroupshierarchy->getHierarchyForQuestgroup($questgroupId);
if(!empty($questgroupHierarchy))
{
$childQuestgroupshierarchy = $this->Questgroupshierarchy->getChildQuestgroupshierarchy($questgroupHierarchy['id']);
foreach($childQuestgroupshierarchy as &$hierarchy)
{
$childQuestgroups = $this->getQuestgroupsForHierarchy($hierarchy['id'], $questgroupId);
foreach($childQuestgroups as &$childQuestgroup) {
$xps += $this->getAchievedXPsForQuestgroup($childQuestgroup['id'], $characterId);
}
}
}
return $xps;
}
/**
* Check if a Questgroups title already exists for a Seminary.
*
* @param int $seminaryId ID of Seminary
* @param string $title Questgroup title to check
* @param int $questgroupId Do not check this ID (for editing)
* @return boolean Whether Questgroup title exists or not
*/
public function questgroupTitleExists($seminaryId, $title, $questgroupId=null)
{
$data = $this->db->query(
'SELECT id '.
'FROM questgroups '.
'WHERE seminary_id = ? AND (title = ? OR url = ?)',
'iss',
$seminaryId,
$title,
\nre\core\Linker::createLinkParam($title)
);
return (!empty($data) && (is_null($questgroupId) || $questgroupId != $data[0]['id']));
}
/**
* Create a new Questgroup.
*
* @param int $userId User-ID that creates the new character
* @param int $seminaryId ID of Seminary
* @param string $title Title for new Questgroup
* @return int ID of new Questgroup
*/
public function createQuestgroup($userId, $seminaryId, $title)
{
$this->db->query(
'INSERT INTO questgroups '.
'(created_user_id, seminary_id, title, url) '.
'VALUES '.
'(?, ?, ?, ?)',
'iiss',
$userId,
$seminaryId,
$title,
\nre\core\Linker::createLinkParam($title)
);
return $this->db->getInsertId();
}
/**
* Set the moodpic for a Questgroup.
*
* @param int $questgroupId ID of Questgroup to set moodpic for
* @param int $mediaId ID of moodpic media
*/
public function setMoodpicForQuestgroup($questgroupId, $mediaId)
{
$this->db->query(
'UPDATE questgroups '.
'SET questgroupspicture_id = ? '.
'WHERE id = ?',
'ii',
$mediaId,
$questgroupId
);
}
/**
* Add a Questgroup to a Questgroupshierarchy.
*
* @param int $questgroupId Id of Questgroup to add
* @param int $hierarchyId Id of Hierarchy to add Questgroup to
* @param int $parentQuestgroupId Id of parent Questgroup
*/
public function addQuestgroupToHierarchy($questgroupId, $hierarchyId, $parentQuestgroupId)
{
// Get last position
$pos = $this->db->query(
'SELECT COALESCE(MAX(pos),0) AS pos '.
'FROM questgroups_questgroupshierarchy '.
'WHERE questgroupshierarchy_id = ? AND '.
'parent_questgroup_id '.(!is_null($parentQuestgroupId) ? sprintf('= %d', $parentQuestgroupId) : 'IS NULL'),
'i',
$hierarchyId
);
$pos = intval($pos[0]['pos']);
// Add Questgroup to Hierarchy
$this->db->query(
'INSERT INTO questgroups_questgroupshierarchy '.
'(questgroup_id, questgroupshierarchy_id, parent_questgroup_id, pos) '.
'VALUES '.
'(?, ?, ?, ?)',
'iiii',
$questgroupId,
$hierarchyId,
$parentQuestgroupId,
$pos + 1
);
}
/**
* Copy Questgroupshierarchy of Questgroups from a Seminary.
*
* @param array $questgroupshierarchyIds Mapping of hierarchy-IDs from source Seminary to target Seminary
* @param array $questgroupIds Mapping of Questgroup-IDs from source Seminary to target Seminary
*/
public function copyQuestgroupsHierarchy($questgroupshierarchyIds, $questgroupIds)
{
foreach($questgroupIds as $sourceQuestgroupId => $targetQuestgroupId)
{
$hierarchy = $this->Questgroupshierarchy->getHierarchyForQuestgroup($sourceQuestgroupId);
if(!is_null($hierarchy))
{
if(is_null($hierarchy['parent_questgroup_id']))
{
$this->db->query(
'INSERT INTO questgroups_questgroupshierarchy '.
'(questgroup_id, questgroupshierarchy_id, parent_questgroup_id, pos) '.
'VALUES '.
'(?, ?, null, ?)',
'iii',
$targetQuestgroupId,
$questgroupshierarchyIds[$hierarchy['id']],
$hierarchy['questgroup_pos']
);
}
else
{
$this->db->query(
'INSERT INTO questgroups_questgroupshierarchy '.
'(questgroup_id, questgroupshierarchy_id, parent_questgroup_id, pos) '.
'VALUES '.
'(?, ?, ?, ?)',
'iiii',
$targetQuestgroupId,
$questgroupshierarchyIds[$hierarchy['id']],
$questgroupIds[$hierarchy['parent_questgroup_id']],
$hierarchy['questgroup_pos']
);
}
}
}
}
/**
* Copy all related Questgroups of Questtexts of a Seminary.
*
* @param array $questgroupIds Mapping of Questgroup-IDs from source Seminary to target Seminary
* @param array $questtextIds Mapping of Questtext-IDs from source Seminary to target Seminary
*/
public function copyRelatedQuestgroups($questgroupIds, $questtextIds)
{
foreach($questgroupIds as $sourceQuestgroupId => $targetQuestgroupId)
{
$questtexts = $this->Questtexts->getRelatedQuesttextsForQuestgroup($sourceQuestgroupId);
foreach($questtexts as &$questtext)
{
$this->db->query(
'INSERT INTO questgroups_questtexts '.
'(questgroup_id, questtext_id, entry_text) '.
'SELECT ?, ?, entry_text '.
'FROM questgroups_questtexts '.
'WHERE questgroup_id = ? AND questtext_id = ?',
'iiii',
$targetQuestgroupId, $questtextIds[$questtext['id']],
$sourceQuestgroupId, $questtext['id']
);
}
}
}
/**
* Move a Questgroup up (decrement position) or down (increment
* position).
*
* @param array $questgroup Questgroup to move
* @param boolean $up True for moving up, false for down
*/
public function moveQuestgroup($questgroup, $up)
{
$this->db->setAutocommit(false);
try {
// Set temporary position
$this->db->query(
'UPDATE questgroups_questgroupshierarchy '.
'SET pos = 0 '.
'WHERE questgroup_id = ?',
'i',
$questgroup['id']
);
// Switch entry
if(is_null($questgroup['hierarchy']['parent_questgroup_id'])) {
$this->db->query(
'UPDATE questgroups_questgroupshierarchy '.
'SET pos = ? '.
'WHERE questgroupshierarchy_id = ? AND parent_questgroup_id IS NULL AND pos = ?',
'iii',
$questgroup['hierarchy']['questgroup_pos'],
$questgroup['hierarchy']['id'],
$questgroup['hierarchy']['questgroup_pos'] + ($up ? -1 : 1)
);
}
else {
$this->db->query(
'UPDATE questgroups_questgroupshierarchy '.
'SET pos = ? '.
'WHERE questgroupshierarchy_id = ? AND parent_questgroup_id = ? AND pos = ?',
'iiii',
$questgroup['hierarchy']['questgroup_pos'],
$questgroup['hierarchy']['id'],
$questgroup['hierarchy']['parent_questgroup_id'],
$questgroup['hierarchy']['questgroup_pos'] + ($up ? -1 : 1)
);
}
// Set new position
$this->db->query(
'UPDATE questgroups_questgroupshierarchy '.
'SET pos = ? '.
'WHERE questgroup_id = ?',
'ii',
$questgroup['hierarchy']['questgroup_pos'] + ($up ? -1 : 1),
$questgroup['id']
);
$this->db->commit();
}
catch(\nre\exceptions\DatamodelException $e) {
$this->db->rollback();
$this->db->setAutocommit(true);
throw $e;
}
$this->db->setAutocommit(true);
}
/**
* Edit a Questgroup.
*
* @throws \nre\exceptions\DatamodelException
* @param int $questgroupId ID of Questgroup to edit
* @param string $title New title of Questgroup
*/
public function editQuestgroup($questgroupId, $title)
{
$this->db->query(
'UPDATE questgroups '.
'SET title = ?, url = ? '.
'WHERE id = ?',
'ssi',
$title,
\nre\core\Linker::createLinkParam($title),
$questgroupId
);
}
/**
* Copy Questgroups of Seminary.
*
* @throws \nre\exceptions\DatamodelException
* @param int $userId ID of creating user
* @param int $sourceSeminaryId ID of Seminary to copy Questgroups from
* @param int $targetSeminaryId ID of Seminary to copy Questgroups to
* @param array $questgroupshierarchyIds Mapping of hierarchy-IDs from source Seminary to target Seminary
* @param array $seminaryMediaIds Mapping of Seminary-media-IDs from source Seminary to target Seminary (optional)
* @return array Mapping of Questgroup-IDs from source Seminary to target Seminary
*/
public function copyQuestgroupsOfSeminary($userId, $sourceSeminaryId, $targetSeminaryId, $questgroupshierarchyIds, $seminaryMediaIds=null)
{
// Get Questgroups of source Seminary
$questgroupIds = array();
$questgroups = $this->getQuestgroupsForSeminary($sourceSeminaryId);
foreach($questgroups as &$questgroup)
{
// Insert into target Seminary
$this->db->query(
'INSERT INTO questgroups '.
'(created_user_id, seminary_id, title, url) '.
'VALUES '.
'(?, ?, ?, ?)',
'iiss',
$userId,
$targetSeminaryId,
$questgroup['title'],
$questgroup['url']
);
$questgroupIds[$questgroup['id']] = $this->db->getInsertId();
// Copy media
if(!is_null($seminaryMediaIds) && !is_null($questgroup['questgroupspicture_id']))
{
$this->Media->copyQuestgroupspicture($userId, $seminaryMediaIds[$questgroup['questgroupspicture_id']]);
$this->db->query(
'UPDATE questgroups '.
'SET questgroupspicture_id = ? '.
'WHERE id = ?',
'ii',
$seminaryMediaIds[$questgroup['questgroupspicture_id']],
$questgroupIds[$questgroup['id']]
);
}
// Copy Questgroup texts
$this->Questgrouptexts->copyQuestgrouptexts($userId, $questgroup['id'], $questgroupIds[$questgroup['id']]);
}
return $questgroupIds;
}
/**
* Delete a Questgroup.
*
* @param int $questgroupId ID of Questgroup to delete
*/
public function deleteQuestgroup($questgroupId)
{
// Get Questgroupshierarchy
$hierarchy = $this->Questgroupshierarchy->getHierarchyForQuestgroup($questgroupId);
// Delete Questgroup texts
$this->Questgrouptexts->deleteQuestgrouptexts($questgroupId);
// Delete Questgroup
$this->db->query('DELETE FROM questgroups WHERE id = ?', 'i', $questgroupId);
// Correct Questgrouphierarchy positions
if(!empty($hierarchy))
{
if(is_null($hierarchy['parent_questgroup_id'])) {
$this->db->query(
'UPDATE questgroups_questgroupshierarchy '.
'SET pos = pos - 1 '.
'WHERE questgroupshierarchy_id = ? AND parent_questgroup_id IS NULL AND pos >= ?',
'ii',
$hierarchy['id'],
$hierarchy['questgroup_pos']
);
}
else {
$this->db->query(
'UPDATE questgroups_questgroupshierarchy '.
'SET pos = pos - 1 '.
'WHERE questgroupshierarchy_id = ? AND parent_questgroup_id = ? AND pos >= ?',
'iii',
$hierarchy['id'],
$hierarchy['parent_questgroup_id'],
$hierarchy['questgroup_pos']
);
}
}
}
/**
* Delete all Questgroups of a Seminary.
*
* @param int $seminaryId ID of Seminary to delete Questgroups of
*/
public function deleteQuestgroupsOfSeminary($seminaryId)
{
// Get Questgroups
$questgroups = $this->getQuestgroupsForSeminary($seminaryId);
// Delete each Questgroup
foreach($questgroups as &$questgroup) {
$this->deleteQuestgroup($questgroup['id']);
}
}
/**
* Get the next (direct) Questgroup.
*
* @param int $seminaryId ID of Seminary
* @param int $parentQuestgroupId ID of parent Questgroup to get next Questgroup of
* @param int $questgroupPos Position of Questgroup to get next Questgroup of
* @return array Data of next Questgroup or NULL
*/
private function _getNextQuestgroup($seminaryId, $parentQuestgroupId, $questgroupPos)
{
if(!is_null($parentQuestgroupId))
{
$data = $this->db->query(
'SELECT * '.
'FROM questgroups_questgroupshierarchy '.
'INNER JOIN questgroups ON questgroups.id = questgroups_questgroupshierarchy.questgroup_id '.
'WHERE seminary_id = ? AND parent_questgroup_id = ? AND pos = ? + 1',
'iii',
$seminaryId, $parentQuestgroupId, $questgroupPos
);
}
else
{
$data = $this->db->query(
'SELECT * '.
'FROM questgroups_questgroupshierarchy '.
'INNER JOIN questgroups ON questgroups.id = questgroups_questgroupshierarchy.questgroup_id '.
'WHERE seminary_id = ? AND parent_questgroup_id IS NULL AND pos = ? + 1',
'ii',
$seminaryId, $questgroupPos
);
}
if(empty($data)) {
return null;
}
return $data[0];
}
/**
* Get the previous (direct) Questgroup.
*
* @param int $seminaryId ID of Seminary
* @param int $parentQuestgroupId ID of parent Questgroup to get previous Questgroup of
* @param int $questgroupPos Position of Questgroup to get previous Questgroup of
* @return array Data of previous Questgroup or NULL
*/
private function _getPreviousQuestgroup($seminaryId, $parentQuestgroupId, $questgroupPos)
{
if(!is_null($parentQuestgroupId))
{
$data = $this->db->query(
'SELECT * '.
'FROM questgroups_questgroupshierarchy '.
'INNER JOIN questgroups ON questgroups.id = questgroups_questgroupshierarchy.questgroup_id '.
'WHERE seminary_id = ? AND parent_questgroup_id = ? AND pos = ? - 1',
'iii',
$seminaryId, $parentQuestgroupId, $questgroupPos
);
}
else
{
$data = $this->db->query(
'SELECT * '.
'FROM questgroups_questgroupshierarchy '.
'INNER JOIN questgroups ON questgroups.id = questgroups_questgroupshierarchy.questgroup_id '.
'WHERE seminary_id = ? AND parent_questgroup_id IS NULL AND pos = ? - 1',
'ii',
$seminaryId, $questgroupPos
);
}
if(empty($data)) {
return null;
}
return $data[0];
}
/**
* Mark a Questgroup for a Character.
*
* @param int $questgroupId ID of Questgroup to mark
* @param int $characterId ID of Character to mark the Questgroup for
* @param int $status Questgroup status to mark
* @param boolean $repeated Insert although status is already set for this Questgroup and Character
*/
private function setQuestgroupStatus($questgroupId, $characterId, $status, $repeated=true)
{
// Check if status is already set
if(!$repeated)
{
$count = $this->db->query(
'SELECT count(*) AS c '.
'FROM questgroups_characters '.
'WHERE questgroup_id = ? AND character_id = ? AND status = ?',
'iii',
$questgroupId,
$characterId,
$status
);
if(!empty($count) && intval($count[0]['c']) > 0) {
return;
}
}
// Set status
$this->db->query(
'INSERT INTO questgroups_characters '.
'(questgroup_id, character_id, status) '.
'VALUES '.
'(?, ?, ?) ',
'iii',
$questgroupId,
$characterId,
$status
);
}
/**
* Calculate the total amount of achievable XPs for a
* Questgroup, its sub-Questgroups, related Questgroups etc. and
* store this value in the database.
*
* @param int $questgroupId ID of Questgroup
* @param array $calculatedQuests Already calculated Quests
* @return int Sum of calculated XPs
*/
public function calculateXPsForQuestgroup($questgroupId, &$calculatedQuests=array())
{
$xps = 0;
// Quests
$quest = $this->Quests->getFirstQuestOfQuestgroup($questgroupId);
if(!is_null($quest)) {
$xps = $this->_calculateXPsForQuestgroup($quest);
}
// Child Questgroups
$questgroupHierarchy = $this->Questgroupshierarchy->getHierarchyForQuestgroup($questgroupId);
if(!empty($questgroupHierarchy))
{
$childQuestgroupshierarchy = $this->Questgroupshierarchy->getChildQuestgroupshierarchy($questgroupHierarchy['id']);
foreach($childQuestgroupshierarchy as &$hierarchy)
{
$questgroups = $this->getQuestgroupsForHierarchy($hierarchy['id'], $questgroupId);
foreach($questgroups as &$questgroup) {
$xps += $this->calculateXPsForQuestgroup($questgroup['id'], $calculatedQuests);
}
}
}
// Save XPs
$this->setXPsForQuestgroup($questgroupId, $xps);
return $xps;
}
/**
* Get the sum of XPs of Quests for a Questgroup solved by a
* Character.
*
* @param int $questgroupId ID of Questgroup
* @param int $characterId ID of Character
* @return int Sum of XPs of Quests
*/
private function _getAchievedXPsForQuestgroup($questgroupId, $characterId)
{
$data = $this->db->query(
'SELECT COALESCE(SUM(quests.xps),0) AS xps '.
'FROM quests '.
'INNER JOIN quests_characters ON quests_characters.quest_id = quests.id AND quests_characters.character_id = ? AND quests_characters.status = ? '.
'WHERE quests.questgroup_id = ?',
'iii',
$characterId,
\hhu\z\models\QuestsModel::QUEST_STATUS_SOLVED,
$questgroupId
);
if(!empty($data)) {
return $data[0]['xps'];
}
}
/**
* Calculate the total amount of achievable XPs for a Quest and
* its following Quests by choosing the path with the highest
* amount of XPs.
*
* @param int $quest Quest data
* @param array $calculatedQuests Already calculated Quests
* @return int Sum of calculated XPs
*/
private function _calculateXPsForQuestgroup($quest, &$calculatedQuests=array())
{
$xps = $quest['xps'];
// Related Questgroups
$relatedQuestgroups = $this->getRelatedQuestsgroupsOfQuest($quest['id']);
foreach($relatedQuestgroups as &$relatedQuestgroup) {
$xps += $this->calculateXPsForQuestgroup($relatedQuestgroup['id'], $calculatedQuests);
}
// Next Quests
$nextQuests = $this->Quests->getNextQuests($quest['id']);
$allNextXPs = array(0);
foreach($nextQuests as &$nextQuest)
{
if(!array_key_exists($nextQuest['id'], $calculatedQuests)) {
$calculatedQuests[$nextQuest['id']] = $this->_calculateXPsForQuestgroup($nextQuest, $calculatedQuests);
}
$allNextXPs[] = $calculatedQuests[$nextQuest['id']];
}
$xps += max($allNextXPs);
return $xps;
}
/**
* Set achievable XPs for a Questgroup.
*
* @param int $questgroupId ID of Questgroup
* @param int $xps XPs to set
*/
private function setXPsForQuestgroup($questgroupId, $xps)
{
$this->db->query(
'UPDATE questgroups '.
'SET achievable_xps = ? '.
'WHERE id = ?',
'ii',
$xps,
$questgroupId
);
}
}
?>