fix: kismi ihalede sahte kirim orani — maliyet tum ihale, bedel kisim basina

Sonuc ayristirici yaklasik maliyeti TUM ihale icin okuyor
((?<!Kısımlarının )Yaklaşık Maliyeti), sozlesme bedeli ise kisim basina
satir. 11 kisimlik ilac ihalesinin ilk kismi 1,6 milyon tahmine karsi 25 bine
verilmisse rakip radarinda "%98 kirim" cikiyordu — aritmetik kurgu.

Kirim artik yalnizca tek sonuc satiri olan (kisimsiz) ihalelerde
hesaplaniyor. Yanlis bir oran, hic oran olmamasindan kotudur.
Test: A (kisimsiz) → %20; B ve C (ayni IKN, iki kisim) → null.

Bulgu kaynagi: erenulutas0/MOBIT-DURT README "olcerek cozulmus uc tuzak".

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-09-03 22:19:15 +03:00
co-authored by Claude Fable 5.1
parent 17c781a9ba
commit 2c70ed9d71
+9 -1
View File
@@ -29,6 +29,13 @@ export function normProvince(name) {
export function firmStats(tenders) {
const map = new Map();
let awardCount = 0;
// Kısmi ihale tuzağı: yaklaşık maliyet TÜM ihale için okunuyor, sözleşme
// bedeli ise kısım başına. 11 kısımlık ilaç ihalesinin ilk kısmı 1,6 milyon
// tahmine karşı 25 bine verilmişse bu %98 kırım değil, aritmetik kurgudur.
// Kırım yalnızca tek sonuç satırı olan (kısımsız) ihalelerde hesaplanır;
// yanlış bir oran, hiç oran olmamasından kötüdür.
const iknSatir = new Map();
for (const t of tenders) if (t.kazananFirma && t.ikn) iknSatir.set(t.ikn, (iknSatir.get(t.ikn) || 0) + 1);
for (const t of tenders) {
if (!t.kazananFirma) continue;
awardCount++;
@@ -43,7 +50,8 @@ export function firmStats(tenders) {
cur.wins++;
if (val != null) cur.total += val;
const maliyet = parseTL(t.yaklasikMaliyet);
if (val != null && maliyet > 0 && val <= maliyet * 1.5) {
const kisimsiz = (iknSatir.get(t.ikn) || 1) === 1;
if (kisimsiz && val != null && maliyet > 0 && val <= maliyet * 1.5) {
cur.kirimToplam += 1 - val / maliyet;
cur.kirimAdet++;
}