<?php
/*---------------------------------------------------------------------------
 * @Project: Alto CMS
 * @Project URI: http://altocms.com
 * @Description: Advanced Community Engine
 * @Copyright: Alto CMS Team
 * @License: GNU GPL v2 & MIT
 *----------------------------------------------------------------------------
 * Based on
 *   LiveStreet Engine Social Networking by Mzhelskiy Maxim
 *   Site: www.livestreet.ru
 *   E-mail: rus.engine@gmail.com
 *----------------------------------------------------------------------------
 */

/**
 * Модуль управления рейтингами и силой
 *
 * @package modules.rating
 * @since   1.0
 */
class ModuleRating extends Module {

    /**
     * Инициализация модуля
     *
     */
    public function Init() {

    }

    /**
     * Расчет рейтинга при голосовании за комментарий
     *
     * @param ModuleUser_EntityUser       $oUser       Объект пользователя, который голосует
     * @param ModuleComment_EntityComment $oComment    Объект комментария
     * @param int                         $iValue
     *
     * @return int
     */
    public function VoteComment($oUser, $oComment, $iValue) {
        /**
         * Устанавливаем рейтинг комментария
         */
        $oComment->setRating($oComment->getRating() + $iValue);
        /**
         * Начисляем силу автору коммента, используя логарифмическое распределение
         */
        $skill = $oUser->getSkill();
        $iMinSize = 0.004;
        $iMaxSize = 0.5;
        $iSizeRange = $iMaxSize - $iMinSize;
        $iMinCount = log(0 + 1);
        $iMaxCount = log(500 + 1);
        $iCountRange = $iMaxCount - $iMinCount;
        if ($iCountRange == 0) {
            $iCountRange = 1;
        }
        if ($skill > 50 and $skill < 200) {
            $skill_new = $skill / 70;
        } elseif ($skill >= 200) {
            $skill_new = $skill / 10;
        } else {
            $skill_new = $skill / 130;
        }
        $iDelta = $iMinSize + (log($skill_new + 1) - $iMinCount) * ($iSizeRange / $iCountRange);
        /**
         * Сохраняем силу
         */
        $oUserComment = $this->User_GetUserById($oComment->getUserId());
        $iSkillNew = $oUserComment->getSkill() + $iValue * $iDelta;
        $iSkillNew = ($iSkillNew < 0) ? 0 : $iSkillNew;
        $oUserComment->setSkill($iSkillNew);
        $this->User_Update($oUserComment);
        return $iValue;
    }

    /**
     * Расчет рейтинга и силы при гоосовании за топик
     *
     * @param ModuleUser_EntityUser   $oUser     Объект пользователя, который голосует
     * @param ModuleTopic_EntityTopic $oTopic    Объект топика
     * @param int                     $iValue
     *
     * @return int
     */
    public function VoteTopic($oUser, $oTopic, $iValue) {

        $skill = $oUser->getSkill();
        /**
         * Устанавливаем рейтинг топика
         */
        $iDeltaRating = $iValue;
        if ($skill >= 100 and $skill < 250) {
            $iDeltaRating = $iValue * 2;
        } elseif ($skill >= 250 and $skill < 400) {
            $iDeltaRating = $iValue * 3;
        } elseif ($skill >= 400) {
            $iDeltaRating = $iValue * 4;
        }
        $oTopic->setRating($oTopic->getRating() + $iDeltaRating);
        /**
         * Начисляем силу и рейтинг автору топика, используя логарифмическое распределение
         */
        $iMinSize = 0.1;
        $iMaxSize = 8;
        $iSizeRange = $iMaxSize - $iMinSize;
        $iMinCount = log(0 + 1);
        $iMaxCount = log(500 + 1);
        $iCountRange = $iMaxCount - $iMinCount;
        if ($iCountRange == 0) {
            $iCountRange = 1;
        }
        if ($skill > 50 and $skill < 200) {
            $skill_new = $skill / 70;
        } elseif ($skill >= 200) {
            $skill_new = $skill / 10;
        } else {
            $skill_new = $skill / 100;
        }
        $iDelta = $iMinSize + (log($skill_new + 1) - $iMinCount) * ($iSizeRange / $iCountRange);
        /**
         * Сохраняем силу и рейтинг
         */
        $oUserTopic = $this->User_GetUserById($oTopic->getUserId());
        $iSkillNew = $oUserTopic->getSkill() + $iValue * $iDelta;
        $iSkillNew = ($iSkillNew < 0) ? 0 : $iSkillNew;
        $oUserTopic->setSkill($iSkillNew);
        $oUserTopic->setRating($oUserTopic->getRating() + $iValue * $iDelta / 2.73);
        $this->User_Update($oUserTopic);
        return $iDeltaRating;
    }

    /**
     * Расчет рейтинга и силы при голосовании за блог
     *
     * @param ModuleUser_EntityUser $oUser    Объект пользователя, который голосует
     * @param ModuleBlog_EntityBlog $oBlog    Объект блога
     * @param int                   $iValue
     *
     * @return int
     */
    public function VoteBlog($oUser, $oBlog, $iValue) {
        /**
         * Устанавливаем рейтинг блога, используя логарифмическое распределение
         */
        $skill = $oUser->getSkill();
        $iMinSize = 1.13;
        $iMaxSize = 15;
        $iSizeRange = $iMaxSize - $iMinSize;
        $iMinCount = log(0 + 1);
        $iMaxCount = log(500 + 1);
        $iCountRange = $iMaxCount - $iMinCount;
        if ($iCountRange == 0) {
            $iCountRange = 1;
        }
        if ($skill > 50 and $skill < 200) {
            $skill_new = $skill / 20;
        } elseif ($skill >= 200) {
            $skill_new = $skill / 10;
        } else {
            $skill_new = $skill / 50;
        }
        $iDelta = $iMinSize + (log($skill_new + 1) - $iMinCount) * ($iSizeRange / $iCountRange);
        /**
         * Сохраняем рейтинг
         */
        $oBlog->setRating($oBlog->getRating() + $iValue * $iDelta);
        return $iValue * $iDelta;
    }

    /**
     * Расчет рейтинга и силы при голосовании за пользователя
     *
     * @param ModuleUser_EntityUser $oUser
     * @param ModuleUser_EntityUser $oUserTarget
     * @param int                   $iValue
     *
     * @return float
     */
    public function VoteUser($oUser, $oUserTarget, $iValue) {
        /**
         * Начисляем силу и рейтинг юзеру, используя логарифмическое распределение
         */
        $skill = $oUser->getSkill();
        $iMinSize = 0.42;
        $iMaxSize = 3.2;
        $iSizeRange = $iMaxSize - $iMinSize;
        $iMinCount = log(0 + 1);
        $iMaxCount = log(500 + 1);
        $iCountRange = $iMaxCount - $iMinCount;
        if ($iCountRange == 0) {
            $iCountRange = 1;
        }
        if ($skill > 50 and $skill < 200) {
            $skill_new = $skill / 40;
        } elseif ($skill >= 200) {
            $skill_new = $skill / 2;
        } else {
            $skill_new = $skill / 70;
        }
        $iDelta = $iMinSize + (log($skill_new + 1) - $iMinCount) * ($iSizeRange / $iCountRange);
        /**
         * Определяем новый рейтинг
         */
        $iRatingNew = $oUserTarget->getRating() + $iValue * $iDelta;
        $oUserTarget->setRating($iRatingNew);
        return $iValue * $iDelta;
    }


    /**
     * Расчет рейтинга блога
     *
     * @return bool
     */
    public function RecalculateBlogRating() {

        /*
         * Получаем статистику
         */
        $aBlogStat = $this->Blog_GetBlogsData(array('personal'));

        foreach ($aBlogStat as $oBlog) {

            $fRating = 0;

            //*** Учет суммы голосов за топики с весовым коэффициентом
            $fRating = $fRating + Config::Get('module.rating.blog.topic_rating_sum') * $oBlog->getSumRating();

            //*** Учет количества топиков с весовым коэффициентом
            $fRating = $fRating + Config::Get('module.rating.blog.count_users') * $oBlog->getCountUser();

            //*** Учет количества топиков с весовым коэффициентом
            $fRating = $fRating + Config::Get('module.rating.blog.count_topic') * $oBlog->getCountTopic();

            $oBlog->setRating($fRating);
            $this->Blog_UpdateBlog($oBlog);

        }

        return true;
    }

}

// EOF