#include "sistem/fiko_sistem.hpp" #include #include #include #include #include #include #include #include #include namespace fikatia::sistem { namespace { constexpr double PI = std::numbers::pi_v; } // ---------------------------------------------------------------- sinyal ---- int Sinyal::ekle(Fonk fonk) { const int kimlik = ++sonKimlik_; fonksiyonlar_.push_back({kimlik, std::move(fonk)}); return kimlik; } void Sinyal::sil(int kimlik) { std::erase_if(fonksiyonlar_, [kimlik](const Kayit& k) { return k.kimlik == kimlik; }); } void Sinyal::calistir(const std::any& veri) const { if (bloke_) return; for (const Kayit& k : fonksiyonlar_) { try { if (k.fonk) k.fonk(veri); } catch (...) { } } } Sinyal& Sinyaller::sinyal(std::string_view isim) { auto it = sinyaller_.find(isim); if (it == sinyaller_.end()) it = sinyaller_.emplace(std::string(isim), Sinyal{}).first; return it->second; } Sinyaller& globalSinyal() { static Sinyaller g; return g; } // --------------------------------------------------------------- ayarlar ---- namespace { using post::fikodb::Deger; using post::fikodb::Satir; using post::fikodb::Tablo; std::string metinAl(const Tablo& t, const Satir& s, std::string_view kolon) { const Deger* d = t.deger(s, kolon); return d ? d->metinDeger() : std::string(); } std::int64_t tamAl(const Tablo& t, const Satir& s, std::string_view kolon, std::int64_t vars) { const Deger* d = t.deger(s, kolon); if (!d || d->bosMu()) return vars; return d->tamDeger(); } void kolonYaz(Tablo& t, Satir& s, std::string_view kolon, Deger deger) { const int i = t.kolonIndeksi(kolon); if (i < 0) return; if (s.degerler.size() < t.kolonlar.size()) s.degerler.resize(t.kolonlar.size()); s.degerler[static_cast(i)] = std::move(deger); } // Bos metin NULL olarak yazilir (Python satirlariyla format esdegerligi). Deger metinVeyaBos(const std::string& v) { return v.empty() ? Deger::bos() : Deger::metinYap(v); } } // namespace int Ayar::asInt() const { return static_cast(std::strtol(degeri.c_str(), nullptr, 10)); } double Ayar::asFloat() const { return std::strtod(degeri.c_str(), nullptr); } const AyarKategori* AyarKategoriler::item(int indeks) const { if (indeks < 0 || indeks >= sayisi()) return nullptr; return &tumu_[static_cast(indeks)]; } const AyarKategori* AyarKategoriler::item(std::string_view ismi) const { for (const AyarKategori& k : tumu_) if (k.ismi == ismi) return &k; return nullptr; } std::string AyarKategoriler::metin() const { std::string s = "["; for (std::size_t i = 0; i < tumu_.size(); ++i) { if (i) s += ", "; s += "'" + tumu_[i].ismi + "'"; } return s + "]"; } Ayarlar Ayarlar::dosyadan(const std::string& yol) { Ayarlar a; a.yol_ = yol; a.vt_ = post::fikodb::dosyadanCoz(yol); const Tablo* t = a.vt_.tablo("ayarlar"); if (!t) throw std::runtime_error("Ayar dosyasinda 'ayarlar' tablosu yok: " + yol); for (const Satir& s : t->satirlar) { Ayar ay; ay.id = tamAl(*t, s, "id", s.rowid); ay.strId = metinAl(*t, s, "strID"); ay.ismi = metinAl(*t, s, "ismi"); ay.degeri = metinAl(*t, s, "degeri"); ay.degerTuru = metinAl(*t, s, "degerTuru"); ay.aciklama = metinAl(*t, s, "aciklama"); ay.simge = metinAl(*t, s, "simge"); ay.kategoriId = tamAl(*t, s, "kategoriId", 0); ay.ekBilgiler = metinAl(*t, s, "ekBilgiler"); a.tumu_.push_back(std::move(ay)); } if (const Tablo* k = a.vt_.tablo("kategoriler")) { for (const Satir& s : k->satirlar) { AyarKategori kat; kat.id = tamAl(*k, s, "id", s.rowid); kat.ismi = metinAl(*k, s, "ismi"); kat.aciklama = metinAl(*k, s, "aciklama"); kat.simge = metinAl(*k, s, "simge"); kat.ustKategoriId = tamAl(*k, s, "ustKategoriId", 0); kat.ekBilgiler = metinAl(*k, s, "ekBilgiler"); a.kategoriler_.tumu_.push_back(std::move(kat)); } } return a; } const Ayar* Ayarlar::item(int indeks) const { if (indeks < 0 || indeks >= sayisi()) return nullptr; return &tumu_[static_cast(indeks)]; } Ayar* Ayarlar::item(int indeks) { return const_cast(static_cast(this)->item(indeks)); } const Ayar* Ayarlar::item(std::string_view strId) const { for (const Ayar& a : tumu_) if (a.strId == strId) return &a; return nullptr; } Ayar* Ayarlar::item(std::string_view strId) { return const_cast(static_cast(this)->item(strId)); } const AyarKategori* Ayarlar::kategorisi(const Ayar& ayar) const { for (const AyarKategori& k : kategoriler_.tumu_) if (k.id == ayar.kategoriId) return &k; return nullptr; } std::vector Ayarlar::kategoriAyarlari(std::int64_t kategoriId) const { std::vector sonuc; for (const Ayar& a : tumu_) if (a.kategoriId == kategoriId) sonuc.push_back(&a); return sonuc; } void Ayarlar::degerAyarla(std::string_view strId, std::string deger) { if (Ayar* a = item(strId)) { a->degeri = std::move(deger); a->degismis = true; } } void Ayarlar::kaydet() { Tablo* t = vt_.tablo("ayarlar"); if (!t) throw std::runtime_error("Ayar dosyasinda 'ayarlar' tablosu yok: " + yol_); bool degisenVar = false; for (Ayar& a : tumu_) { if (!a.degismis) continue; degisenVar = true; for (Satir& s : t->satirlar) { if (tamAl(*t, s, "id", s.rowid) != a.id) continue; kolonYaz(*t, s, "strID", metinVeyaBos(a.strId)); kolonYaz(*t, s, "ismi", metinVeyaBos(a.ismi)); kolonYaz(*t, s, "degeri", metinVeyaBos(a.degeri)); kolonYaz(*t, s, "degerTuru", metinVeyaBos(a.degerTuru)); kolonYaz(*t, s, "aciklama", metinVeyaBos(a.aciklama)); kolonYaz(*t, s, "simge", metinVeyaBos(a.simge)); kolonYaz(*t, s, "kategoriId", Deger::tamYap(a.kategoriId)); kolonYaz(*t, s, "ekBilgiler", metinVeyaBos(a.ekBilgiler)); break; } a.degismis = false; } if (degisenVar) post::fikodb::dosyayaYaz(vt_, yol_); } // -------------------------------------------------------- dosya sistemi ---- namespace { char kucukHarf(char c) { return static_cast(std::tolower(static_cast(c))); } // Windows dosya adi jokeri: * ve ? (buyuk/kucuk harf duyarsiz). bool jokerEsle(std::string_view desen, std::string_view metin) { std::size_t d = 0, m = 0; std::size_t yildiz = std::string_view::npos, geri = 0; while (m < metin.size()) { if (d < desen.size() && (desen[d] == '?' || kucukHarf(desen[d]) == kucukHarf(metin[m]))) { ++d; ++m; } else if (d < desen.size() && desen[d] == '*') { yildiz = d++; geri = m; } else if (yildiz != std::string_view::npos) { d = yildiz + 1; m = ++geri; } else { return false; } } while (d < desen.size() && desen[d] == '*') ++d; return d == desen.size(); } bool surecBaslat(const std::wstring& komutSatiri, int pencereGoster, PROCESS_INFORMATION& pi) { STARTUPINFOW si{}; si.cb = sizeof si; si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = static_cast(pencereGoster); std::wstring tampon = komutSatiri; // CreateProcessW yazilabilir tampon ister return ::CreateProcessW(nullptr, tampon.data(), nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi) != 0; } } // namespace std::vector DosyaSistemi::klasordekiDosyalar(const std::string& klasor, const std::string& uzantilar) { std::vector sonuc; std::error_code ec; for (const auto& girdi : std::filesystem::directory_iterator(klasor, ec)) { const std::string ad = girdi.path().filename().string(); if (jokerEsle(uzantilar, ad)) sonuc.push_back(ad); } return sonuc; } bool DosyaSistemi::programCalistir(const std::wstring& komutSatiri, int pencereGoster) { PROCESS_INFORMATION pi{}; if (!surecBaslat(komutSatiri, pencereGoster, pi)) return false; ::CloseHandle(pi.hThread); ::CloseHandle(pi.hProcess); return true; } std::optional DosyaSistemi::programCalistirBekle(const std::wstring& komutSatiri, int pencereGoster) { PROCESS_INFORMATION pi{}; if (!surecBaslat(komutSatiri, pencereGoster, pi)) return std::nullopt; ::WaitForSingleObject(pi.hProcess, INFINITE); DWORD kod = 0; ::GetExitCodeProcess(pi.hProcess, &kod); ::CloseHandle(pi.hThread); ::CloseHandle(pi.hProcess); return kod; } // ------------------------------------------------------------ numokrator ---- const NumokratorOge* NumokratorOge::altItem(int indeks) const { if (indeks < 0 || indeks >= altParcaSayisi()) return nullptr; return &altOgeler[static_cast(indeks)]; } NumokratorOge& Numokrator::ekle(NumokratorOge oge) { ogeler_.push_back(std::move(oge)); return ogeler_.back(); } NumokratorOge* Numokrator::item(int indeks) { if (indeks < 0 || indeks >= sayisi()) return nullptr; return &ogeler_[static_cast(indeks)]; } const NumokratorOge* Numokrator::item(int indeks) const { if (indeks < 0 || indeks >= sayisi()) return nullptr; return &ogeler_[static_cast(indeks)]; } void Numokrator::sil(int indeks) { if (indeks < 0 || indeks >= sayisi()) return; ogeler_.erase(ogeler_.begin() + indeks); } std::map Numokrator::hazirla() { ogeler_.clear(); std::map partlar; toplam_ = gez(sahip_, partlar); return partlar; } int Numokrator::gez(const Product& urun, std::map& partlar) { int toplam = 0; Productlar liste = urun.productlar(); const long adet = liste.adet(); for (long i = 0; i < adet; ++i) { Product itm = liste.eleman(i); NumokratorOge oge; oge.ismi = itm.ismi(); oge.parcaNumarasi = itm.parcaNumarasi(); if (itm.productMi()) { oge.turu = L"IProduct"; toplam += gez(itm, partlar); } else { oge.turu = L"IPart"; toplam += 1; partlar[oge.parcaNumarasi] += 1; } oge.sayisi = partlar.count(oge.parcaNumarasi) ? partlar[oge.parcaNumarasi] : 0; ekle(std::move(oge)); } return toplam; } // -------------------------------------------------------------- vector3d ---- double Vektor3::uzunluk() const { return std::sqrt(x * x + y * y + z * z); } Vektor3 Vektor3::olcekliVektor(double oran) const { Vektor3 v = *this; v.olcekle(oran); return v; } Vektor3 Vektor3::paralelVektor(const Vektor3& eksen) const { const double eksenBoy = eksen.uzunluk(); if (yakinSifirMi(eksenBoy)) return *this; return eksen.olcekliVektor(icCarpim(*this, eksen) / eksen.uzunluk() / eksen.uzunluk()); } void Vektor3::donustur(const Matris3& m) { const double vx = m.e[0][0] * x + m.e[1][0] * y + m.e[2][0] * z + m.e[3][0]; const double vy = m.e[0][1] * x + m.e[1][1] * y + m.e[2][1] * z + m.e[3][1]; const double vz = m.e[0][2] * x + m.e[1][2] * y + m.e[2][2] * z + m.e[3][2]; x = vx; y = vy; z = vz; } std::string Vektor3::metin() const { char t[96]; std::snprintf(t, sizeof t, "(% .2f, % .2f, % .2f)", x, y, z); return t; } bool Matris3::operator==(const Matris3& o) const { for (int i = 0; i < 3; ++i) for (int j = 0; j < 3; ++j) if (std::fabs(e[i][j] - o.e[i][j]) > KUCUK) return false; return true; } Matris3 Matris3::operator*(const Matris3& o) const { Matris3 c; for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { double val = 0.0; for (int k = 0; k < 3; ++k) val += eleman(k, i) * o.eleman(j, k); c.elemanAyarla(j, i, val); } // c(3,i) oteleme vektorudur (Python birebir) double val = eleman(3, i); for (int k = 0; k < 3; ++k) val += eleman(k, i) * o.eleman(3, k); c.elemanAyarla(3, i, val); } return c; } Vektor3 Matris3::donusturVektor(const Vektor3& v) const { return {e[0][0] * v.x + e[1][0] * v.y + e[2][0] * v.z + e[3][0], e[0][1] * v.x + e[1][1] * v.y + e[2][1] * v.z + e[3][1], e[0][2] * v.x + e[1][2] * v.y + e[2][2] * v.z + e[3][2]}; } std::string Matris3::metin() const { char t[320]; std::snprintf(t, sizeof t, " [% .2f, % .2f, % .2f ]\n [% .2f, % .2f, % .2f ]\n" " [% .2f, % .2f, % .2f ]\n [ ------------------ ]\n [% .2f, % .2f, % .2f ]", e[0][0], e[0][1], e[0][2], e[1][0], e[1][1], e[1][2], e[2][0], e[2][1], e[2][2], e[3][0], e[3][1], e[3][2]); return t; } double aciNormallestir(double aci) { while (std::fabs(aci) > PI) { if (aci > PI) aci -= PI * 2; if (aci < -PI) aci += 2 * PI; } if (yakinSifirMi(std::fabs(aci + PI))) aci = PI; return aci; } double aciFarki(double aci1, double aci2) { return aciNormallestir(aciNormallestir(aci1) - aciNormallestir(aci2)); } double icCarpim(const Vektor3& a, const Vektor3& b) { return a.x * b.x + a.y * b.y + a.z * b.z; } Vektor3 caprazCarpim(const Vektor3& a, const Vektor3& b) { return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x}; } double mesafeKare(const Vektor3& p1, const Vektor3& p2) { const double x = p1.x - p2.x; const double y = p1.y - p2.y; const double z = p1.z - p2.z; return x * x + y * y + z * z; } double mesafe(const Vektor3& p1, const Vektor3& p2) { return std::sqrt(mesafeKare(p2, p1)); } double vektorAcisi(const Vektor3& a, const Vektor3& b) { const double aBoy = a.uzunluk(); const double bBoy = b.uzunluk(); if (aBoy * bBoy < 1e-6) return 0.0; const double c = icCarpim(a, b) / aBoy / bBoy; if (c >= 1.0) return 0.0; if (c <= -1.0) return PI; return std::acos(c); } double konumAcisi(const Vektor3& p1, const Vektor3& p2, const Vektor3& p3) { return vektorAcisi(p1 - p2, p3 - p2); } double vektorDihedral(const Vektor3& a, const Vektor3& eksen, const Vektor3& c) { const Vektor3 ap = a.dikVektor(eksen); const Vektor3 cp = c.dikVektor(eksen); double aci = vektorAcisi(ap, cp); if (icCarpim(caprazCarpim(ap, cp), eksen) > 0) aci = -aci; return aci; } double konumDihedral(const Vektor3& p1, const Vektor3& p2, const Vektor3& p3, const Vektor3& p4) { return vektorDihedral(p1 - p2, p2 - p3, p4 - p3); } Vektor3 duzlemNormali(const Vektor3& p1, const Vektor3& p2, const Vektor3& p3) { return caprazCarpim(p1 - p2, p3 - p2).birimVektor(); } Matris3 orijindeDonme(const Vektor3& eksen, double teta) { const Vektor3 v = eksen.birimVektor(); const double c = std::cos(teta); const double s = std::sin(teta); const double t = 1.0 - c; Matris3 m; m.e[0][0] = t * v.x * v.x + c; m.e[0][1] = t * v.x * v.y + v.z * s; m.e[0][2] = t * v.x * v.z - v.y * s; m.e[1][0] = t * v.y * v.x - v.z * s; m.e[1][1] = t * v.y * v.y + c; m.e[1][2] = t * v.y * v.z + v.x * s; m.e[2][0] = t * v.z * v.x + v.y * s; m.e[2][1] = t * v.z * v.y - v.x * s; m.e[2][2] = t * v.z * v.z + c; return m; } Matris3 oteleme(const Vektor3& p) { Matris3 m; m.e[3][0] = p.x; m.e[3][1] = p.y; m.e[3][2] = p.z; return m; } Matris3 donme(const Vektor3& eksen, double teta, const Vektor3& merkez) { const Matris3 rot = orijindeDonme(eksen, teta); const Matris3 tasima = oteleme(merkez - rot.donusturVektor(merkez)); return tasima * rot; } Vektor3 dondurulmusKonum(double teta, const Vektor3& baglanti, const Vektor3& merkez, const Vektor3& konum) { return donme(merkez - baglanti, teta, merkez).donusturVektor(konum); } Vektor3 izdusumKonum(double uzunluk, double aci, double dihedral, const Vektor3& p1, const Vektor3& p2, const Vektor3& p3) { const Vektor3 norm = duzlemNormali(p1, p2, p3); const Vektor3 eksen = p3 - p2; Vektor3 fark = eksen.olcekliVektor(-uzunluk); fark = orijindeDonme(norm, -aci).donusturVektor(fark); fark = orijindeDonme(eksen, dihedral).donusturVektor(fark); return p3 + fark; } Matris3 superpozisyon3(const Vektor3& ref1, const Vektor3& ref2, const Vektor3& ref3, const Vektor3& mov1, const Vektor3& mov2, const Vektor3& mov3) { Vektor3 movFark = mov2 - mov1; Vektor3 refFark = ref2 - ref1; Matris3 m1; if (std::fabs(vektorAcisi(movFark, refFark)) < KUCUK) { m1 = oteleme(ref1 - mov1); } else { const Vektor3 eksen = caprazCarpim(movFark, refFark); const double burulma = vektorDihedral(refFark, eksen, movFark); const Matris3 rot = orijindeDonme(eksen, burulma); const Matris3 tasima = oteleme(ref2 - rot.donusturVektor(mov2)); m1 = tasima * rot; } movFark = ref2 - m1.donusturVektor(mov3); refFark = ref2 - ref3; Matris3 m; if (std::fabs(vektorAcisi(movFark, refFark)) < KUCUK) { m = m1; } else { const Vektor3 eksen = ref2 - ref1; const double burulma = vektorDihedral(refFark, eksen, movFark); const Matris3 m2 = orijindeDonme(eksen, burulma); const Matris3 m3 = oteleme(ref2 - m2.donusturVektor(ref2)); m = m3 * m2 * m1; } return m; } namespace { double rastgele(double a, double b) { static std::mt19937 motor{std::random_device{}()}; return std::uniform_real_distribution(a, b)(motor); } } // namespace Vektor3 rastgeleVektor() { return {rastgele(-100.0, 100.0), rastgele(-100.0, 100.0), rastgele(-100.0, 100.0)}; } Matris3 rastgeleOrijinDonme() { return orijindeDonme(rastgeleVektor(), rastgele(-PI / 2, PI / 2)); } Matris3 rastgeleDonusum() { return donme(rastgeleVektor(), rastgele(-PI / 2, PI / 2), rastgeleVektor()); } // ---------------------------------------------------- yardimci siniflar ---- namespace { double yuvarla3(double v) { return std::round(v * 1000.0) / 1000.0; } // Python f-string float bicimi: 3 haneye yuvarlanmis, sondaki sifirlar atilmis // ("5.0" korunur). std::string sayiMetni(double v) { char t[64]; std::snprintf(t, sizeof t, "%.3f", v); std::string s = t; while (s.size() > 1 && s.back() == '0') s.pop_back(); if (!s.empty() && s.back() == '.') s += '0'; return s; } } // namespace bool SifirKonum::miX0Merkez() const { return yuvarla3(xMin) == yuvarla3(xMax); } bool SifirKonum::miX0XEksiDuvar() const { return yuvarla3(xMin) == 0.0; } bool SifirKonum::miX0XArtiDuvar() const { return yuvarla3(xMax) == 0.0; } bool SifirKonum::miY0Merkez() const { return yuvarla3(yMin) == yuvarla3(yMax); } bool SifirKonum::miY0YEksiDuvar() const { return yuvarla3(yMin) == 0.0; } bool SifirKonum::miY0YArtiDuvar() const { return yuvarla3(yMax) == 0.0; } bool SifirKonum::miZ0Merkez() const { return yuvarla3(zMin) == yuvarla3(zMax); } bool SifirKonum::miZ0Taban() const { return yuvarla3(zMin) == 0.0; } bool SifirKonum::miZ0Ustu() const { return yuvarla3(zMax) == 0.0; } std::string SifirKonum::xSifir() const { if (miX0Merkez()) return "Merkez ( X±=" + sayiMetni(yuvarla3(xMin)) + "mm )"; if (miX0XEksiDuvar()) return "Sol Duvar (X Eksi)"; if (miX0XArtiDuvar()) return "Sağ Duvar (X Artı)"; return "X Eksi Uç Nokta = " + sayiMetni(yuvarla3(xMin)) + "mm <-> X Artı Uç Nokta = " + sayiMetni(yuvarla3(xMax)) + "mm"; } std::string SifirKonum::ySifir() const { if (miY0Merkez()) return "Merkez ( Y±=" + sayiMetni(yuvarla3(yMin)) + "mm )"; if (miY0YEksiDuvar()) return "Ön Duvar (Y Eksi)"; if (miY0YArtiDuvar()) return "Arka Duvar (Y Artı)"; return "Y Eksi Uç Nokta = " + sayiMetni(yuvarla3(yMin)) + "mm <-> Y Artı Uç Nokta = " + sayiMetni(yuvarla3(yMax)) + "mm"; } std::string SifirKonum::zSifir() const { if (miZ0Merkez()) return "Merkez"; if (miZ0Taban()) return "Taban (Üstü Z" + sayiMetni(yuvarla3(zMax)) + "mm)"; if (miZ0Ustu()) return "Üstü (Taban Z" + sayiMetni(yuvarla3(zMin) * -1) + "mm)"; return "Taban Z" + sayiMetni(yuvarla3(zMin) * -1) + "mm <-> Parça Üstü Z" + sayiMetni(yuvarla3(zMax)) + "mm"; } std::string SifirKonum::toStr() const { return "X0=" + xSifir() + " Y0=" + ySifir() + " Z0=" + zSifir(); } } // namespace fikatia::sistem