diff options
| author | Blista Kanjo | 2024-06-19 06:22:38 -0400 |
|---|---|---|
| committer | Blista Kanjo | 2024-06-19 06:22:38 -0400 |
| commit | b8f5a332bd786baca6370f176ef2938f1de6ee43 (patch) | |
| tree | ca057a97f10768a70076a3b72d78dfe9b8d8e4ef /.local | |
| parent | ca897388046facfeff33220a8c9a9a78f1b2ac1f (diff) | |
feat: add `rainfall` program
Diffstat (limited to '.local')
| -rwxr-xr-x | .local/bin/rainfall | 12 | ||||
| -rw-r--r-- | .local/share/python-rainfall/Makefile | 3 | ||||
| -rw-r--r-- | .local/share/python-rainfall/rainfall.py | 162 |
3 files changed, 177 insertions, 0 deletions
diff --git a/.local/bin/rainfall b/.local/bin/rainfall new file mode 100755 index 0000000..65b8031 --- /dev/null +++ b/.local/bin/rainfall @@ -0,0 +1,12 @@ +#!/bin/sh + +BIN_PATH=~/.local/share/python-rainfall/rainfall +SCRIPT_PATH=~/.local/share/python-rainfall/rainfall.py + +if [ -f "$BIN_PATH" ]; then + $BIN_PATH +elif [ -f "$SCRIPT_PATH" ]; then + python3 $SCRIPT_PATH +else + echo "rainfall/rainfall.py not found" +fi diff --git a/.local/share/python-rainfall/Makefile b/.local/share/python-rainfall/Makefile new file mode 100644 index 0000000..567100b --- /dev/null +++ b/.local/share/python-rainfall/Makefile @@ -0,0 +1,3 @@ +compile: + cython3 --embed -o rainfall.c -X language_level=3 rainfall.py + gcc -march=native -O2 -pipe -fno-plt -I /usr/include/python3.12 -o rainfall rainfall.c -lpython3.12 -lpthread -lm -lutil -ldl diff --git a/.local/share/python-rainfall/rainfall.py b/.local/share/python-rainfall/rainfall.py new file mode 100644 index 0000000..a2d8194 --- /dev/null +++ b/.local/share/python-rainfall/rainfall.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python3.10 +# -*- coding: utf-8 -*- + +import time +import random +import os +import sys + + +colors = { + "black": "\u001b[30m", + "red": "\u001b[31m", + "green": "\u001b[32m", + "yellow": "\u001b[33m", + "blue": "\u001b[34m", + "magenta": "\u001b[35m", + "cyan": "\u001b[36m", + "white": "\u001b[37m", + "reset": "\u001b[0m", + + "b_black": "\u001b[30;1m", + "b_red": "\u001b[31;1m", + "b_green": "\u001b[32;1m", + "b_yellow": "\u001b[33;1m", + "b_blue": "\u001b[34;1m", + "b_magenta": "\u001b[35;1m", + "b_cyan": "\u001b[36;1m", + "b_white": "\u001b[37;1m", + + "Reset": "\u001b[0m", +} + +def Colored(string, color): + return string if "-m" in sys.argv else ( colors[color] + string + colors["Reset"]) + + +def Clear_Screen(): + print("\033[2J") # erase saved lines + print("\033[3J") # erase entire screen + print("\033[H") # moves cursor to home position + + +def Get_Arguments(): + args_dict = {"colors": []} + if sys.argv: + for arg in sys.argv: + if "-i=" in arg: + args_dict["intensity"] = int(arg.split("-i=")[1]) + if "-t=" in arg: + args_dict["timing"] = float(arg.split("-t=")[1]) + if arg in colors: + args_dict["colors"].append(arg) + if not args_dict["colors"]: + del args_dict["colors"] + return args_dict + + +def New_Drop(): + for i in range(intensity): + shape = random.choice(DROPSHAPES) + color = random.choice(drop_colors) + + raindrop = { + "shape": Colored(shape, color), + "x": random.randint(0, xmax), + "y": 0, + } + rainfall.append(raindrop) + +def Rain(): + ## iterate over every line + for i in range(ymax): + line = " "*xmax + + ### to avoid splicing of ansi codes, splice in the drops from the end of the line + this_line_raindrops = [raindrop for raindrop in rainfall if raindrop["y"] == i] + this_line_raindrops.sort(key=lambda y: y["x"]) + this_line_raindrops.reverse() + + ## insert new drops and shift existing drops + for raindrop in this_line_raindrops: + x = raindrop["x"] + line = line[:x] + raindrop["shape"] +line[x:] + + print(line) + + ### update raindrop positions + for raindrop in rainfall: + raindrop["y"] += 1 + + ## once a raindrop reaches the ground, they splash + if raindrop["y"] > ymax-2: + raindrop["shape"] = Colored("o", random.choice(drop_colors)) + + # raindrops outside the window evaporate + if raindrop["y"] > ymax: + rainfall.remove(raindrop) + + New_Drop() + + + +def Weather_Forecast(): + global weather + global intensity + + weather += 1 + if weather == 100: + weather = 0 + intensity += random.choice([-1,1]) + if intensity < 1: + intensity = 1 + if intensity > 10: + intensity = 10 + + +size = os.get_terminal_size() +xmax = size.columns +ymax = int(size.lines) + +weather = 0 +rainfall = [] +DROPSHAPES =["|", "│", "┃", "╽", "╿", "║", "┆", "┇", "┊", "┋", "╵", "╹", "╻"] + +args = Get_Arguments() +intensity = args.get("intensity", 1) +timing = args.get("timing", 0.08) +drop_colors = args.get("colors", ["blue", "b_blue"]) + + + +print('\033[?25l', end="") ## hides the cursor +New_Drop() + +try: + while True: + Rain() + time.sleep(timing) + Clear_Screen() + Weather_Forecast() + +except KeyboardInterrupt: + Clear_Screen() + print('\033[?25h', end="") # makes cursor visible again + + + + + + + + + + + + + + + + + + |
