"""トップと柱(/guide/)に出す自分の計算(商いの帳場)。python scripts/figs/top_numbers.py で再現できる。
外部のデータは使わない。架空の条件はすべてこのファイルに書く。結果は cms/_facts.md 5章に写す。
  1. 転記の数:伝票6段で、明細1行あたり手で写す項目の数
  2. 得意先別単価の持ち方3通り:保つ行数と、標準価格を改定するときに直す行数
  3. インボイスの端数処理:架空の1か月(納品20回、8%と10%が混在)で、納品書ごとに端数処理した税額の合計と、請求書で税率ごとに1回の税額の差
  4. B社の公開仕様の上限(伝票の合計60万明細)に届く年数
"""
import json, random, math

out = {}

# 1. 転記の数(手で写す項目。金額・税額は計算で出るので数えない)
stages = {
    '出荷指示': ['得意先', '商品', '数量', '納期'],
    '納品書': ['得意先', '商品', '数量', '単価'],
    '売上台帳(Excel)': ['日付', '得意先', '商品', '数量', '単価'],
    '請求書': ['日付', '商品', '数量', '単価'],
}
per_line = sum(len(v) for v in stages.values())
lines_month = 1000
out['transcription'] = {
    'stages': {k: len(v) for k, v in stages.items()}, 'perLine': per_line,
    'linesPerMonth': lines_month, 'perMonth': per_line * lines_month,
    'note': '受注票の入力(1回)は数えない。会計への仕訳は得意先ごとの合計なので明細の数に入れない',
}

# 2. 単価の持ち方(得意先300・商品2,000・1社が買う商品は全体の10%・特値は組み合わせの5%・価格ランク5段階)
C, P, use, special, ranks = 300, 2000, 0.10, 0.05, 5
pairs = int(C * P * use)
sp = int(pairs * special)
out['priceMaster'] = {
    'cond': {'customers': C, 'products': P, 'useRate': use, 'specialRate': special, 'ranks': ranks},
    'table': {'rows': pairs, 'revise': pairs},
    'rate': {'rows': P + C + sp, 'revise': P + sp},
    'rank': {'rows': ranks * P + C + sp, 'revise': ranks * P + sp},
}

# 3. 端数処理(切り捨て)。乱数の種を固定
rng = random.Random(20261016)
deliveries = []
for i in range(20):
    lines = []
    for _ in range(rng.randint(2, 6)):
        rate = 8 if rng.random() < 0.7 else 10
        price = rng.choice([128, 198, 248, 356, 480, 615, 742, 980, 1260, 1580, 2380, 3150])
        qty = rng.randint(1, 24)
        lines.append((rate, price * qty))
    deliveries.append(lines)
per_delivery = 0
base = {8: 0, 10: 0}
for lines in deliveries:
    s = {8: 0, 10: 0}
    for r, amt in lines:
        s[r] += amt
    for r in (8, 10):
        per_delivery += math.floor(s[r] * r / 100)
        base[r] += s[r]
per_invoice = sum(math.floor(base[r] * r / 100) for r in (8, 10))
out['rounding'] = {
    'seed': 20261016, 'deliveries': 20, 'lines': sum(len(l) for l in deliveries),
    'base8': base[8], 'base10': base[10],
    'taxPerDelivery': per_delivery, 'taxPerInvoice': per_invoice, 'diff': per_invoice - per_delivery,
    'rule': '切り捨て',
}

# 4. B社の上限(伝票の合計60万明細)に届く年数。受注と売上の両方の伝票を使うと、売上明細1行で2明細(入金は数えない)。年245日
for n in (100, 300, 500):
    pass
out['packageLimit'] = {
    'limit': 600000, 'days': 245,
    'rows': [{'salesLinesPerDay': n, 'linesPerDay': 2 * n, 'years': round(600000 / (2 * n * 245), 1)} for n in (100, 300, 500)],
}

# 5. 差し色のコントラスト
def lum(h):
    c = [int(h[i:i + 2], 16) / 255 for i in (1, 3, 5)]
    c = [x / 12.92 if x <= 0.04045 else ((x + 0.055) / 1.055) ** 2.4 for x in c]
    return 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2]
def cr(a, b):
    la, lb = sorted([lum(a), lum(b)], reverse=True)
    return round((la + 0.05) / (lb + 0.05), 2)
out['contrast'] = {h: {'white': cr(h, '#ffffff'), 'dark111': cr(h, '#111111')} for h in ['#678b2c', '#557323', '#46601d', '#9cbb68', '#a9c47c', '#7f9e4e']}

print(json.dumps(out, ensure_ascii=False, indent=1))
