Hausaufgabe(apollo)

This commit is contained in:
Bendit Straetemans 2025-10-28 15:20:22 +01:00
parent a50285ea57
commit f744388bde
6 changed files with 327 additions and 0 deletions

20
Hausaufgaben/apollo/.env Normal file
View File

@ -0,0 +1,20 @@
# Anzeige
WIDTH=800
HEIGHT=600
FPS=60
BG_COLOR=#0a0a14
# Erde
EARTH_COLOR=#2878ff
EARTH_RADIUS=30
# Mond
MOON_COLOR=#f0f0f0
MOON_RADIUS=10
MOON_ORBIT_RADIUS=160
MOON_ANGULAR_SPEED_DEG=45 # Grad/Sekunde
# Apollo (optional, nur falls apollo.py genutzt wird)
APOLLO_COLOR=#dc3232
APOLLO_RADIUS=7
APOLLO_ORBIT_RADIUS=40

View File

@ -0,0 +1,42 @@
from __future__ import annotations
import math
from typing import Tuple, List
import pygame # type: ignore
from moon import Moon
import compute
class Apollo(Moon):
"""Fügt die Apollo-Kapsel hinzu; liest alle Werte aus Settings (env)."""
def get_apollo_angle(self) -> float:
return -2.0 * self.get_moon_angle()
def get_apollo_position(self) -> Tuple[int, int]:
theta = self.get_apollo_angle()
r = float(self.settings.apollo_orbit_radius)
rot: List[List[float]] = [
[math.cos(theta), -math.sin(theta)],
[math.sin(theta), math.cos(theta)],
]
vec: List[List[float]] = [[r], [0.0]]
res = compute.matmul(rot, vec)
mx, my = self.get_moon_position()
return int(mx + res[0][0]), int(my + res[1][0])
def draw(self, surface: pygame.Surface) -> None:
super().draw(surface)
pygame.draw.circle(
surface, (90, 50, 50), self.get_moon_position(), self.settings.apollo_orbit_radius, width=1
)
ax, ay = self.get_apollo_position()
pygame.draw.circle(surface, self.settings.apollo_color, (ax, ay), self.settings.apollo_radius)
if __name__ == "__main__":
Apollo().run()
#created by chat

View File

@ -0,0 +1,69 @@
from typing import List
def matmul(A: List[List[float]], B: List[List[float]]) -> List[List[float]]:
"""
Multiplies two matrices A and B (nested Python lists).
Requirements:
- A has shape (m x n), B has shape (n x p).
- All rows in A and B must have equal length.
- Elements are numeric (float/int).
Args:
A: Left matrix, list of rows (m x n).
B: Right matrix, list of rows (n x p).
Returns:
New matrix C = A * B with shape (m x p).
Raises:
ValueError: If matrices are empty, ragged,
or shapes are incompatible.
"""
if not A or not B:
raise ValueError("Empty matrices are not supported.")
if not A[0] or not B[0]:
raise ValueError("Matrices must have at least one column.")
a_cols = len(A[0])
for row in A:
if len(row) != a_cols:
raise ValueError("Left matrix has inconsistent row lengths.")
b_cols = len(B[0])
for row in B:
if len(row) != b_cols:
raise ValueError("Right matrix has inconsistent row lengths.")
if a_cols != len(B):
raise ValueError(
f"Incompatible shapes: A is {len(A)}x{a_cols}, "
f"B is {len(B)}x{b_cols}; need cols(A) == rows(B)."
)
m, n, p = len(A), a_cols, b_cols
C: List[List[float]] = [[0 for _ in range(p)] for _ in range(m)]
for i in range(m):
for k in range(n):
a_ik = A[i][k]
for j in range(p):
C[i][j] += a_ik * B[k][j]
return C
if __name__ == "__main__":
matrix_a = [[3, 4, -1, 4],
[-2, 2, 5, 1]]
matrix_b = [[1, 3, -2],
[2, 5, 1],
[-1, 4, -4],
[2, 3, 6]]
matrix_c = matmul(matrix_a, matrix_b)
print("Ergebnis C = A * B:")
for row in matrix_c:
print(row)

View File

@ -0,0 +1,101 @@
"""Konfigurations-Loader für das Moon/Apollo-Projekt.
"""
from __future__ import annotations
import os
import re
from dataclasses import dataclass
from typing import Tuple
from dotenv import load_dotenv
load_dotenv(override=False)
def _get_env(name: str, default: str) -> str:
val = os.getenv(name)
return val if val is not None and val != "" else default
def _parse_int(name: str, default: int, min_val: int | None = None) -> int:
raw = _get_env(name, str(default))
try:
v = int(raw)
if min_val is not None and v < min_val:
raise ValueError
return v
except Exception as _:
return default
def _parse_float(name: str, default: float, min_val: float | None = None) -> float:
raw = _get_env(name, str(default))
try:
v = float(raw)
if min_val is not None and v < min_val:
raise ValueError
return v
except Exception as _:
return default
_HEX = re.compile(r"^#?([0-9a-fA-F]{6})$")
def _parse_rgb(name: str, default_hex: str) -> Tuple[int, int, int]:
"""Erlaubt '#rrggbb' oder 'rrggbb'. Fällt auf default zurück, wenn ungültig."""
raw = _get_env(name, default_hex)
m = _HEX.match(raw)
hx = m.group(1) if m else default_hex.lstrip("#")
r = int(hx[0:2], 16)
g = int(hx[2:4], 16)
b = int(hx[4:6], 16)
return (r, g, b)
@dataclass(frozen=True)
class Settings:
# Anzeige
width: int
height: int
fps: int
bg_color: Tuple[int, int, int]
# Erde
earth_color: Tuple[int, int, int]
earth_radius: int
# Mond
moon_color: Tuple[int, int, int]
moon_radius: int
moon_orbit_radius: int
moon_angular_speed_deg: float # Grad/Sekunde
# Apollo (optional)
apollo_color: Tuple[int, int, int]
apollo_radius: int
apollo_orbit_radius: int
def get_settings() -> Settings:
"""Erzeugt Settings aus Umgebungsvariablen oder Defaults."""
return Settings(
# Anzeige
width=_parse_int("WIDTH", 800, min_val=100),
height=_parse_int("HEIGHT", 600, min_val=100),
fps=_parse_int("FPS", 60, min_val=1),
bg_color=_parse_rgb("BG_COLOR", "#0a0a14"),
# Erde
earth_color=_parse_rgb("EARTH_COLOR", "#2878ff"),
earth_radius=_parse_int("EARTH_RADIUS", 30, min_val=1),
# Mond
moon_color=_parse_rgb("MOON_COLOR", "#f0f0f0"),
moon_radius=_parse_int("MOON_RADIUS", 10, min_val=1),
moon_orbit_radius=_parse_int("MOON_ORBIT_RADIUS", 160, min_val=10),
moon_angular_speed_deg=_parse_float("MOON_ANGULAR_SPEED_DEG", 45.0, min_val=0.1),
# Apollo
apollo_color=_parse_rgb("APOLLO_COLOR", "#dc3232"),
apollo_radius=_parse_int("APOLLO_RADIUS", 7, min_val=1),
apollo_orbit_radius=_parse_int("APOLLO_ORBIT_RADIUS", 40, min_val=5),
)

View File

@ -0,0 +1,31 @@
import pygame
class Game:
def __init__(self, width=800, height=600, fps=60, title="Game"):
pygame.init()
self.width = width
self.height = height
self.fps = fps
self.title = title
self.screen = pygame.display.set_mode((width, height))
pygame.display.set_caption(title)
self.clock = pygame.time.Clock()
self.running = True
def run(self):
"""Startet die Hauptschleife."""
while self.running:
dt = self.clock.tick(self.fps) / 1000 # Zeit seit letztem Frame
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.running = False
self.update(dt)
self.draw(self.screen)
pygame.display.flip()
pygame.quit()
def update(self, dt: float):
pass
def draw(self, surface: pygame.Surface):
pass

View File

@ -0,0 +1,64 @@
from __future__ import annotations
import math
from typing import Tuple, List
import pygame # type: ignore
from game import Game
import compute
from config import get_settings
class Moon(Game):
"""Unterklasse von Game: Animation Mond-um-Erde mit .env-Konfiguration."""
def __init__(self) -> None:
self.settings = get_settings()
super().__init__(
width=self.settings.width,
height=self.settings.height,
fps=self.settings.fps,
title="Moon Orbit (env-configured)",
)
self._theta: float = 0.0
self._center: Tuple[float, float] = (self.width / 2, self.height / 2)
w
def get_earth_center(self) -> Tuple[float, float]:
return self._center
def get_moon_angle(self) -> float:
return self._theta
def get_moon_orbit_radius(self) -> int:
return self.settings.moon_orbit_radius
def get_moon_position(self) -> Tuple[int, int]:
theta = self.get_moon_angle()
r = float(self.get_moon_orbit_radius())
rot: List[List[float]] = [
[math.cos(theta), -math.sin(theta)],
[math.sin(theta), math.cos(theta)],
]
vec: List[List[float]] = [[r], [0.0]]
res = compute.matmul(rot, vec)
cx, cy = self.get_earth_center()
return int(cx + res[0][0]), int(cy + res[1][0])
def update(self, dt: float) -> None:
omega = math.radians(self.settings.moon_angular_speed_deg)
self._theta = (self._theta + omega * dt) % (2.0 * math.pi)
def draw(self, surface: pygame.Surface) -> None:
s = self.settings
surface.fill(s.bg_color)
ex, ey = self.get_earth_center()
pygame.draw.circle(surface, s.earth_color, (int(ex), int(ey)), s.earth_radius)
pygame.draw.circle(surface, (60, 60, 80), (int(ex), int(ey)), s.moon_orbit_radius, width=1)
mx, my = self.get_moon_position()
pygame.draw.circle(surface, s.moon_color, (mx, my), s.moon_radius)
if __name__ == "__main__":
Moon().run()