Files
ihaleist/server/siniflandir.mjs
T

102 lines
7.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Sektör ve kurum tipi sınıflandırması — TEK kaynak.
*
* Üç ayrı veri kaynağı (ilan.gov.tr canlı akışı, doğrudan temin, EKAP sonuç
* arşivi) aynı kurallardan geçer. Aksi halde "Sağlık" filtresi yalnızca bir
* kaynağı süzer, diğer iki kaynaktaki ihaleler görünmez olur.
*
* TÜRKÇE BÜYÜK HARF TUZAĞI: ilan başlıklarının yarısı TAMAMEN BÜYÜK HARF ve
* JavaScript'in `i` bayrağı Türkçe İ/I çiftini katlamaz — /inşaat/i, "İNŞAAT"
* ile EŞLEŞMEZ. Bu yüzden metni önce normalleştiriyoruz (Türkçe küçük harf +
* ASCII katlama) ve kuralları da normalleştirilmiş alfabede yazıyoruz:
* desenlerde ı/i/ş/ç/ğ/ö/ü YOKTUR, hepsi ASCII karşılığıdır.
*/
const TR_KATLAMA = {
'İ': 'i', 'I': 'i', 'ı': 'i', 'i': 'i',
'Ş': 's', 'ş': 's', 'Ç': 'c', 'ç': 'c',
'Ğ': 'g', 'ğ': 'g', 'Ö': 'o', 'ö': 'o',
'Ü': 'u', 'ü': 'u', 'Â': 'a', 'â': 'a', 'Î': 'i', 'î': 'i', 'Û': 'u', 'û': 'u',
};
/** Türkçe duyarlı küçültme + ASCII katlama. "İNŞAAT" → "insaat" */
export function normalizeTr(s) {
if (!s) return '';
let out = '';
for (const ch of String(s)) {
out += TR_KATLAMA[ch] ?? ch.toLowerCase();
}
return out.replace(/\s+/g, ' ');
}
// Desenler NORMALLEŞTİRİLMİŞ metne uygulanır: hepsi küçük harf ve ASCII.
// Sıra ÖNEMLİ: ilk eşleşen kazanır, dar kalıplar geniş olanlardan önce gelir
// (ör. "tibbi gaz" → Sağlık, "dogalgaz" → Isıtma).
export const SECTOR_RULES = [
[/tibbi|medikal|saglik|hastane|ilac |poliklinik|cerrahi|ameliyat|diyaliz|radyoloji|rontgen|tomografi|ultrason|steril|enjektor|eldiven|maske|pansuman|ped |sonda|kateter|protez|ortez|isitme cihaz|dis unit|endo motor|reaktif|hemogram|serum|asi |sedye|ligasyon|test kiti| kit alimi|manometre|oksijen regulator|medikal gaz|isitme engelli|induksiyon dongu|hasta yatak|tekerlekli sandalye|otoklav|aspirator|nebulizator|puls oksimetre/i, 'Sağlık / Tıbbi Malzeme'],
[/yazilim|bilisim|sunucu|donanim|network|bilgisayar|lisans|veri merkezi|siber|yazici alim|toner alim|tablet|projeksiyon|kart okuyucu|nitelikli sertifika|e-imza sertifika|barkod|e-imza|otomasyon sistem/i, 'Bilişim & Yazılım'],
[/guvenlik hizmet|ozel guvenlik|kamera|cctv|alarm|turnike|x-ray|guvenlik sistem|yangin sondur|yangin tup|yangin algila|itfaiye/i, 'Güvenlik Sistemleri'],
[/gida|yemek|catering|ekmek|et alim|kirmizi et|beyaz et|sebze|meyve|kumanya|sut |peynir|tavuk|bakliyat|mutfak|gazoz|icecek|su alimi|cips|kuru gida|dana |kuzu |fritoz|reso |benmari|bulasik makinesi|mutfak ekipman|kantin/i, 'Gıda & Catering'],
[/temizlik|hijyen|dezenfek|deterjan|cop |atik toplama|hasere|ilaclama|supurge|kagit havlu|tuvalet kagidi|konteyner|atik depo|geri donusum/i, 'Temizlik & Hijyen'],
[/asfalt|beton|yol yapim|kilit parke|bordur|kaldirim|kopru|altyapi|kanalizasyon|icme suyu|sulama|menfez|istinat|stabilize|dolgu/i, 'Altyapı & Yol'],
[/insaat|yapim isi|onarim|tamirat|tadilat|guclendirme|cati|cephe|restorasyon|bakim onarim|boya |badana|dograma|pvc pencere|hafriyat|yikim|nalbur|hirdavat|civata|vida |cimento|demir alim|kereste|fayans|seramik|izolasyon|mantolama/i, 'İnşaat & Bakım'],
[/kirtasiye|matbaa|baski|kagit|toner|kartus|fotokopi|buro malzeme|defter|album|dosya alim|zarf |basili evrak|form basim|kaset|klasor/i, 'Kırtasiye & Büro'],
[/mobilya|masa |sandalye|dolap|okul sirasi|buro mobilya|raf |perde|koltuk|yatak |karyola/i, 'Mobilya & Donatı'],
[/giyim|tekstil|elbise|uniforma|kiyafet|ayakkabi|bot alim|camasir|kumas|battaniye|havlu |nevresim/i, 'Tekstil & Giyim'],
[/akaryakit|motorin|benzin|lpg|yakit alim|odun |komur|pelet /i, 'Akaryakıt & Yakıt'],
[/arac kirala|tasit kirala|servis hizmet|personel tasima|ogrenci tasima|nakliye|lojistik|treyler|cekici kirala/i, 'Taşımacılık & Kiralama'],
[/arac |otomotiv|lastik|yedek parca|otobus|kamyon|is makinesi|greyder|ekskavator|kepce|traktor|transmisyon|motor yagi|aku |plakali|tasit bakim|arac bakim|balata|amortisor|rot |far alim/i, 'Otomotiv & İş Makinesi'],
[/elektrik|trafo|enerji|aydinlatma|jenerator|gunes|solar|kablo|pano |ups |armatur|ampul|led /i, 'Elektrik & Enerji'],
[/dogalgaz|kalorifer|kazan |isitma|sogutma|klima|havalandirma|iklimlendirme|mekanik tesisat|radyator|buzdolabi|sogutucu/i, 'Isıtma & İklimlendirme'],
[/asansor|yuruyen merdiven|platform lift/i, 'Asansör & Yürüyen Sistem'],
[/su aritma|aritma tesis|pompa|sondaj|kuyu |su deposu|klorlama|dalgic|boru |vana /i, 'Su & Arıtma'],
[/tarim|tohum|gubre|fide|zirai|hayvan|yem |veteriner|sera |ilaclama zirai|orman|agaclandirma/i, 'Tarım & Hayvancılık'],
[/peyzaj|park bahce|agac |cim |fidan|oyun grubu|kent mobilya|bank alim|cicek/i, 'Peyzaj & Park'],
[/egitim hizmet|kurs |seminer|danismanlik|musavirlik|etut proje|muhendislik hizmet|kontrolluk|arastirma hizmet|saha arastirma|anket/i, 'Danışmanlık & Proje'],
[/reklam|tanitim|organizasyon|fuar |basin|medya|produksiyon|afis|brosur|davetiye|promosyon|porselen kupa|hediyelik|bayrak alim|flama/i, 'Reklam & Organizasyon'],
[/sigorta|zorunlu trafik|kasko/i, 'Sigorta'],
[/kitap|yayin|kutuphane|arsiv|dijitallestirme|tercume|ceviri/i, 'Yayın & Arşiv'],
[/spor |hali saha|tribun|fitness|kondisyon|stadyum|yuzme havuz/i, 'Spor Tesisleri'],
[/laboratuvar|analiz cihaz|olcum cihaz|test cihaz|mikroskop|santrifuj|numune|kantar|tarti |terazi|kalibrasyon|sayac /i, 'Laboratuvar & Ölçüm'],
[/tasinmaz|parsel|arsa |gayrimenkul|kiraya veril|satis ihalesi|irtifak|ecrimisil/i, 'Taşınmaz & Kiralama'],
[/polisaj|testere|torna|kaynak makinesi|matkap|jeneratorlu|atolye|el aleti|kompresor/i, 'Atölye & Makine Ekipmanı'],
[/personel calistir|isci calistir|hizmet alimi personel|temizlik personel|guvenlik personel|destek personel/i, 'Personel Hizmet Alımı'],
];
export const INSTITUTION_RULES = [
[/buyuksehir belediye/i, 'Büyükşehir Belediyeleri'],
[/belediye/i, 'Belediyeler'],
[/universite/i, 'Üniversiteler'],
[/hastane|saglik mudurlugu|bashekim/i, 'Eğitim ve Araştırma Hastaneleri'],
[/agiz ve dis/i, 'Ağız ve Diş Sağlığı Merkezleri'],
[/ceza infaz|cezaevi|tevkifevi/i, 'Ceza İnfaz Kurumları'],
[/bakanligi|bakanlik|valiligi|mudurlugu/i, 'Bakanlıklar'],
[/a\.s\.|genel mudurlugu|isletme/i, 'Kamu Şirketleri'],
];
/** Kuralları NORMALLEŞTİRİLMİŞ metne uygular. */
export function classify(rules, text, fallback) {
const t = normalizeTr(text);
for (const [re, label] of rules) if (re.test(t)) return label;
return fallback;
}
/** İhale metninden sektör. Kaynak ne olursa olsun aynı sonucu verir. */
export function sektorBul(...parcalar) {
return classify(SECTOR_RULES, parcalar.filter(Boolean).join(' '), 'Genel');
}
export function kurumTipiBul(ad) {
return classify(INSTITUTION_RULES, ad || '', 'Diğer Kamu Kurumları');
}
/** Arayüzün kullandığı listeler — kurallardan türetilir, elle tutulmaz. */
// 'Genel' bir kural değil, hiçbir kalıba uymayanların düştüğü kova. Yine de
// listeye eklenir: aksi halde bu kayıtlar sektör filtresiyle hiç bulunamaz.
export const SEKTOR_ETIKETLERI = [
...[...new Set(SECTOR_RULES.map(([, ad]) => ad))].sort((a, b) => a.localeCompare(b, 'tr')),
'Genel',
];
export const KURUM_ETIKETLERI = [...new Set(INSTITUTION_RULES.map(([, ad]) => ad))]
.sort((a, b) => a.localeCompare(b, 'tr'));