Spaces:
Sleeping
Sleeping
| import logging | |
| import gradio as gr | |
| from backend import get_backend | |
| from ui_components import ( | |
| build_data_info, | |
| build_multi_year_summary, | |
| build_prediction_summary, | |
| get_forecast_placeholder, | |
| get_prediction_placeholder, | |
| ) | |
| from utils import setup_logging | |
| setup_logging("INFO") | |
| logger = logging.getLogger("GradioApp") | |
| # Backend Interface | |
| def get_data_info() -> str: | |
| backend = get_backend() | |
| data = backend.get_data_info() | |
| return build_data_info(data) | |
| def generate_predictions(year: int, semester: int): | |
| backend = get_backend() | |
| result = backend.generate_predictions(year, semester) | |
| if result.error: | |
| return f"Error: {result.error}", None, None | |
| summary_html = build_prediction_summary(result.summary_data) | |
| return summary_html, result.predictions_df, result.comparison_df | |
| def generate_multi_year_forecast(year: int, semester: int, years_ahead: int = 3): | |
| backend = get_backend() | |
| result = backend.generate_multi_year_forecast(year, semester, years_ahead) | |
| if result.error: | |
| return f"Error: {result.error}", None | |
| summary_html = build_multi_year_summary(result.summary_data) | |
| return summary_html, result.forecast_df | |
| def update_ui_with_predictions(year: int, semester: int): | |
| summary, all_predictions, comparison = generate_predictions(year, semester) | |
| logger.info( | |
| f"UI Update: comparison is None: {comparison is None}, " | |
| f"empty: {comparison.empty if comparison is not None else 'N/A'}" | |
| ) | |
| if comparison is not None and not comparison.empty: | |
| logger.info(f"Showing comparison table with {len(comparison)} rows") | |
| return ( | |
| summary, | |
| all_predictions, | |
| gr.update(open=True), | |
| gr.update( | |
| value=f"Validasi terhadap {len(comparison)} mata kuliah - " | |
| "termasuk perbandingan jumlah kelas aktual vs prediksi" | |
| ), | |
| gr.update(value=comparison), | |
| ) | |
| else: | |
| logger.info("Hiding comparison table - no data available") | |
| return ( | |
| summary, | |
| all_predictions, | |
| gr.update(open=False), | |
| gr.update(value="Tidak ada data validasi untuk prediksi masa depan"), | |
| gr.update(value=None), | |
| ) | |
| # Gradio UI | |
| def create_gradio_app() -> gr.Blocks: | |
| """Create and configure the Gradio application.""" | |
| with gr.Blocks(title="SKS Enrollment Predictor") as demo: | |
| # Header | |
| gr.Markdown("# Course Enrollment & Class Capacity Predictor") | |
| gr.Markdown( | |
| "Sistem prediksi **jumlah kelas yang perlu dibuka** berdasarkan " | |
| "forecasting enrollment dengan mempertimbangkan kapasitas maksimum per kelas." | |
| ) | |
| with gr.Tabs(): | |
| # Single Year | |
| with gr.TabItem("Prediksi Semester"): | |
| with gr.Row(): | |
| with gr.Column(scale=1, min_width=300): | |
| year_input = gr.Number( | |
| label="Tahun", | |
| value=2025, | |
| precision=0, | |
| minimum=2020, | |
| maximum=2030, | |
| ) | |
| semester_input = gr.Radio( | |
| choices=[("1 (Ganjil)", 1), ("2 (Genap)", 2)], | |
| label="Semester", | |
| value=2, | |
| ) | |
| predict_btn = gr.Button( | |
| "Generate Predictions", | |
| variant="primary", | |
| size="lg", | |
| ) | |
| gr.Markdown("---") | |
| with gr.Accordion("Dataset Info", open=False): | |
| data_info_output = gr.HTML() | |
| demo.load( | |
| fn=get_data_info, inputs=[], outputs=data_info_output | |
| ) | |
| with gr.Column(scale=3): | |
| summary_output = gr.HTML(value=get_prediction_placeholder()) | |
| gr.Markdown("---") | |
| gr.Markdown("### Rekomendasi Jumlah Kelas per Mata Kuliah") | |
| gr.Markdown( | |
| "*Jumlah kelas dihitung berdasarkan prediksi enrollment ÷ " | |
| "kapasitas per kelas*" | |
| ) | |
| all_predictions_output = gr.Dataframe( | |
| label="", | |
| wrap=True, | |
| interactive=False, | |
| ) | |
| with gr.Accordion( | |
| "Detail Validasi", open=False | |
| ) as comparison_accordion: | |
| comparison_info = gr.Markdown( | |
| value="Data validasi muncul ketika data aktual tersedia" | |
| ) | |
| comparison_output = gr.Dataframe( | |
| label="", | |
| wrap=True, | |
| interactive=False, | |
| ) | |
| # Multi-Year Forecast | |
| with gr.TabItem("Proyeksi Multi-Tahun"): | |
| gr.Markdown("### Forecasting Kebutuhan Kelas Beberapa Tahun ke Depan") | |
| gr.Markdown( | |
| "Memprediksi tren jumlah mahasiswa dan kebutuhan kelas " | |
| "untuk perencanaan jangka panjang." | |
| ) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| forecast_year = gr.Number( | |
| label="Tahun Mulai", | |
| value=2025, | |
| precision=0, | |
| minimum=2020, | |
| maximum=2030, | |
| ) | |
| forecast_semester = gr.Radio( | |
| choices=[("1 (Ganjil)", 1), ("2 (Genap)", 2)], | |
| label="Semester", | |
| value=2, | |
| ) | |
| forecast_years = gr.Slider( | |
| label="Tahun ke Depan", | |
| minimum=1, | |
| maximum=5, | |
| value=3, | |
| step=1, | |
| ) | |
| forecast_btn = gr.Button( | |
| "Generate Forecast", | |
| variant="primary", | |
| size="lg", | |
| ) | |
| with gr.Column(scale=3): | |
| forecast_summary = gr.HTML(value=get_forecast_placeholder()) | |
| gr.Markdown("---") | |
| gr.Markdown("### Detail Proyeksi per Mata Kuliah per Tahun") | |
| forecast_table = gr.Dataframe( | |
| label="", | |
| wrap=True, | |
| interactive=False, | |
| ) | |
| predict_btn.click( | |
| fn=update_ui_with_predictions, | |
| inputs=[year_input, semester_input], | |
| outputs=[ | |
| summary_output, | |
| all_predictions_output, | |
| comparison_accordion, | |
| comparison_info, | |
| comparison_output, | |
| ], | |
| ) | |
| forecast_btn.click( | |
| fn=generate_multi_year_forecast, | |
| inputs=[forecast_year, forecast_semester, forecast_years], | |
| outputs=[forecast_summary, forecast_table], | |
| ) | |
| return demo | |
| logger.info("Starting Gradio app...") | |
| backend = get_backend() | |
| init_success = backend.initialize() | |
| if not init_success: | |
| logger.error("Failed to initialize system. App may not work correctly.") | |
| demo = create_gradio_app() | |
| # Launch the app | |
| if __name__ == "__main__": | |
| demo.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| share=False, | |
| show_error=True, | |
| ) | |