From c9069b0739a56f6f654cc5c19a66aec4a52cfa8d Mon Sep 17 00:00:00 2001 From: slowy07 Date: Wed, 30 Jul 2025 11:41:21 +0700 Subject: [PATCH 1/5] chore: update to v1.8.0 Signed-off-by: slowy07 --- OpenSeries/bilangan_istimewa.py | 49 ++--- OpenSeries/util/constant.py | 7 +- OpenSeries/util/error.py | 149 +++++++++++--- pyproject.toml | 1 + testing/bilangan_istimewa_test.py | 103 ++++------ testing/fisika_test.py | 131 ------------- testing/main_test.py | 103 ---------- testing/matematika_test.py | 309 ------------------------------ testing/statistika_test.py | 48 ----- uv.lock | 181 +++++++++++++++++ 10 files changed, 363 insertions(+), 718 deletions(-) delete mode 100644 testing/fisika_test.py delete mode 100644 testing/main_test.py delete mode 100644 testing/matematika_test.py delete mode 100644 testing/statistika_test.py create mode 100644 uv.lock diff --git a/OpenSeries/bilangan_istimewa.py b/OpenSeries/bilangan_istimewa.py index 779a047..0b2bfca 100644 --- a/OpenSeries/bilangan_istimewa.py +++ b/OpenSeries/bilangan_istimewa.py @@ -1,8 +1,9 @@ -import OpenSeries.util.error as error from typing import Union +from .util.error import ErrorTipeData, Error +import numpy as np -def angka_armstrong(angka: int) -> Union[str, error.ErrorTipeData]: +def angka_armstrong(angka: int) -> Union[str, ErrorTipeData]: """ angka armstrong adalah bilangan bulat positif yang sama dengan jumlah pangkat tiga dari digit-digitnya @@ -17,24 +18,16 @@ def angka_armstrong(angka: int) -> Union[str, error.ErrorTipeData]: benar, bukan = "angka armstrong", "bukan angka armstrong" # cek tipe data dari variable angka if isinstance(angka, (float, str)): - return error.ErrorTipeData(["int"]) - else: - total = 0 - number_of_digit = 0 - temp = angka - - number_of_digit = len(str(angka)) - temp = angka - while temp > 0: - rem = temp % 10 - total += rem**number_of_digit - temp //= 10 - if angka == total: - return benar.capitalize() - return bukan.capitalize() + return ErrorTipeData(["int"]) + angka_str = str(abs(angka)) + jumlah_digit = len(angka_str) + + digit_array = np.fromiter((int(digit) for digit in angka_str), dtype=int) + total = np.sum(np.power(digit_array, jumlah_digit)) + return benar if abs(angka) == total else bukan -def angka_automorphic(angka: int) -> Union[str, error.ErrorTipeData]: +def angka_automorphic(angka: int) -> Union[str, ErrorTipeData]: """ angka automorphic adalah bilangan asli dalam basis bilangan tertentu yang kuadratnya berakhir dengan angka yang sama dengan bilangan itu sendiri @@ -54,20 +47,20 @@ def angka_automorphic(angka: int) -> Union[str, error.ErrorTipeData]: benar, bukan = "angka automorphic", "bukan angka automorphic" # cek dari tipe data angka if not isinstance(angka, int): - return error.ErrorTipeData(["int"]) + return ErrorTipeData(["int"]) if angka < 0: return bukan.capitalize() kuadrat_angka = angka * angka - while angka < 0: - if angka % 10 != kuadrat_angka % 10: - return bukan.capitalize() - angka //= 10 - kuadrat_angka //= 10 - return benar.capitalize() + angka_str = str(angka) + kuadrat_str = str(kuadrat_angka) + if kuadrat_str.endswith(angka_str): + return benar.capitalize() + else: + return bukan.capitalize() -def angka_pronic(angka: int) -> Union[str, error.ErrorTipeData]: +def angka_pronic(angka: int) -> Union[str, ErrorTipeData]: """ angka pronic adalah bilangan bulat positif yang merupakan hasil perkalian dari dua bilangan bulat berurutan @@ -96,7 +89,7 @@ def angka_pronic(angka: int) -> Union[str, error.ErrorTipeData]: ) -def angka_segitiga(angka: int) -> Union[int, error.ErrorTipeData, error.Error]: +def angka_segitiga(angka: int) -> Union[int, ErrorTipeData, Error]: """ bilangan segitiga adalah bilangan yang dapat disusun dalam bentuk segitiga sama sisi @@ -113,5 +106,5 @@ def angka_segitiga(angka: int) -> Union[int, error.ErrorTipeData, error.Error]: return error.ErrorTipeData(["int"]) # jika value dari angka diisi nilai negatif if angka < 0: - return error.Error("angka tidak boleh negatif") + return Error("angka tidak boleh negatif") return angka * (angka + 1) // 2 diff --git a/OpenSeries/util/constant.py b/OpenSeries/util/constant.py index c04fc6e..d5aa3e2 100644 --- a/OpenSeries/util/constant.py +++ b/OpenSeries/util/constant.py @@ -1,16 +1,17 @@ +from typing import Final from colorama import Fore, Style # bilangan pi adalah nilai konstant dalam matematika yang merupakan perbandingan keliling # lingkaran dengan diameternya -PI: float = 3.14159265358979323846 +PI: Final[float] = 3.14159265358979323846 # bilangan euler adalah nilai konstant yang dimana nilai kira-kiranya sama dengan 2.71828 # dan dikarakterisasi dalam berbagai cara -BILANGAN_EULER: float = 2.718281828459045235360 +BILANGAN_EULER: Final[float] = 2.718281828459045235360 # variable ini juga mewakili dari konstanta planck, tetapi dinyatan dalam satuan # elektron volt per detik (eV/s) nilainya adalah 4.1357 × 10⁻¹⁵ eV s⁻¹ -KONSTANTA_PLANCK: float = 4.1357 * pow(10, -15) +KONSTANTA_PLANCK: Final[float] = 4.1357 * pow(10, -15) # default error dari warna menggunakan kode ANSI escape # merah diff --git a/OpenSeries/util/error.py b/OpenSeries/util/error.py index fd830fa..5cdda65 100644 --- a/OpenSeries/util/error.py +++ b/OpenSeries/util/error.py @@ -5,10 +5,42 @@ # - menangani error terkait indeks saat melakukan indexing pada struktur data # - menangani error terkait dengan validasi dari values # - menampilkan error saat mencoba dengan pembagian dengan error -from OpenSeries.util import constant as warna +from abc import ABC +from typing import Optional, Union -class ErrorTipeData(TypeError): + +# mocking modul warna jika error import +try: + from util import constant as warna +except ImportError as error: + # mocking object jika module warna tidak tersedia + class MockWarna: + """mock class untuk warna jika modul gagal import""" + + red: str = "" + reset_warna: str = "" + + warna = MockWarna() + + +class BaseError(Exception, ABC): + def __init__(self, message: str, error_code: Optional[str] = None): + """ + inisialisasi base exception + + Args: + message (str): pesan error yang akan ditampilkan + error_code (str): kode error opsional untuk identifikasi programatik + """ + self.error_code = error_code + super().__init__(message) + + def __str__(self) -> str: + return self.args[0] if self.args else "" + + +class ErrorTipeData(BaseError, TypeError): """ Kelas untuk mendeteksi error dari tipe data @@ -19,25 +51,43 @@ class ErrorTipeData(TypeError): (str): pesan error tipe data sesuai dari inputan """ - def __init__(self, expected_types: list[str]): - # mengecek apakah list expected_types tidak kosong + def __init__( + self, + tipe_diharapkan: list[str], + tipe_sebenarnya: Optional[str] = None, + nama_parameter: Optional[str] = None, + ): + self._validate_input(tipe_diharapkan) + self.tipe_diharapkan = tipe_diharapkan + self.tipe_sebenarnya = tipe_sebenarnya + self.nama_parameter = nama_parameter + + # membuat pesan error dengan memanggil method format_tipe_data + message = self._format_message() + super().__init__(message, error_code="TYPE_ERROR") + + def _validate_input(self, expected_types: list[str]) -> None: + if not isinstance(expected_types, list): + raise TypeError("expected_types harus berrupa list") if not expected_types: raise ValueError("tipe data dalam list tidak boleh kosong") - # mengecek apakah semua element di dalam expected_types adalah string if not all(isinstance(data, str) for data in expected_types): - raise TypeError("element dari tipe data harus str (string)!") + raise TypeError("semua element dalam expected_types harus string") - # membuat pesan error dengan memanggil method format_tipe_data - message = self.format_tipe_data(expected_types) - super().__init__(message) + def _format_message(self) -> str: + tipe_str = " atau ".join(self.tipe_diharapkan) + base_message = f"tipe data harus {tipe_str}" - def format_tipe_data(self, tipe_data: list[str]) -> str: - # gabungkan element list menjadi string terpisah oleh `" atau "` - tipe_str = " atau ".join(map(str, tipe_data)) - return f"{warna.red}Error Tipe Data:{warna.reset_warna} tipe data harus {tipe_str}!" + if self.nama_parameter: + base_message = f"parameter `{self.nama_parameter}` {base_message}" + if self.tipe_sebenarnya: + base_message += f" (diterima: {self.tipe_sebenarnya})" -class Error(Exception): + return f"{warna.red}Error Tipe data:{warna.reset_warna}" + + +class Error(BaseError): """ Kelas untuk membuat kostumisasi error @@ -45,37 +95,78 @@ class Error(Exception): pesan (str): pesan kostum yang ingin dimasukkan """ - def __init__(self, pesan: str): - message = f"{warna.red}Error:{warna.reset_warna} {pesan}" - super().__init__(message) + def __init__(self, pesan: str, error_code: Optional[str] = None) -> None: + if not isinstance(pesan, str): + raise TypeError("pesan harus berupa string") + formatted_message = f"{warna.red}Error:{warna.reset_warna} {pesan}" + super().__init__(formatted_message, error_code=error_code) -class IndeksError(IndexError): +class IndeksError(BaseError, IndexError): """ kelas untuk membuat error dari index jika tidak selaras dengan dimensi atau lain """ - def __init__(self, pesan: str): - message = f"{warna.red}Indeks Error:{warna.reset_warna} {pesan}" - super().__init__(message) + def __init__( + self, pesan: str, index: Optional[int] = None, max_index: Optional[int] = None + ): + if not isinstance(pesan, str): + raise TypeError("pesan harus berupa string") + self.index = index + self.max_index = max_index + + detailed_message = pesan + + if index is not None: + detailed_message += f" (indeks: {index})" + if max_index is not None: + detailed_message += f" (maksimum: {max_index})" + + formatted_message = ( + f"{warna.red}Indeks Error:{warna.reset_warna} {detailed_message}" + ) + super().__init__(formatted_message, error_code="INDEX_ERROR") -class ErrorValue(ValueError): + +class ErrorValue(BaseError, ValueError): """ kelas untuk membuat error dari index dengan throw dari ValueError """ - def __init__(self, pesan: str): - message = f"{warna.red}Error Value:{warna.reset_warna} {pesan}" - super().__init__(message) + def __init__( + self, pesan: str, invalid_value: Optional[Union[str, int, float]] = None + ): + if not isinstance(pesan, str): + raise TypeError("pesan harus string") + self.invalid_value = invalid_value + detailed_message = pesan + if invalid_value is not None: + detailed_message += f" (nilai tidak valid: {invalid_value})" + + formatted_message = ( + f"{warna.red}Error Value:{warna.reset_warna} {detailed_message}" + ) + super().__init__(formatted_message, error_code="VALUE_ERROR") -class ErrorDibagiNol(ZeroDivisionError): + +class ErrorDibagiNol(BaseError, ZeroDivisionError): """ Kelas untuk menampilkan error yang tidak bisa dibagi dengan nol """ - def __init__(self): - super().__init__( - f"{warna.red}Error Dibagi Nol:{warna.reset_warna} Tidak bisa dibagi dengan nol" + def __init__(self, operasi: Optional[str] = None, dividend: Optional[float] = None): + self.operasi = operasi + self.dividend = dividend + + base_message = "Tidal bisa dibagi dengan nol" + if operasi: + base_message += f" dalam operasi {operasi}" + if dividend is not None: + base_message += f" (pembilang: {dividend})" + + formatted_message = ( + f"{warna.red}Error dibagi nol:{warna.reset_warna} {base_message}" ) + super().__init__(formatted_message, error_code="ZERO_DIVISION_ERROR") diff --git a/pyproject.toml b/pyproject.toml index 27a2e26..6764353 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,7 @@ classifiers = [ [tool.setuptools.packages.find] include = ["OpenSeries*"] exclude = ["example"] +where = ["."] [tool.setuptools.dynamic] dependencies = {file = ["requirements.txt"]} diff --git a/testing/bilangan_istimewa_test.py b/testing/bilangan_istimewa_test.py index 55552b1..febb96c 100644 --- a/testing/bilangan_istimewa_test.py +++ b/testing/bilangan_istimewa_test.py @@ -1,67 +1,36 @@ -import unittest -import OpenSeries.bilangan_istimewa as bilangan -import OpenSeries.util.error as error - - -class TestAngkaArmstrong(unittest.TestCase): - def test_angka_armstrong(self): - self.assertEqual(bilangan.angka_armstrong(153), "angka armstrong".capitalize()) - self.assertEqual(bilangan.angka_armstrong(370), "angka armstrong".capitalize()) - - def test_salah_armstrong(self): - self.assertEqual( - bilangan.angka_armstrong(222), "bukan angka armstrong".capitalize() - ) - self.assertEqual( - bilangan.angka_armstrong(444), "bukan angka armstrong".capitalize() - ) - - def test_salah_tipe_data_armstrong(self): - hasil = bilangan.angka_armstrong(333.2) - with self.assertRaises(error.ErrorTipeData): - raise hasil - - -class TestAngkaAutomorphic(unittest.TestCase): - def test_tipe_data_angka(self): - with self.assertRaises(error.ErrorTipeData): - raise bilangan.angka_automorphic(12.3) - raise bilangan.angka_automorphic("23") - - def test_angka_negatif(self): - hasil = bilangan.angka_automorphic(-2) - self.assertEqual(hasil, "bukan angka automorphic".capitalize()) - - def test_valid_input(self): - hasil = bilangan.angka_automorphic(25) - self.assertEqual(hasil, "angka automorphic".capitalize()) - - -class TestAngkaPronic(unittest.TestCase): - def test_angka_pronic_return_tipe_data(self): - hasil = bilangan.angka_pronic(30) - self.assertIsInstance(hasil, str) - - hasil = bilangan.angka_pronic("30") - with self.assertRaises(error.ErrorTipeData): - raise hasil - - def test_angka_pronic_negatif(self): - hasil = bilangan.angka_pronic(-30) - self.assertIsInstance(hasil, str) - - -class TestAngkaSegitiga(unittest.TestCase): - def test_angka_segitiga(self): - self.assertEqual(bilangan.angka_segitiga(0), 0) - self.assertEqual(bilangan.angka_segitiga(3), 6) - - def test_angka_negatif(self): - hasil = bilangan.angka_segitiga(-1) - with self.assertRaises(error.Error): - raise hasil - - def test_beda_tipe_data(self): - hasil = bilangan.angka_segitiga("12") - with self.assertRaises(error.ErrorTipeData): - raise hasil +import numpy as np +import pytest +from OpenSeries.bilangan_istimewa import angka_armstrong + + +class TestAngkaArmstrong: + def test_armstrong_3_digit(self): + """Test bilangan Armstrong 3 digit""" + assert angka_armstrong(153) == "angka armstrong" + assert angka_armstrong(371) == "angka armstrong" + assert angka_armstrong(407) == "angka armstrong" + + def test_armstrong_4_digit(self): + """Test bilangan Armstrong 4 digit""" + assert angka_armstrong(9474) == "angka armstrong" + assert angka_armstrong(1634) == "angka armstrong" + + def test_armstrong_5_digit(self): + """Test bilangan Armstrong 5 digit""" + assert angka_armstrong(54748) == "angka armstrong" + + def test_armstrong_6_digit(self): + """Test bilangan Armstrong 6 digit""" + assert angka_armstrong(548834) == "angka armstrong" + + def test_satu_digit(self): + """Semua angka 0-9 adalah Armstrong (n^1 = n)""" + for i in range(10): + assert angka_armstrong(i) == "angka armstrong" + + def test_nol(self): + """0 adalah angka Armstrong""" + assert angka_armstrong(0) == "angka armstrong" + + def test_bilangan_besar(self): + assert angka_armstrong(123456789) == "bukan angka armstrong" diff --git a/testing/fisika_test.py b/testing/fisika_test.py deleted file mode 100644 index 5609a6a..0000000 --- a/testing/fisika_test.py +++ /dev/null @@ -1,131 +0,0 @@ -import unittest -from OpenSeries import fisika as fisika -from OpenSeries.util import error as error - - -class TestKecepatan(unittest.TestCase): - def test_angka_valid(self): - hasil = fisika.kecepatan(100.0, 10.0) - self.assertEqual(hasil, 10.0) - - def test_dibagi_nol(self): - hasil = fisika.kecepatan(150.0, 0) - with self.assertRaises(error.ErrorDibagiNol): - raise hasil - - def test_invalid_input(self): - with self.assertRaises(error.ErrorTipeData): - raise fisika.kecepatan("12", 30) - - def test_kecepatan_invalid_input2(self): - hasil = fisika.kecepatan("12", "50") - with self.assertRaises(error.ErrorTipeData): - raise hasil - - -class TestPercepatan(unittest.TestCase): - def test_percepatan_valid(self): - hasil = fisika.percepatan(20.0, 5.0) - self.assertEqual(hasil, 4.0) - - def test_percepatan_dibagi_nol(self): - hasil = fisika.percepatan(30.0, 0) - with self.assertRaises(error.ErrorDibagiNol): - raise hasil - - def test_percepatan_nilai_tidak_valid(self): - hasil = fisika.percepatan("20", 30) - with self.assertRaises(error.ErrorTipeData): - raise hasil - - -class TestGerakLurusBeraturan(unittest.TestCase): - def test_valid(self): - hasil = fisika.gerak_lurus_beraturan(10.0, 2.0, 3.0) - self.assertAlmostEqual(hasil, 39.0, places=2) - - def test_invalid_int(self): - hasil = fisika.gerak_lurus_beraturan(8, 1.5, 2) - with self.assertRaises(error.ErrorTipeData): - raise hasil - - -class TestEnergiKinetik(unittest.TestCase): - def test_valid_input(self): - hasil = fisika.energi_kinetik(2.0, 5.0) - self.assertAlmostEqual(hasil, 25.0) - - def test_invalid_input_mix_tipe_data(self): - hasil = fisika.energi_kinetik("3", 4.5) - with self.assertRaises(error.ErrorTipeData): - raise hasil - - -class TestKetinggianBarometrik(unittest.TestCase): - def test_valid_input_tekanan(self): - hasil = fisika.ketinggian_barometrik(101325.0) - self.assertIsInstance(hasil, float) - - def test_tekanan_lebih_besar_daripada_air(self): - hasil = fisika.ketinggian_barometrik(110000.0) - with self.assertRaises(error.Error): - raise hasil - - def test_tekanan_angka_negatif(self): - hasil = fisika.ketinggian_barometrik(-820.3) - with self.assertRaises(error.Error): - raise hasil - - def test_tekanan_tipe_data_salah(self): - hasil = fisika.ketinggian_barometrik("12") - with self.assertRaises(error.ErrorTipeData): - raise hasil - - -class TestGayaSentripental(unittest.TestCase): - def test_gaya_sentripental(self): - hasil = fisika.gaya_sentripental(10, 5, 2) - self.assertEqual(hasil, 125.0) - - def test_gaya_sentripental_error_tipe_data(self): - hasil = fisika.gaya_sentripental("12", 5, 2) - self.assertIsInstance(hasil, error.ErrorTipeData) - with self.assertRaises(error.ErrorTipeData): - raise hasil - - def test_gaya_sentripental_minus(self): - hasil = fisika.gaya_sentripental(-10, 5, 2) - self.assertIsInstance(hasil, error.Error) - with self.assertRaises(error.Error): - raise hasil - - def test_gaya_sentripental_nol(self): - hasil = fisika.gaya_sentripental(10, 5, 0) - self.assertIsInstance(hasil, error.Error) - with self.assertRaises(error.Error): - raise hasil - - -class TestEfekDoppler(unittest.TestCase): - def test_efek_doppler(self): - hasil = fisika.efek_doppler(100, 340, 20, 10) - rounding_hasil = round(hasil) - self.assertEqual(rounding_hasil, 109) - - def test_efek_doppler_invalid_tipe_data(self): - hasil = fisika.efek_doppler("12", "340", "20", 10) - self.assertIsInstance(hasil, error.ErrorTipeData) - with self.assertRaises(error.ErrorTipeData): - raise hasil - - def test_efek_doppler_dibagi_nol(self): - hasil = fisika.efek_doppler(0, 0, 0, 0) - self.assertIsInstance(hasil, error.ErrorDibagiNol) - with self.assertRaises(error.ErrorDibagiNol): - raise hasil - - def test_efek_doppler_nilai_negatif(self): - hasil = fisika.efek_doppler(-100, -340, 20, 10) - self.assertIsInstance(hasil, error.Error) - with self.assertRaises(error.Error): - raise hasil diff --git a/testing/main_test.py b/testing/main_test.py deleted file mode 100644 index 3864069..0000000 --- a/testing/main_test.py +++ /dev/null @@ -1,103 +0,0 @@ -import unittest - -from testing.matematika_test import ( - TestKonversi, - TestKelilingLingkaran, - TestDiameterLingkaran, - TestPersamaanKuadrat, - TestRataRata, - TestFaktorial, - TestPermutasi, - TestKombinasi, - TestFPB, - TestFaktorPrima, - TestMatriksTranspose, - TestFungsiEuler, - TestSigmoid, - TestDistribusiBinomial, - TestGaussian, - TestIntegral, - TestDerivative, -) - -from testing.fisika_test import ( - TestKecepatan, - TestPercepatan, - TestGerakLurusBeraturan, - TestEnergiKinetik, - TestKetinggianBarometrik, - TestGayaSentripental, - TestEfekDoppler, -) - -from testing.bilangan_istimewa_test import ( - TestAngkaArmstrong, - TestAngkaAutomorphic, - TestAngkaPronic, - TestAngkaSegitiga, -) - -from testing.statistika_test import TestFungsiEntropy, TestFungiStandardDeviasi - -if __name__ == "__main__": - testing_matematika: list = [ - TestKelilingLingkaran, - TestKonversi, - TestDiameterLingkaran, - TestPersamaanKuadrat, - TestRataRata, - TestFaktorial, - TestPermutasi, - TestKombinasi, - TestFPB, - TestFaktorPrima, - TestMatriksTranspose, - TestFungsiEuler, - TestSigmoid, - TestDistribusiBinomial, - TestGaussian, - TestIntegral, - TestDerivative, - ] - - testing_fisika: list = [ - TestKecepatan, - TestPercepatan, - TestGerakLurusBeraturan, - TestEnergiKinetik, - TestKetinggianBarometrik, - TestGayaSentripental, - TestEfekDoppler, - ] - - testing_statistika: list = [ - TestFungsiEntropy, - TestFungiStandardDeviasi, - ] - - testing_angka_istimewa: list = [ - TestAngkaArmstrong, - TestAngkaAutomorphic, - TestAngkaPronic, - TestAngkaSegitiga, - ] - - all_tests = unittest.TestSuite() - - for testing_math in testing_matematika: - all_tests.addTest(unittest.TestLoader().loadTestsFromTestCase(testing_math)) - - for testing_physic in testing_fisika: - all_tests.addTest(unittest.TestLoader().loadTestsFromTestCase(testing_physic)) - - for testing_statistik in testing_statistika: - all_tests.addTest( - unittest.TestLoader().loadTestsFromTestCase(testing_statistik) - ) - - for testing_special_number in testing_angka_istimewa: - all_tests.addTest( - unittest.TestLoader().loadTestsFromTestCase(testing_special_number) - ) - - unittest.TextTestRunner(verbosity=2).run(all_tests) diff --git a/testing/matematika_test.py b/testing/matematika_test.py deleted file mode 100644 index 6b2709f..0000000 --- a/testing/matematika_test.py +++ /dev/null @@ -1,309 +0,0 @@ -import unittest -from OpenSeries import matematika as matematika -from OpenSeries.util import error as error -import numpy as np - - -class TestKonversi(unittest.TestCase): - def test_radian_ke_derajat(self): - self.assertAlmostEqual(matematika.radian_ke_derajat(1), 57.2957795131) - self.assertAlmostEqual(matematika.radian_ke_derajat(0), 0) - with self.assertRaises(error.ErrorTipeData): - raise matematika.radian_ke_derajat("12") - - def test_derajat_ke_radian(self): - self.assertAlmostEqual(matematika.derajat_ke_radian(180), 3.1415926535) - self.assertAlmostEqual(matematika.derajat_ke_radian(0), 0) - with self.assertRaises(error.ErrorTipeData): - raise matematika.derajat_ke_radian("12") - - def test_radian_ke_gradian(self): - self.assertAlmostEqual(matematika.radian_ke_gradian(180), 11459.1559026) - with self.assertRaises(error.ErrorTipeData): - raise matematika.radian_ke_gradian("128") - - def test_gradian_ke_radian(self): - self.assertAlmostEqual(matematika.gradian_ke_radian(52), 0.8168140899) - with self.assertRaises(error.ErrorTipeData): - raise matematika.gradian_ke_radian("200") - - -class TestKelilingLingkaran(unittest.TestCase): - def test_tipe_data_float(self): - hasil = matematika.keliling_lingkaran(2.5) - self.assertEqual(hasil, 15.707963267948966) - - def test_tipe_data_int(self): - hasil = matematika.keliling_lingkaran(3) - self.assertAlmostEqual(hasil, 18.84955592153876) - - def test_nilai_input_tidak_valid(self): - hasil = matematika.keliling_lingkaran("45") - with self.assertRaises(error.ErrorTipeData): - raise hasil - - -class TestDiameterLingkaran(unittest.TestCase): - def test_tipe_data_float(self): - hasil = matematika.diameter_lingkaran(2.5) - self.assertAlmostEqual(hasil, 5.0) - - def test_tipe_data_int(self): - hasil = matematika.diameter_lingkaran(3) - self.assertAlmostEqual(hasil, 6.0) - - def test_nilai_input_tidak_valid(self): - hasil = matematika.diameter_lingkaran("800") - with self.assertRaises(error.ErrorTipeData): - raise hasil - - -class TestPersamaanKuadrat(unittest.TestCase): - def test_nilai_valid(self): - hasil = matematika.persamaan_kuadrat(1, -3, 2) - self.assertAlmostEqual(hasil, 2.0) - - def test_nilai_valid_float(self): - hasil = matematika.persamaan_kuadrat(1.0, -2.0, 1.0) - self.assertAlmostEqual(hasil, 1.0) - - def test_nilai_input_tidak_valid(self): - hasil = matematika.persamaan_kuadrat("12", 2, 3) - with self.assertRaises(error.ErrorTipeData): - raise hasil - - def test_nilai_complex(self): - hasil = matematika.persamaan_kuadrat(1, 2, 5) - with self.assertRaises(error.Error): - raise hasil - - -class TestRataRata(unittest.TestCase): - def test_nilai_valid(self): - hasil = matematika.rata_rata([1, 2, 3, 4, 5]) - self.assertAlmostEqual(hasil, 3.0) - - def test_nilai_valid_float(self): - hasil = matematika.rata_rata([1.5, 2.5, 3.5, 4.5]) - self.assertAlmostEqual(hasil, 3.0) - - def test_list_kosong(self): - hasil = matematika.rata_rata([]) - with self.assertRaises(error.Error): - raise hasil - - -class TestFaktorial(unittest.TestCase): - def test_faktorial_nilai_nol(self): - hasil = matematika.faktorial(0) - self.assertEqual(hasil, 1) - - def test_faktorial_tipe_data_salah(self): - hasil = matematika.faktorial(20.0) - with self.assertRaises(error.ErrorTipeData): - raise hasil - - def test_faktorial_nilai_negatif(self): - hasil = matematika.faktorial(-120) - with self.assertRaises(error.Error): - raise hasil - - -class TestPermutasi(unittest.TestCase): - def test_input_valid(self): - hasil = matematika.permutasi(5, 2) - self.assertEqual(hasil, 20) - - def test_input_invalid_float(self): - hasil = matematika.permutasi(5.2, 2.0) - with self.assertRaises(error.ErrorTipeData): - raise hasil - - def test_nilai_input_tidak_valid(self): - hasil = matematika.permutasi("12", "14") - with self.assertRaises(error.ErrorTipeData): - raise hasil - - -class TestKombinasi(unittest.TestCase): - def test_input_valid(self): - hasil = matematika.kombinasi(5, 2) - self.assertEqual(hasil, 10) - - def test_input_invalid_float(self): - hasil = matematika.kombinasi(5.2, 2.0) - with self.assertRaises(error.ErrorTipeData): - raise hasil - - def test_nilai_input_tidak_valid(self): - hasil = matematika.kombinasi("12", "14") - with self.assertRaises(error.ErrorTipeData): - raise hasil - - -class TestFPB(unittest.TestCase): - def test_input_valid(self): - hasil = matematika.fpb(36, 48) - self.assertEqual(hasil, 12) - - def test_invalid_input(self): - hasil = matematika.fpb(15.0, 20.0) - self.assertEqual(hasil, 5.0) - - def test_angka_invalid(self): - hasil = matematika.fpb(-36, -40) - with self.assertRaises(error.Error): - raise hasil - - def test_angka_nol(self): - hasil = matematika.fpb(0, 48) - self.assertEqual(hasil, 48) - - -class TestFaktorPrima(unittest.TestCase): - def test_input_valid(self): - hasil = matematika.faktor_prima(30) - self.assertEqual(hasil, [2, 3, 5]) - - def test_input_float(self): - hasil = matematika.faktor_prima(25.0) - with self.assertRaises(error.ErrorTipeData): - raise hasil - - def test_faktor_prima_kosong(self): - hasil = matematika.faktor_prima(1) - self.assertEqual(hasil, []) - - def test_input_negatif(self): - hasil = matematika.faktor_prima(-30) - with self.assertRaises(error.Error): - raise hasil - - -class TestMatriksTranspose(unittest.TestCase): - def test_valid_input(self): - matriks_a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] - ekspetasi = [[1, 4, 7], [2, 5, 8], [3, 6, 9]] - hasil = matematika.transpose_matriks(matriks_a) - self.assertEqual(hasil, ekspetasi) - - -class TestFungsiEuler(unittest.TestCase): - def test_nilai_positif(self): - hasil = matematika.euler_pi(100) - self.assertEqual(hasil, 40.0) - - def test_nilai_tidak_integer(self): - hasil = matematika.euler_pi(3.14) - with self.assertRaises(error.ErrorTipeData): - raise hasil - - def test_nilai_negatif(self): - hasil = matematika.euler_pi(-20) - with self.assertRaises(error.Error): - raise hasil - - def test_nilai_nol(self): - hasil = matematika.euler_pi(0) - with self.assertRaises(error.Error): - raise hasil - - -class TestSigmoid(unittest.TestCase): - def test_sigmoid(self): - input_nilai_array = np.array([1, 2, 3]) - hasil = matematika.sigmoid(input_nilai_array) - nilai_ekspetasi = np.array([0.73105858, 0.88079708, 0.95257413]) - np.testing.assert_allclose(hasil, nilai_ekspetasi, rtol=1e-7) - - def test_invalid_input(self): - hasil = matematika.sigmoid(5) - self.assertIsInstance(hasil, error.ErrorTipeData) - with self.assertRaises(error.ErrorTipeData): - raise hasil - - -class TestDistribusiBinomial(unittest.TestCase): - def test_valid_input(self): - hasil = matematika.distribusi_binomial(2, 5, 0.7) - self.assertAlmostEqual(hasil, 0.13230000000000006) - - def test_invalid_input_keberhasilan_lebih_besar_percobaan(self): - hasil = matematika.distribusi_binomial(5, 3, 0.5) - with self.assertRaises(error.ErrorValue): - raise hasil - - def test_invalid_input_negatif(self): - hasil = matematika.distribusi_binomial(-2, 4, 0.1) - with self.assertRaises(error.ErrorValue): - raise hasil - - def test_input_angka_tidak_integer(self): - hasil = matematika.distribusi_binomial(2.4, 4.2, 0.5) - with self.assertRaises(error.ErrorTipeData): - raise hasil - - -class TestGaussian(unittest.TestCase): - def test_data_valid_input(self): - x = 5 - mu = 3 - sigma = 2 - ekspetasi_nilai = 0.12098536225957168 - hasil = matematika.gaussian(x, mu, sigma) - self.assertAlmostEqual(hasil, ekspetasi_nilai, places=10) - - -class TestIntegral(unittest.TestCase): - def test_nilai_integral(self): - def f(x): - return x * x - - a = 0 - b = 3 - hasil = matematika.integral(f, a, b) - - self.assertAlmostEqual(hasil, 9.00, places=2) - - def testing_tipe_input_data_string(self): - def f(x): - return x * x - - a = "0" - b = "3" - hasil = matematika.integral(f, a, b) - with self.assertRaises(error.ErrorTipeData): - raise hasil - - def testing_tipe_iterasi_string(self): - def f(x): - return x * x - - a = 0 - b = 3 - iterasi = "4" - hasil = matematika.integral(a, b, iterasi) - with self.assertRaises(error.ErrorTipeData): - raise hasil - - -class TestDerivative(unittest.TestCase): - def setUp(self): - def f(x): - return x * x - - self.inputFungsi = f - self.inputValue = 4 - - def testing_input_value_integer(self): - hasil = matematika.turunan(self.inputFungsi, self.inputValue) - self.assertAlmostEqual(hasil, 8.000, places=3) - - def testing_input_value_desimal(self): - hasil = matematika.turunan(self.inputFungsi, float(self.inputValue)) - self.assertAlmostEqual(hasil, 8.000, places=3) - - def testing_input_value_string(self): - hasil = matematika.turunan(self.inputFungsi, str(self.inputValue)) - with self.assertRaises(error.ErrorTipeData): - raise hasil diff --git a/testing/statistika_test.py b/testing/statistika_test.py deleted file mode 100644 index 243e803..0000000 --- a/testing/statistika_test.py +++ /dev/null @@ -1,48 +0,0 @@ -import unittest -import numpy as np -from OpenSeries import statistika as statistika -from OpenSeries.util import error as pesan_error - - -class TestFungsiEntropy(unittest.TestCase): - def test_entropy_dengan_none(self): - label = [1, 1, 2, 2, 3, 3] - hasil = statistika.entropy(label, base=2) - self.assertTrue(np.allclose(hasil, 1.584962500721156)) - - def test_nilai_kosong(self): - label = [] - hasil = statistika.entropy(label, base=2) - with self.assertRaises(pesan_error.Error): - raise hasil - - def test_nilai_element_dalam_label(self): - label = [1, 2, "3", 4] - hasil = statistika.entropy(label, base=2) - with self.assertRaises(pesan_error.ErrorTipeData): - raise hasil - - def test_tipe_data_tuple(self): - label = (1, 2, 3) - hasil = statistika.entropy(label, base=2) - with self.assertRaises(pesan_error.ErrorTipeData): - raise hasil - - -class TestFungiStandardDeviasi(unittest.TestCase): - def test_standard_deviasi_dengan_numpy_array(self): - vektor = np.array([1, 2, 3, 4, 5]) - hasil = statistika.standar_deviasi(vektor) - self.assertAlmostEqual(hasil, np.std(vektor), places=2) - - def test_standard_deviasi_dengan_list(self): - vektor = [1, 2, 3, 4, 5] - hasil = statistika.standar_deviasi(vektor) - with self.assertRaises(pesan_error.ErrorTipeData): - raise hasil - - def test_standard_deviasi_dengan_numpy_kosong(self): - vektor = np.array([]) - hasil = statistika.standar_deviasi(vektor) - with self.assertRaises(pesan_error.Error): - raise hasil diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..d3b9dbd --- /dev/null +++ b/uv.lock @@ -0,0 +1,181 @@ +version = 1 +revision = 2 +requires-python = ">=3.10.0" +resolution-markers = [ + "python_full_version >= '3.11'", + "python_full_version < '3.11'", +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "numpy" +version = "2.2.6" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] +sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" }, + { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" }, + { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" }, + { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" }, + { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" }, + { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" }, + { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" }, + { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" }, + { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" }, + { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" }, + { url = "https://files.pythonhosted.org/packages/da/a8/4f83e2aa666a9fbf56d6118faaaf5f1974d456b1823fda0a176eff722839/numpy-2.2.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f9f1adb22318e121c5c69a09142811a201ef17ab257a1e66ca3025065b7f53ae", size = 21176963, upload-time = "2025-05-17T21:31:19.36Z" }, + { url = "https://files.pythonhosted.org/packages/b3/2b/64e1affc7972decb74c9e29e5649fac940514910960ba25cd9af4488b66c/numpy-2.2.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c820a93b0255bc360f53eca31a0e676fd1101f673dda8da93454a12e23fc5f7a", size = 14406743, upload-time = "2025-05-17T21:31:41.087Z" }, + { url = "https://files.pythonhosted.org/packages/4a/9f/0121e375000b5e50ffdd8b25bf78d8e1a5aa4cca3f185d41265198c7b834/numpy-2.2.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3d70692235e759f260c3d837193090014aebdf026dfd167834bcba43e30c2a42", size = 5352616, upload-time = "2025-05-17T21:31:50.072Z" }, + { url = "https://files.pythonhosted.org/packages/31/0d/b48c405c91693635fbe2dcd7bc84a33a602add5f63286e024d3b6741411c/numpy-2.2.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:481b49095335f8eed42e39e8041327c05b0f6f4780488f61286ed3c01368d491", size = 6889579, upload-time = "2025-05-17T21:32:01.712Z" }, + { url = "https://files.pythonhosted.org/packages/52/b8/7f0554d49b565d0171eab6e99001846882000883998e7b7d9f0d98b1f934/numpy-2.2.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b64d8d4d17135e00c8e346e0a738deb17e754230d7e0810ac5012750bbd85a5a", size = 14312005, upload-time = "2025-05-17T21:32:23.332Z" }, + { url = "https://files.pythonhosted.org/packages/b3/dd/2238b898e51bd6d389b7389ffb20d7f4c10066d80351187ec8e303a5a475/numpy-2.2.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba10f8411898fc418a521833e014a77d3ca01c15b0c6cdcce6a0d2897e6dbbdf", size = 16821570, upload-time = "2025-05-17T21:32:47.991Z" }, + { url = "https://files.pythonhosted.org/packages/83/6c/44d0325722cf644f191042bf47eedad61c1e6df2432ed65cbe28509d404e/numpy-2.2.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bd48227a919f1bafbdda0583705e547892342c26fb127219d60a5c36882609d1", size = 15818548, upload-time = "2025-05-17T21:33:11.728Z" }, + { url = "https://files.pythonhosted.org/packages/ae/9d/81e8216030ce66be25279098789b665d49ff19eef08bfa8cb96d4957f422/numpy-2.2.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9551a499bf125c1d4f9e250377c1ee2eddd02e01eac6644c080162c0c51778ab", size = 18620521, upload-time = "2025-05-17T21:33:39.139Z" }, + { url = "https://files.pythonhosted.org/packages/6a/fd/e19617b9530b031db51b0926eed5345ce8ddc669bb3bc0044b23e275ebe8/numpy-2.2.6-cp311-cp311-win32.whl", hash = "sha256:0678000bb9ac1475cd454c6b8c799206af8107e310843532b04d49649c717a47", size = 6525866, upload-time = "2025-05-17T21:33:50.273Z" }, + { url = "https://files.pythonhosted.org/packages/31/0a/f354fb7176b81747d870f7991dc763e157a934c717b67b58456bc63da3df/numpy-2.2.6-cp311-cp311-win_amd64.whl", hash = "sha256:e8213002e427c69c45a52bbd94163084025f533a55a59d6f9c5b820774ef3303", size = 12907455, upload-time = "2025-05-17T21:34:09.135Z" }, + { url = "https://files.pythonhosted.org/packages/82/5d/c00588b6cf18e1da539b45d3598d3557084990dcc4331960c15ee776ee41/numpy-2.2.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41c5a21f4a04fa86436124d388f6ed60a9343a6f767fced1a8a71c3fbca038ff", size = 20875348, upload-time = "2025-05-17T21:34:39.648Z" }, + { url = "https://files.pythonhosted.org/packages/66/ee/560deadcdde6c2f90200450d5938f63a34b37e27ebff162810f716f6a230/numpy-2.2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de749064336d37e340f640b05f24e9e3dd678c57318c7289d222a8a2f543e90c", size = 14119362, upload-time = "2025-05-17T21:35:01.241Z" }, + { url = "https://files.pythonhosted.org/packages/3c/65/4baa99f1c53b30adf0acd9a5519078871ddde8d2339dc5a7fde80d9d87da/numpy-2.2.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:894b3a42502226a1cac872f840030665f33326fc3dac8e57c607905773cdcde3", size = 5084103, upload-time = "2025-05-17T21:35:10.622Z" }, + { url = "https://files.pythonhosted.org/packages/cc/89/e5a34c071a0570cc40c9a54eb472d113eea6d002e9ae12bb3a8407fb912e/numpy-2.2.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:71594f7c51a18e728451bb50cc60a3ce4e6538822731b2933209a1f3614e9282", size = 6625382, upload-time = "2025-05-17T21:35:21.414Z" }, + { url = "https://files.pythonhosted.org/packages/f8/35/8c80729f1ff76b3921d5c9487c7ac3de9b2a103b1cd05e905b3090513510/numpy-2.2.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2618db89be1b4e05f7a1a847a9c1c0abd63e63a1607d892dd54668dd92faf87", size = 14018462, upload-time = "2025-05-17T21:35:42.174Z" }, + { url = "https://files.pythonhosted.org/packages/8c/3d/1e1db36cfd41f895d266b103df00ca5b3cbe965184df824dec5c08c6b803/numpy-2.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd83c01228a688733f1ded5201c678f0c53ecc1006ffbc404db9f7a899ac6249", size = 16527618, upload-time = "2025-05-17T21:36:06.711Z" }, + { url = "https://files.pythonhosted.org/packages/61/c6/03ed30992602c85aa3cd95b9070a514f8b3c33e31124694438d88809ae36/numpy-2.2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:37c0ca431f82cd5fa716eca9506aefcabc247fb27ba69c5062a6d3ade8cf8f49", size = 15505511, upload-time = "2025-05-17T21:36:29.965Z" }, + { url = "https://files.pythonhosted.org/packages/b7/25/5761d832a81df431e260719ec45de696414266613c9ee268394dd5ad8236/numpy-2.2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fe27749d33bb772c80dcd84ae7e8df2adc920ae8297400dabec45f0dedb3f6de", size = 18313783, upload-time = "2025-05-17T21:36:56.883Z" }, + { url = "https://files.pythonhosted.org/packages/57/0a/72d5a3527c5ebffcd47bde9162c39fae1f90138c961e5296491ce778e682/numpy-2.2.6-cp312-cp312-win32.whl", hash = "sha256:4eeaae00d789f66c7a25ac5f34b71a7035bb474e679f410e5e1a94deb24cf2d4", size = 6246506, upload-time = "2025-05-17T21:37:07.368Z" }, + { url = "https://files.pythonhosted.org/packages/36/fa/8c9210162ca1b88529ab76b41ba02d433fd54fecaf6feb70ef9f124683f1/numpy-2.2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c1f9540be57940698ed329904db803cf7a402f3fc200bfe599334c9bd84a40b2", size = 12614190, upload-time = "2025-05-17T21:37:26.213Z" }, + { url = "https://files.pythonhosted.org/packages/f9/5c/6657823f4f594f72b5471f1db1ab12e26e890bb2e41897522d134d2a3e81/numpy-2.2.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0811bb762109d9708cca4d0b13c4f67146e3c3b7cf8d34018c722adb2d957c84", size = 20867828, upload-time = "2025-05-17T21:37:56.699Z" }, + { url = "https://files.pythonhosted.org/packages/dc/9e/14520dc3dadf3c803473bd07e9b2bd1b69bc583cb2497b47000fed2fa92f/numpy-2.2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:287cc3162b6f01463ccd86be154f284d0893d2b3ed7292439ea97eafa8170e0b", size = 14143006, upload-time = "2025-05-17T21:38:18.291Z" }, + { url = "https://files.pythonhosted.org/packages/4f/06/7e96c57d90bebdce9918412087fc22ca9851cceaf5567a45c1f404480e9e/numpy-2.2.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:f1372f041402e37e5e633e586f62aa53de2eac8d98cbfb822806ce4bbefcb74d", size = 5076765, upload-time = "2025-05-17T21:38:27.319Z" }, + { url = "https://files.pythonhosted.org/packages/73/ed/63d920c23b4289fdac96ddbdd6132e9427790977d5457cd132f18e76eae0/numpy-2.2.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:55a4d33fa519660d69614a9fad433be87e5252f4b03850642f88993f7b2ca566", size = 6617736, upload-time = "2025-05-17T21:38:38.141Z" }, + { url = "https://files.pythonhosted.org/packages/85/c5/e19c8f99d83fd377ec8c7e0cf627a8049746da54afc24ef0a0cb73d5dfb5/numpy-2.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f92729c95468a2f4f15e9bb94c432a9229d0d50de67304399627a943201baa2f", size = 14010719, upload-time = "2025-05-17T21:38:58.433Z" }, + { url = "https://files.pythonhosted.org/packages/19/49/4df9123aafa7b539317bf6d342cb6d227e49f7a35b99c287a6109b13dd93/numpy-2.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bc23a79bfabc5d056d106f9befb8d50c31ced2fbc70eedb8155aec74a45798f", size = 16526072, upload-time = "2025-05-17T21:39:22.638Z" }, + { url = "https://files.pythonhosted.org/packages/b2/6c/04b5f47f4f32f7c2b0e7260442a8cbcf8168b0e1a41ff1495da42f42a14f/numpy-2.2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e3143e4451880bed956e706a3220b4e5cf6172ef05fcc397f6f36a550b1dd868", size = 15503213, upload-time = "2025-05-17T21:39:45.865Z" }, + { url = "https://files.pythonhosted.org/packages/17/0a/5cd92e352c1307640d5b6fec1b2ffb06cd0dabe7d7b8227f97933d378422/numpy-2.2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4f13750ce79751586ae2eb824ba7e1e8dba64784086c98cdbbcc6a42112ce0d", size = 18316632, upload-time = "2025-05-17T21:40:13.331Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3b/5cba2b1d88760ef86596ad0f3d484b1cbff7c115ae2429678465057c5155/numpy-2.2.6-cp313-cp313-win32.whl", hash = "sha256:5beb72339d9d4fa36522fc63802f469b13cdbe4fdab4a288f0c441b74272ebfd", size = 6244532, upload-time = "2025-05-17T21:43:46.099Z" }, + { url = "https://files.pythonhosted.org/packages/cb/3b/d58c12eafcb298d4e6d0d40216866ab15f59e55d148a5658bb3132311fcf/numpy-2.2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b0544343a702fa80c95ad5d3d608ea3599dd54d4632df855e4c8d24eb6ecfa1c", size = 12610885, upload-time = "2025-05-17T21:44:05.145Z" }, + { url = "https://files.pythonhosted.org/packages/6b/9e/4bf918b818e516322db999ac25d00c75788ddfd2d2ade4fa66f1f38097e1/numpy-2.2.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0bca768cd85ae743b2affdc762d617eddf3bcf8724435498a1e80132d04879e6", size = 20963467, upload-time = "2025-05-17T21:40:44Z" }, + { url = "https://files.pythonhosted.org/packages/61/66/d2de6b291507517ff2e438e13ff7b1e2cdbdb7cb40b3ed475377aece69f9/numpy-2.2.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fc0c5673685c508a142ca65209b4e79ed6740a4ed6b2267dbba90f34b0b3cfda", size = 14225144, upload-time = "2025-05-17T21:41:05.695Z" }, + { url = "https://files.pythonhosted.org/packages/e4/25/480387655407ead912e28ba3a820bc69af9adf13bcbe40b299d454ec011f/numpy-2.2.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:5bd4fc3ac8926b3819797a7c0e2631eb889b4118a9898c84f585a54d475b7e40", size = 5200217, upload-time = "2025-05-17T21:41:15.903Z" }, + { url = "https://files.pythonhosted.org/packages/aa/4a/6e313b5108f53dcbf3aca0c0f3e9c92f4c10ce57a0a721851f9785872895/numpy-2.2.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:fee4236c876c4e8369388054d02d0e9bb84821feb1a64dd59e137e6511a551f8", size = 6712014, upload-time = "2025-05-17T21:41:27.321Z" }, + { url = "https://files.pythonhosted.org/packages/b7/30/172c2d5c4be71fdf476e9de553443cf8e25feddbe185e0bd88b096915bcc/numpy-2.2.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1dda9c7e08dc141e0247a5b8f49cf05984955246a327d4c48bda16821947b2f", size = 14077935, upload-time = "2025-05-17T21:41:49.738Z" }, + { url = "https://files.pythonhosted.org/packages/12/fb/9e743f8d4e4d3c710902cf87af3512082ae3d43b945d5d16563f26ec251d/numpy-2.2.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f447e6acb680fd307f40d3da4852208af94afdfab89cf850986c3ca00562f4fa", size = 16600122, upload-time = "2025-05-17T21:42:14.046Z" }, + { url = "https://files.pythonhosted.org/packages/12/75/ee20da0e58d3a66f204f38916757e01e33a9737d0b22373b3eb5a27358f9/numpy-2.2.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:389d771b1623ec92636b0786bc4ae56abafad4a4c513d36a55dce14bd9ce8571", size = 15586143, upload-time = "2025-05-17T21:42:37.464Z" }, + { url = "https://files.pythonhosted.org/packages/76/95/bef5b37f29fc5e739947e9ce5179ad402875633308504a52d188302319c8/numpy-2.2.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8e9ace4a37db23421249ed236fdcdd457d671e25146786dfc96835cd951aa7c1", size = 18385260, upload-time = "2025-05-17T21:43:05.189Z" }, + { url = "https://files.pythonhosted.org/packages/09/04/f2f83279d287407cf36a7a8053a5abe7be3622a4363337338f2585e4afda/numpy-2.2.6-cp313-cp313t-win32.whl", hash = "sha256:038613e9fb8c72b0a41f025a7e4c3f0b7a1b5d768ece4796b674c8f3fe13efff", size = 6377225, upload-time = "2025-05-17T21:43:16.254Z" }, + { url = "https://files.pythonhosted.org/packages/67/0e/35082d13c09c02c011cf21570543d202ad929d961c02a147493cb0c2bdf5/numpy-2.2.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6031dd6dfecc0cf9f668681a37648373bddd6421fff6c66ec1624eed0180ee06", size = 12771374, upload-time = "2025-05-17T21:43:35.479Z" }, + { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" }, + { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" }, + { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" }, + { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" }, +] + +[[package]] +name = "numpy" +version = "2.3.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.11'", +] +sdist = { url = "https://files.pythonhosted.org/packages/37/7d/3fec4199c5ffb892bed55cff901e4f39a58c81df9c44c280499e92cad264/numpy-2.3.2.tar.gz", hash = "sha256:e0486a11ec30cdecb53f184d496d1c6a20786c81e55e41640270130056f8ee48", size = 20489306, upload-time = "2025-07-24T21:32:07.553Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/26/1320083986108998bd487e2931eed2aeedf914b6e8905431487543ec911d/numpy-2.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:852ae5bed3478b92f093e30f785c98e0cb62fa0a939ed057c31716e18a7a22b9", size = 21259016, upload-time = "2025-07-24T20:24:35.214Z" }, + { url = "https://files.pythonhosted.org/packages/c4/2b/792b341463fa93fc7e55abbdbe87dac316c5b8cb5e94fb7a59fb6fa0cda5/numpy-2.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7a0e27186e781a69959d0230dd9909b5e26024f8da10683bd6344baea1885168", size = 14451158, upload-time = "2025-07-24T20:24:58.397Z" }, + { url = "https://files.pythonhosted.org/packages/b7/13/e792d7209261afb0c9f4759ffef6135b35c77c6349a151f488f531d13595/numpy-2.3.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:f0a1a8476ad77a228e41619af2fa9505cf69df928e9aaa165746584ea17fed2b", size = 5379817, upload-time = "2025-07-24T20:25:07.746Z" }, + { url = "https://files.pythonhosted.org/packages/49/ce/055274fcba4107c022b2113a213c7287346563f48d62e8d2a5176ad93217/numpy-2.3.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:cbc95b3813920145032412f7e33d12080f11dc776262df1712e1638207dde9e8", size = 6913606, upload-time = "2025-07-24T20:25:18.84Z" }, + { url = "https://files.pythonhosted.org/packages/17/f2/e4d72e6bc5ff01e2ab613dc198d560714971900c03674b41947e38606502/numpy-2.3.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f75018be4980a7324edc5930fe39aa391d5734531b1926968605416ff58c332d", size = 14589652, upload-time = "2025-07-24T20:25:40.356Z" }, + { url = "https://files.pythonhosted.org/packages/c8/b0/fbeee3000a51ebf7222016e2939b5c5ecf8000a19555d04a18f1e02521b8/numpy-2.3.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20b8200721840f5621b7bd03f8dcd78de33ec522fc40dc2641aa09537df010c3", size = 16938816, upload-time = "2025-07-24T20:26:05.721Z" }, + { url = "https://files.pythonhosted.org/packages/a9/ec/2f6c45c3484cc159621ea8fc000ac5a86f1575f090cac78ac27193ce82cd/numpy-2.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f91e5c028504660d606340a084db4b216567ded1056ea2b4be4f9d10b67197f", size = 16370512, upload-time = "2025-07-24T20:26:30.545Z" }, + { url = "https://files.pythonhosted.org/packages/b5/01/dd67cf511850bd7aefd6347aaae0956ed415abea741ae107834aae7d6d4e/numpy-2.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fb1752a3bb9a3ad2d6b090b88a9a0ae1cd6f004ef95f75825e2f382c183b2097", size = 18884947, upload-time = "2025-07-24T20:26:58.24Z" }, + { url = "https://files.pythonhosted.org/packages/a7/17/2cf60fd3e6a61d006778735edf67a222787a8c1a7842aed43ef96d777446/numpy-2.3.2-cp311-cp311-win32.whl", hash = "sha256:4ae6863868aaee2f57503c7a5052b3a2807cf7a3914475e637a0ecd366ced220", size = 6599494, upload-time = "2025-07-24T20:27:09.786Z" }, + { url = "https://files.pythonhosted.org/packages/d5/03/0eade211c504bda872a594f045f98ddcc6caef2b7c63610946845e304d3f/numpy-2.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:240259d6564f1c65424bcd10f435145a7644a65a6811cfc3201c4a429ba79170", size = 13087889, upload-time = "2025-07-24T20:27:29.558Z" }, + { url = "https://files.pythonhosted.org/packages/13/32/2c7979d39dafb2a25087e12310fc7f3b9d3c7d960df4f4bc97955ae0ce1d/numpy-2.3.2-cp311-cp311-win_arm64.whl", hash = "sha256:4209f874d45f921bde2cff1ffcd8a3695f545ad2ffbef6d3d3c6768162efab89", size = 10459560, upload-time = "2025-07-24T20:27:46.803Z" }, + { url = "https://files.pythonhosted.org/packages/00/6d/745dd1c1c5c284d17725e5c802ca4d45cfc6803519d777f087b71c9f4069/numpy-2.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bc3186bea41fae9d8e90c2b4fb5f0a1f5a690682da79b92574d63f56b529080b", size = 20956420, upload-time = "2025-07-24T20:28:18.002Z" }, + { url = "https://files.pythonhosted.org/packages/bc/96/e7b533ea5740641dd62b07a790af5d9d8fec36000b8e2d0472bd7574105f/numpy-2.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f4f0215edb189048a3c03bd5b19345bdfa7b45a7a6f72ae5945d2a28272727f", size = 14184660, upload-time = "2025-07-24T20:28:39.522Z" }, + { url = "https://files.pythonhosted.org/packages/2b/53/102c6122db45a62aa20d1b18c9986f67e6b97e0d6fbc1ae13e3e4c84430c/numpy-2.3.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:8b1224a734cd509f70816455c3cffe13a4f599b1bf7130f913ba0e2c0b2006c0", size = 5113382, upload-time = "2025-07-24T20:28:48.544Z" }, + { url = "https://files.pythonhosted.org/packages/2b/21/376257efcbf63e624250717e82b4fae93d60178f09eb03ed766dbb48ec9c/numpy-2.3.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3dcf02866b977a38ba3ec10215220609ab9667378a9e2150615673f3ffd6c73b", size = 6647258, upload-time = "2025-07-24T20:28:59.104Z" }, + { url = "https://files.pythonhosted.org/packages/91/ba/f4ebf257f08affa464fe6036e13f2bf9d4642a40228781dc1235da81be9f/numpy-2.3.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:572d5512df5470f50ada8d1972c5f1082d9a0b7aa5944db8084077570cf98370", size = 14281409, upload-time = "2025-07-24T20:40:30.298Z" }, + { url = "https://files.pythonhosted.org/packages/59/ef/f96536f1df42c668cbacb727a8c6da7afc9c05ece6d558927fb1722693e1/numpy-2.3.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8145dd6d10df13c559d1e4314df29695613575183fa2e2d11fac4c208c8a1f73", size = 16641317, upload-time = "2025-07-24T20:40:56.625Z" }, + { url = "https://files.pythonhosted.org/packages/f6/a7/af813a7b4f9a42f498dde8a4c6fcbff8100eed00182cc91dbaf095645f38/numpy-2.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:103ea7063fa624af04a791c39f97070bf93b96d7af7eb23530cd087dc8dbe9dc", size = 16056262, upload-time = "2025-07-24T20:41:20.797Z" }, + { url = "https://files.pythonhosted.org/packages/8b/5d/41c4ef8404caaa7f05ed1cfb06afe16a25895260eacbd29b4d84dff2920b/numpy-2.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc927d7f289d14f5e037be917539620603294454130b6de200091e23d27dc9be", size = 18579342, upload-time = "2025-07-24T20:41:50.753Z" }, + { url = "https://files.pythonhosted.org/packages/a1/4f/9950e44c5a11636f4a3af6e825ec23003475cc9a466edb7a759ed3ea63bd/numpy-2.3.2-cp312-cp312-win32.whl", hash = "sha256:d95f59afe7f808c103be692175008bab926b59309ade3e6d25009e9a171f7036", size = 6320610, upload-time = "2025-07-24T20:42:01.551Z" }, + { url = "https://files.pythonhosted.org/packages/7c/2f/244643a5ce54a94f0a9a2ab578189c061e4a87c002e037b0829dd77293b6/numpy-2.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:9e196ade2400c0c737d93465327d1ae7c06c7cb8a1756121ebf54b06ca183c7f", size = 12786292, upload-time = "2025-07-24T20:42:20.738Z" }, + { url = "https://files.pythonhosted.org/packages/54/cd/7b5f49d5d78db7badab22d8323c1b6ae458fbf86c4fdfa194ab3cd4eb39b/numpy-2.3.2-cp312-cp312-win_arm64.whl", hash = "sha256:ee807923782faaf60d0d7331f5e86da7d5e3079e28b291973c545476c2b00d07", size = 10194071, upload-time = "2025-07-24T20:42:36.657Z" }, + { url = "https://files.pythonhosted.org/packages/1c/c0/c6bb172c916b00700ed3bf71cb56175fd1f7dbecebf8353545d0b5519f6c/numpy-2.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c8d9727f5316a256425892b043736d63e89ed15bbfe6556c5ff4d9d4448ff3b3", size = 20949074, upload-time = "2025-07-24T20:43:07.813Z" }, + { url = "https://files.pythonhosted.org/packages/20/4e/c116466d22acaf4573e58421c956c6076dc526e24a6be0903219775d862e/numpy-2.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:efc81393f25f14d11c9d161e46e6ee348637c0a1e8a54bf9dedc472a3fae993b", size = 14177311, upload-time = "2025-07-24T20:43:29.335Z" }, + { url = "https://files.pythonhosted.org/packages/78/45/d4698c182895af189c463fc91d70805d455a227261d950e4e0f1310c2550/numpy-2.3.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:dd937f088a2df683cbb79dda9a772b62a3e5a8a7e76690612c2737f38c6ef1b6", size = 5106022, upload-time = "2025-07-24T20:43:37.999Z" }, + { url = "https://files.pythonhosted.org/packages/9f/76/3e6880fef4420179309dba72a8c11f6166c431cf6dee54c577af8906f914/numpy-2.3.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:11e58218c0c46c80509186e460d79fbdc9ca1eb8d8aee39d8f2dc768eb781089", size = 6640135, upload-time = "2025-07-24T20:43:49.28Z" }, + { url = "https://files.pythonhosted.org/packages/34/fa/87ff7f25b3c4ce9085a62554460b7db686fef1e0207e8977795c7b7d7ba1/numpy-2.3.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5ad4ebcb683a1f99f4f392cc522ee20a18b2bb12a2c1c42c3d48d5a1adc9d3d2", size = 14278147, upload-time = "2025-07-24T20:44:10.328Z" }, + { url = "https://files.pythonhosted.org/packages/1d/0f/571b2c7a3833ae419fe69ff7b479a78d313581785203cc70a8db90121b9a/numpy-2.3.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:938065908d1d869c7d75d8ec45f735a034771c6ea07088867f713d1cd3bbbe4f", size = 16635989, upload-time = "2025-07-24T20:44:34.88Z" }, + { url = "https://files.pythonhosted.org/packages/24/5a/84ae8dca9c9a4c592fe11340b36a86ffa9fd3e40513198daf8a97839345c/numpy-2.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:66459dccc65d8ec98cc7df61307b64bf9e08101f9598755d42d8ae65d9a7a6ee", size = 16053052, upload-time = "2025-07-24T20:44:58.872Z" }, + { url = "https://files.pythonhosted.org/packages/57/7c/e5725d99a9133b9813fcf148d3f858df98511686e853169dbaf63aec6097/numpy-2.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a7af9ed2aa9ec5950daf05bb11abc4076a108bd3c7db9aa7251d5f107079b6a6", size = 18577955, upload-time = "2025-07-24T20:45:26.714Z" }, + { url = "https://files.pythonhosted.org/packages/ae/11/7c546fcf42145f29b71e4d6f429e96d8d68e5a7ba1830b2e68d7418f0bbd/numpy-2.3.2-cp313-cp313-win32.whl", hash = "sha256:906a30249315f9c8e17b085cc5f87d3f369b35fedd0051d4a84686967bdbbd0b", size = 6311843, upload-time = "2025-07-24T20:49:24.444Z" }, + { url = "https://files.pythonhosted.org/packages/aa/6f/a428fd1cb7ed39b4280d057720fed5121b0d7754fd2a9768640160f5517b/numpy-2.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:c63d95dc9d67b676e9108fe0d2182987ccb0f11933c1e8959f42fa0da8d4fa56", size = 12782876, upload-time = "2025-07-24T20:49:43.227Z" }, + { url = "https://files.pythonhosted.org/packages/65/85/4ea455c9040a12595fb6c43f2c217257c7b52dd0ba332c6a6c1d28b289fe/numpy-2.3.2-cp313-cp313-win_arm64.whl", hash = "sha256:b05a89f2fb84d21235f93de47129dd4f11c16f64c87c33f5e284e6a3a54e43f2", size = 10192786, upload-time = "2025-07-24T20:49:59.443Z" }, + { url = "https://files.pythonhosted.org/packages/80/23/8278f40282d10c3f258ec3ff1b103d4994bcad78b0cba9208317f6bb73da/numpy-2.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4e6ecfeddfa83b02318f4d84acf15fbdbf9ded18e46989a15a8b6995dfbf85ab", size = 21047395, upload-time = "2025-07-24T20:45:58.821Z" }, + { url = "https://files.pythonhosted.org/packages/1f/2d/624f2ce4a5df52628b4ccd16a4f9437b37c35f4f8a50d00e962aae6efd7a/numpy-2.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:508b0eada3eded10a3b55725b40806a4b855961040180028f52580c4729916a2", size = 14300374, upload-time = "2025-07-24T20:46:20.207Z" }, + { url = "https://files.pythonhosted.org/packages/f6/62/ff1e512cdbb829b80a6bd08318a58698867bca0ca2499d101b4af063ee97/numpy-2.3.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:754d6755d9a7588bdc6ac47dc4ee97867271b17cee39cb87aef079574366db0a", size = 5228864, upload-time = "2025-07-24T20:46:30.58Z" }, + { url = "https://files.pythonhosted.org/packages/7d/8e/74bc18078fff03192d4032cfa99d5a5ca937807136d6f5790ce07ca53515/numpy-2.3.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:a9f66e7d2b2d7712410d3bc5684149040ef5f19856f20277cd17ea83e5006286", size = 6737533, upload-time = "2025-07-24T20:46:46.111Z" }, + { url = "https://files.pythonhosted.org/packages/19/ea/0731efe2c9073ccca5698ef6a8c3667c4cf4eea53fcdcd0b50140aba03bc/numpy-2.3.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de6ea4e5a65d5a90c7d286ddff2b87f3f4ad61faa3db8dabe936b34c2275b6f8", size = 14352007, upload-time = "2025-07-24T20:47:07.1Z" }, + { url = "https://files.pythonhosted.org/packages/cf/90/36be0865f16dfed20f4bc7f75235b963d5939707d4b591f086777412ff7b/numpy-2.3.2-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3ef07ec8cbc8fc9e369c8dcd52019510c12da4de81367d8b20bc692aa07573a", size = 16701914, upload-time = "2025-07-24T20:47:32.459Z" }, + { url = "https://files.pythonhosted.org/packages/94/30/06cd055e24cb6c38e5989a9e747042b4e723535758e6153f11afea88c01b/numpy-2.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:27c9f90e7481275c7800dc9c24b7cc40ace3fdb970ae4d21eaff983a32f70c91", size = 16132708, upload-time = "2025-07-24T20:47:58.129Z" }, + { url = "https://files.pythonhosted.org/packages/9a/14/ecede608ea73e58267fd7cb78f42341b3b37ba576e778a1a06baffbe585c/numpy-2.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:07b62978075b67eee4065b166d000d457c82a1efe726cce608b9db9dd66a73a5", size = 18651678, upload-time = "2025-07-24T20:48:25.402Z" }, + { url = "https://files.pythonhosted.org/packages/40/f3/2fe6066b8d07c3685509bc24d56386534c008b462a488b7f503ba82b8923/numpy-2.3.2-cp313-cp313t-win32.whl", hash = "sha256:c771cfac34a4f2c0de8e8c97312d07d64fd8f8ed45bc9f5726a7e947270152b5", size = 6441832, upload-time = "2025-07-24T20:48:37.181Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ba/0937d66d05204d8f28630c9c60bc3eda68824abde4cf756c4d6aad03b0c6/numpy-2.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:72dbebb2dcc8305c431b2836bcc66af967df91be793d63a24e3d9b741374c450", size = 12927049, upload-time = "2025-07-24T20:48:56.24Z" }, + { url = "https://files.pythonhosted.org/packages/e9/ed/13542dd59c104d5e654dfa2ac282c199ba64846a74c2c4bcdbc3a0f75df1/numpy-2.3.2-cp313-cp313t-win_arm64.whl", hash = "sha256:72c6df2267e926a6d5286b0a6d556ebe49eae261062059317837fda12ddf0c1a", size = 10262935, upload-time = "2025-07-24T20:49:13.136Z" }, + { url = "https://files.pythonhosted.org/packages/c9/7c/7659048aaf498f7611b783e000c7268fcc4dcf0ce21cd10aad7b2e8f9591/numpy-2.3.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:448a66d052d0cf14ce9865d159bfc403282c9bc7bb2a31b03cc18b651eca8b1a", size = 20950906, upload-time = "2025-07-24T20:50:30.346Z" }, + { url = "https://files.pythonhosted.org/packages/80/db/984bea9d4ddf7112a04cfdfb22b1050af5757864cfffe8e09e44b7f11a10/numpy-2.3.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:546aaf78e81b4081b2eba1d105c3b34064783027a06b3ab20b6eba21fb64132b", size = 14185607, upload-time = "2025-07-24T20:50:51.923Z" }, + { url = "https://files.pythonhosted.org/packages/e4/76/b3d6f414f4eca568f469ac112a3b510938d892bc5a6c190cb883af080b77/numpy-2.3.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:87c930d52f45df092f7578889711a0768094debf73cfcde105e2d66954358125", size = 5114110, upload-time = "2025-07-24T20:51:01.041Z" }, + { url = "https://files.pythonhosted.org/packages/9e/d2/6f5e6826abd6bca52392ed88fe44a4b52aacb60567ac3bc86c67834c3a56/numpy-2.3.2-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:8dc082ea901a62edb8f59713c6a7e28a85daddcb67454c839de57656478f5b19", size = 6642050, upload-time = "2025-07-24T20:51:11.64Z" }, + { url = "https://files.pythonhosted.org/packages/c4/43/f12b2ade99199e39c73ad182f103f9d9791f48d885c600c8e05927865baf/numpy-2.3.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:af58de8745f7fa9ca1c0c7c943616c6fe28e75d0c81f5c295810e3c83b5be92f", size = 14296292, upload-time = "2025-07-24T20:51:33.488Z" }, + { url = "https://files.pythonhosted.org/packages/5d/f9/77c07d94bf110a916b17210fac38680ed8734c236bfed9982fd8524a7b47/numpy-2.3.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed5527c4cf10f16c6d0b6bee1f89958bccb0ad2522c8cadc2efd318bcd545f5", size = 16638913, upload-time = "2025-07-24T20:51:58.517Z" }, + { url = "https://files.pythonhosted.org/packages/9b/d1/9d9f2c8ea399cc05cfff8a7437453bd4e7d894373a93cdc46361bbb49a7d/numpy-2.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:095737ed986e00393ec18ec0b21b47c22889ae4b0cd2d5e88342e08b01141f58", size = 16071180, upload-time = "2025-07-24T20:52:22.827Z" }, + { url = "https://files.pythonhosted.org/packages/4c/41/82e2c68aff2a0c9bf315e47d61951099fed65d8cb2c8d9dc388cb87e947e/numpy-2.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5e40e80299607f597e1a8a247ff8d71d79c5b52baa11cc1cce30aa92d2da6e0", size = 18576809, upload-time = "2025-07-24T20:52:51.015Z" }, + { url = "https://files.pythonhosted.org/packages/14/14/4b4fd3efb0837ed252d0f583c5c35a75121038a8c4e065f2c259be06d2d8/numpy-2.3.2-cp314-cp314-win32.whl", hash = "sha256:7d6e390423cc1f76e1b8108c9b6889d20a7a1f59d9a60cac4a050fa734d6c1e2", size = 6366410, upload-time = "2025-07-24T20:56:44.949Z" }, + { url = "https://files.pythonhosted.org/packages/11/9e/b4c24a6b8467b61aced5c8dc7dcfce23621baa2e17f661edb2444a418040/numpy-2.3.2-cp314-cp314-win_amd64.whl", hash = "sha256:b9d0878b21e3918d76d2209c924ebb272340da1fb51abc00f986c258cd5e957b", size = 12918821, upload-time = "2025-07-24T20:57:06.479Z" }, + { url = "https://files.pythonhosted.org/packages/0e/0f/0dc44007c70b1007c1cef86b06986a3812dd7106d8f946c09cfa75782556/numpy-2.3.2-cp314-cp314-win_arm64.whl", hash = "sha256:2738534837c6a1d0c39340a190177d7d66fdf432894f469728da901f8f6dc910", size = 10477303, upload-time = "2025-07-24T20:57:22.879Z" }, + { url = "https://files.pythonhosted.org/packages/8b/3e/075752b79140b78ddfc9c0a1634d234cfdbc6f9bbbfa6b7504e445ad7d19/numpy-2.3.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:4d002ecf7c9b53240be3bb69d80f86ddbd34078bae04d87be81c1f58466f264e", size = 21047524, upload-time = "2025-07-24T20:53:22.086Z" }, + { url = "https://files.pythonhosted.org/packages/fe/6d/60e8247564a72426570d0e0ea1151b95ce5bd2f1597bb878a18d32aec855/numpy-2.3.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:293b2192c6bcce487dbc6326de5853787f870aeb6c43f8f9c6496db5b1781e45", size = 14300519, upload-time = "2025-07-24T20:53:44.053Z" }, + { url = "https://files.pythonhosted.org/packages/4d/73/d8326c442cd428d47a067070c3ac6cc3b651a6e53613a1668342a12d4479/numpy-2.3.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:0a4f2021a6da53a0d580d6ef5db29947025ae8b35b3250141805ea9a32bbe86b", size = 5228972, upload-time = "2025-07-24T20:53:53.81Z" }, + { url = "https://files.pythonhosted.org/packages/34/2e/e71b2d6dad075271e7079db776196829019b90ce3ece5c69639e4f6fdc44/numpy-2.3.2-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:9c144440db4bf3bb6372d2c3e49834cc0ff7bb4c24975ab33e01199e645416f2", size = 6737439, upload-time = "2025-07-24T20:54:04.742Z" }, + { url = "https://files.pythonhosted.org/packages/15/b0/d004bcd56c2c5e0500ffc65385eb6d569ffd3363cb5e593ae742749b2daa/numpy-2.3.2-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f92d6c2a8535dc4fe4419562294ff957f83a16ebdec66df0805e473ffaad8bd0", size = 14352479, upload-time = "2025-07-24T20:54:25.819Z" }, + { url = "https://files.pythonhosted.org/packages/11/e3/285142fcff8721e0c99b51686426165059874c150ea9ab898e12a492e291/numpy-2.3.2-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cefc2219baa48e468e3db7e706305fcd0c095534a192a08f31e98d83a7d45fb0", size = 16702805, upload-time = "2025-07-24T20:54:50.814Z" }, + { url = "https://files.pythonhosted.org/packages/33/c3/33b56b0e47e604af2c7cd065edca892d180f5899599b76830652875249a3/numpy-2.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:76c3e9501ceb50b2ff3824c3589d5d1ab4ac857b0ee3f8f49629d0de55ecf7c2", size = 16133830, upload-time = "2025-07-24T20:55:17.306Z" }, + { url = "https://files.pythonhosted.org/packages/6e/ae/7b1476a1f4d6a48bc669b8deb09939c56dd2a439db1ab03017844374fb67/numpy-2.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:122bf5ed9a0221b3419672493878ba4967121514b1d7d4656a7580cd11dddcbf", size = 18652665, upload-time = "2025-07-24T20:55:46.665Z" }, + { url = "https://files.pythonhosted.org/packages/14/ba/5b5c9978c4bb161034148ade2de9db44ec316fab89ce8c400db0e0c81f86/numpy-2.3.2-cp314-cp314t-win32.whl", hash = "sha256:6f1ae3dcb840edccc45af496f312528c15b1f79ac318169d094e85e4bb35fdf1", size = 6514777, upload-time = "2025-07-24T20:55:57.66Z" }, + { url = "https://files.pythonhosted.org/packages/eb/46/3dbaf0ae7c17cdc46b9f662c56da2054887b8d9e737c1476f335c83d33db/numpy-2.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:087ffc25890d89a43536f75c5fe8770922008758e8eeeef61733957041ed2f9b", size = 13111856, upload-time = "2025-07-24T20:56:17.318Z" }, + { url = "https://files.pythonhosted.org/packages/c1/9e/1652778bce745a67b5fe05adde60ed362d38eb17d919a540e813d30f6874/numpy-2.3.2-cp314-cp314t-win_arm64.whl", hash = "sha256:092aeb3449833ea9c0bf0089d70c29ae480685dd2377ec9cdbbb620257f84631", size = 10544226, upload-time = "2025-07-24T20:56:34.509Z" }, + { url = "https://files.pythonhosted.org/packages/cf/ea/50ebc91d28b275b23b7128ef25c3d08152bc4068f42742867e07a870a42a/numpy-2.3.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:14a91ebac98813a49bc6aa1a0dfc09513dcec1d97eaf31ca21a87221a1cdcb15", size = 21130338, upload-time = "2025-07-24T20:57:54.37Z" }, + { url = "https://files.pythonhosted.org/packages/9f/57/cdd5eac00dd5f137277355c318a955c0d8fb8aa486020c22afd305f8b88f/numpy-2.3.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:71669b5daae692189540cffc4c439468d35a3f84f0c88b078ecd94337f6cb0ec", size = 14375776, upload-time = "2025-07-24T20:58:16.303Z" }, + { url = "https://files.pythonhosted.org/packages/83/85/27280c7f34fcd305c2209c0cdca4d70775e4859a9eaa92f850087f8dea50/numpy-2.3.2-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:69779198d9caee6e547adb933941ed7520f896fd9656834c300bdf4dd8642712", size = 5304882, upload-time = "2025-07-24T20:58:26.199Z" }, + { url = "https://files.pythonhosted.org/packages/48/b4/6500b24d278e15dd796f43824e69939d00981d37d9779e32499e823aa0aa/numpy-2.3.2-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:2c3271cc4097beb5a60f010bcc1cc204b300bb3eafb4399376418a83a1c6373c", size = 6818405, upload-time = "2025-07-24T20:58:37.341Z" }, + { url = "https://files.pythonhosted.org/packages/9b/c9/142c1e03f199d202da8e980c2496213509291b6024fd2735ad28ae7065c7/numpy-2.3.2-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8446acd11fe3dc1830568c941d44449fd5cb83068e5c70bd5a470d323d448296", size = 14419651, upload-time = "2025-07-24T20:58:59.048Z" }, + { url = "https://files.pythonhosted.org/packages/8b/95/8023e87cbea31a750a6c00ff9427d65ebc5fef104a136bfa69f76266d614/numpy-2.3.2-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aa098a5ab53fa407fded5870865c6275a5cd4101cfdef8d6fafc48286a96e981", size = 16760166, upload-time = "2025-07-24T21:28:56.38Z" }, + { url = "https://files.pythonhosted.org/packages/78/e3/6690b3f85a05506733c7e90b577e4762517404ea78bab2ca3a5cb1aeb78d/numpy-2.3.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6936aff90dda378c09bea075af0d9c675fe3a977a9d2402f95a87f440f59f619", size = 12977811, upload-time = "2025-07-24T21:29:18.234Z" }, +] + +[[package]] +name = "openseriesbellshade" +version = "1.7.0" +source = { editable = "." } +dependencies = [ + { name = "colorama" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, +] + +[package.metadata] +requires-dist = [ + { name = "colorama" }, + { name = "numpy" }, +] From aabeeafdc0138498fcc096d746c578380b22ffa7 Mon Sep 17 00:00:00 2001 From: slowy07 Date: Wed, 30 Jul 2025 11:44:34 +0700 Subject: [PATCH 2/5] chore: update pytest Signed-off-by: slowy07 --- .github/workflows/pythontesting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pythontesting.yml b/.github/workflows/pythontesting.yml index 8629663..494fde6 100644 --- a/.github/workflows/pythontesting.yml +++ b/.github/workflows/pythontesting.yml @@ -37,4 +37,4 @@ jobs: # testing kode dengan pytest - name: testing kode dengan pytest run: | - pytest testing/main_test.py --verbose + pytest -v From d9c528dd0e4b6016c2d8f732ae8f6524fb4721d3 Mon Sep 17 00:00:00 2001 From: slowy07 Date: Wed, 30 Jul 2025 11:50:20 +0700 Subject: [PATCH 3/5] fix: remove unused code Signed-off-by: slowy07 --- OpenSeries/bilangan_istimewa.py | 4 ++-- OpenSeries/util/error.py | 2 +- testing/bilangan_istimewa_test.py | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/OpenSeries/bilangan_istimewa.py b/OpenSeries/bilangan_istimewa.py index 0b2bfca..b658227 100644 --- a/OpenSeries/bilangan_istimewa.py +++ b/OpenSeries/bilangan_istimewa.py @@ -78,7 +78,7 @@ def angka_pronic(angka: int) -> Union[str, ErrorTipeData]: benar, bukan = "angka pronic", "bukan angka pronic" # cek dari tipe data angka if not isinstance(angka, int): - return error.ErrorTipeData(["int"]) + return ErrorTipeData(["int"]) if angka < 0 or angka % 2 == 1: return bukan.capitalize() angka_pangkat = int(angka**0.5) @@ -103,7 +103,7 @@ def angka_segitiga(angka: int) -> Union[int, ErrorTipeData, Error]: """ # jika tipe data dari angka tidak integer if not isinstance(angka, int): - return error.ErrorTipeData(["int"]) + return ErrorTipeData(["int"]) # jika value dari angka diisi nilai negatif if angka < 0: return Error("angka tidak boleh negatif") diff --git a/OpenSeries/util/error.py b/OpenSeries/util/error.py index 5cdda65..25c8c6c 100644 --- a/OpenSeries/util/error.py +++ b/OpenSeries/util/error.py @@ -13,7 +13,7 @@ # mocking modul warna jika error import try: from util import constant as warna -except ImportError as error: +except ImportError: # mocking object jika module warna tidak tersedia class MockWarna: """mock class untuk warna jika modul gagal import""" diff --git a/testing/bilangan_istimewa_test.py b/testing/bilangan_istimewa_test.py index febb96c..04e9516 100644 --- a/testing/bilangan_istimewa_test.py +++ b/testing/bilangan_istimewa_test.py @@ -1,5 +1,3 @@ -import numpy as np -import pytest from OpenSeries.bilangan_istimewa import angka_armstrong From 2eb529533ba5e0162e508a1b4cd385498f81757c Mon Sep 17 00:00:00 2001 From: slowy07 Date: Thu, 31 Jul 2025 11:02:15 +0700 Subject: [PATCH 4/5] chore: update fungsi kecepatan Signed-off-by: slowy07 --- OpenSeries/fisika.py | 61 +++-- OpenSeries/fisika_calc/__init__.py | 0 OpenSeries/fisika_calc/kecepatan_calc.py | 270 +++++++++++++++++++++++ example/fisika/kecepatan.py | 10 +- testing/fisika_test.py | 18 ++ 5 files changed, 337 insertions(+), 22 deletions(-) create mode 100644 OpenSeries/fisika_calc/__init__.py create mode 100644 OpenSeries/fisika_calc/kecepatan_calc.py create mode 100644 testing/fisika_test.py diff --git a/OpenSeries/fisika.py b/OpenSeries/fisika.py index ae4c02f..e38661e 100644 --- a/OpenSeries/fisika.py +++ b/OpenSeries/fisika.py @@ -1,32 +1,57 @@ -from OpenSeries.util import error as error +import numpy +from .util import error as error from typing import Union +from .fisika_calc import kecepatan_calc def kecepatan( - jarak: Union[float, int], waktu: Union[float, int] -) -> Union[float, error.ErrorDibagiNol, error.ErrorTipeData]: + jarak: Union[float, int, list[Union[float, int]], numpy.ndarray], + waktu: Union[float, int, list[Union[float, int]], numpy.ndarray], +) -> Union[ + float, + list[Union[float, error.ErrorDibagiNol, error.ErrorTipeData, error.Error]], + error.ErrorDibagiNol, + error.ErrorTipeData, + error.Error, +]: """ - fungsi untuk menghitung kecepatan + fungsi menghitung kecepatan benda antara satu dan lainnya Parameter: - jarak (float atau int): jarak tempuh - waktu (float atau int): waktu tempuh (sekon) + jarak (list, numpy.ndarray, float, int): jarak yang ditempuh + waktu (list, numpy.ndarray, float, int): waktu yang ditempuh Return: - float: hasil dari jarak / waktu - error.ErrorTipeData: error jika tipe data data salah - error.ErrorDibagiNol: error jika angka dibagikan dengan 0 + (list, numpy.ndarray, float, int): hasil perhitungan antara jarak dan waktu + menggunakan pendekatan rumus v = s / t + + Example: + + >>> kecepatan(100, 10) + 10.0 + + >>> kecepatan([100, 200, 300], [10, 20, 30]) + [10.0, 10.0, 10.0] + + >>> import numpy as np + >>> kecepatan(np.array([100, 20]), np.array([10, 20])) + [10.0, 10.0] """ - # mengecek apakah variable tersebut bertipe data int atau float - # jika tidak maka error - if all(isinstance(data, (float, int)) for data in [jarak, waktu]): - try: - return jarak / waktu - except ZeroDivisionError: - # error jika hasil pembagian dibagikan dengan 0 - return error.ErrorDibagiNol() + processor = kecepatan_calc.KecepatanService.get_instance() + if isinstance(jarak, (int, float, numpy.integer, numpy.floating)) and isinstance( + waktu, (int, float, numpy.integer, numpy.floating) + ): + return processor.hitung_single(jarak, waktu) + elif isinstance(jarak, (list, numpy.ndarray)) and isinstance( + waktu, (list, numpy.ndarray) + ): + return processor.hitung_multiple(jarak, waktu) else: - return error.ErrorTipeData(["int", "float"]) + return error.ErrorTipeData( + tipe_diharapkan=["sama-sama single atau sama-sama vektor"], + tipe_sebenarnya=f"jarak: {type(jarak).__name__}, waktu: {type(waktu).__name__}", + nama_parameter="jarak dan waktu", + ) def percepatan( diff --git a/OpenSeries/fisika_calc/__init__.py b/OpenSeries/fisika_calc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/OpenSeries/fisika_calc/kecepatan_calc.py b/OpenSeries/fisika_calc/kecepatan_calc.py new file mode 100644 index 0000000..910a2bb --- /dev/null +++ b/OpenSeries/fisika_calc/kecepatan_calc.py @@ -0,0 +1,270 @@ +from abc import ABC, abstractmethod +from typing import Union + +from OpenSeries.util.error import ErrorDibagiNol, ErrorTipeData, Error +import numpy as np + + +class Validator: + @staticmethod + def validasi_numerik( + nilai: Union[float, int], nama_parameter: str = "nilai" + ) -> Union[float, int]: + if not isinstance(nilai, (int, float, np.integer, np.floating)): + raise ErrorTipeData( + tipe_diharapkan=["int", "float"], + tipe_sebenarnya=type(nilai).__name__, + nama_parameter=nama_parameter, + ) + return float(nilai) if isinstance(nilai, (int, np.integer)) else nilai + + @staticmethod + def validasi_list_numerik( + daftar_nilai: Union[list[Union[float, int]], np.ndarray], + nama_parameter: str = "daftar_nilai", + ) -> list[Union[float, int]]: + if not isinstance(daftar_nilai, (list, np.ndarray)): + raise ErrorTipeData( + tipe_diharapkan=["list", "numpy.ndarray"], + tipe_sebenarnya=type(daftar_nilai).__name__, + nama_parameter=nama_parameter, + ) + + hasil_validasi = [] + for i, item in enumerate(daftar_nilai): + try: + hasil_validasi.append( + Validator.validasi_numerik(item, f"{nama_parameter}[{i}]") + ) + except ErrorTipeData as e: + raise e + + return hasil_validasi + + +class Kecepatan(ABC): + @abstractmethod + def hitung_kecepatan( + self, jarak: Union[float, int], waktu: Union[float, int] + ) -> float: + pass + + +class KecepatanImpl(Kecepatan): + def hitung_kecepatan( + self, jarak: Union[float, int], waktu: Union[float, int] + ) -> float: + jarak = Validator.validasi_numerik(jarak, "jarak") + waktu = Validator.validasi_numerik(waktu, "waktu") + + if waktu == 0: + raise ErrorDibagiNol(operasi="kecepatan", dividend=jarak) + + return jarak / waktu + + +class KecepatanNumpy(Kecepatan): + def hitung_kecepatan( + self, jarak: Union[float, int], waktu: Union[float, int] + ) -> float: + jarak = Validator.validasi_numerik(jarak, "jarak") + waktu = Validator.validasi_numerik(waktu, "waktu") + + if waktu == 0: + raise ErrorDibagiNol(operasi="kecepatan", dividend=jarak) + + return np.divide(jarak, waktu) + + +class KecepatanProcessor: + """ + Kelas utama untuk memproses berbagai operasi terkait perhitungan kecepatan. + + Mendukung berbagai tipe data input dan menyediakan berbagai metode pemrosesan. + """ + + def __init__(self, use_numpy: bool = False): + """ + Inisialisasi processor kecepatan. + + Args: + use_numpy (bool): Jika True, gunakan implementasi NumPy untuk performa lebih baik. + """ + self.calculator = KecepatanNumpy() if use_numpy else KecepatanImpl() + self.use_numpy = use_numpy + + def hitung_single( + self, jarak: Union[float, int], waktu: Union[float, int] + ) -> Union[float, ErrorDibagiNol, ErrorTipeData, Error]: + """ + Menghitung kecepatan untuk satu pasang jarak dan waktu. + + Args: + jarak: Jarak tempuh. + waktu: Waktu tempuh. + + Returns: + Union[float, ErrorDibagiNol, ErrorTipeData, ErrorNilai]: + Hasil perhitungan atau error jika terjadi kesalahan. + """ + try: + hasil = self.calculator.hitung_kecepatan(jarak, waktu) + return hasil + except (ErrorDibagiNol, ErrorTipeData, Error) as e: + return e + + def hitung_multiple( + self, + daftar_jarak: Union[list[Union[float, int]], np.ndarray], + daftar_waktu: Union[list[Union[float, int]], np.ndarray], + ) -> Union[list[Union[float, ErrorDibagiNol, ErrorTipeData, Error]], ErrorTipeData]: + """ + Menghitung kecepatan untuk banyak pasang jarak dan waktu. + + Args: + daftar_jarak: List atau array jarak tempuh. + daftar_waktu: List atau array waktu tempuh. + + Returns: + Union[List[Union[float, ErrorDibagiNol, ErrorTipeData, ErrorNilai]], ErrorTipeData]: + List hasil perhitungan atau error jika terjadi kesalahan. + """ + try: + jarak_valid = Validator.validasi_list_numerik(daftar_jarak, "daftar_jarak") + waktu_valid = Validator.validasi_list_numerik(daftar_waktu, "daftar_waktu") + + if len(jarak_valid) != len(waktu_valid): + raise Error("Panjang daftar jarak dan waktu harus sama") + + hasil = [] + if ( + self.use_numpy + and isinstance(daftar_jarak, np.ndarray) + and isinstance(daftar_waktu, np.ndarray) + ): + hasil = self._hitung_vectorized_numpy(daftar_jarak, daftar_waktu) + else: + for j, w in zip(jarak_valid, waktu_valid): + hasil.append(self.hitung_single(j, w)) + + return hasil + + except (ErrorTipeData, Error) as e: + raise e + + def _hitung_vectorized_numpy( + self, array_jarak: np.ndarray, array_waktu: np.ndarray + ) -> list[Union[float, ErrorDibagiNol, ErrorTipeData, Error]]: + """ + Menghitung kecepatan secara vectorized menggunakan NumPy. + + Args: + array_jarak: Array NumPy jarak tempuh. + array_waktu: Array NumPy waktu tempuh. + + Returns: + List[Union[float, ErrorDibagiNol, ErrorTipeData, ErrorNilai]]: List hasil perhitungan. + """ + hasil = [] + for j, w in zip(array_jarak, array_waktu): + try: + kecepatan = np.divide(float(j), float(w)) + hasil.append(kecepatan) + except ZeroDivisionError: + hasil.append(ErrorDibagiNol(operasi="kecepatan", dividend=float(j))) + except Exception as e: + hasil.append(ErrorTipeData(["float", "int"], type(e).__name__)) + + return hasil + + def hitung_rata_rata( + self, daftar_jarak, daftar_waktu + ) -> Union[float, ErrorTipeData, Error]: + """ + Menghitung kecepatan rata-rata dari banyak pasang jarak dan waktu. + + Args: + daftar_jarak: List atau array jarak tempuh. + daftar_waktu: List atau array waktu tempuh. + + Returns: + Union[float, ErrorTipeData, ErrorKustom]: Kecepatan rata-rata atau error. + """ + try: + hasil_perhitungan = self.hitung_multiple(daftar_jarak, daftar_waktu) + + if isinstance(hasil_perhitungan, list): + # Filter hanya hasil numerik + hasil_numerik = [ + h + for h in hasil_perhitungan + if isinstance(h, (int, float, np.number)) + ] + + if not hasil_numerik: + return Error("Tidak ada hasil perhitungan yang valid") + + if self.use_numpy: + return float(np.mean(hasil_numerik)) + else: + return sum(hasil_numerik) / len(hasil_numerik) + else: + return hasil_perhitungan + + except Exception as e: + return Error(f"Error dalam perhitungan rata-rata: {str(e)}") + + def toggle_numpy(self, use_numpy: bool) -> None: + """ + Mengganti implementasi calculator antara NumPy dan implementasi dasar. + + Args: + use_numpy (bool): Jika True, gunakan NumPy; jika False, gunakan implementasi dasar. + """ + self.calculator = KecepatanNumpy() if use_numpy else KecepatanImpl() + self.use_numpy = use_numpy + + +class KecepatanFactory: + """Factory class untuk membuat instance KecepatanProcessor.""" + + @staticmethod + def create_processor(use_numpy: bool = False) -> KecepatanProcessor: + """ + Membuat instance KecepatanProcessor. + + Args: + use_numpy (bool): Jika True, gunakan implementasi NumPy. + + Returns: + KecepatanProcessor: Instance processor yang siap digunakan. + """ + return KecepatanProcessor(use_numpy=use_numpy) + + @staticmethod + def create_default() -> KecepatanProcessor: + """ + Membuat instance KecepatanProcessor dengan konfigurasi default. + + Returns: + KecepatanProcessor: Instance processor dengan konfigurasi default. + """ + return KecepatanProcessor(use_numpy=False) + + +class KecepatanService: + """Singleton service untuk operasi kecepatan.""" + + _instance = None + + @classmethod + def get_instance(cls) -> KecepatanProcessor: + """ + Mendapatkan instance singleton dari KecepatanProcessor. + + Returns: + KecepatanProcessor: Instance processor singleton. + """ + if cls._instance is None: + cls._instance = KecepatanFactory.create_default() + return cls._instance diff --git a/example/fisika/kecepatan.py b/example/fisika/kecepatan.py index bfb7055..1bb3b4e 100644 --- a/example/fisika/kecepatan.py +++ b/example/fisika/kecepatan.py @@ -1,5 +1,7 @@ -import OpenSeries.fisika as fisika +from OpenSeries import fisika -print("hitung kecepatan") -result_kecepatan = fisika.kecepatan(4, 2.3) -print(f"hasil dari kecepatan adalah: {result_kecepatan}\n") +if __name__ == "__main__": + hasil = fisika.kecepatan(12, 3) + hasil_list = fisika.kecepatan([10, 20, 30], [5, 6, 7]) + print(hasil) + print(hasil_list) diff --git a/testing/fisika_test.py b/testing/fisika_test.py new file mode 100644 index 0000000..84efb50 --- /dev/null +++ b/testing/fisika_test.py @@ -0,0 +1,18 @@ +import numpy as np +import unittest + +from OpenSeries.fisika import kecepatan + + +class TestKecepatan(unittest.TestCase): + def test_angka_valid(self): + hasil = kecepatan(100.0, 10.0) + self.assertEqual(hasil, 10.0) + + def test_angka_list(self): + hasil = kecepatan([20, 30, 40], [20, 30, 40]) + self.assertEqual(hasil, [1.0, 1.0, 1.0]) + + def test_numpy_list(self): + hasil = kecepatan(np.array([20, 30, 40]), np.array([20, 30, 40])) + self.assertEqual(hasil, [1.0, 1.0, 1.0]) From c5871d83b8c49d671e448b8cab52a21b55d215f4 Mon Sep 17 00:00:00 2001 From: Arlan Tengga Date: Mon, 6 Oct 2025 17:03:14 +0700 Subject: [PATCH 5/5] feat: menambahkan fitur konversi suhu (#102) * menambahkan fitur konversi suhu * memperbaiki bug pada Error konversi suhu * feat: menambahkan algoritma terbaru * feat: menambahkan algoritma rotasi --- OpenSeries/fisika.py | 396 ++++++++++++++++++++++++++++++++- example/fisika/efek_doppler.py | 2 +- testing/fisika_test.py | 382 ++++++++++++++++++++++++++++++- 3 files changed, 772 insertions(+), 8 deletions(-) diff --git a/OpenSeries/fisika.py b/OpenSeries/fisika.py index e38661e..1700afe 100644 --- a/OpenSeries/fisika.py +++ b/OpenSeries/fisika.py @@ -137,7 +137,7 @@ def masa_jenis( volume (float atau int): volume benda Return: - (int, flloat): hasil dari kalkulasi fungsi dari masa jenis + (int, float): hasil dari kalkulasi fungsi dari masa jenis error.ErrorTipeData: error jika tipe data data salah error.ErrorDibagiNol: error jika angka dibagikan dengan 0 """ @@ -153,6 +153,164 @@ def masa_jenis( return error.ErrorTipeData(["int", "float"]) +def kecepatan_sudut( + sudut: Union[int, float], time: Union[int, float] +) -> Union[int, float, error.ErrorTipeData, error.ErrorDibagiNol]: + """ + Menghitung kecepatan sudut + + Parameter: + sudut (float atau int): sudut tempuh benda + time (float atau int): waktu tempuh benda + + Return: + (int,float): hasil dari kalkulasi fungsi kecepatan sudut + error.ErrorTipeData : error jika tipe data salah + error.ErrorDibagiNol: error jika angka dibagikan dengan 0 + """ + # mengecek apakah variable tersebut bertipe data int atau float + # jika tidak maka error + if all(isinstance(data, (float, int)) for data in [sudut, time]): + try: + return sudut / time + except ZeroDivisionError: + return error.ErrorDibagiNol() + else: + return error.ErrorTipeData(["int", "float"]) + + +def percepatan_sudut( + w_sudut: Union[int, float], time: Union[int, float] +) -> Union[int, float, error.ErrorTipeData, error.ErrorDibagiNol]: + """ + Menghitung percepatan sudut + + Parameter: + w_sudut (int atau float) : kecepatan sudut + time (int atau float) : waktu + + Return: + (int,float): hasil dari kalkulasi fungsi percepatan sudut + error.ErrorTipeData : error jika tipe data salah + error.DibagiNol : error jika angka dibagikan dengan 0 + """ + # mengecek apakah variable tersebut bertipe data int atau float + # jika tidak maka error + if all(isinstance(data, (float, int)) for data in [w_sudut, time]): + try: + return w_sudut / time + except ZeroDivisionError: + return error.ErrorDibagiNol() + else: + return error.ErrorTipeData(["int", "float"]) + + +def percepatan_sentripetal_linear( + kecepatan: Union[int, float], jari_jari: Union[int, float] +) -> Union[int, float, error.ErrorTipeData, error.ErrorDibagiNol]: + """ + Menghitung percepatan sentripetal linear + + Parameter : + kecepatan (int,float) : kecepatan + jari_jari (int,float) : jari-jari lintasan + Return : + (int,float) : hasil kalkulasi percepatan sentripetal linear + error.ErrorTipeData : error jika tipe data salah + error.ErrorDibagiNol : error jika dibagi dengan nol + """ + # mengecek apakah variable tersebut bertipe data int atau float + # jika tidak maka error + if all(isinstance(data, (float, int)) for data in [kecepatan, jari_jari]): + try: + return kecepatan**2 / jari_jari + except ZeroDivisionError: + return error.ErrorDibagiNol() + else: + return error.ErrorTipeData(["int", "float"]) + + +def percepatan_sentripetal_sudut( + jari_jari: Union[int, float], kecepatan_sudut: Union[int, float] +) -> Union[int, float, error.ErrorTipeData]: + """ + Menghitung percepatan sentripetal sudut + + Parameter : + kecepatan_sudut (int,float) : kecepatan sudut + jari_jari (int,float) : jari-jari lintasan + Return : + (int,float) : hasil kalkulasi percepatan sentripetal sudut + error.ErrorTipeData : error jika tipe data salah + """ + # mengecek apakah variable tersebut bertipe data int atau float + # jika tidak maka error + if all(isinstance(data, (int, float)) for data in [kecepatan_sudut, jari_jari]): + return jari_jari * (kecepatan_sudut**2) + else: + return error.ErrorTipeData(["int", "float"]) + + +def gerak_melingkar_beraturan( + w_awal: Union[int, float], a_sudut: Union[int, float], t: Union[int, float] +) -> Union[int, float, error.Error, error.ErrorTipeData]: + """ + menghitung hasil dari gerak melingkar beraturan + + Parameter: + w_awal (float atau int) : kecepatan sudut awal + a_sudur (float atau int): percepatan sudut + Return: + (int atau float) : hasil kalkulasi dari gerak melingkar beraturan + error.ErrorTipeData : error jika tipe data salah + error.Errorvalue : error jika waktu kurang dari 0 + """ + if all(isinstance(data, (int, float)) for data in [w_awal, a_sudut, t]): + return w_awal + a_sudut * t + else: + return error.ErrorTipeData(["Tipe data tidak sesuai"]) + + +def inersia( + m: Union[float, int], r: Union[float, int] +) -> Union[float, int, error.Error, error.ErrorTipeData]: + """ + Menghitung inersia dari suatu benda + + Parameter: + m (float atau int): massa benda + r (float atau int): jari-jari + + Return: + (int atau float) : hasil dari kalkulasi fungsi inersia + error.ErrorValue : error jika massa kurang dari 0 + error.ErrorTipeData : error jika tipe data salah + """ + if all(isinstance(data, (float, int)) for data in [m, r]): + return m * (r**2) + else: + return error.ErrorTipeData(["int", "float"]) + + +def energi_kinetik_rotasi( + inersia: Union[float, int], kecepatan_sudut: Union[int, float] +) -> Union[int, float, error.ErrorTipeData]: + """ + menghitung energi kinetik rotasi + + Parameter: + inersia (float atau int): inersia benda + kecepatan_sudut (float atau int): kecepatan benda + Return: + (int atau float) : hasil kalkulasi dari energi kinetik rotasi + error.ErrorTipeData : error jika tipe data salah + """ + if all(isinstance(data, (float, int)) for data in [inersia, kecepatan_sudut]): + return (1 / 2) * inersia * (kecepatan_sudut**2) + else: + return error.ErrorTipeData(["int", "float"]) + + def energi_potensial( m: Union[int, float], g: Union[int, float], h: Union[int, float] ) -> Union[float, int, error.ErrorTipeData]: @@ -293,3 +451,239 @@ def efek_doppler( "frekuensi tidak positif, kecepatan sumber relatif lebih besar dari kecepatan gelombang dalam medium" ) return doppler + + +def celcius_farenheit(celcius: Union[int, float]) -> Union[float, int]: + """ + mengubah nilai celcius ke farenheit + + Paramieter: + celcius (float atau int): nilai celcius + + Return: + (float atau int): hasil dari kalkulasi celcius ke farenheit + error.ErrorTipeData: error jika tipe data salah + """ + # mengecek apakah variable tersebut bertipe data int atau float + # jika tidak maka error + if not isinstance(celcius, (float, int)): + return error.ErrorTipeData(["float", "int"]) + else: + return celcius * (9 / 5) + 32 + + +def farenheit_celcius(farenheit: Union[int, float]) -> Union[int, float]: + """ + mengubah nilai farenheit ke celcius + + Parameter: + farenheit(int atau float): nilai farenheit + + Return: + (float atau int): hasil dari kalkulasi farenheit ke celcius + errot.ErrorTiperData: error jika data salah + """ + # mengecek apakah variable tersebut bertipe data int atau float + # jika tidak maka error + if not isinstance(farenheit, (float, int)): + return error.ErrorTipeData(["float", "int"]) + else: + return (farenheit - 32) * (5 / 9) + + +def celcius_reaumur(celcius: Union[int, float]) -> Union[int, float]: + """ + mengubah nilai celcius ke reaumur + + Parameter: + celcius(int atau float): nilai celcius + + Return: + (float atau int): hasil dari kalkulasi celcius ke reaumur + errot.ErrorTiperData: error jika data salah + """ + # mengecek apakah variable tersebut bertipe data int atau float + # jika tidak maka error + if not isinstance(celcius, (float, int)): + return error.ErrorTipeData(["float", "int"]) + else: + return celcius * (4 / 5) + + +def reamur_celcius(reamur: Union[int, float]) -> Union[int, float]: + """ + mengubah nilai reamur ke celcius + + Parameter: + reamur(int atau float): nilai reamur + + Return: + (float atau int): hasil dari kalkulasi celcius ke reamur + errot.ErrorTiperData: error jika data salah + """ + # mengecek apakah variable tersebut bertipe data int atau float + # jika tidak maka error + if not isinstance(reamur, (float, int)): + return error.ErrorTipeData(["float", "int"]) + else: + return reamur * (5 / 4) + + +def celcius_kelvin(celcius: Union[int, float]) -> Union[int, float]: + """ + mengubah nilai celcius ke reaumur + + Parameter: + celcius(int atau float): nilai celcius + + Return: + (float atau int): hasil dari kalkulasi celcius ke kelvin + errot.ErrorTiperData: error jika data salah + """ + # mengecek apakah variable tersebut bertipe data int atau float + # jika tidak maka error + if not isinstance(celcius, (float, int)): + return error.ErrorTipeData(["float", "int"]) + else: + return celcius + 273.15 + + +def kelvin_celcius(kelvin: Union[int, float]) -> Union[int, float, error.Error]: + """ + mengubah celcius ke kelvin + + Parameter: + kelvin(int atau float): nilai kelvin + + Return: + (float atau int): hasil dari kalkulasi kelvin ke celcius + error.ErrorTiperData: error jika data salah + erro.Error: error jika nilai kelvin kurang dari nol + """ + # mengecek apakah variable tersebut bertipe data int atau float + # jika tidak maka error + if not isinstance(kelvin, (float, int)): + return error.ErrorTipeData(["float", "int"]) + elif kelvin < 0: + return error.Error("Nilai kelvin tidak boleh kurang dari 0") + else: + return 273.15 - kelvin + + +def kelvin_fahrenheit(kelvin: Union[int, float]) -> Union[int, float, error.Error]: + """ + mengubah kelvin ke fahrenheit + + Parameter: + kelvin(int atau float): nilai kelvin + + Return: + (float atau int): hasil dari kalkulasi kelvin ke fahrenheit + error.ErrorTiperData: error jika data salah + errot.Error ; error jika nilai kelvin kurang dari nol + """ + # mengecek apakah variable tersebut bertipe data int atau float + # jika tidak maka error + if not isinstance(kelvin, (float, int)): + return error.ErrorTipeData(["float", "int"]) + elif kelvin < 0: + return error.Error("Kelvin tidak boleh kurang dari 0") + else: + return kelvin * (9 / 5) - 459.67 + + +def fahrenheit_kelvin(fahrenheit: Union[int, float]) -> Union[int, float]: + """ + mengubah fahrenheit ke kelvin + + Parameter: + fahrenheit(int atau float): nilai fahrenheit + + Return: + (float atau int): hasil dari kalkulasi fahrenheit ke kelvin + errot.ErrorTiperData: error jika data salah + """ + # mengecek apakah variable tersebut bertipe data int atau float + # jika tidak maka error + if not isinstance(fahrenheit, (float, int)): + return error.ErrorTipeData(["float", "int"]) + else: + return (fahrenheit + 459.67) * (5 / 9) + + +def kelvin_reamur(kelvin: Union[int, float]) -> Union[int, float, error.Error]: + """ + mengubah kelvin ke reamur + + Parameter: + kelvin(int atau float): nilai kelvin + + Return: + (float atau int): hasil dari kalkulasi kelvin ke reamur + errot.ErrorTiperData: error jika data salah + """ + # mengecek apakah variable tersebut bertipe data int atau float + # jika tidak maka error + if not isinstance(kelvin, (float, int)): + return error.ErrorTipeData(["int", "float"]) + elif kelvin < 0: + return error.Error("Kelvin tidak boleh kurang dari 0") + else: + return (kelvin - 273.15) * (4 / 5) + + +def reamur_kelvin(reamur: Union[int, float]) -> Union[int, float]: + """ + mengubah reamur ke kelvin + + Parameter: + reamur(int atau float): nilai reamur + + Return: + (float atau int): hasil dari kalkulasi reamur ke kelvin + errot.ErrorTiperData: error jika data salah + """ + # mengecek apakah variable tersebut bertipe data int atau float + # jika tidak maka error + if not isinstance(reamur, (float, int)): + return error.ErrorTipeData(["float", "int"]) + else: + return (reamur * (5 / 4)) + 273.15 + + +def reamur_fahrenheit(reamur: Union[int, float]) -> Union[int, float]: + """ + mengubah reamur ke fahrenheit + + Parameter: + reamur(int atau float): nilai reamur + + Return: + (float atau int): hasil dari kalkulasi reamur ke fahrenheit + errot.ErrorTiperData: error jika data salah + """ + # mengecek apakah variable tersebut bertipe data int atau float + # jika tidak maka error + if not isinstance(reamur, (float, int)): + return error.ErrorTipeData(["float", "int"]) + else: + return (reamur * (9 / 4)) + 32 + + +def fahrenheit_reamur(fahrenheit: Union[int, float]) -> Union[int, float]: + """ + mengubah fahrenheit ke reamur + + Parameter: + fahrenheit(int atau float): nilai fahrenheit + + Return: + (float atau int): hasil dari kalkulasi fahrenheit ke reamur + errot.ErrorTiperData: error jika data salah + """ + # mengecek apakah variable tersebut bertipe data int atau float + # jika tidak maka error + if not isinstance(fahrenheit, (float, int)): + return error.ErrorTipeData(["float", "int"]) + else: + return (fahrenheit - 32) * (4 / 9) diff --git a/example/fisika/efek_doppler.py b/example/fisika/efek_doppler.py index ebad7c3..e3491fb 100644 --- a/example/fisika/efek_doppler.py +++ b/example/fisika/efek_doppler.py @@ -1,5 +1,5 @@ import OpenSeries.fisika as fisika # menghitung fungsi dari efek doppler -doppler_efek = fisika.efek_doppler(100, 330, 10) +doppler_efek = fisika.efek_doppler(100, 330, 10, 10) print(doppler_efek) diff --git a/testing/fisika_test.py b/testing/fisika_test.py index 84efb50..de3cc8e 100644 --- a/testing/fisika_test.py +++ b/testing/fisika_test.py @@ -9,10 +9,380 @@ def test_angka_valid(self): hasil = kecepatan(100.0, 10.0) self.assertEqual(hasil, 10.0) - def test_angka_list(self): - hasil = kecepatan([20, 30, 40], [20, 30, 40]) - self.assertEqual(hasil, [1.0, 1.0, 1.0]) + def test_dibagi_nol(self): + hasil = fisika.kecepatan(150.0, 0) + with self.assertRaises(error.ErrorDibagiNol): + raise hasil - def test_numpy_list(self): - hasil = kecepatan(np.array([20, 30, 40]), np.array([20, 30, 40])) - self.assertEqual(hasil, [1.0, 1.0, 1.0]) + def test_invalid_input(self): + with self.assertRaises(error.ErrorTipeData): + raise fisika.kecepatan("12", 30) + + def test_kecepatan_invalid_input2(self): + hasil = fisika.kecepatan("12", "50") + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestPercepatan(unittest.TestCase): + def test_percepatan_valid(self): + hasil = fisika.percepatan(20.0, 5.0) + self.assertEqual(hasil, 4.0) + + def test_percepatan_dibagi_nol(self): + hasil = fisika.percepatan(30.0, 0) + with self.assertRaises(error.ErrorDibagiNol): + raise hasil + + def test_percepatan_nilai_tidak_valid(self): + hasil = fisika.percepatan("20", 30) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestKecepatanSudut(unittest.TestCase): + def test_kecepatan_sudut_valid(self): + hasil = fisika.kecepatan_sudut(30, 2) + self.assertEqual(hasil, 15) + + def test_kecepatan_sudut_dibagi_nol(self): + hasil = fisika.kecepatan_sudut(30.0, 0) + with self.assertRaises(error.ErrorDibagiNol): + raise hasil + + def test_kecepatan_sudut_tidak_valid(self): + hasil = fisika.kecepatan_sudut("30.0", 2) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestPercepatanSudut(unittest.TestCase): + def test_percepatan_sudut_valid(self): + hasil = fisika.percepatan_sudut(50, 2) + self.assertEqual(hasil, 25) + + def test_percepatan_sudut_dibagi_nol(self): + hasil = fisika.percepatan_sudut(50.0, 0) + with self.assertRaises(error.ErrorDibagiNol): + raise hasil + + def test_percepatan_sudut_tidak_valid(self): + hasil = fisika.percepatan_sudut("50.0", 2) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestPercepatanSentripetallinear(unittest.TestCase): + def test_percepatanSentripetal_linear_valid(self): + hasil = fisika.percepatan_sentripetal_linear(5.0, 2) + self.assertEqual(hasil, 12.5) + + def test_percepatan_sudut_dibagi_nol(self): + hasil = fisika.percepatan_sudut(50.0, 0) + with self.assertRaises(error.ErrorDibagiNol): + raise hasil + + def test_percepatan_sudut_tidak_valid(self): + hasil = fisika.percepatan_sudut("50.0", 2) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestPercepatanSentripetalSudut(unittest.TestCase): + def test_percepatansentripetal_sudut_valid(self): + hasil = fisika.percepatan_sentripetal_sudut(5, 8) + self.assertEqual(hasil, 320) + + def test_percepatan_sudut_tidak_valid(self): + hasil = fisika.percepatan_sentripetal_sudut("5", 8) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestGerakLurusBeraturan(unittest.TestCase): + def test_valid(self): + hasil = fisika.gerak_lurus_beraturan(10.0, 2.0, 3.0) + self.assertAlmostEqual(hasil, 39.0) + + def test_invalid_int(self): + hasil = fisika.gerak_lurus_beraturan(8, 1.5, 2) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TesGerakMelingkarBeraturan(unittest.TestCase): + def test_valid(self): + hasil = fisika.gerak_melingkar_beraturan(5, 6, 3) + self.assertAlmostEqual(hasil, 23) + + def test_invalid(self): + hasil = fisika.gerak_melingkar_beraturan("5", "6", 3) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestInersia(unittest.TestCase): + def test_valid(self): + hasil = fisika.inersia(2, 4) + self.assertAlmostEqual(hasil, 32) + + def test_invalid(self): + hasil = fisika.inersia("2", 4) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestEnergiKinetik(unittest.TestCase): + def test_valid_input(self): + hasil = fisika.energi_kinetik(2.0, 5.0) + self.assertAlmostEqual(hasil, 25.0) + + def test_invalid_input_mix_tipe_data(self): + hasil = fisika.energi_kinetik("3", 4.5) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestEnergiKinetikRotasi(unittest.TestCase): + def test_valid(self): + hasil = fisika.energi_kinetik_rotasi(2, 6) + self.assertAlmostEqual(hasil, 36) + + def test_invalid(self): + hasil = fisika.energi_kinetik_rotasi("2", 6) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestKetinggianBarometrik(unittest.TestCase): + def test_valid_input_tekanan(self): + hasil = fisika.ketinggian_barometrik(101325.0) + self.assertIsInstance(hasil, float) + + def test_tekanan_lebih_besar_daripada_air(self): + hasil = fisika.ketinggian_barometrik(110000.0) + with self.assertRaises(error.Error): + raise hasil + + def test_tekanan_angka_negatif(self): + hasil = fisika.ketinggian_barometrik(-820.3) + with self.assertRaises(error.Error): + raise hasil + + def test_tekanan_tipe_data_salah(self): + hasil = fisika.ketinggian_barometrik("12") + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestGayaSentripental(unittest.TestCase): + def test_gaya_sentripental(self): + hasil = fisika.gaya_sentripental(10, 5, 2) + self.assertEqual(hasil, 125.0) + + def test_gaya_sentripental_error_tipe_data(self): + hasil = fisika.gaya_sentripental("12", 5, 2) + self.assertIsInstance(hasil, error.ErrorTipeData) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + def test_gaya_sentripental_minus(self): + hasil = fisika.gaya_sentripental(-10, 5, 2) + self.assertIsInstance(hasil, error.Error) + with self.assertRaises(error.Error): + raise hasil + + def test_gaya_sentripental_nol(self): + hasil = fisika.gaya_sentripental(10, 5, 0) + self.assertIsInstance(hasil, error.Error) + with self.assertRaises(error.Error): + raise hasil + + +class TestEfekDoppler(unittest.TestCase): + def test_efek_doppler(self): + hasil = fisika.efek_doppler(100, 340, 20, 10) + rounding_hasil = round(hasil) + self.assertEqual(rounding_hasil, 109) + + def test_efek_doppler_invalid_tipe_data(self): + hasil = fisika.efek_doppler("12", "340", "20", 10) + self.assertIsInstance(hasil, error.ErrorTipeData) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + def test_efek_doppler_dibagi_nol(self): + hasil = fisika.efek_doppler(0, 0, 0, 0) + self.assertIsInstance(hasil, error.ErrorDibagiNol) + with self.assertRaises(error.ErrorDibagiNol): + raise hasil + + def test_efek_doppler_nilai_negatif(self): + hasil = fisika.efek_doppler(-100, -340, 20, 10) + self.assertIsInstance(hasil, error.Error) + with self.assertRaises(error.Error): + raise hasil + + +class TestCelciusFarenheit(unittest.TestCase): + def test_CelciusFarenheit(self): + hasil = fisika.celcius_farenheit(0) + rounding_hasil = round(hasil) + self.assertEqual(rounding_hasil, 32) + + def test_CelciusFarenheit_invalid_tipe_data(self): + hasil = fisika.celcius_farenheit("0") + self.assertIsInstance(hasil, error.ErrorTipeData) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestFarenheitCelcius(unittest.TestCase): + def test_FarenheitCelcius(self): + hasil = fisika.farenheit_celcius(32) + rounding_hasil = round(hasil) + self.assertEqual(rounding_hasil, 0) + + def test_FarenheitCelcius_invalid_tipe_data(self): + hasil = fisika.farenheit_celcius("32") + self.assertIsInstance(hasil, error.ErrorTipeData) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestCelciusReamur(unittest.TestCase): + def test_CelciusReamur(self): + hasil = fisika.celcius_reaumur(32) + self.assertEqual(hasil, 25.6) + + def test_CelciusReamur_invalid_tipe_data(self): + hasil = fisika.farenheit_celcius("32") + self.assertIsInstance(hasil, error.ErrorTipeData) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestReamurCelcius(unittest.TestCase): + def test_ReamurCelcius(self): + hasil = fisika.reamur_celcius(32) + self.assertEqual(hasil, 40) + + def test_ReamurCelcius_invalid_tipe_data(self): + hasil = fisika.farenheit_celcius("32") + self.assertIsInstance(hasil, error.ErrorTipeData) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestCelciusKelvin(unittest.TestCase): + def test_CelciusKelvin(self): + hasil = fisika.celcius_kelvin(0) + self.assertEqual(hasil, 273.15) + + def test_CelciusKelvin_invalid_tipe_data(self): + hasil = fisika.farenheit_celcius("0") + self.assertIsInstance(hasil, error.ErrorTipeData) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestKelvinCelcius(unittest.TestCase): + def test_KelvinCelcius(self): + hasil = fisika.kelvin_celcius(273.15) + self.assertEqual(hasil, 0) + + def test_kelvin_nilai_negatif(self): + hasil = fisika.kelvin_celcius(-10) + self.assertIsInstance(hasil, error.Error) + with self.assertRaises(error.Error): + raise hasil + + def test_KelvinCelcius_invalid_tipe_data(self): + hasil = fisika.kelvin_celcius("273.15") + self.assertIsInstance(hasil, error.ErrorTipeData) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestKelvinFarenheit(unittest.TestCase): + def test_KelvinFarenheit(self): + hasil = fisika.kelvin_fahrenheit(300) + self.assertEqual(hasil, 80.32999999999998) + + def test_kelvin_nilai_negatif(self): + hasil = fisika.kelvin_fahrenheit(-10) + self.assertIsInstance(hasil, error.Error) + with self.assertRaises(error.Error): + raise hasil + + def test_KelvinFarenheit_invalid_tipe_data(self): + hasil = fisika.kelvin_fahrenheit("0") + self.assertIsInstance(hasil, error.ErrorTipeData) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestFarenheitKelvin(unittest.TestCase): + def test_FarenheitKelvin(self): + hasil = fisika.fahrenheit_kelvin(-459.67) + self.assertEqual(hasil, 0) + + def test_FarenheitKelvin_invalid_tipe_data(self): + hasil = fisika.fahrenheit_kelvin("-459.67") + self.assertIsInstance(hasil, error.ErrorTipeData) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestKelvinReamur(unittest.TestCase): + def test_KelvinReamur(self): + hasil = fisika.kelvin_reamur(300) + self.assertEqual(hasil, 21.480000000000018) + + def test_kelvin_nilai_negatif(self): + hasil = fisika.kelvin_reamur(-10) + self.assertIsInstance(hasil, error.Error) + with self.assertRaises(error.Error): + raise hasil + + def test_KelvinReamur_invalid_tipe_data(self): + hasil = fisika.kelvin_reamur("300") + self.assertIsInstance(hasil, error.ErrorTipeData) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestReamurKelvin(unittest.TestCase): + def test_ReamurKelvin(self): + hasil = fisika.reamur_kelvin(0) + self.assertEqual(hasil, 273.15) + + def test_ReamurFahrenheit_invalid_tipe_data(self): + hasil = fisika.reamur_fahrenheit("-218.52") + self.assertIsInstance(hasil, error.ErrorTipeData) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestReamurFahrenheit(unittest.TestCase): + def test_ReamurFahrenheit(self): + hasil = fisika.reamur_fahrenheit(0) + self.assertEqual(hasil, 32) + + def test_ReamurFahrenheit_invalid_tipe_data(self): + hasil = fisika.reamur_fahrenheit("0") + self.assertIsInstance(hasil, error.ErrorTipeData) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestFahrenheitReamur(unittest.TestCase): + def test_FahrenheitReamur(self): + hasil = fisika.fahrenheit_reamur(40) + self.assertEqual(hasil, 3.5555555555555554) + + def test_FahrenheitReamur_invalid_tipe_data(self): + hasil = fisika.fahrenheit_reamur("0") + self.assertIsInstance(hasil, error.ErrorTipeData) + with self.assertRaises(error.ErrorTipeData): + raise hasil