Exemplo n.º 1
0
void ItemsManagerWorker::Update(TabCache::Policy policy, const std::vector<ItemLocation> &tab_names) {
    if (updating_) {
        QLOG_WARN() << "ItemsManagerWorker::Update called while updating";
        return;
    }

    if (policy == TabCache::ManualCache) {
        for (auto const &tab: tab_names)
            tab_cache_->AddManualRefresh(tab);
    }

    tab_cache_->OnPolicyUpdate(policy);

    QLOG_DEBUG() << "Updating stash tabs";
    updating_ = true;
    // remove all mappings (from previous requests)
    if (signal_mapper_)
        delete signal_mapper_;
    signal_mapper_ = new QSignalMapper;
    // remove all pending requests
    queue_ = std::queue<ItemsRequest>();
    queue_id_ = 0;
    replies_.clear();
    items_.clear();
    tabs_as_string_ = "";
    selected_character_ = "";

    // first, download the main page because it's the only way to know which character is selected
    QNetworkReply *main_page = network_manager_.get(Request(QUrl(kMainPage), ItemLocation(), TabCache::Refresh));
    connect(main_page, &QNetworkReply::finished, this, &ItemsManagerWorker::OnMainPageReceived);
}
Exemplo n.º 2
0
void ItemsManagerWorker::Init() {
    items_.clear();
    std::string items = data_.Get("items");
    if (items.size() != 0) {
        rapidjson::Document doc;
        doc.Parse(items.c_str());
        for (auto item = doc.Begin(); item != doc.End(); ++item)
            items_.push_back(std::make_shared<Item>(*item));
    }

    tabs_.clear();
    std::string tabs = data_.Get("tabs");
    if (tabs.size() != 0) {
        rapidjson::Document doc;
        if (doc.Parse(tabs.c_str()).HasParseError()) {
            QLOG_ERROR() << "Malformed tabs data:" << tabs.c_str() << "The error was"
                         << rapidjson::GetParseError_En(doc.GetParseError());
            return;
        }
        for (auto &tab : doc) {
            if (!tab.HasMember("n") || !tab["n"].IsString()) {
                QLOG_ERROR() << "Malformed tabs data:" << tabs.c_str() << "Tab doesn't contain its name (field 'n').";
                continue;
            }
            auto index = tab["i"].GetInt();
            // Index 0 is 'hidden' so we don't want to display
            if (index != 0)
                tabs_.push_back(ItemLocation(index, tab["n"].GetString()));
        }
    }
    emit ItemsRefreshed(items_, tabs_, true);
}
Exemplo n.º 3
0
void ItemsManagerWorker::OnFirstTabReceived() {
    QNetworkReply *reply = qobject_cast<QNetworkReply *>(QObject::sender());
    QByteArray bytes = reply->readAll();
    rapidjson::Document doc;
    doc.Parse(bytes.constData());

    if (!doc.IsObject()) {
        QLOG_ERROR() << "Can't even fetch first tab. Failed to update items.";
        updating_ = false;
        return;
    }
    if (!doc.HasMember("tabs") || doc["tabs"].Size() == 0) {
        QLOG_WARN() << "There are no tabs, this should not happen, bailing out.";
        updating_ = false;
        return;
    }

    tabs_as_string_ = Util::RapidjsonSerialize(doc["tabs"]);

    QLOG_DEBUG() << "Received tabs list, there are" << doc["tabs"].Size() << "tabs";
    tabs_.clear();

    // Create tab location objects
    for (auto &tab : doc["tabs"]) {
        std::string label = tab["n"].GetString();
        auto index = tab["i"].GetInt();
        // Ignore hidden locations
        if (!doc["tabs"][index].HasMember("hidden") || !doc["tabs"][index]["hidden"].GetBool())
            tabs_.push_back(ItemLocation(index, label, ItemLocationType::STASH));
    }

    // Immediately parse items received from this tab (first_fetch_tab_) and Queue requests for the others
    for (auto const &tab: tabs_) {
        auto index = tab.get_tab_id();
        if (index == first_fetch_tab_) {
            ParseItems(&doc["items"], tab, doc.GetAllocator());
        } else {
            QueueRequest(MakeTabRequest(index, tab), tab);
        }
    }

    total_needed_ = queue_.size() + 1;
    total_completed_ = 1;
    total_cached_ = reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool() ? 1:0;

    FetchItems(kThrottleRequests - 1);

    connect(signal_mapper_, SIGNAL(mapped(int)), this, SLOT(OnTabReceived(int)));
    reply->deleteLater();
}
Exemplo n.º 4
0
void ItemsManagerWorker::OnCharacterListReceived() {
    QNetworkReply *reply = qobject_cast<QNetworkReply *>(QObject::sender());
    QByteArray bytes = reply->readAll();
    rapidjson::Document doc;
    doc.Parse(bytes.constData());

    if (doc.HasParseError() || !doc.IsArray()) {
        QLOG_ERROR() << "Received invalid reply instead of character list. The reply was"
                     << bytes.constData();
        if (doc.HasParseError()) {
            QLOG_ERROR() << "The error was" << rapidjson::GetParseError_En(doc.GetParseError());
        }
        updating_ = false;
        return;
    }

    QLOG_DEBUG() << "Received character list, there are" << doc.Size() << "characters";
    for (auto &character : doc) {
        if (!character.HasMember("league") || !character.HasMember("name") || !character["league"].IsString() || !character["name"].IsString()) {
            QLOG_ERROR() << "Malformed character entry, the reply is most likely invalid" << bytes.constData();
            continue;
        }
        if (character["league"].GetString() == league_) {
            std::string name = character["name"].GetString();
            ItemLocation location;
            location.set_type(ItemLocationType::CHARACTER);
            location.set_character(name);
            QueueRequest(MakeCharacterRequest(name, location), location);
        }
    }

    // Fetch a single tab and also request tabs list.  We can fetch any tab here with tabs list
    // appended, so prefer one that the user has already 'checked'.  Default to index '1' which is
    // first user visible tab.
    first_fetch_tab_ = 1;
    for (auto const &tab : tabs_) {
        if (bo_manager_.GetRefreshChecked(tab)) {
            first_fetch_tab_ = tab.get_tab_id();
            break;
        }
    }

    QNetworkReply *first_tab = network_manager_.get(MakeTabRequest(first_fetch_tab_, ItemLocation(), true));
    connect(first_tab, SIGNAL(finished()), this, SLOT(OnFirstTabReceived()));
    reply->deleteLater();
}
Exemplo n.º 5
0
Item::Item(const rapidjson::Value &json) :
    location_(ItemLocation(json)),
    name_(correct_name(json["name"].GetString())),
    typeLine_(correct_name(json["typeLine"].GetString())),
    corrupted_(json["corrupted"].GetBool()),
    w_(json["w"].GetInt()),
    h_(json["h"].GetInt()),
    frameType_(json["frameType"].GetInt()),
    icon_(json["icon"].GetString()),
    sockets_cnt_(0),
    links_cnt_(0),
    sockets_({ 0, 0, 0, 0 }),
    has_mtx_(false)
{
    for (auto &mod_type : ITEM_MOD_TYPES) {
        text_mods_[mod_type] = std::vector<std::string>();
        if (json.HasMember(mod_type.c_str())) {
            auto &mods = text_mods_[mod_type];
            for (auto &mod : json[mod_type.c_str()])
                mods.push_back(mod.GetString());
        }
    }

    if (json.HasMember("properties")) {
        for (auto prop_it = json["properties"].Begin(); prop_it != json["properties"].End(); ++prop_it) {
            auto &prop = *prop_it;
            std::string name = prop["name"].GetString();
            if (name == "Уровень карты")
                name = "Уровень";
            if (name == "Урон от стихий") {
                for (auto value_it = prop["values"].Begin(); value_it != prop["values"].End(); ++value_it)
                    elemental_damage_.push_back(std::make_pair((*value_it)[0].GetString(), (*value_it)[1].GetInt()));
            }
            else {
                if (prop["values"].Size())
                    properties_[name] = prop["values"][0][0].GetString();
            }

            ItemProperty property;
            property.name = name;
            property.display_mode = prop["displayMode"].GetInt();
            for (auto &value : prop["values"])
                property.values.push_back(value[0].GetString());
            text_properties_.push_back(property);
        }
    }

    if (json.HasMember("requirements")) {
        for (auto &req : json["requirements"]) {
            std::string name = req["name"].GetString();
            std::string value = req["values"][0][0].GetString();
            requirements_[name] = std::atoi(value.c_str());
            text_requirements_.push_back({ name, value });
        }
    }

    if (json.HasMember("sockets")) {
        ItemSocketGroup current_group = { 0, 0, 0, 0 };
        sockets_cnt_ = json["sockets"].Size();
        int counter = 0, prev_group = -1;
        for (auto &socket : json["sockets"]) {
            ItemSocket current_socket = { static_cast<unsigned char>(socket["group"].GetInt()), socket["attr"].GetString()[0] };
            text_sockets_.push_back(current_socket);
            if (prev_group != current_socket.group) {
                counter = 0;
                socket_groups_.push_back(current_group);
                current_group = { 0, 0, 0, 0 };
            }
            prev_group = current_socket.group;
            ++counter;
            links_cnt_ = std::max(links_cnt_, counter);
            switch (current_socket.attr) {
            case 'S':
                sockets_.r++;
                current_group.r++;
                break;
            case 'D':
                sockets_.g++;
                current_group.g++;
                break;
            case 'I':
                sockets_.b++;
                current_group.b++;
                break;
            case 'G':
                sockets_.w++;
                current_group.w++;
                break;
            }
        }
        socket_groups_.push_back(current_group);
    }

    std::string hashes[3];
    for (int i = 0; i < 3; i++) {
        std::string unique(name_ + "~" + typeLine_ + "~");

        if (i == 2) {
            // Strip off last "~" (a mistake from 0.3)
            unique = unique.substr(0, unique.length() - 1);
        }

        if (json.HasMember("explicitMods"))
            for (auto mod_it = json["explicitMods"].Begin(); mod_it != json["explicitMods"].End(); ++mod_it)
                unique += std::string(mod_it->GetString()) + "~";

        if (json.HasMember("implicitMods"))
            for (auto mod_it = json["implicitMods"].Begin(); mod_it != json["implicitMods"].End(); ++mod_it)
                unique += std::string(mod_it->GetString()) + "~";

        unique += item_unique_properties(json, "properties") + "~";
        unique += item_unique_properties(json, "additionalProperties") + "~";

        if (json.HasMember("sockets"))
            for (auto socket_it = json["sockets"].Begin(); socket_it != json["sockets"].End(); ++socket_it)
                unique += std::to_string((*socket_it)["group"].GetInt()) + "~" + (*socket_it)["attr"].GetString() + "~";

        // This will only effect corrupted item's new hashes...
        if (i == 1 && corrupted())
            unique += "corrupted";

        hashes[i] = Util::Md5(unique);
    }
    old_hash_ = hashes[0];
    hash_ = hashes[1];
    broken_hash_ = hashes[2];

    count_ = 1;
    if (properties_.find("Размер стопки") != properties_.end()) {
        std::string size = properties_["Размер стопки"];
        if (size.find("/") != std::string::npos) {
            size = size.substr(0, size.find("/"));
            count_ = std::stoi(size);
        }
    }

    has_mtx_ = json.HasMember("cosmeticMods");

    GenerateMods(json);
}
Exemplo n.º 6
0
Item::Item(const rapidjson::Value &json) :
    name_(fixup_name(json["name"].GetString())),
    location_(ItemLocation(json)),
    typeLine_(fixup_name(json["typeLine"].GetString())),
    corrupted_(json["corrupted"].GetBool()),
    identified_(json["identified"].GetBool()),
    w_(json["w"].GetInt()),
    h_(json["h"].GetInt()),
    frameType_(json["frameType"].GetInt()),
    icon_(json["icon"].GetString()),
    sockets_cnt_(0),
    links_cnt_(0),
    sockets_({ 0, 0, 0, 0 }),
    json_(Util::RapidjsonSerialize(json)),
    has_mtx_(false),
    ilvl_(0)
{
    for (auto &mod_type : ITEM_MOD_TYPES) {
        text_mods_[mod_type] = std::vector<std::string>();
        if (json.HasMember(mod_type.c_str())) {
            auto &mods = text_mods_[mod_type];
            for (auto &mod : json[mod_type.c_str()])
                mods.push_back(mod.GetString());
        }
    }

    if (json.HasMember("note")) {
        note_ = json["note"].GetString();
    }

    if (json.HasMember("properties")) {
        for (auto prop_it = json["properties"].Begin(); prop_it != json["properties"].End(); ++prop_it) {
            auto &prop = *prop_it;
            std::string name = prop["name"].GetString();
            if (name == "Map Level")
                name = "Level";
            if (name == "Elemental Damage") {
                for (auto value_it = prop["values"].Begin(); value_it != prop["values"].End(); ++value_it)
                    elemental_damage_.push_back(std::make_pair((*value_it)[0].GetString(), (*value_it)[1].GetInt()));
            }
            else {
                if (prop["values"].Size())
                    properties_[name] = prop["values"][0][0].GetString();
            }

            ItemProperty property;
            property.name = name;
            property.display_mode = prop["displayMode"].GetInt();
            for (auto &value : prop["values"]) {
                ItemPropertyValue v;
                v.str = value[0].GetString();
                v.type = value[1].GetInt();
                property.values.push_back(v);
            }
            text_properties_.push_back(property);
        }
    }

    if (json.HasMember("requirements")) {
        for (auto &req : json["requirements"]) {
            std::string name = req["name"].GetString();
            std::string value = req["values"][0][0].GetString();
            requirements_[name] = std::atoi(value.c_str());
            ItemPropertyValue v;
            v.str = value;
            v.type = req["values"][0][1].GetInt();
            text_requirements_.push_back({ name, v });
        }
    }

    if (json.HasMember("sockets")) {
        ItemSocketGroup current_group = { 0, 0, 0, 0 };
        sockets_cnt_ = json["sockets"].Size();
        int counter = 0, prev_group = -1;
        for (auto &socket : json["sockets"]) {
            ItemSocket current_socket = { static_cast<unsigned char>(socket["group"].GetInt()), socket["attr"].GetString()[0] };
            text_sockets_.push_back(current_socket);
            if (prev_group != current_socket.group) {
                counter = 0;
                socket_groups_.push_back(current_group);
                current_group = { 0, 0, 0, 0 };
            }
            prev_group = current_socket.group;
            ++counter;
            links_cnt_ = std::max(links_cnt_, counter);
            switch (current_socket.attr) {
            case 'S':
                sockets_.r++;
                current_group.r++;
                break;
            case 'D':
                sockets_.g++;
                current_group.g++;
                break;
            case 'I':
                sockets_.b++;
                current_group.b++;
                break;
            case 'G':
                sockets_.w++;
                current_group.w++;
                break;
            }
        }
        socket_groups_.push_back(current_group);
    }

    CalculateHash(json);

    count_ = 1;
    if (properties_.find("Stack Size") != properties_.end()) {
        std::string size = properties_["Stack Size"];
        if (size.find("/") != std::string::npos) {
            size = size.substr(0, size.find("/"));
            count_ = std::stoi(size);
        }
    }

    has_mtx_ = json.HasMember("cosmeticMods");

    if (json.HasMember("ilvl"))
        ilvl_ = json["ilvl"].GetInt();

    GenerateMods(json);
}
Exemplo n.º 7
0
void ItemsManagerWorker::PreserveSelectedCharacter() {
    if (selected_character_.empty())
        return;
    network_manager_.get(MakeCharacterRequest(selected_character_, ItemLocation()));
}
Exemplo n.º 8
0
void ItemsManagerWorker::OnMainPageReceived() {
    QNetworkReply *reply = qobject_cast<QNetworkReply *>(QObject::sender());
    std::string page(reply->readAll().constData());

    selected_character_ = Util::FindTextBetween(page, "activeCharacter\":{\"name\":\"", "\",\"league");
    if (selected_character_.empty()) {
        QLOG_WARN() << "Can't extract selected character name from the page";
    }

    // now get character list
    QNetworkReply *characters = network_manager_.get(Request(QUrl(kGetCharactersUrl), ItemLocation(), TabCache::Refresh));
    connect(characters, &QNetworkReply::finished, this, &ItemsManagerWorker::OnCharacterListReceived);

    reply->deleteLater();
}
Exemplo n.º 9
0
Item::Item(const rapidjson::Value &json) :
    location_(ItemLocation(json)),
    name_(json["name"].GetString()),
    typeLine_(json["typeLine"].GetString()),
    corrupted_(json["corrupted"].GetBool()),
    w_(json["w"].GetInt()),
    h_(json["h"].GetInt()),
    frameType_(json["frameType"].GetInt()),
    icon_(json["icon"].GetString()),
    sockets_cnt_(0),
    links_cnt_(0),
    sockets_({ 0, 0, 0, 0 }),
    has_mtx_(false)
{
    // Fix for 2.0.2
    QString name = QString::fromStdString(name_);
    name.remove(QRegularExpression("<(.*)>"));
    name_ = name.toStdString();

    QString typeLine = QString::fromStdString(typeLine_);
    typeLine.remove(QRegularExpression("<(.*)>"));
    typeLine_ = typeLine.toStdString();

    for (auto &mod_type : ITEM_MOD_TYPES) {
        text_mods_[mod_type] = std::vector<std::string>();
        if (json.HasMember(mod_type.c_str())) {
            auto &mods = text_mods_[mod_type];
            for (auto &mod : json[mod_type.c_str()])
                mods.push_back(mod.GetString());
        }
    }

    if (json.HasMember("properties")) {
        for (auto prop_it = json["properties"].Begin(); prop_it != json["properties"].End(); ++prop_it) {
            auto &prop = *prop_it;
            std::string name = prop["name"].GetString();
            if (name == "Map Level")
                name = "Level";
            if (name == "Elemental Damage") {
                for (auto value_it = prop["values"].Begin(); value_it != prop["values"].End(); ++value_it)
                    elemental_damage_.push_back(std::make_pair((*value_it)[0].GetString(), (*value_it)[1].GetInt()));
            }
            else {
                if (prop["values"].Size())
                    properties_[name] = prop["values"][0][0].GetString();
            }

            ItemProperty property;
            property.name = name;
            property.display_mode = prop["displayMode"].GetInt();
            for (auto &value : prop["values"])
                property.values.push_back(value[0].GetString());
            text_properties_.push_back(property);
        }
    }

    if (json.HasMember("requirements")) {
        for (auto &req : json["requirements"]) {
            std::string name = req["name"].GetString();
            std::string value = req["values"][0][0].GetString();
            requirements_[name] = std::atoi(value.c_str());
            text_requirements_.push_back({ name, value });
        }
    }

    if (json.HasMember("sockets")) {
        ItemSocketGroup current_group = { 0, 0, 0, 0 };
        sockets_cnt_ = json["sockets"].Size();
        int counter = 0, prev_group = -1;
        for (auto &socket : json["sockets"]) {
            ItemSocket current_socket = { static_cast<unsigned char>(socket["group"].GetInt()), socket["attr"].GetString()[0] };
            text_sockets_.push_back(current_socket);
            if (prev_group != current_socket.group) {
                counter = 0;
                socket_groups_.push_back(current_group);
                current_group = { 0, 0, 0, 0 };
            }
            prev_group = current_socket.group;
            ++counter;
            links_cnt_ = std::max(links_cnt_, counter);
            switch (current_socket.attr) {
            case 'S':
                sockets_.r++;
                current_group.r++;
                break;
            case 'D':
                sockets_.g++;
                current_group.g++;
                break;
            case 'I':
                sockets_.b++;
                current_group.b++;
                break;
            case 'G':
                sockets_.w++;
                current_group.w++;
                break;
            }
        }
        socket_groups_.push_back(current_group);
    }

    std::string unique(std::string(json["name"].GetString()) + "~" + json["typeLine"].GetString() + "~");

    if (json.HasMember("explicitMods"))
        for (auto mod_it = json["explicitMods"].Begin(); mod_it != json["explicitMods"].End(); ++mod_it)
            unique += std::string(mod_it->GetString()) + "~";

    if (json.HasMember("implicitMods"))
        for (auto mod_it = json["implicitMods"].Begin(); mod_it != json["implicitMods"].End(); ++mod_it)
            unique += std::string(mod_it->GetString()) + "~";

    unique += item_unique_properties(json, "properties") + "~";
    unique += item_unique_properties(json, "additionalProperties") + "~";

    if (json.HasMember("sockets"))
        for (auto socket_it = json["sockets"].Begin(); socket_it != json["sockets"].End(); ++socket_it)
            unique += std::to_string((*socket_it)["group"].GetInt()) + "~" + (*socket_it)["attr"].GetString() + "~";

    hash_ = Util::Md5(unique);

    count_ = 1;
    if (properties_.find("Stack Size") != properties_.end()) {
        std::string size = properties_["Stack Size"];
        if (size.find("/") != std::string::npos) {
            size = size.substr(0, size.find("/"));
            count_ = std::stoi(size);
        }
    }

    has_mtx_ = json.HasMember("cosmeticMods");

    GenerateMods(json);
}