From fe550f1e0170fb3b16ad8002f8de0b7c7d272c35 Mon Sep 17 00:00:00 2001 From: Mariam Date: Thu, 15 Oct 2026 17:09:26 +0200 Subject: [PATCH] Initial commit of project --- .idea/.gitignore | 8 ++ .idea/Prog3.iml | 12 ++ .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 7 ++ .idea/modules.xml | 8 ++ __pycache__/compute.cpython-313.pyc | Bin 0 -> 5312 bytes __pycache__/game.cpython-313.pyc | Bin 0 -> 2988 bytes __pycache__/moon.cpython-313.pyc | Bin 0 -> 2969 bytes apollo.py | 42 +++++++ compute.py | 115 ++++++++++++++++++ game.py | 52 ++++++++ moon.py | 48 ++++++++ opencode.json | 16 +++ reverse.py | 11 ++ 14 files changed, 325 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/Prog3.iml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 __pycache__/compute.cpython-313.pyc create mode 100644 __pycache__/game.cpython-313.pyc create mode 100644 __pycache__/moon.cpython-313.pyc create mode 100644 apollo.py create mode 100644 compute.py create mode 100644 game.py create mode 100644 moon.py create mode 100644 opencode.json create mode 100644 reverse.py diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/Prog3.iml b/.idea/Prog3.iml new file mode 100644 index 0000000..08dd6fe --- /dev/null +++ b/.idea/Prog3.iml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..626ac92 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..3ea5936 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/__pycache__/compute.cpython-313.pyc b/__pycache__/compute.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4e203804a4f2829cb33f6c98d41a02ce0c9fe808 GIT binary patch literal 5312 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 bool: + # First let the moon move + super().update_game() + # Rotate Apollo around the moon + point = transpose([list(self.apollo_offset)]) + result = matmul(self.rot_apollo, point) + self.apollo_offset = (result[0][0], result[1][0]) + return True + + def draw_game(self) -> None: + # Draw background and Earth and Moon via super() + super().draw_game() + # Compute Apollo absolute position + moon_abs = (self.center[0] + self.position_moon[0], self.center[1] + self.position_moon[1]) + apollo_pos = (int(moon_abs[0] + self.apollo_offset[0]), int(moon_abs[1] + self.apollo_offset[1])) + screen = pygame.display.get_surface() + pygame.draw.circle(screen, RED, apollo_pos, 5) + pygame.display.flip() + +if __name__ == "__main__": + Apollo().run() diff --git a/compute.py b/compute.py new file mode 100644 index 0000000..be2f526 --- /dev/null +++ b/compute.py @@ -0,0 +1,115 @@ +"""Einfache Matrixoperationen: +Multiplikation, Transponieren und Drehung um 90° im Uhrzeigersinn. +""" + +from __future__ import annotations +from typing import List + +# Eine Matrix ist hier eine Liste von Zeilen mit Zahlen. +Matrix = List[List[float]] + + +def matmul(A: Matrix, B: Matrix) -> Matrix: + """Multipliziert zwei Matrizen A und B.""" + + # Leere Matrizen sind nicht erlaubt. + if not A or not B: + raise ValueError("Matrizen dürfen nicht leer sein") + + # Prüfen, ob alle Zeilen von A gleich lang sind. + spalten_A = len(A[0]) + if any(len(zeile) != spalten_A for zeile in A): + raise ValueError("Matrix A ist nicht rechteckig") + + # Prüfen, ob alle Zeilen von B gleich lang sind. + spalten_B = len(B[0]) + if any(len(zeile) != spalten_B for zeile in B): + raise ValueError("Matrix B ist nicht rechteckig") + + # Für A × B muss die Spaltenzahl von A + # der Zeilenzahl von B entsprechen. + if spalten_A != len(B): + raise ValueError( + f"Multiplikation nicht möglich: A hat {spalten_A} Spalten, " + f"B hat {len(B)} Zeilen" + ) + + ergebnis: Matrix = [] + + # Jede Zeile von A mit jeder Spalte von B kombinieren. + for i in range(len(A)): + ergebnis_zeile: List[float] = [] + + for j in range(spalten_B): + # Produkte der passenden Elemente bilden und addieren. + wert = sum(A[i][k] * B[k][j] for k in range(spalten_A)) + ergebnis_zeile.append(wert) + + ergebnis.append(ergebnis_zeile) + + return ergebnis + + +def transpose(M: Matrix) -> Matrix: + """Vertauscht Zeilen und Spalten einer Matrix.""" + + if not M: + raise ValueError("Matrix darf nicht leer sein") + + # Eine rechteckige Matrix muss gleich lange Zeilen haben. + spalten = len(M[0]) + if any(len(zeile) != spalten for zeile in M): + raise ValueError("Matrix ist nicht rechteckig") + + # Die Elemente jeder Spalte werden zu einer neuen Zeile. + return [[M[i][j] for i in range(len(M))] for j in range(spalten)] + + +def rotate90_clockwise(M: Matrix) -> Matrix: + """Dreht eine Matrix um 90° im Uhrzeigersinn.""" + + if not M: + raise ValueError("Matrix darf nicht leer sein") + + spalten = len(M[0]) + if any(len(zeile) != spalten for zeile in M): + raise ValueError("Matrix ist nicht rechteckig") + + # Erst transponieren, dann jede neue Zeile umkehren. + transponiert = [ + [M[i][j] for i in range(len(M))] + for j in range(spalten) + ] + return [zeile[::-1] for zeile in transponiert] + + +if __name__ == "__main__": + # Beispiel: Eine 2×3-Matrix mal eine 3×2-Matrix. + A = [[1, 2, 3], [4, 5, 6]] + B = [[7, 8], [9, 10], [11, 12]] + print("A × B:") + print(matmul(A, B)) # [[58, 64], [139, 154]] + + # Eine Einheitsmatrix verändert eine Matrix bei der Multiplikation nicht. + C = [[1, 0, 0], [0, 1, 0], [0, 0, 1]] + D = [[2, 3, 4], [5, 6, 7], [8, 9, 10]] + print("D × C:") + print(matmul(D, C)) # ergibt wieder D + + # Zeilen und Spalten tauschen. + E = [[1, 2, 3], [4, 5, 6]] + print("Transponierte Matrix:") + print(transpose(E)) # [[1, 4], [2, 5], [3, 6]] + + # Erst transponieren, dann die Zeilen umkehren. + F = [[1, 2, 3], [4, 5, 6]] + print("90° im Uhrzeigersinn gedreht:") + print(rotate90_clockwise(F)) # [[4, 1], [5, 2], [6, 3]] + +def rot_2D(theta: float): + """Return a 2x2 rotation matrix for angle theta in radians.""" + import math + c = math.cos(theta) + s = math.sin(theta) + return [[c, -s], [s, c]] +# Katzen-Test \ No newline at end of file diff --git a/game.py b/game.py new file mode 100644 index 0000000..dfc7168 --- /dev/null +++ b/game.py @@ -0,0 +1,52 @@ +import pygame + +class Game: + + def __init__(self, title, fps=60, size=(640, 400)): + self.title = title + self.fps = fps + self.size = size + self.clock = pygame.time.Clock() + self.dt = 0 + self.screen = None + + def init_game(self): + pygame.init() + pygame.display.set_caption(self.title) + self.screen = pygame.display.set_mode(self.size) + + + def game_loop(self): + while True: + # Berechnung der Zeitdifferenz seit dem letzten Frame in Sekunden + self.dt = self.clock.tick(self.fps) / 1000 + if self.event_handling() == False: + break + if self.update_game() == False: + break + self.draw_game() + + def exit_game(self): + pygame.quit() + + def event_handling(self): # bleibt in der Unterklasse unverändert + for event in pygame.event.get(): + if not self.handle_event(event): + return False + return True + + def handle_event(self, event): # wird in der Unterklasse überschrieben + if event.type == pygame.QUIT: + return False + return True + + def update_game(self): + return True + + def draw_game(self): + pygame.display.flip() + + def run(self): + self.init_game() + self.game_loop() + self.exit_game() diff --git a/moon.py b/moon.py new file mode 100644 index 0000000..ae34f9c --- /dev/null +++ b/moon.py @@ -0,0 +1,48 @@ +import pygame +from compute import matmul, rot_2D, transpose # Hilfsfunktionen für Matrizen und Drehung +from game import Game + +EARTH_RADIUS = 30 +MOON_RADIUS = 10 +BLACK = (0, 0, 0) +WHITE = (255, 255, 255) +BLUE = (0, 0, 255) + +class Moon(Game): # Moon ist ein Spiel und übernimmt Funktionen von Game + """Der Mond kreist um die Erde.""" + + def __init__( + self, + title: str = "Moon", + fps: int = 60, + size: tuple[int, int] = (640, 400), + ) -> None: + """Legt Startposition, Drehwinkel und Rotationsmatrix fest.""" + super().__init__(title, fps, size) + self.center = (size[0] // 2, size[1] // 2) + self.position_moon = (100.0, 0.0) + self.theta = 0.01 + self.rot_moon = rot_2D(self.theta) + + def update_game(self) -> bool: + """Dreht den Mond ein Stück weiter.""" + point = transpose([list(self.position_moon)]) # Macht aus der Mondposition eine Spalte + result = matmul(self.rot_moon, point) # Dreht die Position mit der Rotationsmatrix + self.position_moon = (result[0][0], result[1][0]) # Speichert die neue Position + return True # Sagt dem Spiel: Es soll weiterlaufen + + def draw_game(self) -> None: + """Zeichnet Erde und Mond.""" + screen = pygame.display.get_surface() # Holt die Zeichenfläche des Fensters + screen.fill(BLACK) # Löscht das alte Bild und färbt den Hintergrund schwarz + pygame.draw.circle(screen, BLUE, self.center, EARTH_RADIUS) # Zeichnet die Erde + moon_pos = ( # Berechnet die Position des Mondes im Fenster + int(self.center[0] + self.position_moon[0]), # Mittelpunkt-x plus Mond-x + int(self.center[1] + self.position_moon[1]), # Mittelpunkt-y plus Mond-y + ) + pygame.draw.circle(screen, WHITE, moon_pos, MOON_RADIUS) # Zeichnet den Mond + pygame.display.flip() # Zeigt das fertige Bild im Fenster an + + +if __name__ == "__main__": # Prüft, ob diese Datei direkt gestartet wurde + Moon().run() # Erstellt das Spiel und startet die Spielschleife \ No newline at end of file diff --git a/opencode.json b/opencode.json new file mode 100644 index 0000000..15be39d --- /dev/null +++ b/opencode.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "thn": { + "npm": "@ai-sdk/openai-compatible", + "options": { + "baseURL": "http://141.75.33.244:8000/v1", + "apiKey": "sk-QXj1p40XOwNSze_5-eYrBzVh3qIgAfqoWPkAjNVqOS8" + }, + "models": { + "gpt-oss:20b": { "name": "GPT-OSS 20B" } + } + } + }, + "model": "thn/gpt-oss:20b" +} \ No newline at end of file diff --git a/reverse.py b/reverse.py new file mode 100644 index 0000000..88a31a1 --- /dev/null +++ b/reverse.py @@ -0,0 +1,11 @@ +def reverse_string(s: str) -> str: + """Return the reverse of the input string.""" + return s[::-1] + +if __name__ == "__main__": + import sys + if len(sys.argv) > 1: + input_str = sys.argv[1] + else: + input_str = "Hello, World!" + print(reverse_string(input_str))