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 IBLUE() { return "\033[0;94m"; }
|
||||
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::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;
|
||||
while (!finished) {
|
||||
@@ -36,7 +36,7 @@ namespace platform {
|
||||
if (all_of(line.begin(), line.end(), ::isdigit)) {
|
||||
command = defaultCommand;
|
||||
index = stoi(line);
|
||||
if (index > maxIndex || index < 0) {
|
||||
if (index > maxIndex || index < minIndex) {
|
||||
messageError("Index out of range");
|
||||
continue;
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@ namespace platform {
|
||||
class CommandParser {
|
||||
public:
|
||||
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; };
|
||||
int getIndex() const { return index; };
|
||||
private:
|
||||
|
@@ -23,6 +23,8 @@ namespace platform {
|
||||
this->numFiles = results.size();
|
||||
}
|
||||
}
|
||||
paginator = Paginator(numFiles, results.size());
|
||||
page = 1;
|
||||
}
|
||||
void ManageResults::doMenu()
|
||||
{
|
||||
@@ -41,10 +43,10 @@ namespace platform {
|
||||
void ManageResults::list()
|
||||
{
|
||||
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;
|
||||
oss << "Results on screen: " << numFiles << suffix;
|
||||
std::cout << Colors::GREEN() << oss.str() << std::endl;
|
||||
oss << index_to - index_from + 1 << " Results on screen - Page " << page << " of " << paginator.getPages();
|
||||
std::cout << Colors::CLRSCR() << Colors::GREEN() << oss.str() << std::endl;
|
||||
std::cout << std::string(oss.str().size(), '-') << std::endl;
|
||||
if (complete) {
|
||||
std::cout << Colors::MAGENTA() << "Only listing complete results" << std::endl;
|
||||
@@ -57,13 +59,10 @@ namespace platform {
|
||||
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 << "=== ========== " << 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();
|
||||
std::cout << color << std::setw(3) << std::fixed << std::right << i++ << " ";
|
||||
std::cout << result.to_string(maxModel) << std::endl;
|
||||
if (i == numFiles) {
|
||||
break;
|
||||
}
|
||||
std::cout << color << std::setw(3) << std::fixed << std::right << i << " ";
|
||||
std::cout << results.at(i).to_string(maxModel) << std::endl;
|
||||
}
|
||||
}
|
||||
bool ManageResults::confirmAction(const std::string& intent, const std::string& fileName) const
|
||||
@@ -166,7 +165,10 @@ namespace platform {
|
||||
{"title", 't', true},
|
||||
{"set A", 'a', 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>
|
||||
std::vector<std::tuple<std::string, char, bool>> listOptions = {
|
||||
@@ -178,11 +180,36 @@ namespace platform {
|
||||
auto parser = CommandParser();
|
||||
while (!finished) {
|
||||
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 {
|
||||
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) {
|
||||
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':
|
||||
finished = true;
|
||||
break;
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <xlsxwriter.h>
|
||||
#include "ResultsManager.h"
|
||||
#include "Paginator.hpp"
|
||||
|
||||
namespace platform {
|
||||
class ManageResults {
|
||||
@@ -23,6 +24,8 @@ namespace platform {
|
||||
bool complete;
|
||||
bool partial;
|
||||
bool compare;
|
||||
int page;
|
||||
Paginator paginator;
|
||||
ResultsManager results;
|
||||
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