diff --git a/.gitignore b/.gitignore index 137752d..f419996 100644 --- a/.gitignore +++ b/.gitignore @@ -252,6 +252,39 @@ fps_demo server_c Bash/ffmpeg-build/FFmpeg +# C/C++ compiled binaries +C/1dvelocitysimulator/1dvelocitysimulator +C/imageViewer/imageviewer +C/lichess_random_engine/random_engine +C/lichess_random_engine/perft +C/misc/generating_words +C/misc/randomJPG/generate_images +C/misc/split/split +C/opening_learner/opening_learner +C/scrapeWebsite/scrape +C/tests/polish_letters +C/vocabulary_curve/vocabulary_curve +C/websocketServer/websocket_server +CPP/miscelanious/brydz/brydz +CPP/miscelanious/calculateShotsDarts/darts +CPP/miscelanious/findIntegerPercentageValue/find_percentage +CPP/miscelanious/howManyValidISBNNumbersAreThere/isbn_counter +CPP/miscelanious/howOftenDoesCharOccur +CPP/miscelanious/quickchallenges +CPP/miscelanious/reverseString +CPP/miscelanious/solveQuadraticEquation +CPP/miscelanious/markovChainGenerator/markov +CPP/miscelanious/mutiplicationWithoutStar/multiplication +CPP/miscelanious/Pi/pi +CPP/miscelanious/randomDevice/random_device_demo +CPP/miscelanious/tictactoe/tictactoe +CPP/miscelanious/tierListConverter/tier_list_converter +CPP/miscelanious/xGoesTo0/xgoes +CPP/miscelanious/yousuckatcards/a.out +CPP/miscelanious/yousuckatcards/Bernouli/bernouli +CPP/miscelanious/yousuckatcards/Bernouli/test +CPP/tests/division_test + # Screen locker workout log python_pkg/screen_locker/workout_log.json python_pkg/music_gen/output/ @@ -282,3 +315,4 @@ python_pkg/cinema_planner/pasted_content.txt # FVM Version Cache .fvm/ +CPP/miscelanious/howManyValidISBNNumbersAreThere/ISBN.txt diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a95b147..2ac259f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -311,6 +311,18 @@ repos: types_or: [ts, tsx] files: ^TS/ + # =========================================================================== + # CHECK C/C++ BUILD FILES - Ensure every C/C++ dir has Makefile and run.sh + # =========================================================================== + - repo: local + hooks: + - id: check-c-cpp-build-files + name: check C/C++ dirs have Makefile and run.sh + entry: scripts/check_c_cpp_build_files.sh + language: script + types_or: [c, c++] + exclude: ^CPP/mini_browser/ + # =========================================================================== # REMOVE EMPTY DIRECTORIES - Clean up empty folders in the repo # =========================================================================== diff --git a/C/1dvelocitysimulator/Makefile b/C/1dvelocitysimulator/Makefile new file mode 100644 index 0000000..1fce470 --- /dev/null +++ b/C/1dvelocitysimulator/Makefile @@ -0,0 +1,19 @@ +CC := gcc +CFLAGS := -O2 -Wall -Wextra -std=c11 -D_DEFAULT_SOURCE +LDFLAGS := + +SRC := main.c +BIN := 1dvelocitysimulator + +all: $(BIN) + +$(BIN): $(SRC) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +run: $(BIN) + ./$(BIN) + +clean: + rm -f $(BIN) + +.PHONY: all run clean diff --git a/C/1dvelocitysimulator/main.c b/C/1dvelocitysimulator/main.c index d4ccc07..b5ea54a 100644 --- a/C/1dvelocitysimulator/main.c +++ b/C/1dvelocitysimulator/main.c @@ -1,7 +1,24 @@ #include #include #include + +#ifdef _WIN32 #include +#define SLEEP_MS(ms) Sleep(ms) +#define CLEAR_SCREEN() system("CLS") +#define PAUSE() system("PAUSE") +#else +#include +#define SLEEP_MS(ms) usleep((ms) * 1000U) +#define CLEAR_SCREEN() system("clear") +#define PAUSE() \ + do \ + { \ + printf("Press Enter to continue..."); \ + getchar(); \ + } while (0) +#endif + #define LINE_LENGTH 100 void C() @@ -13,27 +30,27 @@ void C() void printAcceleration(int acceleration) { printf("The value of acceleration is: %d\n", acceleration); - system("PAUSE"); + PAUSE(); return; } -void pauseSystem() { system("PAUSE"); } +void pauseSystem() { PAUSE(); } void clearScreen() { - system("CLS"); + CLEAR_SCREEN(); return; } void pauseForASecond() { - Sleep(1000); + SLEEP_MS(1000); return; } void pauseForGivenTime(float given_time) { - Sleep(fabs(given_time * 1000)); + SLEEP_MS((unsigned int)fabs(given_time * 1000)); return; } diff --git a/C/1dvelocitysimulator/run.sh b/C/1dvelocitysimulator/run.sh new file mode 100755 index 0000000..aa6f158 --- /dev/null +++ b/C/1dvelocitysimulator/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +make +./1dvelocitysimulator diff --git a/C/fps/run.sh b/C/fps/run.sh new file mode 100755 index 0000000..f90b626 --- /dev/null +++ b/C/fps/run.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -e +# Install dependencies +if command -v apt-get &>/dev/null; then + sudo apt-get install -y freeglut3-dev libglu1-mesa-dev libsdl2-dev +elif command -v pacman &>/dev/null; then + pacman -Q freeglut sdl2 &>/dev/null || sudo pacman -S --noconfirm freeglut sdl2 +elif command -v dnf &>/dev/null; then + sudo dnf install -y freeglut-devel mesa-libGLU-devel SDL2-devel +fi +make +./fps_demo diff --git a/C/imageViewer/run.sh b/C/imageViewer/run.sh new file mode 100755 index 0000000..2c44c2d --- /dev/null +++ b/C/imageViewer/run.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -e +# Install dependencies +if command -v apt-get &>/dev/null; then + sudo apt-get install -y libsdl2-dev libsdl2-image-dev +elif command -v pacman &>/dev/null; then + pacman -Q sdl2 sdl2_image &>/dev/null || sudo pacman -S --noconfirm sdl2 sdl2_image +elif command -v dnf &>/dev/null; then + sudo dnf install -y SDL2-devel SDL2_image-devel +fi +make +echo "Usage: ./imageviewer " +if [[ $# -gt 0 ]]; then + ./imageviewer "$@" +fi diff --git a/C/lichess_random_engine/run.sh b/C/lichess_random_engine/run.sh new file mode 100755 index 0000000..8082341 --- /dev/null +++ b/C/lichess_random_engine/run.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -e +make +echo "Usage: ./random_engine --fen \"\" move1 move2 ..." +echo " ./random_engine --fen \"\" --explain move1 ..." diff --git a/C/misc/Makefile b/C/misc/Makefile new file mode 100644 index 0000000..268edf2 --- /dev/null +++ b/C/misc/Makefile @@ -0,0 +1,19 @@ +CC := gcc +CFLAGS := -O2 -Wall -Wextra -std=c11 +LDFLAGS := + +SRC := generatingWordsEndingWIthalka.c +BIN := generating_words + +all: $(BIN) + +$(BIN): $(SRC) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +run: $(BIN) + ./$(BIN) + +clean: + rm -f $(BIN) + +.PHONY: all run clean diff --git a/C/misc/randomJPG/run.sh b/C/misc/randomJPG/run.sh new file mode 100755 index 0000000..28ddbc7 --- /dev/null +++ b/C/misc/randomJPG/run.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -e +# Install dependencies +if command -v apt-get &>/dev/null; then + sudo apt-get install -y libjpeg-dev +elif command -v pacman &>/dev/null; then + pacman -Q libjpeg-turbo &>/dev/null || sudo pacman -S --noconfirm libjpeg-turbo +elif command -v dnf &>/dev/null; then + sudo dnf install -y libjpeg-turbo-devel +fi +make +./generate_images diff --git a/C/misc/run.sh b/C/misc/run.sh new file mode 100755 index 0000000..683b87c --- /dev/null +++ b/C/misc/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +make +./generating_words diff --git a/C/misc/split/Makefile b/C/misc/split/Makefile new file mode 100644 index 0000000..5400fa9 --- /dev/null +++ b/C/misc/split/Makefile @@ -0,0 +1,19 @@ +CC := gcc +CFLAGS := -O2 -Wall -Wextra -std=c11 +LDFLAGS := + +SRC := main.c +BIN := split + +all: $(BIN) + +$(BIN): $(SRC) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +run: $(BIN) + ./$(BIN) + +clean: + rm -f $(BIN) + +.PHONY: all run clean diff --git a/C/misc/split/run.sh b/C/misc/split/run.sh new file mode 100755 index 0000000..ddfb785 --- /dev/null +++ b/C/misc/split/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +make +./split diff --git a/C/opening_learner/chess.o b/C/opening_learner/chess.o index ee51fb8..bebc2ad 100644 Binary files a/C/opening_learner/chess.o and b/C/opening_learner/chess.o differ diff --git a/C/opening_learner/engine.o b/C/opening_learner/engine.o index e400c89..60b6546 100644 Binary files a/C/opening_learner/engine.o and b/C/opening_learner/engine.o differ diff --git a/C/opening_learner/gui.o b/C/opening_learner/gui.o index 46d7ba4..6b95491 100644 Binary files a/C/opening_learner/gui.o and b/C/opening_learner/gui.o differ diff --git a/C/opening_learner/main.o b/C/opening_learner/main.o index e59782f..c308086 100644 Binary files a/C/opening_learner/main.o and b/C/opening_learner/main.o differ diff --git a/C/opening_learner/mistakes.o b/C/opening_learner/mistakes.o index e8e7eba..91cbd2e 100644 Binary files a/C/opening_learner/mistakes.o and b/C/opening_learner/mistakes.o differ diff --git a/C/opening_learner/opening_learner b/C/opening_learner/opening_learner index 578843f..7b8ae26 100755 Binary files a/C/opening_learner/opening_learner and b/C/opening_learner/opening_learner differ diff --git a/C/opening_learner/run.sh b/C/opening_learner/run.sh index e88c54c..2043ff1 100755 --- a/C/opening_learner/run.sh +++ b/C/opening_learner/run.sh @@ -14,7 +14,7 @@ if ! command -v sdl2-config >/dev/null 2>&1; then sudo apt-get install -y libsdl2-dev ;; arch|manjaro|endeavouros) - sudo pacman -Syu --noconfirm sdl2 + pacman -Q sdl2 &>/dev/null || sudo pacman -S --noconfirm sdl2 ;; fedora) sudo dnf install -y SDL2-devel diff --git a/C/scrapeWebsite/Makefile b/C/scrapeWebsite/Makefile new file mode 100644 index 0000000..e8586c0 --- /dev/null +++ b/C/scrapeWebsite/Makefile @@ -0,0 +1,19 @@ +CC := gcc +CFLAGS := -O2 -Wall -Wextra -std=c11 -D_DEFAULT_SOURCE $(shell pkg-config --cflags libcurl libxml-2.0 2>/dev/null) +LDFLAGS := $(shell pkg-config --libs libcurl libxml-2.0 2>/dev/null) + +SRC := scrape.c +BIN := scrape + +all: $(BIN) + +$(BIN): $(SRC) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +run: $(BIN) + ./$(BIN) + +clean: + rm -f $(BIN) + +.PHONY: all run clean diff --git a/C/scrapeWebsite/run.sh b/C/scrapeWebsite/run.sh new file mode 100755 index 0000000..c859efb --- /dev/null +++ b/C/scrapeWebsite/run.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -e +# Install dependencies +if command -v apt-get &>/dev/null; then + sudo apt-get install -y libcurl4-openssl-dev libxml2-dev +elif command -v pacman &>/dev/null; then + pacman -Q curl libxml2 &>/dev/null || sudo pacman -S --noconfirm curl libxml2 +elif command -v dnf &>/dev/null; then + sudo dnf install -y libcurl-devel libxml2-devel +fi +make +./scrape diff --git a/C/tests/Makefile b/C/tests/Makefile new file mode 100644 index 0000000..bb1e434 --- /dev/null +++ b/C/tests/Makefile @@ -0,0 +1,19 @@ +CC := gcc +CFLAGS := -O2 -Wall -Wextra -std=c11 -D_DEFAULT_SOURCE +LDFLAGS := + +SRC := generatingPolishLettersOnWindowsTerminal.c +BIN := polish_letters + +all: $(BIN) + +$(BIN): $(SRC) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +run: $(BIN) + ./$(BIN) + +clean: + rm -f $(BIN) + +.PHONY: all run clean diff --git a/C/tests/generatingPolishLettersOnWindowsTerminal.c b/C/tests/generatingPolishLettersOnWindowsTerminal.c index d69be9a..c04be43 100644 --- a/C/tests/generatingPolishLettersOnWindowsTerminal.c +++ b/C/tests/generatingPolishLettersOnWindowsTerminal.c @@ -1,10 +1,17 @@ #include #include -#include -int main() +#ifdef _WIN32 +#include +#define SLEEP_S(s) Sleep((s) * 1000) +#else +#include +#define SLEEP_S(s) sleep(s) +#endif + +int main(void) { printf("Henlo\n"); - sleep(20); + SLEEP_S(20); return 0; } diff --git a/C/tests/run.sh b/C/tests/run.sh new file mode 100755 index 0000000..35a4386 --- /dev/null +++ b/C/tests/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +make +./polish_letters diff --git a/C/vocabulary_curve/run.sh b/C/vocabulary_curve/run.sh new file mode 100755 index 0000000..226f7cc --- /dev/null +++ b/C/vocabulary_curve/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +make +./vocabulary_curve diff --git a/C/vocabulary_curve/vocabulary_curve b/C/vocabulary_curve/vocabulary_curve index 360863e..e41ae48 100755 Binary files a/C/vocabulary_curve/vocabulary_curve and b/C/vocabulary_curve/vocabulary_curve differ diff --git a/C/websocketServer/Makefile b/C/websocketServer/Makefile new file mode 100644 index 0000000..a5212ff --- /dev/null +++ b/C/websocketServer/Makefile @@ -0,0 +1,19 @@ +CC := gcc +CFLAGS := -O2 -Wall -Wextra -std=c11 $(shell pkg-config --cflags libwebsockets 2>/dev/null) +LDFLAGS := $(shell pkg-config --libs libwebsockets 2>/dev/null) + +SRC := main.c +BIN := websocket_server + +all: $(BIN) + +$(BIN): $(SRC) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +run: $(BIN) + ./$(BIN) + +clean: + rm -f $(BIN) + +.PHONY: all run clean diff --git a/C/websocketServer/run.sh b/C/websocketServer/run.sh new file mode 100755 index 0000000..94b4383 --- /dev/null +++ b/C/websocketServer/run.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -e +# Install dependencies +if command -v pacman &>/dev/null; then + pacman -Q libwebsockets &>/dev/null || sudo pacman -S --noconfirm libwebsockets +elif command -v apt-get &>/dev/null; then + sudo apt-get install -y libwebsockets-dev +elif command -v dnf &>/dev/null; then + sudo dnf install -y libwebsockets-devel +elif command -v zypper &>/dev/null; then + sudo zypper install -y libwebsockets-devel +else + echo "Could not detect package manager. Please install libwebsockets manually." >&2 + exit 1 +fi +make +./websocket_server diff --git a/CPP/miscelanious/Makefile b/CPP/miscelanious/Makefile new file mode 100644 index 0000000..e790323 --- /dev/null +++ b/CPP/miscelanious/Makefile @@ -0,0 +1,30 @@ +CXX := g++ +CXXFLAGS := -O2 -Wall -Wextra -std=c++17 +LDFLAGS := + +BINS := howOftenDoesCharOccur quickchallenges reverseString solveQuadraticEquation + +all: $(BINS) + +howOftenDoesCharOccur: howOftenDoesCharOccur.cpp + $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + +quickchallenges: quickchallenges.cpp + $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + +reverseString: reverseString.cpp + $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + +solveQuadraticEquation: solveQuadraticEquation.cpp + $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + +run: all + ./howOftenDoesCharOccur + ./quickchallenges + ./reverseString + ./solveQuadraticEquation + +clean: + rm -f $(BINS) + +.PHONY: all run clean diff --git a/CPP/miscelanious/Pi/Makefile b/CPP/miscelanious/Pi/Makefile new file mode 100644 index 0000000..b7de6be --- /dev/null +++ b/CPP/miscelanious/Pi/Makefile @@ -0,0 +1,19 @@ +CXX := g++ +CXXFLAGS := -O2 -Wall -Wextra -std=c++17 +LDFLAGS := -lm + +SRC := main.cpp +BIN := pi + +all: $(BIN) + +$(BIN): $(SRC) + $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + +run: $(BIN) + ./$(BIN) + +clean: + rm -f $(BIN) + +.PHONY: all run clean diff --git a/CPP/miscelanious/Pi/run.sh b/CPP/miscelanious/Pi/run.sh new file mode 100755 index 0000000..419b200 --- /dev/null +++ b/CPP/miscelanious/Pi/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +make +./pi diff --git a/CPP/miscelanious/brydz/Makefile b/CPP/miscelanious/brydz/Makefile new file mode 100644 index 0000000..105fb24 --- /dev/null +++ b/CPP/miscelanious/brydz/Makefile @@ -0,0 +1,19 @@ +CXX := g++ +CXXFLAGS := -O2 -Wall -Wextra -std=c++17 +LDFLAGS := + +SRC := brydz.cpp +BIN := brydz + +all: $(BIN) + +$(BIN): $(SRC) + $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + +run: $(BIN) + ./$(BIN) + +clean: + rm -f $(BIN) + +.PHONY: all run clean diff --git a/CPP/miscelanious/brydz/brydz.cpp b/CPP/miscelanious/brydz/brydz.cpp index 36d9297..1e9a658 100644 --- a/CPP/miscelanious/brydz/brydz.cpp +++ b/CPP/miscelanious/brydz/brydz.cpp @@ -4,7 +4,7 @@ const std::vector ATUTY = {"BA", "Trefl", "Karo", "Kier", "Pik"}; const bool A_ID = 0; const bool B_ID = 1; -const std::vector GRACZE = {}; +const std::vector GRACZE = {"Gracz A", "Gracz B"}; const std::vector PO_PARTII{"Nikt", GRACZE[A_ID], GRACZE[B_ID], "Obaj Gracze"}; const int DOMYSLNE_LEWY = 6; diff --git a/CPP/miscelanious/brydz/run.sh b/CPP/miscelanious/brydz/run.sh new file mode 100755 index 0000000..2f96b54 --- /dev/null +++ b/CPP/miscelanious/brydz/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +make +./brydz diff --git a/CPP/miscelanious/calculateShotsDarts/Makefile b/CPP/miscelanious/calculateShotsDarts/Makefile new file mode 100644 index 0000000..873aa8c --- /dev/null +++ b/CPP/miscelanious/calculateShotsDarts/Makefile @@ -0,0 +1,20 @@ +CXX := g++ +CXXFLAGS := -O2 -Wall -Wextra -std=c++17 +LDFLAGS := + +# main.cpp includes basic.cpp directly +SRC := main.cpp +BIN := darts + +all: $(BIN) + +$(BIN): $(SRC) + $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + +run: $(BIN) + ./$(BIN) + +clean: + rm -f $(BIN) + +.PHONY: all run clean diff --git a/CPP/miscelanious/calculateShotsDarts/basic.cpp b/CPP/miscelanious/calculateShotsDarts/basic.cpp index bc7c383..acdb536 100644 --- a/CPP/miscelanious/calculateShotsDarts/basic.cpp +++ b/CPP/miscelanious/calculateShotsDarts/basic.cpp @@ -4,7 +4,6 @@ #include #include #include -#include void print(const std::string s) { std::cout << s << std::endl; } void printErrorStringContainsNotNumber(const std::string s) { diff --git a/CPP/miscelanious/calculateShotsDarts/main.cpp b/CPP/miscelanious/calculateShotsDarts/main.cpp index 0dd4134..eb631ae 100644 --- a/CPP/miscelanious/calculateShotsDarts/main.cpp +++ b/CPP/miscelanious/calculateShotsDarts/main.cpp @@ -63,8 +63,78 @@ bool validInput(const std::string s) { return 1; } -// cppcheck-suppress missingReturn -std::vector requiredShoots(const int pointsLeft) {} +// Darts checkout finder: find combinations of up to 3 darts that reduce +// pointsLeft to exactly 0, finishing on a double (standard 501 rules). +std::vector requiredShoots(const int pointsLeft) { + // All valid dart scores with labels + std::vector> all_darts; + for (int i = MIN_SPOT; i <= MAX_SPOT; i++) + all_darts.push_back({i, std::to_string(i)}); + all_darts.push_back({25, "Bull"}); + for (int i = MIN_SPOT; i <= MAX_SPOT; i++) + all_darts.push_back({i * 2, "D" + std::to_string(i)}); + all_darts.push_back({50, "D-Bull"}); + for (int i = MIN_SPOT; i <= MAX_SPOT; i++) + all_darts.push_back({i * 3, "T" + std::to_string(i)}); + + // Doubles only (valid finishing darts) + std::vector> doubles; + for (int i = MIN_SPOT; i <= MAX_SPOT; i++) + doubles.push_back({i * 2, "D" + std::to_string(i)}); + doubles.push_back({50, "D-Bull"}); + + std::vector> checkouts; + const int MAX_RESULTS = 5; + + // 1-dart checkouts + for (auto &d : doubles) + if (d.first == pointsLeft) + checkouts.push_back({d.second}); + + // 2-dart checkouts + for (auto &d1 : all_darts) { + for (auto &d2 : doubles) { + if (d1.first + d2.first == pointsLeft) { + checkouts.push_back({d1.second, d2.second}); + if ((int)checkouts.size() >= MAX_RESULTS) + goto done; + } + } + } + + // 3-dart checkouts (stop early once we have enough results) + for (auto &d1 : all_darts) { + for (auto &d2 : all_darts) { + for (auto &d3 : doubles) { + if (d1.first + d2.first + d3.first == pointsLeft) { + checkouts.push_back({d1.second, d2.second, d3.second}); + if ((int)checkouts.size() >= MAX_RESULTS) + goto done; + } + } + } + } +done: + if (checkouts.empty()) { + print("No checkout possible for " + std::to_string(pointsLeft) + + " points."); + return {}; + } + + print("Possible checkouts (showing up to " + std::to_string(MAX_RESULTS) + + "):"); + std::vector firstCheckout; + for (auto &combo : checkouts) { + std::string line; + for (unsigned int i = 0; i < combo.size(); i++) { + if (i > 0) + line += " \u2192 "; + line += combo[i]; + } + print(line); + } + return firstCheckout; +} int main() { print("Enter points left: "); diff --git a/CPP/miscelanious/calculateShotsDarts/run.sh b/CPP/miscelanious/calculateShotsDarts/run.sh new file mode 100755 index 0000000..4c932f1 --- /dev/null +++ b/CPP/miscelanious/calculateShotsDarts/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +make +./darts diff --git a/CPP/miscelanious/findIntegerPercentageValue/Makefile b/CPP/miscelanious/findIntegerPercentageValue/Makefile new file mode 100644 index 0000000..a6f27ef --- /dev/null +++ b/CPP/miscelanious/findIntegerPercentageValue/Makefile @@ -0,0 +1,19 @@ +CXX := g++ +CXXFLAGS := -O2 -Wall -Wextra -std=c++17 +LDFLAGS := + +SRC := main.cpp +BIN := find_percentage + +all: $(BIN) + +$(BIN): $(SRC) + $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + +run: $(BIN) + ./$(BIN) + +clean: + rm -f $(BIN) + +.PHONY: all run clean diff --git a/CPP/miscelanious/findIntegerPercentageValue/run.sh b/CPP/miscelanious/findIntegerPercentageValue/run.sh new file mode 100755 index 0000000..5e6738f --- /dev/null +++ b/CPP/miscelanious/findIntegerPercentageValue/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +make +./find_percentage diff --git a/CPP/miscelanious/howManyValidISBNNumbersAreThere/Makefile b/CPP/miscelanious/howManyValidISBNNumbersAreThere/Makefile new file mode 100644 index 0000000..b6f4eb0 --- /dev/null +++ b/CPP/miscelanious/howManyValidISBNNumbersAreThere/Makefile @@ -0,0 +1,19 @@ +CXX := g++ +CXXFLAGS := -O2 -Wall -Wextra -std=c++17 +LDFLAGS := + +SRC := 11.cpp +BIN := isbn_counter + +all: $(BIN) + +$(BIN): $(SRC) + $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + +run: $(BIN) + ./$(BIN) + +clean: + rm -f $(BIN) + +.PHONY: all run clean diff --git a/CPP/miscelanious/howManyValidISBNNumbersAreThere/run.sh b/CPP/miscelanious/howManyValidISBNNumbersAreThere/run.sh new file mode 100755 index 0000000..e9f640c --- /dev/null +++ b/CPP/miscelanious/howManyValidISBNNumbersAreThere/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +make +./isbn_counter diff --git a/CPP/miscelanious/markovChainGenerator/Makefile b/CPP/miscelanious/markovChainGenerator/Makefile new file mode 100644 index 0000000..6d46e2d --- /dev/null +++ b/CPP/miscelanious/markovChainGenerator/Makefile @@ -0,0 +1,20 @@ +CXX := g++ +CXXFLAGS := -O2 -Wall -Wextra -std=c++17 +LDFLAGS := + +# main.cpp includes basic.cpp directly +SRC := main.cpp +BIN := markov + +all: $(BIN) + +$(BIN): $(SRC) + $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + +run: $(BIN) + ./$(BIN) + +clean: + rm -f $(BIN) + +.PHONY: all run clean diff --git a/CPP/miscelanious/markovChainGenerator/main.cpp b/CPP/miscelanious/markovChainGenerator/main.cpp index 6a87674..248e922 100644 --- a/CPP/miscelanious/markovChainGenerator/main.cpp +++ b/CPP/miscelanious/markovChainGenerator/main.cpp @@ -9,21 +9,20 @@ struct wordOccurences { std::string word; int occurences; -} +}; struct previousWords { std::string word; std::vector previousWords; }; -struct wordProbabiliy { +struct wordProbability { std::string previousWord; std::string nextWord; float probability; -} +}; -bool validInput(const std::string userInput) -{ +bool validInput(const std::string userInput) { if (stringContainsNumbers(userInput)) return 0; return 1; @@ -61,8 +60,10 @@ int wordRepeats(const std::vector wordsList, bool alreadyExists(const std::vector wordsList, const std::string s) { for (unsigned int i = 0; i < wordsList.size(); i++) { - if(s == wordsList.previousWOrds + if (s == wordsList.at(i).word) + return true; } + return false; } std::vector @@ -73,17 +74,16 @@ getWordsAndTheirPrevious(const std::vector words) { previousWords temp; temp.word = words.at(i); wordOccurences tempTwo; - tempTwo.word = words.at(i - 1)); - tempTwo.occurences = 1; - temp.previousWords.push_back(tempTwo); - int position = wordRepeats(wordsList, temp.word); - if (position == -1) { - wordsList.push_back(temp); - } else { + tempTwo.word = words.at(i - 1); + tempTwo.occurences = 1; + temp.previousWords.push_back(tempTwo); + int position = wordRepeats(wordsList, temp.word); + if (position == -1) { + wordsList.push_back(temp); + } else { - wordsList.at(position).previousWords.push_back( - temp.previousWords.at(0)); - } + wordsList.at(position).previousWords.push_back(temp.previousWords.at(0)); + } } return wordsList; } @@ -92,7 +92,7 @@ void printPreviousWord(const previousWords word) { std::cout << "The word is \"" << word.word << "\" Words before it are: " << std::endl; for (unsigned int i = 0; i < word.previousWords.size(); i++) { - print(word.previousWords.at(i)); + print(word.previousWords.at(i).word); } } @@ -105,9 +105,22 @@ void printPreviousWordsVector(const std::vector v) { std::vector getWordProbability(const std::vector wordsList) { std::vector probalityVector; - for (unsigned int i = 0; i - 1 < wordsList.size(); i++) { - pro + for (unsigned int i = 0; i < wordsList.size(); i++) { + int total = 0; + for (unsigned int j = 0; j < wordsList.at(i).previousWords.size(); j++) + total += wordsList.at(i).previousWords.at(j).occurences; + for (unsigned int j = 0; j < wordsList.at(i).previousWords.size(); j++) { + wordProbability wp; + wp.previousWord = wordsList.at(i).previousWords.at(j).word; + wp.nextWord = wordsList.at(i).word; + wp.probability = + total > 0 + ? (float)wordsList.at(i).previousWords.at(j).occurences / total + : 0.0f; + probalityVector.push_back(wp); + } } + return probalityVector; } int main() { diff --git a/CPP/miscelanious/markovChainGenerator/run.sh b/CPP/miscelanious/markovChainGenerator/run.sh new file mode 100755 index 0000000..87d4b5b --- /dev/null +++ b/CPP/miscelanious/markovChainGenerator/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +make +./markov diff --git a/CPP/miscelanious/mutiplicationWithoutStar/Makefile b/CPP/miscelanious/mutiplicationWithoutStar/Makefile new file mode 100644 index 0000000..40d1289 --- /dev/null +++ b/CPP/miscelanious/mutiplicationWithoutStar/Makefile @@ -0,0 +1,19 @@ +CXX := g++ +CXXFLAGS := -O2 -Wall -Wextra -std=c++17 +LDFLAGS := + +SRC := multiplication.cpp +BIN := multiplication + +all: $(BIN) + +$(BIN): $(SRC) + $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + +run: $(BIN) + ./$(BIN) + +clean: + rm -f $(BIN) + +.PHONY: all run clean diff --git a/CPP/miscelanious/mutiplicationWithoutStar/run.sh b/CPP/miscelanious/mutiplicationWithoutStar/run.sh new file mode 100755 index 0000000..4738372 --- /dev/null +++ b/CPP/miscelanious/mutiplicationWithoutStar/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +make +./multiplication diff --git a/CPP/miscelanious/randomDevice/Makefile b/CPP/miscelanious/randomDevice/Makefile new file mode 100644 index 0000000..c2550b9 --- /dev/null +++ b/CPP/miscelanious/randomDevice/Makefile @@ -0,0 +1,19 @@ +CXX := g++ +CXXFLAGS := -O2 -Wall -Wextra -std=c++17 +LDFLAGS := + +SRC := main.cpp +BIN := random_device_demo + +all: $(BIN) + +$(BIN): $(SRC) + $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + +run: $(BIN) + ./$(BIN) + +clean: + rm -f $(BIN) + +.PHONY: all run clean diff --git a/CPP/miscelanious/randomDevice/run.sh b/CPP/miscelanious/randomDevice/run.sh new file mode 100755 index 0000000..79e8981 --- /dev/null +++ b/CPP/miscelanious/randomDevice/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +make +./random_device_demo diff --git a/CPP/miscelanious/run.sh b/CPP/miscelanious/run.sh new file mode 100755 index 0000000..d999467 --- /dev/null +++ b/CPP/miscelanious/run.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -e +make +./howOftenDoesCharOccur +./quickchallenges +./reverseString +./solveQuadraticEquation diff --git a/CPP/miscelanious/tictactoe/Makefile b/CPP/miscelanious/tictactoe/Makefile new file mode 100644 index 0000000..2bdc7e2 --- /dev/null +++ b/CPP/miscelanious/tictactoe/Makefile @@ -0,0 +1,19 @@ +CXX := g++ +CXXFLAGS := -O2 -Wall -Wextra -std=c++17 +LDFLAGS := + +SRC := tictactoe.cpp +BIN := tictactoe + +all: $(BIN) + +$(BIN): $(SRC) + $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + +run: $(BIN) + ./$(BIN) + +clean: + rm -f $(BIN) + +.PHONY: all run clean diff --git a/CPP/miscelanious/tictactoe/run.sh b/CPP/miscelanious/tictactoe/run.sh new file mode 100755 index 0000000..0dc73eb --- /dev/null +++ b/CPP/miscelanious/tictactoe/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +make +./tictactoe diff --git a/CPP/miscelanious/tierListConverter/Makefile b/CPP/miscelanious/tierListConverter/Makefile new file mode 100644 index 0000000..0ee2271 --- /dev/null +++ b/CPP/miscelanious/tierListConverter/Makefile @@ -0,0 +1,19 @@ +CXX := g++ +CXXFLAGS := -O2 -Wall -Wextra -std=c++17 +LDFLAGS := + +SRC := tierListConverter.cpp +BIN := tier_list_converter + +all: $(BIN) + +$(BIN): $(SRC) + $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + +run: $(BIN) + ./$(BIN) + +clean: + rm -f $(BIN) + +.PHONY: all run clean diff --git a/CPP/miscelanious/tierListConverter/run.sh b/CPP/miscelanious/tierListConverter/run.sh new file mode 100755 index 0000000..573f39b --- /dev/null +++ b/CPP/miscelanious/tierListConverter/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +make +./tier_list_converter diff --git a/CPP/miscelanious/xGoesTo0/Makefile b/CPP/miscelanious/xGoesTo0/Makefile new file mode 100644 index 0000000..0bfc1a7 --- /dev/null +++ b/CPP/miscelanious/xGoesTo0/Makefile @@ -0,0 +1,19 @@ +CXX := g++ +CXXFLAGS := -O2 -Wall -Wextra -std=c++17 +LDFLAGS := + +SRC := xgoes.cpp +BIN := xgoes + +all: $(BIN) + +$(BIN): $(SRC) + $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + +run: $(BIN) + ./$(BIN) + +clean: + rm -f $(BIN) + +.PHONY: all run clean diff --git a/CPP/miscelanious/xGoesTo0/run.sh b/CPP/miscelanious/xGoesTo0/run.sh new file mode 100755 index 0000000..4f56cca --- /dev/null +++ b/CPP/miscelanious/xGoesTo0/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +make +./xgoes diff --git a/CPP/miscelanious/yousuckatcards/Bernouli/Makefile b/CPP/miscelanious/yousuckatcards/Bernouli/Makefile new file mode 100644 index 0000000..f42e63b --- /dev/null +++ b/CPP/miscelanious/yousuckatcards/Bernouli/Makefile @@ -0,0 +1,22 @@ +CXX := g++ +CXXFLAGS := -O2 -Wall -Wextra -std=c++17 +LDFLAGS := + +BINS := bernouli test + +all: $(BINS) + +bernouli: bernouli.cpp + $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + +test: test.cpp + $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + +run: all + ./bernouli + ./test + +clean: + rm -f $(BINS) + +.PHONY: all run clean diff --git a/CPP/miscelanious/yousuckatcards/Bernouli/run.sh b/CPP/miscelanious/yousuckatcards/Bernouli/run.sh new file mode 100755 index 0000000..7cbf675 --- /dev/null +++ b/CPP/miscelanious/yousuckatcards/Bernouli/run.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -e +make +./bernouli +./test diff --git a/CPP/miscelanious/yousuckatcards/run.sh b/CPP/miscelanious/yousuckatcards/run.sh new file mode 100755 index 0000000..3d2e80e --- /dev/null +++ b/CPP/miscelanious/yousuckatcards/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +make +./a.out diff --git a/CPP/tests/Makefile b/CPP/tests/Makefile new file mode 100644 index 0000000..24168f9 --- /dev/null +++ b/CPP/tests/Makefile @@ -0,0 +1,19 @@ +CXX := g++ +CXXFLAGS := -O2 -Wall -Wextra -std=c++17 +LDFLAGS := + +SRC := howCppHandlesDivision.cpp +BIN := division_test + +all: $(BIN) + +$(BIN): $(SRC) + $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + +run: $(BIN) + ./$(BIN) + +clean: + rm -f $(BIN) + +.PHONY: all run clean diff --git a/CPP/tests/run.sh b/CPP/tests/run.sh new file mode 100755 index 0000000..cc8ac67 --- /dev/null +++ b/CPP/tests/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +make +./division_test diff --git a/LaTeX/.gitignore b/linux_configuration/LaTeX/.gitignore similarity index 100% rename from LaTeX/.gitignore rename to linux_configuration/LaTeX/.gitignore diff --git a/LaTeX/main.tex b/linux_configuration/LaTeX/main.tex similarity index 100% rename from LaTeX/main.tex rename to linux_configuration/LaTeX/main.tex diff --git a/LaTeX/mauin2.tex b/linux_configuration/LaTeX/mauin2.tex similarity index 100% rename from LaTeX/mauin2.tex rename to linux_configuration/LaTeX/mauin2.tex diff --git a/python_pkg/anki_decks/polish_gminy/run.sh b/python_pkg/anki_decks/polish_gminy/run.sh index e18a3d3..3f7765c 100755 --- a/python_pkg/anki_decks/polish_gminy/run.sh +++ b/python_pkg/anki_decks/polish_gminy/run.sh @@ -21,8 +21,7 @@ echo "Activating virtual environment..." source "$VENV_DIR/bin/activate" echo "Installing dependencies..." -pip install --quiet --upgrade pip -pip install --quiet matplotlib genanki geopandas requests shapely +pip show genanki &>/dev/null || pip install --quiet matplotlib genanki geopandas requests shapely cd "$SCRIPT_DIR" diff --git a/python_pkg/anki_decks/polish_license_plates/run.sh b/python_pkg/anki_decks/polish_license_plates/run.sh new file mode 100755 index 0000000..ba7a253 --- /dev/null +++ b/python_pkg/anki_decks/polish_license_plates/run.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)" +VENV="$REPO_ROOT/.venv" +[[ ! -d "$VENV" ]] && python3 -m venv "$VENV" +_pip_sync() { local r="$1" h; h=$(md5sum "$r"|cut -d' ' -f1); local lf="$VENV/.req_${h:0:8}.lock"; [[ -f "$lf" ]] && return; "$VENV/bin/pip" install -r "$r" -q && touch "$lf"; } +_pip_sync "$REPO_ROOT/requirements.txt" +"$VENV/bin/python" "$SCRIPT_DIR/polish_license_plates_anki.py" "$@" diff --git a/python_pkg/anki_decks/polish_powiaty/run.sh b/python_pkg/anki_decks/polish_powiaty/run.sh index 3df7b8b..9c72b41 100755 --- a/python_pkg/anki_decks/polish_powiaty/run.sh +++ b/python_pkg/anki_decks/polish_powiaty/run.sh @@ -19,8 +19,7 @@ echo "Activating virtual environment..." source "$VENV_DIR/bin/activate" echo "Installing dependencies..." -pip install --quiet --upgrade pip -pip install --quiet matplotlib genanki geopandas +pip show genanki &>/dev/null || pip install --quiet matplotlib genanki geopandas cd "$SCRIPT_DIR" diff --git a/python_pkg/anki_decks/run.sh b/python_pkg/anki_decks/run.sh new file mode 100755 index 0000000..20bb77d --- /dev/null +++ b/python_pkg/anki_decks/run.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +VENV="$REPO_ROOT/.venv" +[[ ! -d "$VENV" ]] && python3 -m venv "$VENV" +_pip_sync() { local r="$1" h; h=$(md5sum "$r"|cut -d' ' -f1); local lf="$VENV/.req_${h:0:8}.lock"; [[ -f "$lf" ]] && return; "$VENV/bin/pip" install -r "$r" -q && touch "$lf"; } +_pip_sync "$REPO_ROOT/requirements.txt" + +# Run all deck generators in sequence +for deck_dir in "$SCRIPT_DIR"/*/; do + if [[ -f "$deck_dir/run.sh" ]]; then + echo "==> Building deck: $(basename "$deck_dir")" + bash "$deck_dir/run.sh" + fi +done diff --git a/python_pkg/anki_decks/warsaw_bridges/run.sh b/python_pkg/anki_decks/warsaw_bridges/run.sh index a848782..c5459c5 100755 --- a/python_pkg/anki_decks/warsaw_bridges/run.sh +++ b/python_pkg/anki_decks/warsaw_bridges/run.sh @@ -19,8 +19,7 @@ echo "Activating virtual environment..." source "$VENV_DIR/bin/activate" echo "Installing dependencies..." -pip install --quiet --upgrade pip -pip install --quiet matplotlib genanki geopandas requests shapely +pip show genanki &>/dev/null || pip install --quiet matplotlib genanki geopandas requests shapely cd "$SCRIPT_DIR" diff --git a/python_pkg/anki_decks/warsaw_districts/run.sh b/python_pkg/anki_decks/warsaw_districts/run.sh index 7af26d5..9812cfc 100755 --- a/python_pkg/anki_decks/warsaw_districts/run.sh +++ b/python_pkg/anki_decks/warsaw_districts/run.sh @@ -22,8 +22,7 @@ source "$VENV_DIR/bin/activate" # Install dependencies echo "Installing dependencies..." -pip install --quiet --upgrade pip -pip install --quiet matplotlib genanki geopandas +pip show genanki &>/dev/null || pip install --quiet matplotlib genanki geopandas # Export preview images echo diff --git a/python_pkg/anki_decks/warsaw_landmarks/run.sh b/python_pkg/anki_decks/warsaw_landmarks/run.sh index a602308..b9bb256 100755 --- a/python_pkg/anki_decks/warsaw_landmarks/run.sh +++ b/python_pkg/anki_decks/warsaw_landmarks/run.sh @@ -19,8 +19,7 @@ echo "Activating virtual environment..." source "$VENV_DIR/bin/activate" echo "Installing dependencies..." -pip install --quiet --upgrade pip -pip install --quiet matplotlib genanki geopandas requests shapely +pip show genanki &>/dev/null || pip install --quiet matplotlib genanki geopandas requests shapely cd "$SCRIPT_DIR" diff --git a/python_pkg/anki_decks/warsaw_metro/run.sh b/python_pkg/anki_decks/warsaw_metro/run.sh index 7e4415c..90960da 100755 --- a/python_pkg/anki_decks/warsaw_metro/run.sh +++ b/python_pkg/anki_decks/warsaw_metro/run.sh @@ -19,8 +19,7 @@ echo "Activating virtual environment..." source "$VENV_DIR/bin/activate" echo "Installing dependencies..." -pip install --quiet --upgrade pip -pip install --quiet matplotlib genanki geopandas requests shapely +pip show genanki &>/dev/null || pip install --quiet matplotlib genanki geopandas requests shapely cd "$SCRIPT_DIR" diff --git a/python_pkg/anki_decks/warsaw_osiedla/run.sh b/python_pkg/anki_decks/warsaw_osiedla/run.sh index 73c09bc..7bc6e69 100755 --- a/python_pkg/anki_decks/warsaw_osiedla/run.sh +++ b/python_pkg/anki_decks/warsaw_osiedla/run.sh @@ -19,8 +19,7 @@ echo "Activating virtual environment..." source "$VENV_DIR/bin/activate" echo "Installing dependencies..." -pip install --quiet --upgrade pip -pip install --quiet matplotlib genanki geopandas requests shapely +pip show genanki &>/dev/null || pip install --quiet matplotlib genanki geopandas requests shapely cd "$SCRIPT_DIR" diff --git a/python_pkg/anki_decks/warsaw_streets/run.sh b/python_pkg/anki_decks/warsaw_streets/run.sh index 6aa117a..5b4af30 100755 --- a/python_pkg/anki_decks/warsaw_streets/run.sh +++ b/python_pkg/anki_decks/warsaw_streets/run.sh @@ -19,8 +19,7 @@ echo "Activating virtual environment..." source "$VENV_DIR/bin/activate" echo "Installing dependencies..." -pip install --quiet --upgrade pip -pip install --quiet matplotlib genanki geopandas requests shapely +pip show genanki &>/dev/null || pip install --quiet matplotlib genanki geopandas requests shapely cd "$SCRIPT_DIR" diff --git a/python_pkg/brightness_controller/run.sh b/python_pkg/brightness_controller/run.sh new file mode 100755 index 0000000..a75161b --- /dev/null +++ b/python_pkg/brightness_controller/run.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +VENV="$REPO_ROOT/.venv" +[[ ! -d "$VENV" ]] && python3 -m venv "$VENV" +_pip_sync() { local r="$1" h; h=$(md5sum "$r"|cut -d' ' -f1); local lf="$VENV/.req_${h:0:8}.lock"; [[ -f "$lf" ]] && return; "$VENV/bin/pip" install -r "$r" -q && touch "$lf"; } +_pip_sync "$REPO_ROOT/requirements.txt" +"$VENV/bin/python" "$SCRIPT_DIR/brightness_controller.py" "$@" diff --git a/python_pkg/brother_printer/run.sh b/python_pkg/brother_printer/run.sh new file mode 100755 index 0000000..8a2a0fb --- /dev/null +++ b/python_pkg/brother_printer/run.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# No pip dependencies — script only uses stdlib +# Requires root for USB mode; pass printer IP as argument for network/SNMP mode +# Usage: ./run.sh # auto-detect +# ./run.sh # network/SNMP mode +echo "Note: sudo may prompt for your password (required for USB printer access)." +sudo python3 "$SCRIPT_DIR/check_brother_printer.py" "$@" diff --git a/python_pkg/download_cats/requirements.txt b/python_pkg/download_cats/requirements.txt index d90a3af..f229360 100644 --- a/python_pkg/download_cats/requirements.txt +++ b/python_pkg/download_cats/requirements.txt @@ -1,4 +1 @@ -json -os -pathlib requests diff --git a/python_pkg/download_cats/run.sh b/python_pkg/download_cats/run.sh new file mode 100755 index 0000000..fd42b6d --- /dev/null +++ b/python_pkg/download_cats/run.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +VENV="$REPO_ROOT/.venv" +[[ ! -d "$VENV" ]] && python3 -m venv "$VENV" +_pip_sync() { local r="$1" h; h=$(md5sum "$r"|cut -d' ' -f1); local lf="$VENV/.req_${h:0:8}.lock"; [[ -f "$lf" ]] && return; "$VENV/bin/pip" install -r "$r" -q && touch "$lf"; } +_pip_sync "$SCRIPT_DIR/requirements.txt" +"$VENV/bin/python" "$SCRIPT_DIR/generate_cats.py" "$@" diff --git a/python_pkg/keyboard_coop/run.sh b/python_pkg/keyboard_coop/run.sh new file mode 100755 index 0000000..2771441 --- /dev/null +++ b/python_pkg/keyboard_coop/run.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# pygame has no prebuilt wheel for Python 3.14+, use the system package +pacman -Q python-pygame &>/dev/null || sudo pacman -S --noconfirm python-pygame + +# Use a local venv with --system-site-packages so it can see system pygame +VENV="$SCRIPT_DIR/.venv" +[[ ! -d "$VENV" ]] && python3 -m venv "$VENV" --system-site-packages +"$VENV/bin/python" "$SCRIPT_DIR/main.py" "$@" diff --git a/python_pkg/lichess_bot/run.sh b/python_pkg/lichess_bot/run.sh index 1b51113..7fe7956 100755 --- a/python_pkg/lichess_bot/run.sh +++ b/python_pkg/lichess_bot/run.sh @@ -67,4 +67,4 @@ echo "Starting Lichess bot..." echo "Tip: Open another terminal to watch logs; press Ctrl+C here to stop." trap 'echo; echo "Stopping bot (Ctrl+C)."' INT -"$PY" -m PYTHON.lichess_bot.main "$@" +"$PY" -m python_pkg.lichess_bot.main "$@" diff --git a/python_pkg/mock_server/run.sh b/python_pkg/mock_server/run.sh index 8c4c6c2..17645ed 100755 --- a/python_pkg/mock_server/run.sh +++ b/python_pkg/mock_server/run.sh @@ -1,2 +1,17 @@ -#!/bin/sh -mitmdump -s mock_server.py +#!/usr/bin/env bash +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Use a local venv with pip-installed mitmproxy (not in Arch repos) +LVENV="$SCRIPT_DIR/.venv" +if [[ ! -d "$LVENV" ]]; then + echo "Creating local venv for mitmproxy..." + python3 -m venv "$LVENV" +fi +if ! "$LVENV/bin/python" -c "import mitmproxy" &>/dev/null; then + echo "Installing mitmproxy..." + "$LVENV/bin/pip" install mitmproxy -q +fi + +cd "$SCRIPT_DIR" +"$LVENV/bin/mitmdump" --scripts mock_server.py "$@" diff --git a/python_pkg/music_gen/run.sh b/python_pkg/music_gen/run.sh new file mode 100755 index 0000000..cb710a0 --- /dev/null +++ b/python_pkg/music_gen/run.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +VENV="$REPO_ROOT/.venv" +[[ ! -d "$VENV" ]] && python3 -m venv "$VENV" +"$VENV/bin/pip" show torch &>/dev/null || "$VENV/bin/pip" install torch transformers numpy scipy bark -q +echo "Loading models (this may take a minute on first run)..." +export PYTHONUNBUFFERED=1 +"$VENV/bin/python" "$SCRIPT_DIR/music_generator.py" "$@" diff --git a/python_pkg/praca_magisterska_video/run.sh b/python_pkg/praca_magisterska_video/run.sh new file mode 100755 index 0000000..8bf8a5e --- /dev/null +++ b/python_pkg/praca_magisterska_video/run.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +VENV="$REPO_ROOT/.venv" +[[ ! -d "$VENV" ]] && python3 -m venv "$VENV" +"$VENV/bin/pip" show moviepy &>/dev/null || "$VENV/bin/pip" install moviepy numpy -q +export PYTHONUNBUFFERED=1 +# Run all visualizations +echo "==> Rendering visualize_q02 (Dijkstra/Bellman-Ford/A*)" +"$VENV/bin/python" "$SCRIPT_DIR/visualize_q02.py" "$@" +echo "==> Rendering visualize_q23" +"$VENV/bin/python" "$SCRIPT_DIR/visualize_q23.py" "$@" +echo "==> Rendering visualize_q24" +"$VENV/bin/python" "$SCRIPT_DIR/visualize_q24.py" "$@" +echo "Done." diff --git a/python_pkg/random_jpg/run.sh b/python_pkg/random_jpg/run.sh new file mode 100755 index 0000000..ccbe6bf --- /dev/null +++ b/python_pkg/random_jpg/run.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +VENV="$REPO_ROOT/.venv" +[[ ! -d "$VENV" ]] && python3 -m venv "$VENV" +"$VENV/bin/pip" show pillow &>/dev/null || "$VENV/bin/pip" install pillow -q +"$VENV/bin/python" "$SCRIPT_DIR/generate_jpeg.py" "$@" diff --git a/python_pkg/randomize_numbers/run.sh b/python_pkg/randomize_numbers/run.sh new file mode 100755 index 0000000..33df461 --- /dev/null +++ b/python_pkg/randomize_numbers/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +"$SCRIPT_DIR/../../.venv/bin/python" "$SCRIPT_DIR/random_digits.py" "$@" diff --git a/python_pkg/repo_explorer/repo_explorer.py b/python_pkg/repo_explorer/repo_explorer.py new file mode 100755 index 0000000..c98e0d2 --- /dev/null +++ b/python_pkg/repo_explorer/repo_explorer.py @@ -0,0 +1,594 @@ +#!/usr/bin/env python3 +"""Repo Explorer - browse and run any project in the monorepo via a GUI.""" + +from __future__ import annotations + +import contextlib +import fcntl +import os +from pathlib import Path +import pty +import re +import select +import shutil +import subprocess +import threading +import tkinter as tk +from tkinter import font, ttk +from typing import cast + +# Strip ANSI/VT100 escape sequences so the Text widget shows plain text +_ANSI_ESCAPE = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])") + + +def _strip_ansi(text: str) -> str: + return _ANSI_ESCAPE.sub("", text) + + +def _find_terminal() -> list[str]: + """Return argv prefix for the first available terminal emulator.""" + candidates = [ + ("kitty", ["kitty", "--"]), + ("alacritty", ["alacritty", "-e"]), + ("konsole", ["konsole", "-e"]), + ("gnome-terminal", ["gnome-terminal", "--"]), + ("xfce4-terminal", ["xfce4-terminal", "-x"]), + ("xterm", ["xterm", "-e"]), + ] + for exe, args in candidates: + if shutil.which(exe): + return args + return [] + + +REPO_ROOT = Path(__file__).resolve().parent.parent.parent + +IGNORED_DIRS = { + ".git", + ".venv", + "__pycache__", + "node_modules", + "build", + "target", + ".mypy_cache", + ".ruff_cache", +} + + +# --------------------------------------------------------------------------- +# Discovery helpers +# --------------------------------------------------------------------------- + + +def _is_ignored(path: Path) -> bool: + return any(part in IGNORED_DIRS for part in path.parts) + + +def find_projects(root: Path) -> list[dict[str, object]]: + """Return every directory under *root* that contains a run.sh.""" + projects: list[dict[str, object]] = [] + for run_sh in sorted(root.rglob("run.sh")): + if _is_ignored(run_sh): + continue + proj_dir = run_sh.parent + rel = proj_dir.relative_to(root) + projects.append({"path": proj_dir, "rel": rel, "name": proj_dir.name}) + return projects + + +def _desc_from_run_sh(run_sh: Path) -> str: + """Extract leading comment block from run.sh as a description.""" + comments: list[str] = [] + for line in run_sh.read_text(errors="replace").splitlines(): + s = line.strip() + if s.startswith("#!"): + continue + if s.startswith("#"): + comments.append(s[1:].strip()) + elif comments: + break + return " ".join(comments)[:300] if comments else "" + + +def get_description(project_path: Path) -> str: + """Return a short description from README.md or leading run.sh comments.""" + for readme_name in ("README.md", "README.txt", "readme.md"): + readme = project_path / readme_name + if readme.exists(): + text = readme.read_text(errors="replace") + for line in text.splitlines(): + stripped = line.strip().lstrip("#").strip() + if stripped: + return stripped[:300] + + run_sh = project_path / "run.sh" + if run_sh.exists(): + desc = _desc_from_run_sh(run_sh) + if desc: + return desc + + return "(no description)" + + +# --------------------------------------------------------------------------- +# Main application +# --------------------------------------------------------------------------- + + +class RepoExplorer(tk.Tk): + """Main application window for browsing and running monorepo projects.""" + + # Catppuccin Mocha palette + _BG = "#1e1e2e" + _SURFACE = "#313244" + _TEXT = "#cdd6f4" + _TEXT_DIM = "#6c7086" + _ACCENT = "#89b4fa" + _GREEN = "#a6e3a1" + _RED = "#f38ba8" + _TERMINAL_BG = "#11111b" + _MAX_EXPAND = 60 # expand tree groups automatically when <= this many results + _IDLE_FLUSH_TICKS = 2 # flush partial PTY buffer after this many 50 ms timeouts + + def __init__(self) -> None: + """Initialise the window, build the UI and load all projects.""" + super().__init__() + self.title("Repo Explorer") + self.geometry("1200x750") + self.configure(bg=self._BG) + self._proc: subprocess.Popen[bytes] | None = None + self._master_fd: int | None = None + self._projects: list[dict[str, object]] = [] + self._terminal_args = _find_terminal() + self._build_style() + self._build_ui() + self._load_projects() + + # ------------------------------------------------------------------ + # UI construction + # ------------------------------------------------------------------ + + def _build_style(self) -> None: + s = ttk.Style(self) + s.theme_use("clam") + opts: dict[str, object] + opts = { + "background": self._BG, + "foreground": self._TEXT, + "fieldbackground": self._BG, + "font": ("Monospace", 10), + "rowheight": 24, + } + s.configure("Treeview", **opts) + s.configure( + "Treeview.Heading", background=self._SURFACE, foreground=self._ACCENT + ) + s.map( + "Treeview", + background=[("selected", self._SURFACE)], + foreground=[("selected", self._ACCENT)], + ) + s.configure("TFrame", background=self._BG) + s.configure("TLabel", background=self._BG, foreground=self._TEXT) + s.configure( + "TButton", background=self._SURFACE, foreground=self._TEXT, padding=4 + ) + s.map( + "TButton", + background=[("active", "#45475a"), ("disabled", self._BG)], + foreground=[("disabled", self._TEXT_DIM)], + ) + s.configure( + "TEntry", + fieldbackground=self._SURFACE, + foreground=self._TEXT, + insertcolor=self._TEXT, + ) + s.configure("TPanedwindow", background=self._BG) + s.configure("TSeparator", background=self._SURFACE) + + def _build_ui(self) -> None: + paned = ttk.PanedWindow(self, orient=tk.HORIZONTAL) + paned.pack(fill=tk.BOTH, expand=True, padx=6, pady=6) + + paned.add(self._build_left(paned), weight=1) + paned.add(self._build_right(paned), weight=3) + + def _build_left(self, parent: ttk.PanedWindow) -> ttk.Frame: + frame = ttk.Frame(parent) + + # Search bar + sf = ttk.Frame(frame) + sf.pack(fill=tk.X, padx=4, pady=(4, 2)) + ttk.Label(sf, text="Search:").pack(side=tk.LEFT) + self._search_var = tk.StringVar() + self._search_var.trace_add("write", lambda *_: self._filter_tree()) + ttk.Entry(sf, textvariable=self._search_var).pack( + side=tk.LEFT, fill=tk.X, expand=True, padx=(4, 0) + ) + + # Project count label + self._count_var = tk.StringVar(value="") + ttk.Label( + frame, + textvariable=self._count_var, + foreground=self._TEXT_DIM, + font=("sans-serif", 8), + ).pack(anchor=tk.W, padx=6) + + # Tree + scrollbar + tree_frame = ttk.Frame(frame) + tree_frame.pack(fill=tk.BOTH, expand=True, padx=4, pady=4) + self._tree = ttk.Treeview(tree_frame, show="tree", selectmode="browse") + scroll = ttk.Scrollbar(tree_frame, command=self._tree.yview) + self._tree.configure(yscrollcommand=scroll.set) + scroll.pack(side=tk.RIGHT, fill=tk.Y) + self._tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) + + self._tree.bind("<>", self._on_select) + self._tree.bind("", lambda _: self._run_embedded()) + self._tree.bind("", lambda _: self._run_embedded()) + + return frame + + def _build_right(self, parent: ttk.PanedWindow) -> ttk.Frame: + frame = ttk.Frame(parent) + + # Description section + info_frame = ttk.Frame(frame) + info_frame.pack(fill=tk.X, padx=6, pady=(4, 0)) + + ttk.Label( + info_frame, + text="Project", + font=("sans-serif", 11, "bold"), + foreground=self._ACCENT, + ).pack(anchor=tk.W) + self._title_var = tk.StringVar(value="Select a project from the list") + ttk.Label( + info_frame, + textvariable=self._title_var, + font=("Monospace", 9), + foreground=self._TEXT_DIM, + ).pack(anchor=tk.W) + + self._desc_var = tk.StringVar(value="") + ttk.Label( + info_frame, + textvariable=self._desc_var, + wraplength=700, + justify=tk.LEFT, + foreground=self._GREEN, + ).pack(anchor=tk.W, pady=(2, 0)) + + ttk.Separator(frame, orient=tk.HORIZONTAL).pack(fill=tk.X, padx=6, pady=4) + + # Args + buttons row + ctrl_frame = ttk.Frame(frame) + ctrl_frame.pack(fill=tk.X, padx=6, pady=(0, 4)) + + ttk.Label(ctrl_frame, text="Args:").pack(side=tk.LEFT) + self._args_var = tk.StringVar() + ttk.Entry(ctrl_frame, textvariable=self._args_var, width=30).pack( + side=tk.LEFT, padx=(4, 12) + ) + + self._run_btn = ttk.Button( + ctrl_frame, + text="▶ Run here", + command=self._run_embedded, + state=tk.DISABLED, + ) + self._run_btn.pack(side=tk.LEFT, padx=(0, 4)) + + term_label = self._terminal_args[0] if self._terminal_args else "terminal" + self._term_btn = ttk.Button( + ctrl_frame, + text=f"⧉ Open in {term_label}", + command=self._run_in_terminal, + state=tk.DISABLED, + ) + self._term_btn.pack(side=tk.LEFT, padx=(0, 4)) + + self._stop_btn = ttk.Button( + ctrl_frame, text="■ Stop", command=self._stop, state=tk.DISABLED + ) + self._stop_btn.pack(side=tk.LEFT, padx=(0, 4)) + + ttk.Button(ctrl_frame, text="✕ Clear", command=self._clear).pack(side=tk.LEFT) + + # Status indicator + self._status_var = tk.StringVar(value="") + ttk.Label( + ctrl_frame, textvariable=self._status_var, font=("sans-serif", 9) + ).pack(side=tk.RIGHT) + + # stdin input row (for interactive embedded processes) + stdin_frame = ttk.Frame(frame) + stdin_frame.pack(fill=tk.X, padx=6, pady=(0, 4)) + ttk.Label(stdin_frame, text="Send input:").pack(side=tk.LEFT) + self._stdin_var = tk.StringVar() + stdin_entry = ttk.Entry(stdin_frame, textvariable=self._stdin_var) + stdin_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(4, 4)) + stdin_entry.bind("", self._send_stdin) + ttk.Button(stdin_frame, text="↵ Send", command=self._send_stdin).pack( + side=tk.LEFT + ) + + # Output terminal + term_frame = ttk.Frame(frame) + term_frame.pack(fill=tk.BOTH, expand=True, padx=6, pady=(0, 6)) + + mono = font.Font(family="Monospace", size=9) + self._output = tk.Text( + term_frame, + bg=self._TERMINAL_BG, + fg=self._TEXT, + font=mono, + wrap=tk.WORD, + state=tk.DISABLED, + relief=tk.FLAT, + insertbackground=self._TEXT, + ) + out_scroll = ttk.Scrollbar(term_frame, command=self._output.yview) + self._output.configure(yscrollcommand=out_scroll.set) + out_scroll.pack(side=tk.RIGHT, fill=tk.Y) + self._output.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) + + self._output.tag_config("stderr", foreground=self._RED) + self._output.tag_config("info", foreground=self._ACCENT) + self._output.tag_config("success", foreground=self._GREEN) + self._output.tag_config("error", foreground=self._RED) + + return frame + + # ------------------------------------------------------------------ + # Project discovery / tree population + # ------------------------------------------------------------------ + + def _load_projects(self) -> None: + self._projects = find_projects(REPO_ROOT) + self._populate_tree(self._projects) + + def _populate_tree(self, projects: list[dict[str, object]]) -> None: + self._tree.delete(*self._tree.get_children()) + + groups: dict[str, list[dict[str, object]]] = {} + for p in projects: + rel = cast("Path", p["rel"]) + parts = rel.parts + group = parts[0] if len(parts) > 1 else "(root)" + groups.setdefault(group, []).append(p) + + icons = { + "python_pkg": "🐍", + "C": "⚙️", + "CPP": "⚙️", + "articles": "📰", + "TS": "📜", + "Bash": "🐚", + } + for group, items in sorted(groups.items()): + icon = icons.get(group, "📁") + gid = self._tree.insert("", tk.END, text=f"{icon} {group}", tags=("group",)) + for item in items: + rel2 = cast("Path", item["rel"]) + label = cast( + "str", + "/".join(rel2.parts[1:]) if len(rel2.parts) > 1 else item["name"], + ) + path_str = str(item["path"]) + self._tree.insert(gid, tk.END, text=f" {label}", values=[path_str]) + + self._tree.tag_configure("group", foreground=self._TEXT_DIM) + # Expand all groups if result set is small enough + if len(projects) <= self._MAX_EXPAND: + for gid in self._tree.get_children(): + self._tree.item(gid, open=True) + + n = len(projects) + self._count_var.set(f"{n} project{'s' if n != 1 else ''}") + + def _filter_tree(self) -> None: + q = self._search_var.get().lower() + if not q: + self._populate_tree(self._projects) + return + filtered = [ + p + for p in self._projects + if q in str(p["rel"]).lower() or q in str(p["name"]).lower() + ] + self._populate_tree(filtered) + + # ------------------------------------------------------------------ + # Selection / info panel + # ------------------------------------------------------------------ + + def _selected_path(self) -> Path | None: + sel = self._tree.selection() + if not sel: + return None + vals = self._tree.item(sel[0], "values") + if not vals: + return None + return Path(vals[0]) + + def _on_select(self, _event: object) -> None: + path = self._selected_path() + if path is None: + self._run_btn.configure(state=tk.DISABLED) + self._term_btn.configure(state=tk.DISABLED) + return + self._title_var.set(str(path.relative_to(REPO_ROOT))) + self._desc_var.set(get_description(path)) + self._run_btn.configure(state=tk.NORMAL) + self._term_btn.configure( + state=tk.NORMAL if self._terminal_args else tk.DISABLED + ) + + # ------------------------------------------------------------------ + # Run in external terminal (for interactive / keyboard-driven programs) + # ------------------------------------------------------------------ + + def _run_in_terminal(self) -> None: + path = self._selected_path() + if path is None or not self._terminal_args: + return + args_str = self._args_var.get().strip() + extra = args_str.split() if args_str else [] + subprocess.Popen([*self._terminal_args, "bash", "run.sh", *extra], cwd=path) + self._write_output( + f"$ Launched in {self._terminal_args[0]}: {path.relative_to(REPO_ROOT)}\n", + "info", + ) + + # ------------------------------------------------------------------ + # Run embedded with PTY (captures terminal-aware / ncurses output) + # ------------------------------------------------------------------ + + def _run_embedded(self) -> None: + path = self._selected_path() + if path is None: + return + if self._proc and self._proc.poll() is None: + self._stop() + + self._clear() + args_str = self._args_var.get().strip() + extra = args_str.split() if args_str else [] + display_cmd = ("bash run.sh " + args_str).strip() + self._write_output( + f"$ {display_cmd} [{path.relative_to(REPO_ROOT)}]\n", "info" + ) + + master_fd, slave_fd = pty.openpty() + self._master_fd = master_fd + # Non-blocking reads on master so the reader thread doesn't stall + fl = fcntl.fcntl(master_fd, fcntl.F_GETFL) + fcntl.fcntl(master_fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) + + self._proc = subprocess.Popen( + ["bash", "run.sh", *extra], # noqa: S607 + cwd=path, + stdin=slave_fd, + stdout=slave_fd, + stderr=slave_fd, + close_fds=True, + ) + os.close(slave_fd) + + self._run_btn.configure(state=tk.DISABLED) + self._stop_btn.configure(state=tk.NORMAL) + self._status_var.set("● running") + + threading.Thread(target=self._read_pty, daemon=True).start() + threading.Thread(target=self._wait_proc, daemon=True).start() + + def _read_pty(self) -> None: # noqa: C901, PLR0912 + """Stream PTY output to the widget, stripping ANSI codes. + + Partial lines (prompts without a trailing newline) are flushed after + ~100 ms of silence so interactive prompts like "Enter value: " appear. + """ + buf = b"" + idle_ticks = 0 # consecutive 50 ms timeouts while buf has content + while self._proc and self._proc.poll() is None: + mfd = self._master_fd + if mfd is None: + break + ready, _, _ = select.select([mfd], [], [], 0.05) + if not ready: + # No new data — flush partial buffer after ~100 ms (2 ticks) + if buf: + idle_ticks += 1 + if idle_ticks >= self._IDLE_FLUSH_TICKS: + text = _strip_ansi( + buf.decode("utf-8", errors="replace").replace("\r", "") + ) + if text: + self._write_output(text) + buf = b"" + idle_ticks = 0 + continue + idle_ticks = 0 + try: + chunk = os.read(mfd, 4096) + except OSError: + break + if not chunk: + break + buf += chunk + while b"\n" in buf: + line, buf = buf.split(b"\n", 1) + text = _strip_ansi( + line.decode("utf-8", errors="replace").replace("\r", "") + ) + if text: + self._write_output(text + "\n") + # flush remainder + if buf: + text = _strip_ansi(buf.decode("utf-8", errors="replace").replace("\r", "")) + if text: + self._write_output(text) + if self._master_fd is not None: + with contextlib.suppress(OSError): + os.close(self._master_fd) + self._master_fd = None + + # ------------------------------------------------------------------ + # stdin forwarding (typed into the "Send input" field) + # ------------------------------------------------------------------ + + def _send_stdin(self, _event: object = None) -> None: + text = self._stdin_var.get() + self._stdin_var.set("") + payload = (text + "\n").encode() + if self._master_fd is not None: + with contextlib.suppress(OSError): + os.write(self._master_fd, payload) + + def _wait_proc(self) -> None: + if self._proc: + code = self._proc.wait() + self.after(0, self._on_proc_done, code) + + def _on_proc_done(self, code: int) -> None: + if code == 0: + self._write_output(f"\n[exited with code {code}]\n", "success") + self._status_var.set("✓ done") + else: + self._write_output(f"\n[exited with code {code}]\n", "error") + self._status_var.set(f"✗ exit {code}") + self._run_btn.configure(state=tk.NORMAL) + self._stop_btn.configure(state=tk.DISABLED) + + def _stop(self) -> None: + if self._proc and self._proc.poll() is None: + self._proc.terminate() + self._status_var.set("stopped") + + def _clear(self) -> None: + self._output.configure(state=tk.NORMAL) + self._output.delete("1.0", tk.END) + self._output.configure(state=tk.DISABLED) + self._status_var.set("") + + def _write_output(self, text: str, tag: str | None = None) -> None: + """Thread-safe output append via after().""" + self.after(0, self._append_output, text, tag) + + def _append_output(self, text: str, tag: str | None) -> None: + self._output.configure(state=tk.NORMAL) + if tag: + self._output.insert(tk.END, text, tag) + else: + self._output.insert(tk.END, text) + self._output.see(tk.END) + self._output.configure(state=tk.DISABLED) + + +# --------------------------------------------------------------------------- + +if __name__ == "__main__": + RepoExplorer().mainloop() diff --git a/python_pkg/repo_explorer/run.sh b/python_pkg/repo_explorer/run.sh new file mode 100755 index 0000000..2b47ae2 --- /dev/null +++ b/python_pkg/repo_explorer/run.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# Repo Explorer - browse and run any project in the monorepo via a GUI. +# Requires tkinter (Arch: sudo pacman -S python-tkinter) +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +VENV="$REPO_ROOT/.venv" + +# Ensure tkinter is available (it's stdlib but needs the python-tkinter OS package) +if ! python3 -c "import tkinter" 2>/dev/null; then + echo "tkinter not found. Installing python-tkinter..." + sudo pacman -S --noconfirm python-tkinter 2>/dev/null \ + || sudo apt-get install -y python3-tk 2>/dev/null \ + || { echo "Please install python-tkinter manually."; exit 1; } +fi + +[[ ! -d "$VENV" ]] && python3 -m venv "$VENV" +"$VENV/bin/python" "$SCRIPT_DIR/repo_explorer.py" "$@" diff --git a/python_pkg/scrape_website/run.sh b/python_pkg/scrape_website/run.sh new file mode 100755 index 0000000..965ba47 --- /dev/null +++ b/python_pkg/scrape_website/run.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +VENV="$REPO_ROOT/.venv" +[[ ! -d "$VENV" ]] && python3 -m venv "$VENV" +_pip_sync() { local r="$1" h; h=$(md5sum "$r"|cut -d' ' -f1); local lf="$VENV/.req_${h:0:8}.lock"; [[ -f "$lf" ]] && return; "$VENV/bin/pip" install -r "$r" -q && touch "$lf"; } +_pip_sync "$SCRIPT_DIR/requirements.txt" +# Usage: ./run.sh [--output-dir DIR] [--max-pages N] +"$VENV/bin/python" "$SCRIPT_DIR/scrape_comics.py" "$@" diff --git a/python_pkg/screen_locker/run.sh b/python_pkg/screen_locker/run.sh new file mode 100755 index 0000000..f40d569 --- /dev/null +++ b/python_pkg/screen_locker/run.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +VENV="$REPO_ROOT/.venv" +[[ ! -d "$VENV" ]] && python3 -m venv "$VENV" +# tkinter is from Python stdlib; install python-tk system package if missing: +# Arch: sudo pacman -S python-tk +# Debian: sudo apt-get install python3-tk +"$VENV/bin/python" "$SCRIPT_DIR/screen_lock.py" "$@" diff --git a/python_pkg/split/run.sh b/python_pkg/split/run.sh new file mode 100755 index 0000000..f2639b1 --- /dev/null +++ b/python_pkg/split/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +"$SCRIPT_DIR/../../.venv/bin/python" "$SCRIPT_DIR/split_x_into_n_symmetrically.py" "$@" diff --git a/python_pkg/stockfish_analysis/analyze_chess_game.py b/python_pkg/stockfish_analysis/analyze_chess_game.py index afabb11..1f56c70 100755 --- a/python_pkg/stockfish_analysis/analyze_chess_game.py +++ b/python_pkg/stockfish_analysis/analyze_chess_game.py @@ -367,19 +367,19 @@ def _configure_hash( def _configure_multipv( - engine: chess.engine.SimpleEngine, options: EngineOptions, requested: int + _engine: chess.engine.SimpleEngine, options: EngineOptions, requested: int ) -> int: """Configure MultiPV and return effective value.""" effective = max(1, int(requested)) - if "MultiPV" not in options: - return effective - try: - max_mpv = getattr(options["MultiPV"], "max", None) - if isinstance(max_mpv, int): - effective = min(effective, max_mpv) - engine.configure({"MultiPV": int(effective)}) - except (AttributeError, TypeError, ValueError): - _logger.debug("Failed to configure MultiPV option") + # MultiPV is automatically managed by python-chess and passed directly to + # engine.analyse(..., multipv=N) — do not configure() it here. + if "MultiPV" in options: + try: + max_mpv = getattr(options["MultiPV"], "max", None) + if isinstance(max_mpv, int): + effective = min(effective, max_mpv) + except (AttributeError, TypeError, ValueError): + _logger.debug("Failed to read MultiPV max option") return effective diff --git a/python_pkg/stockfish_analysis/run.sh b/python_pkg/stockfish_analysis/run.sh index 2807671..1779a4a 100755 --- a/python_pkg/stockfish_analysis/run.sh +++ b/python_pkg/stockfish_analysis/run.sh @@ -24,8 +24,12 @@ fi # shellcheck disable=SC1090 source "$VENV_DIR/bin/activate" -# Install dependencies quietly -pip install -r "$SCRIPT_DIR/requirements.txt" >/dev/null +# Install dependencies only if requirements.txt has changed +_REQ="$SCRIPT_DIR/requirements.txt" +_HASH=$(md5sum "$_REQ" | cut -d' ' -f1) +_LOCK="$VENV_DIR/.req_${_HASH:0:8}.lock" +[[ -f "$_LOCK" ]] || { pip install -r "$_REQ" >/dev/null && touch "$_LOCK"; } +unset _REQ _HASH _LOCK # Default engine (can override with STOCKFISH env var) ENGINE_BIN="${STOCKFISH:-stockfish}" diff --git a/python_pkg/tag_divider/run.sh b/python_pkg/tag_divider/run.sh new file mode 100755 index 0000000..19c6de3 --- /dev/null +++ b/python_pkg/tag_divider/run.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +VENV="$REPO_ROOT/.venv" +[[ ! -d "$VENV" ]] && python3 -m venv "$VENV" +"$VENV/bin/pip" show opencv-python &>/dev/null || "$VENV/bin/pip" install opencv-python -q +# Usage: ./run.sh +"$VENV/bin/python" "$SCRIPT_DIR/tag_divider.py" "$@" diff --git a/python_pkg/word_frequency/run.sh b/python_pkg/word_frequency/run.sh new file mode 100755 index 0000000..063c63d --- /dev/null +++ b/python_pkg/word_frequency/run.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# Usage: ./run.sh [options] +"$SCRIPT_DIR/../../.venv/bin/python" "$SCRIPT_DIR/vocabulary_curve.py" "$@" diff --git a/scripts/check_c_cpp_build_files.sh b/scripts/check_c_cpp_build_files.sh new file mode 100755 index 0000000..d8a2bac --- /dev/null +++ b/scripts/check_c_cpp_build_files.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# Check that every directory containing C/C++ source files has a Makefile and run.sh. +# Used as a pre-commit hook; receives staged file paths as arguments. + +set -uo pipefail + +errors=() +declare -A checked_dirs + +for file in "$@"; do + dir=$(dirname "$file") + + # Skip build directories and CMake artefact trees + if echo "$dir" | grep -qE '(^|/)build(/|$)'; then + continue + fi + + # Skip if already checked this directory + [[ -v checked_dirs["$dir"] ]] && continue + checked_dirs["$dir"]=1 + + # Check for Makefile (case-insensitive: Makefile or makefile) + if ! compgen -G "$dir/[Mm]akefile" > /dev/null 2>&1; then + errors+=("MISSING Makefile in: $dir") + fi + + # Check for run.sh + if [[ ! -f "$dir/run.sh" ]]; then + errors+=("MISSING run.sh in: $dir") + fi +done + +if [[ ${#errors[@]} -gt 0 ]]; then + printf 'C/C++ build file check failed:\n' + printf ' %s\n' "${errors[@]}" + printf '\nEvery directory with .c/.cpp files must have a Makefile and run.sh.\n' + exit 1 +fi + +exit 0