fix:menambah prediksi grafik 4 kernel

This commit is contained in:
muhamad fais aizat 2025-06-12 12:59:51 +07:00
parent 3ff9446d54
commit 4eadee3e43
19 changed files with 605 additions and 212 deletions

View File

@ -2,6 +2,7 @@ from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine, MetaData from sqlalchemy import create_engine, MetaData
engine = create_engine("mysql+pymysql://uupkixae2jbw2zse:1bFkfd8pfZ6EZhphAPQa@bdcaorplf9ct8apn6n5o-mysql.services.clever-cloud.com:3306/bdcaorplf9ct8apn6n5o") engine = create_engine("mysql+pymysql://uupkixae2jbw2zse:1bFkfd8pfZ6EZhphAPQa@bdcaorplf9ct8apn6n5o-mysql.services.clever-cloud.com:3306/bdcaorplf9ct8apn6n5o")
# engine = create_engine("mysql+pymysql://root@localhost:3306/predict")
meta = MetaData() meta = MetaData()
conn = engine.connect() conn = engine.connect()

View File

@ -12,5 +12,6 @@ settingPredict = Table(
Column('nilai_degree',String(255), nullable=True), Column('nilai_degree',String(255), nullable=True),
Column('nilai_coef',String(255), nullable=True), Column('nilai_coef',String(255), nullable=True),
Column('status',Boolean, nullable=False, default=False), Column('status',Boolean, nullable=False, default=False),
Column('statuskedepan',Boolean, nullable=False, default=False),
) )

View File

@ -90,9 +90,20 @@ def predict_price(db: Session = Depends(get_db)):
df['Tanggal'] = pd.to_datetime(df['Tanggal']) df['Tanggal'] = pd.to_datetime(df['Tanggal'])
# df['Harga_2Hari_Lalu'] = df['Harga_Kemarin'].shift(1) # df['Harga_2Hari_Lalu'] = df['Harga_Kemarin'].shift(1)
df.dropna(inplace=True) df.dropna(inplace=True)
min_max_per_kolom = {}
for kolom in kolom_numerik:
nilai_min = df[kolom].min()
nilai_max = df[kolom].max()
min_max_per_kolom[kolom] = {
'min': nilai_min,
'max': nilai_max
}
# Normalisasi Data # Normalisasi Data
scaler = StandardScaler() # scaler = StandardScaler()
scaler = MinMaxScaler()
df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'RataRata_Kemarin', 'RataRata_Sekarang']] = scaler.fit_transform( df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'RataRata_Kemarin', 'RataRata_Sekarang']] = scaler.fit_transform(
df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'RataRata_Kemarin', 'RataRata_Sekarang']] df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'RataRata_Kemarin', 'RataRata_Sekarang']]
) )
@ -169,12 +180,19 @@ def predict_price(db: Session = Depends(get_db)):
id_tomat = id_test[i] id_tomat = id_test[i]
hasil = y_pred[i] hasil = y_pred[i]
print("start prediction", id_tomat, hasil) # hasil = float(y_pred[i])
# print("start prediction", id_tomat, hasil)
# Invers hasil prediksi # Invers hasil prediksi
dummy_row = np.zeros((1, 5)) # dummy_row = np.zeros((1, 5))
dummy_row[0][4] = hasil # dummy_row[0][4] = hasil
prediksi_asli = float(scaler.inverse_transform(dummy_row)[0][4]) # prediksi_asli = float(scaler.inverse_transform(dummy_row)[0][4])
min_pred = min_max_per_kolom['RataRata_Sekarang']['min']
max_pred = min_max_per_kolom['RataRata_Sekarang']['max']
prediksi_asli1 = hasil * (max_pred - min_pred) + min_pred
prediksi_asli = int(round(prediksi_asli1, 0))
# print("start prediction", id_tomat, prediksi_asli)
insert_data.append({ insert_data.append({
@ -238,7 +256,7 @@ def get_price_history(
if tanggal_input == latest_date: if tanggal_input == latest_date:
# **Melakukan Prediksi 7 Hari ke Depan** # **Melakukan Prediksi 7 Hari ke Depan**
settings = db.execute(select(settingPredict).where(settingPredict.c.status == True)).fetchone() settings = db.execute(select(settingPredict).where(settingPredict.c.statuskedepan == True)).mappings().all()
if not settings: if not settings:
raise HTTPException(status_code=400, detail="Tidak ada konfigurasi prediksi yang aktif") raise HTTPException(status_code=400, detail="Tidak ada konfigurasi prediksi yang aktif")
@ -272,9 +290,19 @@ def get_price_history(
# df['Harga_2Hari_Lalu'] = df['Harga_Kemarin'].shift(1) # df['Harga_2Hari_Lalu'] = df['Harga_Kemarin'].shift(1)
df.dropna(inplace=True) df.dropna(inplace=True)
min_max_per_kolom = {}
for kolom in kolom_numerik:
nilai_min = df[kolom].min()
nilai_max = df[kolom].max()
min_max_per_kolom[kolom] = {
'min': nilai_min,
'max': nilai_max
}
# 6. Normalisasi Data # 6. Normalisasi Data
# scaler = MinMaxScaler() scaler = MinMaxScaler()
scaler = StandardScaler() # scaler = StandardScaler()
df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'RataRata_Kemarin', 'RataRata_Sekarang']] = scaler.fit_transform( df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'RataRata_Kemarin', 'RataRata_Sekarang']] = scaler.fit_transform(
df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'RataRata_Kemarin', 'RataRata_Sekarang']] df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'RataRata_Kemarin', 'RataRata_Sekarang']]
) )
@ -286,83 +314,168 @@ def get_price_history(
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)
# Inisialisasi SVR # # Inisialisasi SVR
kernel = settings.nama_kernel # # kernel = settings.nama_kernel
C = float(settings.nilai_c) if settings.nilai_c is not None else 1.0 # kernel = settings["nama_kernel"]
gamma = float(settings.nilai_gamma) if settings.nilai_gamma not in [None, "auto", "scale"] else settings.nilai_gamma # C = float(settings.nilai_c) if settings.nilai_c is not None else 1.0
epsilon = float(settings.nilai_epsilon) if settings.nilai_epsilon is not None else 0.1 # gamma = float(settings.nilai_gamma) if settings.nilai_gamma not in [None, "auto", "scale"] else settings.nilai_gamma
degree = int(settings.nilai_degree) if settings.nilai_degree is not None else 3 # epsilon = float(settings.nilai_epsilon) if settings.nilai_epsilon is not None else 0.1
coef0 = float(settings.nilai_coef) if settings.nilai_coef is not None else 0.0 # degree = int(settings.nilai_degree) if settings.nilai_degree is not None else 3
# coef0 = float(settings.nilai_coef) if settings.nilai_coef is not None else 0.0
if kernel == "linear": # if kernel == "linear":
svr = SVR(kernel="linear", C=C, epsilon=epsilon) # svr = SVR(kernel="linear", C=C, epsilon=epsilon)
elif kernel == "rbf": # elif kernel == "rbf":
svr = SVR(kernel="rbf", C=C, gamma=gamma, epsilon=epsilon) # svr = SVR(kernel="rbf", C=C, gamma=gamma, epsilon=epsilon)
elif kernel == "sigmoid": # elif kernel == "sigmoid":
svr = SVR(kernel="sigmoid", C=C, gamma=gamma, coef0=coef0, epsilon=epsilon) # svr = SVR(kernel="sigmoid", C=C, gamma=gamma, coef0=coef0, epsilon=epsilon)
elif kernel == "poly": # elif kernel == "poly":
svr = SVR(kernel="poly", C=C, gamma=gamma, coef0=coef0, degree=degree, epsilon=epsilon) # svr = SVR(kernel="poly", C=C, gamma=gamma, coef0=coef0, degree=degree, epsilon=epsilon)
svr.fit(X_train, y_train) # svr.fit(X_train, y_train)
# 9. Lakukan Prediksi pada Data Uji # # # 9. Lakukan Prediksi pada Data Uji
y_pred = svr.predict(X_test) # # y_pred = svr.predict(X_test)
# 10. Evaluasi Model # # # 10. Evaluasi Model
mae = mean_absolute_error(y_test, y_pred) # # mae = mean_absolute_error(y_test, y_pred)
rmse = np.sqrt(mean_squared_error(y_test, y_pred)) # # rmse = np.sqrt(mean_squared_error(y_test, y_pred))
mape = mape = mean_absolute_percentage_error(y_test, y_pred) # # mape = mape = mean_absolute_percentage_error(y_test, y_pred)
# 11. Prediksi 7 Hari ke Depan # # 11. Prediksi 7 Hari ke Depan
last_data = pd.DataFrame([X.iloc[-1].values], columns=X.columns) # last_data = pd.DataFrame([X.iloc[-1].values], columns=X.columns)
predictions = [] # predictions = []
for _ in range(7): # for _ in range(7):
pred = svr.predict(last_data)[0] # pred = svr.predict(last_data)[0]
predictions.append(pred) # predictions.append(pred)
# Update input dengan DataFrame, bukan NumPy array # # Update input dengan DataFrame, bukan NumPy array
last_data = pd.DataFrame([[last_data.iloc[0, 1], last_data.iloc[0, 2], last_data.iloc[0, 3], pred]], columns=X.columns) # last_data = pd.DataFrame([[last_data.iloc[0, 1], last_data.iloc[0, 2], last_data.iloc[0, 3], pred]], columns=X.columns)
# 12. Konversi hasil prediksi ke skala asli # # 12. Konversi hasil prediksi ke skala asli
predictions = scaler.inverse_transform([[0, 0, 0, 0, p] for p in predictions])[:, 4] # # predictions = scaler.inverse_transform([[0, 0, 0, 0, p] for p in predictions])[:, 4]
# predictions = np.array(predictions)
# min_pred = min_max_per_kolom['RataRata_Sekarang']['min']
# max_pred = min_max_per_kolom['RataRata_Sekarang']['max']
# prediksi_asli1 = predictions * (max_pred - min_pred) + min_pred
# predictions = prediksi_asli1
# 13. Tampilkan hasil prediksi # # 13. Tampilkan hasil prediksi
prediksi_harga = [] # hasil_prediksi_semua_kernel = []
harga_list = [] # Menyimpan harga untuk mencari min dan max # prediksi_harga = []
# harga_list = [] # Menyimpan harga untuk mencari min dan max
for i, pred in enumerate(predictions, start=1): # for i, pred in enumerate(predictions, start=1):
tanggal_prediksi = latest_date + timedelta(days=i) # tanggal_prediksi = latest_date + timedelta(days=i)
tanggal_str = tanggal_prediksi.strftime("%Y-%m-%d") # Format tanggal YYYY-MM-DD # tanggal_str = tanggal_prediksi.strftime("%Y-%m-%d") # Format tanggal YYYY-MM-DD
harga_bulat = round(pred, 0) # harga_bulat = round(pred, 0)
# print(f"Tanggal {tanggal_str}: {harga_bulat}") # # print(f"Tanggal {tanggal_str}: {harga_bulat}")
prediksi_harga.append({"tanggal": tanggal_str, "harga_prediksi": harga_bulat}) # prediksi_harga.append({"tanggal": tanggal_str, "harga_prediksi": harga_bulat})
harga_list.append(harga_bulat) # harga_list.append(harga_bulat)
# Dapatkan nilai min dan max # hasil_prediksi_semua_kernel.append({
harga_min = min(harga_list) # "kernel": kernel,
harga_max = max(harga_list) # "hasil_prediksi": prediksi_harga,
y_axis = f"{harga_min},{harga_max}" # "min": min(harga_list),
# "max": max(harga_list)
# })
# # Dapatkan nilai min dan max
# harga_min = min(harga_list)
# harga_max = max(harga_list)
# y_axis = f"{harga_min},{harga_max}"
dataTableAktual = [] dataTableAktual = []
dataTablePrediksi = [] dataTablePrediksi = []
prediksi_per_hari = {}
hasil_prediksi_semua_kernel = []
y_axis = f"{int(min_max_per_kolom['RataRata_Sekarang']['min'])},{int(min_max_per_kolom['RataRata_Sekarang']['max'])}"
# Loop setiap kernel aktif
for setting in settings:
kernel = setting["nama_kernel"]
C = float(setting["nilai_c"]) if setting["nilai_c"] is not None else 1.0
gamma = setting["nilai_gamma"]
gamma = float(gamma) if gamma not in [None, "auto", "scale"] else gamma
epsilon = float(setting["nilai_epsilon"]) if setting["nilai_epsilon"] is not None else 0.1
degree = int(setting["nilai_degree"]) if setting["nilai_degree"] is not None else 3
coef0 = float(setting["nilai_coef"]) if setting["nilai_coef"] is not None else 0.0
# Inisialisasi model SVR sesuai kernel
if kernel == "linear":
svr = SVR(kernel="linear", C=C, epsilon=epsilon)
elif kernel == "rbf":
svr = SVR(kernel="rbf", C=C, gamma=gamma, epsilon=epsilon)
elif kernel == "sigmoid":
svr = SVR(kernel="sigmoid", C=C, gamma=gamma, coef0=coef0, epsilon=epsilon)
elif kernel == "poly":
svr = SVR(kernel="poly", C=C, gamma=gamma, coef0=coef0, degree=degree, epsilon=epsilon)
else:
continue # Lewati jika kernel tidak valid
svr.fit(X_train, y_train)
# Prediksi 7 hari ke depan
last_data = pd.DataFrame([X.iloc[-1].values], columns=X.columns)
predictions = []
for _ in range(7):
pred = svr.predict(last_data)[0]
predictions.append(pred)
last_data = pd.DataFrame([[last_data.iloc[0, 1], last_data.iloc[0, 2], last_data.iloc[0, 3], pred]], columns=X.columns)
# Konversi skala prediksi ke harga asli
predictions = np.array(predictions)
min_pred = min_max_per_kolom['RataRata_Sekarang']['min']
max_pred = min_max_per_kolom['RataRata_Sekarang']['max']
prediksi_asli = predictions * (max_pred - min_pred) + min_pred
# Format hasil
prediksi_harga = []
harga_list = []
for i, pred in enumerate(prediksi_asli, start=1):
tanggal_prediksi = latest_date + timedelta(days=i)
tanggal_str = tanggal_prediksi.strftime("%Y-%m-%d")
harga_bulat = round(pred, 0)
prediksi_harga.append({"tanggal": tanggal_str, "harga_prediksi": harga_bulat})
harga_list.append(harga_bulat)
hasil_prediksi_semua_kernel.append({
"kernel": kernel,
"hasil_prediksi": prediksi_harga,
})
for i, pred in enumerate(prediksi_asli, start=1):
tanggal_prediksi = latest_date + timedelta(days=i)
tanggal_str = tanggal_prediksi.strftime("%Y-%m-%d")
harga_bulat = round(pred, 0)
if tanggal_str not in prediksi_per_hari:
prediksi_per_hari[tanggal_str] = {"tanggal": tanggal_str}
prediksi_per_hari[tanggal_str][kernel] = harga_bulat
dataTablePrediksi = list(prediksi_per_hari.values())
return { return {
"Mean Absolute Error (MAE)": mae, # "Mean Absolute Error (MAE)": mae,
"Root Mean Squared Error (RMSE)": rmse, # "Root Mean Squared Error (RMSE)": rmse,
"Mean Absolute Percentage Error (MAPE)": mape, # "Mean Absolute Percentage Error (MAPE)": mape,
"dataTableAktual": dataTableAktual, "dataTableAktual": dataTableAktual,
"dataTablePrediksi": prediksi_harga, "dataTablePrediksi": dataTablePrediksi,
"tanggal_input": tanggal, "tanggal_input": tanggal,
"dataGrafik": prediksi_harga, "dataGrafik": dataTablePrediksi,
"YAxis": y_axis "YAxis": y_axis
} }

View File

@ -2,7 +2,7 @@ from fastapi import APIRouter, HTTPException, Query, Depends
from config.db import conn, get_db from config.db import conn, get_db
from models.index import settingPredict from models.index import settingPredict
from schemas.index import SettingPredict from schemas.index import SettingPredict
from sqlalchemy.sql import select, insert, update, delete from sqlalchemy.sql import select, insert, update, delete, text
from middleware.index import verify_token from middleware.index import verify_token
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
@ -12,6 +12,25 @@ settingPredict_router = APIRouter(
) )
# Get All Settings # Get All Settings
@settingPredict_router.get("/all", dependencies=[Depends(verify_token)])
def get_all_settings(db: Session = Depends(get_db)):
try:
raw_query = text("""
SELECT *
FROM setting_predict
WHERE nama_kernel IN ('linear', 'rbf', 'sigmoid', 'poly')
ORDER BY FIELD(nama_kernel, 'linear', 'rbf', 'sigmoid', 'poly');
""")
result = db.execute(raw_query).fetchall()
if not result:
return {"message": "No data found"} # Menghindari error saat data kosong
return [dict(row._mapping) for row in result]
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@settingPredict_router.get("/", dependencies=[Depends(verify_token)]) @settingPredict_router.get("/", dependencies=[Depends(verify_token)])
def get_all_settings(db: Session = Depends(get_db)): def get_all_settings(db: Session = Depends(get_db)):
try: try:
@ -128,3 +147,26 @@ async def update_status_setting(
db.commit() db.commit()
return {"message": "Status updated successfully", "updated_status": status} return {"message": "Status updated successfully", "updated_status": status}
@settingPredict_router.put("/update-status-kedepan/{setting_id}", dependencies=[Depends(verify_token)])
async def update_status_setting(
setting_id: int,
statuskedepan: bool = Query(...),
db: Session = Depends(get_db)
):
# Cek apakah setting dengan ID tersebut ada
query = select(settingPredict.c.id).where(settingPredict.c.id == setting_id)
result = db.execute(query).fetchone()
if not result:
raise HTTPException(status_code=404, detail="Setting not found")
# Update hanya status
query = update(settingPredict).where(settingPredict.c.id == setting_id).values(statuskedepan=statuskedepan)
result = db.execute(query)
if result.rowcount == 0:
raise HTTPException(status_code=400, detail="Failed to update status kedepan")
db.commit()
return {"message": "Status updated successfully", "updated_status_kedepan": statuskedepan}

View File

@ -62,15 +62,26 @@ def predict_price(
# df.dropna(inplace=True) # df.dropna(inplace=True)
min_max_per_kolom = {}
for kolom in kolom_numerik:
nilai_min = df[kolom].min()
nilai_max = df[kolom].max()
min_max_per_kolom[kolom] = {
'min': nilai_min,
'max': nilai_max
}
# Simpan hasil preprocessing # Simpan hasil preprocessing
hasil_preprocessing = df.to_dict(orient='records') hasil_preprocessing = df.to_dict(orient='records')
# Normalisasi Data # Normalisasi Data
# scaler = MinMaxScaler() scaler = MinMaxScaler()
# df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_Sekarang']] = scaler.fit_transform(df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_Sekarang']]) df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_Sekarang']] = scaler.fit_transform(df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_Sekarang']])
scaler = StandardScaler() # scaler = StandardScaler()
df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_Sekarang']] = scaler.fit_transform(df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_Sekarang']]) # df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_Sekarang']] = scaler.fit_transform(df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_Sekarang']])
# Simpan hasil normalisasi # Simpan hasil normalisasi
@ -113,50 +124,45 @@ def predict_price(
# Kembalikan skala data # Kembalikan skala data
df_prediksi = df.iloc[len(X_train):].copy() df_prediksi = df.iloc[len(X_train):].copy()
# df_prediksi['Tanggal'] = df_prediksi['Tanggal'].dt.date # # df_prediksi['Tanggal'] = df_prediksi['Tanggal'].dt.date
df_prediksi['Harga_Prediksi'] = y_pred df_prediksi['Harga_Prediksi'] = y_pred
# Daftar kolom yang telah dinormalisasi # # Daftar kolom yang telah dinormalisasi
cols_scaled = ['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_Sekarang'] cols_scaled = ['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_Sekarang']
# Invers scaling satu per satu kolom berdasarkan mean dan std dari StandardScaler # # Invers scaling satu per satu kolom berdasarkan mean dan std dari StandardScaler
feature_names = scaler.feature_names_in_.tolist()
# Invers Harga_Prediksi berdasarkan skala 'Harga_Sekarang'
index_harga_sekarang = feature_names.index('Harga_Sekarang')
mean_sekarang = scaler.mean_[index_harga_sekarang]
std_sekarang = np.sqrt(scaler.var_[index_harga_sekarang])
df_prediksi['Harga_Prediksi'] = df_prediksi['Harga_Prediksi'] * std_sekarang + mean_sekarang
df_prediksi['Harga_Prediksi'] = df_prediksi['Harga_Prediksi'].round(0)
# Invers kolom lain yang tersedia di df_prediksi
for kolom in cols_scaled:
if kolom in df_prediksi.columns:
index = feature_names.index(kolom)
mean = scaler.mean_[index]
std = np.sqrt(scaler.var_[index])
df_prediksi[kolom] = df_prediksi[kolom] * std + mean
# Ambil nilai min dan max dari scaler
# data_min = scaler.data_min_
# data_max = scaler.data_max_
# feature_names = scaler.feature_names_in_.tolist() # feature_names = scaler.feature_names_in_.tolist()
# # Invers Harga_Prediksi berdasarkan skala 'Harga_Sekarang' # # Invers Harga_Prediksi berdasarkan skala 'Harga_Sekarang'
# index_harga_sekarang = feature_names.index('Harga_Sekarang') # index_harga_sekarang = feature_names.index('Harga_Sekarang')
# min_sekarang = data_min[index_harga_sekarang] # mean_sekarang = scaler.mean_[index_harga_sekarang]
# max_sekarang = data_max[index_harga_sekarang] # std_sekarang = np.sqrt(scaler.var_[index_harga_sekarang])
# df_prediksi['Harga_Prediksi'] = df_prediksi['Harga_Prediksi'] * (max_sekarang - min_sekarang) + min_sekarang # df_prediksi['Harga_Prediksi'] = df_prediksi['Harga_Prediksi'] * std_sekarang + mean_sekarang
# df_prediksi['Harga_Prediksi'] = df_prediksi['Harga_Prediksi'].round(0) # df_prediksi['Harga_Prediksi'] = df_prediksi['Harga_Prediksi'].round(0)
# # Invers kolom lain yang tersedia di df_prediksi # # Invers kolom lain yang tersedia di df_prediksi
# for kolom in cols_scaled: # for kolom in cols_scaled:
# if kolom in df_prediksi.columns: # if kolom in df_prediksi.columns:
# index = feature_names.index(kolom) # index = feature_names.index(kolom)
# min_val = data_min[index] # mean = scaler.mean_[index]
# max_val = data_max[index] # std = np.sqrt(scaler.var_[index])
# df_prediksi[kolom] = df_prediksi[kolom] * (max_val - min_val) + min_val # df_prediksi[kolom] = df_prediksi[kolom] * std + mean
# # Ambil nilai min dan max dari scaler
# Inverse semua kolom yang dinormalisasi ke skala asli
for kolom in cols_scaled:
if kolom in df_prediksi.columns:
min_val = min_max_per_kolom[kolom]['min']
max_val = min_max_per_kolom[kolom]['max']
df_prediksi[kolom] = df_prediksi[kolom] * (max_val - min_val) + min_val
df_prediksi[kolom] = df_prediksi[kolom].round(0)
# Inverse kolom prediksi (Harga_Prediksi) berdasarkan skala 'Harga_Sekarang'
min_pred = min_max_per_kolom['Harga_Sekarang']['min']
max_pred = min_max_per_kolom['Harga_Sekarang']['max']
df_prediksi['Harga_Prediksi'] = df_prediksi['Harga_Prediksi'] * (max_pred - min_pred) + min_pred
df_prediksi['Harga_Prediksi'] = df_prediksi['Harga_Prediksi'].round(0)
# Export atau tampilkan hasil # Export atau tampilkan hasil
@ -184,5 +190,6 @@ def predict_price(
"MAE": mae, "MAE": mae,
"RMSE": rmse, "RMSE": rmse,
"MAPE": mape "MAPE": mape
} },
"min_max_per_kolom": min_max_per_kolom
} }

View File

@ -9,6 +9,7 @@ class SettingPredict(BaseModel):
nilai_degree: Optional[str] = None nilai_degree: Optional[str] = None
nilai_coef: Optional[str] = None nilai_coef: Optional[str] = None
status: bool status: bool
statuskedepan: bool
class Config: class Config:
orm_mode = True orm_mode = True

View File

@ -1,60 +1,102 @@
import React from 'react' import React from 'react'
import { import {
Table, Table,
TableBody, TableBody,
TableCaption, TableCaption,
TableCell, TableCell,
TableFooter, TableFooter,
TableHead, TableHead,
TableHeader, TableHeader,
TableRow, TableRow,
} from "@/components/ui/table"; } from "@/components/ui/table";
import dayjs from "dayjs"; import dayjs from "dayjs";
// Generate data selama satu bulan
const dataHarga = Array.from({ length: 30 }, (_, index) => ({
no: index + 1,
tanggal: dayjs().subtract(30 - index, "day").format("DD/MM/YYYY"),
harga: `Rp ${Math.floor(Math.random() * 10000) + 5000}`,
}));
const TablePrediksi = ({tabelDataPredict}) => { // Generate data selama satu bulan
const dataHarga = Array.from({ length: 30 }, (_, index) => ({
no: index + 1,
tanggal: dayjs().subtract(30 - index, "day").format("DD/MM/YYYY"),
harga: `Rp ${Math.floor(Math.random() * 10000) + 5000}`,
}));
const TablePrediksi = ({ tabelDataPredict }) => {
const isHargaAvailable = tabelDataPredict.some(item => item.harga_prediksi !== undefined);
const isLinearAvailable = tabelDataPredict.some(item => item.linear !== undefined);
const isRbfAvailable = tabelDataPredict.some(item => item.rbf !== undefined);
const isSigmoidAvailable = tabelDataPredict.some(item => item.sigmoid !== undefined);
const isPolyAvailable = tabelDataPredict.some(item => item.poly !== undefined);
const totalColSpan =
2 + // kolom No dan Tanggal
(isHargaAvailable ? 1 : 0) +
(isLinearAvailable ? 1 : 0) +
(isRbfAvailable ? 1 : 0) +
(isSigmoidAvailable ? 1 : 0) +
(isPolyAvailable ? 1 : 0);
return ( return (
<div className='w-[100%]'> <div className='w-[100%]'>
<h3 className='text-[14px] font-bold mb-6' >Harga Prediksi</h3> <h3 className='text-[14px] font-bold mb-6' >Harga Prediksi</h3>
<Table className='border'> <Table className='border'>
<TableHeader className='bg-[#F5F5F5]'> <TableHeader className='bg-[#F5F5F5]'>
<TableRow > <TableRow >
<TableHead className="w-[50px] font-bold text-black">No</TableHead> <TableHead className="w-[50px] font-bold text-black">No</TableHead>
<TableHead className='text-center font-bold text-black'>Tanggal</TableHead> <TableHead className='text-center font-bold text-black'>Tanggal</TableHead>
<TableHead className="text-center font-bold text-black">Harga</TableHead> {isHargaAvailable && (
</TableRow> <TableHead className="text-center font-bold text-black">Harga</TableHead>
</TableHeader> )}
<TableBody className='bg-white'> {isLinearAvailable && (
{tabelDataPredict.length > 0 ? ( <TableHead className="text-center font-bold text-black">Prediksi Linear</TableHead>
tabelDataPredict.map((item, index) => ( )}
<TableRow key={index}> {isRbfAvailable && (
<TableCell className="font-medium">{index + 1}</TableCell> <TableHead className="text-center font-bold text-black">Prediksi RBF</TableHead>
<TableCell className="text-center">{item.tanggal}</TableCell> )}
<TableCell className="text-center">Rp.{item.harga_prediksi}</TableCell> {isSigmoidAvailable && (
</TableRow> <TableHead className="text-center font-bold text-black">Prediksi Sigmoid</TableHead>
)) )}
) : ( {isPolyAvailable && (
<TableRow> <TableHead className="text-center font-bold text-black">Prediksi Polynomial</TableHead>
<TableCell colSpan="3" className="text-center text-gray-500"> )}
Tidak ada data </TableRow>
</TableCell> </TableHeader>
</TableRow> <TableBody className='bg-white'>
)} {tabelDataPredict.length > 0 ? (
</TableBody> tabelDataPredict.map((item, index) => (
<TableFooter> <TableRow key={index}>
<TableRow> <TableCell className="font-medium">{index + 1}</TableCell>
<TableCell colSpan={2}>Total Data</TableCell> <TableCell className="text-center">{item.tanggal}</TableCell>
<TableCell className="text-right">{tabelDataPredict.length} Hari</TableCell> {item.harga_prediksi !== undefined && (
</TableRow> <TableCell className="text-center">Rp.{item.harga_prediksi}</TableCell>
</TableFooter> )}
</Table> {item.linear !== undefined && (
<TableCell className="text-center">Rp.{item.linear}</TableCell>
)}
{item.rbf !== undefined && (
<TableCell className="text-center">Rp.{item.rbf}</TableCell>
)}
{item.sigmoid !== undefined && (
<TableCell className="text-center">Rp.{item.sigmoid}</TableCell>
)}
{item.poly !== undefined && (
<TableCell className="text-center">Rp.{item.poly}</TableCell>
)}
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan="3" className="text-center text-gray-500">
Tidak ada data
</TableCell>
</TableRow>
)}
</TableBody>
<TableFooter>
<TableRow>
<TableCell colSpan={totalColSpan - 1}>Total Data</TableCell>
<TableCell className="text-right">{tabelDataPredict.length} Hari</TableCell>
</TableRow>
</TableFooter>
</Table>
</div> </div>
) )
} }

View File

@ -69,8 +69,8 @@ const ViewGrafik = ({ date, setDate, dataYAxis, setDataYAxis, priceType, setPric
const fetchData = async () => { const fetchData = async () => {
if (!date && !tempPriceType) { if (!date && !tempPriceType) {
setTabelDataAktual([]); setTabelDataAktual([]);
@ -105,7 +105,7 @@ const ViewGrafik = ({ date, setDate, dataYAxis, setDataYAxis, priceType, setPric
console.log(tempPriceType); console.log(tempPriceType);
if (formattedDate==dateTerbaru && tempPriceType=="all") { if (formattedDate == dateTerbaru && tempPriceType == "all") {
setTabelDataAktual([]); setTabelDataAktual([]);
setTabelDataPredict([]); setTabelDataPredict([]);
@ -120,7 +120,7 @@ const ViewGrafik = ({ date, setDate, dataYAxis, setDataYAxis, priceType, setPric
return; return;
} }
if (formattedDate==dateTerbaru && tempPriceType=="actual") { if (formattedDate == dateTerbaru && tempPriceType == "actual") {
setTabelDataAktual([]); setTabelDataAktual([]);
setTabelDataPredict([]); setTabelDataPredict([]);
@ -150,13 +150,17 @@ const ViewGrafik = ({ date, setDate, dataYAxis, setDataYAxis, priceType, setPric
return; return;
} }
try { try {
const response = await axios.get(`${API_URL}/predict/history?tanggal=${formattedDate}&data_type=${tempPriceType}`); const response = await axios.get(`${API_URL}/predict/history?tanggal=${formattedDate}&data_type=${tempPriceType}`);
const formattedData = response.data.dataGrafik.map(item => ({ const formattedData = response.data.dataGrafik.map(item => ({
date: item.tanggal, date: item.tanggal,
actual: item.harga_aktual, actual: item.harga_aktual,
predicted: item.harga_prediksi predicted: item.harga_prediksi,
linear: item.linear,
rbf: item.rbf,
sigmoid: item.sigmoid,
poly: item.poly,
})); }));
setPriceType(tempPriceType); setPriceType(tempPriceType);
@ -247,6 +251,25 @@ const ViewGrafik = ({ date, setDate, dataYAxis, setDataYAxis, priceType, setPric
{priceType !== "actual" && ( {priceType !== "actual" && (
<Line dataKey="predicted" type="monotone" stroke="#387ef5" strokeWidth={2} dot={false} name="Harga Prediksi" /> <Line dataKey="predicted" type="monotone" stroke="#387ef5" strokeWidth={2} dot={false} name="Harga Prediksi" />
)} )}
{["linear", "poly", "rbf", "sigmoid"].map((kernel) =>
chartData[0] && chartData[0][kernel] !== undefined ? (
<Line
key={kernel}
dataKey={kernel}
type="monotone"
stroke={
kernel === "linear" ? "#00C49F" :
kernel === "rbf" ? "#FFBB28" :
kernel === "sigmoid" ? "#8884d8" :
kernel === "poly" ? "#FF4444" :
"#000"
}
strokeWidth={2}
dot={false}
name={`Prediksi ${kernel}`}
/>
) : null
)}
</LineChart> </LineChart>
</ResponsiveContainer> </ResponsiveContainer>
<ScrollBar orientation="horizontal" /> <ScrollBar orientation="horizontal" />

View File

@ -9,6 +9,7 @@ import { useToast } from '@/hooks/use-toast';
const Setting = () => { const Setting = () => {
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [isLoadingGrafik, setIsLoadingGrafik] = useState(false);
const { toast } = useToast(); const { toast } = useToast();
const getemail = localStorage.getItem("email"); const getemail = localStorage.getItem("email");
const idUser = localStorage.getItem("idUser"); const idUser = localStorage.getItem("idUser");
@ -21,35 +22,75 @@ const Setting = () => {
const [gamma, setGamma] = useState(""); const [gamma, setGamma] = useState("");
const [degree, setDegree] = useState(""); const [degree, setDegree] = useState("");
const [coef0, setCoef0] = useState(""); const [coef0, setCoef0] = useState("");
const [isChecked, setIsChecked] = useState(false);
const [isCheckedRBF, setIsCheckedRBF] = useState(false);
const [isCheckedSigmoid, setIsCheckedSigmoid] = useState(false);
const [isCheckedPoly, setIsCheckedPoly] = useState(false);
const [kernelData, setKernelData] = useState([]);
const handleCheckboxChangeall = (id) => {
setKernelData(prev =>
prev.map(item =>
item.id === id ? { ...item, statuskedepan: !item.statuskedepan } : item
)
);
}
const handleInputChange = (id, field, value) => {
const updatedData = kernelData.map((kernel) =>
kernel.id === id ? { ...kernel, [field]: value } : kernel
);
setKernelData(updatedData);
};
const fetchDataKernel = async () => { const fetchDataKernel = async () => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
try { try {
const response = await axios.get(`${API_URL}/setpredict/`, { const response = await axios.get(`${API_URL}/setpredict/`, {
headers: { headers: {
Authorization: `Bearer ${token}`, Authorization: `Bearer ${token}`,
}, },
}); });
console.log(response.data) console.log(response.data)
if (response.data.length > 0) { if (response.data.length > 0) {
setSelectedKernel(response.data[0].id) setSelectedKernel(response.data[0].id)
setSelectedKernelfalse(response.data[0].id) setSelectedKernelfalse(response.data[0].id)
setNilaiC(response.data[0].nilai_c) setNilaiC(response.data[0].nilai_c)
setEpsilon(response.data[0].nilai_epsilon) setEpsilon(response.data[0].nilai_epsilon)
setGamma(response.data[0].nilai_gamma) setGamma(response.data[0].nilai_gamma)
setDegree(response.data[0].nilai_degree) setDegree(response.data[0].nilai_degree)
setCoef0(response.data[0].nilai_coef) setCoef0(response.data[0].nilai_coef)
} }
// setDataHarga(response.data) // setDataHarga(response.data)
} catch (error) { } catch (error) {
console.error("Error fetching data", error); console.error("Error fetching data", error);
} }
} }
const fetchDataKernelkedepan = async () => {
const token = localStorage.getItem("token");
try {
const response = await axios.get(`${API_URL}/setpredict/all`, {
headers: {
Authorization: `Bearer ${token}`,
},
});
console.log(response.data)
setKernelData(response.data)
} catch (error) {
console.error("Error fetching data", error);
}
}
useEffect(() => { useEffect(() => {
fetchDataKernel(); fetchDataKernel();
}, []); fetchDataKernelkedepan();
}, []);
const handleCheckboxChange = (kernel) => { const handleCheckboxChange = (kernel) => {
setSelectedKernel(kernel === selectedKernel ? "" : kernel); setSelectedKernel(kernel === selectedKernel ? "" : kernel);
@ -130,7 +171,7 @@ const Setting = () => {
}, },
} }
); );
} else if (selectedKernel ===2 ){ } else if (selectedKernel === 2) {
const poly = await axios.put( const poly = await axios.put(
`${API_URL}/setpredict/2?nilai_c=${nilaiC}&nilai_gamma=${gamma}&nilai_epsilon=${epsilon}&nilai_degree=${degree}&nilai_coef=${coef0}`, `${API_URL}/setpredict/2?nilai_c=${nilaiC}&nilai_gamma=${gamma}&nilai_epsilon=${epsilon}&nilai_degree=${degree}&nilai_coef=${coef0}`,
null, null,
@ -142,7 +183,7 @@ const Setting = () => {
}, },
} }
); );
} else if (selectedKernel ===3 ){ } else if (selectedKernel === 3) {
const sigmoid = await axios.put( const sigmoid = await axios.put(
`${API_URL}/setpredict/3?nilai_c=${nilaiC}&nilai_gamma=${gamma}&nilai_epsilon=${epsilon}&nilai_coef=${coef0}`, `${API_URL}/setpredict/3?nilai_c=${nilaiC}&nilai_gamma=${gamma}&nilai_epsilon=${epsilon}&nilai_coef=${coef0}`,
null, null,
@ -154,7 +195,7 @@ const Setting = () => {
}, },
} }
); );
} else if (selectedKernel ===4 ){ } else if (selectedKernel === 4) {
const rbf = await axios.put( const rbf = await axios.put(
`${API_URL}/setpredict/4?nilai_c=${nilaiC}&nilai_gamma=${gamma}&nilai_epsilon=${epsilon}`, `${API_URL}/setpredict/4?nilai_c=${nilaiC}&nilai_gamma=${gamma}&nilai_epsilon=${epsilon}`,
null, null,
@ -182,19 +223,80 @@ const Setting = () => {
toast({ toast({
description: "Pengaturan model berhasil disimpan", description: "Pengaturan model berhasil disimpan",
}); });
fetchDataKernel();
fetchDataKernel();
} catch (error) { } catch (error) {
toast({ toast({
description: `${error.response.data.detail}`, description: `${error.response.data.detail}`,
variant: "destructive", variant: "destructive",
}); });
} finally { } finally {
setIsLoading(false); setIsLoading(false);
} }
} }
const handleSaveDataKernelGrafik = async () => {
setIsLoadingGrafik(true);
const token = localStorage.getItem("token");
try {
for (const kernel of kernelData) {
const {
id,
nilai_c,
nilai_epsilon,
nilai_gamma,
nilai_coef,
nilai_degree,
statuskedepan
} = kernel;
let params = new URLSearchParams();
if (nilai_c) params.append("nilai_c", nilai_c);
if (nilai_epsilon) params.append("nilai_epsilon", nilai_epsilon);
if (nilai_gamma) params.append("nilai_gamma", nilai_gamma);
if (nilai_coef) params.append("nilai_coef", nilai_coef);
if (nilai_degree) params.append("nilai_degree", nilai_degree);
await axios.put(`${API_URL}/setpredict/${id}?${params.toString()}`, null, {
headers: {
"Content-Type": "application/json",
Accept: "application/json",
Authorization: `Bearer ${token}`,
},
});
await axios.put(`${API_URL}/setpredict/update-status-kedepan/${id}?statuskedepan=${statuskedepan}`,null, {
headers: {
"Content-Type": "application/json",
Accept: "application/json",
Authorization: `Bearer ${token}`,
},
});
}
toast({
description: "Data kernel berhasil disimpan",
variant: "success",
});
} catch (error) {
toast({
description: `${error.response?.data?.detail || "Gagal menyimpan data"}`,
variant: "destructive",
});
} finally {
setIsLoadingGrafik(false);
fetchDataKernelkedepan();
}
};
return ( return (
<div className=" grid gap-[20px] mx-auto sm:px-6 md:px-8 "> <div className=" grid gap-[20px] mx-auto sm:px-6 md:px-8 ">
<div className='grid gap-[20px]'> <div className='grid gap-[20px]'>
@ -220,12 +322,12 @@ const Setting = () => {
</div> </div>
</div> </div>
<span className="block border-t-2 border-gray-200 w-full"></span> <span className="block border-t-2 border-gray-200 w-full"></span>
<div className='grid gap-[20px]'> <div className='grid gap-[20px] mb-10'>
<h1 className='text-[20px]'>Atur model peramalan</h1> <h1 className='text-[20px]'>Atur model prediksi history</h1>
<div className="flex flex-wrap -m-4"> <div className="flex flex-wrap -m-4">
<div className="xl:w-[30%] md:w-full w-full px-5 py-2"> <div className="xl:w-[30%] md:w-full w-full px-5 py-2">
<div className="grid w-full max-w-full items-center gap-3"> <div className="grid w-full max-w-full items-center gap-3">
<Label >pilih kernel</Label> <Label >pilih kernel untuk menghasilkan prediksi historynya</Label>
<div className="flex flex-wrap gap-3 px-5"> <div className="flex flex-wrap gap-3 px-5">
<div className="flex items-center space-x-2 xl:w-1/4 md:w-full w-full "> <div className="flex items-center space-x-2 xl:w-1/4 md:w-full w-full ">
<Checkbox <Checkbox
@ -287,33 +389,33 @@ const Setting = () => {
<div className="grid grid-cols-auto-fit md:grid-cols-2 xl:grid-cols-3 gap-4"> <div className="grid grid-cols-auto-fit md:grid-cols-2 xl:grid-cols-3 gap-4">
<div className="grid w-full items-center gap-1.5"> <div className="grid w-full items-center gap-1.5">
<Label>Masukan nilai C</Label> <Label>Masukan nilai C</Label>
<Input <Input
type="text" type="text"
placeholder="nilai C" placeholder="nilai C"
value={nilaiC ?? ""} value={nilaiC ?? ""}
onChange={(e) => setNilaiC(e.target.value)} onChange={(e) => setNilaiC(e.target.value)}
disabled={ disabled={
selectedKernel !== 1 && selectedKernel !== 1 &&
selectedKernel !== 2 && selectedKernel !== 2 &&
selectedKernel !== 3 && selectedKernel !== 3 &&
selectedKernel !== 4 selectedKernel !== 4
} }
/> />
</div> </div>
<div className="grid w-full items-center gap-1.5"> <div className="grid w-full items-center gap-1.5">
<Label>Masukan nilai epsilon</Label> <Label>Masukan nilai epsilon</Label>
<Input <Input
type="text" type="text"
placeholder="nilai epsilon" placeholder="nilai epsilon"
value={epsilon ?? ""} value={epsilon ?? ""}
onChange={(e) => setEpsilon(e.target.value)} onChange={(e) => setEpsilon(e.target.value)}
disabled={ disabled={
selectedKernel !== 1 && selectedKernel !== 1 &&
selectedKernel !== 2 && selectedKernel !== 2 &&
selectedKernel !== 3 && selectedKernel !== 3 &&
selectedKernel !== 4 selectedKernel !== 4
} }
/> />
</div> </div>
<div className="grid w-full items-center gap-1.5"> <div className="grid w-full items-center gap-1.5">
@ -321,7 +423,7 @@ const Setting = () => {
<Input <Input
type="text" type="text"
placeholder="nilai Gamma" placeholder="nilai Gamma"
value={gamma ?? ""} value={gamma ?? ""}
onChange={(e) => setGamma(e.target.value)} onChange={(e) => setGamma(e.target.value)}
disabled={ disabled={
selectedKernel !== 2 && selectedKernel !== 2 &&
@ -332,19 +434,19 @@ const Setting = () => {
</div> </div>
<div className="grid w-full items-center gap-1.5"> <div className="grid w-full items-center gap-1.5">
<Label>Masukan nilai degree</Label> <Label>Masukan nilai degree</Label>
<Input <Input
type="text" type="text"
placeholder="nilai degree" placeholder="nilai degree"
value={degree ?? ""} value={degree ?? ""}
onChange={(e) => setDegree(e.target.value)} onChange={(e) => setDegree(e.target.value)}
disabled={selectedKernel !== 2} /> disabled={selectedKernel !== 2} />
</div> </div>
<div className="grid w-full items-center gap-1.5"> <div className="grid w-full items-center gap-1.5">
<Label>Masukan nilai coef0</Label> <Label>Masukan nilai coef0</Label>
<Input <Input
type="text" type="text"
placeholder="nilai coef0" placeholder="nilai coef0"
value={coef0 ?? ""} value={coef0 ?? ""}
onChange={(e) => setCoef0(e.target.value)} onChange={(e) => setCoef0(e.target.value)}
disabled={ disabled={
selectedKernel !== 2 && selectedKernel !== 3 selectedKernel !== 2 && selectedKernel !== 3
@ -357,6 +459,67 @@ const Setting = () => {
<div> <div>
<Button className="xl:w-[80px] md:w-full w-full px-5 py-2 bg-gradient-to-r from-[#402412a8] to-[#9a070790]" onClick={handleSaveDataKernel} disabled={isLoading}> {isLoading ? "Diproses..." : "Simpan"}</Button> <Button className="xl:w-[80px] md:w-full w-full px-5 py-2 bg-gradient-to-r from-[#402412a8] to-[#9a070790]" onClick={handleSaveDataKernel} disabled={isLoading}> {isLoading ? "Diproses..." : "Simpan"}</Button>
</div> </div>
<span className="block border-t-2 border-gray-200 w-full"></span>
<h1 className='text-[20px]'>Atur kernel untuk grafik prediksi kedepan</h1>
{kernelData.map((kernel) => (
<div key={kernel.id} className="grid gap-[20px]">
<h1 className="text-[14px] capitalize">Kernel {kernel.nama_kernel}</h1>
<div className="flex flex-wrap -m-4 px-5 items-center">
<div className="flex items-center gap-4 xl:w-1/12 md:w-full w-full justify-end md:justify-start">
<Checkbox
id={`${kernel.nama_kernel}Status`}
checked={kernel.statuskedepan}
onCheckedChange={() => handleCheckboxChangeall(kernel.id)}
/>
<label
htmlFor={`${kernel.nama_kernel}Status`}
className="text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 cursor-pointer"
>
{kernel.statuskedepan ? "Sudah Aktif" : "Belum Aktif"}
</label>
</div>
{/* Input Nilai C */}
<div className="xl:w-1/6 md:w-full w-full px-5 py-2">
<Label>Masukan Nilai C</Label>
<Input type="text" value={kernel.nilai_c || ""} onChange={(e) => handleInputChange(kernel.id, "nilai_c", e.target.value)} disabled={!kernel.statuskedepan} />
</div>
{/* Input Nilai Epsilon */}
<div className="xl:w-1/6 md:w-full w-full px-5 py-2">
<Label>Masukan Nilai Epsilon</Label>
<Input type="text" value={kernel.nilai_epsilon || ""} onChange={(e) => handleInputChange(kernel.id, "nilai_epsilon", e.target.value)} disabled={!kernel.statuskedepan} />
</div>
{/* Input Nilai Gamma */}
{kernel.nilai_gamma !== null && (
<div className="xl:w-1/6 md:w-full w-full px-5 py-2">
<Label>Masukan Nilai Gamma</Label>
<Input type="text" value={kernel.nilai_gamma || ""} onChange={(e) => handleInputChange(kernel.id, "nilai_gamma", e.target.value)} disabled={!kernel.statuskedepan} />
</div>
)}
{/* Input Nilai Coef */}
{kernel.nilai_coef !== null && (
<div className="xl:w-1/6 md:w-full w-full px-5 py-2">
<Label>Masukan Nilai Coef()</Label>
<Input type="text" value={kernel.nilai_coef || ""} onChange={(e) => handleInputChange(kernel.id, "nilai_coef", e.target.value)} disabled={!kernel.statuskedepan} />
</div>
)}
{/* Input Nilai Degree */}
{kernel.nilai_degree !== null && (
<div className="xl:w-1/6 md:w-full w-full px-5 py-2">
<Label>Masukan Nilai Degree</Label>
<Input type="text" value={kernel.nilai_degree || ""} onChange={(e) => handleInputChange(kernel.id, "nilai_degree", e.target.value)} disabled={!kernel.statuskedepan} />
</div>
)}
</div>
</div>
))}
<Button className="xl:w-[80px] md:w-full w-full px-5 py-2 bg-gradient-to-r from-[#402412a8] to-[#9a070790]" onClick={handleSaveDataKernelGrafik} disabled={isLoadingGrafik}> {isLoadingGrafik ? "Diproses..." : "Simpan"}</Button>
</div> </div>
</div> </div>