From 218b341f970dd7e1a53182730e8c6adc6b9cfea2 Mon Sep 17 00:00:00 2001 From: Xuan4781 Date: Thu, 30 Oct 2025 23:34:17 -0400 Subject: [PATCH 01/25] create initial folder setup --- examples/demo.py | 0 src/morse_code/__init__.py | 0 tests/test_decode.py | 0 tests/test_encode.py | 0 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 examples/demo.py create mode 100644 src/morse_code/__init__.py create mode 100644 tests/test_decode.py create mode 100644 tests/test_encode.py diff --git a/examples/demo.py b/examples/demo.py new file mode 100644 index 0000000..e69de29 diff --git a/src/morse_code/__init__.py b/src/morse_code/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_decode.py b/tests/test_decode.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_encode.py b/tests/test_encode.py new file mode 100644 index 0000000..e69de29 From f7513194761af18b058b6353392df4d2668a394b Mon Sep 17 00:00:00 2001 From: Xuan4781 Date: Thu, 30 Oct 2025 23:43:02 -0400 Subject: [PATCH 02/25] Add initial pyproject.toml for morse_code package --- pyproject.toml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 pyproject.toml diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..4e81985 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,31 @@ +[build-system] +requires = ["setuptools>=68", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "morse_code" +version = "0.1.0" +description = "A Python package for encoding and decoding Morse code." +readme = "README.md" +requires-python = ">=3.10" +license = { file = "LICENSE" } +authors = [{ name = "Team Lumen" }] +keywords = ["python", "morse code", "encoder", "decoder"] +classifiers = [ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent" +] + +[project.urls] +Homepage = "https://github.com/swe-students-fall2025/3-python-package-team_lumen" +Issues = "https://github.com/swe-students-fall2025/3-python-package-team_lumen/issues" + +[tool.setuptools] +package-dir = {"" = "src"} + +[tool.setuptools.packages.find] +where = ["src"] + +[project.scripts] +morse_code = "morse_code.core:cli" From 761c6345914d7c8f18914a516da65c7b21ee7a1b Mon Sep 17 00:00:00 2001 From: Xuan4781 Date: Thu, 30 Oct 2025 23:48:40 -0400 Subject: [PATCH 03/25] Add Pipfile with Python version and dependencies --- Pipfile | 13 +++++++++ Pipfile.lock | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 Pipfile create mode 100644 Pipfile.lock diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..65722d5 --- /dev/null +++ b/Pipfile @@ -0,0 +1,13 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +pytest = "*" +morse_code = {file = ".", editable = true} + +[dev-packages] + +[requires] +python_version = "3.10" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..2f9e06a --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,74 @@ +{ + "_meta": { + "hash": { + "sha256": "30b7f7af999b98edc5254671e6cb948a61005dc6efd8a65a82a4b35cb500fba6" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.10" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "colorama": { + "hashes": [ + "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", + "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", + "version": "==0.4.6" + }, + "iniconfig": { + "hashes": [ + "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", + "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12" + ], + "markers": "python_version >= '3.10'", + "version": "==2.3.0" + }, + "morse-code": { + "editable": true, + "file": "." + }, + "packaging": { + "hashes": [ + "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", + "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f" + ], + "markers": "python_version >= '3.8'", + "version": "==25.0" + }, + "pluggy": { + "hashes": [ + "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", + "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746" + ], + "markers": "python_version >= '3.9'", + "version": "==1.6.0" + }, + "pygments": { + "hashes": [ + "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", + "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b" + ], + "markers": "python_version >= '3.8'", + "version": "==2.19.2" + }, + "pytest": { + "hashes": [ + "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", + "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==8.4.2" + } + }, + "develop": {} +} From 6dbc02709ce5f7c090e0773be5159dfcda6202fa Mon Sep 17 00:00:00 2001 From: Xuan4781 Date: Thu, 30 Oct 2025 23:56:14 -0400 Subject: [PATCH 04/25] add Github build.yml for CI/CD --- .github/workflows/build.yml | 61 +++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..019f533 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,61 @@ +name: CI / CD - Morse Code + +on: + pull_request: + branches: [pipfile-experiment] + push: + tags: ["v*"] + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + timeout-minutes: 5 + strategy: + matrix: + python-version: ["3.10", "3.11"] + + steps: + - uses: actions/checkout@v4 + + - name: Install Python and Pipenv + uses: kojoru/prepare-pipenv@v1 + with: + python-version: ${{ matrix.python-version }} + + + - name: Turn on 'editable' mode + run: | + pipenv install -e . + + - name: Run pytest + run: | + pipenv install pytest + pipenv --venv + pipenv run python -m pytest + + deliver: + if: github.event_name != 'pull_request' + needs: [build] + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - uses: actions/checkout@v4 + + - name: Install Python, pipenv and Pipfile packages + uses: kojoru/prepare-pipenv@v1 + with: + python-version: "3.10" + + - name: Build package + run: | + pipenv install build + pipenv run python -m build . + + # publish to PyPI Test server + # - name: Publish to TestPyPI + # uses: pypa/gh-action-pypi-publish@release/v1 + # with: + # password: ${{ secrets.TEST_PYPI_API_TOKEN }} + # repository-url: https://test.pypi.org/legacy/ From bc0d10fc0e2574b6abde8322fcc2ca8a107fee9a Mon Sep 17 00:00:00 2001 From: Xuan4781 Date: Fri, 31 Oct 2025 00:08:22 -0400 Subject: [PATCH 05/25] Add placeholder tests --- tests/test_decode.py | 2 ++ tests/test_encode.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/test_decode.py b/tests/test_decode.py index e69de29..26af617 100644 --- a/tests/test_decode.py +++ b/tests/test_decode.py @@ -0,0 +1,2 @@ +def test_encode(): + assert True \ No newline at end of file diff --git a/tests/test_encode.py b/tests/test_encode.py index e69de29..03bb3d5 100644 --- a/tests/test_encode.py +++ b/tests/test_encode.py @@ -0,0 +1,2 @@ +def test_decode(): + assert True \ No newline at end of file From 5f7494fb43df08e42f15717ac7812f37f766f502 Mon Sep 17 00:00:00 2001 From: yiminliu2004 Date: Fri, 31 Oct 2025 01:16:56 -0400 Subject: [PATCH 06/25] add main file --- src/morse_code/__init__.py | 25 +++++++++++++++++++++++++ src/morse_code/__main__.py | 16 ++++++++++++++++ src/morse_code/core.py | 0 3 files changed, 41 insertions(+) create mode 100644 src/morse_code/__main__.py create mode 100644 src/morse_code/core.py diff --git a/src/morse_code/__init__.py b/src/morse_code/__init__.py index e69de29..8c7b2c4 100644 --- a/src/morse_code/__init__.py +++ b/src/morse_code/__init__.py @@ -0,0 +1,25 @@ +""" +Morse Code Package +A Python package for encoding and decoding Morse code with additional utilities. +""" + +from morse_code.core import ( + encode, + decode, + is_valid, + normalize_text, + normalize_code, + explain, + quiz +) + +__all__ = [ + 'encode', + 'decode', + 'is_valid', + 'normalize_text', + 'normalize_code', + 'explain', + 'quiz' +] + diff --git a/src/morse_code/__main__.py b/src/morse_code/__main__.py new file mode 100644 index 0000000..895938c --- /dev/null +++ b/src/morse_code/__main__.py @@ -0,0 +1,16 @@ +from .core import encode, decode, is_valid, explain + + +def main(): + print("Morse Code Demo") + text = "HELLO WORLD" + encoded = encode(text) + decoded = decode(encoded) + print(f"Original: {text}") + print(f"Encoded : {encoded}") + print(f"Decoded : {decoded}") + # print(f"Valid? {is_valid(encoded)}") + # print(f"Explain : {explain(encoded)}") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/src/morse_code/core.py b/src/morse_code/core.py new file mode 100644 index 0000000..e69de29 From ae4f73733c5e558c78ba6c8248c482ba957bf16b Mon Sep 17 00:00:00 2001 From: yiminliu2004 Date: Fri, 31 Oct 2025 01:19:51 -0400 Subject: [PATCH 07/25] add mapping morse code data --- src/morse_code/mapping.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/morse_code/mapping.py diff --git a/src/morse_code/mapping.py b/src/morse_code/mapping.py new file mode 100644 index 0000000..78e2a87 --- /dev/null +++ b/src/morse_code/mapping.py @@ -0,0 +1,13 @@ +LETTER_TO_MORSE = { + "A": ".-", "B": "-...", "C": "-.-.", "D": "-..", "E": ".", + "F": "..-.", "G": "--.", "H": "....", "I": "..", "J": ".---", + "K": "-.-", "L": ".-..", "M": "--", "N": "-.", "O": "---", + "P": ".--.", "Q": "--.-", "R": ".-.", "S": "...", "T": "-", + "U": "..-", "V": "...-", "W": ".--", "X": "-..-", "Y": "-.--", + "Z": "--..", + "0": "-----", "1": ".----", "2": "..---", "3": "...--", "4": "....-", + "5": ".....", "6": "-....", "7": "--...", "8": "---..", "9": "----.", + ".": ".-.-.-", ",": "--..--", "?": "..--..", "/": "-..-.", "-": "-....-", + "(": "-.--.", ")": "-.--.-" +} +MORSE_TO_LETTER = {v: k for k, v in LETTER_TO_MORSE.items()} From 6df246cf21c6c4f93b60168614c283267d11c69a Mon Sep 17 00:00:00 2001 From: yiminliu2004 Date: Fri, 31 Oct 2025 01:26:36 -0400 Subject: [PATCH 08/25] add function TODOs --- src/morse_code/__main__.py | 5 +++++ src/morse_code/core.py | 18 ++++++++++++++++++ src/morse_code/explain.py | 3 +++ src/morse_code/normalize.py | 8 ++++++++ src/morse_code/quiz.py | 3 +++ 5 files changed, 37 insertions(+) create mode 100644 src/morse_code/explain.py create mode 100644 src/morse_code/normalize.py create mode 100644 src/morse_code/quiz.py diff --git a/src/morse_code/__main__.py b/src/morse_code/__main__.py index 895938c..c5198a1 100644 --- a/src/morse_code/__main__.py +++ b/src/morse_code/__main__.py @@ -12,5 +12,10 @@ def main(): # print(f"Valid? {is_valid(encoded)}") # print(f"Explain : {explain(encoded)}") + # text = input("Enter text to encode: ") + # encoded = encode(text) + # print("Encoded:", encoded) + # print("Decoded back:", decode(encoded)) + if __name__ == "__main__": main() \ No newline at end of file diff --git a/src/morse_code/core.py b/src/morse_code/core.py index e69de29..3cf5c77 100644 --- a/src/morse_code/core.py +++ b/src/morse_code/core.py @@ -0,0 +1,18 @@ +def encode(text): + # TODO: Implement encoding logic + pass + + +def decode(morse_code): + # TODO: Implement decoding logic + pass + + +def is_valid(morse_code): + # TODO: Implement validation logic + pass + + + + + diff --git a/src/morse_code/explain.py b/src/morse_code/explain.py new file mode 100644 index 0000000..d17e65a --- /dev/null +++ b/src/morse_code/explain.py @@ -0,0 +1,3 @@ +def explain(morse_message): + # TODO: Implement explanation logic + pass \ No newline at end of file diff --git a/src/morse_code/normalize.py b/src/morse_code/normalize.py new file mode 100644 index 0000000..b793cde --- /dev/null +++ b/src/morse_code/normalize.py @@ -0,0 +1,8 @@ +def normalize_text(text): + # TODO: Implement text normalization logic + pass + + +def normalize_code(morse_code): + # TODO: Implement code normalization logic + pass \ No newline at end of file diff --git a/src/morse_code/quiz.py b/src/morse_code/quiz.py new file mode 100644 index 0000000..8cdba94 --- /dev/null +++ b/src/morse_code/quiz.py @@ -0,0 +1,3 @@ +def quiz(morse_code): + # TODO: Implement quiz logic + pass From 20619d2d9926e07cfe584e35b4f8c7648d270ff3 Mon Sep 17 00:00:00 2001 From: yiminliu2004 Date: Fri, 31 Oct 2025 01:36:36 -0400 Subject: [PATCH 09/25] add encode function --- src/morse_code/__init__.py | 10 ++++++---- src/morse_code/__main__.py | 3 ++- src/morse_code/core.py | 37 ++++++++++++++++++++++++++++++++++--- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/morse_code/__init__.py b/src/morse_code/__init__.py index 8c7b2c4..c2d0d6b 100644 --- a/src/morse_code/__init__.py +++ b/src/morse_code/__init__.py @@ -6,12 +6,14 @@ from morse_code.core import ( encode, decode, - is_valid, + is_valid +) +from morse_code.normalize import ( normalize_text, - normalize_code, - explain, - quiz + normalize_code ) +from morse_code.explain import explain +from morse_code.quiz import quiz __all__ = [ 'encode', diff --git a/src/morse_code/__main__.py b/src/morse_code/__main__.py index c5198a1..2219f5c 100644 --- a/src/morse_code/__main__.py +++ b/src/morse_code/__main__.py @@ -1,4 +1,5 @@ -from .core import encode, decode, is_valid, explain +from .core import encode, decode, is_valid +from .explain import explain def main(): diff --git a/src/morse_code/core.py b/src/morse_code/core.py index 3cf5c77..3b3a42d 100644 --- a/src/morse_code/core.py +++ b/src/morse_code/core.py @@ -1,10 +1,41 @@ def encode(text): - # TODO: Implement encoding logic - pass + """ + Convert English text to morse code. + + Args: + text: English text string to encode + + Returns: + Morse code string + """ + from morse_code.mapping import LETTER_TO_MORSE + + # Normalize the text first(delete after normalize function is implemented) + if text is None: + return None + normalized = text.upper().strip() + + # change to this: + # normalized = normalize_text(text) + + # Convert each character to morse code + result = [] + for char in normalized: + if char == ' ': + # Space between words becomes ' / ' + result.append('/') + else: + # Get morse code for character + morse_char = LETTER_TO_MORSE.get(char, '') + if morse_char: + result.append(morse_char) + + # Join with spaces between letters + return ' '.join(result) def decode(morse_code): - # TODO: Implement decoding logic + # TODO: Implement decoding logic: convert morse code to English pass From fd1215ac4718038588924d5a4194d8ca0e62836c Mon Sep 17 00:00:00 2001 From: yiminliu2004 Date: Fri, 31 Oct 2025 01:39:08 -0400 Subject: [PATCH 10/25] change project name to morseify --- src/{morse_code => morseify}/__init__.py | 8 ++++---- src/{morse_code => morseify}/__main__.py | 0 src/{morse_code => morseify}/core.py | 4 +++- src/{morse_code => morseify}/explain.py | 0 src/{morse_code => morseify}/mapping.py | 0 src/{morse_code => morseify}/normalize.py | 0 src/{morse_code => morseify}/quiz.py | 0 7 files changed, 7 insertions(+), 5 deletions(-) rename src/{morse_code => morseify}/__init__.py (69%) rename src/{morse_code => morseify}/__main__.py (100%) rename src/{morse_code => morseify}/core.py (95%) rename src/{morse_code => morseify}/explain.py (100%) rename src/{morse_code => morseify}/mapping.py (100%) rename src/{morse_code => morseify}/normalize.py (100%) rename src/{morse_code => morseify}/quiz.py (100%) diff --git a/src/morse_code/__init__.py b/src/morseify/__init__.py similarity index 69% rename from src/morse_code/__init__.py rename to src/morseify/__init__.py index c2d0d6b..7b188a8 100644 --- a/src/morse_code/__init__.py +++ b/src/morseify/__init__.py @@ -3,17 +3,17 @@ A Python package for encoding and decoding Morse code with additional utilities. """ -from morse_code.core import ( +from morseify.core import ( encode, decode, is_valid ) -from morse_code.normalize import ( +from morseify.normalize import ( normalize_text, normalize_code ) -from morse_code.explain import explain -from morse_code.quiz import quiz +from morseify.explain import explain +from morseify.quiz import quiz __all__ = [ 'encode', diff --git a/src/morse_code/__main__.py b/src/morseify/__main__.py similarity index 100% rename from src/morse_code/__main__.py rename to src/morseify/__main__.py diff --git a/src/morse_code/core.py b/src/morseify/core.py similarity index 95% rename from src/morse_code/core.py rename to src/morseify/core.py index 3b3a42d..35a830b 100644 --- a/src/morse_code/core.py +++ b/src/morseify/core.py @@ -1,3 +1,5 @@ +from morseify.mapping import LETTER_TO_MORSE + def encode(text): """ Convert English text to morse code. @@ -8,7 +10,7 @@ def encode(text): Returns: Morse code string """ - from morse_code.mapping import LETTER_TO_MORSE + # Normalize the text first(delete after normalize function is implemented) if text is None: diff --git a/src/morse_code/explain.py b/src/morseify/explain.py similarity index 100% rename from src/morse_code/explain.py rename to src/morseify/explain.py diff --git a/src/morse_code/mapping.py b/src/morseify/mapping.py similarity index 100% rename from src/morse_code/mapping.py rename to src/morseify/mapping.py diff --git a/src/morse_code/normalize.py b/src/morseify/normalize.py similarity index 100% rename from src/morse_code/normalize.py rename to src/morseify/normalize.py diff --git a/src/morse_code/quiz.py b/src/morseify/quiz.py similarity index 100% rename from src/morse_code/quiz.py rename to src/morseify/quiz.py From 47d1e03bfeda3b2d011294dc4c2b46d12a0d15ff Mon Sep 17 00:00:00 2001 From: yiminliu2004 Date: Fri, 31 Oct 2025 01:58:07 -0400 Subject: [PATCH 11/25] add decode function --- Pipfile | 2 +- Pipfile.lock | 10 +--------- src/morseify/__main__.py | 42 ++++++++++++++++++++++++++++------------ src/morseify/core.py | 40 ++++++++++++++++++++++++++++++++++---- 4 files changed, 68 insertions(+), 26 deletions(-) diff --git a/Pipfile b/Pipfile index 65722d5..7e1d224 100644 --- a/Pipfile +++ b/Pipfile @@ -5,7 +5,7 @@ name = "pypi" [packages] pytest = "*" -morse_code = {file = ".", editable = true} +morse-code = {file = ".", editable = true} [dev-packages] diff --git a/Pipfile.lock b/Pipfile.lock index 2f9e06a..7c5eb6e 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "30b7f7af999b98edc5254671e6cb948a61005dc6efd8a65a82a4b35cb500fba6" + "sha256": "8d4fce0340a506ab07fcfec2c61ecc8853335394bbda7148e9f28d01a844aded" }, "pipfile-spec": 6, "requires": { @@ -16,14 +16,6 @@ ] }, "default": { - "colorama": { - "hashes": [ - "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", - "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", - "version": "==0.4.6" - }, "iniconfig": { "hashes": [ "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", diff --git a/src/morseify/__main__.py b/src/morseify/__main__.py index 2219f5c..5490ec8 100644 --- a/src/morseify/__main__.py +++ b/src/morseify/__main__.py @@ -3,20 +3,38 @@ def main(): - print("Morse Code Demo") - text = "HELLO WORLD" - encoded = encode(text) - decoded = decode(encoded) - print(f"Original: {text}") - print(f"Encoded : {encoded}") - print(f"Decoded : {decoded}") - # print(f"Valid? {is_valid(encoded)}") - # print(f"Explain : {explain(encoded)}") - + print("Morse Code Encode/Decode Test") + # Test cases + test_cases = [ + "HELLO", + "HELLO WORLD", + "SOS", + "PYTHON", + "123", + "A1B2C3" + ] + + for text in test_cases: + encoded = encode(text) + decoded = decode(encoded) + + print(f"\nOriginal: '{text}'") + print(f"Encoded : '{encoded}'") + print(f"Decoded : '{decoded}'") + + # Check if round-trip works + if decoded == text: + print("✓ Round-trip successful!") + else: + print(f"✗ Round-trip failed! Expected: '{text}'") + + # Uncomment for interactive mode + # print("\nInteractive mode:") # text = input("Enter text to encode: ") # encoded = encode(text) - # print("Encoded:", encoded) - # print("Decoded back:", decode(encoded)) + # print(f"Encoded: {encoded}") + # decoded = decode(encoded) + # print(f"Decoded: {decoded}") if __name__ == "__main__": main() \ No newline at end of file diff --git a/src/morseify/core.py b/src/morseify/core.py index 35a830b..124361a 100644 --- a/src/morseify/core.py +++ b/src/morseify/core.py @@ -1,4 +1,5 @@ from morseify.mapping import LETTER_TO_MORSE +from morseify.mapping import MORSE_TO_LETTER def encode(text): """ @@ -10,8 +11,7 @@ def encode(text): Returns: Morse code string """ - - + # Normalize the text first(delete after normalize function is implemented) if text is None: return None @@ -37,8 +37,40 @@ def encode(text): def decode(morse_code): - # TODO: Implement decoding logic: convert morse code to English - pass + """ + Convert morse code to English text. + + Args: + morse_code: Morse code string to decode + + Returns: + English text string + """ + # check if the morse code is valid + # valid_morse = is_valid(morse_code) + + valid_morse = morse_code + + # Split morse code by spaces to get individual morse sequences + morse_words = valid_morse.split(' ') + # print(morse_words) + + result = [] + for i in morse_words: + if i == '': + # Skip empty sequences (multiple spaces) + continue + elif i == '/': + # Word separator + result.append(' ') + else: + # Look up the morse sequence in the dictionary + letter = MORSE_TO_LETTER.get(i, '') + result.append(letter) + + return ''.join(result) + + def is_valid(morse_code): From e3411b4bea4e0c205ac8d7d6ff4c46ebe1474ebc Mon Sep 17 00:00:00 2001 From: Angela Gao Date: Fri, 31 Oct 2025 14:45:02 -0400 Subject: [PATCH 12/25] add is_valid function & test file setup --- src/morseify/core.py | 25 ++++++++++++++++++++----- tests/test_is_valid.py | 2 ++ 2 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 tests/test_is_valid.py diff --git a/src/morseify/core.py b/src/morseify/core.py index 124361a..99f3ba7 100644 --- a/src/morseify/core.py +++ b/src/morseify/core.py @@ -74,10 +74,25 @@ def decode(morse_code): def is_valid(morse_code): - # TODO: Implement validation logic - pass - - - + # check if morse_code is str or empty + try: + morse_code = morse_code.strip() + except AttributeError: + return False + + if not morse_code: + return False + + #check if valid chars or sequence + validchars = {'.', '-', '/', ' '} + if any(ch not in validchars for ch in morse_code): + return False + + for seq in morse_code.split(' '): + if not seq or seq == '/': + continue + if seq not in MORSE_TO_LETTER: + return False + return True diff --git a/tests/test_is_valid.py b/tests/test_is_valid.py new file mode 100644 index 0000000..32a6635 --- /dev/null +++ b/tests/test_is_valid.py @@ -0,0 +1,2 @@ +def test_is_valid(): + assert True \ No newline at end of file From 53ed5f84c502339c5e72d5ce263a58263e710bbf Mon Sep 17 00:00:00 2001 From: phoebelh <153004907+phoebelh@users.noreply.github.com> Date: Fri, 31 Oct 2025 16:02:27 -0400 Subject: [PATCH 13/25] add: normalize_text and normalize_code function --- src/morseify/normalize.py | 56 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/src/morseify/normalize.py b/src/morseify/normalize.py index b793cde..38d3392 100644 --- a/src/morseify/normalize.py +++ b/src/morseify/normalize.py @@ -1,8 +1,56 @@ +import re +import string + def normalize_text(text): - # TODO: Implement text normalization logic - pass + """ + Clean and standardize English text before encoding to Morse. + + Args: + text (str): Input text string + + Returns: + str: Normalized text ready for encoding + """ + if not isinstance(text, str): + return "" + # convert to uppercase + text = text.upper() + + # keep only supporting text + morse_punct = ".,?/-()" + allowed_chars = string.ascii_uppercase + string.digits + ' ' + morse_punct + cleaned = ''.join(ch for ch in text if ch in allowed_chars) + + # clean multiple or leading/trailing spaces + cleaned = re.sub(r'\s+', ' ', cleaned) + cleaned = cleaned.strip() + + return cleaned def normalize_code(morse_code): - # TODO: Implement code normalization logic - pass \ No newline at end of file + """ + Clean and standardize Morse code text before decoding. + + Args: + morse_code (str): Raw Morse code string + + Returns: + str: Normalized Morse code ready for decoding + """ + if not isinstance(morse_code, str): + return "" + + # replace any tabs with a space + morse_code = morse_code.replace('\t', ' ') + + # clean multiple spaces + morse_code = re.sub(r'\s+', ' ', morse_code) + + # clean multiple slashes + morse_code = re.sub(r'/+', '/', morse_code) + + # clean any leading/trailing space or slashes + morse_code = morse_code.strip(' /') + + return morse_code From 022d60eb00d0948cc0142bc6868d598fcc9caa48 Mon Sep 17 00:00:00 2001 From: phoebelh <153004907+phoebelh@users.noreply.github.com> Date: Fri, 31 Oct 2025 16:03:14 -0400 Subject: [PATCH 14/25] add: normalize_text and normalize_code test file setup --- tests/test_normalize_code.py | 2 ++ tests/test_normalize_text.py | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 tests/test_normalize_code.py create mode 100644 tests/test_normalize_text.py diff --git a/tests/test_normalize_code.py b/tests/test_normalize_code.py new file mode 100644 index 0000000..abcd8d4 --- /dev/null +++ b/tests/test_normalize_code.py @@ -0,0 +1,2 @@ +def test_normalize_code(): + assert True \ No newline at end of file diff --git a/tests/test_normalize_text.py b/tests/test_normalize_text.py new file mode 100644 index 0000000..14519ca --- /dev/null +++ b/tests/test_normalize_text.py @@ -0,0 +1,2 @@ +def test_normalize_text(): + assert True \ No newline at end of file From 77018f887e4a6ac690b51551c46d32ec96285378 Mon Sep 17 00:00:00 2001 From: yiminliu2004 Date: Sat, 1 Nov 2025 14:36:26 -0400 Subject: [PATCH 15/25] add is_valid and normalize funcs to decode/encode --- pyproject.toml | 2 +- src/morseify/core.py | 36 +++++++++++++++++++++++++----------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4e81985..451501e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,4 +28,4 @@ package-dir = {"" = "src"} where = ["src"] [project.scripts] -morse_code = "morse_code.core:cli" +morse_code = "morseify.core:cli" diff --git a/src/morseify/core.py b/src/morseify/core.py index 99f3ba7..04c9343 100644 --- a/src/morseify/core.py +++ b/src/morseify/core.py @@ -1,5 +1,7 @@ from morseify.mapping import LETTER_TO_MORSE from morseify.mapping import MORSE_TO_LETTER +from morseify.normalize import normalize_text +from morseify.normalize import normalize_code def encode(text): """ @@ -13,12 +15,11 @@ def encode(text): """ # Normalize the text first(delete after normalize function is implemented) - if text is None: - return None - normalized = text.upper().strip() + # if text is None: + # return None + # normalized = text.upper().strip() - # change to this: - # normalized = normalize_text(text) + normalized = normalize_text(text) # Convert each character to morse code result = [] @@ -44,16 +45,17 @@ def decode(morse_code): morse_code: Morse code string to decode Returns: - English text string + English text string, or error message if morse code is invalid """ - # check if the morse code is valid - # valid_morse = is_valid(morse_code) + # Check if the morse code is valid + if not is_valid(morse_code): + return "Morse code is not valid" - valid_morse = morse_code + # If valid: normalize and decode + normalized = normalize_code(morse_code) # Split morse code by spaces to get individual morse sequences - morse_words = valid_morse.split(' ') - # print(morse_words) + morse_words = normalized.split(' ') result = [] for i in morse_words: @@ -73,7 +75,19 @@ def decode(morse_code): + + def is_valid(morse_code): + """ + Check if morse code is valid. + + Args: + morse_code: Morse code string to check if valid + + Returns: + Boolean: True if valid, False otherwise + """ + # check if morse_code is str or empty try: morse_code = morse_code.strip() From f5847a68bc91d0c063f6ba33c3bb66eb05548f5e Mon Sep 17 00:00:00 2001 From: yiminliu2004 Date: Sat, 1 Nov 2025 14:46:04 -0400 Subject: [PATCH 16/25] add cli --- pyproject.toml | 2 +- src/morseify/cli.py | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 src/morseify/cli.py diff --git a/pyproject.toml b/pyproject.toml index 451501e..6413373 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,4 +28,4 @@ package-dir = {"" = "src"} where = ["src"] [project.scripts] -morse_code = "morseify.core:cli" +morseify = "morseify.cli:cli" diff --git a/src/morseify/cli.py b/src/morseify/cli.py new file mode 100644 index 0000000..296591b --- /dev/null +++ b/src/morseify/cli.py @@ -0,0 +1,41 @@ +""" +Command-line interface for morseify. +""" + +import sys +from morseify.core import encode, decode, is_valid + + +def cli(): + """ + Command-line interface for morseify. + Auto-detects whether input is text (encode) or morse code (decode). + + Usage: + morseify "HELLO" # Encodes text to morse code + morseify ".... . .-.. .-.. ---" # Decodes morse code to text + """ + if len(sys.argv) < 2: + print("Usage: morseify ") + print("Examples:") + print(' morseify "HELLO"') + print(' morseify ".... . .-.. .-.. ---"') + sys.exit(1) + + # Join all arguments in case user passes multiple words + input_text = ' '.join(sys.argv[1:]) + + # Auto-detect: if input contains only morse characters (., -, /, space), decode it + # Otherwise, encode it + valid_morse_chars = {'.', '-', '/', ' '} + is_morse = all(char in valid_morse_chars for char in input_text) and input_text.strip() + + if is_morse and is_valid(input_text): + # It's valid morse code, decode it + result = decode(input_text) + print(result) + else: + # It's text, encode it + result = encode(input_text) + print(result) + From 0515325e748b34fa481f531c6a2a631347c1a135 Mon Sep 17 00:00:00 2001 From: gkbichara Date: Sun, 2 Nov 2025 01:11:00 -0400 Subject: [PATCH 17/25] Started quiz functionality --- src/morseify/__main__.py | 1 + src/morseify/quiz.py | 68 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/src/morseify/__main__.py b/src/morseify/__main__.py index 5490ec8..e974edb 100644 --- a/src/morseify/__main__.py +++ b/src/morseify/__main__.py @@ -1,5 +1,6 @@ from .core import encode, decode, is_valid from .explain import explain +from .quiz import quiz def main(): diff --git a/src/morseify/quiz.py b/src/morseify/quiz.py index 8cdba94..cfb0e8c 100644 --- a/src/morseify/quiz.py +++ b/src/morseify/quiz.py @@ -1,3 +1,67 @@ -def quiz(morse_code): - # TODO: Implement quiz logic +import random +import sys +from pathlib import Path + +# Add parent directory to path if running as script +if __name__ == "__main__": + sys.path.insert(0, str(Path(__file__).parent.parent)) + +try: + from morseify.core import encode, decode +except ModuleNotFoundError: + from .core import encode, decode, is_valid + +# List of sentences for the quiz +QUIZ_SENTENCES = [ + "HELLO WORLD", + "LET US TRY", + "MORSE CODE IS FUN", + "PYTHON ROCKS", + "LEARNING TAKES TIME", + "FORZA ROMA", + "SWE IS USEFUL", + "RUNNING OUT OF IDEAS", + "THIS SHOULD BE ENOUGH", + "I AM NOT VERY CREATIVE" +] + + +def quiz(sentence=None, mode=None): + """ + Interactive morse code quiz. + + Args: + sentence: Optional - specific sentence to use, or None for random + mode: Optional - 'reading' or 'writing', or None to ask + """ + if sentence is None: + selected_sentence = random.choice(QUIZ_SENTENCES) + else: + selected_sentence = sentence.upper().strip() + + + if mode is None: + mode = input("Enter the mode: 'reading' or 'writing': ") + while mode not in ['reading', 'writing']: + print() + print("Invalid mode. Please enter 'reading' or 'writing'") + print("Please try again.") + print() + mode = input("Enter the mode: 'reading' or 'writing': ") + + if mode == 'reading': + print(f"Your sentence in morse code is: {encode(selected_sentence)}") + answer = input("Enter the answer: ").upper().strip() + if answer == (selected_sentence): + print("Correct!") + else: + print("Incorrect!") + else: + print(f"Writing mode: {selected_sentence}") + + # TODO: Rest of quiz logic pass + + +if __name__ == "__main__": + quiz() \ No newline at end of file From 513d1737415ad5f0afb628315c29726e4f68b735 Mon Sep 17 00:00:00 2001 From: gkbichara Date: Sun, 2 Nov 2025 01:32:08 -0400 Subject: [PATCH 18/25] Added write function, and prettified output --- src/morseify/quiz.py | 61 ++++++++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/src/morseify/quiz.py b/src/morseify/quiz.py index cfb0e8c..cf5821f 100644 --- a/src/morseify/quiz.py +++ b/src/morseify/quiz.py @@ -7,7 +7,7 @@ sys.path.insert(0, str(Path(__file__).parent.parent)) try: - from morseify.core import encode, decode + from morseify.core import encode, decode, is_valid except ModuleNotFoundError: from .core import encode, decode, is_valid @@ -40,27 +40,56 @@ def quiz(sentence=None, mode=None): selected_sentence = sentence.upper().strip() + # Ask for mode if not provided if mode is None: - mode = input("Enter the mode: 'reading' or 'writing': ") + print("\n" + "=" * 60) + print("MORSE CODE QUIZ") + print("=" * 60) + print("Choose your mode:") + print("'reading' - Decode morse code → text") + print("'writing' - Encode text → morse code") + print() + mode = input("Enter the mode ('reading' or 'writing'): ").strip().lower() + while mode not in ['reading', 'writing']: - print() - print("Invalid mode. Please enter 'reading' or 'writing'") - print("Please try again.") - print() - mode = input("Enter the mode: 'reading' or 'writing': ") + print("\nInvalid mode!") + print("Please enter 'reading' or 'writing'") + mode = input("\nEnter the mode: ").strip().lower() + print("\n" + "=" * 60) if mode == 'reading': - print(f"Your sentence in morse code is: {encode(selected_sentence)}") - answer = input("Enter the answer: ").upper().strip() - if answer == (selected_sentence): - print("Correct!") + print("READING MODE: Decode morse code → text") + print("=" * 60) + morse_to_decode = encode(selected_sentence) + print(f"\nMorse code: {morse_to_decode}") + print() + answer = input("Your answer: ").upper().strip() + + if answer == selected_sentence: + print("\nCorrect! Well done!") else: - print("Incorrect!") - else: - print(f"Writing mode: {selected_sentence}") + print("\nIncorrect!") + + else: # writing mode + print("WRITING MODE: Encode text → morse code") + print("=" * 60) + print(f"\nText to encode: {selected_sentence}") + print() + + answer = input("Your answer: ").strip() + while not is_valid(answer): + print("\nInvalid morse code format!") + print("Please use only dots (.), dashes (-), spaces, and slashes (/)") + print("Example: ... --- ... (for SOS)") + answer = input("\nYour answer: ").strip() + + # Now check if the valid morse code is correct + if answer == encode(selected_sentence): + print("\nCorrect! Well done!") + else: + print("\nIncorrect!") - # TODO: Rest of quiz logic - pass + print("=" * 60) if __name__ == "__main__": From 300d411f4cee2ed66b362ccb494f0988db1be0ab Mon Sep 17 00:00:00 2001 From: gkbichara Date: Sun, 2 Nov 2025 01:45:26 -0400 Subject: [PATCH 19/25] Finished quiz functionality --- src/morseify/quiz.py | 70 +++++++++++++++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 17 deletions(-) diff --git a/src/morseify/quiz.py b/src/morseify/quiz.py index cf5821f..da116b5 100644 --- a/src/morseify/quiz.py +++ b/src/morseify/quiz.py @@ -63,31 +63,67 @@ def quiz(sentence=None, mode=None): morse_to_decode = encode(selected_sentence) print(f"\nMorse code: {morse_to_decode}") print() - answer = input("Your answer: ").upper().strip() - if answer == selected_sentence: - print("\nCorrect! Well done!") - else: - print("\nIncorrect!") + # Loop until correct or user gives up + while True: + answer = input("Your answer: ").upper().strip() + + if answer == selected_sentence: + print("\nCorrect! Well done!") + break + else: + print("\nIncorrect!") + retry = input("Try again? (yes/no): ").strip().lower() + + if retry == 'yes': + continue # Try again + else: # 'no' or anything else means give up + print("\n" + "-" * 60) + print("ANSWER REVEALED") + print("-" * 60) + print(f"Your answer: {answer}") + print(f"Correct answer: {selected_sentence}") + print(f"\nThe morse code '{morse_to_decode}' translates to '{selected_sentence}'") + print("-" * 60) + break else: # writing mode print("WRITING MODE: Encode text → morse code") print("=" * 60) print(f"\nText to encode: {selected_sentence}") print() + correct_morse = encode(selected_sentence) - answer = input("Your answer: ").strip() - while not is_valid(answer): - print("\nInvalid morse code format!") - print("Please use only dots (.), dashes (-), spaces, and slashes (/)") - print("Example: ... --- ... (for SOS)") - answer = input("\nYour answer: ").strip() - - # Now check if the valid morse code is correct - if answer == encode(selected_sentence): - print("\nCorrect! Well done!") - else: - print("\nIncorrect!") + # Loop until correct or user gives up + while True: + answer = input("Your answer: ").strip() + + # Validate morse code format first + while not is_valid(answer): + print("\nInvalid morse code format!") + print("Please use only dots (.), dashes (-), spaces, and slashes (/)") + print("Example: ... --- ... (for SOS)") + answer = input("\nYour answer: ").strip() + + # Check if correct + if answer == correct_morse: + print("\nCorrect! Well done!") + break + else: + print("\nIncorrect!") + retry = input("Try again? (yes/no): ").strip().lower() + + if retry == 'yes': + continue # Try again + else: # 'no' or anything else means give up + print("\n" + "-" * 60) + print("ANSWER REVEALED") + print("-" * 60) + print(f"Your answer: {answer}") + print(f"Correct answer: {correct_morse}") + print(f"\n'{selected_sentence}' in morse code is: {correct_morse}") + print("-" * 60) + break print("=" * 60) From 6f0a20e31bd4d907f9558fc35688ad30672f54b3 Mon Sep 17 00:00:00 2001 From: phoebelh <153004907+phoebelh@users.noreply.github.com> Date: Sun, 2 Nov 2025 17:46:36 -0500 Subject: [PATCH 20/25] update: readme file for overview and installation instruction template --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index 6022e0e..2272b65 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,21 @@ # Python Package Exercise An exercise to create a Python package, build it, test it, distribute it, and use it. See [instructions](./instructions.md) for details. + +## morseify - Overview +morseify is a lightweight Python package that brings the world of Morse code to anyone curious about how digital communication began. It offers intuitive encode and decode functionality to translate between English text and Morse code, along with built-in tools for text normalization and message validation. + +For a more interactive experience, morseify also includes a quiz mode that generates random Morse code challenges for users to decode, making it both an educational and entertaining way to explore the fundamentals of encoded communication. + +## Features +- Encode English text to Morse code +- Decode Morse code to English text +- Normalize text and Morse sequences +- Validate Morse message formats +- Explain message steps +- Quiz mode to test Morse knowledge + +## Installation / Setup + + From 56cf1b24c67be55335db73e738e8dbf8cce4109c Mon Sep 17 00:00:00 2001 From: yiminliu2004 Date: Sun, 2 Nov 2025 00:57:57 -0400 Subject: [PATCH 21/25] add tests for decode function --- tests/test_decode.py | 54 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/tests/test_decode.py b/tests/test_decode.py index 26af617..b5c6997 100644 --- a/tests/test_decode.py +++ b/tests/test_decode.py @@ -1,2 +1,52 @@ -def test_encode(): - assert True \ No newline at end of file +from morseify.core import decode + + +def test_decode_single_letter(): + """Test decoding a single letter.""" + assert decode(".-") == "A" + assert decode("-") == "T" + assert decode("...") == "S" + + +def test_decode_word(): + """Test decoding a word.""" + assert decode(".... . .-.. .-.. ---") == "HELLO" + assert decode("... --- ...") == "SOS" + + +def test_decode_multiple_words(): + """Test decoding multiple words with separator.""" + assert decode(".... . .-.. .-.. --- / .-- --- .-. .-.. -..") == "HELLO WORLD" + assert decode("... --- ... / .... . .-.. .--.") == "SOS HELP" + + +def test_decode_numbers(): + """Test decoding numbers.""" + assert decode(".---- ..--- ...--") == "123" + assert decode("-----") == "0" + + +def test_decode_invalid_morse_code(): + """Test decoding invalid morse code returns error message.""" + assert decode("---.") == "Morse code is not valid" # Invalid sequence not in mapping + assert decode("ABC") == "Morse code is not valid" # Contains invalid characters + assert decode("....X") == "Morse code is not valid" # Contains invalid character + assert decode("") == "Morse code is not valid" # Empty string + assert decode(" ") == "Morse code is not valid" # Only spaces + + +def test_decode_mixed_valid_invalid(): + """Test decoding morse code with invalid sequences.""" + assert decode(".... . .-.. .-.. --- ---.") == "Morse code is not valid" # Has invalid sequence + + +def test_decode_with_punctuation(): + """Test decoding morse code with punctuation.""" + assert decode(".... . .-.. .-.. --- .-.-.-") == "HELLO." + assert decode("-- ..- .-.. - .. .--. .-.. .") == "MULTIPLE" + + +def test_decode_normalized_input(): + """Test decoding already normalized morse code.""" + # decode should handle normalization internally + assert decode(" .... . .-.. .-.. --- ") == "HELLO" # Extra spaces \ No newline at end of file From 1a47d21e805750051b75aa0dc5d68833d66bde74 Mon Sep 17 00:00:00 2001 From: yiminliu2004 Date: Sun, 2 Nov 2025 16:28:05 -0500 Subject: [PATCH 22/25] add more tests for decode --- tests/test_decode.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/test_decode.py b/tests/test_decode.py index b5c6997..1a5fe4d 100644 --- a/tests/test_decode.py +++ b/tests/test_decode.py @@ -25,6 +25,9 @@ def test_decode_numbers(): assert decode(".---- ..--- ...--") == "123" assert decode("-----") == "0" +def test_decode_extra_spaces(): + """Test decoding morse code with extra spaces.""" + assert decode(" ... --- ... ") == "SOS" def test_decode_invalid_morse_code(): """Test decoding invalid morse code returns error message.""" @@ -49,4 +52,22 @@ def test_decode_with_punctuation(): def test_decode_normalized_input(): """Test decoding already normalized morse code.""" # decode should handle normalization internally - assert decode(" .... . .-.. .-.. --- ") == "HELLO" # Extra spaces \ No newline at end of file + assert decode(" .... . .-.. .-.. --- ") == "HELLO" # Extra spaces + + + +def test_decode_punctuation_only(): + """Test decoding morse code with only punctuation.""" + assert decode(".-.-.-") == "." # period + assert decode("--..--") == "," # comma + assert decode("..--..") == "?" # question mark + assert decode("-..-.") == "/" # slash + assert decode("-....-") == "-" # hyphen + + +def test_decode_with_parentheses(): + """Test decoding morse code with parentheses.""" + assert decode("-.--. -.--.-") == "()" + assert decode(".... . .-.. .-.. --- -.--.") == "HELLO(" + assert decode("-.--.- .-- --- .-. .-.. -..") == ")WORLD" + From 1367bc06800dcdceb224a961e040ad839cf88403 Mon Sep 17 00:00:00 2001 From: yiminliu2004 Date: Sun, 2 Nov 2025 17:43:57 -0500 Subject: [PATCH 23/25] add decode alphabet letter test --- tests/test_decode.py | 25 ++++++++++++++++++++++++- tests/test_encode.py | 2 +- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/tests/test_decode.py b/tests/test_decode.py index 1a5fe4d..7a5d4cb 100644 --- a/tests/test_decode.py +++ b/tests/test_decode.py @@ -4,8 +4,31 @@ def test_decode_single_letter(): """Test decoding a single letter.""" assert decode(".-") == "A" - assert decode("-") == "T" + assert decode("-...") == "B" + assert decode("-.-.") == "C" + assert decode("-..") == "D" + assert decode(".") == "E" + assert decode("..-.") == "F" + assert decode("--.") == "G" + assert decode("....") == "H" + assert decode("..") == "I" + assert decode(".---") == "J" + assert decode("-.-") == "K" + assert decode(".-..") == "L" + assert decode("--") == "M" + assert decode("-.") == "N" + assert decode("---") == "O" + assert decode(".--.") == "P" + assert decode("--.-") == "Q" + assert decode(".-.") == "R" assert decode("...") == "S" + assert decode("-") == "T" + assert decode("..-") == "U" + assert decode("...-") == "V" + assert decode(".--") == "W" + assert decode("-..-") == "X" + assert decode("-.--") == "Y" + assert decode("--..") == "Z" def test_decode_word(): diff --git a/tests/test_encode.py b/tests/test_encode.py index 03bb3d5..26af617 100644 --- a/tests/test_encode.py +++ b/tests/test_encode.py @@ -1,2 +1,2 @@ -def test_decode(): +def test_encode(): assert True \ No newline at end of file From b4f46a454dcaf91e509bf1548b388c0d5d17ffea Mon Sep 17 00:00:00 2001 From: yiminliu2004 Date: Sun, 2 Nov 2025 17:51:11 -0500 Subject: [PATCH 24/25] add tests for encode function --- tests/test_encode.py | 99 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 2 deletions(-) diff --git a/tests/test_encode.py b/tests/test_encode.py index 26af617..1b0b633 100644 --- a/tests/test_encode.py +++ b/tests/test_encode.py @@ -1,2 +1,97 @@ -def test_encode(): - assert True \ No newline at end of file +from morseify.core import encode, decode + + +def test_encode_single_letter(): + """Test encoding a single letter.""" + assert encode("A") == ".-" + assert encode("B") == "-..." + assert encode("C") == "-.-." + assert encode("D") == "-.." + assert encode("E") == "." + assert encode("F") == "..-." + assert encode("G") == "--." + assert encode("H") == "...." + assert encode("I") == ".." + assert encode("J") == ".---" + assert encode("K") == "-.-" + assert encode("L") == ".-.." + assert encode("M") == "--" + assert encode("N") == "-." + assert encode("O") == "---" + assert encode("P") == ".--." + assert encode("Q") == "--.-" + assert encode("R") == ".-." + assert encode("S") == "..." + assert encode("T") == "-" + assert encode("U") == "..-" + assert encode("V") == "...-" + assert encode("W") == ".--" + assert encode("X") == "-..-" + assert encode("Y") == "-.--" + assert encode("Z") == "--.." + + +def test_encode_lowercase(): + """Test encoding lowercase letters (should convert to uppercase first).""" + assert encode("a") == ".-" + assert encode("hello") == ".... . .-.. .-.. ---" + assert encode("sos") == "... --- ..." + + +def test_encode_word(): + """Test encoding an uppercase word.""" + assert encode("HELLO") == ".... . .-.. .-.. ---" + assert encode("SOS") == "... --- ..." + +def test_encode_mixed_case(): + """Test encoding text with mixed case.""" + assert encode("Hello") == ".... . .-.. .-.. ---" + assert encode("World") == ".-- --- .-. .-.. -.." + assert encode("SoS") == "... --- ..." + + +def test_encode_multiple_words(): + """Test encoding multiple words with separator.""" + assert encode("HELLO WORLD") == ".... . .-.. .-.. --- / .-- --- .-. .-.. -.." + assert encode("SOS HELP") == "... --- ... / .... . .-.. .--." + + +def test_encode_numbers(): + """Test encoding numbers.""" + assert encode("123") == ".---- ..--- ...--" + assert encode("0") == "-----" + assert encode("0123456789") == "----- .---- ..--- ...-- ....- ..... -.... --... ---.. ----." + + +def test_encode_with_punctuation(): + """Test encoding text with punctuation.""" + assert encode("HELLO.") == ".... . .-.. .-.. --- .-.-.-" + assert encode("SOS?") == "... --- ... ..--.." + assert encode("A,B") == ".- --..-- -..." + + +def test_encode_with_parentheses(): + """Test encoding text with parentheses.""" + assert encode("()") == "-.--. -.--.-" + assert encode("HELLO(WORLD)") == ".... . .-.. .-.. --- -.--. .-- --- .-. .-.. -.. -.--.-" + assert encode("(A)") == "-.--. .- -.--.-" + + +def test_encode_with_extra_spaces(): + """Test encoding text with extra spaces.""" + assert encode(" HELLO ") == ".... . .-.. .-.. ---" + assert encode("A B") == ".- / -..." + assert encode(" SOS ") == "... --- ..." + + +def test_encode_only_spaces(): + """Test encoding only spaces.""" + assert encode(" ") == "" + assert encode(" ") == "" + assert encode(" ") == "" + + +def test_encode_empty_string(): + """Test encoding empty string.""" + assert encode("") == "" + From 9eb91e7f43467452202aaca7d4554f329bc0a124 Mon Sep 17 00:00:00 2001 From: yiminliu2004 Date: Sun, 2 Nov 2025 18:00:09 -0500 Subject: [PATCH 25/25] add test for encode+decode roundtrip --- tests/test_encode.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/test_encode.py b/tests/test_encode.py index 1b0b633..be6716b 100644 --- a/tests/test_encode.py +++ b/tests/test_encode.py @@ -95,3 +95,47 @@ def test_encode_empty_string(): """Test encoding empty string.""" assert encode("") == "" + +def test_encode_decode_roundtrip(): + """Test that encoding then decoding returns the original text.""" + texts = [ + "A", + "HELLO", + "HELLO WORLD", + "123", + "SOS", + "HELLO.", + "SOS?", + "()", + "HELLO(WORLD)", + "0123456789" + ] + + for text in texts: + encoded = encode(text) + decoded = decode(encoded) + assert decoded == text, f"Round trip failed for '{text}': {encoded} -> {decoded}" + + +def test_decode_encode_roundtrip(): + """Test that decoding then encoding returns the original morse code.""" + morse_codes = [ + ".-", + "-", + "...", + ".... . .-.. .-.. ---", + "... --- ...", + ".... . .-.. .-.. --- / .-- --- .-. .-.. -..", + ".---- ..--- ...--", + "-----", + ".... . .-.. .-.. --- .-.-.-", + "... --- ... ..--..", + "-.--. -.--.-", + ".- .-.-.- -..." + ] + + for morse_code in morse_codes: + decoded = decode(morse_code) + encoded = encode(decoded) + assert encoded == morse_code, f"Round trip failed for '{morse_code}': {decoded} -> {encoded}" + \ No newline at end of file