questlab/models/AchievementsModel.inc

1531 lines
57 KiB
PHP
Raw Permalink 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 Achievements-tables.
*
* @author Oliver Hanraths <oliver.hanraths@uni-duesseldorf.de>
*/
class AchievementsModel extends \hhu\z\Model
{
/**
* Required models
*
* @var array
*/
public $models = array('media');
/**
* Construct a new AchievementsModel.
*/
public function __construct()
{
parent::__construct();
}
/**
* Get an Achievement by its URL.
*
* @param int $seminaryId ID of Seminary
* @param string $achievementUrl URL-title of Achievement
* @return array Achievement data
*/
public function getAchievementByUrl($seminaryId, $achievementUrl)
{
$data = $this->db->query(
'SELECT achievements.id, achievementconditions.condition, seminary_id, pos, title, url, description, progress, hidden, only_once, all_conditions, deadline, unachieved_achievementsmedia_id, achieved_achievementsmedia_id '.
'FROM achievements '.
'LEFT JOIN achievementconditions ON achievementconditions.id = achievements.achievementcondition_id '.
'WHERE seminary_id = ? AND url = ?',
'is',
$seminaryId, $achievementUrl
);
if(empty($data)) {
throw new \nre\exceptions\IdNotFoundException($achievementUrl);
}
return $data[0];
}
/**
* Get an Achievement by its ID.
*
* @param int $achievementId ID of Achievement
* @return array Achievement data
*/
public function getAchievementById($achievementId)
{
$data = $this->db->query(
'SELECT achievements.id, achievementconditions.condition, seminary_id, pos, title, url, description, progress, hidden, only_once, all_conditions, deadline, unachieved_achievementsmedia_id, achieved_achievementsmedia_id '.
'FROM achievements '.
'LEFT JOIN achievementconditions ON achievementconditions.id = achievements.achievementcondition_id '.
'WHERE achievements.id = ?',
'i',
$achievementId
);
if(empty($data)) {
throw new \nre\exceptions\IdNotFoundException($achievementId);
}
return $data[0];
}
/**
* Get all not yet achieved Achievements for a Seminary that can
* only be achieved once (only by one Character).
*
* @param int $seminaryId ID of Seminary
* @return array Achievements data
*/
public function getUnachievedOnlyOnceAchievementsForSeminary($seminaryId)
{
return $this->db->query(
'SELECT achievements.id, achievements.pos, achievementconditions.condition, title, url, description, progress, hidden, only_once, all_conditions, deadline, unachieved_achievementsmedia_id, achieved_achievementsmedia_id '.
'FROM achievements '.
'LEFT JOIN achievementconditions ON achievementconditions.id = achievements.achievementcondition_id '.
'WHERE achievements.seminary_id = ? AND only_once = 1 AND NOT EXISTS ('.
'SELECT character_id '.
'FROM achievements_characters '.
'WHERE achievements_characters.achievement_id = achievements.id'.
')',
'i',
$seminaryId
);
}
/**
* Get all Achievements that have a deadline.
*
* @param int $seminaryId ID of Seminary
* @return array Achievements data
*/
public function getDeadlineAchievements($seminaryId)
{
return $this->db->query(
'SELECT achievements.id, achievements.pos, achievementconditions.condition, title, url, description, progress, hidden, only_once, all_conditions, deadline, unachieved_achievementsmedia_id, achieved_achievementsmedia_id '.
'FROM achievements '.
'LEFT JOIN achievementconditions ON achievementconditions.id = achievements.achievementcondition_id '.
'WHERE achievements.seminary_id = ? AND deadline IS NOT NULL '.
'ORDER BY deadline ASC',
'i',
$seminaryId
);
}
/**
* Get seldom Achievements.
*
* @param int $seminaryId ID of Seminary
* @param int $count Number of Achievements to retrieve
* @param bool $alsoWithDeadline Include Achievements with deadline (optional)
* @return array List of seldom Achievements
*/
public function getSeldomAchievements($seminaryId, $count, $alsoWithDeadline=true)
{
return $this->db->query(
'SELECT achievements.id, achievements.pos, achievements.title, achievements.url, achievements.description, achievements.progress, achievements.hidden, achievements.unachieved_achievementsmedia_id, achievements.achieved_achievementsmedia_id, count(DISTINCT achievements_characters.character_id) AS c '.
'FROM achievements_characters '.
'INNER JOIN characters_characterroles ON characters_characterroles.character_id = achievements_characters.character_id '.
'INNER JOIN characterroles ON characterroles.id = characters_characterroles.characterrole_id AND characterroles.name = ? '.
'LEFT JOIN achievements ON achievements.id = achievements_characters.achievement_id '.
'WHERE achievements.seminary_id = ? AND achievements.only_once = 0 '.
(!$alsoWithDeadline ? 'AND achievements.deadline IS NULL ' : null).
'GROUP BY achievements_characters.achievement_id '.
'ORDER BY count(DISTINCT achievements_characters.character_id) ASC '.
'LIMIT ?',
'sii',
'user',
$seminaryId,
$count
);
}
/**
* Get all achieved Achievements for a Character.
*
* @param int $characterId ID of Character
* @param bool $alsoWithDeadline Include Achievements with deadline (optional)
* @return array Achievements data
*/
public function getAchievedAchievementsForCharacter($characterId, $alsoWithDeadline=true)
{
return $this->db->query(
'SELECT achievements.id, achievements.pos, achievements_characters.created, achievements.title, achievements.url, achievements.description, achievements.progress, unachieved_achievementsmedia_id, achieved_achievementsmedia_id '.
'FROM achievements '.
'INNER JOIN achievements_characters ON achievements_characters.achievement_id = achievements.id '.
'WHERE achievements_characters.character_id = ? '.
(!$alsoWithDeadline ? 'AND achievements.deadline IS NULL ' : null).
'ORDER BY achievements_characters.created DESC',
'i',
$characterId
);
}
/**
* Get all not yet achieved Achievements for a Character.
*
* @param int $seminaryId ID of Seminary
* @param int $characterId ID of Character
* @param boolean $includeOnlyOnce Include Achievements that can only be achieved by one Character
* @param boolean $alsoWithDeadline Include milestone Achievements
* @return array Achievements data
*/
public function getUnachhievedAchievementsForCharacter($seminaryId, $characterId, $includeOnlyOnce=false, $alsoWithDeadline=true)
{
return $this->db->query(
'SELECT achievements.id, achievements.pos, achievementconditions.condition, title, url, description, progress, hidden, only_once, all_conditions, deadline, unachieved_achievementsmedia_id, achieved_achievementsmedia_id '.
'FROM achievements '.
'LEFT JOIN achievementconditions ON achievementconditions.id = achievements.achievementcondition_id '.
'WHERE achievements.seminary_id = ? AND only_once <= ? AND NOT EXISTS ('.
'SELECT character_id '.
'FROM achievements_characters '.
'WHERE '.
'achievements_characters.achievement_id = achievements.id AND '.
'achievements_characters.character_id = ?'.
') '.
(!$alsoWithDeadline ? 'AND achievements.deadline IS NULL ' : null).
'ORDER BY achievements.pos ASC',
'iii',
$seminaryId,
$includeOnlyOnce,
$characterId
);
}
/**
* Get the amount of Achievement for a Seminary.
*
* @param int $seminaryId ID of Seminary
* @param boolean $includeOnlyOnce Include Achievements that can only be achieved by one Character
* @param boolean $alsoWithDeadline Include milestone Achievements
* @return int Count of Achievements
*/
public function getAchievementsCountForSeminary($seminaryId, $includeOnlyOnce=false, $alsoWithDeadline=true)
{
$data = $this->db->query(
'SELECT count(id) AS c '.
'FROM achievements '.
'WHERE seminary_id = ? AND only_once <= ?'.
(!$alsoWithDeadline ? ' AND achievements.deadline IS NULL ' : null),
'ii',
$seminaryId,
$includeOnlyOnce
);
if(!empty($data)) {
return $data[0]['c'];
}
return 0;
}
/**
* Get all Achievements for a Seminary.
*
* @param int $seminaryId ID of Seminary
* @return array List of Achievements
*/
public function getAchievementsForSeminary($seminaryId)
{
return $this->db->query(
'SELECT achievements.id, achievementconditions.condition, seminary_id, pos, title, url, description, progress, hidden, only_once, all_conditions, deadline, unachieved_achievementsmedia_id, achieved_achievementsmedia_id '.
'FROM achievements '.
'LEFT JOIN achievementconditions ON achievementconditions.id = achievements.achievementcondition_id '.
'WHERE seminary_id = ? '.
'ORDER BY pos ASC',
'i',
$seminaryId
);
}
/**
* Get the rank for the number of achieved Achievements.
*
* @param int $seminaryId ID of Seminary
* @param int $count Amount of achieved Achievements
* @return int Rank of Achievements count
*/
public function getCountRank($seminaryId, $count)
{
$data = $this->db->query(
'SELECT count(*) AS c '.
'FROM ('.
'SELECT count(DISTINCT achievement_id) '.
'FROM achievements_characters '.
'LEFT JOIN achievements ON achievements.id = achievements_characters.achievement_id '.
'WHERE achievements.seminary_id = ? '.
'GROUP BY character_id '.
'HAVING count(DISTINCT achievement_id) > ?'.
') AS ranking',
'ii',
$seminaryId,
$count
);
if(!empty($data)) {
return $data[0]['c'] + 1;
}
return 1;
}
/**
* Get all date conditions for an Achievement.
*
* @param int $achievementId ID of Achievement
* @return array Date conditions
*/
public function getAchievementConditionsDate($achievementId)
{
return $this->db->query(
'SELECT id, `select` '.
'FROM achievementconditions_date '.
'WHERE achievement_id = ?',
'i',
$achievementId
);
}
/**
* Check a date condition.
*
* @param string $select SELECT-string with date-functions
* @return boolean Result
*/
public function checkAchievementConditionDate($select)
{
$data = $this->db->query(
'SELECT ('.$select.') AS got '
);
if(!empty($data)) {
return ($data[0]['got'] == 1);
}
return false;
}
/**
* Add a new date condition.
*
* @param int $userId ID of creating user
* @param int $achievementId ID of Achievement to add condition to
* @param string $select SELECT-string for condition
*/
public function addAchievementConditionDate($userId, $achievementId, $select)
{
$this->db->query(
'INSERT INTO achievementconditions_date '.
'(created_user_id, achievement_id, `select`) '.
'VALUES '.
'(?, ?, ?)',
'iis',
$userId,
$achievementId,
$select
);
}
/**
* Edit a date condition.
*
* @param int $conditionId ID of condition to edit
* @param string $select New SELECT-string for condition
*/
public function editAchievementConditionDate($conditionId, $select)
{
$this->db->query(
'UPDATE achievementconditions_date '.
'SET `select` = ? '.
'WHERE id = ?',
'si',
$select,
$conditionId
);
}
/**
* Copy all date conditions of an Achievement.
*
* @param int $userId ID of creating user
* @param int $sourceAchievementId ID of Achievement to copy conditions from
* @param int $targetAchievementId ID of Achievement to copy conditions to
*/
public function copyAchievementConditionsDate($userId, $sourceAchievementId, $targetAchievementId)
{
$this->db->query(
'INSERT INTO achievementconditions_date '.
'(created_user_id, achievement_id, `select`) '.
'SELECT ?, ?, `select` '.
'FROM achievementconditions_date '.
'WHERE achievement_id = ?',
'iii',
$userId, $targetAchievementId,
$sourceAchievementId
);
}
/**
* Delete a date condition.
*
* @param int $conditionId ID of condition to delete
*/
public function deleteAchievementConditionDate($conditionId)
{
$this->db->query('DELETE FROM achievementconditions_date WHERE id = ?', 'i', $conditionId);
}
/**
* Get all Character conditions for an Achievement.
*
* @param int $achievementId ID of Achievement
* @return array Character conditions
*/
public function getAchievementConditionsCharacter($achievementId)
{
return $this->db->query(
'SELECT id, field, value '.
'FROM achievementconditions_character '.
'WHERE achievement_id = ?',
'i',
$achievementId
);
}
/**
* Check a Character condition.
*
* @param string $field Field to check
* @param int $value The value the field has to match
* @param int $characterId ID of Character
* @return boolean Result
*/
public function checkAchievementConditionCharacter($field, $value, $characterId)
{
$data = $this->db->query(
"SELECT ($field >= $value) AS got ".
'FROM ('.
'SELECT '.
'characters.id, characters.created, characters.user_id, characters.name, characters.url, cache_characters.xps, cache_characters.quest_xps, cache_characters.avatar_id, '.
'charactertypes.id AS charactertype_id, charactertypes.name AS charactertype_name, charactertypes.url AS charactertype_url, '.
'xplevels.id AS xplevel_id, xplevels.level AS xplevel '.
'FROM characters '.
'LEFT JOIN cache_characters ON cache_characters.character_id = characters.id '.
'LEFT JOIN charactertypes ON charactertypes.id = characters.charactertype_id '.
'LEFT JOIN xplevels ON xplevels.id = cache_characters.xplevel_id '.
') AS c '.
'WHERE c.id = ?',
'i',
$characterId
);
if(!empty($data)) {
return ($data[0]['got'] == 1);
}
return false;
}
/**
* Get the progress for a Character condition.
*
* @param string $field Field to check
* @param int $value The value the field has to match
* @param int $characterId ID of Character
* @return float Percentage progress
*/
public function getAchievementConditionCharacterProgress($field, $value, $characterId)
{
$data = $this->db->query(
"SELECT $field AS field ".
'FROM ('.
'SELECT '.
'characters.id, characters.created, characters.user_id, characters.name, characters.url, cache_characters.xps, cache_characters.quest_xps, cache_characters.avatar_id, '.
'charactertypes.id AS charactertype_id, charactertypes.name AS charactertype_name, charactertypes.url AS charactertype_url, '.
'xplevels.id AS xplevel_id, xplevels.level AS xplevel '.
'FROM characters '.
'LEFT JOIN cache_characters ON cache_characters.character_id = characters.id '.
'LEFT JOIN charactertypes ON charactertypes.id = characters.charactertype_id '.
'LEFT JOIN xplevels ON xplevels.id = cache_characters.xplevel_id '.
') AS c '.
'WHERE c.id = ?',
'i',
$characterId
);
if(!empty($data)) {
return $data[0]['field'] / $value;
}
return 0;
}
/**
* Add a new Character condition.
*
* @param int $userId ID of creating user
* @param int $achievementId ID of Achievement to add condition to
* @param string $field Field to match
* @param string $value Value to match
*/
public function addAchievementConditionCharacter($userId, $achievementId, $field, $value)
{
$this->db->query(
'INSERT INTO achievementconditions_character '.
'(created_user_id, achievement_id, field, value) '.
'VALUES '.
'(?, ?, ?, ?)',
'iiss',
$userId,
$achievementId,
$field,
$value
);
}
/**
* Edit a Character condition.
*
* @param int $conditionId ID of condition to edit
* @param string $field Field to match
* @param string $value Value to match
*/
public function editAchievementConditionCharacter($conditionId, $field, $value)
{
$this->db->query(
'UPDATE achievementconditions_character '.
'SET field = ?, value = ? '.
'WHERE id = ?',
'ssi',
$field,
$value,
$conditionId
);
}
/**
* Copy all Character conditions of an Achievement.
*
* @param int $userId ID of creating user
* @param int $sourceAchievementId ID of Achievement to copy conditions from
* @param int $targetAchievementId ID of Achievement to copy conditions to
*/
public function copyAchievementConditionsCharacter($userId, $sourceAchievementId, $targetAchievementId)
{
$this->db->query(
'INSERT INTO achievementconditions_character '.
'(created_user_id, achievement_id, field, value) '.
'SELECT ?, ?, field, value '.
'FROM achievementconditions_character '.
'WHERE achievement_id = ?',
'iii',
$userId, $targetAchievementId,
$sourceAchievementId
);
}
/**
* Delete a Character condition.
*
* @param int $conditionId ID of condition to delete
*/
public function deleteAchievementConditionCharacter($conditionId)
{
$this->db->query('DELETE FROM achievementconditions_character WHERE id = ?', 'i', $conditionId);
}
/**
* Get all Quest conditions for an Achievement.
*
* @param int $achievementId ID of Achievement
* @return array Quest conditions
*/
public function getAchievementConditionsQuest($achievementId)
{
return $this->db->query(
'SELECT id, field, `count`, value, quest_id, status, groupby '.
'FROM achievementconditions_quest '.
'WHERE achievement_id = ?',
'i',
$achievementId
);
}
/**
* Check a Quest condition.
*
* @param string $field Field to check
* @param boolean $count Conut field-value
* @param int $value The value the field has to match
* @param int $status Status of Quest or NULL
* @param string $groupby Field to group or NULL
* @param int $questId ID of related Quest or NULL
* @param int $characterId ID of Character
* @return boolean Result
*/
public function checkAchievementConditionQuest($field, $count, $value, $status, $groupby, $questId, $characterId)
{
$data = $this->db->query(
'SELECT ('.(
$count
? "count($field) = $value"
: "$field = $value"
). ') AS got '.
'FROM quests_characters '.
'WHERE '.
'character_id = ?'.
(!is_null($questId) ? " AND quest_id = $questId" : '').
(!is_null($status) ? " AND status = $status" : '').
(!is_null($groupby) ? " GROUP BY $groupby" : ''),
'i',
$characterId
);
if(!empty($data)) {
foreach($data as &$datum) {
if($datum['got'] == 1) {
return true;
}
}
}
return false;
}
/**
* Get the progress for a Quest condition.
*
* @param string $field Field to check
* @param boolean $count Conut field-value
* @param int $value The value the field has to match
* @param int $status Status of Quest or NULL
* @param string $groupby Field to group or NULL
* @param int $questId ID of related Quest or NULL
* @param int $characterId ID of Character
* @return float Percentage progress
*/
public function getAchievementConditionQuestProgress($field, $count, $value, $status, $groupby, $questId, $characterId)
{
$data = $this->db->query(
'SELECT '.(
$count
? "count($field)"
: "$field"
). ' AS field '.
'FROM quests_characters '.
'WHERE '.
'character_id = ?'.
(!is_null($questId) ? " AND quest_id = $questId" : '').
(!is_null($status) ? " AND status = $status" : '').
(!is_null($groupby) ? " GROUP BY $groupby" : ''),
'i',
$characterId
);
if(!empty($data))
{
$maxField = 0;
foreach($data as &$datum) {
$maxField = max($maxField, intval($datum['field']));
}
return $maxField / $value;
}
return 0;
}
/**
* Add a new Quest condition.
*
* @param int $userId ID of creating user
* @param int $achievementId ID of Achievement to add condition to
* @param string $field Field to match
* @param boolean $count Count the value
* @param string $value Value to match
* @param int $questId ID of Quest (optional)
* @param int $status Quest status (optional)
* @param string $groupby Field to group by (optional)
*/
public function addAchievementConditionQuest($userId, $achievementId, $field, $count, $value, $questId=null, $status=null, $groupby=null)
{
$this->db->query(
'INSERT INTO achievementconditions_quest '.
'(created_user_id, achievement_id, field, count, value, quest_id, status, groupby) '.
'VALUES '.
'(?, ?, ?, ?, ?, ?, ?, ?)',
'iisisiis',
$userId,
$achievementId,
$field,
$count,
$value,
$questId,
$status,
$groupby
);
}
/**
* Edit a Quest condition.
*
* @param int $conditionId ID of condition to edit
* @param string $field Field to match
* @param boolean $count Count the value
* @param string $value Value to match
* @param int $questId ID of Quest (optional)
* @param int $status Quest status (optional)
* @param string $groupby Field to group by (optional)
*/
public function editAchievementConditionQuest($conditionId, $field, $count, $value, $questId=null, $status=null, $groupby=null)
{
$this->db->query(
'UPDATE achievementconditions_quest '.
'SET field = ?, count = ?, value = ?, quest_id = ?, status = ?, groupby = ? '.
'WHERE id = ?',
'sisiisi',
$field,
$count,
$value,
$questId,
$status,
$groupby,
$conditionId
);
}
/**
* Copy all Quest conditions of an Achievement.
*
* @param int $userId ID of creating user
* @param int $sourceAchievementId ID of Achievement to copy conditions from
* @param int $targetAchievementId ID of Achievement to copy conditions to
* @param array $questIds Mapping of Quest-IDs from source Seminary to target Seminary
*/
public function copyAchievementConditionsQuest($userId, $sourceAchievementId, $targetAchievementId, $questIds)
{
// Get conditions
$conditions = $this->getAchievementConditionsQuest($sourceAchievementId);
// Copy each condition
foreach($conditions as &$condition)
{
if(is_null($condition['quest_id']))
{
$this->db->query(
'INSERT INTO achievementconditions_quest '.
'(created_user_id, achievement_id, field, count, value, status, groupby) '.
'SELECT ?, ?, field, count, value, status, groupby '.
'FROM achievementconditions_quest '.
'WHERE id = ?',
'iii',
$userId, $targetAchievementId,
$condition['id']
);
}
else
{
$this->db->query(
'INSERT INTO achievementconditions_quest '.
'(created_user_id, achievement_id, field, count, value, quest_id, status, groupby) '.
'SELECT ?, ?, field, count, value, ?, status, groupby '.
'FROM achievementconditions_quest '.
'WHERE id = ?',
'iiii',
$userId, $targetAchievementId, $questIds[$condition['quest_id']],
$condition['id']
);
}
}
}
/**
* Delete a Quest condition.
*
* @param int $conditionId ID of condition to delete
*/
public function deleteAchievementConditionQuest($conditionId)
{
$this->db->query('DELETE FROM achievementconditions_quest WHERE id = ?', 'i', $conditionId);
}
/**
* Get all Metaachievement conditions for an Achievement.
*
* @param int $achievementId ID of Achievement
* @return array Metaachievement conditions
*/
public function getAchievementConditionsAchievement($achievementId)
{
return $this->db->query(
'SELECT id, field, `count`, value, meta_achievement_id, groupby '.
'FROM achievementconditions_achievement '.
'WHERE achievement_id = ?',
'i',
$achievementId
);
}
/**
* Check a Metaachievement condition.
*
* @param string $field Field to check
* @param boolean $count Conut field-value
* @param int $value The value the field has to match
* @param string $groupby Field to group or NULL
* @param int $metaAchievementId ID of related Achievement or NULL
* @param int $characterId ID of Character
* @return boolean Result
*/
public function checkAchievementConditionAchievement($field, $count, $value, $groupby, $metaAchievementId, $characterId)
{
$data = $this->db->query(
'SELECT ('.(
$count
? "count($field) >= $value"
: "$field = $value"
). ') AS got '.
'FROM achievements_characters '.
'WHERE '.
'character_id = ?'.
(!is_null($metaAchievementId) ? " AND achievement_id = $metaAchievementId" : '').
(!is_null($groupby) ? " GROUP BY $groupby" : ''),
'i',
$characterId
);
if(!empty($data)) {
foreach($data as &$datum) {
if($datum['got'] == 1) {
return true;
}
}
}
return false;
}
/**
* Get the progress for a Metaachievement condition.
*
* @param string $field Field to check
* @param boolean $count Conut field-value
* @param int $value The value the field has to match
* @param string $groupby Field to group or NULL
* @param int $metaAchievementId ID of related Achievement or NULL
* @param int $characterId ID of Character
* @return float Percentage progress
*/
public function getAchievementConditionAchievementProgress($field, $count, $value, $groupby, $metaAchievementId, $characterId)
{
$data = $this->db->query(
'SELECT '.(
$count
? "count($field)"
: "$field"
). ' AS field '.
'FROM achievements_characters '.
'WHERE '.
'character_id = ?'.
(!is_null($metaAchievementId) ? " AND achievement_id = $metaAchievementId" : '').
(!is_null($groupby) ? " GROUP BY $groupby" : ''),
'i',
$characterId
);
if(!empty($data))
{
$maxField = 0;
foreach($data as &$datum) {
$maxField = max($maxField, intval($datum['field']));
}
return $maxField / $value;
}
return 0;
}
/**
* Add a new Achievement condition.
*
* @param int $userId ID of creating user
* @param int $achievementId ID of Achievement to add condition to
* @param string $field Field to match
* @param boolean $count Count the value
* @param string $value Value to match
* @param int $metaAchievementId ID of Meta-Achievement (optional)
* @param string $groupby Field to group by (optional)
*/
public function addAchievementConditionAchievement($userId, $achievementId, $field, $count, $value, $metaAchievementId=null, $groupby=null)
{
$this->db->query(
'INSERT INTO achievementconditions_achievement '.
'(created_user_id, achievement_id, field, count, value, meta_achievement_id, groupby) '.
'VALUES '.
'(?, ?, ?, ?, ?, ?, ?)',
'iisisis',
$userId,
$achievementId,
$field,
$count,
$value,
$metaAchievementId,
$groupby
);
}
/**
* Edit a Achievement condition.
*
* @param int $conditionId ID of condition to edit
* @param string $field Field to match
* @param boolean $count Count the value
* @param string $value Value to match
* @param int $metaAchievementId ID of Achievement (optional)
* @param string $groupby Field to group by (optional)
*/
public function editAchievementConditionAchievement($conditionId, $field, $count, $value, $metaAchievementId=null, $groupby=null)
{
$this->db->query(
'UPDATE achievementconditions_achievement '.
'SET field = ?, count = ?, value = ?, meta_achievement_id = ?, groupby = ? '.
'WHERE id = ?',
'sisisi',
$field,
$count,
$value,
$metaAchievementId,
$groupby,
$conditionId
);
}
/**
* Copy all Achievement conditions of an Achievement.
*
* @param int $userId ID of creating user
* @param int $sourceAchievementId ID of Achievement to copy conditions from
* @param int $targetAchievementId ID of Achievement to copy conditions to
* @param array $achievementIds Mapping of Achievement-IDs from source Seminary to target Seminary
*/
public function copyAchievementConditionsAchievement($userId, $sourceAchievementId, $targetAchievementId, $achievementIds)
{
// Get conditions
$conditions = $this->getAchievementConditionsAchievement($sourceAchievementId);
// Copy each condition
foreach($conditions as &$condition)
{
if(is_null($condition['meta_achievement_id']) || !array_key_exists($condition['meta_achievement_id'], $achievementIds))
{
$this->db->query(
'INSERT INTO achievementconditions_achievement '.
'(created_user_id, achievement_id, field, count, value, groupby) '.
'SELECT ?, ?, field, count, value, groupby '.
'FROM achievementconditions_achievement '.
'WHERE id = ?',
'iii',
$userId, $targetAchievementId,
$condition['id']
);
}
else
{
$this->db->query(
'INSERT INTO achievementconditions_achievement '.
'(created_user_id, achievement_id, field, count, value, meta_achievement_id, groupby) '.
'SELECT ?, ?, field, count, value, ?, groupby '.
'FROM achievementconditions_achievement '.
'WHERE id = ?',
'iiii',
$userId, $targetAchievementId, $achievementIds[$condition['meta_achievement_id']],
$condition['id']
);
}
}
}
/**
* Delete a Achievement condition.
*
* @param int $conditionId ID of condition to delete
*/
public function deleteAchievementConditionAchievement($conditionId)
{
$this->db->query('DELETE FROM achievementconditions_achievement WHERE id = ?', 'i', $conditionId);
}
/**
* Get all QR-code conditions for an Achievement.
*
* @param int $achievementId ID of Achievement
* @return array List of QR-code conditions
*/
public function getAchievementConditionsQrcode($achievementId)
{
return $this->db->query(
'SELECT id, hash '.
'FROM achievementconditions_qrcode '.
'WHERE achievement_id = ?',
'i',
$achievementId
);
}
/**
* Get QR-code condition for a hash value.
*
* @param string $hash Hash value to get condition for
* @return array QR-code condition or null
*/
public function getAchievementConditionQrcode($hash)
{
$data = $this->db->query(
'SELECT id, achievement_id, hash '.
'FROM achievementconditions_qrcode '.
'WHERE hash = ?',
's',
$hash
);
if(!empty($data)) {
return $data[0];
}
return null;
}
/**
* Add a new QR-code condition.
*
* @param int $userId ID of creating user
* @param int $achievementId ID of Achievement to add condition to
*/
public function addAchievementConditionQrcode($userId, $achievementId)
{
// Delete all existing QR-codes, we allow only one per Achievement
$this->db->query(
'DELETE FROM achievementconditions_qrcode WHERE achievement_id = ?',
'i',
$achievementId
);
// Create new QR-code condition
$this->db->query(
'INSERT INTO achievementconditions_qrcode '.
'(created_user_id, achievement_id, hash) '.
'VALUES '.
'(?, ?, ?)',
'iis',
$userId, $achievementId,
\hhu\z\Utils::createRandomHash()
);
}
/**
* Copy all QR-code conditions of an Achievement.
*
* @param int $userId ID of creating user
* @param int $sourceAchievementId ID of Achievement to copy conditions from
* @param int $targetAchievementId ID of Achievement to copy conditions to
*/
public function copyAchievementConditionsQrcode($userId, $sourceAchievementId, $targetAchievementId)
{
$this->db->query(
'INSERT INTO achievementconditions_qrcode '.
'(created_user_id, achievement_id, hash) '.
'SELECT ?, ?, ? '.
'FROM achievementconditions_qrcode '.
'WHERE achievement_id = ?',
'iisi',
$userId, $targetAchievementId,
\hhu\z\Utils::createRandomHash(),
$sourceAchievementId
);
}
/**
* Delete a QR-code condition.
*
* @param int $conditionId ID of condition to delete
*/
public function deleteAchievementConditionQrcode($conditionId)
{
$this->db->query('DELETE FROM achievementconditions_qrcode WHERE id = ?', 'i', $conditionId);
}
/**
* Set an Achievement as achieved for a Character.
*
* @param int $achievementId ID of Achievement
* @param int $characterId ID of Character
*/
public function setAchievementAchieved($achievementId, $characterId)
{
$this->db->query(
'INSERT INTO achievements_characters '.
'(achievement_id, character_id) '.
'VALUES '.
'(?, ?)',
'ii',
$achievementId, $characterId
);
}
/**
* Check if a Character has achieved an Achievement.
*
* @param int $achievementId ID of Achievement
* @param int $characterId ID of Character
* @return boolean Whether Character has achieved the Achievement or not
*/
public function hasCharacterAchievedAchievement($achievementId, $characterId)
{
$data = $this->db->query(
'SELECT achievement_id, character_id, created '.
'FROM achievements_characters '.
'WHERE achievement_id = ? AND character_id = ?',
'ii',
$achievementId, $characterId
);
if(!empty($data)) {
return $data[0];
}
return false;
}
/**
* Get all existing Achievements conditions.
*
* @return array List of Achievements conditions
*/
public function getAchievementsConditions()
{
return $this->db->query(
'SELECT id, created, `condition` '.
'FROM achievementconditions'
);
}
/**
* Check if an Achievement title already exists.
*
* @param int $seminaryId ID of Seminary
* @param string $title Achievement title to check
* @param int $achievementId Do not check this ID (for editing)
* @return boolean Whether Achievement title exists or not
*/
public function achievementTitleExists($seminaryId, $title, $achievementId=null)
{
$data = $this->db->query(
'SELECT id '.
'FROM achievements '.
'WHERE seminary_id = ? AND (title = ? OR url = ?)',
'iss',
$seminaryId,
$title,
\nre\core\Linker::createLinkParam($title)
);
return (!empty($data) && (is_null($achievementId) || $achievementId != $data[0]['id']));
}
/**
* Create a new Achievement for a Seminary.
*
* @param int $userId ID of creating user
* @param int $seminaryId ID of Seminary
* @param int $conditionId ID of Achievement condition
* @param string $title Title of new Achievement
* @param string $description Description of new Achievement
* @param boolean $progress Show progress
* @param boolean $hidden Secret Achievement
* @param boolean $onlyOnce Only achieveable by one user
* @param boolean $allConditions Achievement must match all conditions
* @param string $deadline Deadline for Achievement
* @return int ID of newly created Achievement
*/
public function createAchievement($userId, $seminaryId, $conditionId, $title, $description, $progress, $hidden, $onlyOnce, $allConditions, $deadline)
{
// Get position
$pos = $this->db->query(
'SELECT COALESCE(MAX(pos),0)+1 AS pos '.
'FROM achievements '.
'WHERE seminary_id = ?',
'i',
$seminaryId
);
$pos = $pos[0]['pos'];
// Create Achievement
$this->db->query(
'INSERT INTO achievements '.
'(created_user_id, seminary_id, achievementcondition_id, pos, title, url, description, progress, hidden, only_once, all_conditions, deadline) '.
'VALUES '.
'(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
'iiiisssiiiis',
$userId,
$seminaryId,
$conditionId,
$pos,
$title,
\nre\core\Linker::createLinkParam($title),
$description,
$progress,
$hidden,
$onlyOnce,
$allConditions,
$deadline
);
// Return ID
return $this->db->getInsertId();
}
/**
* Move an Achievement up (decrement position) or down
* (increment position).
*
* @param array $achievement Achievement to move
* @param boolean $up True for moving up, false for down
*/
public function moveAchievement($achievement, $up)
{
$this->db->setAutocommit(false);
try {
// Set temporary position
$this->db->query(
'UPDATE achievements '.
'SET pos = 0 '.
'WHERE id = ?',
'i',
$achievement['id']
);
// Switch entry
$this->db->query(
'UPDATE achievements '.
'SET pos = ? '.
'WHERE seminary_id = ? AND pos = ?',
'iii',
$achievement['pos'],
$achievement['seminary_id'],
$achievement['pos'] + ($up ? -1 : 1)
);
// Set new position
$this->db->query(
'UPDATE achievements '.
'SET pos = ? '.
'WHERE id = ?',
'ii',
$achievement['pos'] + ($up ? -1 : 1),
$achievement['id']
);
$this->db->commit();
}
catch(\nre\exceptions\DatamodelException $e) {
$this->db->rollback();
$this->db->setAutocommit(true);
throw $e;
}
$this->db->setAutocommit(true);
}
/**
* Edit an Achievement of a Seminary.
*
* @param int $achievementId ID of Achievement to edit
* @param int $conditionId ID of Achievement condition
* @param string $title New title of Achievement
* @param string $description New description of Achievement
* @param boolean $progress Show progress
* @param boolean $hidden Secret Achievement
* @param boolean $onlyOnce Only achieveable by one user
* @param boolean $allConditions Achievement must match all conditions
* @param string $deadline Deadline for Achievement
*/
public function editAchievement($achievementId, $conditionId, $title, $description, $progress, $hidden, $onlyOnce, $allConditions, $deadline)
{
$this->db->query(
'UPDATE achievements '.
'SET achievementcondition_id = ?, title = ?, url = ?, description = ?, progress = ?, hidden = ?, only_once = ?, all_conditions = ?, deadline = ? '.
'WHERE id = ?',
'isssiiiisi',
$conditionId,
$title,
\nre\core\Linker::createLinkParam($title),
$description,
$progress,
$hidden,
$onlyOnce,
$allConditions,
$deadline,
$achievementId
);
}
/**
* Set unachieved media for an Achievement.
*
* @param int $achievementId ID of Achievement to set media for
* @param int $achievementsmediaId ID of achievementsmedia to set
*/
public function setUnachievedMediaForAchievement($achievementId, $achievementsmediaId)
{
$this->db->query(
'UPDATE achievements '.
'SET unachieved_achievementsmedia_id = ? '.
'WHERE id = ?',
'ii',
$achievementsmediaId,
$achievementId
);
}
/**
* Set achieved media for an Achievement.
*
* @param int $achievementId ID of Achievement to set media for
* @param int $achievementsmediaId ID of achievementsmedia to set
*/
public function setAchievedMediaForAchievement($achievementId, $achievementsmediaId)
{
$this->db->query(
'UPDATE achievements '.
'SET achieved_achievementsmedia_id = ? '.
'WHERE id = ?',
'ii',
$achievementsmediaId,
$achievementId
);
}
/**
* Copy all Achievements of a Seminary.
*
* @param int $userId ID of creating user
* @param int $sourceSeminaryId Seminary to copy from
* @param int $targetSeminaryId Seminary to copy to
* @param array $seminaryMediaIds Mapping of Seminarymedia-IDs from source Seminary to target Seminary
* @param array $questIds Mapping of Quest-IDs from source Seminary to target Seminary (optional)
*/
public function copyAchievementsOfSeminary($userId, $sourceSeminaryId, $targetSeminaryId, $seminaryMediaIds, $questIds=null)
{
$achievementIds = array();
// Get Achievements
$achievements = $this->getAchievementsForSeminary($sourceSeminaryId);
// Copy each Achievements
foreach($achievements as &$achievement)
{
// Check Quest-IDs
if($achievement['condition'] == 'quest' && is_null($questIds)) {
continue;
}
// Copy Achievement
$this->db->query(
'INSERT INTO achievements '.
'(created_user_id, seminary_id, achievementcondition_id, pos, title, url, description, progress, hidden, only_once, all_conditions, deadline) '.
'SELECT ?, ?, achievementcondition_id, pos, title, url, description, progress, hidden, only_once, all_conditions, deadline '.
'FROM achievements '.
'WHERE id = ?',
'iii',
$userId, $targetSeminaryId,
$achievement['id']
);
$achievementIds[$achievement['id']] = $this->db->getInsertId();
// Copy media
if(!is_null($achievement['unachieved_achievementsmedia_id']))
{
$this->Media->copyAchievementMedia($userId, $seminaryMediaIds[$achievement['unachieved_achievementsmedia_id']]);
$this->db->query(
'UPDATE achievements '.
'SET unachieved_achievementsmedia_id = ? '.
'WHERE id = ?',
'ii',
$seminaryMediaIds[$achievement['unachieved_achievementsmedia_id']],
$achievementIds[$achievement['id']]
);
}
if(!is_null($achievement['achieved_achievementsmedia_id']))
{
$this->Media->copyAchievementMedia($userId, $seminaryMediaIds[$achievement['achieved_achievementsmedia_id']]);
$this->db->query(
'UPDATE achievements '.
'SET achieved_achievementsmedia_id = ? '.
'WHERE id = ?',
'ii',
$seminaryMediaIds[$achievement['achieved_achievementsmedia_id']],
$achievementIds[$achievement['id']]
);
}
}
// Copy Achievement conditions
// Do this after copying the Achievements themselves to ensure Meta-
// Achievements work correctly
foreach($achievements as &$achievement)
{
// Copy conditions
switch($achievement['condition'])
{
case 'date':
$this->copyAchievementConditionsDate($userId, $achievement['id'], $achievementIds[$achievement['id']]);
break;
case 'quest':
if(!is_null($questIds)) {
$this->copyAchievementConditionsQuest($userId, $achievement['id'], $achievementIds[$achievement['id']], $questIds);
}
break;
case 'character':
$this->copyAchievementConditionsCharacter($userId, $achievement['id'], $achievementIds[$achievement['id']]);
break;
case 'achievement':
$this->copyAchievementConditionsAchievement($userId, $achievement['id'], $achievementIds[$achievement['id']], $achievementIds);
break;
case 'qrcode':
$this->copyAchievementConditionsQrcode(
$userId,
$achievement['id'],
$achievementIds[$achievement['id']]
);
break;
}
}
}
/**
* Delete an Achievement.
*
* @param int $achievement Achievement to delete
*/
public function deleteAchievement($achievement)
{
$this->db->setAutocommit(false);
try {
// Delete Achievement
$this->db->query('DELETE FROM achievements WHERE id = ?', 'i', $achievement['id']);
// Adjust positions
$this->db->query(
'UPDATE achievements '.
'SET pos = pos - 1 '.
'WHERE seminary_id = ? AND pos > ?',
'ii',
$achievement['seminary_id'],
$achievement['pos']
);
$this->db->commit();
}
catch(\Exception $e) {
$this->db->rollback();
$this->db->setAutocommit(true);
throw $e;
}
$this->db->setAutocommit(true);
}
/**
* Delete all Achievements of a Seminary.
*
* @param int $seminaryId ID of Seminary to delete Achievements of
*/
public function deleteAchievementsOfSeminary($seminaryId)
{
// Delete Achievements
$this->db->query('DELETE FROM achievements WHERE seminary_id = ?', 'i', $seminaryId);
}
}
?>