{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://hesapla.narch.tech/arac/arsa-payi/arsa-payi.json",
  "title": "ArsaPayi hesaplama girdisi",
  "description": "Bağımsız bölüm değer puanlarını seçilen tam sayı paydaya dağıtmak için doğrudan doğrulanabilir girdi şemasıdır. Araç brüt veya net alanı seçmez; proje ya da uzman tarafından seçilmiş aynı alan tanımı bütün satırlarda tutarlı kullanılmalıdır.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "satirlar",
    "payda"
  ],
  "properties": {
    "satirlar": {
      "type": "array",
      "minItems": 2,
      "maxItems": 10000,
      "description": "En az iki bağımsız bölüm veya aynı tip bölüm satırı.",
      "items": {
        "$ref": "#/$defs/inputRow"
      }
    },
    "payda": {
      "type": "integer",
      "minimum": 1,
      "maximum": 1000000000,
      "examples": [
        100,
        240,
        1000,
        2400,
        10000
      ],
      "x-unit": "tam sayı pay",
      "description": "Başarılı sonuçtaki bütün tam sayı payların toplamı. Her bağımsız bölüme en az bir pay verecek kadar büyük seçilmelidir."
    },
    "toplamArsaM2": {
      "type": [
        "number",
        "null"
      ],
      "exclusiveMinimum": 0,
      "maximum": 1000000000,
      "x-unit": "m²",
      "description": "İsteğe bağlı, 0'dan büyük ve en çok 1.000.000.000 m² toplam arsa alanı. Verilmezse veya null ise çıktıdaki arsaM2 değerleri null olur."
    }
  },
  "$defs": {
    "inputRow": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "ad",
        "alan",
        "katsayi"
      ],
      "properties": {
        "ad": {
          "type": "string",
          "minLength": 1,
          "pattern": ".*\\S.*",
          "description": "Bağımsız bölüm adı."
        },
        "alan": {
          "type": "number",
          "exclusiveMinimum": 0,
          "maximum": 1000000000,
          "x-unit": "m²",
          "description": "Proje veya uzman tarafından seçilmiş alan tanımına göre 0'dan büyük ve en çok 1.000.000.000 m² yüzölçümü. Araç brüt/net seçmez; aynı tanım bütün satırlarda kullanılmalıdır."
        },
        "katsayi": {
          "type": "number",
          "exclusiveMinimum": 0,
          "maximum": 1000000000,
          "x-unit": "birimsiz",
          "x-policy": "Zorunlu, kullanıcı kaynaklı ve varsayansız. Eksik katsayı şema tarafından reddedilir; koşulsuz default yoktur. 1,00 resmî ya da örtük katsayı değildir; yalnız kullanıcı bütün bölümlerin eşit değerde olduğunu açıkça kabul ederse 1 olarak yazılabilir.",
          "description": "Kullanıcının açıkça sağladığı, 0'dan büyük ve en çok 1.000.000.000 olan değer katsayısı. Varsayılanı yoktur ve agent tarafından uydurulamaz. İnsan arayüzü de katsayı alanını boş bırakır; kullanıcı yalnız alan girerse motor KATSAYI_SIFIR ile durur, sessiz 1,00 üretilmez."
        },
        "adet": {
          "type": "integer",
          "minimum": 1,
          "maximum": 10000,
          "default": 1,
          "x-unit": "adet",
          "description": "Aynı tip bağımsız bölüm sayısı; verilmezse motor 1 kabul eder."
        }
      }
    },
    "output": {
      "title": "ArsaPayi başarılı çıktısı",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "satirlar",
        "toplamDeger",
        "toplamPay",
        "toplamArsaM2YuzdeBir",
        "uyarilar"
      ],
      "properties": {
        "satirlar": {
          "type": "array",
          "minItems": 2,
          "maxItems": 10000,
          "items": {
            "$ref": "#/$defs/outputRow"
          }
        },
        "toplamDeger": {
          "type": "number",
          "exclusiveMinimum": 0,
          "x-unit": "değer puanı",
          "x-scale": "alan × katsayı değer puanlarının toplamı",
          "description": "Bütün satırların değer puanlarının toplamı."
        },
        "toplamPay": {
          "type": "integer",
          "minimum": 2,
          "maximum": 1000000000,
          "x-unit": "tam sayı pay",
          "x-scale": "pay/payda kesrinin pay birimi",
          "description": "Başarılı çağrıda girdideki payda ile aynı olan tam sayı pay toplamı."
        },
        "toplamArsaM2YuzdeBir": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0,
          "maximum": 100000000000,
          "x-unit": "0,01 m² birim (cent-tamsayı)",
          "x-invariant": "toplamArsaM2 verilmişse satır arsaM2YuzdeBir değerlerinin tam toplamıdır; verilmediyse null.",
          "description": "toplamArsaM2 girişinin yarım-yukarı iki haneye yuvarlanmış tam sayı 0,01 m² (cent) karşılığı. toplamArsaM2 verilmediyse null. Σ arsaM2YuzdeBir tam olarak bu değere eşittir; kayan noktalı arsaM2 toplamı değil, cent-tamsayı toplamı bağlayıcıdır."
        },
        "uyarilar": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/warning"
          },
          "description": "Yapılandırılmış, bağlayıcı olmayan uyarılar. Mevcut başarılı motor çağrısı normalde boş dizi döndürür."
        }
      }
    },
    "outputRow": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "ad",
        "alan",
        "katsayi",
        "deger",
        "oran",
        "pay",
        "sadelesmis",
        "arsaM2",
        "arsaM2YuzdeBir"
      ],
      "properties": {
        "ad": {
          "type": "string",
          "minLength": 1
        },
        "alan": {
          "type": "number",
          "exclusiveMinimum": 0,
          "maximum": 1000000000,
          "x-unit": "m²"
        },
        "katsayi": {
          "type": "number",
          "exclusiveMinimum": 0,
          "maximum": 1000000000,
          "x-unit": "birimsiz"
        },
        "deger": {
          "type": "number",
          "exclusiveMinimum": 0,
          "x-unit": "değer puanı",
          "x-scale": "alan × katsayı",
          "description": "Satırın pozitif alan × katsayı değer puanı."
        },
        "oran": {
          "type": "number",
          "exclusiveMinimum": 0,
          "maximum": 1,
          "x-unit": "0–1 oran",
          "x-scale": "0 ile 1 arasında; yüzde değildir",
          "description": "deger/toplamDeger oranı; yüzde gösterimi için 100 ile çarpılır."
        },
        "pay": {
          "type": "integer",
          "minimum": 1,
          "x-unit": "tam sayı pay",
          "x-scale": "pay/toplamPay kesrinin pay birimi",
          "description": "En büyük artık dağıtımından sonraki pozitif nihai tam sayı pay."
        },
        "sadelesmis": {
          "type": "string",
          "pattern": "^[1-9][0-9]*/[1-9][0-9]*$",
          "description": "Nihai pay/toplamPay kesrinin sadeleştirilmiş gösterimi."
        },
        "arsaM2": {
          "type": [
            "number",
            "null"
          ],
          "minimum": 0,
          "maximum": 1000000000,
          "x-unit": "m²",
          "x-formula": "largestRemainderCents(roundHalfUp2(toplamArsaM2), pay, toplamPay)",
          "x-rounding": "Toplam alan önce 0,01 m² birimine yarım-yukarı yuvarlanır; tam 0,01 m² birimleri nihai paylara en büyük artık yöntemiyle, eşitlikte sonraki satır öncelikli dağıtılır.",
          "description": "toplamArsaM2 verilmişse, toplam önce 0,01 m² birimine yarım-yukarı yuvarlanır ve bu birimler nihai tam sayı pay/toplamPay oranına göre en büyük artıkla dağıtılır. Satırların arsaM2 toplamı iki haneli hedef toplama eşittir; aksi halde null. arsaM2 kayan noktalı gösterimdir; toplam-koruma değişmezi tam olarak arsaM2YuzdeBir cent-tamsayıları düzeyinde geçerlidir."
        },
        "arsaM2YuzdeBir": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0,
          "maximum": 100000000000,
          "x-unit": "0,01 m² birim (cent-tamsayı)",
          "x-formula": "largestRemainderCents(roundHalfUp2(toplamArsaM2), pay, toplamPay)",
          "x-invariant": "Σ arsaM2YuzdeBir === toplamArsaM2YuzdeBir (toplamArsaM2 verilmişse). Kayan noktalı arsaM2 değerlerini toplamak yerine bu cent-tamsayılar toplanmalıdır.",
          "description": "Satıra düşen tam sayı 0,01 m² (cent) birimi. toplamArsaM2 verilmediyse null. Bu alan toplam-koruma değişmezinin kesin kaynağıdır; JS tüketici, kayan noktalı arsaM2 yerine Math.round(arsaM2*100) yerine doğrudan arsaM2YuzdeBir değerlerini toplamalıdır."
        }
      }
    },
    "warning": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "string",
          "pattern": "^[A-Z][A-Z0-9_]*$"
        },
        "message": {
          "type": "string",
          "minLength": 1
        }
      }
    },
    "error": {
      "title": "Motorun fırlattığı yapılandırılmış hata",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "string",
          "enum": [
            "GIRDI_GECERSIZ",
            "BILINMEYEN_ALAN",
            "SATIR_YETERSIZ",
            "PAYDA_GECERSIZ",
            "PAYDA_YETERSIZ",
            "ALAN_NEGATIF",
            "ALAN_SIFIR",
            "KATSAYI_SIFIR",
            "DEGER_GECERSIZ",
            "SAYISAL_SINIR_DISI",
            "ADET_GECERSIZ",
            "AD_GECERSIZ"
          ]
        },
        "message": {
          "type": "string",
          "minLength": 1
        }
      },
      "description": "hesaplaPaylar başarısız olduğunda JavaScript Error nesnesinin code ve message alanları bu yapıya uyar."
    }
  },
  "x-contract": {
    "version": "2.2.0",
    "tool": "ArsaPayi",
    "slug": "arsa-payi",
    "deterministic": true,
    "offline": true,
    "legalNature": "bilgilendirme, bağlayıcı değil",
    "inputSchemaRef": "#",
    "outputSchemaRef": "#/$defs/output",
    "errorSchemaRef": "#/$defs/error",
    "katsayiPolicy": "Zorunlu, kullanıcı kaynaklı, varsayansız. Şema eksik katsayıyı reddeder; koşulsuz default yoktur; agent katsayı uydurmaz. 1,00 yalnız kullanıcı eşit değer varsayımını açıkça seçerse kullanılır; ülke çapında sabit kat/cephe/tip katsayısı yoktur. İnsan arayüzü de katsayı alanını boş bırakır; yalnız alan girilirse KATSAYI_SIFIR ile durur.",
    "engine": {
      "mainFunction": "hesaplaPaylar",
      "signature": "hesaplaPaylar({satirlar, payda, toplamArsaM2})",
      "helpers": [
        "enBuyukArtikDagit(hamPaylar, payda)",
        "kesinDegerlerdenDagit(degerler, payda)",
        "sadelestir(pay, payda)"
      ],
      "formula": "pay_i = payda × (alan_i×katsayi_i) / Σ(alan×katsayi), tam sayıya en büyük artık yöntemiyle indirilir",
      "equalRemainderRule": "Ana motor artıkları BigInt ile kesin karşılaştırır. enBuyukArtikDagit kayan nokta artıklarını doğrudan karşılaştırır; yalnız aynı Number artık değeri eşit sayılır ve eşitlikte sonraki satır önce pay alır.",
      "successInvariant": "Bütün paylar pozitif tam sayıdır ve toplamları paydaya eşittir.",
      "quantityRule": "adet > 1 ise her kopya hesap öncesinde ayrı bağımsız bölüm olarak genişletilir.",
      "inputNumericMaximum": 1000000000,
      "inputNumericMaximumAppliesTo": [
        "alan",
        "katsayi",
        "toplamArsaM2"
      ],
      "arsaM2Rule": "toplamArsaM2 önce yarım-yukarı 0,01 m² birimine çevrilir; birimler nihai tam sayı paylara en büyük artıkla dağıtılır ve satır toplamı bu hedefi korur.",
      "arsaM2Invariant": "Toplam-koruma değişmezi cent-tamsayı düzeyinde kesindir: Σ arsaM2YuzdeBir === toplamArsaM2YuzdeBir (toplamArsaM2 verilmişse). Kayan noktalı arsaM2 değerleri bunların /100 gösterimidir; JS tüketici Math.round(arsaM2*100) yerine doğrudan arsaM2YuzdeBir değerlerini toplamalıdır.",
      "helperRegression": "enBuyukArtikDagit([500000000.5000001,499999999.4999999],1000000000) => [500000001,499999999]"
    }
  },
  "x-error-code-details": {
    "GIRDI_GECERSIZ": "Kök girdi düz bir nesne değildir.",
    "BILINMEYEN_ALAN": "Kök girdide veya satır nesnesinde sözleşmede tanımlanmayan bir anahtar vardır.",
    "SATIR_YETERSIZ": "En az iki kaynak satırı gerekir; tek satırdaki adet bu koşulu kaldırmaz.",
    "PAYDA_GECERSIZ": "Payda 1–1.000.000.000 aralığında bir tam sayı değildir veya yardımcıya verilen ham pay toplamı paydayla uyumsuzdur.",
    "PAYDA_YETERSIZ": "Pozitif değerli en az bir bağımsız bölüm nihai dağıtımda 0 pay almıştır; daha büyük payda seçilmelidir.",
    "ALAN_NEGATIF": "Bir bölüm alanı veya isteğe bağlı toplam arsa alanı negatif, sonlu olmayan ya da geçersizdir.",
    "ALAN_SIFIR": "Bir bölüm alanı veya verilmiş toplam arsa alanı sıfırdır; pozitif alan gerekir.",
    "KATSAYI_SIFIR": "Değer katsayısı sonlu değildir ya da sıfırdan büyük değildir.",
    "DEGER_GECERSIZ": "Pozitif alan ve katsayının çarpımı sıfır ya da sonlu olmayan bir değer puanı üretmiştir.",
    "SAYISAL_SINIR_DISI": "alan, katsayi veya toplamArsaM2 için 1.000.000.000 üst sınırı aşılmıştır.",
    "ADET_GECERSIZ": "Adet pozitif tam sayı değildir veya genişletilmiş sonuç 10.000 satırı aşar.",
    "AD_GECERSIZ": "Bağımsız bölüm adı boş veya metin değildir."
  },
  "x-golden-examples": [
    {
      "id": "kolay_arsa_alanli",
      "input": {
        "satirlar": [
          {
            "ad": "A",
            "alan": 100,
            "katsayi": 1
          },
          {
            "ad": "B",
            "alan": 100,
            "katsayi": 1
          },
          {
            "ad": "C",
            "alan": 200,
            "katsayi": 1
          }
        ],
        "payda": 1000,
        "toplamArsaM2": 500
      },
      "expected": {
        "satirlar": [
          {
            "ad": "A",
            "alan": 100,
            "katsayi": 1,
            "deger": 100,
            "oran": 0.25,
            "pay": 250,
            "sadelesmis": "1/4",
            "arsaM2": 125,
            "arsaM2YuzdeBir": 12500
          },
          {
            "ad": "B",
            "alan": 100,
            "katsayi": 1,
            "deger": 100,
            "oran": 0.25,
            "pay": 250,
            "sadelesmis": "1/4",
            "arsaM2": 125,
            "arsaM2YuzdeBir": 12500
          },
          {
            "ad": "C",
            "alan": 200,
            "katsayi": 1,
            "deger": 200,
            "oran": 0.5,
            "pay": 500,
            "sadelesmis": "1/2",
            "arsaM2": 250,
            "arsaM2YuzdeBir": 25000
          }
        ],
        "toplamDeger": 400,
        "toplamPay": 1000,
        "toplamArsaM2YuzdeBir": 50000,
        "uyarilar": []
      }
    },
    {
      "id": "uc_esit_son_satir",
      "input": {
        "satirlar": [
          {
            "ad": "A",
            "alan": 100,
            "katsayi": 1
          },
          {
            "ad": "B",
            "alan": 100,
            "katsayi": 1
          },
          {
            "ad": "C",
            "alan": 100,
            "katsayi": 1
          }
        ],
        "payda": 1000
      },
      "expected": {
        "satirlar": [
          {
            "ad": "A",
            "alan": 100,
            "katsayi": 1,
            "deger": 100,
            "oran": 0.3333333333333333,
            "pay": 333,
            "sadelesmis": "333/1000",
            "arsaM2": null,
            "arsaM2YuzdeBir": null
          },
          {
            "ad": "B",
            "alan": 100,
            "katsayi": 1,
            "deger": 100,
            "oran": 0.3333333333333333,
            "pay": 333,
            "sadelesmis": "333/1000",
            "arsaM2": null,
            "arsaM2YuzdeBir": null
          },
          {
            "ad": "C",
            "alan": 100,
            "katsayi": 1,
            "deger": 100,
            "oran": 0.3333333333333333,
            "pay": 334,
            "sadelesmis": "167/500",
            "arsaM2": null,
            "arsaM2YuzdeBir": null
          }
        ],
        "toplamDeger": 300,
        "toplamPay": 1000,
        "toplamArsaM2YuzdeBir": null,
        "uyarilar": []
      }
    },
    {
      "id": "katsayili_iki_bolum",
      "input": {
        "satirlar": [
          {
            "ad": "Standart",
            "alan": 100,
            "katsayi": 1
          },
          {
            "ad": "Yüksek değer",
            "alan": 100,
            "katsayi": 1.2
          }
        ],
        "payda": 1000
      },
      "expected": {
        "satirlar": [
          {
            "ad": "Standart",
            "alan": 100,
            "katsayi": 1,
            "deger": 100,
            "oran": 0.45454545454545453,
            "pay": 455,
            "sadelesmis": "91/200",
            "arsaM2": null,
            "arsaM2YuzdeBir": null
          },
          {
            "ad": "Yüksek değer",
            "alan": 100,
            "katsayi": 1.2,
            "deger": 120,
            "oran": 0.5454545454545454,
            "pay": 545,
            "sadelesmis": "109/200",
            "arsaM2": null,
            "arsaM2YuzdeBir": null
          }
        ],
        "toplamDeger": 220,
        "toplamPay": 1000,
        "toplamArsaM2YuzdeBir": null,
        "uyarilar": []
      }
    }
  ]
}
