Add pagination to b_manage
This commit is contained in:
@@ -12,4 +12,19 @@ public:
|
|||||||
static std::string WHITE() { return "\033[1;37m"; }
|
static std::string WHITE() { return "\033[1;37m"; }
|
||||||
static std::string IBLUE() { return "\033[0;94m"; }
|
static std::string IBLUE() { return "\033[0;94m"; }
|
||||||
static std::string RESET() { return "\033[0m"; }
|
static std::string RESET() { return "\033[0m"; }
|
||||||
|
static std::string BOLD() { return "\033[1m"; }
|
||||||
|
static std::string UNDERLINE() { return "\033[4m"; }
|
||||||
|
static std::string BLINK() { return "\033[5m"; }
|
||||||
|
static std::string REVERSE() { return "\033[7m"; }
|
||||||
|
static std::string CONCEALED() { return "\033[8m"; }
|
||||||
|
static std::string BLACK() { return "\033[1;30m"; }
|
||||||
|
static std::string IBROWN() { return "\033[0;93m"; }
|
||||||
|
static std::string IRED() { return "\033[0;91m"; }
|
||||||
|
static std::string IWHITE() { return "\033[0;97m"; }
|
||||||
|
static std::string IGREEN() { return "\033[0;92m"; }
|
||||||
|
static std::string IYELLOW() { return "\033[0;93m"; }
|
||||||
|
static std::string ICYAN() { return "\033[0;96m"; }
|
||||||
|
static std::string IBLACK() { return "\033[0;90m"; }
|
||||||
|
static std::string IMAGENTA() { return "\033[0;95m"; }
|
||||||
|
static std::string CLRSCR() { return "\033[2J\033[1;1H"; }
|
||||||
};
|
};
|
||||||
|
@@ -10,7 +10,7 @@ namespace platform {
|
|||||||
{
|
{
|
||||||
std::cout << Colors::RED() << message << Colors::RESET() << std::endl;
|
std::cout << Colors::RED() << message << Colors::RESET() << std::endl;
|
||||||
}
|
}
|
||||||
std::pair<char, int> CommandParser::parse(const std::string& color, const std::vector<std::tuple<std::string, char, bool>>& options, const char defaultCommand, const int maxIndex)
|
std::pair<char, int> CommandParser::parse(const std::string& color, const std::vector<std::tuple<std::string, char, bool>>& options, const char defaultCommand, const int minIndex, const int maxIndex)
|
||||||
{
|
{
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
while (!finished) {
|
while (!finished) {
|
||||||
@@ -36,7 +36,7 @@ namespace platform {
|
|||||||
if (all_of(line.begin(), line.end(), ::isdigit)) {
|
if (all_of(line.begin(), line.end(), ::isdigit)) {
|
||||||
command = defaultCommand;
|
command = defaultCommand;
|
||||||
index = stoi(line);
|
index = stoi(line);
|
||||||
if (index > maxIndex || index < 0) {
|
if (index > maxIndex || index < minIndex) {
|
||||||
messageError("Index out of range");
|
messageError("Index out of range");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,7 @@ namespace platform {
|
|||||||
class CommandParser {
|
class CommandParser {
|
||||||
public:
|
public:
|
||||||
CommandParser() = default;
|
CommandParser() = default;
|
||||||
std::pair<char, int> parse(const std::string& color, const std::vector<std::tuple<std::string, char, bool>>& options, const char defaultCommand, const int maxIndex);
|
std::pair<char, int> parse(const std::string& color, const std::vector<std::tuple<std::string, char, bool>>& options, const char defaultCommand, const int minIndex, const int maxIndex);
|
||||||
char getCommand() const { return command; };
|
char getCommand() const { return command; };
|
||||||
int getIndex() const { return index; };
|
int getIndex() const { return index; };
|
||||||
private:
|
private:
|
||||||
|
@@ -23,6 +23,8 @@ namespace platform {
|
|||||||
this->numFiles = results.size();
|
this->numFiles = results.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
paginator = Paginator(numFiles, results.size());
|
||||||
|
page = 1;
|
||||||
}
|
}
|
||||||
void ManageResults::doMenu()
|
void ManageResults::doMenu()
|
||||||
{
|
{
|
||||||
@@ -41,10 +43,10 @@ namespace platform {
|
|||||||
void ManageResults::list()
|
void ManageResults::list()
|
||||||
{
|
{
|
||||||
auto temp = ConfigLocale();
|
auto temp = ConfigLocale();
|
||||||
std::string suffix = numFiles != results.size() ? " of " + std::to_string(results.size()) : "";
|
auto [index_from, index_to] = paginator.getOffset(page);
|
||||||
std::stringstream oss;
|
std::stringstream oss;
|
||||||
oss << "Results on screen: " << numFiles << suffix;
|
oss << index_to - index_from + 1 << " Results on screen - Page " << page << " of " << paginator.getPages();
|
||||||
std::cout << Colors::GREEN() << oss.str() << std::endl;
|
std::cout << Colors::CLRSCR() << Colors::GREEN() << oss.str() << std::endl;
|
||||||
std::cout << std::string(oss.str().size(), '-') << std::endl;
|
std::cout << std::string(oss.str().size(), '-') << std::endl;
|
||||||
if (complete) {
|
if (complete) {
|
||||||
std::cout << Colors::MAGENTA() << "Only listing complete results" << std::endl;
|
std::cout << Colors::MAGENTA() << "Only listing complete results" << std::endl;
|
||||||
@@ -57,13 +59,10 @@ namespace platform {
|
|||||||
int maxTitle = results.maxTitleSize();
|
int maxTitle = results.maxTitleSize();
|
||||||
std::cout << Colors::GREEN() << " # Date " << std::setw(maxModel) << std::left << "Model" << " Score Name Score C/P Duration Title" << std::endl;
|
std::cout << Colors::GREEN() << " # Date " << std::setw(maxModel) << std::left << "Model" << " Score Name Score C/P Duration Title" << std::endl;
|
||||||
std::cout << "=== ========== " << std::string(maxModel, '=') << " =========== =========== === ========= " << std::string(maxTitle, '=') << std::endl;
|
std::cout << "=== ========== " << std::string(maxModel, '=') << " =========== =========== === ========= " << std::string(maxTitle, '=') << std::endl;
|
||||||
for (auto& result : results) {
|
for (int i = index_from; i <= index_to; i++) {
|
||||||
auto color = (i % 2) ? Colors::BLUE() : Colors::CYAN();
|
auto color = (i % 2) ? Colors::BLUE() : Colors::CYAN();
|
||||||
std::cout << color << std::setw(3) << std::fixed << std::right << i++ << " ";
|
std::cout << color << std::setw(3) << std::fixed << std::right << i << " ";
|
||||||
std::cout << result.to_string(maxModel) << std::endl;
|
std::cout << results.at(i).to_string(maxModel) << std::endl;
|
||||||
if (i == numFiles) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool ManageResults::confirmAction(const std::string& intent, const std::string& fileName) const
|
bool ManageResults::confirmAction(const std::string& intent, const std::string& fileName) const
|
||||||
@@ -166,7 +165,10 @@ namespace platform {
|
|||||||
{"title", 't', true},
|
{"title", 't', true},
|
||||||
{"set A", 'a', true},
|
{"set A", 'a', true},
|
||||||
{"set B", 'b', true},
|
{"set B", 'b', true},
|
||||||
{"compare A~B", 'c', false}
|
{"compare A~B", 'c', false},
|
||||||
|
{"Page", 'p', true},
|
||||||
|
{"Page+", '+', false },
|
||||||
|
{"Page-", '-', false}
|
||||||
};
|
};
|
||||||
// tuple<Option, digit, requires value>
|
// tuple<Option, digit, requires value>
|
||||||
std::vector<std::tuple<std::string, char, bool>> listOptions = {
|
std::vector<std::tuple<std::string, char, bool>> listOptions = {
|
||||||
@@ -178,11 +180,36 @@ namespace platform {
|
|||||||
auto parser = CommandParser();
|
auto parser = CommandParser();
|
||||||
while (!finished) {
|
while (!finished) {
|
||||||
if (indexList) {
|
if (indexList) {
|
||||||
std::tie(option, index) = parser.parse(Colors::GREEN(), mainOptions, 'r', numFiles - 1);
|
auto [min_index, max_index] = paginator.getOffset(page);
|
||||||
|
std::tie(option, index) = parser.parse(Colors::GREEN(), mainOptions, 'r', min_index, max_index);
|
||||||
} else {
|
} else {
|
||||||
std::tie(option, subIndex) = parser.parse(Colors::BLUE(), listOptions, 'r', results.at(index).getJson()["results"].size() - 1);
|
std::tie(option, subIndex) = parser.parse(Colors::BLUE(), listOptions, 'r', 0, results.at(index).getJson()["results"].size() - 1);
|
||||||
}
|
}
|
||||||
switch (option) {
|
switch (option) {
|
||||||
|
case 'p':
|
||||||
|
if (paginator.valid(index)) {
|
||||||
|
page = index;
|
||||||
|
list();
|
||||||
|
} else {
|
||||||
|
std::cout << Colors::RED() << "Invalid page!" << Colors::RESET() << std::endl;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '+':
|
||||||
|
if (paginator.hasNext(page)) {
|
||||||
|
page++;
|
||||||
|
list();
|
||||||
|
} else {
|
||||||
|
std::cout << Colors::RED() << "No more pages!" << Colors::RESET() << std::endl;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
if (paginator.hasPrev(page)) {
|
||||||
|
page--;
|
||||||
|
list();
|
||||||
|
} else {
|
||||||
|
std::cout << Colors::RED() << "First page already!" << Colors::RESET() << std::endl;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
finished = true;
|
finished = true;
|
||||||
break;
|
break;
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <xlsxwriter.h>
|
#include <xlsxwriter.h>
|
||||||
#include "ResultsManager.h"
|
#include "ResultsManager.h"
|
||||||
|
#include "Paginator.hpp"
|
||||||
|
|
||||||
namespace platform {
|
namespace platform {
|
||||||
class ManageResults {
|
class ManageResults {
|
||||||
@@ -23,6 +24,8 @@ namespace platform {
|
|||||||
bool complete;
|
bool complete;
|
||||||
bool partial;
|
bool partial;
|
||||||
bool compare;
|
bool compare;
|
||||||
|
int page;
|
||||||
|
Paginator paginator;
|
||||||
ResultsManager results;
|
ResultsManager results;
|
||||||
lxw_workbook* workbook;
|
lxw_workbook* workbook;
|
||||||
};
|
};
|
||||||
|
29
src/manage/Paginator.hpp
Normal file
29
src/manage/Paginator.hpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
class Paginator {
|
||||||
|
public:
|
||||||
|
Paginator() = default;
|
||||||
|
Paginator(int pageSize, int total) : pageSize(pageSize), total(total)
|
||||||
|
{
|
||||||
|
numPages = (total + pageSize - 1) / pageSize;
|
||||||
|
};
|
||||||
|
~Paginator() = default;
|
||||||
|
int getPageSize() const { return pageSize; }
|
||||||
|
int getTotal() const { return total; }
|
||||||
|
std::pair<int, int> getOffset(int page) const
|
||||||
|
{
|
||||||
|
if (page > numPages)
|
||||||
|
throw std::out_of_range("page out of range");
|
||||||
|
return { (page - 1) * pageSize, std::min(total - 1, page * pageSize - 1) };
|
||||||
|
}
|
||||||
|
int getPages() const { return numPages; }
|
||||||
|
bool valid(int page) const { return page > 0 && page <= numPages; }
|
||||||
|
bool hasPrev(int page) const { return page > 1; }
|
||||||
|
bool hasNext(int page) const { return page < getPages(); }
|
||||||
|
private:
|
||||||
|
int pageSize;
|
||||||
|
int total;
|
||||||
|
int numPages;
|
||||||
|
};
|
Reference in New Issue
Block a user