Compare commits
3 Commits
5c345fb5a1
..
0.6
| Author | SHA1 | Date | |
|---|---|---|---|
| 43d53629ca | |||
| d9fd2d40eb | |||
| 19c45c6969 |
+14
-1
@@ -1,6 +1,19 @@
|
||||
#include <string_view>
|
||||
#ifndef VERSION
|
||||
|
||||
#define VERSION "0.5"
|
||||
#define VERSION "0.6"
|
||||
#define NAME "bakatui"
|
||||
|
||||
inline constexpr auto hash_djb2a(const std::string_view sv) {
|
||||
unsigned long hash{5381};
|
||||
for (unsigned char c : sv) {
|
||||
hash = ((hash << 5) + hash) ^ c;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
inline constexpr auto operator"" _sh(const char *str, size_t len) {
|
||||
return hash_djb2a(std::string_view{str, len});
|
||||
}
|
||||
|
||||
#endif
|
||||
+14
-1
@@ -9,6 +9,7 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <locale>
|
||||
#include <panel.h>
|
||||
#include <string>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
@@ -217,4 +218,16 @@ std::wstring string_to_wstring(const std::string &str) {
|
||||
std::string wstring_to_string(const std::wstring &wstr) {
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
|
||||
return converter.to_bytes(wstr);
|
||||
}
|
||||
}
|
||||
|
||||
void move_panel_relative(PANEL *panel, int dy, int dx) {
|
||||
WINDOW *win = panel_window(panel);
|
||||
int y, x;
|
||||
|
||||
getbegyx(win, y, x);
|
||||
|
||||
int new_y = y + dy;
|
||||
int new_x = x + dx;
|
||||
|
||||
move_panel(panel, new_y, new_x);
|
||||
}
|
||||
|
||||
+178
-29
@@ -1,17 +1,19 @@
|
||||
#include "timetable.h"
|
||||
#include "color.h"
|
||||
#include "const.h"
|
||||
#include "helper_funcs.h"
|
||||
#include "net.h"
|
||||
#include "types.h"
|
||||
#include <cstdint>
|
||||
#include <curses.h>
|
||||
#include <cwchar>
|
||||
#include <format>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <locale>
|
||||
#include <ncurses.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <panel.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using nlohmann::json;
|
||||
#define BOTTOM_PADDING 3
|
||||
@@ -24,8 +26,9 @@ const wchar_t *day_abriviations[] = {nullptr, L"Mo", L"Tu", L"We",
|
||||
void draw_grid(const uint8_t num_of_columns, const uint8_t num_of_rows,
|
||||
const uint16_t cell_width, const uint16_t cell_height);
|
||||
|
||||
uint8_t hour_id_to_index(uint8_t *HourIdLookupTable, uint8_t id) {
|
||||
for (uint8_t i = 0; i < 10; i++) {
|
||||
uint8_t hour_id_to_index(const std::vector<uint8_t> &HourIdLookupTable,
|
||||
uint8_t id) {
|
||||
for (uint8_t i = 0; i < HourIdLookupTable.size(); i++) {
|
||||
if (HourIdLookupTable[i] == id) {
|
||||
return i;
|
||||
}
|
||||
@@ -63,7 +66,7 @@ void timetable_page() {
|
||||
|
||||
// this may be unnecessary but i dont have enaugh data to test it
|
||||
// it sorts the hours by start time
|
||||
uint8_t *HourIdLookupTable = new uint8_t[resp_from_api["Hours"].size()];
|
||||
std::vector<uint8_t> HourIdLookupTable(resp_from_api["Hours"].size());
|
||||
{
|
||||
using Id_and_Start_time = std::tuple<uint8_t, std::string>;
|
||||
// ID, start_time
|
||||
@@ -116,20 +119,22 @@ void timetable_page() {
|
||||
delete[] temp_hour_sorting_array;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < resp_from_api["Hours"].size(); i++) {
|
||||
std::clog << (int)i << ": " << (int)HourIdLookupTable[i] << "\n";
|
||||
}
|
||||
|
||||
// some lambda dark magic
|
||||
const uint8_t num_of_columns = [&]() -> uint8_t {
|
||||
uint8_t result = 0;
|
||||
for (uint8_t i = 0; i < resp_from_api["Days"].size(); i++) {
|
||||
uint8_t currentSize = resp_from_api["Days"][i]["Atoms"].size();
|
||||
if (currentSize > result) {
|
||||
result = currentSize;
|
||||
for (uint8_t j = 0; j < resp_from_api["Days"][i]["Atoms"].size(); j++) {
|
||||
if (hour_id_to_index(
|
||||
HourIdLookupTable,
|
||||
resp_from_api["Days"][i]["Atoms"][j]["HourId"].get<uint8_t>()) >
|
||||
result) {
|
||||
result = hour_id_to_index(
|
||||
HourIdLookupTable,
|
||||
resp_from_api["Days"][i]["Atoms"][j]["HourId"].get<uint8_t>());
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return result + 1;
|
||||
}();
|
||||
|
||||
const uint8_t num_of_days = resp_from_api["Days"].size();
|
||||
@@ -182,7 +187,8 @@ void timetable_page() {
|
||||
if (resp_from_api["Hours"][j]["Id"].get<uint8_t>() ==
|
||||
HourIdLookupTable[i]) {
|
||||
// DEBUG
|
||||
// std::clog << resp_from_api["Hours"][j]["Caption"].get<std::string>();
|
||||
// std::clog <<
|
||||
// resp_from_api["Hours"][j]["Caption"].get<std::string>();
|
||||
|
||||
std::string caption_ascii =
|
||||
resp_from_api["Hours"][j]["Caption"].get<std::string>();
|
||||
@@ -200,7 +206,7 @@ void timetable_page() {
|
||||
}
|
||||
std::cerr << RED "[ERROR]" << RESET " Hour with id " << HourIdLookupTable[i]
|
||||
<< " not found\n";
|
||||
goto timetable_error_exit;
|
||||
safe_exit(128);
|
||||
|
||||
hour_id_found:
|
||||
|
||||
@@ -220,7 +226,7 @@ void timetable_page() {
|
||||
cells[i][j] =
|
||||
newwin(cell_height, cell_width, i * cell_height + DEFAULT_OFFSET,
|
||||
j * cell_width + DEFAULT_OFFSET);
|
||||
box(cells[i][j], 0, 0);
|
||||
|
||||
json *atom;
|
||||
for (uint8_t k = 0; k < resp_from_api["Days"][i]["Atoms"].size(); k++) {
|
||||
if (resp_from_api["Days"][i]["Atoms"][k]["HourId"].get<uint8_t>() ==
|
||||
@@ -231,39 +237,182 @@ void timetable_page() {
|
||||
}
|
||||
continue;
|
||||
correct_atom_found:
|
||||
std::wstring Subject_Abbrev;
|
||||
std::wstring Room_Abbrev;
|
||||
std::wstring Teacher_Abbrev;
|
||||
try {
|
||||
if (atom->contains("Change")) {
|
||||
if (atom->contains("Change") && !atom->at("Change").is_null()) {
|
||||
|
||||
switch (
|
||||
hash_djb2a(atom->at("Change")["ChangeType"].get<std::string>())) {
|
||||
case "Canceled"_sh:
|
||||
case "Removed"_sh:
|
||||
wattron(cells[i][j], COLOR_PAIR(COLOR_GREEN));
|
||||
box(cells[i][j], 0, 0);
|
||||
wattroff(cells[i][j], COLOR_PAIR(COLOR_GREEN));
|
||||
break;
|
||||
case "RoomChanged"_sh:
|
||||
case "Substitution"_sh:
|
||||
wattron(cells[i][j], COLOR_PAIR(COLOR_YELLOW));
|
||||
box(cells[i][j], 0, 0);
|
||||
wattroff(cells[i][j], COLOR_PAIR(COLOR_YELLOW));
|
||||
break;
|
||||
case "Added"_sh:
|
||||
wattron(cells[i][j], COLOR_PAIR(COLOR_BLUE));
|
||||
box(cells[i][j], 0, 0);
|
||||
wattroff(cells[i][j], COLOR_PAIR(COLOR_BLUE));
|
||||
break;
|
||||
default:
|
||||
// TODO add error handling
|
||||
__asm__("nop");
|
||||
}
|
||||
if (!atom->at("Change")["TypeAbbrev"].is_null()) {
|
||||
Subject_Abbrev = string_to_wstring(
|
||||
atom->at("Change")["TypeAbbrev"].get<std::string>());
|
||||
}
|
||||
} else {
|
||||
box(cells[i][j], 0, 0);
|
||||
}
|
||||
std::wstring Subject_Abbrev = get_data_for_atom(
|
||||
resp_from_api, atom, "Subjects", "SubjectId", "Abbrev");
|
||||
|
||||
if (Subject_Abbrev.empty()) {
|
||||
try {
|
||||
Subject_Abbrev = get_data_for_atom(resp_from_api, atom, "Subjects",
|
||||
"SubjectId", "Abbrev");
|
||||
} catch (...) {
|
||||
__asm__("nop");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Room_Abbrev = get_data_for_atom(resp_from_api, atom, "Rooms",
|
||||
"RoomId", "Abbrev");
|
||||
} catch (...) {
|
||||
__asm__("nop");
|
||||
}
|
||||
|
||||
try {
|
||||
Teacher_Abbrev = get_data_for_atom(resp_from_api, atom, "Teachers",
|
||||
"TeacherId", "Abbrev");
|
||||
} catch (...) {
|
||||
__asm__("nop");
|
||||
}
|
||||
|
||||
wprint_in_middle(cells[i][j], cell_height / 2,
|
||||
cell_width / 2 - wcslen(Subject_Abbrev.c_str()) / 2,
|
||||
wcslen(Subject_Abbrev.c_str()), Subject_Abbrev.c_str(),
|
||||
COLOR_PAIR(0));
|
||||
|
||||
std::wstring Room_Abbrev =
|
||||
get_data_for_atom(resp_from_api, atom, "Rooms", "RoomId", "Abbrev");
|
||||
wprint_in_middle(cells[i][j], cell_height - 2,
|
||||
cell_width - wcslen(Room_Abbrev.c_str()) - 1,
|
||||
wcslen(Room_Abbrev.c_str()), Room_Abbrev.c_str(),
|
||||
COLOR_PAIR(0));
|
||||
|
||||
std::wstring Teacher_Abbrev = get_data_for_atom(
|
||||
resp_from_api, atom, "Teachers", "TeacherId", "Abbrev");
|
||||
wprint_in_middle(cells[i][j], cell_height - 2, 1,
|
||||
wcslen(Teacher_Abbrev.c_str()), Teacher_Abbrev.c_str(),
|
||||
COLOR_PAIR(0));
|
||||
wrefresh(cells[i][j]);
|
||||
} catch (...) {
|
||||
} catch (const std::exception &e) {
|
||||
std::cerr << RED "[ERROR]" << RESET " " << e.what() << "\n";
|
||||
// world's best error handling
|
||||
__asm__("nop");
|
||||
}
|
||||
}
|
||||
}
|
||||
refresh();
|
||||
getch();
|
||||
timetable_error_exit:
|
||||
delete[] HourIdLookupTable;
|
||||
|
||||
SelectorType selected_cell(0, 0, 0, num_of_columns - 1, 0, num_of_days - 1);
|
||||
std::array<WINDOW *, 4> selector_windows;
|
||||
std::array<PANEL *, 4> selector_panels;
|
||||
|
||||
{
|
||||
const chtype corners[] = {
|
||||
ACS_ULCORNER, /* Upper left corner */
|
||||
ACS_URCORNER, /* Upper right corner */
|
||||
ACS_LLCORNER, /* Lower left corner */
|
||||
ACS_LRCORNER /* Lower right corner */
|
||||
};
|
||||
|
||||
unsigned short x_offset, y_offset;
|
||||
for (uint8_t i = 0; i < selector_windows.size(); i++) {
|
||||
|
||||
if (!(i % 2 == 0)) {
|
||||
x_offset = cell_width - 1;
|
||||
} else {
|
||||
x_offset = 0;
|
||||
}
|
||||
if (!(i < 2)) {
|
||||
y_offset = cell_height - 1;
|
||||
} else {
|
||||
y_offset = 0;
|
||||
}
|
||||
|
||||
selector_windows[i] =
|
||||
newwin(1, 1, DEFAULT_OFFSET + y_offset, DEFAULT_OFFSET + x_offset);
|
||||
selector_panels[i] = new_panel(selector_windows[i]);
|
||||
wattron(selector_windows[i], COLOR_PAIR(COLOR_RED));
|
||||
mvwaddch(selector_windows[i], 0, 0, corners[i]);
|
||||
wattroff(selector_windows[i], COLOR_PAIR(COLOR_RED));
|
||||
}
|
||||
}
|
||||
|
||||
update_panels();
|
||||
doupdate();
|
||||
|
||||
int ch;
|
||||
while ((ch = getch()) != KEY_F(1)) {
|
||||
run_loop_again:
|
||||
switch (ch) {
|
||||
case KEY_UP:
|
||||
case 'k':
|
||||
selected_cell.y--;
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
case 'j':
|
||||
selected_cell.y++;
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
case 'h':
|
||||
selected_cell.x--;
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
case 'l':
|
||||
selected_cell.x++;
|
||||
break;
|
||||
}
|
||||
{ // print selected indicator
|
||||
chtype top_left_corner =
|
||||
mvwinch(cells[selected_cell.y][selected_cell.x], 0, 0);
|
||||
|
||||
if (!((top_left_corner & A_CHARTEXT) == 32)) {
|
||||
for (uint8_t i = 0; i < selector_panels.size(); i++) {
|
||||
unsigned short x_offset, y_offset;
|
||||
if (!(i % 2 == 0)) {
|
||||
x_offset = cell_width - 1;
|
||||
} else {
|
||||
x_offset = 0;
|
||||
}
|
||||
if (!(i < 2)) {
|
||||
y_offset = cell_height - 1;
|
||||
} else {
|
||||
y_offset = 0;
|
||||
}
|
||||
|
||||
move_panel(selector_panels[i],
|
||||
DEFAULT_OFFSET + y_offset + selected_cell.y * cell_height,
|
||||
DEFAULT_OFFSET + x_offset + selected_cell.x * cell_width);
|
||||
}
|
||||
for (uint8_t i = 0; i < num_of_days; i++) {
|
||||
for (uint8_t j = 0; j < num_of_columns; j++) {
|
||||
wrefresh(cells[i][j]);
|
||||
}
|
||||
}
|
||||
update_panels();
|
||||
doupdate();
|
||||
|
||||
} else {
|
||||
// skip if the cell is empty
|
||||
goto run_loop_again;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] day_windows;
|
||||
delete[] lesson_windows;
|
||||
endwin();
|
||||
|
||||
+140
-2
@@ -2,8 +2,146 @@
|
||||
#ifndef _ba_ty_hg_
|
||||
#define _ba_ty_hg_
|
||||
|
||||
#include <istream>
|
||||
struct Config {
|
||||
bool verbose = false;
|
||||
bool ignoressl = false;
|
||||
bool verbose = false;
|
||||
bool ignoressl = false;
|
||||
};
|
||||
|
||||
class LimitedInt {
|
||||
private:
|
||||
int value;
|
||||
const int min_value;
|
||||
const int max_value;
|
||||
|
||||
void setValue(int new_value) {
|
||||
int range = max_value - min_value + 1;
|
||||
if (new_value < min_value || new_value > max_value) {
|
||||
new_value = ((new_value - min_value) % range + range) % range + min_value;
|
||||
}
|
||||
value = new_value;
|
||||
}
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
LimitedInt(int initial_value = 0, int min = std::numeric_limits<int>::min(),
|
||||
int max = std::numeric_limits<int>::max())
|
||||
: min_value(min), max_value(max) {
|
||||
if (min >= max)
|
||||
throw std::invalid_argument("Min must be less than max");
|
||||
setValue(initial_value);
|
||||
}
|
||||
|
||||
// Conversion operators
|
||||
operator int() const { return value; } // Implicit conversion to int
|
||||
|
||||
// Assignment operators
|
||||
LimitedInt &operator=(int rhs) {
|
||||
setValue(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Compound assignment with BoundedInt
|
||||
LimitedInt &operator+=(const LimitedInt &rhs) {
|
||||
setValue(value + rhs.value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Compound assignment with int
|
||||
LimitedInt &operator+=(int rhs) {
|
||||
setValue(value + rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Similarly define -=, *=, /=, %=, &=, |=, ^=, <<=, >>= for both types
|
||||
|
||||
// Increment/decrement
|
||||
LimitedInt &operator++() { // Prefix ++
|
||||
setValue(value + 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
LimitedInt operator++(int) { // Postfix ++
|
||||
LimitedInt temp = *this;
|
||||
setValue(value + 1);
|
||||
return temp;
|
||||
}
|
||||
|
||||
LimitedInt &operator--() { // Prefix --
|
||||
setValue(value - 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
LimitedInt operator--(int) { // Postfix --
|
||||
LimitedInt temp = *this;
|
||||
setValue(value - 1);
|
||||
return temp;
|
||||
}
|
||||
|
||||
// Binary arithmetic operators
|
||||
friend LimitedInt operator+(const LimitedInt &lhs, const LimitedInt &rhs) {
|
||||
LimitedInt result = lhs;
|
||||
result += rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
friend LimitedInt operator+(const LimitedInt &lhs, int rhs) {
|
||||
LimitedInt result = lhs;
|
||||
result += rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
friend LimitedInt operator+(int lhs, const LimitedInt &rhs) {
|
||||
LimitedInt result(lhs, rhs.min_value, rhs.max_value);
|
||||
result += rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Similarly define -, *, /, %, &, |, ^, <<, >> for all combinations
|
||||
|
||||
// Unary operators
|
||||
LimitedInt operator-() const {
|
||||
return LimitedInt(-value, min_value, max_value);
|
||||
}
|
||||
|
||||
LimitedInt operator+() const { return *this; }
|
||||
|
||||
// Comparison operators
|
||||
friend bool operator==(const LimitedInt &lhs, const LimitedInt &rhs) {
|
||||
return lhs.value == rhs.value;
|
||||
}
|
||||
|
||||
friend bool operator!=(const LimitedInt &lhs, const LimitedInt &rhs) {
|
||||
return lhs.value != rhs.value;
|
||||
}
|
||||
|
||||
friend bool operator<(const LimitedInt &lhs, const LimitedInt &rhs) {
|
||||
return lhs.value < rhs.value;
|
||||
}
|
||||
|
||||
// Similarly define >, <=, >= for both BoundedInt and int comparisons
|
||||
|
||||
// Stream operators
|
||||
friend std::ostream &operator<<(std::ostream &os, const LimitedInt &bi) {
|
||||
os << bi.value;
|
||||
return os;
|
||||
}
|
||||
|
||||
friend std::istream &operator>>(std::istream &is, LimitedInt &bi) {
|
||||
int temp;
|
||||
is >> temp;
|
||||
bi.setValue(temp);
|
||||
return is;
|
||||
}
|
||||
};
|
||||
|
||||
struct SelectorType {
|
||||
LimitedInt x;
|
||||
LimitedInt y;
|
||||
|
||||
SelectorType(int xArg, int yArg, int min_limit_x, int max_limit_x,
|
||||
int min_limit_y, int max_limit_y)
|
||||
: x(xArg, min_limit_x, max_limit_x), y(yArg, min_limit_y, max_limit_y) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user