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