From 84055e4d0cb58f94ac8e6be28885c7d51d13ef3a Mon Sep 17 00:00:00 2001 From: Hong-Phuc Bui <hong-phuc.bui@htwsaar.de> Date: Mon, 13 May 2024 02:54:33 +0200 Subject: [PATCH] Example for functions --- funktion-modular/README.md | 5 + .gitignore | 3 python-grundlage/Lissajous-turtle.py | 35 +++++-- funktion-modular/calendar/__pycache__/month_of_year.cpython-312.pyc | 0 funktion-modular/calendar/test_month_of_year.py | 25 +++++ funktion-modular/calendar/HOWTO.md | 15 +++ funktion-modular/calendar/__pycache__/test_month_of_year.cpython-312.pyc | 0 funktion-modular/calendar/month_of_year.py | 99 +++++++++++++++++++ python-grundlage/Lissajous-np.py | 16 ++ funktion-modular/calendar/month_of_year-no-fn.py | 90 ++++++++++++++++++ 10 files changed, 273 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index f282e9f..ae4b8a2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ sandbox* -queens* \ No newline at end of file +queens* +*.venv* \ No newline at end of file diff --git a/funktion-modular/README.md b/funktion-modular/README.md new file mode 100644 index 0000000..c09b1de --- /dev/null +++ b/funktion-modular/README.md @@ -0,0 +1,5 @@ +# README + +1. One project one directory with unittest +2. Use typing annotation for every function. + diff --git a/funktion-modular/calendar/HOWTO.md b/funktion-modular/calendar/HOWTO.md new file mode 100644 index 0000000..56f2d5d --- /dev/null +++ b/funktion-modular/calendar/HOWTO.md @@ -0,0 +1,15 @@ +# HOWTO + +## Run unittest + +* For all unittests in directory + +```shell +python -m unittest +``` + +* For some files + +```shell +python -m unittest -p '*_test.py' +``` diff --git a/funktion-modular/calendar/__pycache__/month_of_year.cpython-312.pyc b/funktion-modular/calendar/__pycache__/month_of_year.cpython-312.pyc new file mode 100644 index 0000000..7934e3f --- /dev/null +++ b/funktion-modular/calendar/__pycache__/month_of_year.cpython-312.pyc Binary files differ diff --git a/funktion-modular/calendar/__pycache__/test_month_of_year.cpython-312.pyc b/funktion-modular/calendar/__pycache__/test_month_of_year.cpython-312.pyc new file mode 100644 index 0000000..f14a14a --- /dev/null +++ b/funktion-modular/calendar/__pycache__/test_month_of_year.cpython-312.pyc Binary files differ diff --git a/funktion-modular/calendar/month_of_year-no-fn.py b/funktion-modular/calendar/month_of_year-no-fn.py new file mode 100755 index 0000000..d03cb1e --- /dev/null +++ b/funktion-modular/calendar/month_of_year-no-fn.py @@ -0,0 +1,90 @@ +#! /usr/bin/env python +""" +Description: + Programm zur Ausgabe einer Ansicht eines Monats wie gängige Kalender-Format + +Usage: + +``` +$ python month_of_year-no-fn.py 12 2024 +``` +""" + +from typing import Final +import sys + +month: Final[int] = int(sys.argv[1]) +year: Final[int] = int(sys.argv[2]) + +# Calender setup +weekdays: Final[tuple[str, ...]] = ("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa") +first_day_of_week: Final[int] = 1 # it is monday, common in Europa +months: Final[tuple[ tuple[str, int], ...]] = (("", 0), + ("Januar", 31), ("Februar", 28), ("März", 31), + ("April", 30), ("Mai", 31), ("Juni", 30), + ("July", 31), ("August", 31), ("September", 30), + ("Oktober", 31), ("November", 30), ("Dezember", 31)) + + +# calculate the weekday of the 1.st day of the given month +# Not possible to test next lines of code, since all variables are global +first_date: Final[int] = 1 # first day of the month +y0 = year - ((14 - month)//12) +x = y0 + (y0//4) - (y0//100) + (y0//400) +m0 = month + 12 * ((14 - month)//12) - 2 +day_of_first_date = (first_date + x + (31 * m0) // 12) % 7 + +# test and comment out +# print(weekdays[first_day_of_month]) + +# calculate how many days of last month get places in the first week +# of this month +diff: Final[int] = (7 + day_of_first_date - first_day_of_week) % 7 +# test and comment out +# print(diff) + +# calculate how many days in the month +days_in_months = months[month][1] +# check leap year +if month == 2: + if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0: + days_in_months += 1 + + +# print the calendar +column_width: Final[int] = 5 # at least 3, since days in month have at most 2 digits +calendar_width: Final[int] = 7 * column_width # 7 days of a week, each day need 3 spaces +head_line = f"{months[month][0]} {year}" +fmt_head_line = f"{head_line}".center(calendar_width, '-') +# test and comment out +# print(fmt_head_line) + +# calender_view is initialized with Headline +calendar_view: str = fmt_head_line + "\n" + +# 7 weekdays +for d in weekdays: + calendar_view += f"{d}".rjust(column_width, ' ') +# test and comment out +calendar_view += "\n" +# print(calendar_view) + +# the empty columns in the first week of the month +for _ in range(diff, 0, -1): + calendar_view += ("#"*(column_width-1) + "-") # mark empty columns with some characters to let debug easier + +# print the days in the first week +day = 1 +days_in_first_week = "" +while day + diff <= 7: + days_in_first_week += (f"{day}".rjust(column_width)) + day += 1 +calendar_view += days_in_first_week + "\n" + +while day <= days_in_months: + calendar_view += (f"{day}".rjust(column_width)) + if (day + diff) % 7 == 0: # reaches the last day of week + calendar_view += "\n" + day += 1 + +print(calendar_view) diff --git a/funktion-modular/calendar/month_of_year.py b/funktion-modular/calendar/month_of_year.py new file mode 100755 index 0000000..29bac62 --- /dev/null +++ b/funktion-modular/calendar/month_of_year.py @@ -0,0 +1,99 @@ +#! /usr/bin/env python +""" +Description: + Programm zur Ausgabe einer Ansicht eines Monats wie gängige Kalender-Format + +Usage: + +``` +$ python month_of_year.py 12 2024 +``` +""" +from typing import Final +import sys + + +# Calender setup +weekdays: Final[tuple[str, ...]] = ("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa") +first_day_of_week: Final[int] = 1 # it is monday, common in Europa +months: Final[tuple[ tuple[str, int], ...]] = (("", 0), + ("Januar", 31), ("Februar", 28), ("März", 31), + ("April", 30), ("Mai", 31), ("Juni", 30), + ("July", 31), ("August", 31), ("September", 30), + ("Oktober", 31), ("November", 30), ("Dezember", 31)) + + +def is_leap_year(year: int) -> bool: + return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0) + + +def weekday_of_date(day: int, month: int, year: int) -> int: + y0 = year - ((14 - month) // 12) + x = y0 + (y0 // 4) - (y0 // 100) + (y0 // 400) + m0 = month + 12 * ((14 - month) // 12) - 2 + return (day + x +(31 * m0) // 12) % 7 + + +def count_days_in_month(month: int, year: int) -> int: + count_days = months[month][1] + if month == 2 and is_leap_year(year): count_days += 1 + return count_days + + +def build_calendar_head(month: int, year: int, calendar_width: int, fill_char: str =' ') -> str: + head_line = f"{months[month][0]} {year}" + return head_line.center(calendar_width, fill_char) + + +def build_weekdays_line(column_width) -> str: + wd_line = "" + for i in range(0, 7): + d = (i + first_day_of_week) % 7 + wd_line += f"{weekdays[d]}".rjust(column_width, ' ') + return wd_line + + +def format_day(day: int, column_width: int) -> str: + return f"{day}".rjust(column_width) + + +def build_month_view(month: int, year: int, column_width: int) -> str: + month_view = "" + day = 1 + # the first week + day_of_first_date = weekday_of_date(day, month, year) + # how many columns before the first day of this month + diff = (7 + day_of_first_date - first_day_of_week) % 7 + # -> empty column + for _ in range(diff, 0, -1): + month_view += ("#"*(column_width - 1) + "-") + # -> next days in the first week + while day + diff <= 7: + month_view += format_day(day, column_width) + day += 1 + month_view += "\n" + # next weeks + days_in_month = count_days_in_month(month, year) + while day <= days_in_month: + month_view += format_day(day, column_width) + if (day + diff) % 7 == 0: month_view += "\n" + day += 1 + return month_view + + +def build_calendar(month: int, year: int, column_width: int = 3) -> str: + calendar_width = 7 * column_width + head_line = build_calendar_head(month, year, calendar_width, fill_char="-") + calendar_view = f"{head_line}\n" + weekdays_line = build_weekdays_line(column_width) + calendar_view += f"{weekdays_line}\n" + month_view = build_month_view(month, year, column_width) + calendar_view += f"{month_view}\n" + return calendar_view + + +if __name__ == "__main__": + month = int(sys.argv[1]) + year = int(sys.argv[2]) + cal = build_calendar(month, year, 4) + print(cal) \ No newline at end of file diff --git a/funktion-modular/calendar/test_month_of_year.py b/funktion-modular/calendar/test_month_of_year.py new file mode 100644 index 0000000..074bf03 --- /dev/null +++ b/funktion-modular/calendar/test_month_of_year.py @@ -0,0 +1,25 @@ +import unittest + +import month_of_year as mofy + + +class MofyTestCase(unittest.TestCase): + def test_2024_leapyear(self): + year = 2024 + is_leap_year = mofy.is_leap_year(year) + self.assertEqual(is_leap_year, True) + + def test_2000_leapyear(self): + year = 2000 + is_leap_year = mofy.is_leap_year(year) + self.assertEqual(is_leap_year, True) # add assertion here + + def test_weekday_of_day(self): + d, m, y = (1, 2, 2024) + wd = mofy.weekday_of_date(d, m, y) + self.assertEqual(wd, 4) + + + +if __name__ == '__main__': + unittest.main() diff --git a/python-grundlage/Lissajous-np.py b/python-grundlage/Lissajous-np.py index 4460ee5..f51902c 100644 --- a/python-grundlage/Lissajous-np.py +++ b/python-grundlage/Lissajous-np.py @@ -1,5 +1,5 @@ #! /usr/bin/env python - +import sys from typing import Final import numpy as np from numpy import pi @@ -7,12 +7,13 @@ amplitude: tuple[float, float] = (1, 1) -# frequent -omega: tuple[float, float] = (-1, -2) +# frequent, some values (-3, 5) (-3, 8) (3, 11) +omega: tuple[float, float] = (3, 11) + # phase phi: tuple[float, float] = (pi/2, 3*pi/4) -N: Final[int] = 100 +N: Final[int] = 360*2 T = np.linspace(0, 2*pi, num=N) x = amplitude[0] * np.cos(omega[0]*T + phi[0]) y = amplitude[1] * np.cos(omega[1]*T + phi[1]) @@ -21,5 +22,12 @@ fig, ax = plt.subplots() ax.plot(x, y, linewidth=2.0) +write_to_file = False +if write_to_file: + output_dir = "../../2024/python-output" + image_filename = f"{output_dir}/{sys.argv[0].replace('.py','.pdf')}" + plt.savefig(image_filename) + plt.show() + diff --git a/python-grundlage/Lissajous-turtle.py b/python-grundlage/Lissajous-turtle.py index 62a1d4a..9f44134 100644 --- a/python-grundlage/Lissajous-turtle.py +++ b/python-grundlage/Lissajous-turtle.py @@ -1,19 +1,19 @@ #! /usr/bin/env python - +import sys from typing import Final from math import pi, cos import turtle -amplitude: tuple[float, float] = (1, 1) +amplitude: Final[tuple[float, float]] = (1, 1) # frequent -omega: tuple[float, float] = (-1, -2) +omega: Final[tuple[float, float]] = (3, 11) # phase -phi: tuple[float, float] = (pi/2, 3*pi/4) +phi: Final[tuple[float, float]] = (pi/2, 3*pi/4) # Diskretisieren N: Final[int] = 360 -step = (2*pi) / N -T = [k * step for k in range(N)] +step: Final = (2*pi) / N +T: Final = [k * step for k in range(N)] points = [( amplitude[0] * cos(omega[0]*t + phi[0]), amplitude[1] * cos(omega[1]*t + phi[1]) @@ -22,18 +22,33 @@ # Plot with turtle (canvaswidth, canvasheight) = turtle.screensize() -point_size = 3 +point_size = 1.5 +turtle.setup(width=canvaswidth + 5*point_size, height=canvaswidth + 5*point_size) + # scale up x_factor = (canvaswidth / 2) / amplitude[0] y_factor = (canvasheight / 2) / amplitude[1] print(x_factor, y_factor) # as fast as possible turtle.speed(0) -turtle.pendown() +turtle.penup() +turtle.pensize(point_size) for p in points: x = x_factor * p[0] y = y_factor * p[1] - turtle.teleport(x, y) - turtle.dot(point_size) + #turtle.teleport(x, y) + #turtle.dot(point_size) + turtle.goto(x, y) + turtle.pendown() +p0 = points[0] +turtle.goto(x_factor * p0[0], y_factor * p0[1]) + +write_to_file = False +if write_to_file: + output_dir = "../../2024/python-output" + image_filename = f"{output_dir}/{sys.argv[0].replace('.py','.eps')}" + print(f"save file to {image_filename}") + canvas_screen = turtle.getscreen().getcanvas() + canvas_screen.postscript(file=image_filename) turtle.done() -- Gitblit v1.10.0-SNAPSHOT