/
BirdLeon
/
ROBLOX2016
Обзор
Документация
Войти
/
BirdLeon
/
ROBLOX2016
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
App/util/Statistics.cpp
381 строка
10 KB
PatoFlamejanteTV
full source code
19 дек 2024, 19:11
19 дек 2024, 19:11
05db15d
Код
Авторство
О чём код?
#include "stdafx.h" #undef min #undef max #include "Util/Statistics.h" #include <sstream> #include <algorithm> #include "RbxFormat.h" #include "util/StandardOut.h" #include "util/Http.h" #include "format_string.h" #include "SimpleJSON.h" #include "util/FileSystem.h" #include "rbx/rbxTime.h" #include "RobloxServicesTools.h" #include "v8xml/WebParser.h" #include "util/RobloxGoogleAnalytics.h" #include <boost/algorithm/string/predicate.hpp> LOGGROUP(ClientSettings); ABTEST_NEWSTUDIOUSERS_VARIABLE(DummyTest); #ifdef RBX_TEST_BUILD static std::string defaultFilePath; void SetDefaultFilePath(const std::string &path) { defaultFilePath = path; } const std::string &GetDefaultFilePath() { return defaultFilePath; } #endif static std::string defaultBaseUrl; void SetBaseURL(const std::string& baseUrl) { defaultBaseUrl = baseUrl; } const std::string& GetBaseURL() { return defaultBaseUrl; } std::string RBX::Http::urlEncode(const std::string& url) { std::string result; const size_t strLen = url.size(); for (unsigned i=0; i < strLen; i++) { unsigned char c = url[i]; if ( (c<=47) || (c>=58 && c<=64) || (c>=91 && c<=96) || (c>=123) ) { result += RBX::format("%%%02X", c); } else result += c; } return result; } std::string RBX::Http::urlDecode(const std::string& fragment) { std::string result; const size_t strLen = fragment.size(); std::string::size_type i = 0; char hexBuffer[3]; while (i < strLen) { unsigned char c = fragment[i]; if (c == '%') { RBXASSERT((i + 3) <= strLen); hexBuffer[0] = fragment[i + 1]; hexBuffer[1] = fragment[i + 2]; hexBuffer[2] = '\0'; result += (char)strtol(hexBuffer, NULL, 16); i += 3; } else { result += c; ++i; } } return result; } std::string UploadLogFile(const std::string& baseUrl, const std::string& data) { try { std::stringstream request; request << baseUrl + "/Analytics/LogFile.ashx" << char(0); std::stringstream dataStream; dataStream << data << char(0); std::string result; RBX::Http(request.str()).post(dataStream, RBX::Http::kContentTypeDefaultUnspecified, true, result); return result; } catch(std::bad_alloc&) { throw; } catch(RBX::base_exception&) { return ""; } } bool FetchLocalClientSettingsData(const char* group, SimpleJSON* dest) { std::string localSettingsData; // Load from file boost::filesystem::path localFilename = RBX::FileSystem::getUserDirectory(false, RBX::DirExe, "ClientSettings") / (group + std::string(".json")); std::ifstream localConfigFile(localFilename.native().c_str()); if(localConfigFile.is_open()) { std::stringstream localConfigBuffer; localConfigBuffer << localConfigFile.rdbuf(); localSettingsData = localConfigBuffer.str(); if(localSettingsData.length() > 0) { FASTLOG(FLog::ClientSettings, "Found local json file"); dest->ReadFromStream(localSettingsData.c_str()); return true; } } return false; } void LoadClientSettingsFromString(const char* group, const std::string& settingsData, SimpleJSON* dest) { FASTLOGS(FLog::ClientSettings, "Loading group %s", group); if(settingsData.length() > 0) { dest->ReadFromStream(settingsData.c_str()); } bool localDataFetched = FetchLocalClientSettingsData(group, dest); if(localDataFetched && settingsData.length() == 0) { FASTLOG(FLog::ClientSettings, "Couldn't find any data to fetch"); } } // returns if the fetch from web was successful, useful if you want to terminate the operation if web fetch fails bool FetchClientSettingsData(const char* group, const char* apiKey, SimpleJSON* dest) { bool fetchedFromWeb = false; std::string settingsData = ""; FetchClientSettingsData(group, apiKey, &settingsData); if (settingsData.length()) fetchedFromWeb = true; LoadClientSettingsFromString(group, settingsData, dest); return fetchedFromWeb; } void FetchClientSettingsData(const char* group, const char* apiKey, std::string* dest) { FASTLOGS(FLog::ClientSettings, "Loading group %s to string", group); const std::string& baseUrl = GetBaseURL(); if (baseUrl.size()==0) RBXCRASH(); // You didn't set BaseURL before loading settings! std::string url = GetSettingsUrl(baseUrl, group, apiKey); RBX::Http request(url); try { request.get(*dest); } catch (RBX::base_exception&) { FASTLOG(FLog::Always, "FetchClientSettingsData exception"); } } RBX::HttpFuture FetchClientSettingsDataAsync(const char* group, const char* apiKey) { FASTLOGS(FLog::ClientSettings, "Loading group %s to string", group); const std::string& baseUrl = GetBaseURL(); if (baseUrl.size()==0) RBXCRASH(); // You didn't set BaseURL before loading settings! std::string url = GetSettingsUrl(baseUrl, group, apiKey); return RBX::HttpAsync::get(url); } struct ABPass { std::string entry; shared_ptr<RBX::Reflection::ValueArray> experiments; }; void addABTest(const std::string& name, const std::string& value, void* context) { ABPass* pass = (ABPass*)context; shared_ptr<RBX::Reflection::ValueTable> experimentTable = rbx::make_shared<RBX::Reflection::ValueTable>(); (*experimentTable)["Name"] = name; (*experimentTable)["Type"] = pass->entry; pass->experiments->push_back(shared_ptr<const RBX::Reflection::ValueTable>(experimentTable)); } RBX::HttpFuture FetchABTestDataAsync(const std::string& url) { FASTLOG(FLog::ClientSettings, "Loading AB tests to http future"); shared_ptr<RBX::Reflection::ValueArray> experiments = rbx::make_shared<RBX::Reflection::ValueArray>(); ABPass passData; passData.experiments = experiments; passData.entry = "NewUsers"; FLog::ForEachVariable(addABTest, &passData, FASTVARTYPE_AB_NEWUSERS); passData.entry = "NewStudioUsers"; FLog::ForEachVariable(addABTest, &passData, FASTVARTYPE_AB_NEWSTUDIOUSERS); passData.entry = "AllUsers"; FLog::ForEachVariable(addABTest, &passData, FASTVARTYPE_AB_ALLUSERS); std::string jsonRequest; RBX::WebParser::writeJSON(shared_ptr<const RBX::Reflection::ValueArray>(experiments), jsonRequest); RBX::HttpPostData postData(jsonRequest, RBX::Http::kContentTypeApplicationJson, false); return RBX::HttpAsync::post(url, postData); } std::string LoadABTestFromString(const std::string& responseData) { std::string trackerId = ""; shared_ptr<const RBX::Reflection::ValueTable> jsonResponse; bool result = RBX::WebParser::parseJSONTable(responseData, jsonResponse); RBXASSERT(result); if(!result) return trackerId; try { shared_ptr<const RBX::Reflection::ValueTable> experiments = jsonResponse->at("Experiments").cast<shared_ptr<const RBX::Reflection::ValueTable> >(); for(RBX::Reflection::ValueTable::const_iterator it = experiments->begin(); it != experiments->end(); ++it) { shared_ptr<const RBX::Reflection::ValueTable> experimentDesc = it->second.cast<shared_ptr<const RBX::Reflection::ValueTable> >(); int value = experimentDesc->at("Variation").cast<int>(); bool locked = experimentDesc->at("IsLocked").cast<bool>(); // -1, 0, 1 and 2 are control groups, 3+ are variations int variation = std::max(value - 2, 0); FLog::SetValue(it->first, RBX::StringConverter<int>::convertToString(variation)); if(value > 0 && !locked) { RBX::RobloxGoogleAnalytics::setExperimentVariation(it->first, value); } } if(jsonResponse->find("BrowserTrackerId") != jsonResponse->end()) trackerId = jsonResponse->at("BrowserTrackerId").cast<std::string>(); } catch(std::exception& e) { RBXASSERT(false); FASTLOGS(FLog::ClientSettings, "Failed to parse AB test JSON - %s", e.what()); } return trackerId; } void ReportStatisticPost(const std::string& baseUrl, const std::string& id, const std::string& postData, const char* primaryFilterName, const char* primaryFilterValue, const char* secondaryFilterName, const char* secondaryFilterValue); void ReportStatisticWithMessage(const std::string& baseUrl, const std::string& id, const std::string& simpleMessage, const char* secondaryFilterName, const char* secondaryFilterValue) { std::stringstream data; if(simpleMessage.length() > 0){ std::string messageStr(simpleMessage); while(messageStr.find("\n") != std::string::npos){ messageStr.replace(messageStr.find("\n"),1,"%20"); } while(messageStr.find("\t") != std::string::npos){ messageStr.replace(messageStr.find("\t"),1,"%20"); } data << "string\tmessage\t" << messageStr; } data << char(0); ReportStatisticPost(baseUrl, id, data.str(), NULL, NULL, secondaryFilterName, secondaryFilterValue); } void ReportStatistic(const std::string& baseUrl, const std::string& id, const std::string& primaryFilterName, const std::string& primaryFilterValue, const std::string& secondaryFilterName, const std::string& secondaryFilterValue) { ReportStatisticPost(baseUrl, id, "", primaryFilterName.empty() ? 0 : primaryFilterName.c_str(), // 0 means use IPFilter! primaryFilterValue.c_str(), secondaryFilterName.c_str(), secondaryFilterValue.c_str()); } void ReportStatisticPost(const std::string& baseUrl, const std::string& id, const std::string& postData, const char* secondaryFilterName, const char* secondaryFilterValue) { ReportStatisticPost(baseUrl, id, postData, NULL, NULL, secondaryFilterName, secondaryFilterValue); } void DontCareResponse(std::string* response, std::exception* exception) { } void ReportStatisticPost(const std::string& baseUrl, const std::string& id, const std::string& postData, const char* primaryFilterName, const char* primaryFilterValue, const char* secondaryFilterName, const char* secondaryFilterValue) { try { std::string idStr = std::string("ROBLOXAPP ") + std::string(id); idStr = RBX::Http::urlEncode(idStr); std::stringstream request; request << baseUrl + "/Analytics/Measurement.ashx?Type=" << idStr; if (primaryFilterName) { request << "&FilterName=" << primaryFilterName << "&FilterValue=" << primaryFilterValue; } else request << "&IpFilter=primary"; if (secondaryFilterName) request << "&SecondaryFilterName=" << secondaryFilterName << "&SecondaryFilterValue=" << secondaryFilterValue; request << char(0); std::string result; if(postData.length() > 0){ RBX::Http(request.str()).post(postData, RBX::Http::kContentTypeDefaultUnspecified, true, &DontCareResponse); } else{ RBX::Http(request.str()).get(&DontCareResponse); } } catch (RBX::base_exception& e) { std::stringstream log; log << "ReportStat '" << id << "' failed. " << e.what() << '\n'; RBX::StandardOut::singleton()->printf(RBX::MESSAGE_ERROR,"%s",log.str().c_str()); } }