tututz commited on
Commit
f797e4e
·
verified ·
1 Parent(s): 999de42

Create recommendation_builder.py

Browse files
Files changed (1) hide show
  1. recommendation_builder.py +181 -0
recommendation_builder.py ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ======================================================================
2
+ # --- recommendation_builder.py ---
3
+ # ======================================================================
4
+ import random
5
+ from typing import List, Dict
6
+
7
+ # --- SENTIMENT CONFIG ---
8
+ SENTIMENT_MAP = {
9
+ "IPS_Terakhir": {"rendah": -1, "tinggi": 1},
10
+ "IPK_Terakhir": {"rendah": -1, "tinggi": 1},
11
+ "Jumlah_MK_Gagal": {"rendah": 1, "tinggi": -1},
12
+ "Total_SKS": {"rendah": -1, "tinggi": 1},
13
+ "Tren_IPS_Slope": {"rendah": -1, "tinggi": 1},
14
+ "Rentang_IPS": {"rendah": 1, "tinggi": -1},
15
+ "Total_SKS_Gagal": {"rendah": 1, "tinggi": -1},
16
+ }
17
+
18
+ # --- KLAUSA TEKS (UNTUK DIJAHIT) ---
19
+ CLAUSES = {
20
+ "IPS_Terakhir": {
21
+ "rendah": "capaian IPS semester terakhir yang berada di bawah standar",
22
+ "tinggi": "capaian IPS semester terakhir yang sangat memuaskan",
23
+ },
24
+ "IPK_Terakhir": {
25
+ "rendah": "nilai IPK kumulatif yang masih relatif rendah",
26
+ "tinggi": "rekam IPK kumulatif yang solid dan stabil",
27
+ },
28
+ "Jumlah_MK_Gagal": {
29
+ "rendah": "rekam jejak mata kuliah yang bersih dari kegagalan",
30
+ "tinggi": "adanya beban mata kuliah gagal yang menumpuk",
31
+ },
32
+ "Total_SKS_Gagal": {
33
+ "rendah": "minimnya SKS yang terbuang",
34
+ "tinggi": "besarnya jumlah SKS yang harus diulang",
35
+ },
36
+ "Tren_IPS_Slope": {
37
+ "rendah": "tren performa yang menurun belakangan ini",
38
+ "tinggi": "tren peningkatan nilai yang konsisten",
39
+ },
40
+ "Total_SKS": {
41
+ "rendah": "jumlah SKS yang masih di bawah target progres studi",
42
+ "tinggi": "kemajuan pengambilan SKS yang sejalan dengan rencana studi",
43
+ },
44
+ }
45
+
46
+ # --- KATA SAMBUNG ---
47
+ CONNECTORS = {
48
+ "same_bad": [". Masalah ini diperberat dengan ", ". Selain itu, terdeteksi juga ", ". Sayangnya, hal ini diikuti oleh "],
49
+ "same_good": [". Hal ini didukung pula oleh ", ". Ditambah lagi dengan ", ". Serta adanya "],
50
+ "contrast_bad_to_good": [". Namun kabar baiknya, ", ". Walaupun begitu, Anda memiliki ", ". Untungnya, hal ini diimbangi oleh "],
51
+ "contrast_good_to_bad": [". Namun sayangnya, ", ". Meskipun demikian, perlu diwaspadai adanya ", ". Akan tetapi, sistem mencatat "],
52
+ }
53
+
54
+ # --- TEMPLATE STATIS (FORMATTING DIHAPUS) ---
55
+ REKOMENDASI_BANK = {
56
+ "Resiko Tinggi": [
57
+ (
58
+ "🚨 Tindakan Mendesak Diperlukan. Berdasarkan analisis sistem, Anda berada di kategori Resiko Tinggi. "
59
+ "Segera lakukan evaluasi mendalam terhadap kebiasaan belajar, disiplin waktu, dan strategi akademik Anda. "
60
+ "Prioritaskan perbaikan pada mata kuliah dengan nilai rendah, manfaatkan bimbingan dosen, "
61
+ "dan pertimbangkan untuk mengurangi beban SKS sementara agar fokus pada peningkatan performa inti."
62
+ ),
63
+ (
64
+ "⚠️ Perhatian Serius. Performa akademik Anda menunjukkan tanda risiko tinggi. "
65
+ "Usahakan untuk memperbaiki IPK dan IPS dengan memperkuat dasar konsep, "
66
+ "bergabung dalam kelompok belajar, serta mencari mentor akademik. "
67
+ "Manajemen waktu dan pola belajar teratur akan sangat membantu dalam mengembalikan performa Anda."
68
+ )
69
+ ],
70
+ "Resiko Sedang": [
71
+ (
72
+ "⚠️ Waspada & Antisipasi. Anda berada di zona Resiko Sedang. "
73
+ "Hal ini menandakan performa Anda masih fluktuatif. "
74
+ "Pertahankan aspek yang sudah baik, namun segera identifikasi area yang masih lemah. "
75
+ "Disarankan untuk membuat jadwal belajar lebih terstruktur dan melakukan evaluasi kecil tiap minggu."
76
+ ),
77
+ (
78
+ "💡 Perlu Peningkatan. Kinerja akademik Anda stabil namun belum optimal. "
79
+ "Fokuslah pada konsistensi nilai dan hindari penurunan mendadak di semester berikutnya. "
80
+ "Coba tingkatkan interaksi dengan dosen dan teman sekelas untuk memperkuat pemahaman materi."
81
+ )
82
+ ],
83
+ "Resiko Rendah": [
84
+ (
85
+ "✅ Pertahankan Momentum. Anda berada di kategori Resiko Rendah. "
86
+ "Performa Anda sudah cukup baik dan konsisten. "
87
+ "Teruskan pola belajar yang efektif, namun jangan lengah terhadap materi yang sulit. "
88
+ "Pertimbangkan untuk mengambil tantangan baru seperti proyek penelitian atau lomba akademik."
89
+ ),
90
+ (
91
+ "📈 Progres Positif. Anda menunjukkan performa yang solid. "
92
+ "Gunakan kesempatan ini untuk memperkuat area yang masih lemah dan menjaga keseimbangan antara studi dan istirahat. "
93
+ "Tetap evaluasi hasil belajar secara berkala untuk memastikan kestabilan performa."
94
+ )
95
+ ],
96
+ "Aman": [
97
+ (
98
+ "🌟 Luar Biasa! Anda berada di kategori Aman. "
99
+ "Kinerja akademik Anda konsisten dan menunjukkan kedewasaan belajar yang tinggi. "
100
+ "Pertahankan strategi belajar yang sudah terbukti efektif, "
101
+ "dan jangan ragu berbagi pengalaman dengan rekan yang membutuhkan bantuan."
102
+ ),
103
+ (
104
+ "🏆 Prestasi Stabil. Sistem mendeteksi profil akademik Anda sangat kuat. "
105
+ "Anda dapat mulai mengeksplorasi kegiatan tambahan seperti magang, penelitian, atau lomba akademik "
106
+ "untuk memperluas wawasan dan pengalaman profesional."
107
+ )
108
+ ],
109
+ "default": (
110
+ "🔍 Evaluasi Umum. Hasil prediksi Anda menunjukkan area yang perlu diperhatikan. "
111
+ "Tetap jaga semangat belajar dan lakukan refleksi berkala terhadap hasil akademik Anda."
112
+ )
113
+ }
114
+
115
+
116
+ def generate_recommendation_paragraph(prediction_val: str, structured_rules: List[Dict]) -> str:
117
+ """
118
+ Menghasilkan rekomendasi personal: Template Statis + Jahitan Dinamis
119
+ """
120
+
121
+ # 1️⃣ Pilih template dasar (statis) dari REKOMENDASI_BANK
122
+ base_templates = REKOMENDASI_BANK.get(prediction_val)
123
+ if not base_templates:
124
+ base_templates = [REKOMENDASI_BANK["default"]]
125
+
126
+ if isinstance(base_templates, list):
127
+ base_text = random.choice(base_templates)
128
+ else:
129
+ base_text = base_templates # Handle 'default' yang bukan list
130
+
131
+ # 2️⃣ Buat bagian dinamis (berdasarkan fitur dominan)
132
+ active_clauses = []
133
+ features_seen = set()
134
+
135
+ for rule in reversed(structured_rules):
136
+ feature = rule["feature"]
137
+ if feature in features_seen: continue
138
+ features_seen.add(feature)
139
+
140
+ condition = rule["condition"]
141
+ text = CLAUSES.get(feature, {}).get(condition)
142
+ sentiment = SENTIMENT_MAP.get(feature, {}).get(condition, 0)
143
+
144
+ if text:
145
+ active_clauses.append({"text": text, "sentiment": sentiment})
146
+
147
+ if not active_clauses:
148
+ # Jika tidak ada fitur penting, kembalikan template statis saja
149
+ return base_text
150
+
151
+ # 3️⃣ Stitching: gabungkan klausa
152
+ dynamic_part = " Secara lebih rinci, profil Anda dipengaruhi oleh "
153
+ current = active_clauses[0]
154
+ dynamic_part += current["text"]
155
+ last_sentiment = current["sentiment"]
156
+
157
+ for i in range(1, len(active_clauses)):
158
+ item = active_clauses[i]
159
+ current_sentiment = item["sentiment"]
160
+
161
+ if last_sentiment == -1 and current_sentiment == -1:
162
+ connector = random.choice(CONNECTORS["same_bad"])
163
+ elif last_sentiment == 1 and current_sentiment == 1:
164
+ connector = random.choice(CONNECTORS["same_good"])
165
+ elif last_sentiment == -1 and current_sentiment == 1:
166
+ connector = random.choice(CONNECTORS["contrast_bad_to_good"])
167
+ elif last_sentiment == 1 and current_sentiment == -1:
168
+ connector = random.choice(CONNECTORS["contrast_good_to_bad"])
169
+ else:
170
+ connector = ". Selanjutnya, perhatikan juga "
171
+
172
+ dynamic_part += connector + item["text"]
173
+ last_sentiment = current_sentiment
174
+
175
+ dynamic_part += "."
176
+
177
+ # 4️⃣ Gabungkan template + hasil stitching
178
+ # Format: [Paragraf Statis] + [Paragraf Dinamis]
179
+ # \n\n digunakan untuk membuat paragraf baru
180
+ final_text = f"{base_text}\n\n{dynamic_part}"
181
+ return final_text