~aleteoryx/muditaos

d6535a9814e458e7b952d17cd00507ef34930567 — Lefucjusz 2 years ago 2643d9a
[MOS-238] Change RNG used in quotes randomization

* Changed RNG used when randomizing quotes list
that was accidentally omitted in the previous
PR.
* Small cleanup around RandomizedQuoteModel.
M module-services/service-db/agents/quotes/QuotesAgent.cpp => module-services/service-db/agents/quotes/QuotesAgent.cpp +12 -23
@@ 1,10 1,9 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QuotesAgent.hpp"
#include "QuotesQueries.hpp"

//#include <Application.hpp>
#include <Common/Query.hpp>

namespace Quotes


@@ 15,8 14,7 @@ namespace Quotes
        : predefinedDB(predefinedQuotesDB), customDB(customQuotesDB),
          randomizedQuoteModel(std::move(settings), predefinedQuotesDB, customQuotesDB)
    {
        constexpr auto forced = false;
        randomizedQuoteModel.updateList(forced);
        randomizedQuoteModel.updateList(ListUpdateMode::Normal);
    }

    auto QuotesAgent::runQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>


@@ 66,9 64,8 @@ namespace Quotes
    {
        auto req              = std::dynamic_pointer_cast<Messages::EnableCategoryByIdRequest>(query);
        auto queryResult      = predefinedDB->execute(Queries::enableCategory, req->enable, req->categoryId);
        auto response         = std::make_unique<Messages::EnableCategoryByIdResponse>(std::move(queryResult));
        constexpr auto forced = true;
        randomizedQuoteModel.updateList(forced);
        auto response         = std::make_unique<Messages::EnableCategoryByIdResponse>(queryResult);
        randomizedQuoteModel.updateList(ListUpdateMode::Forced);
        response->setRequestQuery(query);
        return response;
    }


@@ 89,8 86,7 @@ namespace Quotes
        auto req              = std::dynamic_pointer_cast<Messages::EnableQuoteByIdRequest>(query);
        auto queryResult      = customDB->execute(Queries::enableQuote, req->enable, req->quoteId);
        auto response         = std::make_unique<Messages::EnableQuoteByIdResponse>(queryResult);
        constexpr auto forced = true;
        randomizedQuoteModel.updateList(forced);
        randomizedQuoteModel.updateList(ListUpdateMode::Forced);
        response->setRequestQuery(query);
        return response;
    }


@@ 102,8 98,7 @@ namespace Quotes
        auto success = customDB->execute(Queries::addQuote, req->quote.c_str(), req->author.c_str(), req->enabled);

        if (success) {
            constexpr auto forced = true;
            randomizedQuoteModel.updateList(forced);
            randomizedQuoteModel.updateList(ListUpdateMode::Forced);
        }
        auto quoteId  = customDB->getLastInsertRowId();
        auto response = std::make_unique<Messages::AddQuoteResponse>(success, quoteId);


@@ 125,22 120,19 @@ namespace Quotes
            queryResult = customDB->query(Queries::readCustomQuote, randomizedId);
        }

        if (queryResult->getRowCount()) {
            QuoteRecord quoteRecord(queryResult.get());
        if (queryResult->getRowCount() > 0) {
            const QuoteRecord quoteRecord(queryResult.get());
            auto response = std::make_unique<Messages::ReadRandomizedQuoteResponse>(
                quoteRecord.quote_id, quoteRecord.quote, quoteRecord.author);
            response->setRequestQuery(query);
            return response;
        }
        else {
            return nullptr;
        }
        return nullptr;
    }

    void QuotesAgent::handleInformLanguageChange()
    {
        constexpr auto forced = true;
        randomizedQuoteModel.updateList(forced);
        randomizedQuoteModel.updateList(ListUpdateMode::Forced);
    }

    auto QuotesAgent::handleWriteQuote(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>


@@ 148,8 140,7 @@ namespace Quotes
        auto req = std::dynamic_pointer_cast<Messages::WriteQuoteRequest>(query);
        auto queryResult =
            customDB->execute(Queries::writeQuote, req->quote.c_str(), req->author.c_str(), req->enabled, req->quoteId);
        constexpr auto forced = true;
        randomizedQuoteModel.updateList(forced);
        randomizedQuoteModel.updateList(ListUpdateMode::Forced);
        auto response = std::make_unique<Messages::WriteQuoteResponse>(queryResult);
        response->setRequestQuery(query);
        return response;


@@ 159,11 150,9 @@ namespace Quotes
    {
        auto req              = std::dynamic_pointer_cast<Messages::DeleteQuoteRequest>(query);
        auto queryResult      = customDB->execute(Queries::deleteQuote, req->quoteId);
        constexpr auto forced = true;
        randomizedQuoteModel.updateList(forced);
        randomizedQuoteModel.updateList(ListUpdateMode::Forced);
        auto response = std::make_unique<Messages::DeleteQuoteResponse>(queryResult);
        response->setRequestQuery(query);
        return response;
    }

} // namespace Quotes

M module-services/service-db/agents/quotes/QuotesSettingsSerializer.cpp => module-services/service-db/agents/quotes/QuotesSettingsSerializer.cpp +1 -2
@@ 1,8 1,7 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QuotesSettingsSerializer.hpp"
#include <log/log.hpp>
#include <module-utils/utility/Utils.hpp>

namespace Quotes

M module-services/service-db/agents/quotes/RandomizedQuoteModel.cpp => module-services/service-db/agents/quotes/RandomizedQuoteModel.cpp +16 -16
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "RandomizedQuoteModel.hpp"


@@ 6,27 6,26 @@

#include "log/log.hpp"
#include <service-db/agents/settings/SystemSettings.hpp>
#include <algorithm> // std::random_shuffle
#include <memory>
#include <sstream>
#include <bsp/trng/trng.hpp>

namespace Quotes
{
    constexpr inline auto zeroOffset = 0;
    constexpr inline auto maxLimit   = std::numeric_limits<unsigned int>().max();
    RandomizedQuoteModel::RandomizedQuoteModel(std::unique_ptr<settings::Settings> settings,
                                               Database *predefinedQuotesDB,
                                               Database *customQuotesDB)
        : settings(std::move(settings)), predefinedQuotesDB(predefinedQuotesDB), customQuotesDB(customQuotesDB),
          serializer(std::make_unique<QuotesSettingsSerializer>())
          serializer(std::make_unique<QuotesSettingsSerializer>()), rngEngine{std::make_unique<std::mt19937>(
                                                                        bsp::trng::getRandomValue())}
    {}

    void RandomizedQuoteModel::randomize(IdList &list)
    {
        srand(time(NULL));
        std::random_shuffle(std::begin(list), std::end(list));
        std::shuffle(std::begin(list), std::end(list), *rngEngine);
    }
    void RandomizedQuoteModel::updateList(bool forced)

    void RandomizedQuoteModel::updateList(ListUpdateMode updateMode)
    {
        auto queryResult      = customQuotesDB->query(Queries::getEnabledCustomQuotes);
        auto customQuotesList = getList<QuotesList, QuoteRecord>(zeroOffset, maxLimit, std::move(queryResult));


@@ 34,11 33,12 @@ namespace Quotes
        queryResult =
            predefinedQuotesDB->query(Queries::getEnabledPredefinedQuotes, utils::getDisplayLanguage().c_str());
        auto predefinedQuotesList = getList<QuotesList, QuoteRecord>(zeroOffset, maxLimit, std::move(queryResult));
        populateList(std::move(predefinedQuotesList), std::move(customQuotesList), forced);
        populateList(std::move(predefinedQuotesList), std::move(customQuotesList), updateMode);
    }

    void RandomizedQuoteModel::populateList(std::unique_ptr<QuotesList> predefinedQuotesList,
                                            std::unique_ptr<QuotesList> customQuotesList,
                                            bool forcedUpdate)
                                            ListUpdateMode updateMode)
    {
        IdList list;
        for (const auto &item : predefinedQuotesList->data) {


@@ 49,7 49,7 @@ namespace Quotes
        }

        randomize(list);
        if (not forcedUpdate) {
        if (updateMode == ListUpdateMode::Normal) {
            auto settingsList = settings->getValue(settings::Quotes::randomQuotesList, settings::SettingsScope::Global);
            if (not settingsList.empty()) {
                return;


@@ 57,7 57,7 @@ namespace Quotes
        }
        settings->setValue(
            settings::Quotes::randomQuotesList, serializer->serialize(list), settings::SettingsScope::Global);
        LOG_ERROR("ID queue length: %zu", list.size());
        LOG_INFO("ID queue length: %zu", list.size());
    }

    auto RandomizedQuoteModel::getId() -> QuoteID


@@ 81,7 81,7 @@ namespace Quotes
        }

        if (list.empty()) {
            updateList(true);
            updateList(ListUpdateMode::Forced);
        }
        else {
            settings->setValue(


@@ 94,9 94,9 @@ namespace Quotes
    }
    auto RandomizedQuoteModel::isIdExpired() -> bool
    {
        auto lastTimestampString =
        const auto lastTimestampString =
            settings->getValue(settings::Quotes::randomQuoteIDUpdateTime, settings::SettingsScope::Global);
        long lastTimestamp;
        time_t lastTimestamp;

        try {
            lastTimestamp = stol(lastTimestampString);


@@ 106,7 106,7 @@ namespace Quotes
            lastTimestamp = 0;
        }

        auto currentTimestamp = std::time(nullptr);
        const auto currentTimestamp = std::time(nullptr);
        if ((currentTimestamp - lastTimestamp) >= quotesChangingInterval) {
            lastTimestamp = currentTimestamp;
            settings->setValue(settings::Quotes::randomQuoteIDUpdateTime,

M module-services/service-db/agents/quotes/RandomizedQuoteModel.hpp => module-services/service-db/agents/quotes/RandomizedQuoteModel.hpp +14 -4
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 12,28 12,38 @@
namespace Quotes
{
    using namespace std::chrono;
    inline constexpr auto quotesChangingInterval = duration_cast<seconds>(hours{24}).count();

    enum class ListUpdateMode
    {
        Normal,
        Forced
    };

    class RandomizedQuoteModel
    {
      private:
        static constexpr auto zeroOffset             = 0;
        static constexpr auto maxLimit               = std::numeric_limits<unsigned>::max();
        static constexpr auto quotesChangingInterval = duration_cast<seconds>(24h).count();

        app::ApplicationCommon *app = nullptr;
        std::unique_ptr<settings::Settings> settings;
        Database *predefinedQuotesDB = nullptr;
        Database *customQuotesDB     = nullptr;
        void populateList(std::unique_ptr<QuotesList> predefinedQuotesList,
                          std::unique_ptr<QuotesList> customQuotesList,
                          bool forcedUpdate = false);
                          ListUpdateMode updateMode = ListUpdateMode::Normal);
        void shiftIdList();
        auto isIdExpired() -> bool;
        void randomize(IdList &list);
        std::unique_ptr<QuotesSettingsSerializer> serializer;
        std::unique_ptr<std::mt19937> rngEngine;

      public:
        RandomizedQuoteModel(std::unique_ptr<settings::Settings> settings,
                             Database *predefinedQuotesDB,
                             Database *customQuotesDB);
        void updateList(bool forced);
        void updateList(ListUpdateMode updateMode);
        [[nodiscard]] auto getId() -> QuoteID;
    };