Skip to content

Commit 39eb075

Browse files
Refactor contact page content, update theme colors, enhance translations with boot phases, add language metadata, and introduce new scripts for ASCII art, calculator, chess, dice rolling, hello world demo, media demo, minimal Pacman, Pong, quote bot, Snake game, Solitaire, animated starfield, and more.
1 parent 698bf9e commit 39eb075

31 files changed

+7254
-781
lines changed

public/file.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

public/globe.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

public/models/computer.glb

-18 MB
Binary file not shown.

public/next.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

public/og.svg

Lines changed: 0 additions & 29 deletions
This file was deleted.

public/vercel.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

public/window.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

scripts/ascii_image.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
"""ASCII art text renderer.
2+
3+
Usage:
4+
python ascii_image.py --text "Retro Bot" --scale 2
5+
"""
6+
7+
from __future__ import annotations
8+
9+
import argparse
10+
11+
12+
FONT = {
13+
"A": [" # ", " # # ", "#####", "# #", "# #"],
14+
"B": ["#### ", "# #", "#### ", "# #", "#### "],
15+
"C": [" ####", "# ", "# ", "# ", " ####"],
16+
"D": ["#### ", "# #", "# #", "# #", "#### "],
17+
"E": ["#####", "# ", "#### ", "# ", "#####"],
18+
"F": ["#####", "# ", "#### ", "# ", "# "],
19+
"G": [" ####", "# ", "# ##", "# #", " ####"],
20+
"H": ["# #", "# #", "#####", "# #", "# #"],
21+
"I": ["#####", " # ", " # ", " # ", "#####"],
22+
"J": [" ###", " # ", " # ", "# # ", " ## "],
23+
"K": ["# #", "# # ", "### ", "# # ", "# #"],
24+
"L": ["# ", "# ", "# ", "# ", "#####"],
25+
"M": ["# #", "## ##", "# # #", "# #", "# #"],
26+
"N": ["# #", "## #", "# # #", "# ##", "# #"],
27+
"O": [" ### ", "# #", "# #", "# #", " ### "],
28+
"P": ["#### ", "# #", "#### ", "# ", "# "],
29+
"Q": [" ### ", "# #", "# # #", "# ##", " ####"],
30+
"R": ["#### ", "# #", "#### ", "# # ", "# #"],
31+
"S": [" ####", "# ", " ### ", " #", "#### "],
32+
"T": ["#####", " # ", " # ", " # ", " # "],
33+
"U": ["# #", "# #", "# #", "# #", " ### "],
34+
"V": ["# #", "# #", "# #", " # # ", " # "],
35+
"W": ["# #", "# #", "# # #", "## ##", "# #"],
36+
"X": ["# #", " # # ", " # ", " # # ", "# #"],
37+
"Y": ["# #", " # # ", " # ", " # ", " # "],
38+
"Z": ["#####", " # ", " # ", " # ", "#####"],
39+
"0": [" ### ", "# ##", "# # #", "## #", " ### "],
40+
"1": [" # ", " ## ", " # ", " # ", " ### "],
41+
"2": [" ### ", "# #", " # ", " # ", "#####"],
42+
"3": ["#### ", " #", " ### ", " #", "#### "],
43+
"4": ["# #", "# #", "#####", " #", " #"],
44+
"5": ["#####", "# ", "#### ", " #", "#### "],
45+
"6": [" ### ", "# ", "#### ", "# #", " ### "],
46+
"7": ["#####", " #", " # ", " # ", " # "],
47+
"8": [" ### ", "# #", " ### ", "# #", " ### "],
48+
"9": [" ### ", "# #", " ####", " #", " ### "],
49+
"-": [" ", " ", "#####", " ", " "],
50+
" ": [" ", " ", " ", " ", " "],
51+
}
52+
53+
54+
def scale_rows(rows: list[str], scale: int) -> list[str]:
55+
if scale <= 1:
56+
return rows
57+
scaled: list[str] = []
58+
for row in rows:
59+
expanded = "".join(ch * scale for ch in row)
60+
scaled.extend([expanded] * scale)
61+
return scaled
62+
63+
64+
def render_text(text: str, scale: int = 1) -> str:
65+
chars = [FONT.get(ch, FONT["-"]) for ch in text.upper()]
66+
rows = ["" for _ in range(5)]
67+
for glyph in chars:
68+
for idx, row in enumerate(glyph):
69+
rows[idx] += f"{row} "
70+
rows = scale_rows(rows, scale)
71+
return "\n".join(rows)
72+
73+
74+
def main() -> None:
75+
parser = argparse.ArgumentParser(description="ASCII text renderer")
76+
parser.add_argument("--text", default="Retro Bot", help="Text to render")
77+
parser.add_argument("--scale", type=int, default=1, help="Scale factor")
78+
args = parser.parse_args()
79+
scale = max(1, min(5, args.scale))
80+
print(render_text(args.text, scale=scale))
81+
82+
83+
if __name__ == "__main__":
84+
main()

scripts/calc.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
"""Safe scientific calculator.
2+
3+
Examples:
4+
python calc.py "sin(pi/2) + log10(100)"
5+
"""
6+
7+
from __future__ import annotations
8+
9+
import argparse
10+
import ast
11+
import math
12+
from typing import Any
13+
14+
15+
ALLOWED_NAMES = {
16+
"pi": math.pi,
17+
"e": math.e,
18+
"sin": math.sin,
19+
"cos": math.cos,
20+
"tan": math.tan,
21+
"asin": math.asin,
22+
"acos": math.acos,
23+
"atan": math.atan,
24+
"sqrt": math.sqrt,
25+
"log": math.log,
26+
"log10": math.log10,
27+
"abs": abs,
28+
"pow": pow,
29+
"min": min,
30+
"max": max,
31+
"round": round,
32+
}
33+
34+
35+
def _eval_node(node: ast.AST) -> Any:
36+
if isinstance(node, ast.Expression):
37+
return _eval_node(node.body)
38+
if isinstance(node, ast.Constant):
39+
if isinstance(node.value, (int, float)):
40+
return node.value
41+
raise ValueError("Only numbers are allowed")
42+
if isinstance(node, ast.BinOp):
43+
left = _eval_node(node.left)
44+
right = _eval_node(node.right)
45+
if isinstance(node.op, ast.Add):
46+
return left + right
47+
if isinstance(node.op, ast.Sub):
48+
return left - right
49+
if isinstance(node.op, ast.Mult):
50+
return left * right
51+
if isinstance(node.op, ast.Div):
52+
return left / right
53+
if isinstance(node.op, ast.Pow):
54+
return left**right
55+
if isinstance(node.op, ast.Mod):
56+
return left % right
57+
raise ValueError("Unsupported operator")
58+
if isinstance(node, ast.UnaryOp):
59+
value = _eval_node(node.operand)
60+
if isinstance(node.op, ast.UAdd):
61+
return +value
62+
if isinstance(node.op, ast.USub):
63+
return -value
64+
raise ValueError("Unsupported unary operator")
65+
if isinstance(node, ast.Name):
66+
if node.id in ALLOWED_NAMES:
67+
return ALLOWED_NAMES[node.id]
68+
raise ValueError(f"Unknown symbol: {node.id}")
69+
if isinstance(node, ast.Call):
70+
if not isinstance(node.func, ast.Name):
71+
raise ValueError("Only simple functions allowed")
72+
func = ALLOWED_NAMES.get(node.func.id)
73+
if func is None:
74+
raise ValueError(f"Unknown function: {node.func.id}")
75+
args = [_eval_node(arg) for arg in node.args]
76+
return func(*args)
77+
raise ValueError("Unsupported expression")
78+
79+
80+
def safe_eval(expr: str) -> float:
81+
tree = ast.parse(expr, mode="eval")
82+
return float(_eval_node(tree))
83+
84+
85+
def repl() -> None:
86+
print("SciCalc - type 'exit' to quit")
87+
while True:
88+
try:
89+
line = input(">>> ").strip()
90+
except (EOFError, KeyboardInterrupt):
91+
print()
92+
return
93+
if not line:
94+
continue
95+
if line.lower() in {"exit", "quit"}:
96+
return
97+
try:
98+
print(safe_eval(line))
99+
except Exception as exc: # noqa: BLE001
100+
print(f"error: {exc}")
101+
102+
103+
def main() -> None:
104+
parser = argparse.ArgumentParser(description="Safe scientific calculator")
105+
parser.add_argument("expr", nargs="?", help="Expression to evaluate")
106+
args = parser.parse_args()
107+
if args.expr:
108+
print(safe_eval(args.expr))
109+
return
110+
repl()
111+
112+
113+
if __name__ == "__main__":
114+
main()

0 commit comments

Comments
 (0)