lolautoaccept/src/clientapi_json.cpp

310 lines
11 KiB
C++

#include "clientapi.h"
#include <QJsonArray>
#include <QJsonObject>
#include <Log.h>
#include "json.h"
// calculate the size of a constant sized array
#define ARRSIZE(ARRNAME) (sizeof(ARRNAME) / sizeof(ARRNAME[0]))
#define ARR(NAME, ...) static const QString NAME ## Names[] = {__VA_ARGS__}; \
static const uint32_t NAME ## NamesCount = ARRSIZE(NAME ## Names);
ARR(ReadyCheckState, "Invalid", "None", "InProgress", "Accepted", "Declined");
ARR(GameflowPhase, "None", "Lobby", "Matchmaking", "CheckedIntoTournament", "ReadyCheck", "ChampSelect", "GameStart", "FailedToLaunch", "InProgress", "Reconnect", "WaitingForStats", "PreEndOfGame", "EndOfGame", "TerminatedInError");
ARR(ChampSelectPhase, "Invalid", "GAME_STARTING", "PLANNING", "BAN_PICK", "FINALIZATION");
ARR(Position, "Invalid", "top", "jungle", "middle", "bottom", "utility");
ARR(ShortPosition, "", "Top", "Jgl", "Mid", "Bot", "Sup");
ARR(ChampSelectActionType, "Invalid", "ban", "pick", "ten_bans_reveal");
template<typename T>
static T mapEnum(const QString& input, const QString* names, uint32_t count, T defaul) {
if(input.isEmpty()) return defaul;
for (uint32_t i = 0; i < count; ++i) {
if (names[i] == input) {
return (T) i;
}
}
qWarning() << "no mapping of enum-string: " << input << " using default: " << defaul << " type: " << typeid(T).name();
return defaul;
}
#define MAPENUM(VAR, ENUM, DEFAULT) \
mapEnum(VAR, ENUM ## Names, ENUM ## NamesCount, ClientAPI:: ENUM :: DEFAULT)
template<typename T>
static std::vector<T> readVector(QJsonArray arr) {
std::vector<T> out;
out.reserve(arr.size());
for(auto it : arr) {
out.push_back(convert<T>((QJsonValue) it));
}
return out;
}
ClientAPI::ReadyCheckState ClientAPI::toReadyCheckState(const QJsonObject& obj) {
QString searchState = getValue<QString>(obj, "state", "Invalid");
QString playerresponse = getValue<QString>(obj, "playerResponse", "None");
ClientAPI::ReadyCheckState response = MAPENUM(playerresponse, ReadyCheckState, NONE);
if(response == ClientAPI::ReadyCheckState::NONE) {
auto sstate = MAPENUM(searchState, ReadyCheckState, INVALID);
if(sstate == ClientAPI::ReadyCheckState::INPROGRESS) {
return sstate;
}
}
return response;
}
ClientAPI::GameflowPhase ClientAPI::toGameflowPhase(const QString& str) {
return MAPENUM(str, GameflowPhase, NONE);
}
ClientAPI::ChampSelectPhase ClientAPI::toChampSelectPhase(const QString& str) {
return MAPENUM(str, ChampSelectPhase, INVALID);
}
Position toPosition(const QString& str) {
return mapEnum(str, PositionNames, PositionNamesCount, Position::INVALID);
}
QString toString(Position p) {
return PositionNames[(int) p];
}
QString toShortString(Position p) {
return ShortPositionNames[(int) p];
}
ClientAPI::ChampSelectActionType ClientAPI::toChampSelectActionType(const QString& str) {
return MAPENUM(str, ChampSelectActionType, INVALID);
}
ClientAPI::TimerInfo::TimerInfo() {}
ClientAPI::TimerInfo::TimerInfo(const QJsonObject& obj) {
adjustedTimeLeftInPhase = getValue<int64_t>(obj, "adjustedTimeLeftInPhase", 0);
internalNowInEpochMs = getValue<int64_t>(obj, "internalNowInEpochMs", 0);
isefinite = getValue<bool>(obj, "isefinite", 0);
phase = MAPENUM(getValue<QString>(obj, "phase", "Invalid"), ChampSelectPhase, INVALID);
totalTimeInPhase = getValue<int64_t>(obj, "totalTimeInPhase", 0);
}
ClientAPI::ChampSelectAction::ChampSelectAction() {}
ClientAPI::ChampSelectAction::ChampSelectAction(const QJsonObject& json) {
actorCellID = getValue<int32_t>(json, "actorCellId");
championID = getValue<int32_t>(json, "championId");
completed = getValue<bool>(json, "completed");
id = getValue<int32_t>(json, "id");
isAllyAction = getValue<bool>(json, "isAllyAction");
isInProgress = getValue<bool>(json, "isInProgress");
const QString typestr = getValue<QString>(json, "type", "Invalid");
type = toChampSelectActionType(typestr);
}
ClientAPI::ChampSelectCell::ChampSelectCell() {}
ClientAPI::ChampSelectCell::ChampSelectCell(const QJsonObject& json) {
position = toPosition(getValue<QString>(json, "assignedPosition"));
cellID = getValue<int32_t>(json, "cellId");
championID = getValue<int32_t>(json, "championId");
championPickIntentID = getValue<int32_t>(json, "championPickIntent");
summonerID = getValue<int32_t>(json, "summonerId");
spell1Id = getValue<int64_t>(json, "spell1Id", 0);
spell2Id = getValue<int64_t>(json, "spell2Id", 0);
}
std::vector<ClientAPI::ChampSelectCell> ClientAPI::loadAllInfos(const QJsonArray& arr) {
std::vector<ClientAPI::ChampSelectCell> out;
out.reserve(arr.size()); // should usualy be 5
for(auto it = arr.constBegin(); it != arr.constEnd(); ++it) {
if(it->isObject()) {
out.push_back((ChampSelectCell) it->toObject());
}
}
return out;
}
ClientAPI::ChampSelectSession::ChampSelectSession() {}
ClientAPI::ChampSelectSession::ChampSelectSession(const QJsonObject& json) {
// loading actions
auto actionsref = json["actions"];
// its an array of array id ChampSelectAction
if(actionsref.isArray()) {
QJsonArray jactions = actionsref.toArray();
for(auto jact = jactions.constBegin(); jact != jactions.constEnd(); ++jact) {
if(!jact->isArray()) continue;
QJsonArray jactarr = jact->toArray();
for(auto it = jactarr.constBegin(); it != jactarr.constEnd(); ++it) {
if(it->isObject()) {
actions.push_back((ChampSelectAction) it->toObject());
}
}
}
}
counter = getValue<int32_t>(json, "counter");
gameid = getValue<int64_t>(json, "gameId");
allowDuplicatePick = getValue(json, "allowDuplicatePicks", false);
allowRerolling = getValue(json, "allowRerolling", false);
allowSkinSelection = getValue(json, "allowSkinSelection", true);
hasSimultaneousBans = getValue(json, "hasSimultaneousBans", false);
hasSimultaneousPicks = getValue(json, "hasSimultaneousPicks", true);
isCustomGame = getValue(json, "isCustomGame", false);
isSpectating = getValue(json, "isSpectating", false);
skipChampionSelect = getValue(json, "skipChampionSelect", false);
rerollsRemaining = getValue(json, "rerollsRemaining", 0);
localPlayerCellId = getValue(json, "localPlayerCellId", -1);
auto timerref = json["timer"];
if(timerref.isObject()) {
timer = (TimerInfo) timerref.toObject();
}
// load cellinfo
auto myteamref = json["myTeam"];
if(myteamref.isArray()) {
myTeam = loadAllInfos(myteamref.toArray());
}
auto theirteamref = json["theirTeam"];
if(theirteamref.isArray()) {
theirTeam = loadAllInfos(theirteamref.toArray());
}
}
ClientAPI::ChampSelectSession::operator bool() {
return gameid != 0;
}
ClientAPI::RunePage::RunePage() {}
ClientAPI::RunePage::RunePage(const QJsonObject& json) {
id = getValue<int32_t>(json, "id", 0);
lastmodified = getValue<int64_t>(json, "lastModified", 0);
runepage.primaryStyle = getValue<int32_t>(json, "primaryStyleId", 0);
runepage.secondaryStyle = getValue<int32_t>(json, "subStyleId", 0);
name = getValue<QString>(json, "name");
isDeleteable = getValue<bool>(json, "isDeletable", false);
isEditable = getValue<bool>(json, "isEditable", false);
isActive = getValue<bool>(json, "isActive", false);
isCurrent = getValue<bool>(json, "current", false);
isValid = getValue<bool>(json, "isValid", false);
order = getValue<int32_t>(json, "order", 0);
auto selectedref = json["selectedPerkIds"];
if(selectedref.isArray()) {
runepage.selectedAspects = readVector<uint32_t>(selectedref.toArray());
}
}
RuneStyleSlot::RuneStyleSlot() {}
RuneStyleSlot::RuneStyleSlot(const QJsonObject& json) {
type = getValue<QString>(json, "type");
auto perksj = json["perks"];
if(perksj.isArray()) {
perks = readVector<int>(perksj.toArray());
}
}
RuneStyle::RuneStyle() {}
RuneStyle::RuneStyle(const QJsonObject& json) {
id = getValue<int32_t>(json, "id", 0);
name = getValue<QString>(json, "name");
iconPath = getValue<QString>(json, "iconPath");
tooltip = getValue<QString>(json, "tooltip");
idName = getValue<QString>(json, "idName");
auto subStylesRef = json["allowedSubStyles"];
if(subStylesRef.isArray()) {
allowedSubStyles = readVector<int>(subStylesRef.toArray());
}
auto runeSlotsRef = json["slots"];
if(runeSlotsRef.isArray()) {
runeSlots = readVector<RuneStyleSlot>(runeSlotsRef.toArray());
}
}
RuneAspekt::RuneAspekt() {}
RuneAspekt::RuneAspekt(const QJsonObject& json) {
id = getValue<int32_t>(json, "id", 0);
name = getValue<QString>(json, "name");
shortDesc = getValue<QString>(json, "shortDesc");
longDesc = getValue<QString>(json, "longDesc");
tooltip = getValue<QString>(json, "tooltip");
iconPath = getValue<QString>(json, "iconPath");
}
ClientAPI::Message::Message() {}
ClientAPI::Message::Message(const QJsonObject& json) {
body = getValue<QString>(json, "body");
fromId = getValue<QString>(json, "fromId");
fromPid = getValue<QString>(json, "fromPid");
fromSummonerId = getValue<int64_t>(json, "fromSummonerId");
id = getValue<QString>(json, "id");
isHistorical = getValue<bool>(json, "isHistorical", true);
timestamp = getValue<QString>(json, "timestamp");
type = getValue<QString>(json, "type");
}
ClientAPI::Conversation::Conversation() {}
ClientAPI::Conversation::Conversation(const QJsonObject& json) : lastMessage(nullptr) {
gameName = getValue<QString>(json, "gameName");
gameTag = getValue<QString>(json, "gameTag");
id = getValue<QString>(json, "id");
isMuted = getValue<bool>(json, "isMuted");
name = getValue<QString>(json, "name");
password = getValue<QString>(json, "password");
pid = getValue<QString>(json, "pid");
targetRegion = getValue<QString>(json, "targetRegion");
type = getValue<QString>(json, "type");
unreadMessageCount = getValue<int64_t>(json, "unreadMessageCount");
auto msgref = json["lastMessage"];
if(msgref.isObject()) {
lastMessage = std::make_shared<Message>(msgref.toObject());
}
}
#define PRINTENUM(ENUMNAME) \
std::ostream& operator<<(std::ostream& str, const ClientAPI:: ENUMNAME & state) { \
assert(((uint32_t) state) < ENUMNAME ## NamesCount); \
return str << ENUMNAME ## Names[(uint32_t) state].toStdString() << " (" << (uint32_t) state << ')'; \
} \
\
QDebug operator<<(QDebug str, const ClientAPI:: ENUMNAME & state) { \
assert(((uint32_t) state) < ENUMNAME ## NamesCount); \
return str << ENUMNAME ## Names[(uint32_t) state] << " (" << (uint32_t) state << ')'; \
}
PRINTENUM(ReadyCheckState)
PRINTENUM(GameflowPhase)
PRINTENUM(ChampSelectPhase)
PRINTENUM(ChampSelectActionType)
// not using macro because its not in ClientAPI
std::ostream& operator<<(std::ostream& str, const Position & state) {
assert(((uint32_t) state) < PositionNamesCount);
return str << PositionNames[(uint32_t) state].toStdString() << " (" << (uint32_t) state << ')';
}
QDebug operator<<(QDebug str, const Position & state) {
assert(((uint32_t) state) < PositionNamesCount);
return str << PositionNames[(uint32_t) state] << " (" << (uint32_t) state << ')';
}