diff --git a/ugc/CMakeLists.txt b/ugc/CMakeLists.txt index 7bbab407e1..8d4da5489e 100644 --- a/ugc/CMakeLists.txt +++ b/ugc/CMakeLists.txt @@ -23,6 +23,7 @@ set( serdes_json.hpp storage.cpp storage.hpp + types.cpp types.hpp ) diff --git a/ugc/types.cpp b/ugc/types.cpp new file mode 100644 index 0000000000..104cd66a2b --- /dev/null +++ b/ugc/types.cpp @@ -0,0 +1,8 @@ +#include "ugc/types.hpp" + +namespace ugc +{ +float const UGC::kMaxRating; +float const UGC::kMinRating; +float const UGC::kRatingDetalizationThreshold; +} // namespace ugc diff --git a/ugc/types.hpp b/ugc/types.hpp index b10ac26a2d..496c5a9b3d 100644 --- a/ugc/types.hpp +++ b/ugc/types.hpp @@ -6,6 +6,7 @@ #include "coding/hex.hpp" +#include "base/assert.hpp" #include "base/math.hpp" #include "base/visitor.hpp" @@ -319,10 +320,23 @@ inline std::string DebugPrint(UGCUpdate const & ugcUpdate) struct UGC { + static float constexpr kMinRating = 0.0f; + static float constexpr kMaxRating = 10.0f; + // Ratings below threshold will be packed to ratings section without detalization (as single + // value). + static float constexpr kRatingDetalizationThreshold = 4.0f; + static_assert(kMinRating <= kRatingDetalizationThreshold && + kRatingDetalizationThreshold <= kMaxRating, + ""); + UGC() = default; UGC(Ratings const & records, Reviews const & reviews, float const totalRating, uint32_t basedOn) : m_ratings(records), m_reviews(reviews), m_totalRating(totalRating), m_basedOn(basedOn) { + float constexpr kEps = 0.01f; + CHECK_LESS(m_totalRating - kEps, kMaxRating, ()); + CHECK_GREATER(m_totalRating + kEps, kMinRating, ()); + m_totalRating = base::clamp(m_totalRating, kMinRating, kMaxRating); } DECLARE_VISITOR(visitor(m_ratings, "ratings"), visitor(m_reviews, "reviews"), @@ -362,8 +376,12 @@ struct UGC confidence = 3; uint8_t rating = 0; - if (m_totalRating > 4.0f) - rating = 1 + (m_totalRating - 4.0f) / 6.0f * 62.0f; + + if (m_totalRating > kRatingDetalizationThreshold) + { + rating = 1 + (m_totalRating - kRatingDetalizationThreshold) / + (kMaxRating - kRatingDetalizationThreshold) * 62.0f; + } rating = base::clamp(rating, static_cast(0), static_cast(63)); return confidence << 6 | rating; @@ -376,10 +394,13 @@ struct UGC { uint8_t const confidence = packed >> 6; - float rating = 4.0; + float rating = kRatingDetalizationThreshold; uint8_t const packedRating = packed & 63; if (packedRating > 0) - rating = 4.0f + static_cast(packedRating - 1) / 62.0f * 6.0f; + { + rating = kRatingDetalizationThreshold + static_cast(packedRating - 1) / 62.0f * + (kMaxRating - kRatingDetalizationThreshold); + } return std::make_pair(confidence, rating); } diff --git a/xcode/ugc/ugc.xcodeproj/project.pbxproj b/xcode/ugc/ugc.xcodeproj/project.pbxproj index e426b287d7..b8257af344 100644 --- a/xcode/ugc/ugc.xcodeproj/project.pbxproj +++ b/xcode/ugc/ugc.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 3D74EF041F86840C0081202C /* loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D74EF021F86840C0081202C /* loader.cpp */; }; 3D74EF1E1F8B94EA0081202C /* serdes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D74EF1A1F8B90B00081202C /* serdes.cpp */; }; 407E8A152265FEF200C6E668 /* ratings_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 407E8A142265FEF100C6E668 /* ratings_tests.cpp */; }; + 40B4381D2269D75D003B1D5A /* types.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 40B4381C2269D75D003B1D5A /* types.cpp */; }; 670E7B981EF97D1000A8E9ED /* serdes_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 670E7B941EF97CE700A8E9ED /* serdes_tests.cpp */; }; 670E7B991EF97D1600A8E9ED /* testingmain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 670E7B961EF97D0E00A8E9ED /* testingmain.cpp */; }; 670E7B9B1EF9803C00A8E9ED /* libbase.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 670E7B9A1EF9803C00A8E9ED /* libbase.a */; }; @@ -65,6 +66,7 @@ 3D74EF1C1F8B90B00081202C /* ugc_holder.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ugc_holder.hpp; sourceTree = ""; }; 3D74EF1D1F8B90B00081202C /* visitors.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = visitors.hpp; sourceTree = ""; }; 407E8A142265FEF100C6E668 /* ratings_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ratings_tests.cpp; sourceTree = ""; }; + 40B4381C2269D75D003B1D5A /* types.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = types.cpp; sourceTree = ""; }; 670E7B7C1EF97C1000A8E9ED /* ugc_tests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ugc_tests.app; sourceTree = BUILT_PRODUCTS_DIR; }; 670E7B941EF97CE700A8E9ED /* serdes_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = serdes_tests.cpp; sourceTree = ""; }; 670E7B961EF97D0E00A8E9ED /* testingmain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = testingmain.cpp; path = ../../testing/testingmain.cpp; sourceTree = ""; }; @@ -220,6 +222,7 @@ F6150E201EF90040000B955D /* api.hpp */, 670E7BD01EFA6D7400A8E9ED /* serdes_json.hpp */, 670E7BA61EF980E900A8E9ED /* serdes.hpp */, + 40B4381C2269D75D003B1D5A /* types.cpp */, F6150E211EF90040000B955D /* types.hpp */, ); name = ugc; @@ -358,6 +361,7 @@ buildActionMask = 2147483647; files = ( F6150E221EF90040000B955D /* api.cpp in Sources */, + 40B4381D2269D75D003B1D5A /* types.cpp in Sources */, F63EE67620D3F6B40025CC27 /* utility.cpp in Sources */, 407E8A152265FEF200C6E668 /* ratings_tests.cpp in Sources */, 3D74EF1E1F8B94EA0081202C /* serdes.cpp in Sources */,