multiple tabs working

This commit is contained in:
mrbesen 2022-07-04 22:59:48 +02:00
parent 68c7ce92d9
commit 94d2869c51
Signed by untrusted user: MrBesen
GPG Key ID: 596B2350DCD67504
8 changed files with 144 additions and 60 deletions

View File

@ -29,7 +29,7 @@ public:
std::string name;
std::string id;
int key;
int key = 0;
std::string partype;
std::string title;
};
@ -51,6 +51,8 @@ public:
const ChampData& getBestMatchingChamp(const std::string& name, int* count = nullptr);
std::vector<const ChampData*> getMatchingChamp(const std::string& name, uint32_t limit = 25);
std::vector<uint32_t> resolveChampIDs(const std::vector<std::string>& champnames);
static const ChampData EMPTYCHAMP;
protected:
std::string getImageUrl(const std::string& champid, ImageType type);

View File

@ -5,8 +5,12 @@
#include <mutex>
#include "clientapi.h"
#include "config.h"
#include "datadragon.h"
class LolAutoAccept {
public:
using onposchange_func = std::function<void(Position)>;
protected:
struct Stage {
Stage();
@ -18,15 +22,18 @@ protected:
};
std::mutex stagesMutex; // protects stagesvector
std::vector<Stage*> stages;
std::vector<Stage> stages;
Position currentPosition = Position::INVALID;
Config::RootConfig& config;
DataDragon& dd;
onposchange_func onPoschange;
bool shouldrun = false;
std::thread lolaathread;
std::shared_ptr<ClientAPI> clientapi;
int64_t summonerid = -1;
public:
enum class State {
LOBBY = 0,
@ -34,7 +41,7 @@ public:
PICK = 2,
};
LolAutoAccept();
LolAutoAccept(Config::RootConfig& config, DataDragon& dd, onposchange_func = {});
~LolAutoAccept();
void setChamps(const std::vector<uint32_t>& champs, State s);
@ -44,15 +51,20 @@ public:
void run();
void stop();
void reload(); // reload the config, when something was changed
private:
void stopJoinThread();
void innerRun();
void resetAllOffsets();
void applyConfigToStage(Stage& stage, const Config::StageConfig& stageconf);
void loadPosition(Position pos);
uint32_t getChampOfState(State s);
void nextChampOfState(State s);
static bool isChampIntentofTeammate(uint32_t champid, const ClientAPI::ChampSelectSession& session);
static bool isChampBanned(uint32_t champid, const ClientAPI::ChampSelectSession& session);
using ownactions_t = std::vector<ClientAPI::ChampSelectAction>;
ownactions_t getOwnActions(int32_t cellid, const std::vector<ClientAPI::ChampSelectAction> actions);

View File

@ -16,7 +16,7 @@ class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(LolAutoAccept& lolaa, QWidget *parent = nullptr);
MainWindow(QWidget *parent = nullptr);
~MainWindow();
protected:
@ -30,15 +30,18 @@ private slots:
void tabtoggled(Position, LolAutoAccept::State, bool);
void tabchanged(Position, LolAutoAccept::State);
signals:
void requestTabChange(int tabindex);
private:
// returns empty string on no match
const DataDragon::ChampData& getBestMatchingChamp(const std::string& name);
void onPosChange(Position newpos); // to trigger the signal from a QObject
Ui::MainWindow *ui;
LolAutoAccept& lolaa;
std::thread lolaathread;
DataDragon dd;
Config conf;
LolAutoAccept lolaa;
};
#endif // MAINWINDOW_H

View File

@ -192,6 +192,18 @@ std::vector<const DataDragon::ChampData*> DataDragon::getMatchingChamp(const std
return out;
}
std::vector<uint32_t> DataDragon::resolveChampIDs(const std::vector<std::string>& champnames) {
std::vector<uint32_t> out;
out.reserve(champnames.size());
std::transform(champnames.begin(), champnames.end(), std::insert_iterator(out, out.begin()), [this](const std::string& champname) {
auto cd = getBestMatchingChamp(champname);
return cd.key; // might be 0 (invalid)
});
return out;
}
std::string DataDragon::getImageUrl(const std::string& champid, ImageType type) {
switch(type) {
case ImageType::SQUARE: {

View File

@ -1,27 +1,19 @@
#include "lolautoaccept.h"
#include <algorithm>
#include <thread>
#include <Log.h>
LolAutoAccept::Stage::Stage() {}
LolAutoAccept::Stage::~Stage() {}
LolAutoAccept::LolAutoAccept() {
LolAutoAccept::LolAutoAccept(Config::RootConfig& config, DataDragon& dd, onposchange_func onposch) : config(config), dd(dd), onPoschange(onposch) {
std::lock_guard lock(stagesMutex);
stages.reserve(3);
stages.push_back(new Stage()); // accept
stages.push_back(new Stage()); // ban
stages.push_back(new Stage()); // pick
stages.resize(3); // accept, ban, pick
}
LolAutoAccept::~LolAutoAccept() {
stopJoinThread();
std::lock_guard lock(stagesMutex);
for(auto s : stages) {
delete s;
}
}
void LolAutoAccept::setChamps(const std::vector<uint32_t>& champs, State s) {
@ -31,8 +23,8 @@ void LolAutoAccept::setChamps(const std::vector<uint32_t>& champs, State s) {
}
{
std::lock_guard lock(stagesMutex);
stages.at((int) s)->champids = champs;
stages.at((int) s)->currentOffset = 0;
stages.at((int) s).champids = champs;
stages.at((int) s).currentOffset = 0;
}
Log::info << "set champs on state: " << (int) s << " count: " << champs.size();
}
@ -44,7 +36,7 @@ void LolAutoAccept::setEnabled(bool b, State s) {
}
std::lock_guard lock(stagesMutex);
stages.at((int) s)->enabled = b;
stages.at((int) s).enabled = b;
}
bool LolAutoAccept::init() {
@ -54,7 +46,6 @@ bool LolAutoAccept::init() {
if(ca) {
clientapi = std::make_shared<ClientAPI>(*ca.get());
auto selfinfo = clientapi->getSelf();
summonerid = selfinfo.summonerid;
Log::info << "selfinfo: gameName: " << selfinfo.gameName << " name: " << selfinfo.name << " summonerid: " << selfinfo.summonerid << " statusMessage: " << selfinfo.statusMessage << " puuid: " << selfinfo.puuid << " level: " << selfinfo.level;
}
@ -74,6 +65,11 @@ void LolAutoAccept::stop() {
shouldrun = false;
}
void LolAutoAccept::reload() {
Log::note << "reload LolAutoAccept";
loadPosition(currentPosition);
}
void LolAutoAccept::stopJoinThread() {
stop();
@ -94,8 +90,10 @@ void LolAutoAccept::innerRun() {
Log::info << "current Gameflowphase: " << phase;
// do processing
if(phase == ClientAPI::GameflowPhase::READYCHECK) {
if(stages.at(0)->enabled) { // auto accept enabled
if(phase == ClientAPI::GameflowPhase::MATCHMAKING) {
extrasleep = 200;
} else if(phase == ClientAPI::GameflowPhase::READYCHECK) {
if(stages.at(0).enabled) { // auto accept enabled
auto state = clientapi->getReadyCheckState();
Log::info << "readychack state: " << state;
@ -118,53 +116,76 @@ void LolAutoAccept::innerRun() {
} else if(phase == ClientAPI::GameflowPhase::WAITINGFORSTATS) {
extrasleep = 4000; // 4 s bonus sleep
} else if(phase == ClientAPI::GameflowPhase::NONE) {
extrasleep = 30000; // 30 s bonus sleep - no lobby
extrasleep = 10000; // 10 s bonus sleep - no lobby
}
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> dur = (end-start);
//if(dur.count() > 1e-5)
Log::note << "iteration took: " << (dur.count() * 1000) << " ms";
Log::note << "iteration took: " << (dur.count() * 1000) << " ms extrasleep: " << extrasleep;
std::this_thread::sleep_for(std::chrono::milliseconds(400 + extrasleep));
}
}
void LolAutoAccept::resetAllOffsets() {
for(Stage* stage : stages) {
stage->currentOffset = 0;
for(Stage& stage : stages) {
stage.currentOffset = 0;
}
currentPosition = Position::INVALID;
}
void LolAutoAccept::applyConfigToStage(Stage& stage, const Config::StageConfig& stageconf) {
stage.champids = dd.resolveChampIDs(stageconf.champs);
stage.enabled = stage.enabled;
stage.currentOffset = 0;
}
void LolAutoAccept::loadPosition(Position pos) {
Log::trace << __PRETTY_FUNCTION__ << " pos: " << pos;
// reinit the stages
std::lock_guard lock(stagesMutex);
stages.resize(1); // first stage does not change
stages.resize(3);
const Config::PositionConfig& posconf = config.getPositionConfig(pos);
applyConfigToStage(stages.at((int) State::BAN), posconf.ban);
applyConfigToStage(stages.at((int) State::PICK), posconf.pick);
currentPosition = pos;
}
uint32_t LolAutoAccept::getChampOfState(State s) {
assert(((int) s) >= 0 && s <= State::PICK);
auto stage = stages[(int) s];
uint32_t size = stage->champids.size();
if(stage->currentOffset >= size) {
Stage& stage = stages[(int) s];
uint32_t size = stage.champids.size();
if(stage.currentOffset >= size) {
// no champ to try left
Log::warn << "no champ left at stage: " << (int) s;
Log::warn << "stage size: " << stage->champids.size();
Log::warn << "stage size: " << stage.champids.size();
return 0;
}
return stage->champids[stage->currentOffset];
return stage.champids[stage.currentOffset];
}
void LolAutoAccept::nextChampOfState(State s) {
assert(((int) s) >= 0 && s <= State::PICK);
assert(s > State::LOBBY && s <= State::PICK);
auto stage = stages[(int) s];
uint32_t size = stage->champids.size();
uint32_t size = stage.champids.size();
stage->currentOffset++;
stage.currentOffset++;
if(stage->currentOffset >= size) {
if(stage.currentOffset >= size) {
// no champ to try left
Log::warn << "no champ left at stage: " << (int) s;
Log::warn << "stage size: " << stage->champids.size();
Log::warn << "stage size: " << stage.champids.size();
stage->currentOffset = 0;
stage.currentOffset = 0;
return;
}
}
@ -179,6 +200,15 @@ bool LolAutoAccept::isChampIntentofTeammate(uint32_t champid, const ClientAPI::C
return false;
}
bool LolAutoAccept::isChampBanned(uint32_t champid, const ClientAPI::ChampSelectSession& session) {
for(const ClientAPI::ChampSelectAction& act : session.actions) {
if(act.type == ClientAPI::ChampSelectActionType::BAN && act.championID == (int32_t) champid && act.completed) {
return true;
}
}
return false;
}
LolAutoAccept::ownactions_t LolAutoAccept::getOwnActions(int32_t cellid, const std::vector<ClientAPI::ChampSelectAction> actions) {
ownactions_t out;
for(const auto& it : actions) {
@ -198,7 +228,7 @@ void LolAutoAccept::prepickPhase(const ownactions_t& ownactions) {
void LolAutoAccept::banPhase(const ownactions_t& ownactions, const ClientAPI::ChampSelectSession& session) {
phase(ownactions, ClientAPI::ChampSelectActionType::BAN, State::BAN, true, [session](uint32_t champid) {
return !isChampIntentofTeammate(champid, session);
return !isChampIntentofTeammate(champid, session) && !isChampBanned(champid, session);
});
}
@ -215,6 +245,7 @@ void LolAutoAccept::phase(const ownactions_t& ownactions, ClientAPI::ChampSelect
if(filter) {
// filter says no
if(!filter(champid)) {
Log::trace << "champid: " << champid << " filter says no - next champ";
nextChampOfState(s);
return;
}
@ -247,9 +278,20 @@ void LolAutoAccept::champSelect() {
}
Position pos = me ? me->position : Position::INVALID;
if(pos == Position::INVALID) {
pos = Position::UTILITY; // default: support TODO: make the default changeable? extra tab?
}
// reload config based on position if changed
if(pos != currentPosition) {
Log::note << "LolAutoAccept reloading config for position: " << pos << " because it was: " << currentPosition;
loadPosition(pos);
if(onPoschange) {
onPoschange(pos);
}
}
Log::debug << "cellid: " << cellid << " position: " << pos << " counter: " << session.counter << " timer: timeleftip: " << session.timer.adjustedTimeLeftInPhase << " totaltimephase: " << session.timer.totalTimeInPhase;
// find actions for own cell
auto ownactions = getOwnActions(cellid, session.actions);
Log::debug << "ownactions: " << ownactions.size();

View File

@ -11,7 +11,6 @@
#include "arg.h"
#include "mainwindow.h"
#include "lolautoaccept.h"
#include "clientaccess.h"
#include "clientapi.h"
@ -54,7 +53,6 @@ int main(int argc, char** argv) {
std::string base = getBaseString(argv);
Log::info << "appbase: " << base;
LolAutoAccept lolaa;
QApplication app(argc, argv);
QTranslator translator;
if(translator.load(QLocale().name(), QString::fromStdString(base + "ts"))) {
@ -62,7 +60,7 @@ int main(int argc, char** argv) {
} else {
Log::warn << "translation not found";
}
MainWindow win(lolaa);
MainWindow win;
QIcon icon(QString::fromStdString(base + "lolautoaccept.png"));
win.setWindowIcon(icon);

View File

@ -3,7 +3,7 @@
#include <Log.h>
MainWindow::MainWindow(LolAutoAccept& lolaa, QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), lolaa(lolaa), dd(QLocale().name().toStdString()) {
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), dd(QLocale().name().toStdString()), lolaa(conf.getConfig(), dd, std::bind(&MainWindow::onPosChange, this, std::placeholders::_1)) {
ui->setupUi(this);
conf.load();
@ -67,26 +67,24 @@ void MainWindow::aatoggled(bool state) {
conf.getConfig().enabledAutoAccept = state;
}
static std::vector<uint32_t> toChampionIDList(const std::vector<StageSettings::SelectedChamp>& scs) {
std::vector<uint32_t> out;
for(const StageSettings::SelectedChamp& sc : scs) {
out.push_back(sc.id);
}
return out;
}
void MainWindow::tabtoggled(Position p, LolAutoAccept::State s, bool state) {
Log::info << "checkbox toggled " << state << " position: " << p << " state: " << (int) s;
lolaa.setEnabled(state, s);
if(s == LolAutoAccept::State::LOBBY) {
lolaa.setEnabled(state, s);
}
lolaa.reload();
}
void MainWindow::tabchanged(Position p, LolAutoAccept::State s) {
Log::info << "edited position: " << p << " state: " << (int) s;
SettingsTab* tab = (SettingsTab*) ui->tabWidget->widget((int) p -1);
auto champs = tab->getChamps(s);
lolaa.setChamps(toChampionIDList(champs), s);
lolaa.reload();
}
void MainWindow::onPosChange(Position newpos) {
if(newpos != Position::INVALID) {
emit requestTabChange((int) newpos -1);
}
}

View File

@ -176,8 +176,25 @@
</hint>
</hints>
</connection>
<connection>
<sender>MainWindow</sender>
<signal>requestTabChange(int)</signal>
<receiver>tabWidget</receiver>
<slot>setCurrentIndex(int)</slot>
<hints>
<hint type="sourcelabel">
<x>417</x>
<y>86</y>
</hint>
<hint type="destinationlabel">
<x>407</x>
<y>145</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<signal>requestTabChange(int)</signal>
<slot>aatoggled(bool)</slot>
<slot>tabtoggled(Position, LolAutoAccept::State, bool)</slot>
<slot>tabchanged(Position, LolAutoAccept::State)</slot>