SHELLAPANDIANGANHUNGING commited on
Commit
50317c7
Β·
verified Β·
1 Parent(s): 160e66f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +107 -103
app.py CHANGED
@@ -1,9 +1,10 @@
1
  import gradio as gr
2
  import pandas as pd
 
3
 
4
- # ================= DEFAULT & DATA =================
5
  last_pressure = 85.0
6
- last_time = "10:38"
7
 
8
  try:
9
  df = pd.read_excel("df_final.xlsx", sheet_name="Sheet1")
@@ -15,34 +16,23 @@ try:
15
 
16
  if not df.empty:
17
  last_row = df.sort_values('Time').iloc[-1]
18
- last_pressure = float(last_row.get('Pressure', 85.0)) if pd.notna(last_row.get('Pressure')) else 85.0
19
  last_time = last_row['Time'].strftime("%H:%M")
20
- except:
21
- pass # fallback ke default
22
 
23
- # BATAS OPERASIONAL β€” tetap (bisa disesuaikan jika ada file konfig)
24
- RED_LOW = 70.0
25
- AMBER_LOW = 75.0
26
- AMBER_HIGH = 95.0
27
- RED_HIGH = 100.0
28
 
29
- # ================= LOGIKA DINAMIS: MARGIN BERDASARKAN JARAK KE AMBER =================
30
- def compute_fill_range(last_p):
31
- # Jarak ke batas amber
32
- max_decrease = last_p - AMBER_LOW # berapa boleh dikurangi tanpa kena amber_low
33
- max_increase = AMBER_HIGH - last_p # berapa boleh ditambah tanpa kena amber_high
34
 
35
- # Batas aman dengan buffer 0.5 psi
36
- lower_bound = last_p - max_decrease + 0.5 # minimal: 0.5 di atas amber_low
37
- upper_bound = last_p + max_increase - 0.5 # maksimal: 0.5 di bawah amber_high
38
-
39
- # Pastikan tidak melewati red (safety double-check)
40
- lower_bound = max(lower_bound, RED_LOW + 0.5)
41
- upper_bound = min(upper_bound, RED_HIGH - 0.5)
42
-
43
- return round(lower_bound, 1), round(upper_bound, 1)
44
-
45
- # ================= CUSTOM CSS β€” BERSIH, RAPI, PROFESIONAL, FULL SCREEN =================
46
  custom_css = """
47
  body, .gradio-container {
48
  background: #000000 !important;
@@ -62,80 +52,96 @@ body, .gradio-container {
62
  #title-box {
63
  background: #003A8F;
64
  color: white;
65
- padding: 16px 24px;
66
- border-radius: 10px;
67
- margin: 20px 0;
68
  text-align: center;
69
  width: 100%;
70
- max-width: 760px;
71
- box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3);
72
  }
73
  #title-box h1 {
74
  margin: 0;
75
- font-size: 26px;
76
- font-weight: 600;
77
  }
78
  .form-section {
79
- width: 100%;
80
- max-width: 760px;
81
  display: flex;
82
  flex-direction: column;
 
 
 
83
  gap: 24px;
84
  }
85
- .row-block {
86
- width: 100%;
87
  display: flex;
88
- gap: 20px;
 
 
89
  }
90
- .input-col {
91
  flex: 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  }
93
  .gr-button {
94
  background: #003A8F !important;
95
  color: white !important;
96
- font-weight: 600;
97
- font-size: 17px !important;
98
- padding: 10px 28px !important;
99
  border-radius: 8px !important;
100
  border: none !important;
101
  width: auto !important;
102
- margin-top: 8px;
103
  }
104
  .gr-button:hover {
105
  background: #002D6B !important;
106
- box-shadow: 0 3px 8px rgba(0, 58, 143, 0.4);
 
107
  }
108
  label {
109
  color: #CCCCCC !important;
110
- font-size: 17px !important;
111
  font-weight: 500;
112
  }
113
- .gradio-html, .output-area {
114
- width: 100%;
115
- max-width: 760px;
116
- background: #121212;
117
- border: 1px solid #333;
118
- border-radius: 10px;
119
- padding: 22px;
120
- font-size: 17px;
121
- line-height: 1.5;
122
- }
123
- .output-area h3 {
124
- color: #FFD100;
125
- margin: 18px 0 12px 0;
126
- font-size: 20px;
127
- font-weight: 600;
128
- }
129
- .output-area p {
130
- margin: 8px 0;
131
- font-size: 17px;
132
  }
133
- .output-area .safe { color: #00FF00; font-weight: bold; }
134
- .output-area .caution { color: #FFA500; font-weight: bold; }
135
- .output-area .danger { color: #FF0000; font-weight: bold; }
136
  """
137
 
138
- # ================= INTERFACE β€” RAPI, KIRI, SATU HALAMAN =================
139
  with gr.Blocks(title="Michelin Mining Tyre Analytics β€” Objective 6", css=custom_css) as demo:
140
  gr.HTML("""
141
  <div id="title-box">
@@ -144,71 +150,69 @@ with gr.Blocks(title="Michelin Mining Tyre Analytics β€” Objective 6", css=custo
144
  """)
145
 
146
  with gr.Column(elem_classes="form-section"):
147
- # Baris 1: Suhu & Jenis Ban (dalam satu baris)
148
- with gr.Row(elem_classes="row-block"):
149
  temperature = gr.Slider(
150
  label="Suhu Saat Ini (Β°C)",
151
  minimum=40,
152
  maximum=70,
153
  value=54,
154
  step=0.5,
155
- interactive=True,
156
- elem_classes="input-col"
157
  )
158
  tyre_type = gr.Radio(
159
  choices=["10 (Depan)", "11 (Belakang)"],
160
  label="Jenis Ban",
161
  value="10 (Depan)",
162
- interactive=True,
163
- elem_classes="input-col"
164
  )
165
 
166
- # Baris 2: Info tekanan terakhir (tengah, kecil)
167
- gr.Markdown(f"<div style='font-size:16px;color:#AAAAAA;'>Tekanan terakhir: {last_pressure} psi | Jam: {last_time}</div>")
168
 
169
- # Tombol Submit (kiri, compact)
170
  btn_submit = gr.Button("Submit", elem_classes="gr-button")
171
-
172
- # Output
173
  output = gr.HTML(elem_classes="output-area")
174
 
175
- # ================= LOGIKA SIMULASI β€” DINAMIS SESUAI BATAS AMBER =================
176
  def simulate(tyre_str, temp):
177
- # Hitung tekanan ideal (sederhana, linear)
178
- ideal_pressure = 85.0 + 0.42 * (temp - 54.0)
179
- ideal_pressure = round(ideal_pressure, 1)
 
 
 
 
 
 
 
180
 
181
- # Status vs zona
182
- if ideal_pressure < RED_LOW:
183
  status = '<span class="danger">Risiko Red β€” Tekanan terlalu rendah</span>'
184
- elif ideal_pressure < AMBER_LOW:
185
  status = '<span class="caution">Risiko Amber β€” Tekanan mendekati batas bawah</span>'
186
- elif ideal_pressure > RED_HIGH:
187
  status = '<span class="danger">Risiko Red β€” Tekanan terlalu tinggi</span>'
188
- elif ideal_pressure > AMBER_HIGH:
189
  status = '<span class="caution">Risiko Amber β€” Tekanan mendekati batas atas</span>'
190
  else:
191
  status = '<span class="safe">Dalam zona aman</span>'
192
 
193
- # Hitung rekomendasi isi ulang DINAMIS
194
- lower_fill, upper_fill = compute_fill_range(last_pressure)
195
-
196
- rec = f"""
197
  <h3>Hasil Simulasi</h3>
198
- <p>Ideal Tekanan pada {temp}Β°C: {ideal_pressure} psi</p>
199
  <p>Status: {status}</p>
200
-
201
  <h3>Rekomendasi Isi Ulang</h3>
202
- <p>Berdasarkan tekanan terakhir ({last_pressure} psi pukul {last_time}):</p>
203
- <p class="safe">Isi tekanan antara {lower_fill} – {upper_fill} psi</p>
204
- <p class="caution">Jangan isi kurang dari {AMBER_LOW} psi (batas Amber bawah)</p>
205
- <p class="caution">Jangan isi lebih dari {AMBER_HIGH} psi (batas Amber atas)</p>
206
- <p class="danger">Hindari tekanan di bawah {RED_LOW} psi atau di atas {RED_HIGH} psi (zona Red)</p>
207
- <p style="margin-top:14px; font-size:15px; color:#999;">
208
- Catatan: Rekomendasi mempertahankan jarak aman minimal 0.5 psi dari zona Amber.
209
- </p>
210
  """
211
- return rec
212
 
213
  btn_submit.click(simulate, inputs=[tyre_type, temperature], outputs=output)
214
 
 
1
  import gradio as gr
2
  import pandas as pd
3
+ import numpy as np
4
 
5
+ # ================= LOAD DATA β€” AMBIL TEKANAN & WAKTU TERAKHIR =================
6
  last_pressure = 85.0
7
+ last_time = "–"
8
 
9
  try:
10
  df = pd.read_excel("df_final.xlsx", sheet_name="Sheet1")
 
16
 
17
  if not df.empty:
18
  last_row = df.sort_values('Time').iloc[-1]
19
+ last_pressure = float(last_row['Pressure']) if pd.notna(last_row.get('Pressure')) else 85.0
20
  last_time = last_row['Time'].strftime("%H:%M")
21
+ except Exception as e:
22
+ pass
23
 
24
+ # ================= BATAS AMAN (SESUAI STANDAR OPERASIONAL) =================
25
+ red_low = 70.0
26
+ amber_low = 75.0
27
+ amber_high = 95.0
28
+ red_high = 100.0
29
 
30
+ def get_safe_fill_range(last_p):
31
+ lower = max(last_p - 10, amber_low + 0.5)
32
+ upper = min(last_p + 10, amber_high - 0.5)
33
+ return round(lower, 1), round(upper, 1)
 
34
 
35
+ # ================= CUSTOM CSS β€” (TETAP SAMA SEPERTI ANDA INGINKAN) =================
 
 
 
 
 
 
 
 
 
 
36
  custom_css = """
37
  body, .gradio-container {
38
  background: #000000 !important;
 
52
  #title-box {
53
  background: #003A8F;
54
  color: white;
55
+ padding: 16px 32px;
56
+ border-radius: 12px;
57
+ margin-bottom: 32px;
58
  text-align: center;
59
  width: 100%;
60
+ max-width: 800px;
61
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
62
  }
63
  #title-box h1 {
64
  margin: 0;
65
+ font-size: 28px;
66
+ font-weight: 700;
67
  }
68
  .form-section {
 
 
69
  display: flex;
70
  flex-direction: column;
71
+ align-items: flex-start;
72
+ width: 100%;
73
+ max-width: 800px;
74
  gap: 24px;
75
  }
76
+ .control-row {
 
77
  display: flex;
78
+ gap: 24px;
79
+ width: 100%;
80
+ align-items: center;
81
  }
82
+ .control-row > div {
83
  flex: 1;
84
+ min-width: 200px;
85
+ }
86
+ .gradio-html, .output-area {
87
+ width: 100%;
88
+ max-width: 800px;
89
+ background: #121212;
90
+ border: 1px solid #333;
91
+ border-radius: 12px;
92
+ padding: 24px;
93
+ margin-top: 16px;
94
+ font-size: 18px;
95
+ line-height: 1.6;
96
+ }
97
+ .output-area h3 {
98
+ color: #FFD100;
99
+ margin: 16px 0 12px 0;
100
+ font-size: 22px;
101
+ font-weight: 600;
102
+ }
103
+ .output-area p {
104
+ margin: 10px 0;
105
+ }
106
+ .output-area .safe {
107
+ color: #00FF00;
108
+ font-weight: bold;
109
+ }
110
+ .output-area .caution {
111
+ color: #FFA500;
112
+ font-weight: bold;
113
+ }
114
+ .output-area .danger {
115
+ color: #FF0000;
116
+ font-weight: bold;
117
  }
118
  .gr-button {
119
  background: #003A8F !important;
120
  color: white !important;
121
+ font-weight: bold;
122
+ font-size: 18px !important;
123
+ padding: 12px 32px !important;
124
  border-radius: 8px !important;
125
  border: none !important;
126
  width: auto !important;
127
+ margin-top: 12px;
128
  }
129
  .gr-button:hover {
130
  background: #002D6B !important;
131
+ transform: scale(1.03);
132
+ box-shadow: 0 4px 12px rgba(0, 58, 143, 0.4);
133
  }
134
  label {
135
  color: #CCCCCC !important;
136
+ font-size: 18px !important;
137
  font-weight: 500;
138
  }
139
+ input, select {
140
+ font-size: 18px !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  }
 
 
 
142
  """
143
 
144
+ # ================= GRADIO LAYOUT β€” (TETAP SAMA) =================
145
  with gr.Blocks(title="Michelin Mining Tyre Analytics β€” Objective 6", css=custom_css) as demo:
146
  gr.HTML("""
147
  <div id="title-box">
 
150
  """)
151
 
152
  with gr.Column(elem_classes="form-section"):
153
+ with gr.Row(elem_classes="control-row"):
 
154
  temperature = gr.Slider(
155
  label="Suhu Saat Ini (Β°C)",
156
  minimum=40,
157
  maximum=70,
158
  value=54,
159
  step=0.5,
160
+ interactive=True
 
161
  )
162
  tyre_type = gr.Radio(
163
  choices=["10 (Depan)", "11 (Belakang)"],
164
  label="Jenis Ban",
165
  value="10 (Depan)",
166
+ interactive=True
 
167
  )
168
 
169
+ last_info = gr.Markdown(f"Tekanan Terakhir: {last_pressure} psi | Jam: {last_time}")
 
170
 
 
171
  btn_submit = gr.Button("Submit", elem_classes="gr-button")
 
 
172
  output = gr.HTML(elem_classes="output-area")
173
 
174
+ # ================= LOGIKA SIMULASI β€” DIPERBAIKI REKOMENDASINYA =================
175
  def simulate(tyre_str, temp):
176
+ # Interpolasi tekanan ideal
177
+ ideal = 85.0 + 0.42 * (temp - 54.0)
178
+ ideal = round(ideal, 1)
179
+
180
+ # Ambil batas aman
181
+ lower_safe, upper_safe = get_safe_fill_range(last_pressure)
182
+
183
+ # Hitung selisih operasional (untuk penjelasan)
184
+ max_add = round(amber_high - last_pressure, 1) # maks boleh tambah tanpa kena amber
185
+ max_sub = round(last_pressure - amber_low, 1) # maks boleh kurangi tanpa kena amber
186
 
187
+ # Status
188
+ if ideal < red_low:
189
  status = '<span class="danger">Risiko Red β€” Tekanan terlalu rendah</span>'
190
+ elif ideal < amber_low:
191
  status = '<span class="caution">Risiko Amber β€” Tekanan mendekati batas bawah</span>'
192
+ elif ideal > red_high:
193
  status = '<span class="danger">Risiko Red β€” Tekanan terlalu tinggi</span>'
194
+ elif ideal > amber_high:
195
  status = '<span class="caution">Risiko Amber β€” Tekanan mendekati batas atas</span>'
196
  else:
197
  status = '<span class="safe">Dalam zona aman</span>'
198
 
199
+ # βœ… REKOMENDASI YANG ANDA INGINKAN β€” EKSPLISIT & OPERASIONAL
200
+ rec_html = f"""
 
 
201
  <h3>Hasil Simulasi</h3>
202
+ <p>Ideal Tekanan pada {temp}Β°C: {ideal} psi</p>
203
  <p>Status: {status}</p>
204
+ <hr>
205
  <h3>Rekomendasi Isi Ulang</h3>
206
+ <p>Berdasarkan tekanan terakhir <strong>{last_pressure} psi</strong> (pukul {last_time}):</p>
207
+ <p class="safe">Isi tekanan antara <strong>{lower_safe} – {upper_safe} psi</strong></p>
208
+ <p>Maksimal penambahan: <strong>+{min(10.0, max_add):.1f} psi</strong> (agar tidak melebihi {amber_high} psi)</p>
209
+ <p>Maksimal pengurangan: <strong>βˆ’{min(10.0, max_sub):.1f} psi</strong> (agar tidak turun di bawah {amber_low} psi)</p>
210
+ <p class="caution">Jangan isi kurang dari {amber_low} psi (batas Amber bawah)</p>
211
+ <p class="caution">Jangan isi lebih dari {amber_high} psi (batas Amber atas)</p>
212
+ <p class="danger">Hindari tekanan di bawah {red_low} psi atau di atas {red_high} psi (zona Red)</p>
213
+ <p style="margin-top:16px;"><em>Catatan: Rekomendasi menjaga margin aman minimal 0.5 psi dari zona Amber.</em></p>
214
  """
215
+ return rec_html
216
 
217
  btn_submit.click(simulate, inputs=[tyre_type, temperature], outputs=output)
218