#include "fiko/cam/bom.hpp" #include #include namespace fiko::cam { namespace { // Ağacı özyineli gezer; carpan = bu düğümün ebeveyn zincirinden gelen kopya sayısı. void gez(const BomDugum& d, int carpan, BomSonuc& sonuc) { const int etkin = carpan * d.adet; if (d.cocuklar.empty()) { // Yaprak parça → ada göre topla (ilk görülme sırasını koru). for (BomSatir& s : sonuc.satirlar) { if (s.ad == d.ad) { s.toplamAdet += etkin; s.toplamKutle = s.toplamAdet * s.birimKutle; sonuc.toplamParca += etkin; sonuc.toplamKutle += etkin * d.kutle; return; } } BomSatir s; s.ad = d.ad; s.malzeme = d.malzeme; s.toplamAdet = etkin; s.birimKutle = d.kutle; s.toplamKutle = etkin * d.kutle; sonuc.satirlar.push_back(std::move(s)); sonuc.toplamParca += etkin; sonuc.toplamKutle += etkin * d.kutle; return; } // Alt-montaj → yaprakları etkin çarpanla topla (montajın kendisi sayılmaz). for (const BomDugum& c : d.cocuklar) gez(c, etkin, sonuc); } } // namespace BomSonuc bomOlustur(const BomDugum& kok) { BomSonuc sonuc; gez(kok, 1, sonuc); return sonuc; } namespace { // RFC-4180 CSV alan kaçışı: virgül/tırnak/yeni-satır varsa tırnakla + iç tırnağı ikile. std::string csvAlan(const std::string& s) { if (s.find_first_of(",\"\n\r") == std::string::npos) return s; std::string r = "\""; for (char c : s) { if (c == '"') r += '"'; r += c; } r += "\""; return r; } } // namespace std::string bomCsvMetin(const BomSonuc& sonuc) { std::string o = "Ad,Malzeme,Adet,BirimKutle,ToplamKutle\n"; char b[128]; for (const BomSatir& s : sonuc.satirlar) { o += csvAlan(s.ad) + "," + csvAlan(s.malzeme) + ","; std::snprintf(b, sizeof(b), "%d,%.3f,%.3f\n", s.toplamAdet, s.birimKutle, s.toplamKutle); o += b; } std::snprintf(b, sizeof(b), "TOPLAM,,%d,,%.3f\n", sonuc.toplamParca, sonuc.toplamKutle); o += b; return o; } bool bomCsvKaydet(const BomSonuc& sonuc, const std::string& yol) { std::ofstream f(yol, std::ios::binary); if (!f) return false; f << bomCsvMetin(sonuc); return f.good(); } } // namespace fiko::cam