{
  "version": 1,
  "session_id": "1787962704361_ktjek",
  "source": "vscode",
  "pid": 1452,
  "started_at": "2026-08-29T00:18:25.305Z",
  "ended_at": "2026-08-29T01:47:42.822Z",
  "exit_code": 1,
  "status": "failed",
  "interactive": true,
  "provider": "cline",
  "model": "z-ai/glm-5.3-flash",
  "cwd": "d:\\__sistem__\\Masaustu\\FikoYT.Yeni.Cag",
  "workspace_root": "d:\\__sistem__\\Masaustu\\FikoYT.Yeni.Cag",
  "enable_tools": true,
  "enable_spawn": false,
  "enable_teams": false,
  "prompt": "'fikoyt-sistem/src/app/uygulamalar/post-birlestiricisi/' (see below for folder content)\n\n                              <label class=\"offset-label\">Work Offset:</label>\n                              <select class=\"offset-select\"\n                                      [value]=\"file.workOffset\"\n                                      (change)=\"updateOffset(idx, $any($event.target).value)\">\n                                   <option *ngFor=\"let offset of availableOffsets\"\n                                           [value]=\"offset\">{{ offset }}</option>\n                              </select>\n\nbak burda work ofssetler var eğer başka itemde aynı workoffset var ise ikisii aynı renge boyayıp pulse efekti versin örğneğin g54 iki itemdede kullanılıyor ikisini aynı renk yapıp pulselice g55i 3 tane kullanıyor onlarda farklı renk olucak\n\n<folder_content path=\"fikoyt-sistem/src/app/uygulamalar/post-birlestiricisi/\" workspace=\"FikoYT.Yeni.Cag\">\n├── pipes/\n├── post-birlestiricisi.component.html\n├── post-birlestiricisi.component.less\n├── post-birlestiricisi.component.ts\n└── services/\n\n<file_content path=\"fikoyt-sistem/src/app/uygulamalar/post-birlestiricisi/post-birlestiricisi.component.html\">\n<div class=\"container\">\n     <!-- Header -->\n     <div class=\"header\">\n          <div class=\"header-content\">\n               <svg class=\"icon-large\"\n                    viewBox=\"0 0 24 24\"\n                    fill=\"none\"\n                    stroke=\"currentColor\"\n                    stroke-width=\"2\">\n                    <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\"></path>\n                    <polyline points=\"14 2 14 8 20 8\"></polyline>\n                    <line x1=\"16\"\n                          y1=\"13\"\n                          x2=\"8\"\n                          y2=\"13\"></line>\n                    <line x1=\"16\"\n                          y1=\"17\"\n                          x2=\"8\"\n                          y2=\"17\"></line>\n                    <polyline points=\"10 9 9 9 8 9\"></polyline>\n               </svg>\n               <h1>CNC Post Birlestiricisi</h1>\n               <svg class=\"icon-zap\"\n                    viewBox=\"0 0 24 24\"\n                    fill=\"none\"\n                    stroke=\"currentColor\"\n                    stroke-width=\"2\">\n                    <polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\"></polygon>\n               </svg>\n          </div>\n          <p class=\"subtitle\">Profesyonel G-Code birlestirme araci</p>\n     </div>\n\n     @if (recentFiles.length > 0) {\n     <h4 style=\"text-align:center;margin-bottom:10px;font-weight:600;color:#333;\">\n          Uyar Model Son Postlar\n     </h4>\n     <div id=\"container\"\n          class=\"mb-3\"\n          style=\"display: flex; flex-wrap: wrap; gap: 5px;justify-content: center; \">\n          @for (file of recentFiles; track $index) {\n\n          <div\n               style=\"background: white; border-radius: 12px; padding: 12px; width: 180px; box-shadow: 0 8px 20px rgba(0,0,0,0.15); transition: all 0.3s ease; border-left: 4px solid #667eea; position: relative;\">\n\n               <div style=\"display: flex; align-items: center; margin-bottom: 10px;\">\n                    <span style=\"font-size: 1.8rem; margin-right: 10px;\">📄</span>\n                    <div style=\"flex: 1; min-width: 0;\">\n                         <div\n                              style=\"font-weight: 600; color: #333; font-size: 0.85rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\">\n                              {{ file.name }}</div>\n                         <div style=\"font-size: 0.8rem; color: #666; margin-top: 2px;\">\n                              <span style=\"display: inline-block; margin-right: 8px;\">{{ (file.size |\n                                   toDosyaBoyutu).join(' ') }}</span>\n                              <span style=\"display: inline-block;\">{{ file.date_modified |\n                                   date:\"dd.MM.yyyy HH:mm\" }}</span>\n                         </div>\n                         <nz-progress [nzPercent]=\"file.progress\"\n                                      [nzShowInfo]=\"false\"></nz-progress>\n                    </div>\n               </div>\n\n\n               <button style=\"width: 100%; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border: none; padding: 8px; border-radius: 8px; font-size: 0.8rem; font-weight: 600; cursor: pointer; transition: all 0.3s ease;\"\n                       (click)=\"addFileFromUrl(file)\">\n                    @if ( file.mesgul){\n                    ⏳\n                    } @else {\n                    ➕\n                    } Ekle\n               </button>\n\n               <button nz-button\n                       nzType=\"default\"\n                       nzShape=\"circle\"\n                       style=\"position: absolute;top: 5px;right: 5px;width: 24px;height: 24px;padding: 0;flex:1;\"\n                       (click)=\"postKopyala(file)\">\n                    📥\n               </button>\n          </div>\n          }\n     </div>\n     }\n     <nz-row nzJustify=\"center\"\n             class=\"mb-2\"\n             style=\"margin-top: 1em;position: -webkit-sticky;position: sticky;bottom: 5px;\">\n          <div\n               style=\"max-width: 960px;row-gap: 10px;width: 100%;display: flex;flex-wrap: wrap;justify-content: end;column-gap: 10px;margin-right:1em;\">\n\n               <nz-pagination #sayfalayici\n                              [nzSimple]=\"false\"\n                              [nzTotal]=\"total\"\n                              style=\"background: white;padding: 0px 10px;border-radius: 2em;box-shadow: 0px 4px 8px -2px rgba(9, 30, 66, 0.25), 0px 0px 0px 1px rgba(9, 30, 66, 0.08);\"\n                              [(nzPageSize)]=\"pageSize\"\n                              (nzPageIndexChange)=\"onPageChange($event)\"\n                              (nzPageSizeChange)=\"onPageSizeChange($event)\"\n                              nzSize=\"small\"\n                              [nzPageSizeOptions]=\"[5, 10, 15]\"\n                              [(nzPageIndex)]=\"pageIndex\"\n                              nzShowSizeChanger\n                              nzShowQuickJumper></nz-pagination>\n          </div>\n     </nz-row>\n\n     <!-- Upload Area -->\n     @if (files.length<=0){ <div\n           class=\"upload-area\"\n           [class.dragging]=\"isDragging\"\n           (drop)=\"onDrop($event)\"\n           (dragover)=\"onDragOver($event)\"\n           (dragleave)=\"onDragLeave($event)\"\n           (click)=\"fileInput.click()\">\n\n          <input\n                    #fileInput\n                    type=\"file\"\n                    multiple\n                    accept=\".nc,.txt,.gcode\"\n                    (change)=\"onFileInputChange($event)\"\n                    style=\"display: none;\">\n\n          <svg class=\"upload-icon\"\n               [class.bounce]=\"isDragging\"\n               viewBox=\"0 0 24 24\"\n               fill=\"none\"\n               stroke=\"currentColor\"\n               stroke-width=\"2\">\n               <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"></path>\n               <polyline points=\"17 8 12 3 7 8\"></polyline>\n               <line x1=\"12\"\n                     y1=\"3\"\n                     x2=\"12\"\n                     y2=\"15\"></line>\n          </svg>\n\n          <p class=\"upload-title\">\n               {{ isDragging ? 'Dosyalari birak!' : 'Dosyalari surukle veya tikla' }}\n          </p>\n          <p class=\"upload-subtitle\">NC, TXT, GCODE dosyalari desteklenir</p>\n</div>\n}\n\n\n\n\n<!-- Progress Bar -->\n<div *ngIf=\"progressVisible\"\n     class=\"progress-container\">\n     <div class=\"progress-info\">\n          <span class=\"progress-filename\">{{ currentFileName }}</span>\n          <span class=\"progress-percent\">{{ progressPercent }}%</span>\n     </div>\n     <div class=\"progress-bar\">\n          <div class=\"progress-fill\"\n               [style.width.%]=\"progressPercent\"></div>\n     </div>\n</div>\n\n<!-- Files List -->\n<div *ngIf=\"files.length > 0\"\n     class=\"files-section\"\n     (drop)=\"onDrop($event)\"\n     (dragover)=\"onDragOver($event)\"\n     (dragleave)=\"onDragLeave($event)\">\n     <div class=\"section-header\">\n          <h2 class=\"section-title\">\n               <svg class=\"icon-check\"\n                    viewBox=\"0 0 24 24\"\n                    fill=\"none\"\n                    stroke=\"currentColor\"\n                    stroke-width=\"2\">\n                    <path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"></path>\n                    <polyline points=\"22 4 12 14.01 9 11.01\"></polyline>\n               </svg>\n               Yuklenen Dosyalar ({{ files.length }})\n\n\n               <div [class.dragging]=\"isDragging\"\n                    (click)=\"fileInput.click()\">\n\n                    <input\n                                  #fileInput\n                                  type=\"file\"\n                                  multiple\n                                  accept=\".nc,.txt,.gcode\"\n                                  (change)=\"onFileInputChange($event)\"\n                                  style=\"display: none;\">\n\n                    <svg class=\"upload-icon\"\n                         [class.bounce]=\"isDragging\"\n                         viewBox=\"0 0 24 24\"\n                         fill=\"none\"\n                         stroke=\"currentColor\"\n                         stroke-width=\"2\">\n                         <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"></path>\n                         <polyline points=\"17 8 12 3 7 8\"></polyline>\n                         <line x1=\"12\"\n                               y1=\"3\"\n                               x2=\"12\"\n                               y2=\"15\"></line>\n                    </svg>\n               </div>\n\n\n          </h2>\n          <div class=\"ui labeled button\"\n               tabindex=\"0\"\n               (click)=\"gecisleriAyarla()\">\n               <div class=\"ui blue button\">\n                    <i class=\"heart icon\"></i> Geçileri Ayarla\n               </div>\n               <a class=\"ui basic red left pointing label\">\n                    {{enBuyukKutuk()}}\n               </a>\n          </div>\n          <button class=\"btn-danger\"\n                  (click)=\"clearAll()\">\n               <svg class=\"icon-small\"\n                    viewBox=\"0 0 24 24\"\n                    fill=\"none\"\n                    stroke=\"currentColor\"\n                    stroke-width=\"2\">\n                    <polyline points=\"3 6 5 6 21 6\"></polyline>\n                    <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\">\n                    </path>\n               </svg>\n               Tümünü Temizle\n          </button>\n     </div>\n\n     <!-- Duplicate Offset Warning -->\n     @if (hasDuplicateOffsets()) {\n     <div class=\"duplicate-warning\"\n          style=\"\n          background: linear-gradient(135deg, #fff3cd 0%, #ffe69c 100%);\n          border: 2px solid #ffc107;\n          border-radius: 8px;\n          padding: 12px 16px;\n          margin-bottom: 16px;\n          display: flex;\n          align-items: flex-start;\n          gap: 12px;\n          box-shadow: 0 2px 8px rgba(255, 193, 7, 0.3);\n     \">\n          <svg style=\"width: 24px; height: 24px; flex-shrink: 0; color: #856404;\"\n               viewBox=\"0 0 24 24\"\n               fill=\"none\"\n               stroke=\"currentColor\"\n               stroke-width=\"2\">\n               <path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\">\n               </path>\n               <line x1=\"12\"\n                     y1=\"9\"\n                     x2=\"12\"\n                     y2=\"13\"></line>\n               <line x1=\"12\"\n                     y1=\"17\"\n                     x2=\"12.01\"\n                     y2=\"17\"></line>\n          </svg>\n          <div style=\"flex: 1;\">\n               <div style=\"font-weight: 600; color: #856404; margin-bottom: 4px;\">\n                    Ayni Koordinat Duzlemi Secili!\n               </div>\n               <div style=\"font-size: 0.9rem; color: #664d03;\">\n                    @for (dup of getDuplicateOffsets(); track dup.offset) {\n                    <div style=\"margin-top: 4px;\">\n                         <strong>{{ dup.offset }}:</strong> {{ dup.files.join(', ') }}\n                    </div>\n                    }\n               </div>\n               <div style=\"font-size: 0.8rem; color: #856404; margin-top: 8px; font-style: italic;\">\n                    Farkli dosyalar icin farkli work offset (G54, G55, ...) secmeniz onerilir.\n               </div>\n          </div>\n     </div>\n     }\n\n     <div class=\"file-list\">\n          <div *ngFor=\"let file of files; let idx = index\"\n               class=\"file-card\">\n               <div class=\"file-content\">\n                    <div class=\"file-controls\">\n                         <button class=\"btn-icon\"\n                                 [disabled]=\"idx === 0\"\n                                 (click)=\"moveUp(idx)\">\n                              <svg class=\"icon-small\"\n                                   viewBox=\"0 0 24 24\"\n                                   fill=\"none\"\n                                   stroke=\"currentColor\"\n                                   stroke-width=\"2\">\n                                   <polyline points=\"18 15 12 9 6 15\"></polyline>\n                              </svg>\n                         </button>\n                         <button class=\"btn-icon\"\n                                 [disabled]=\"idx === files.length - 1\"\n                                 (click)=\"moveDown(idx)\">\n                              <svg class=\"icon-small\"\n                                   viewBox=\"0 0 24 24\"\n                                   fill=\"none\"\n                                   stroke=\"currentColor\"\n                                   stroke-width=\"2\">\n                                   <polyline points=\"6 9 12 15 18 9\"></polyline>\n                              </svg>\n                         </button>\n                    </div>\n\n                    <div class=\"file-info\">\n                         <div class=\"file-name-row\">\n                              <svg class=\"icon-small\"\n                                   viewBox=\"0 0 24 24\"\n                                   fill=\"none\"\n                                   stroke=\"currentColor\"\n                                   stroke-width=\"2\">\n                                   <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\"></path>\n                                   <polyline points=\"14 2 14 8 20 8\"></polyline>\n                              </svg>\n                              <span class=\"file-name\">{{ file.name }}</span>\n                              <span class=\"file-size\">({{ (file.size | toDosyaBoyutu).join(' ') }})</span>\n                         </div>\n                         <div class=\"offset-row\">\n                              <label class=\"offset-label\">Work Offset:</label>\n                              <select class=\"offset-select\"\n                                      [value]=\"file.workOffset\"\n                                      (change)=\"updateOffset(idx, $any($event.target).value)\">\n                                   <option *ngFor=\"let offset of availableOffsets\"\n                                           [value]=\"offset\">{{ offset }}</option>\n                              </select>\n                              <div class=\"ui tag label\"\n                                   [class.teal]=\"file.baglamaYonu=='Uzun Taraf X'\"\n                                   [class.orange]=\"file.baglamaYonu=='Uzun Taraf Y'\">\n                                   {{ file.baglamaYonu }}\n                              </div>\n                              <div class=\"ui tag label\">\n                                   {{ file.kutukZ }}\n                              </div>\n                              <div class=\"ui teal label\">\n                                   {{ file.onMu ? \"Ön İşleme\":\"Arka İşleme\" }}\n                              </div>\n                         </div>\n                         <div class=\"coord-label\">\n                              Xmin\n                              <span class=\"coord-detail\">{{ file.xMin }}</span>\n                         </div>\n                         <div class=\"coord-label\">\n                              Xmax\n                              <span class=\"coord-detail\">{{ file.xMax }}</span>\n                         </div>\n                         <div class=\"coord-label\">\n                              Ymin\n                              <span class=\"coord-detail\">{{ file.yMin }}</span>\n                         </div>\n                         <div class=\"coord-label\">\n                              Ymax\n                              <span class=\"coord-detail\">{{ file.yMax }}</span>\n                         </div>\n                         <div class=\"coord-label\"\n                              [class.z-pulse]=\"zPulseVar(file)\">\n                              Zmin\n                              <span class=\"coord-detail\">{{ file.zMin }}</span>\n                         </div>\n                         <div class=\"coord-label\">\n                              Zmax\n                              <span class=\"coord-detail\">{{ file.zMax }}</span>\n                         </div>\n                         @if (zPulseVar(file)) {\n                         <div class=\"ui red py-2 tag label\">\n                              Eğer Arka İşlem Değil İse Zte Tablaya girebilir.\n                         </div>\n                         }\n                    </div>\n\n                    <div style=\"display: flex; align-items: center;flex-direction: column; gap: 5px; margin-top: 5px;\">\n                         <div class=\"coord-label coord-label-danger\">\n                              Son Z\n                              <span class=\"coord-detail\">{{ getDisplayZLast(file) }}</span>\n                         </div>\n\n                         <input\n                           type=\"number\"\n                           step=\"0.001\"\n                           [value]=\"file.customZLast !== undefined && file.customZLast !== null ? file.customZLast : file.zLast\"\n                           (input)=\"updateCustomZLast(idx, $any($event.target).value)\"\n                           placeholder=\"{{file.zLast}}\"\n                           title=\"Orijinal: {{formatCoordinate(file.zLast)}}\"\n                           style=\"width: 100px; padding: 4px 8px; border: 1px solid #ced4da; border-radius: 3px; font-size: 0.85rem;\"\n                         />\n\n                         @if (file.customZLast !== undefined && file.customZLast !== null && file.customZLast !== file.zLast) {\n                         <div style=\"font-size: 0.7rem; color: #dc3545;\">Orjinal Z: {{formatCoordinate(file.zLast)}}\n                         </div>\n                         }\n                    </div>\n\n                    <button class=\"btn-remove\"\n                            (click)=\"removeFile(idx)\">\n                         <svg class=\"icon-small\"\n                              viewBox=\"0 0 24 24\"\n                              fill=\"none\"\n                              stroke=\"currentColor\"\n                              stroke-width=\"2\">\n                              <line x1=\"18\"\n                                    y1=\"6\"\n                                    x2=\"6\"\n                                    y2=\"18\"></line>\n                              <line x1=\"6\"\n                                    y1=\"6\"\n                                    x2=\"18\"\n                                    y2=\"18\"></line>\n                         </svg>\n                    </button>\n               </div>\n          </div>\n     </div>\n</div>\n\n<!-- Controls -->\n<div *ngIf=\"files.length > 0\"\n     class=\"controls-section\">\n     <div class=\"controls-content\">\n          <div class=\"program-number\">\n               <label class=\"control-label\">Program No:</label>\n               <input\n           type=\"number\"\n           class=\"number-input\"\n           [(ngModel)]=\"programNumber\"\n           [disabled]=\"mergeInProgress\">\n          </div>\n\n          <button class=\"btn-primary\"\n                  (click)=\"mergePosts()\"\n                  [disabled]=\"mergeInProgress\">\n               <svg class=\"icon-small\"\n                    viewBox=\"0 0 24 24\"\n                    fill=\"none\"\n                    stroke=\"currentColor\"\n                    stroke-width=\"2\">\n                    <polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\"></polygon>\n               </svg>\n               {{ mergeInProgress ? 'Isleniyor...' : 'Birlestir' }}\n          </button>\n          <span style=\"flex:1\"></span>\n          <span style=\"margin-right: 15px; display: flex; align-items: center; gap: 8px;\">\n               <span style=\"font-size: 0.85rem; color: #475569;\">\n                    Limit Kontrol Gezisi {{ limitKontrolYap ? 'Yapilacak' : 'Yapilmayacak' }}\n               </span>\n               <nz-switch [(ngModel)]=\"limitKontrolYap\"\n                          nzCheckedChildren=\"🎯\"\n                          nzUnCheckedChildren=\"✖\"></nz-switch>\n          </span>\n          <span style=\"display: flex; align-items: center; gap: 8px;\">\n               <span style=\"font-size: 0.85rem; color: #475569;\">\n                    Programin Basina Basliklari {{ basliklariYaz ? 'Yazicak' : 'Yazmicak' }}\n               </span>\n               <nz-switch [(ngModel)]=\"basliklariYaz\"\n                          nzCheckedChildren=\"💭\"\n                          nzUnCheckedChildren=\"✖\"></nz-switch>\n          </span>\n     </div>\n</div>\n<div *ngIf=\"mergeInProgress\"\n     class=\"merge-progress-container\">\n     <div class=\"merge-progress-header\">\n          <div class=\"spinner1\"></div>\n          <h3 class=\"merge-title\">Birlestirme Islemi Devam Ediyor</h3>\n     </div>\n     <div class=\"merge-status\">{{ mergeStatus }}</div>\n     <div class=\"merge-progress-bar\">\n          <div class=\"merge-progress-fill\"\n               [style.width.%]=\"mergeProgress\"></div>\n     </div>\n     <div class=\"merge-percent\">{{ mergeProgress }}%</div>\n</div>\n\n<!-- Result -->\n<div *ngIf=\"mergedResult\"\n     class=\"result-section\">\n     <h2 class=\"section-title\">\n          <svg class=\"icon-check\"\n               viewBox=\"0 0 24 24\"\n               fill=\"none\"\n               stroke=\"currentColor\"\n               stroke-width=\"2\">\n               <path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"></path>\n               <polyline points=\"22 4 12 14.01 9 11.01\"></polyline>\n          </svg>\n          Birlestirilmis Program\n     </h2>\n     <div class=\"coord-label\">\n          Xmin\n          <span class=\"coord-detail\">{{ mergedBounds.xMin }}</span>\n     </div>\n     <div class=\"coord-label\">\n          Xmax\n          <span class=\"coord-detail\">{{ mergedBounds.xMax }}</span>\n     </div>\n     <div class=\"coord-label\">\n          Ymin\n          <span class=\"coord-detail\">{{ mergedBounds.yMin }}</span>\n     </div>\n     <div class=\"coord-label\">\n          Ymax\n          <span class=\"coord-detail\">{{ mergedBounds.yMax }}</span>\n     </div>\n     <div class=\"coord-label\">\n          Zmin\n          <span class=\"coord-detail\">{{ mergedBounds.zMin }}</span>\n     </div>\n     <div class=\"coord-label mb-3\">\n          Zmax\n          <span class=\"coord-detail\">{{ mergedBounds.zMax }}</span>\n     </div>\n     <textarea class=\"result-textarea\"\n               [value]=\"getFirstNLines(mergedResult,100)+ '\\n'+ '... Devami Dosyaya Yazilacak ...'\"\n               readonly\n               rows=\"20\">\n       </textarea>\n     <div class=\"program-number p-2\"\n          style=\"width: 100%;display: flex;\">\n          <label class=\"control-label\">Program Ismi:</label>\n          <input\n     type=\"text\"\n     class=\"number-input flex-1\"\n\n     [(ngModel)]=\"programIsmi\"\n     [disabled]=\"mergeInProgress\">\n     </div>\n\n     <nz-row nzJustify=\"space-between\"\n             nzAlign=\"middle\">\n          <nz-col>\n               <button class=\"btn-success\"\n                       (click)=\"downloadMerged()\"\n                       [disabled]=\"mergeInProgress\">\n                    <svg class=\"icon-small\"\n                         viewBox=\"0 0 24 24\"\n                         fill=\"none\"\n                         stroke=\"currentColor\"\n                         stroke-width=\"2\">\n                         <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"></path>\n                         <polyline points=\"7 10 12 15 17 10\"></polyline>\n                         <line x1=\"12\"\n                               y1=\"15\"\n                               x2=\"12\"\n                               y2=\"3\"></line>\n                    </svg>\n                    Indir\n               </button>\n          </nz-col>\n\n          <nz-col>\n               <div style=\"position: relative; display: inline-block; width: 200px;\">\n                    <button class=\"btn-primary\"\n                            (click)=\"postYolla()\"\n                            [disabled]=\"postYollamaMesgul\"\n                            style=\"width: 100%; padding-bottom: 10px; position: relative; overflow: hidden;\">\n                         <svg class=\"icon-small\"\n                              viewBox=\"0 0 24 24\"\n                              fill=\"none\"\n                              stroke=\"currentColor\"\n                              stroke-width=\"2\">\n                              <polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\"></polygon>\n                         </svg>\n                         {{ mergeInProgress ? 'Post Klasorune Yolla...' : 'Post Klasorune Yolla' }}\n\n                         <!-- Progress bar buton icinde, altta -->\n                         @if (postYollamaMesgul) {\n                         <nz-progress [nzPercent]=\"postYollaniyor\"\n                                      nzSize=\"small\"\n                                      [nzShowInfo]=\"false\"\n                                      style=\"position: absolute; bottom: -5px; left: 0; right:0;\">\n                         </nz-progress>\n                         }\n                    </button>\n               </div>\n          </nz-col>\n     </nz-row>\n</div>\n</div>\n</file_content>\n\n<file_content path=\"fikoyt-sistem/src/app/uygulamalar/post-birlestiricisi/post-birlestiricisi.component.less\">\n:host {\n  display: block;\n  background: #e6e6e6;\n  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n}\n\n.container {\n  min-height: 100vh;\n  padding: 2rem 1rem;\n}\n\n.header {\n  text-align: center;\n  margin-bottom: 2rem;\n  animation: fadeIn 0.5s ease-out;\n}\n\n.header-content {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  gap: 0.75rem;\n  margin-bottom: 0.75rem;\n}\n\n.header-content h1 {\n  font-size: 2.25rem;\n  font-weight: 700;\n  color: #1e293b;\n  margin: 0;\n}\n\n.icon-large {\n  width: 2.5rem;\n  height: 2.5rem;\n  color: #3b82f6;\n}\n\n.icon-zap {\n  width: 2rem;\n  height: 2rem;\n  color: #f59e0b;\n}\n\n.subtitle {\n  color: #64748b;\n  font-size: 1.125rem;\n  margin: 0;\n}\n\n.upload-area {\n  max-width: 72rem;\n  margin: 0 auto 2rem;\n  border: 2px dashed #cbd5e1;\n  border-radius: 1rem;\n  padding: 3rem;\n  text-align: center;\n  cursor: pointer;\n  background: white;\n  transition: all 0.3s ease;\n  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.upload-area:hover {\n  border-color: #3b82f6;\n  box-shadow: 0 4px 12px rgba(59, 130, 246, 0.15);\n}\n\n.upload-area.dragging {\n  border-color: #3b82f6;\n  background: #eff6ff;\n  transform: scale(1.01);\n  box-shadow: 0 8px 24px rgba(59, 130, 246, 0.2);\n}\n\n.upload-icon {\n  width: 2rem;\n  height: 2rem;\n  margin: 0 auto 1rem;\n  color: #3b82f6;\n  transition: all 0.3s ease;\n}\n\n.upload-icon.bounce {\n  animation: bounce 0.5s infinite;\n}\n\n.upload-title {\n  font-size: 1.25rem;\n  color: #1e293b;\n  font-weight: 600;\n  margin: 0 0 0.5rem 0;\n}\n\n.upload-subtitle {\n  color: #64748b;\n  margin: 0;\n}\n\n.progress-container {\n  max-width: 72rem;\n  margin: 0 auto 1.5rem;\n  background: white;\n  border: 1px solid #e2e8f0;\n  border-radius: 0.75rem;\n  padding: 1rem;\n  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.progress-info {\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  margin-bottom: 0.5rem;\n}\n\n.progress-filename {\n  color: #475569;\n  font-size: 0.875rem;\n  font-weight: 500;\n}\n\n.progress-percent {\n  color: #3b82f6;\n  font-weight: 600;\n}\n\n.progress-bar {\n  width: 100%;\n  height: 0.75rem;\n  background: #f1f5f9;\n  border-radius: 9999px;\n  overflow: hidden;\n}\n\n.progress-fill {\n  height: 100%;\n  background: linear-gradient(90deg, #3b82f6 0%, #60a5fa 100%);\n  transition: width 0.2s ease;\n  border-radius: 9999px;\n}\n\n.files-section, .controls-section, .result-section {\n  max-width: 72rem;\n  margin: 0 auto 1.5rem;\n  background: white;\n  border: 1px solid #e2e8f0;\n  border-radius: 1rem;\n  padding: 1.5rem;\n  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.section-header {\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  margin-bottom: 1rem;\n  flex-wrap: wrap;\n  gap: 1rem;\n}\n\n.section-title {\n  font-size: 1.5rem;\n  font-weight: 700;\n  color: #1e293b;\n  display: flex;\n  align-items: center;\n  gap: 0.5rem;\n  margin: 0;\n}\n\n.icon-check {\n  width: 1.5rem;\n  height: 1.5rem;\n  color: #10b981;\n}\n\n.icon-small {\n  width: 1.25rem;\n  height: 1.25rem;\n}\n\n.btn-danger {\n  display: flex;\n  align-items: center;\n  gap: 0.5rem;\n  padding: 0.5rem 1rem;\n  background: #ef4444;\n  color: white;\n  border: none;\n  border-radius: 0.5rem;\n  font-weight: 500;\n  cursor: pointer;\n  transition: all 0.2s ease;\n  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-danger:hover {\n  background: #dc2626;\n  transform: translateY(-1px);\n  box-shadow: 0 4px 6px rgba(239, 68, 68, 0.2);\n}\n\n.file-list {\n  display: flex;\n  flex-direction: column;\n  gap: 0.75rem;\n}\n\n.file-card {\n  background: #f8fafc;\n  border: 1px solid #e2e8f0;\n  border-radius: 0.75rem;\n  padding: 1rem;\n  transition: all 0.2s ease;\n}\n\n.file-card:hover {\n  border-color: #3b82f6;\n  box-shadow: 0 2px 8px rgba(59, 130, 246, 0.1);\n}\n\n.file-content {\n  display: flex;\n  align-items: center;\n  gap: 1rem;\n}\n\n.file-controls {\n  display: flex;\n  flex-direction: column;\n  gap: 0.25rem;\n}\n\n.btn-icon {\n  padding: 0.25rem;\n  background: transparent;\n  border: 1px solid #e2e8f0;\n  border-radius: 0.25rem;\n  cursor: pointer;\n  color: #64748b;\n  transition: all 0.2s ease;\n}\n\n.btn-icon:hover:not(:disabled) {\n  background: #3b82f6;\n  color: white;\n  border-color: #3b82f6;\n}\n\n.btn-icon:disabled {\n  opacity: 0.3;\n  cursor: not-allowed;\n}\n\n.file-info {\n  flex: 1;\n}\n\n.file-name-row {\n  display: flex;\n  align-items: center;\n  gap: 0.75rem;\n  margin-bottom: 0.5rem;\n}\n\n.file-name {\n  color: #1e293b;\n  font-weight: 600;\n}\n\n.file-size {\n  color: #64748b;\n  font-size: 0.875rem;\n}\n\n.offset-row {\n  display: flex;\n  align-items: center;\n  gap: 0.5rem;\n}\n\n.offset-label {\n  color: #475569;\n  font-size: 0.875rem;\n  font-weight: 500;\n}\n\n.offset-select {\n  background: white;\n  color: #1e293b;\n  border: 1px solid #cbd5e1;\n  border-radius: 0.375rem;\n  padding: 0.375rem 0.75rem;\n  font-size: 0.875rem;\n  cursor: pointer;\n  transition: all 0.2s ease;\n}\n\n.offset-select:hover {\n  border-color: #3b82f6;\n}\n\n.offset-select:focus {\n  outline: none;\n  border-color: #3b82f6;\n  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n}\n\n.coord-label {\n  display: inline-block;\n  background: #e5e7eb;\n  border: 1px solid #d1d5db;\n  border-radius: 4px;\n  padding: 2px 8px;\n  font-size: 0.8rem;\n  color: #374151;\n  margin: 2px;\n}\n\n.coord-label-danger {\n  background: #fee2e2;\n  border-color: #fca5a5;\n  color: #dc2626;\n}\n\n/* Tehlikeli Z bandi (+2 ile -70 arasi): Z degerleri pulse animasyonu ile vurgulanir */\n.z-pulse {\n  animation: zDegerPulse 1.2s ease-in-out infinite;\n  background: red;\n  color:white !important;\n  font-weight:bold;\n}\n\n@keyframes zDegerPulse {\n  0%,\n  100% {\n    color: #dc2626;\n    text-shadow: none;\n    transform: scale(1);\n  }\n  50% {\n    color: #ff0000;\n    text-shadow: 0 0 6px rgba(220, 38, 38, 0.6);\n    transform: scale(1.08);\n  }\n}\n\n.coord-detail {\n  font-weight: 600;\n  margin-left: 4px;\n}\n\n.btn-remove {\n  padding: 0.5rem;\n  background: transparent;\n  border: 1px solid #e2e8f0;\n  border-radius: 0.5rem;\n  cursor: pointer;\n  color: #ef4444;\n  transition: all 0.2s ease;\n}\n\n.btn-remove:hover {\n  background: #fef2f2;\n  border-color: #ef4444;\n  transform: scale(1.05);\n}\n\n.controls-content {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 1rem;\n  align-items: center;\n}\n\n.program-number {\n  display: flex;\n  align-items: center;\n  gap: 0.75rem;\n}\n\n.control-label {\n  color: #1e293b;\n  font-weight: 600;\n}\n\n.number-input {\n  background: white;\n  color: #1e293b;\n  border: 1px solid #cbd5e1;\n  border-radius: 0.5rem;\n  padding: 0.5rem 1rem;\n  width: 8rem;\n  font-size: 1rem;\n  transition: all 0.2s ease;\n}\n\n.number-input:focus {\n  outline: none;\n  border-color: #3b82f6;\n  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n}\n\n.number-input:disabled {\n  opacity: 0.5;\n  cursor: not-allowed;\n  background: #f1f5f9;\n}\n\n.btn-primary, .btn-success {\n  display: flex;\n  align-items: center;\n  gap: 0.5rem;\n  padding: 0.75rem 1.5rem;\n  border: none;\n  border-radius: 0.5rem;\n  font-weight: 600;\n  cursor: pointer;\n  transition: all 0.2s ease;\n  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.btn-primary {\n  background: #3b82f6;\n  color: white;\n}\n\n.btn-primary:hover:not(:disabled) {\n  background: #2563eb;\n  transform: translateY(-1px);\n  box-shadow: 0 4px 6px rgba(59, 130, 246, 0.2);\n}\n\n.btn-success {\n  background: #10b981;\n  color: white;\n}\n\n.btn-success:hover:not(:disabled) {\n  background: #059669;\n  transform: translateY(-1px);\n  box-shadow: 0 4px 6px rgba(16, 185, 129, 0.2);\n}\n\n.btn-primary:disabled, .btn-success:disabled {\n  opacity: 0.5;\n  cursor: not-allowed;\n  transform: none;\n}\n\n.btn-primary:disabled:hover, .btn-success:disabled:hover {\n  transform: none;\n}\n\n/* Merge Progress Styles */\n.merge-progress-container {\n  max-width: 72rem;\n  margin: 0 auto 1.5rem;\n  background: white;\n  border: 2px solid #3b82f6;\n  border-radius: 1rem;\n  padding: 2rem;\n  box-shadow: 0 4px 12px rgba(59, 130, 246, 0.15);\n}\n\n.merge-progress-header {\n  display: flex;\n  align-items: center;\n  gap: 1rem;\n  margin-bottom: 1rem;\n}\n\n.spinner1 {\n  width: 2rem;\n  height: 2rem;\n  border: 3px solid #dbeafe;\n  border-top-color: #3b82f6;\n  border-radius: 50%;\n  animation: spin 0.8s linear infinite;\n}\n\n@keyframes spin {\n  to { transform: rotate(360deg); }\n}\n\n.merge-title {\n  font-size: 1.25rem;\n  font-weight: 700;\n  color: #1e293b;\n  margin: 0;\n}\n\n.merge-status {\n  color: #475569;\n  font-size: 0.875rem;\n  margin-bottom: 0.75rem;\n  font-weight: 500;\n}\n\n.merge-progress-bar {\n  width: 100%;\n  height: 1.5rem;\n  background: #f1f5f9;\n  border-radius: 9999px;\n  overflow: hidden;\n  margin-bottom: 0.5rem;\n  border: 1px solid #e2e8f0;\n}\n\n.merge-progress-fill {\n  height: 100%;\n  background: linear-gradient(90deg, #3b82f6 0%, #60a5fa 50%, #3b82f6 100%);\n  background-size: 200% 100%;\n  transition: width 0.3s ease;\n  border-radius: 9999px;\n  animation: shimmer 2s infinite;\n}\n\n@keyframes shimmer {\n  0% { background-position: 200% 0; }\n  100% { background-position: -200% 0; }\n}\n\n.merge-percent {\n  text-align: right;\n  color: #3b82f6;\n  font-weight: 700;\n  font-size: 1.125rem;\n}\n\n.result-textarea {\n  width: 100%;\n  background: #f8fafc;\n  color: #059669;\n  font-family: 'Courier New', monospace;\n  font-size: 0.875rem;\n  padding: 1rem;\n  border: 1px solid #e2e8f0;\n  border-radius: 0.5rem;\n  resize: vertical;\n}\n\n.result-textarea:focus {\n  outline: none;\n  border-color: #3b82f6;\n  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n}\n\n// Utility classes\n.mb-2 { margin-bottom: 0.5rem; }\n.mb-3 { margin-bottom: 1rem; }\n.p-2 { padding: 0.5rem; }\n.flex-1 { flex: 1; }\n\n@keyframes fadeIn {\n  from {\n    opacity: 0;\n    transform: translateY(-10px);\n  }\n  to {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n\n@keyframes bounce {\n  0%, 100% {\n    transform: translateY(0);\n  }\n  50% {\n    transform: translateY(-10px);\n  }\n}\n\n</file_content>\n\n<file_content path=\"fikoyt-sistem/src/app/uygulamalar/post-birlestiricisi/post-birlestiricisi.component.ts\">\nimport { DosyaBoyutuPipe } from './pipes/dosya-boyutu.pipe';\nimport { CommonModule } from '@angular/common';\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { HttpClient, HttpEventType } from '@angular/common/http';\nimport { NzProgressComponent } from \"ng-zorro-antd/progress\";\nimport { FileBrowserService } from './services/file-browser.service';\nimport { NzPaginationComponent } from 'ng-zorro-antd/pagination';\nimport { NzGridModule } from 'ng-zorro-antd/grid';\nimport { NzSwitchModule } from 'ng-zorro-antd/switch';\nimport { NzButtonModule } from 'ng-zorro-antd/button';\n\ninterface PostFile {\n  id: string;\n  name: string;\n  cleanedContent: string;\n  workOffset: string;\n  size: number;\n  xMin: number | null;\n  xMax: number | null;\n  yMin: number | null;\n  yMax: number | null;\n  zMin: number | null;\n  zMax: number | null;\n  zLast: number | null;\n  customZLast?: number | null;\n  kutukZ?: number | null;\n  baglamaYonu?: string | null;\n  onMu?: boolean | null;\n}\n\ninterface RecentFile {\n  name: string;\n  url: string;\n  size: number;\n  date_modified: string;\n  selected: boolean;\n  progress: number;\n  progressVisible: boolean;\n  mesgul: boolean;\n}\n\ninterface NcMove {\n  from: { x: number; y: number; z: number };\n  to: { x: number; y: number; z: number };\n  distance: number;\n  mode: 'G0' | 'G1';\n  feed: number;\n  time: number;\n}\n\ninterface NcTimeResult {\n  totalTimeMin: number;\n  totalTimeSec: number;\n  rapidTimeMin: number;\n  rapidTimeSec: number;\n  cuttingTimeMin: number;\n  cuttingTimeSec: number;\n  totalMoves: number;\n  moves: NcMove[];\n}\n\ninterface Bounds {\n  xMin: number | null;\n  xMax: number | null;\n  yMin: number | null;\n  yMax: number | null;\n  zMin: number | null;\n  zMax: number | null;\n  zLast: number | null;\n}\n\n@Component({\n  selector: 'app-post-birlestiricisi',\n  standalone: true,\n  imports: [\n    CommonModule,\n    FormsModule,\n    DosyaBoyutuPipe,\n    NzProgressComponent,\n    NzPaginationComponent,\n    NzGridModule,\n    NzSwitchModule,\n    NzButtonModule\n  ],\n  templateUrl: './post-birlestiricisi.component.html',\n  styleUrls: ['./post-birlestiricisi.component.less'],\n  providers: [FileBrowserService],\n  changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class PostBirlestiricisiComponent {\n  files: PostFile[] = [];\n  readonly availableOffsets = ['G54', 'G55', 'G56', 'G57', 'G58', 'G59', 'G59.1', 'G59.2', 'G59.3', 'G59.4', 'G59.5', 'G59.6'] as const;\n  mergedResult = '';\n  mergedBounds: Bounds = this.createEmptyBounds();\n  programNumber = 1000;\n  programIsmi = \"BIRLESIK\";\n  readonly headerLines = ['G90', 'G40', 'G80'] as const;\n\n  isDragging = false;\n  progressVisible = false;\n  progressPercent = 0;\n  currentFileName = '';\n\n  mergeInProgress = false;\n  mergeProgress = 0;\n  mergeStatus = '';\n\n  recentFiles: RecentFile[] = [];\n  showRecentFiles = false;\n  loadingRecentFiles = false;\n  recentFilesError = '';\n\n  basliklariYaz: boolean = true;\n  limitKontrolYap: boolean = true;\n\n  total = 0;\n  pageIndex = 1;\n  pageSize = 5;\n\n  postYollaniyor = 0;\n  postYollamaMesgul = false;\n\n\n\n  // Regex patterns - compile once\n  private readonly gCodePattern = /G(\\d+)/g;\n  private readonly fPattern = /F([\\d.]+)/;\n  private readonly xPattern = /X(-?\\d+\\.?\\d*)/i;\n  private readonly yPattern = /Y(-?\\d+\\.?\\d*)/i;\n  private readonly zPattern = /Z(-?\\d+\\.?\\d*)/i;\n  private readonly commentPattern = /\\([^)]*\\)/g;\n  private readonly workOffsetPattern = /G5[4-9](\\.\\d+)?/gi;\n\n  constructor(\n    private http: HttpClient,\n    public everything: FileBrowserService,\n    private CD: ChangeDetectorRef\n  ) { }\n\n  ngAfterViewInit() {\n    setTimeout(() => this.loadRecentFiles(), 0);\n  }\n\n  // Event Handlers\n  onDrop(event: DragEvent) {\n    event.preventDefault();\n    this.isDragging = false;\n    const dt = event.dataTransfer;\n    if (dt?.files) {\n      this.readMultipleFiles(dt.files);\n    }\n  }\n\n  onDragOver(event: DragEvent) {\n    event.preventDefault();\n    this.isDragging = true;\n  }\n\n  onDragLeave(event: DragEvent) {\n    event.preventDefault();\n    this.isDragging = false;\n  }\n\n  onFileInputChange(event: Event) {\n    const input = event.target as HTMLInputElement;\n    if (input.files) {\n      this.readMultipleFiles(input.files);\n      input.value = '';\n    }\n  }\n\n  // Recent Files\n  async loadRecentFiles() {\n    this.showRecentFiles = true;\n    this.loadingRecentFiles = true;\n    this.recentFilesError = '';\n    this.degisti();\n\n    try {\n      const response: any = await this.everything.search(\"*.nc\", this.pageIndex - 1, this.pageSize);\n      this.total = response.total;\n\n      if (response?.files && Array.isArray(response.files)) {\n        this.recentFiles = response.files.map((file: any) => ({\n          name: file.name || '',\n          url: `${file.path || ''}/${file.name || ''}`,\n          size: parseInt(file.size || 0) || 0,\n          date_modified: file.dateModified,\n          selected: false,\n          progress: 0,\n          progressVisible: false,\n          mesgul: false\n        }));\n      } else {\n        this.recentFilesError = 'Dosya listesi alinamadi';\n      }\n    } catch (error: any) {\n      console.error('Recent files loading error:', error);\n      this.recentFilesError = error.status === 0\n        ? 'Baglanti hatasi - HTTPS sitesinden HTTP endpoint\\'e erisilemez.'\n        : `Dosyalar yuklenirken hata olustu: ${error.message || ''}`;\n    } finally {\n      this.loadingRecentFiles = false;\n      this.degisti();\n    }\n  }\n\n  toggleRecentFile(file: RecentFile) {\n    file.selected = !file.selected;\n    this.degisti();\n  }\n\n  async addSelectedRecentFiles() {\n    const selectedFiles = this.recentFiles.filter(f => f.selected);\n    if (!selectedFiles.length) return;\n\n    this.loadingRecentFiles = true;\n    this.degisti();\n\n    try {\n      for (const recentFile of selectedFiles) {\n        this.subscribeToFileDownload(recentFile);\n      }\n    } finally {\n      this.loadingRecentFiles = false;\n      this.showRecentFiles = false;\n      this.recentFiles = [];\n      this.progressVisible = false;\n      this.degisti();\n    }\n  }\n\n  async addFileFromUrl(recentFile: RecentFile) {\n    recentFile.progressVisible = true;\n    recentFile.progress = 0;\n    recentFile.mesgul = true;\n    this.degisti();\n\n    this.subscribeToFileDownload(recentFile, () => {\n      setTimeout(() => {\n        recentFile.progressVisible = false;\n        recentFile.mesgul = false;\n        this.degisti();\n      }, 750);\n    });\n  }\n\n  private subscribeToFileDownload(recentFile: RecentFile, onComplete?: () => void) {\n    this.http.get(`https://fikoyt.com:9000/uyar/admin/everything/file/${recentFile.url}`, {\n      responseType: 'blob',\n      reportProgress: true,\n      observe: 'events'\n    }).subscribe({\n      next: async (event) => {\n        if (event.type === HttpEventType.DownloadProgress) {\n          recentFile.progress = Math.round((event.loaded / (event.total || event.loaded)) * 100);\n          this.degisti();\n        } else if (event.type === HttpEventType.Response) {\n          const response = event.body as Blob;\n          const file = new File([response], recentFile.name, { type: 'text/plain' });\n          const postFile = await this.readFile(file);\n          this.files = [...this.files, postFile];\n          this.degisti();\n          onComplete?.();\n        }\n      },\n      error: (error) => {\n        console.error(`Error loading ${recentFile.name}:`, error);\n        recentFile.progressVisible = false;\n        recentFile.progress = 0;\n        recentFile.mesgul = false;\n        this.degisti();\n      }\n    });\n  }\n\n  cancelRecentFiles() {\n    this.showRecentFiles = false;\n    this.recentFiles = [];\n    this.degisti();\n  }\n\n  // File Reading\n  private async readMultipleFiles(fileList: FileList) {\n    const tasks: Promise<PostFile>[] = [];\n    for (let i = 0; i < fileList.length; i++) {\n      const f = fileList.item(i);\n      if (f) tasks.push(this.readFile(f));\n    }\n\n    const results = await Promise.all(tasks);\n    this.files = [...this.files, ...results];\n    this.progressVisible = false;\n\n    for (let i = 0; i < this.files.length; i++) {\n      const f = this.files[i];\n      f.kutukZ = this.tahminiKutukZ(f);\n      f.baglamaYonu = this.baglamaYonu(f);\n      f.onMu = this.OnIsl(f);\n    }\n\n    this.degisti();\n  }\n\n  private async readFile(file: File): Promise<PostFile> {\n    this.progressVisible = false;\n    this.progressPercent = 0;\n    this.currentFileName = file.name;\n    this.degisti();\n\n    const reader = file.stream().getReader();\n    const decoder = new TextDecoder(\"utf-8\");\n    let { value, done } = await reader.read();\n    let buffer = '';\n    const cleaned: string[] = [];\n    let loadedBytes = 0;\n    const totalBytes = file.size;\n    const bounds = this.createEmptyBounds();\n\n    while (!done) {\n      buffer += decoder.decode(value, { stream: true });\n      loadedBytes += value?.length || 0;\n\n      this.progressPercent = Math.min(100, Math.floor((loadedBytes / totalBytes) * 100));\n      this.degisti();\n\n      const lines = buffer.split(/\\r?\\n/);\n      buffer = lines.pop() || '';\n\n      this.processLines(lines, cleaned, bounds);\n\n      ({ value, done } = await reader.read());\n    }\n\n    if (buffer.trim()) {\n      this.processLines([buffer.trim()], cleaned, bounds);\n    }\n\n    const finalLines = this.removeProgramEnd(cleaned);\n\n    this.progressVisible = false;\n    this.progressPercent = 0;\n    this.degisti();\n\n    return {\n      id: this.makeId(),\n      name: file.name,\n      cleanedContent: finalLines.join('\\n'),\n      workOffset: this.availableOffsets[0],\n      size: file.size,\n      ...bounds\n    };\n  }\n\n  private processLines(lines: string[], cleaned: string[], bounds: Bounds) {\n    for (let line of lines) {\n      line = line.trim();\n      if (!line || line[0] === 'O' || line[0] === '%') continue;\n      if (line.startsWith('M30') || line.startsWith('M99')) continue;\n\n      if (line.includes('(')) {\n        line = line.replace('(', '//(');\n      }\n\n      this.extractCoordinates(line, bounds);\n\n      line = line.replace(this.workOffsetPattern, '').replace(/\\s+/g, ' ').trim();\n      if (line) cleaned.push(line);\n    }\n  }\n\n  private extractCoordinates(line: string, bounds: Bounds) {\n    let cleanLine = line\n      .replace(this.commentPattern, '')\n      .replace(/\\/\\/.*$/, '');\n\n    const xMatch = cleanLine.match(this.xPattern);\n    if (xMatch) {\n      const x = parseFloat(xMatch[1]);\n      if (!isNaN(x)) {\n        bounds.xMin = bounds.xMin === null ? x : Math.min(bounds.xMin, x);\n        bounds.xMax = bounds.xMax === null ? x : Math.max(bounds.xMax, x);\n      }\n    }\n\n    const yMatch = cleanLine.match(this.yPattern);\n    if (yMatch) {\n      const y = parseFloat(yMatch[1]);\n      if (!isNaN(y)) {\n        bounds.yMin = bounds.yMin === null ? y : Math.min(bounds.yMin, y);\n        bounds.yMax = bounds.yMax === null ? y : Math.max(bounds.yMax, y);\n      }\n    }\n\n    const zMatch = cleanLine.match(this.zPattern);\n    if (zMatch) {\n      const z = parseFloat(zMatch[1]);\n      if (!isNaN(z)) {\n        bounds.zMin = bounds.zMin === null ? z : Math.min(bounds.zMin, z);\n        bounds.zMax = bounds.zMax === null ? z : Math.max(bounds.zMax, z);\n        bounds.zLast = z;\n      }\n    }\n  }\n\n  private removeProgramEnd(lines: string[]): string[] {\n    while (lines.length) {\n      const t = lines[lines.length - 1].trim();\n      if (/^N\\d+\\s+M(2|5|30)\\b/i.test(t) || /^M(2|5|30)$/i.test(t)) {\n        lines.pop();\n      } else {\n        break;\n      }\n    }\n    return lines;\n  }\n\n  private makeId(): string {\n    return Math.random().toString(36).slice(2, 11);\n  }\n\n  // File Management\n  moveUp(index: number) {\n    if (index <= 0) return;\n    [this.files[index - 1], this.files[index]] = [this.files[index], this.files[index - 1]];\n    this.files = [...this.files];\n    this.clearMerge();\n  }\n\n  moveDown(index: number) {\n    if (index >= this.files.length - 1) return;\n    [this.files[index], this.files[index + 1]] = [this.files[index + 1], this.files[index]];\n    this.files = [...this.files];\n    this.clearMerge();\n  }\n\n  removeFile(index: number) {\n    this.files.splice(index, 1);\n    this.files = [...this.files];\n    this.clearMerge();\n  }\n\n  updateOffset(index: number, offset: string) {\n    this.files[index].workOffset = offset;\n    this.files = [...this.files];\n    this.clearMerge();\n  }\n\n  private clearMerge() {\n    this.mergedResult = '';\n    this.resetMergedBounds();\n    this.degisti();\n  }\n\n  // NC Time Calculation\n  calculateNcTime(\n    ncCode: string,\n    rapidFeed: number = 15000,\n    defaultFeed: number = 1000\n  ): NcTimeResult {\n    const lines = ncCode.trim().split('\\n');\n    let currentX = 0.0, currentY = 0.0, currentZ = 0.0;\n    let currentFeed = defaultFeed;\n    let currentMode: 'G0' | 'G1' = 'G0';\n    let totalTime = 0.0, rapidTime = 0.0, cuttingTime = 0.0;\n    const moves: NcMove[] = [];\n\n    for (const line of lines) {\n      const cleanLine = line.replace(this.commentPattern, '').trim();\n      if (!cleanLine) continue;\n\n      const gMatches = cleanLine.matchAll(this.gCodePattern);\n      for (const match of gMatches) {\n        const gCode = match[1];\n        if (gCode === '0' || gCode === '00') currentMode = 'G0';\n        else if (gCode === '1' || gCode === '01') currentMode = 'G1';\n      }\n\n      const fMatch = cleanLine.match(this.fPattern);\n      if (fMatch) currentFeed = parseFloat(fMatch[1]);\n\n      const xMatch = cleanLine.match(this.xPattern);\n      const yMatch = cleanLine.match(this.yPattern);\n      const zMatch = cleanLine.match(this.zPattern);\n\n      const newX = xMatch ? parseFloat(xMatch[1]) : currentX;\n      const newY = yMatch ? parseFloat(yMatch[1]) : currentY;\n      const newZ = zMatch ? parseFloat(zMatch[1]) : currentZ;\n\n      if (xMatch || yMatch || zMatch) {\n        const distance = Math.sqrt(\n          Math.pow(newX - currentX, 2) +\n          Math.pow(newY - currentY, 2) +\n          Math.pow(newZ - currentZ, 2)\n        );\n\n        const moveTime = currentMode === 'G0' ? distance / rapidFeed : distance / currentFeed;\n        totalTime += moveTime;\n        if (currentMode === 'G0') rapidTime += moveTime;\n        else cuttingTime += moveTime;\n\n        moves.push({\n          from: { x: currentX, y: currentY, z: currentZ },\n          to: { x: newX, y: newY, z: newZ },\n          distance,\n          mode: currentMode,\n          feed: currentMode === 'G0' ? rapidFeed : currentFeed,\n          time: moveTime\n        });\n\n        currentX = newX;\n        currentY = newY;\n        currentZ = newZ;\n      }\n    }\n\n    return {\n      totalTimeMin: totalTime,\n      totalTimeSec: totalTime * 60,\n      rapidTimeMin: rapidTime,\n      rapidTimeSec: rapidTime * 60,\n      cuttingTimeMin: cuttingTime,\n      cuttingTimeSec: cuttingTime * 60,\n      totalMoves: moves.length,\n      moves\n    };\n  }\n\n  getTimeReport(result: NcTimeResult): string {\n    const sep = '='.repeat(60);\n    return `${sep}\\nNC KOD SURE ANALIZI\\n${sep}\\n\\n` +\n      `Toplam Sure:\\n  ${result.totalTimeMin.toFixed(3)} dakika\\n  ${result.totalTimeSec.toFixed(2)} saniye\\n\\n` +\n      `Hizli Hareket (G0) Suresi:\\n  ${result.rapidTimeMin.toFixed(3)} dakika\\n  ${result.rapidTimeSec.toFixed(2)} saniye\\n\\n` +\n      `Kesme (G1) Suresi:\\n  ${result.cuttingTimeMin.toFixed(3)} dakika\\n  ${result.cuttingTimeSec.toFixed(2)} saniye\\n\\n` +\n      `Toplam Hareket Sayisi: ${result.totalMoves}\\n${sep}`;\n  }\n\n  // Merge Logic\n  mergePosts() {\n    if (!this.files.length) {\n      this.clearMerge();\n      return;\n    }\n\n    this.mergeInProgress = true;\n    this.mergeProgress = 0;\n    this.mergeStatus = 'Birlestirme baslatiliyor...';\n    this.degisti();\n\n    setTimeout(() => scrollTo({ left: 0, top: document.body.scrollHeight, behavior: 'smooth' }), 500);\n\n    setTimeout(() => this.executeMerge(), 200);\n  }\n\n  updateCustomZLast(index: number, value: string) {\n    const numValue = parseFloat(value);\n    if (!isNaN(numValue)) {\n      this.files[index].customZLast = numValue;\n    } else {\n      this.files[index].customZLast = null;\n    }\n    this.clearMerge();\n    this.degisti();\n  }\n\n  getDisplayZLast(file: PostFile): number | null {\n    return file.customZLast !== undefined && file.customZLast !== null\n      ? file.customZLast\n      : file.zLast;\n  }\n\n  /**\n   * Tehlikeli Z bandi kontrolu:\n   * Dosyanin en derin noktasi (zMin) +3 ile -70 arasinda ise true doner.\n   * Sadece Zmin degeri arayuzde pulse animasyonu ile vurgulanir.\n   */\n  zPulseVar(file: PostFile): boolean {\n    if (file.zMin === null) return false;\n    return file.zMin <= 2.5 && file.zMin >= -70;\n  }\n\n  baglamaYonu(file: PostFile): \"Uzun Taraf X\" | \"Uzun Taraf Y\" | \"Kare\" {\n    // if (file.zMin === null) return false;\n    let xBoy = Math.abs(file.xMax) + Math.abs(file.xMin);\n    let yBoy = Math.abs(file.yMax) + Math.abs(file.yMin);\n    if (xBoy == yBoy) {\n      return \"Kare\";\n    }\n    if (xBoy > yBoy) {\n      return \"Uzun Taraf X\";\n    } else if (yBoy > xBoy) {\n      return \"Uzun Taraf Y\";\n    }\n\n  }\n\n  OnIsl(file: PostFile): boolean {\n    return (file.zMin + file.zMax) > 3;\n  }\n\n  enBuyukKutuk(): number {\n    let enBuyuk = 0;\n\n    for (const f of this.files) {\n      const deger = f?.kutukZ ?? 0;\n      if (deger > enBuyuk) {\n        enBuyuk = deger;\n      }\n    }\n\n    return enBuyuk;\n  }\n\n  tahminiKutukZ(file: PostFile): number {\n    // if (file.zMin === null) return false;\n    let zBoy = Math.abs(file.zMin) + Math.abs(file.zLast);\n\n    if (file.zMin > 0) {\n      // zBoy+=30;\n    }\n\n    zBoy = Math.floor(zBoy / 50) * 50;\n\n    return zBoy;\n  }\n\n  gecisleriAyarla(): void {\n    let enBuyukKutuk = this.enBuyukKutuk()\n\n    for (let index = 0; index < this.files.length; index++) {\n      const element = this.files[index];\n\n      if (element.onMu) {\n        element.customZLast = enBuyukKutuk + 30;\n      } else if (element.onMu == false) {\n        let gecis = (enBuyukKutuk - element.kutukZ) + 30\n        element.customZLast = gecis;\n      }\n    }\n    this.CD.detectChanges();\n  }\n\n\n  private executeMerge() {\n    this.mergeProgress = 20;\n    this.mergeStatus = 'Header yaziliyor...';\n    this.degisti();\n\n    setTimeout(() => {\n      this.mergeProgress = 40;\n      this.mergeStatus = `Dosyalar isleniyor (0/${this.files.length})...`;\n      this.degisti();\n\n      const lines: string[] = [\n        `O${this.programNumber || 1000}`,\n        this.headerLines.join(' ')\n      ];\n\n      let toplamDakika = 0;\n\n      for (const element of this.files) {\n        if (this.basliklariYaz) {\n          const timeResult = this.calculateNcTime(element.cleanedContent, 15000, 10000);\n          const satir = element.cleanedContent.split('\\n').length;\n\n          const sonZti = element.customZLast !== undefined && element.customZLast !== null\n            ? element.customZLast\n            : element.zLast;\n\n          lines.push(`//( ${element.workOffset} : ${element.name} | SATIR:${satir} | DK:${timeResult.totalTimeMin.toFixed(3)} )`);\n          lines.push(`//( X-:${this.formatCncNumber(element.xMin)} X+:${this.formatCncNumber(element.xMax)} Y-:${this.formatCncNumber(element.yMin)} Y+:${this.formatCncNumber(element.yMax)} Z-:${this.formatCncNumber(element.zMin)} Z+:${this.formatCncNumber(element.zMax)} )`);\n          lines.push(`//( SON GECIS ZTI:${this.formatCncNumber(sonZti)} )`);\n          toplamDakika += timeResult.totalTimeMin;\n        }\n      }\n\n      const totalSatir = this.files.reduce((sum, e) => sum + (e.cleanedContent?.split('\\n').length || 0), 0);\n      lines.push(`// ( -- FIKOYT SISTEM - YENI CAG | SATIR:${totalSatir} | DK:${toplamDakika.toFixed(3)} -- )`);\n\n      // Limit kontrol gezisi\n      if (this.limitKontrolYap) {\n        lines.push('');\n        lines.push('//( ========== LIMIT KONTROL GEZISI ========== )');\n        lines.push('//( TEZGAH TUM DOSYALARIN LIMITLERINI GEZECEK )');\n        lines.push('//( HER NOKTADA M0 ILE DURACAK - KONTROL ET )');\n        lines.push('');\n\n        for (const element of this.files) {\n          const sonZti = element.customZLast !== undefined && element.customZLast !== null\n            ? element.customZLast\n            : element.zLast;\n\n          lines.push(`//( --- ${element.name} LIMIT KONTROLU --- )`);\n          lines.push(element.workOffset);\n          lines.push(`//( ${element.workOffset} : ${element.name} )`);\n\n          lines.push(`G0 X0. Y0. M0 //( MERKEZ - DOGRUMU? CYCLE START )`);\n          if (sonZti !== null) {\n            lines.push(`G0 Z${this.formatCncNumber(sonZti)} //( GUVENLI YUKSEKLIK )`);\n          }\n\n          if (element.xMin !== null) {\n            lines.push(`G0 X${this.formatCncNumber(element.xMin)} M0 //( X- LIMIT - SIKINTI YOKSA CYCLE START )`);\n          }\n          if (element.xMax !== null) {\n            lines.push(`G0 X${this.formatCncNumber(element.xMax)} M0 //( X+ LIMIT - SIKINTI YOKSA CYCLE START )`);\n          }\n\n          if (element.yMin !== null) {\n            lines.push(`G0 Y${this.formatCncNumber(element.yMin)} M0 //( Y- LIMIT - SIKINTI YOKSA CYCLE START )`);\n          }\n          if (element.yMax !== null) {\n            lines.push(`G0 Y${this.formatCncNumber(element.yMax)} M0 //( Y+ LIMIT - SIKINTI YOKSA CYCLE START )`);\n          }\n\n          lines.push(`//( Z-:${this.formatCncNumber(element.zMin)} Z+:${this.formatCncNumber(element.zMax)} )`);\n          lines.push(`//( SON GECIS ZTI:${this.formatCncNumber(sonZti)} )`);\n          lines.push('//( TAKIMI VE ZTI KONTROL ET )');\n\n          if (sonZti !== null) {\n            lines.push(`G0 Z${this.formatCncNumber(sonZti)} M0 //( ZTI - DIGER KALIBA GECIS BURADAN OLACAK )`);\n          }\n          lines.push('');\n        }\n\n        lines.push('//( ========== LIMIT KONTROL BITTI ========== )');\n        lines.push('G0 G90 G53 Z-1.');\n        lines.push('M0 //( SIMDI GERCEK ISLEM BASLAYACAK )');\n        lines.push('');\n      }\n\n      this.resetMergedBounds();\n\n      let processedFiles = 0;\n      const totalFiles = this.files.length;\n\n      for (const f of this.files) {\n        processedFiles++;\n        this.mergeProgress = 40 + Math.floor((processedFiles / totalFiles) * 50);\n        this.mergeStatus = `Dosyalar isleniyor (${processedFiles}/${totalFiles})...`;\n        this.degisti();\n\n        lines.push(`//(--- BASLANGIC: ${f.name} | Offset: ${f.workOffset} ---)`);\n        if (f.workOffset) lines.push(f.workOffset);\n\n        if (f.cleanedContent.trim()) {\n          const contentLines = f.cleanedContent.trim().split('\\n');\n          const cleanedLines = this.removeProgramEnd(contentLines);\n\n          if (f.customZLast !== undefined && f.customZLast !== null && f.customZLast !== f.zLast) {\n            for (let i = cleanedLines.length - 1; i >= 0; i--) {\n              const line = cleanedLines[i];\n              if (/Z-?\\d+\\.?\\d*/i.test(line)) {\n                cleanedLines[i] = line.replace(/Z-?\\d+\\.?\\d*/i, `Z${this.formatCncNumber(f.customZLast)}`);\n                break;\n              }\n            }\n          }\n\n          lines.push(cleanedLines.join('\\n'));\n        }\n\n        lines.push(`//(--- BITIS: ${f.name} ---)`);\n\n        this.mergeBoundsFromFile(f);\n      }\n\n      this.mergeProgress = 95;\n      this.mergeStatus = 'Son kontroller yapiliyor...';\n      this.degisti();\n\n      lines.push('M5', 'M30', 'M2');\n      this.mergedResult = lines.join('\\n');\n\n      setTimeout(() => {\n        this.mergeProgress = 100;\n        this.mergeStatus = 'Tamamlandi!';\n        this.degisti();\n\n        setTimeout(() => {\n          this.mergeInProgress = false;\n          this.programIsmi = this.files.length === 1\n            ? (this.files[0]?.name?.replace(/\\.[^/.]+$/, '') || 'BIRLESIK')\n            : 'BIRLESIK';\n          this.degisti();\n          scrollTo({ left: 0, top: document.body.scrollHeight, behavior: 'smooth' });\n        }, 800);\n      }, 200);\n    }, 300);\n  }\n\n  downloadMerged() {\n    if (!this.mergedResult) return;\n    const blob = new Blob([this.mergedResult], { type: 'text/plain' });\n    const url = window.URL.createObjectURL(blob);\n    const a = document.createElement('a');\n    a.href = url;\n    a.download = `${this.programIsmi || \"BIRLESIK\"}.NC`;\n    document.body.appendChild(a);\n    a.click();\n    a.remove();\n    window.URL.revokeObjectURL(url);\n  }\n\n  clearAll() {\n    this.files = [];\n    this.mergedResult = '';\n    this.programNumber = 1000;\n    this.resetMergedBounds();\n  }\n\n  // Formatting Helpers\n  formatFileSize(bytes: number): string {\n    return `${(bytes / 1024).toFixed(1)} KB`;\n  }\n\n  formatCoordinate(value: number | null): string {\n    return value !== null ? value.toFixed(3) : 'N/A';\n  }\n\n  formatCncNumber(value: number | null): string {\n    if (value === null) return 'N/A';\n    const str = value.toString();\n    return str.includes('.') ? str : str + '.';\n  }\n\n  formatDate(dateStr: string): string {\n    if (!dateStr) return '';\n    try {\n      return new Date(dateStr).toLocaleString('tr-TR');\n    } catch {\n      return dateStr;\n    }\n  }\n\n  getBoundsInfo(file: PostFile): string {\n    const parts: string[] = [];\n    if (file.xMin !== null && file.xMax !== null) {\n      parts.push(`X: ${this.formatCoordinate(file.xMin)} / ${this.formatCoordinate(file.xMax)}`);\n    }\n    if (file.yMin !== null && file.yMax !== null) {\n      parts.push(`Y: ${this.formatCoordinate(file.yMin)} / ${this.formatCoordinate(file.yMax)}`);\n    }\n    if (file.zMin !== null && file.zMax !== null) {\n      parts.push(`Z: ${this.formatCoordinate(file.zMin)} / ${this.formatCoordinate(file.zMax)}`);\n    }\n\n    const displayZLast = file.customZLast !== undefined && file.customZLast !== null\n      ? file.customZLast\n      : file.zLast;\n\n    if (displayZLast !== null) {\n      parts.push(`Son Z: ${this.formatCoordinate(displayZLast)}`);\n    }\n    return parts.length > 0 ? parts.join(' | ') : 'Koordinat bulunamadi';\n  }\n\n  getMergedBoundsInfo(): string {\n    const parts: string[] = [];\n    const b = this.mergedBounds;\n    if (b.xMin !== null && b.xMax !== null) {\n      parts.push(`X: ${this.formatCoordinate(b.xMin)} / ${this.formatCoordinate(b.xMax)}`);\n    }\n    if (b.yMin !== null && b.yMax !== null) {\n      parts.push(`Y: ${this.formatCoordinate(b.yMin)} / ${this.formatCoordinate(b.yMax)}`);\n    }\n    if (b.zMin !== null && b.zMax !== null) {\n      parts.push(`Z: ${this.formatCoordinate(b.zMin)} / ${this.formatCoordinate(b.zMax)}`);\n    }\n    if (b.zLast !== null) {\n      parts.push(`Son Z: ${this.formatCoordinate(b.zLast)}`);\n    }\n    return parts.length > 0 ? parts.join(' | ') : 'Henuz birlestirme yapilmadi';\n  }\n\n  // Bounds Helpers\n  private createEmptyBounds(): Bounds {\n    return {\n      xMin: null, xMax: null,\n      yMin: null, yMax: null,\n      zMin: null, zMax: null,\n      zLast: null\n    };\n  }\n\n  private resetMergedBounds() {\n    this.mergedBounds = this.createEmptyBounds();\n  }\n\n  private mergeBoundsFromFile(file: PostFile) {\n    const b = this.mergedBounds;\n    if (file.xMin !== null) b.xMin = b.xMin === null ? file.xMin : Math.min(b.xMin, file.xMin);\n    if (file.xMax !== null) b.xMax = b.xMax === null ? file.xMax : Math.max(b.xMax, file.xMax);\n    if (file.yMin !== null) b.yMin = b.yMin === null ? file.yMin : Math.min(b.yMin, file.yMin);\n    if (file.yMax !== null) b.yMax = b.yMax === null ? file.yMax : Math.max(b.yMax, file.yMax);\n    if (file.zMin !== null) b.zMin = b.zMin === null ? file.zMin : Math.min(b.zMin, file.zMin);\n    if (file.zMax !== null) b.zMax = b.zMax === null ? file.zMax : Math.max(b.zMax, file.zMax);\n    if (file.zLast !== null) b.zLast = file.zLast;\n  }\n\n  // Duplicate Offset Detection\n  getDuplicateOffsets(): { offset: string; files: string[] }[] {\n    const offsetMap = new Map<string, string[]>();\n    for (const file of this.files) {\n      const existing = offsetMap.get(file.workOffset) || [];\n      existing.push(file.name);\n      offsetMap.set(file.workOffset, existing);\n    }\n\n    const duplicates: { offset: string; files: string[] }[] = [];\n    for (const [offset, files] of offsetMap) {\n      if (files.length > 1) {\n        duplicates.push({ offset, files });\n      }\n    }\n    return duplicates;\n  }\n\n  hasDuplicateOffsets(): boolean {\n    return this.getDuplicateOffsets().length > 0;\n  }\n\n  // Change Detection\n  degisti() {\n    this.CD.markForCheck();\n  }\n\n  // Pagination\n  async onPageChange(page: number) {\n    this.pageIndex = page;\n    this.loadRecentFiles();\n  }\n\n  async onPageSizeChange(size: number) {\n    this.loadRecentFiles();\n  }\n\n  getFirstNLines(str: string, n: number): string {\n    let count = 0;\n    let lastIndex = 0;\n    while (count < n) {\n      const nextIndex = str.indexOf('\\n', lastIndex);\n      if (nextIndex === -1) return str;\n      lastIndex = nextIndex + 1;\n      count++;\n    }\n    return str.slice(0, lastIndex);\n  }\n\n  // Post Operations\n  async postYolla() {\n    if (this.postYollamaMesgul) return;\n\n    this.postYollamaMesgul = true;\n    this.CD.detectChanges();\n\n    try {\n      await this.everything.postSil(this.programIsmi + \".NC\");\n    } catch (error) {\n      console.warn(\"Silme basarisiz (dosya yok olabilir):\", error);\n    }\n\n    try {\n      await new Promise(resolve => setTimeout(resolve, 1000));\n      const blob = new Blob([this.mergedResult], { type: 'text/plain' });\n\n      await this.everything.postYolla(blob, this.programIsmi + \".NC\", (p) => {\n        this.postYollaniyor = p;\n        this.CD.detectChanges();\n      });\n    } finally {\n      this.postYollamaMesgul = false;\n      this.postYollaniyor = 0;\n      this.CD.detectChanges();\n    }\n  }\n\n  postTasi(dosya: any) {\n    console.log(\"postTasi\", dosya);\n  }\n\n  async postKopyala(dosya: any) {\n    try {\n      await this.everything.postSil(dosya.name);\n    } catch (error) {\n      console.warn(\"Silme basarisiz (dosya yok olabilir):\", error);\n    }\n\n    await new Promise(resolve => setTimeout(resolve, 1000));\n\n    const cleanPath = dosya.url.replace(/\\\\/g, '/').replace(/^[A-Za-z]:/, '').replace(/^\\/+/, '');\n    await this.everything.postKopyala(cleanPath, dosya.name);\n  }\n}\n\n</file_content>\n</folder_content>",
  "metadata": {
    "sessionHistoryOrigin": {
      "mode": "user",
      "version": "4.1.16"
    },
    "git": {
      "branch": "feat/ecs-cekirdek"
    },
    "checkpoint": {
      "latest": {
        "ref": "2b6c9c81b4f3f734a4b31d34c540e7a30ec64954",
        "createdAt": 1787962751668,
        "runCount": 1,
        "kind": "commit"
      },
      "history": [
        {
          "ref": "2b6c9c81b4f3f734a4b31d34c540e7a30ec64954",
          "createdAt": 1787962751668,
          "runCount": 1,
          "kind": "commit"
        }
      ]
    },
    "title": "'fikoyt-sistem/src/app/uygulamalar/post-birlestiricisi/' (see below for folder content)\n\n                              <",
    "isFavorited": false,
    "size": 198969,
    "totalCost": 0,
    "tokensIn": 2543,
    "tokensOut": 550,
    "cacheWrites": 0,
    "cacheReads": 23616,
    "modelId": "z-ai/glm-5.3-flash",
    "legacyTask": false,
    "aggregatedAgentsCost": 0,
    "usage": {
      "inputTokens": 70850,
      "outputTokens": 1868,
      "cacheReadTokens": 44672,
      "cacheWriteTokens": 0,
      "totalCost": 0
    },
    "aggregateUsage": {
      "inputTokens": 70850,
      "outputTokens": 1868,
      "cacheReadTokens": 44672,
      "cacheWriteTokens": 0,
      "totalCost": 0
    },
    "terminal_marker": "failed_external_process_exit",
    "terminal_marker_at": "2026-08-29T01:47:42.822Z",
    "terminal_marker_pid": 1452,
    "terminal_marker_source": "stale_session_reconciler"
  },
  "messages_path": "C:\\Users\\FikoYT\\.cline\\data\\sessions\\1787962704361_ktjek\\1787962704361_ktjek.messages.json"
}
