From 56abf5bfae3b07e55ac7fe4bb16313c7c6d70714 Mon Sep 17 00:00:00 2001 From: MrWaradana Date: Tue, 25 Feb 2025 13:19:06 +0700 Subject: [PATCH] fix: prediction script --- src/modules/equipment/Prediksi.py | 9 ++-- .../__pycache__/Prediksi.cpython-311.pyc | Bin 25181 -> 25326 bytes .../insert_actual_data.cpython-311.pyc | Bin 13221 -> 12441 bytes .../equipment/__pycache__/run.cpython-311.pyc | Bin 1854 -> 2622 bytes src/modules/equipment/insert_actual_data.py | 50 ++++++++++-------- src/modules/equipment/run.py | 30 ++++++++--- 6 files changed, 55 insertions(+), 34 deletions(-) diff --git a/src/modules/equipment/Prediksi.py b/src/modules/equipment/Prediksi.py index a5c72cb..c3d34e1 100644 --- a/src/modules/equipment/Prediksi.py +++ b/src/modules/equipment/Prediksi.py @@ -372,7 +372,6 @@ class Prediksi: try: # Mengambil data dari database df = self.__fetch_data_from_db(p_equipment_id) - if df is None: print("Data tidak tersedia untuk prediksi.") return @@ -382,7 +381,6 @@ class Prediksi: # Tahun proyeksi future_years = list(range(df["year"].max() + 1, par_tahun_target + 1)) - # Hasil prediksi predictions = {"year": future_years} @@ -399,10 +397,15 @@ class Prediksi: # Fungsi untuk prediksi menggunakan Exponential Smoothing def exponential_smoothing_predict(column, years): data_series = df[column].fillna(0).values + + # Add a small epsilon to avoid zeros in the data if needed + if np.any(data_series == 0): + data_series = data_series + 1e-10 + model = ExponentialSmoothing( data_series, trend="add", seasonal=None, seasonal_periods=None ) - model_fit = model.fit() + model_fit = model.fit(optimized=True, use_brute=False) preds = model_fit.forecast(len(years)) return np.abs(preds) diff --git a/src/modules/equipment/__pycache__/Prediksi.cpython-311.pyc b/src/modules/equipment/__pycache__/Prediksi.cpython-311.pyc index 830b5e5f95be520461652a7c0f05068adb064133..86ca7fec26a9173710b918539441e48269c5e6bd 100644 GIT binary patch delta 610 zcmcb6gz?=`M!w~|yj%=Ga4LCkdUwc1z8ijwEt8-7ZDF!woIKY*C@hN^BntvHOeu`n zOd!@WMh1q}KnwvztUwv2Dj=tpse}_I3RcgY!jQtShGiKGP(2VsKrM3(^W;EjF{u>R z6t*?&%Ya6%1{({Ku4SoVS->_~QAUKRgn#k|cd5x$jC=yMtR<{a-9RdfWAXuE3E^M{ zO%A^zkk0hod#~TTUvt}b^3nh;gAg}Ordyo(1tpoenN_JNw>V3SQ{$70N=s5TIg2`g z%8S}SL>G{_#hjQ|Ir(;g)Z||Q>)HB%UMikFd3~UQ%2zf95wR&|GqhI-UXs$fD6D-& zSo;G5qoCOhCEX3I7nMvWct4$dAyAcP1Iq!{8J-tq+^)#DZT=Y;#l$!l7<$f|r-x`V zu`LAIvv~5cu&Ju9z+n9Gg5d>21H%WV1V&E12ZEy41+^{-YOS!lC}?#>(5l1f#^i?Z zWabCbij!Z2D@pS3s(xU=LdZ@27%sWlCgL%Z%5sqT%Rt0h5U~+NYyuIRLBuK$v2(I> z^aja9MpnHK3|Pp`JTWy)j5{ZH#;LI$1ggKic}v`8Mz&obtp_LPCMYr9+&m${gVCUd VjS*-9cJd=w{0p*d-DHlWPyluvuXO+b delta 456 zcmaENl=1EnM!w~|yj%=Gu$_H<`tIP3d^h|U+a^Ev+rspZVe(x6AgLOr6s8o06oxg- z%UBo~Rs%5v)G|*tRFRmxK#Xs)oUas93HRg;?oyMh82JQhSxb0fsu&ou*e4$lmf#9z z&}8u|Vgia!eixvnuE|l<0c01ofe2<0(Fr7OairxJr6wm9mlRoo#JVQO1#V`Wz{tQ* zTrgQYNP+S0OKS-GPSvc){?3p@HE8 zQ!FE=-UC6=>w;RB1hrP!T@7IO34m>MR=ZIh+q)mZld w)!*3c8o!y5Z97QozRCX*lo+pVR!sC@G^k`_1e$=I{0J8Rf-GAxd1g{50J!&q+yDRo diff --git a/src/modules/equipment/__pycache__/insert_actual_data.cpython-311.pyc b/src/modules/equipment/__pycache__/insert_actual_data.cpython-311.pyc index c7ba8477ac4294f48e7b1ee69377608ffdfd0cb3..5058c3cfd51d8095a074284fe412b99f6fb4aa80 100644 GIT binary patch delta 1551 zcma)5ZD?Cn7``VrUu&B-A2;bun%vx`ZF-Y7tF4_)yVRb(!4x(S@rUOm9kbfW4(C4S zInVoXUe0;%+au>9x_5QDG768M4qqDi`GW2yt*L4mi^SqB8Kd%bB=pJpzJ*B)cz#ru z7B6@{^ptj&qRaIcW1qxIyUe$$0R=h*PHm?)l1L0E;}c^UQF}_Mk~BCw6e{+hMsVxg z$PFRg4UBs#dE|wm$}S|pT%{GQXO=2m3Y3Q{`XAAW%=?BVgkFTlO?BlTq>PF8Ql`X` zXohvBtujfIf=eT1g)`@icN})K;aiaIC(w=|L9U(W zrzHnbI^c@K1uxn6-m7o<84}h>;NG$y!$Jn;$tmE{jou9P}9_!!93kxP#gmgI?ze@T98l_x;=68 z1ig#fqzKLg)~apuU1y)43BqR{8|_~d;Rlb6Kax|*me8stl(&Rt9=dMvEPB%a)PVJR zG$O6TX+#KmFIKVHcKN;ot4vRx>5-Wp&^PV2g|efvEre&TwzRG?;XD(TnJ_%o#07)2 zA&kCftg_9Y6;_!*o(afIV7*2tP`$J{jM6n*Wclb8DJXSuD=BtCBJ<(F z64|5`4(=v}p-==|wG*E8S&)#K@pUP7-@V**i*>$dZe*68qc{7CS6>Kc3M~(!CpxLm zO}+dhoz$1@ZNWxm&W$k7HJ0`1HMv%EU%6&Qt-{Jmxe6;Q`hEd#uKLlChPv8WHt3-9 zw0@AK^ClHm@~ny|4jS`onjZI~K6s_|bay{#GzPNu`M4U72N$eNCp*8fL|WcwTYWVIIn delta 1511 zcmb7Ee@q)y9KUzhmQpBCdTp=VwY~nN?f9`FjIFXYgfd~B*-8UO8H|oHLb4WUOPr(; zqKV-TH7t)sjLV|Qj3hIr%SG)Hmw-AgiHldM5to?FxJC4@qFb^U|L{Ey;^s1wy?gKT z{d~Xo{eIu~-F@%gj=Vpr{y?o(5or8yIJ3j z9B_xls&IxufacYXW!aVP&$=b;I+Y8omVQ$zX~H%6Q4+iYb;|waBa>5O6S0wa>cm)7 z=u^HdtGMxy4gOf(0^G1t?E+r7SN$ufh2{z#?1KIZAL~I?4U@RG?ZF`VDq4SD6c#FM zB=`h=T6Gfygts)802qZGT6^ic>FVT#v^IGjj%%BR6)gq8$M70$1tvJDZGx>j4=}@s zt`k_`9>xT})Xf1NKC5R9R^!etL>xrR)0%`Tt%=&;jNS-rP-8Gsny4Mt8*Hj*NxC|r zOjk#(@Mpb_wf!47fdaRJs}nrBkHc7igFKI<*P`@V(#KEpfk-OC$H!Cr$eFQZD#@Q3 zPw)@AMfRctsNiJ_Cj=}}%Fb;CJkHs-;|v3qu7}!6Sg@>;aK-kw!i`U{3w~k0sBmK1 z0Ar5Z+(|_H(MrCjB#8SP#0D`-tZQ_$hl}L%Fy?F}2bJ)n`eAsXUQHJJA>)ecCaF^M zCV_FTW1TfGPM`PB9f9w-Y7Vqz97T$>R%{Xo?qU$jP4|?9!Mo(i9M1(reJHOF74)IG zXYS}d|FOY8T%M94N{w<4L0j#WN-moccL(xxXMye%=}!22ZNp6Oa-CSyi)T+*B6+&6 zK=+As-#X3BcS+ZMG>URkW5QBNF!oI%KxulwPqb02Y0I9@)4>8A6zSkC)?FmpDP0f9 zu-jz0f14C#YB#r7evc!(`_?)4l0)3xK`!^g6^|DVd09{ge{(Mcj%C_J^D#7Y4oT*j zP=N`FObC%Xj7c=({g_~Z35raxsCYD|l+syL5S*h(P{u*9q{z5Mw@*^CXL5>y|EQ!u z#_KeRw&U3}0zCU(kVu{zC~yNJHvqqN8$q3r_WH<%$JcgCZ(M9YJ33FDr8e8Q9(wVR zaJ%jR7-WghwViyJCBANM>Z+CHTmbQ0t*X1KB)3P`T~@NHkR!`#nH*VGs}8G>vQ`6n zJ;WNT3j3)wXI0oot+mLp#V5xWKZW@Bo_5!Bm2jrvwSz(2eKdj_vgp`wDq+UD)SZ~& vj+DM*{MXz1e*aRo#m1vkr$-JZCWMYg3ux_^0q2svNMM;6mgN6q0%!XNI)1~5EPJU%5_~5zcp84H7=g#@v^P5#+ zHD7p@ooxYXV$a6`hMy9?SWR^Gkk0J|W@^XHm_e&Tbusy}6I9m7+_MXy)Qq#Lk-TpK zq?!*fK$M+F0B`8rvl*CWj_)Aog#e7R57+?Q+D9X31V(W$j36_p)`PS3Yg!-5;kYO_ z$7@5#Zh|O8(OX7)jLOc!44*SI+Yz&Q4KumS95HBVpOO76blCHxqaL;x;0}OhMTId_ z)D*>IRM&BGOd&2x0{jdcFwNrswJEBX9KX)U7G!+4zLG^+*&B?Z%7 zrp;ZWekrU5Lvor6D?wRJ<6%|No-$30%dF|lMTE59Of6^pV4~*6-LYbdjMZ?0-v28d z6R?$AFkLcLI$b((J;Sn`ZA&QDOX?P+gwU828g+8A?`~Q1Gr(}Rqp(G?b;148zfk$S z|3yEA)Dy&$Bp#i3Qbd^KCu2MfbnH^gaP+kCB!m{Vm+EDnguNkYZR{E-w^6k zS^25Fq6`N%_Yc4}%Z?E;fX!zKyFUqJ6&&%SC`Kz8EL&Ebi@v4m*bCP2FDqW z;<(k>;eoiv(&@zUW=CfQ{#3zH{NB%gN419jY2x+DzCp?BO=Be@zlLqP2}%(SzsQxr fP#|(oYEvq;alS9F3|&JR_$Rh$-}sxXNOS)HLXkY+ delta 513 zcmdldvX75%IWI340}$kG-jqI>Wg_2gZdM?#8HhgzF;4uVH(7;I$EE}%1_d=t%NQ9L zRs%5v)UwpDEMSK5km(wR8pbt@lm9WwFqLpl?qiZIwQ=}Wbo^pv?5Y!?f7>&=$_LYNyo3B%~N43HE1`GRj7MV*dGBYAB zvZ!5QQM4cb*3UraGHgy}f6u55^1>~S`1riU+|>B^Tg*kJc`F%;#DJnj oB0%C7hfQvNN@-52U6I`6TFz)8K1L754-818(&Sg10W2U50Njy%YXATM diff --git a/src/modules/equipment/insert_actual_data.py b/src/modules/equipment/insert_actual_data.py index 99ed31a..4d03c7f 100644 --- a/src/modules/equipment/insert_actual_data.py +++ b/src/modules/equipment/insert_actual_data.py @@ -21,7 +21,7 @@ async def fetch_api_data( # ) try: response = await client.get( - f"{url}/main/number-of-failures/{assetnum}/{int(year)}/{int(year)}", + f"{url}/main/failures/{assetnum}/{int(year)}/{int(year)}", timeout=30.0, headers={"Authorization": f"Bearer {token}"}, ) @@ -32,9 +32,9 @@ async def fetch_api_data( return {} -def get_recursive_query(cursor, equipment_id, worktype="CM"): +def get_recursive_query(cursor, assetnum, worktype="CM"): """ - Fungsi untuk menjalankan query rekursif berdasarkan equipment_id dan worktype. + Fungsi untuk menjalankan query rekursif berdasarkan assetnum dan worktype. worktype memiliki nilai default 'CM'. """ query = f""" @@ -68,7 +68,7 @@ def get_recursive_query(cursor, equipment_id, worktype="CM"): ) AS tbl WHERE tbl.worktype = '{worktype}' - AND tbl.assetnum = '{equipment_id}' + AND tbl.assetnum = '{assetnum}' ORDER BY tbl.assetnum, tbl.year, @@ -114,26 +114,26 @@ async def query_data(RELIABILITY_APP_URL: str, token: str): # Tahun sekarang current_year = datetime.now().year - # Looping untuk setiap equipment_id + # Looping untuk setiap assetnum for row in results: - equipment_id = row["assetnum"] # Mengambil equipment_id dari hasil query + assetnum = row["assetnum"] # Mengambil assetnum dari hasil query forecasting_start_year = row["forecasting_start_year"] - 1 # CM recursive_results = get_recursive_query( - cursor_wo, equipment_id, worktype="CM" + cursor_wo, assetnum, worktype="CM" ) # PM - data_pm = get_recursive_query(cursor_wo, equipment_id, worktype="PM") + data_pm = get_recursive_query(cursor_wo, assetnum, worktype="PM") # OH - data_oh = get_recursive_query(cursor_wo, equipment_id, worktype="OH") + data_oh = get_recursive_query(cursor_wo, assetnum, worktype="OH") # Data Tahun data_tahunan = get_data_tahun(cursor) seq = 0 # Looping untuk setiap tahun for year in range(forecasting_start_year, current_year + 1): - # print(f"Processing equipment_id {equipment_id} in year {year}") + # print(f"Processing assetnum {assetnum} in year {year}") # Filter data berdasarkan tahun recursive_row = next( (r for r in recursive_results if r["year"] == year), None @@ -151,15 +151,15 @@ async def query_data(RELIABILITY_APP_URL: str, token: str): """ try: - cursor.execute(check_query, (equipment_id, year)) + cursor.execute(check_query, (assetnum, year)) data_exists = cursor.fetchone()[0] - # print("Data exists for equipment_id", equipment_id) + # print("Data exists for assetnum", assetnum) except Exception as e: - print(f"Error checking data for equipment_id {equipment_id}: {e}") + print(f"Error checking data for assetnum {assetnum}: {e}") continue if not data_exists: - print("Data not exists for equipment_id", equipment_id) + print("Data not exists for assetnum", assetnum) # Insert data jika belum ada if not recursive_row and not data_pm_row and not data_oh_row: # Jika data recursive_row tidak ada @@ -178,13 +178,14 @@ async def query_data(RELIABILITY_APP_URL: str, token: str): ) """ api_data = await fetch_api_data( - equipment_id, year, RELIABILITY_APP_URL, token + assetnum, year, RELIABILITY_APP_URL, token ) + print(api_data) cursor.execute( insert_query, ( str(uuid4()), # id - equipment_id, # equipment_id + assetnum, # assetnum year, # tahun seq, # seq 1, # is_actual @@ -215,14 +216,14 @@ async def query_data(RELIABILITY_APP_URL: str, token: str): ), ), ) - print(f"Data inserted for {equipment_id} in year {year}") + print(f"Data inserted for {assetnum} in year {year}") else: - print("Data exists for equipment_id", equipment_id) + print("Data exists for assetnum", assetnum) # Jika data recursive_row ada # raw_cm_interval ambil dari reliability predict insert_query = """ INSERT INTO lcc_equipment_tr_data ( - id, equipment_id, tahun, seq, is_actual, + id, assetnum, tahun, seq, is_actual, raw_cm_interval, raw_cm_material_cost, raw_cm_labor_time, raw_cm_labor_human , raw_pm_interval, raw_pm_material_cost, raw_pm_labor_time, raw_pm_labor_human @@ -235,17 +236,20 @@ async def query_data(RELIABILITY_APP_URL: str, token: str): ) """ api_data = await fetch_api_data( - equipment_id, year, RELIABILITY_APP_URL, token + assetnum, year, RELIABILITY_APP_URL, token ) + print(api_data) if api_data and "data" in api_data and api_data["data"]: print("API data:", api_data["data"][0]["actual_fail"]) else: - print(f"No API data available for {equipment_id} in year {year}") + print( + f"No API data available for {assetnum} in year {year}" + ) cursor.execute( insert_query, ( str(uuid4()), # id - equipment_id, # equipment_id + assetnum, # assetnum year, # tahun seq, # seq 1, # is_actual @@ -354,7 +358,7 @@ async def query_data(RELIABILITY_APP_URL: str, token: str): ), ), ) - print(f"Data inserted for {equipment_id} in year {year}") + print(f"Data inserted for {assetnum} in year {year}") seq = seq + 1 diff --git a/src/modules/equipment/run.py b/src/modules/equipment/run.py index 5f255a4..bc3e7fb 100644 --- a/src/modules/equipment/run.py +++ b/src/modules/equipment/run.py @@ -9,14 +9,28 @@ import time async def main(assetnum, token, RELIABILITY_APP_URL): start_time = time.time() - await query_data(RELIABILITY_APP_URL, token) - prediksi = Prediksi(RELIABILITY_APP_URL) - await prediksi.predict_equipment_data( - assetnum, - token=token, - ) - eac = Eac() - eac.hitung_eac_equipment(assetnum) + try: + await query_data(RELIABILITY_APP_URL, token) + except Exception as e: + print(f"Error in query_data: {str(e)}") + return + + try: + prediksi = Prediksi(RELIABILITY_APP_URL) + await prediksi.predict_equipment_data( + assetnum, + token=token, + ) + except Exception as e: + print(f"Error in predict_equipment_data: {str(e)}") + return + + try: + eac = Eac() + eac.hitung_eac_equipment(assetnum) + except Exception as e: + print(f"Error in hitung_eac_equipment: {str(e)}") + return end_time = time.time() execution_time = end_time - start_time