Fourstore commited on
Commit
ecb61f4
·
verified ·
1 Parent(s): 0cf1728

Update endpoints/antibot.js

Browse files
Files changed (1) hide show
  1. endpoints/antibot.js +113 -21
endpoints/antibot.js CHANGED
@@ -6,6 +6,10 @@ function mapAnswer(soalArray, jawaban, botIndex) {
6
  return jawaban;
7
  }
8
 
 
 
 
 
9
  function isValueMatch(value, targetSoal) {
10
  const numberMap = {
11
  '0': 'zero', '1': 'one', '2': 'two', '3': 'three', '4': 'four',
@@ -16,21 +20,69 @@ function isValueMatch(value, targetSoal) {
16
  'VI': '6', 'VII': '7', 'VIII': '8', 'IX': '9', 'X': '10'
17
  };
18
 
19
- const normalizedValue = value.toLowerCase().trim();
20
- const normalizedSoal = targetSoal.toLowerCase().trim();
 
21
 
 
22
  if (normalizedValue === normalizedSoal) return true;
23
 
24
- const mappedValue = numberMap[normalizedValue] || numberMap[normalizedValue.toUpperCase()];
25
- const mappedSoal = numberMap[normalizedSoal] || numberMap[normalizedSoal.toUpperCase()];
 
26
 
27
  if (mappedValue === normalizedSoal) return true;
28
  if (normalizedValue === mappedSoal) return true;
29
- if (mappedValue === mappedSoal && mappedValue) return true;
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
  return false;
32
  }
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  async function antibot(data) {
35
  try {
36
  const { main, bots } = data;
@@ -38,14 +90,16 @@ async function antibot(data) {
38
  const mainBuffer = Buffer.from(main, 'base64');
39
  const mainText = await extractTextFromImage(mainBuffer);
40
 
41
- const soalText = mainText.response;
42
- const soalArray = soalText.replace(/[,;]/g, ' ').split(' ').filter(n => n.trim());
43
 
44
- const soalRaw = soalArray;
45
- const soalLeet = soalArray;
 
46
 
47
  const botResults = [];
48
 
 
49
  for (let i = 0; i < bots.length; i++) {
50
  const bot = bots[i];
51
  try {
@@ -57,7 +111,8 @@ async function antibot(data) {
57
  botResults.push({
58
  id: bot.id,
59
  text: botText.response,
60
- value: mappedValue
 
61
  });
62
 
63
  } catch (error) {
@@ -66,17 +121,18 @@ async function antibot(data) {
66
  id: bot.id,
67
  text: '',
68
  value: '',
 
69
  error: error.message
70
  });
71
  }
72
  }
73
 
74
- // LOGIC BARU: Hitung yang cocok dulu
75
  const result = [];
76
  const usedIds = new Set();
77
  let matchedCount = 0;
78
 
79
- // STEP 1: CARI YANG COCOK
80
  for (let i = 0; i < soalArray.length; i++) {
81
  const targetSoal = soalArray[i];
82
  let foundId = null;
@@ -91,17 +147,45 @@ async function antibot(data) {
91
  }
92
  }
93
 
94
- result.push({ id: foundId });
 
 
 
 
95
  }
96
 
97
- // STEP 2: ISI BERDASARKAN LOGIC BARU
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  if (matchedCount >= 2) {
99
- // Kalo ada 2 atau 3 yang cocok, isi yang kosong dengan sisa bot
100
  for (let i = 0; i < result.length; i++) {
101
  if (!result[i].id) {
102
  for (const bot of botResults) {
103
  if (!usedIds.has(bot.id) && bot.value && bot.value.trim() !== '') {
104
  result[i].id = bot.id;
 
105
  usedIds.add(bot.id);
106
  break;
107
  }
@@ -109,33 +193,41 @@ async function antibot(data) {
109
  }
110
  }
111
  } else if (matchedCount === 1) {
112
- // Kalo cuma 1 yang cocok, yang kosong kasih "invalid"
113
  for (let i = 0; i < result.length; i++) {
114
  if (!result[i].id) {
115
  result[i].id = 'invalid';
 
116
  }
117
  }
118
  } else {
119
- // Kalo ga ada yang cocok, semua kasih "invalid"
120
  for (let i = 0; i < result.length; i++) {
121
  result[i].id = 'invalid';
 
122
  }
123
  }
124
 
125
- // Pastikan semua slot terisi
126
  for (let i = 0; i < result.length; i++) {
127
  if (!result[i].id) {
128
  result[i].id = 'invalid';
 
129
  }
130
  }
131
 
132
  return {
133
  success: true,
134
  data: {
135
- soal: soalRaw,
136
- soalLeet: soalLeet,
137
  botResults: botResults,
138
- result: result
 
 
 
 
 
139
  }
140
  };
141
 
 
6
  return jawaban;
7
  }
8
 
9
+ function normalizeText(text) {
10
+ return text.toLowerCase().replace(/[^\w\s]/g, '').trim();
11
+ }
12
+
13
  function isValueMatch(value, targetSoal) {
14
  const numberMap = {
15
  '0': 'zero', '1': 'one', '2': 'two', '3': 'three', '4': 'four',
 
20
  'VI': '6', 'VII': '7', 'VIII': '8', 'IX': '9', 'X': '10'
21
  };
22
 
23
+ // Normalisasi teks
24
+ const normalizedValue = normalizeText(value);
25
+ const normalizedSoal = normalizeText(targetSoal);
26
 
27
+ // Cek exact match setelah normalisasi
28
  if (normalizedValue === normalizedSoal) return true;
29
 
30
+ // Cek match dengan number mapping
31
+ const mappedValue = numberMap[normalizedValue] || numberMap[value] || normalizedValue;
32
+ const mappedSoal = numberMap[normalizedSoal] || numberMap[targetSoal] || normalizedSoal;
33
 
34
  if (mappedValue === normalizedSoal) return true;
35
  if (normalizedValue === mappedSoal) return true;
36
+ if (mappedValue === mappedSoal) return true;
37
+
38
+ // Cek untuk operasi matematika sederhana
39
+ try {
40
+ const valueResult = evaluateSimpleMath(value);
41
+ const soalResult = evaluateSimpleMath(targetSoal);
42
+
43
+ if (valueResult !== null && soalResult !== null && valueResult === soalResult) {
44
+ return true;
45
+ }
46
+ } catch (e) {
47
+ // Ignore math evaluation errors
48
+ }
49
 
50
  return false;
51
  }
52
 
53
+ function evaluateSimpleMath(expression) {
54
+ if (!expression) return null;
55
+
56
+ const cleanExpr = expression.toString().replace(/[^\d+\-*/.()]/g, '');
57
+ if (!cleanExpr) return null;
58
+
59
+ try {
60
+ // Safety check untuk ekspresi yang terlalu kompleks
61
+ if (cleanExpr.length > 10) return null;
62
+
63
+ // Gunakan Function constructor sebagai alternatif yang lebih aman dari eval
64
+ const result = Function(`"use strict"; return (${cleanExpr})`)();
65
+ return typeof result === 'number' ? result : null;
66
+ } catch (e) {
67
+ return null;
68
+ }
69
+ }
70
+
71
+ function parseSoalText(text) {
72
+ // Split dengan berbagai delimiter: . , : ; dan spasi
73
+ const delimiters = /[.,:;\\/\s]+/;
74
+
75
+ // Split dan filter elemen kosong
76
+ let parts = text.split(delimiters).filter(part => part.trim() !== '');
77
+
78
+ // Jika hasil split hanya 1 elemen, coba split dengan spasi saja
79
+ if (parts.length === 1) {
80
+ parts = text.split(/\s+/).filter(part => part.trim() !== '');
81
+ }
82
+
83
+ return parts;
84
+ }
85
+
86
  async function antibot(data) {
87
  try {
88
  const { main, bots } = data;
 
90
  const mainBuffer = Buffer.from(main, 'base64');
91
  const mainText = await extractTextFromImage(mainBuffer);
92
 
93
+ // Parse soal dengan delimiter yang benar
94
+ const soalArray = parseSoalText(mainText.response);
95
 
96
+ if (soalArray.length === 0) {
97
+ throw new Error('Tidak ada soal yang terdeteksi');
98
+ }
99
 
100
  const botResults = [];
101
 
102
+ // Process semua bot
103
  for (let i = 0; i < bots.length; i++) {
104
  const bot = bots[i];
105
  try {
 
111
  botResults.push({
112
  id: bot.id,
113
  text: botText.response,
114
+ value: mappedValue,
115
+ normalized: normalizeText(botText.response)
116
  });
117
 
118
  } catch (error) {
 
121
  id: bot.id,
122
  text: '',
123
  value: '',
124
+ normalized: '',
125
  error: error.message
126
  });
127
  }
128
  }
129
 
130
+ // LOGIC MATCHING YANG DIPERBAIKI
131
  const result = [];
132
  const usedIds = new Set();
133
  let matchedCount = 0;
134
 
135
+ // STEP 1: CARI YANG COCOK PERSIS
136
  for (let i = 0; i < soalArray.length; i++) {
137
  const targetSoal = soalArray[i];
138
  let foundId = null;
 
147
  }
148
  }
149
 
150
+ result.push({
151
+ id: foundId,
152
+ soal: targetSoal,
153
+ matchType: foundId ? 'exact' : 'none'
154
+ });
155
  }
156
 
157
+ // STEP 2: CARI MATCH DENGAN NORMALIZATION (untuk kasus seperti "T!g3r" vs "tiger")
158
+ if (matchedCount < soalArray.length) {
159
+ for (let i = 0; i < result.length; i++) {
160
+ if (!result[i].id) {
161
+ const targetSoal = soalArray[i];
162
+ const normalizedSoal = normalizeText(targetSoal);
163
+
164
+ for (const bot of botResults) {
165
+ if (!usedIds.has(bot.id) && bot.normalized && bot.normalized.trim() !== '') {
166
+ // Cek match setelah normalisasi
167
+ if (bot.normalized === normalizedSoal) {
168
+ result[i].id = bot.id;
169
+ result[i].matchType = 'normalized';
170
+ usedIds.add(bot.id);
171
+ matchedCount++;
172
+ break;
173
+ }
174
+ }
175
+ }
176
+ }
177
+ }
178
+ }
179
+
180
+ // STEP 3: LOGIC FALLBACK BERDASARKAN MATCH COUNT
181
  if (matchedCount >= 2) {
182
+ // Jika 2 atau lebih match, isi sisanya dengan bot yang tersisa
183
  for (let i = 0; i < result.length; i++) {
184
  if (!result[i].id) {
185
  for (const bot of botResults) {
186
  if (!usedIds.has(bot.id) && bot.value && bot.value.trim() !== '') {
187
  result[i].id = bot.id;
188
+ result[i].matchType = 'fallback';
189
  usedIds.add(bot.id);
190
  break;
191
  }
 
193
  }
194
  }
195
  } else if (matchedCount === 1) {
196
+ // Jika hanya 1 match, yang lain diisi invalid
197
  for (let i = 0; i < result.length; i++) {
198
  if (!result[i].id) {
199
  result[i].id = 'invalid';
200
+ result[i].matchType = 'invalid';
201
  }
202
  }
203
  } else {
204
+ // Jika tidak ada match sama sekali, semua invalid
205
  for (let i = 0; i < result.length; i++) {
206
  result[i].id = 'invalid';
207
+ result[i].matchType = 'invalid';
208
  }
209
  }
210
 
211
+ // Final cleanup - pastikan semua slot terisi
212
  for (let i = 0; i < result.length; i++) {
213
  if (!result[i].id) {
214
  result[i].id = 'invalid';
215
+ result[i].matchType = 'invalid';
216
  }
217
  }
218
 
219
  return {
220
  success: true,
221
  data: {
222
+ soal: soalArray,
223
+ soalLeet: soalArray, // Tetap sama untuk sekarang
224
  botResults: botResults,
225
+ result: result.map(r => ({ id: r.id })), // Hanya return id untuk kompatibilitas
226
+ debug: {
227
+ parsedSoal: soalArray,
228
+ matches: result.map(r => ({ id: r.id, matchType: r.matchType, soal: r.soal })),
229
+ totalMatches: matchedCount
230
+ }
231
  }
232
  };
233