From 1091560aa9705642f03d40c14a4ea9c3f100f6f5 Mon Sep 17 00:00:00 2001 From: Maather AlJabri <85490284+aljab017@users.noreply.github.com> Date: Mon, 29 Apr 2024 14:09:08 +0400 Subject: [PATCH 01/11] add pcm --- README.md | 30 ++++++ .../measurement_converter_api.cpython-312.pyc | Bin 0 -> 2156 bytes controller/measurement_converter_api.py | 36 +++++++ main.py | 10 ++ measurement_conversion.py | 0 .../measurement_converter.cpython-312.pyc | Bin 0 -> 2590 bytes .../measurement_converter_db.cpython-312.pyc | Bin 0 -> 2573 bytes models/measurement_converter.py | 90 ++++++++++++++++++ models/measurement_converter_db.py | 41 ++++++++ ...easurement_converter_tests.cpython-312.pyc | Bin 0 -> 2397 bytes models/tests/measurement_converter_tests.py | 39 ++++++++ 11 files changed, 246 insertions(+) create mode 100644 README.md create mode 100644 controller/__pycache__/measurement_converter_api.cpython-312.pyc create mode 100644 controller/measurement_converter_api.py create mode 100644 main.py create mode 100644 measurement_conversion.py create mode 100644 models/__pycache__/measurement_converter.cpython-312.pyc create mode 100644 models/__pycache__/measurement_converter_db.cpython-312.pyc create mode 100644 models/measurement_converter.py create mode 100644 models/measurement_converter_db.py create mode 100644 models/tests/__pycache__/measurement_converter_tests.cpython-312.pyc create mode 100644 models/tests/measurement_converter_tests.py diff --git a/README.md b/README.md new file mode 100644 index 0000000..c366fbb --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +## Package Conversion API Overview +The Package Conversion API functions is a web-based service designed to facilitate the conversion of package measurements as per user specifications. It offers endpoints specifically for converting measurements and accessing conversion records. + +## Features +- **Seamless Handling of Sequence Input:** Capable of processing sequences comprising characters and underscores, facilitating smooth conversion. +- **Optimized Conversion Algorithms:** Incorporates streamlined algorithms for the swift transformation of input sequences into lists of measurements. +- **Transparent and Flexible:** Exhibits clarity in design and is easily customizable, allowing for seamless integration of supplementary features. + +## Installation +Clone the repository: +``` +git clone https://github.com/aljab017/PackageMeasurementConversionAPI.git +``` + +## Install dependencies: +``` +pip install -r requirements.txt +``` + +## Usage +- Start the server: +```python main.py``` +- Convert measurement: +```GET http://127.0.0.1:8080/convert_measurements?input_str=INPUT STRING HERE``` +- Get conversion history +```GET http://127.0.0.1:8080/get_history``` +## Testing + +- To run tests: +``` python -m unittest .\models\tests\measurement_converter_tests.py ``` \ No newline at end of file diff --git a/controller/__pycache__/measurement_converter_api.cpython-312.pyc b/controller/__pycache__/measurement_converter_api.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..20bd7386099e70d1037f0c8f9a8430a74b4da54a GIT binary patch literal 2156 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 literal 0 HcmV?d00001 diff --git a/models/measurement_converter.py b/models/measurement_converter.py new file mode 100644 index 0000000..086d83c --- /dev/null +++ b/models/measurement_converter.py @@ -0,0 +1,90 @@ +# from measurement_converter_db import save_to_history + +class MeasurementConverter: + def __init__(self, string=None): + self.string = string + + def get_letter_value(self, letter): + """ + Get the numerical value of a letter. + """ + if letter == 'z': + return 26 + else: + return ord(letter) - 96 + + def pmc(self, string): + """ + Parse the string and calculate the sum of letter values for each segment. + """ + self.string = string + result = [] + index = 0 + try: + # Iterate through the string + while index < len(string): + if string[index].isalpha(): + count = 0 + # If the letter is z, add 26 to the count until you find the first non-z letter/char + if string[index] == 'z': + while string[index] == 'z': + count += self.get_letter_value(string[index]) + index += 1 + if string[index].isalpha(): + count += self.get_letter_value(string[index]) + index += 1 + else: + count = self.get_letter_value(string[index]) + index += 1 + + sum_value = 0 + i = index # i determains the start of the segment while index is a pointer to the current character + range = index + count + + # Extract the sum of letter values for the segment + while i < (range): + if string[i].isalpha(): + if string[i] == 'z': + range += 1 + while string[i] == 'z': + sum_value += self.get_letter_value(string[i]) + index += 1 + i += 1 + if string[i].isalpha(): + sum_value += self.get_letter_value(string[i]) + else: + sum_value += self.get_letter_value(string[i]) + i += 1 + + result.append(sum_value) + index += count + + elif string[index] == '_': + # Append 0 and break the loop if the first character is '_' + result.append(0) + break + + else: + # For any other character that is not a letter or '_', return "Invalid string input" + return "Invalid string input" + + except: + return "Invalid string input" + return result + +# Test cases +# mc = MeasurementConverter() +# print(mc.pmc("dz_a_aazzaaa")) # Output: [28, 53, 1] +# print(mc.pmc("za_a_a_a_a_a_a_a_a_a_a_a_a_azaaa")) # Output: [40, 1] +# print(mc.pmc("aa")) # Output: [1] +# print(mc.pmc("abbcc")) # Output: [2, 6] +# print(mc.pmc("a_")) # Output: [0] +# print(mc.pmc("abcdabcdab")) # Output: [2, 7, 7] +# print(mc.pmc("abcdabcdab_")) # Output: [2, 7, 7, 0] +# print(mc.pmc("zdaaaaaaaabaaaaaaaabaaaaaaaabbaa")) # Output: [34] +# print(mc.pmc("za_a_a_a_a_a_a_a_a_a_a_a_a_azaaa")) # Output: [40, 1] +# print(mc.pmc("zza_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_")) # Output: [26] +# print(mc.pmc("__")) # [0] +# print(mc.pmc("_zzzb")) # [0] +# print(mc.pmc("_")) # [0] +# print(mc.pmc("+")) # Invalid output diff --git a/models/measurement_converter_db.py b/models/measurement_converter_db.py new file mode 100644 index 0000000..01ecace --- /dev/null +++ b/models/measurement_converter_db.py @@ -0,0 +1,41 @@ +import sqlite3 +import json + +class MeasurementConverterDB(object): + def __init__(self, db_name='history.db'): + self.db_name = db_name + self.conn = sqlite3.connect(self.db_name) + self.cursor = self.conn.cursor() + self.create_table() + + def create_table(self): + """ + Create the table for the history of the measurements. + """ + self.cursor.execute(''' + CREATE TABLE IF NOT EXISTS history ( + id INTEGER PRIMARY KEY, + input TEXT, + output TEXT, + timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) + ''') + self.conn.commit() + + def save_to_history(self, input_str, output_str): + """ + Save the input and output to the history table. + """ + output_str = str(output_str) + self.cursor.execute('INSERT INTO history (input, output) VALUES (?, ?)', (input_str, output_str)) + self.conn.commit() + + def get_history(self): + """ + Get the history of the measurements from the database. + """ + self.cursor.execute("SELECT input, output FROM history ORDER BY timestamp DESC") + rows = self.cursor.fetchall() + history = [{'input': row[0], 'output': row[1]} for row in rows] + return history + diff --git a/models/tests/__pycache__/measurement_converter_tests.cpython-312.pyc b/models/tests/__pycache__/measurement_converter_tests.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ebcacf94e31e2c78527eb5f25fd4a4a154d849bf GIT binary patch literal 2397 zcmd6oO-v+36o9Mx2O4O=S;mD$h8gs_TUF<* zRrTK2uYRnruO-lan!7&N#1rxdD&+>c*N$xHR*6bfnj$gmnG{VkF@_R`yh~Jeg{YiH z=Bonx6Ws>uD=|*vRsQ}pLd-Bjz*anA6b#j>Z>u+`uTYYsIVuSyRHr2Bh9@<}%9>hQ zGwiX9@jx?e%}fL{y)KwZj@m(8g*9SSB{4>&DL1paP%FBRg#1VtkY$xGD)hkDwky73BOL&sw7Qv%Zy!_YX|2hWQmr~RPM*gr+tJh zvrA;Y9AWTYZZ@vzwT+;kuL%Yxx+S{AUID%AbBPIb#y6tm%K?t$swKhcs*MH>j~soV zq;xfEWQ?d2wQN&2l2%W}LgHLTQCwb`olPX%T4gq&`hR#Vm+*8YT%d%RmRJ*$Si=39 z4Jh!{)MMV|O~puRE}PN}w@$Gv$kjWGStVs+P+WE)oq%;XOH0kUB5Xu0zA$zp{vmj>;zNCd{cpy{Gl?v+V8s&|RZHoH*1eF6Pb-Q0N>V$O zS4+Bm8v^W_Waj}rl zhvZNoEhBkxzx9;DX0{@N;x6q~OVL((CkHF26B-4|cl z6WeygwqGKB#mK;3WN0Tc^hDgc_q4GXx${H!_D3J@+>PyupZvw*gd+tHKJVvQ41?i$ z1{XeedD(HCS(nNZTWW*&mIgtXbvS|w7mQkQyh(d|cXAa|RKn~Cl4jeL#I z-tbq;#n5Yr-psk^30tA3b;Zc|mcBiG@B7rQ_yLkPLrpy9+2nl#Z;r|P*R`<+Y9sR> zYa?^AHmc0VaaHVvs>n*5^8#18;n&5}6_IyYD1jh=DeAavU;lu^b#=V`suQ00$E2uN z#HRdYvwpH00>43l^Ye^V5K5Y#=CGIMvROIV-4`eO1#?8ungHRYymchs;OF&LvHA64 zs0$OTo}1W)t;L<;iDKmL_ItCtVgj?O`dOWls$4;q4JEC~vRf<5P(8CL9E-Ay_1u4B zVyw+h6p%Xdn0QEdr!(<>^8^koV!E`}d51F&tCi&hU0|9Ts;vbZ++JuDs6^zqIGV zh<~tK=3Ag*5w&iDIAAHIzmdk@$<1d~?Np_O&-SkN?p*DCMo>GrO$jIFouAn&`&{VZ Voi8RopDc|2%C#S`glqNO{|zWoQg8qO literal 0 HcmV?d00001 diff --git a/models/tests/measurement_converter_tests.py b/models/tests/measurement_converter_tests.py new file mode 100644 index 0000000..6d6bc40 --- /dev/null +++ b/models/tests/measurement_converter_tests.py @@ -0,0 +1,39 @@ +import unittest +from models.measurement_converter import MeasurementConverter + + +class TestMeasurementConverter(unittest.TestCase): + + def test_non_z_strings(self): + """ + Test valid non z strings. + """ + non_z_inputs = ["aa", "abbcc", "abcdabcdab", "a_" ] + non_z_outputs = [[1], [2, 6], [2, 7, 7], [0]] + + for i in range(len(non_z_inputs)): + self.assertEqual(MeasurementConverter().pmc(non_z_inputs[i]), non_z_outputs[i]) + + + def test_z_strings(self): + """ + Test valid z strings. + """ + z_inputs = ["dz_a_aazzaaa", "za_a_a_a_a_a_a_a_a_a_a_a_a_azaaa", "zza_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_", "_zzzb", "_"] + z_outputs = [[28, 53, 1], [40, 1], [26], [0], [0]] + + for i in range(len(z_inputs)): + self.assertEqual(MeasurementConverter().pmc(z_inputs[i]), z_outputs[i]) + + def test_invalid_strings(self): + """ + Test invalid strings. + """ + invalid_inputs = ["abc", "aaa", "z", "123", "+!@#"] + + for i in range(len(invalid_inputs)): + self.assertEqual(MeasurementConverter().pmc(invalid_inputs[i]), "Invalid string input") + + +if __name__ == '__main__': + unittest.main(verbosity=2) \ No newline at end of file From dc560fccfb90407c1af220bbffb86c8c38d771d8 Mon Sep 17 00:00:00 2001 From: Maather AlJabri <85490284+aljab017@users.noreply.github.com> Date: Mon, 29 Apr 2024 14:12:27 +0400 Subject: [PATCH 02/11] add reqs --- requirements.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..cdd578d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +CherryPy==18.9.0 +requests==2.31.0 +setuptools==69.2.0 \ No newline at end of file From e14929ca0277c33c033f609677ca4739ec2d39a2 Mon Sep 17 00:00:00 2001 From: Maather AlJabri <85490284+aljab017@users.noreply.github.com> Date: Mon, 29 Apr 2024 14:16:15 +0400 Subject: [PATCH 03/11] remove file --- measurement_conversion.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 measurement_conversion.py diff --git a/measurement_conversion.py b/measurement_conversion.py deleted file mode 100644 index e69de29..0000000 From 22df15607a1aaefe2c26cd160c2e1b0f8c8f6cd7 Mon Sep 17 00:00:00 2001 From: Maather AlJabri <85490284+aljab017@users.noreply.github.com> Date: Mon, 29 Apr 2024 14:23:32 +0400 Subject: [PATCH 04/11] clean up --- models/measurement_converter.py | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/models/measurement_converter.py b/models/measurement_converter.py index 086d83c..3156a52 100644 --- a/models/measurement_converter.py +++ b/models/measurement_converter.py @@ -1,5 +1,3 @@ -# from measurement_converter_db import save_to_history - class MeasurementConverter: def __init__(self, string=None): self.string = string @@ -71,20 +69,3 @@ def pmc(self, string): except: return "Invalid string input" return result - -# Test cases -# mc = MeasurementConverter() -# print(mc.pmc("dz_a_aazzaaa")) # Output: [28, 53, 1] -# print(mc.pmc("za_a_a_a_a_a_a_a_a_a_a_a_a_azaaa")) # Output: [40, 1] -# print(mc.pmc("aa")) # Output: [1] -# print(mc.pmc("abbcc")) # Output: [2, 6] -# print(mc.pmc("a_")) # Output: [0] -# print(mc.pmc("abcdabcdab")) # Output: [2, 7, 7] -# print(mc.pmc("abcdabcdab_")) # Output: [2, 7, 7, 0] -# print(mc.pmc("zdaaaaaaaabaaaaaaaabaaaaaaaabbaa")) # Output: [34] -# print(mc.pmc("za_a_a_a_a_a_a_a_a_a_a_a_a_azaaa")) # Output: [40, 1] -# print(mc.pmc("zza_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_")) # Output: [26] -# print(mc.pmc("__")) # [0] -# print(mc.pmc("_zzzb")) # [0] -# print(mc.pmc("_")) # [0] -# print(mc.pmc("+")) # Invalid output From a7e40d4e442a74cb43a8ea02f3f774275427a040 Mon Sep 17 00:00:00 2001 From: Maather AlJabri <85490284+aljab017@users.noreply.github.com> Date: Wed, 1 May 2024 08:48:54 +0400 Subject: [PATCH 05/11] add .gitignore --- .gitignore | 2 ++ .../measurement_converter_api.cpython-312.pyc | Bin 2156 -> 0 bytes .../measurement_converter.cpython-312.pyc | Bin 2590 -> 0 bytes .../measurement_converter_db.cpython-312.pyc | Bin 2573 -> 0 bytes .../measurement_converter_tests.cpython-312.pyc | Bin 2397 -> 0 bytes 5 files changed, 2 insertions(+) create mode 100644 .gitignore delete mode 100644 controller/__pycache__/measurement_converter_api.cpython-312.pyc delete mode 100644 models/__pycache__/measurement_converter.cpython-312.pyc delete mode 100644 models/__pycache__/measurement_converter_db.cpython-312.pyc delete mode 100644 models/tests/__pycache__/measurement_converter_tests.cpython-312.pyc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8ae8ce5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +.idea/ diff --git a/controller/__pycache__/measurement_converter_api.cpython-312.pyc b/controller/__pycache__/measurement_converter_api.cpython-312.pyc deleted file mode 100644 index 20bd7386099e70d1037f0c8f9a8430a74b4da54a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2156 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 diff --git a/models/tests/__pycache__/measurement_converter_tests.cpython-312.pyc b/models/tests/__pycache__/measurement_converter_tests.cpython-312.pyc deleted file mode 100644 index ebcacf94e31e2c78527eb5f25fd4a4a154d849bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2397 zcmd6oO-v+36o9Mx2O4O=S;mD$h8gs_TUF<* zRrTK2uYRnruO-lan!7&N#1rxdD&+>c*N$xHR*6bfnj$gmnG{VkF@_R`yh~Jeg{YiH z=Bonx6Ws>uD=|*vRsQ}pLd-Bjz*anA6b#j>Z>u+`uTYYsIVuSyRHr2Bh9@<}%9>hQ zGwiX9@jx?e%}fL{y)KwZj@m(8g*9SSB{4>&DL1paP%FBRg#1VtkY$xGD)hkDwky73BOL&sw7Qv%Zy!_YX|2hWQmr~RPM*gr+tJh zvrA;Y9AWTYZZ@vzwT+;kuL%Yxx+S{AUID%AbBPIb#y6tm%K?t$swKhcs*MH>j~soV zq;xfEWQ?d2wQN&2l2%W}LgHLTQCwb`olPX%T4gq&`hR#Vm+*8YT%d%RmRJ*$Si=39 z4Jh!{)MMV|O~puRE}PN}w@$Gv$kjWGStVs+P+WE)oq%;XOH0kUB5Xu0zA$zp{vmj>;zNCd{cpy{Gl?v+V8s&|RZHoH*1eF6Pb-Q0N>V$O zS4+Bm8v^W_Waj}rl zhvZNoEhBkxzx9;DX0{@N;x6q~OVL((CkHF26B-4|cl z6WeygwqGKB#mK;3WN0Tc^hDgc_q4GXx${H!_D3J@+>PyupZvw*gd+tHKJVvQ41?i$ z1{XeedD(HCS(nNZTWW*&mIgtXbvS|w7mQkQyh(d|cXAa|RKn~Cl4jeL#I z-tbq;#n5Yr-psk^30tA3b;Zc|mcBiG@B7rQ_yLkPLrpy9+2nl#Z;r|P*R`<+Y9sR> zYa?^AHmc0VaaHVvs>n*5^8#18;n&5}6_IyYD1jh=DeAavU;lu^b#=V`suQ00$E2uN z#HRdYvwpH00>43l^Ye^V5K5Y#=CGIMvROIV-4`eO1#?8ungHRYymchs;OF&LvHA64 zs0$OTo}1W)t;L<;iDKmL_ItCtVgj?O`dOWls$4;q4JEC~vRf<5P(8CL9E-Ay_1u4B zVyw+h6p%Xdn0QEdr!(<>^8^koV!E`}d51F&tCi&hU0|9Ts;vbZ++JuDs6^zqIGV zh<~tK=3Ag*5w&iDIAAHIzmdk@$<1d~?Np_O&-SkN?p*DCMo>GrO$jIFouAn&`&{VZ Voi8RopDc|2%C#S`glqNO{|zWoQg8qO From a774b5008cf64ea635d6533ba6a9974fa4a1600f Mon Sep 17 00:00:00 2001 From: Maather AlJabri <85490284+aljab017@users.noreply.github.com> Date: Wed, 1 May 2024 09:14:46 +0400 Subject: [PATCH 06/11] refactor and clean-up --- {models => services}/measurement_converter.py | 0 {models => services}/measurement_converter_db.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {models => services}/measurement_converter.py (100%) rename {models => services}/measurement_converter_db.py (100%) diff --git a/models/measurement_converter.py b/services/measurement_converter.py similarity index 100% rename from models/measurement_converter.py rename to services/measurement_converter.py diff --git a/models/measurement_converter_db.py b/services/measurement_converter_db.py similarity index 100% rename from models/measurement_converter_db.py rename to services/measurement_converter_db.py From 7dfee81537ef38f836d039539f192b18c47a6540 Mon Sep 17 00:00:00 2001 From: Maather AlJabri <85490284+aljab017@users.noreply.github.com> Date: Wed, 1 May 2024 09:22:23 +0400 Subject: [PATCH 07/11] change import refs --- controller/measurement_converter_api.py | 4 ++-- models/tests/measurement_converter_tests.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/controller/measurement_converter_api.py b/controller/measurement_converter_api.py index e779c9a..83099ec 100644 --- a/controller/measurement_converter_api.py +++ b/controller/measurement_converter_api.py @@ -1,6 +1,6 @@ import cherrypy -from models.measurement_converter import MeasurementConverter -from models.measurement_converter_db import MeasurementConverterDB +from services.measurement_converter import MeasurementConverter +from services.measurement_converter_db import MeasurementConverterDB class MeasurementConverterAPI(object): diff --git a/models/tests/measurement_converter_tests.py b/models/tests/measurement_converter_tests.py index 6d6bc40..342a9b5 100644 --- a/models/tests/measurement_converter_tests.py +++ b/models/tests/measurement_converter_tests.py @@ -1,5 +1,5 @@ import unittest -from models.measurement_converter import MeasurementConverter +from services.measurement_converter import MeasurementConverter class TestMeasurementConverter(unittest.TestCase): From a63c61d2d2b82a5846d1851814f56f39eb15e104 Mon Sep 17 00:00:00 2001 From: Maather AlJabri <85490284+aljab017@users.noreply.github.com> Date: Wed, 1 May 2024 10:21:56 +0400 Subject: [PATCH 08/11] add db model --- controller/measurement_converter_api.py | 11 +++++++---- models/measurement_history.py | 7 +++++++ services/measurement_converter.py | 2 +- .../tests/measurement_converter_tests.py | 6 +++--- {services => utils}/measurement_converter_db.py | 0 5 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 models/measurement_history.py rename {models => services}/tests/measurement_converter_tests.py (73%) rename {services => utils}/measurement_converter_db.py (100%) diff --git a/controller/measurement_converter_api.py b/controller/measurement_converter_api.py index 83099ec..0ce5ba7 100644 --- a/controller/measurement_converter_api.py +++ b/controller/measurement_converter_api.py @@ -1,6 +1,7 @@ import cherrypy from services.measurement_converter import MeasurementConverter -from services.measurement_converter_db import MeasurementConverterDB +from utils.measurement_converter_db import MeasurementConverterDB +from models.measurement_history import MeasurementHistory class MeasurementConverterAPI(object): @@ -11,15 +12,17 @@ def convert_measurements(self, input_str=None): """ Convert the measurements to the sum of letter values for each segment. """ + db_entry = MeasurementHistory + db_entry.input = input_str try: if input_str is None: raise cherrypy.HTTPError(400, "Missing input parameter") - output = MeasurementConverter().pmc(input_str) - MeasurementConverterDB().save_to_history(input_str, output) + db_entry.output = MeasurementConverter().package_measurement_converter(input_str) + MeasurementConverterDB().save_to_history(db_entry.input, db_entry.output) except Exception as e: raise cherrypy.HTTPError(400, str(e)) - return output + return db_entry.output @cherrypy.expose @cherrypy.tools.json_out() diff --git a/models/measurement_history.py b/models/measurement_history.py new file mode 100644 index 0000000..e563e94 --- /dev/null +++ b/models/measurement_history.py @@ -0,0 +1,7 @@ +class MeasurementHistory: + """ + Class to represent a measurement history object + """ + def __init__(self, input_str, output): + self.input = input_str + self.output = output diff --git a/services/measurement_converter.py b/services/measurement_converter.py index 3156a52..3139ac3 100644 --- a/services/measurement_converter.py +++ b/services/measurement_converter.py @@ -11,7 +11,7 @@ def get_letter_value(self, letter): else: return ord(letter) - 96 - def pmc(self, string): + def package_measurement_converter(self, string): """ Parse the string and calculate the sum of letter values for each segment. """ diff --git a/models/tests/measurement_converter_tests.py b/services/tests/measurement_converter_tests.py similarity index 73% rename from models/tests/measurement_converter_tests.py rename to services/tests/measurement_converter_tests.py index 342a9b5..7893917 100644 --- a/models/tests/measurement_converter_tests.py +++ b/services/tests/measurement_converter_tests.py @@ -12,7 +12,7 @@ def test_non_z_strings(self): non_z_outputs = [[1], [2, 6], [2, 7, 7], [0]] for i in range(len(non_z_inputs)): - self.assertEqual(MeasurementConverter().pmc(non_z_inputs[i]), non_z_outputs[i]) + self.assertEqual(MeasurementConverter().package_measurement_converter(non_z_inputs[i]), non_z_outputs[i]) def test_z_strings(self): @@ -23,7 +23,7 @@ def test_z_strings(self): z_outputs = [[28, 53, 1], [40, 1], [26], [0], [0]] for i in range(len(z_inputs)): - self.assertEqual(MeasurementConverter().pmc(z_inputs[i]), z_outputs[i]) + self.assertEqual(MeasurementConverter().package_measurement_converter(z_inputs[i]), z_outputs[i]) def test_invalid_strings(self): """ @@ -32,7 +32,7 @@ def test_invalid_strings(self): invalid_inputs = ["abc", "aaa", "z", "123", "+!@#"] for i in range(len(invalid_inputs)): - self.assertEqual(MeasurementConverter().pmc(invalid_inputs[i]), "Invalid string input") + self.assertEqual(MeasurementConverter().package_measurement_converter(invalid_inputs[i]), "Invalid string input") if __name__ == '__main__': diff --git a/services/measurement_converter_db.py b/utils/measurement_converter_db.py similarity index 100% rename from services/measurement_converter_db.py rename to utils/measurement_converter_db.py From fec6aa26df0ac1ae34b576c747982d0917a54ad7 Mon Sep 17 00:00:00 2001 From: Maather AlJabri <85490284+aljab017@users.noreply.github.com> Date: Wed, 1 May 2024 11:04:07 +0400 Subject: [PATCH 09/11] add logs --- main.py | 5 +++++ utils/measurement_converter_db.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/main.py b/main.py index db0f9b3..ae873b7 100644 --- a/main.py +++ b/main.py @@ -1,8 +1,13 @@ import cherrypy +import logging from controller.measurement_converter_api import MeasurementConverterAPI if __name__ == '__main__': + # Configure logging + logging.basicConfig(filename='./logs/measurement_log.log', level=logging.CRITICAL, + format='%(asctime)s:%(levelname)s:%(message)s') + cherrypy.tree.mount(MeasurementConverterAPI(), '/') cherrypy.config.update({'server.socket_host': '0.0.0.0'}) cherrypy.config.update({'server.socket_port': 8080}) diff --git a/utils/measurement_converter_db.py b/utils/measurement_converter_db.py index 01ecace..c645903 100644 --- a/utils/measurement_converter_db.py +++ b/utils/measurement_converter_db.py @@ -2,7 +2,7 @@ import json class MeasurementConverterDB(object): - def __init__(self, db_name='history.db'): + def __init__(self, db_name='./data/history.db'): self.db_name = db_name self.conn = sqlite3.connect(self.db_name) self.cursor = self.conn.cursor() From fc724a21f62f200bc99d4871ffc8b44c05f9f41e Mon Sep 17 00:00:00 2001 From: Maather AlJabri <85490284+aljab017@users.noreply.github.com> Date: Wed, 1 May 2024 11:28:16 +0400 Subject: [PATCH 10/11] add empty directory placeholder --- data/.gitkeep | 0 logs/.gitkeep | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 data/.gitkeep create mode 100644 logs/.gitkeep diff --git a/data/.gitkeep b/data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/logs/.gitkeep b/logs/.gitkeep new file mode 100644 index 0000000..e69de29 From cd8370fc4039befec622d6de8a317ed7efe363e6 Mon Sep 17 00:00:00 2001 From: Maather AlJabri <85490284+aljab017@users.noreply.github.com> Date: Thu, 2 May 2024 09:13:01 +0400 Subject: [PATCH 11/11] return json output --- controller/measurement_converter_api.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/controller/measurement_converter_api.py b/controller/measurement_converter_api.py index 0ce5ba7..14dd75f 100644 --- a/controller/measurement_converter_api.py +++ b/controller/measurement_converter_api.py @@ -1,4 +1,5 @@ import cherrypy +import json from services.measurement_converter import MeasurementConverter from utils.measurement_converter_db import MeasurementConverterDB from models.measurement_history import MeasurementHistory @@ -16,14 +17,16 @@ def convert_measurements(self, input_str=None): db_entry.input = input_str try: if input_str is None: - raise cherrypy.HTTPError(400, "Missing input parameter") + raise cherrypy.HTTPError(400, "Missing input parameter") db_entry.output = MeasurementConverter().package_measurement_converter(input_str) MeasurementConverterDB().save_to_history(db_entry.input, db_entry.output) + error_msg = "Invalid string input" if db_entry.output == "Invalid string input" else "" + status = "SUCCESS" if error_msg == "" else "FAIL" + result = db_entry.output if error_msg == "" else [] + return {"status": status, "error_msg": error_msg, "result": result} except Exception as e: - raise cherrypy.HTTPError(400, str(e)) - - return db_entry.output - + return {"status": "FAIL", "error_msg": str(e), "result": []} + @cherrypy.expose @cherrypy.tools.json_out() def get_history(self):