#!/bin/bash
# =============================================================================
#  Kanana Studio - 端末スペック詳細取得スクリプト (macOS)
#  https://kanana-studio.com/tools/spec/
#
#  このスクリプトは端末のハードウェア構成を読み取り、JSON ファイルに保存します。
#  ・読み取り専用です。設定変更・ファイル削除・インストールは一切行いません。
#  ・外部への通信は一切行いません（収集結果はローカルに保存されるだけです）。
#  ・管理者権限（sudo）は不要です。
#  ・macOS 標準コマンドのみを使用します（jq / python などの追加導入は不要）。
#
#  使い方:
#    1) ターミナル.app を開く（Launchpad →「その他」→「ターミナル」）
#    2) 次の行を貼り付けて実行:
#         bash ~/Downloads/spec-check.sh
#    3) ホームフォルダに spec-<Mac名>-<日付>.json が作成されます
#    4) https://kanana-studio.com/tools/spec/ を開き、その JSON をドラッグ＆ドロップ
#
#  オプション:
#    --bench            簡易ベンチマーク（CPU / ディスク）を実行します
#    --out <path>       出力先を指定します
#
#  スキーマ: kanana-spec/1     バージョン: 1.0.0
# =============================================================================

set -u

SCHEMA="kanana-spec/1"
COLLECTOR="spec-check.sh 1.0.0"
DO_BENCH=0
OUTFILE=""
NOTES=""

while [ $# -gt 0 ]; do
  case "$1" in
    --bench) DO_BENCH=1; shift ;;
    --out) OUTFILE="${2:-}"; shift 2 ;;
    -h|--help) sed -n '2,30p' "$0"; exit 0 ;;
    *) shift ;;
  esac
done

# ------------------------------------------------------------- JSON ヘルパー
esc() {
  printf '%s' "$1" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' | tr '\t' ' ' | tr -d '\000-\037'
}
jstr() {
  if [ -z "${1:-}" ]; then printf 'null'; else printf '"%s"' "$(esc "$1")"; fi
}
jnum() {
  case "${1:-}" in
    ''|*[!0-9.]*) printf 'null' ;;
    *) printf '%s' "$1" ;;
  esac
}
jbool() { if [ "${1:-0}" = "1" ]; then printf 'true'; else printf 'false'; fi; }
note() { if [ -z "$NOTES" ]; then NOTES="$(jstr "$1")"; else NOTES="$NOTES,$(jstr "$1")"; fi; }

# text から "キー: 値" を1件取り出す（キーは完全一致・記号込みで安全）
f() {
  printf '%s\n' "$2" | awk -v k="$1" '
    { line=$0; sub(/^[ \t]+/,"",line);
      if (index(line, k ": ")==1) { print substr(line, length(k)+3); exit } }'
}
# "12.34 GB (13,000,000 bytes)" → 12.34
num_head() { printf '%s' "$1" | awk '{print $1+0}'; }

echo ""
echo "  Kanana Studio - 端末スペック詳細取得 (macOS)"
echo "  読み取りのみ / 通信なし"
echo ""
printf "  収集中..."

HW="$(system_profiler SPHardwareDataType 2>/dev/null)"
SW="$(system_profiler SPSoftwareDataType 2>/dev/null)"
GPU_TXT="$(system_profiler SPDisplaysDataType 2>/dev/null)"
STO_TXT="$(system_profiler SPStorageDataType 2>/dev/null)"
PWR_TXT="$(system_profiler SPPowerDataType 2>/dev/null)"
MEM_TXT="$(system_profiler SPMemoryDataType 2>/dev/null)"

# --------------------------------------------------------------- 基本 / 資産
HOSTNAME_S="$(scutil --get ComputerName 2>/dev/null || hostname)"
MODEL_NAME="$(f 'Model Name' "$HW")"
MODEL_ID="$(sysctl -n hw.model 2>/dev/null)"
MODEL_NUMBER="$(f 'Model Number' "$HW")"
SERIAL="$(f 'Serial Number (system)' "$HW")"
UUID_S="$(f 'Hardware UUID' "$HW")"
FIRMWARE="$(f 'System Firmware Version' "$HW")"
[ -z "$FIRMWARE" ] && FIRMWARE="$(f 'Boot ROM Version' "$HW")"
OS_NAME="$(sw_vers -productName 2>/dev/null)"
OS_VER="$(sw_vers -productVersion 2>/dev/null)"
OS_BUILD="$(sw_vers -buildVersion 2>/dev/null)"
OS_ARCH="$(uname -m)"
SETUP_DATE="$(stat -f '%SB' -t '%Y-%m-%d' /var/db/.AppleSetupDone 2>/dev/null)"
LAST_BOOT="$(sysctl -n kern.boottime 2>/dev/null | sed -E 's/.*sec = ([0-9]+).*/\1/')"
if [ -n "$LAST_BOOT" ]; then LAST_BOOT="$(date -r "$LAST_BOOT" '+%Y-%m-%d %H:%M' 2>/dev/null)"; fi

case "$MODEL_ID" in
  MacBookPro*|MacBookAir*|MacBook*) CHASSIS="ノートPC" ;;
  Macmini*|iMac*|MacStudio*|MacPro*|Mac[0-9]*) CHASSIS="デスクトップ / ノート（Model Identifier参照）" ;;
  *) CHASSIS="" ;;
esac
case "$MODEL_NAME" in
  MacBook*) CHASSIS="ノートPC" ;;
  iMac*|Mac\ mini*|Mac\ Studio*|Mac\ Pro*) CHASSIS="デスクトップ" ;;
esac

# ----------------------------------------------------------------------- CPU
CHIP="$(f 'Chip' "$HW")"
IS_ARM=0
if [ "$OS_ARCH" = "arm64" ] || [ -n "$CHIP" ]; then IS_ARM=1; fi
if [ -n "$CHIP" ]; then
  CPU_MODEL="$CHIP"
  CPU_VENDOR="Apple"
else
  CPU_MODEL="$(sysctl -n machdep.cpu.brand_string 2>/dev/null)"
  [ -z "$CPU_MODEL" ] && CPU_MODEL="$(f 'Processor Name' "$HW")"
  CPU_VENDOR="Intel"
fi
CPU_PHYS="$(sysctl -n hw.physicalcpu 2>/dev/null)"
CPU_LOGI="$(sysctl -n hw.logicalcpu 2>/dev/null)"
CORE_P="$(sysctl -n hw.perflevel0.logicalcpu 2>/dev/null)"
CORE_E="$(sysctl -n hw.perflevel1.logicalcpu 2>/dev/null)"
CPU_HZ="$(sysctl -n hw.cpufrequency_max 2>/dev/null)"
CPU_MHZ=""
if [ -n "$CPU_HZ" ]; then CPU_MHZ="$(awk -v h="$CPU_HZ" 'BEGIN{printf "%d", h/1000000}')"; fi
if [ -z "$CPU_MHZ" ]; then
  PSPEED="$(f 'Processor Speed' "$HW")"
  if [ -n "$PSPEED" ]; then
    CPU_MHZ="$(printf '%s' "$PSPEED" | awk '{ if ($2 ~ /GHz/) printf "%d", $1*1000; else printf "%d", $1 }')"
  fi
fi
L3_MB="$(f 'L3 Cache' "$HW" | awk '{ if ($2 ~ /MB/) print $1; else if ($2 ~ /KB/) printf "%.1f", $1/1024 }')"

# -------------------------------------------------------------------- メモリ
MEM_BYTES="$(sysctl -n hw.memsize 2>/dev/null)"
MEM_GB=""
if [ -n "$MEM_BYTES" ]; then MEM_GB="$(awk -v b="$MEM_BYTES" 'BEGIN{printf "%.0f", b/1073741824}')"; fi
MEM_TYPE="$(f 'Type' "$MEM_TXT")"
MEM_SPEED="$(f 'Speed' "$MEM_TXT" | awk '{print $1+0}')"
MEM_UPGRADEABLE="$(f 'Upgradeable Memory' "$MEM_TXT")"
MEM_FREE_GB="$(vm_stat 2>/dev/null | awk '
  /page size of/ { ps=$8 }
  /Pages free/ { gsub(/\./,"",$3); free=$3 }
  /Pages inactive/ { gsub(/\./,"",$3); inact=$3 }
  END { if (ps>0) printf "%.1f", (free+inact)*ps/1073741824 }')"

# メモリモジュール（Intel Mac のみスロット情報あり）
MEM_MODULES=""
MEM_SLOTS_USED=0
if [ "$IS_ARM" = "0" ]; then
  MEM_MODULES="$(printf '%s\n' "$MEM_TXT" | awk '
    BEGIN { slot=""; size=""; type=""; speed=""; part=""; first=1 }
    function flush() {
      if (slot != "" && size != "" && size !~ /Empty/) {
        if (!first) printf ",";
        first=0;
        gsub(/"/,"",slot); gsub(/"/,"",part);
        sz=size+0;
        printf "{\"slot\":\"%s\",\"sizeGB\":%d,\"type\":\"%s\",\"speedMHz\":%d,\"partNumber\":\"%s\"}", slot, sz, type, speed+0, part;
      }
      slot=""; size=""; type=""; speed=""; part="";
    }
    /^ *(BANK|DIMM|SLOT|ChannelA|ChannelB)[^:]*:$/ { flush(); slot=$0; sub(/^ +/,"",slot); sub(/:$/,"",slot); next }
    /^ *Size: / { size=$2 " " $3; sub(/^ */,"",size); size=$2; next }
    /^ *Type: / { type=$2; next }
    /^ *Speed: / { speed=$2; next }
    /^ *Part Number: / { part=$3; next }
    END { flush() }')"
  MEM_SLOTS_USED="$(printf '%s' "$MEM_MODULES" | awk -F'},{' '{print ($0=="")?0:NF}')"
fi

# ----------------------------------------------------------------------- GPU
# Apple Silicon はユニファイドメモリのため VRAM 欄が存在しない
GPU_JSON="$(printf '%s\n' "$GPU_TXT" | awk -v arm="$IS_ARM" -v totalmem="${MEM_GB:-0}" '
  function esc(s) { gsub(/\\/,"\\\\",s); gsub(/"/,"\\\"",s); return s }
  function flush() {
    if (model != "") {
      if (!first) printf ",";
      first=0;
      printf "{\"name\":\"%s\"", esc(model);
      printf ",\"vendor\":\"%s\"", esc(vendor);
      if (vram != "") printf ",\"vramGB\":%s", vram; else printf ",\"vramGB\":null";
      if (cores != "") printf ",\"cores\":%d", cores; else printf ",\"cores\":null";
      printf ",\"metal\":\"%s\"", esc(metal);
      printf ",\"unifiedMemory\":%s", (arm=="1" ? "true" : "false");
      printf ",\"vramSource\":\"%s\"", (arm=="1" ? "ユニファイドメモリ（本体メモリと共有）" : "system_profiler");
      printf "}";
    }
    model=""; vendor=""; vram=""; cores=""; metal="";
  }
  BEGIN { first=1; model=""; vendor=""; vram=""; cores=""; metal="" }
  /^ *Chipset Model: / { flush(); model=$0; sub(/^ *Chipset Model: /,"",model); next }
  /^ *Vendor: / { vendor=$0; sub(/^ *Vendor: /,"",vendor); sub(/ *\(0x[0-9a-fA-F]+\)/,"",vendor); next }
  /^ *VRAM \(Total\): / { v=$0; sub(/^ *VRAM \(Total\): /,"",v); n=v+0; if (v ~ /MB/) n=n/1024; vram=sprintf("%.1f", n); next }
  /^ *VRAM \(Dynamic, Max\): / { v=$0; sub(/^ *VRAM \(Dynamic, Max\): /,"",v); n=v+0; if (v ~ /MB/) n=n/1024; vram=sprintf("%.1f", n); next }
  /^ *Total Number of Cores: / { c=$0; sub(/^ *Total Number of Cores: /,"",c); cores=c+0; next }
  /^ *Metal Support: / { metal=$0; sub(/^ *Metal Support: /,"",metal); next }
  END { flush() }')"

# ------------------------------------------------------------------ ディスプレイ
DISPLAY_JSON="$(printf '%s\n' "$GPU_TXT" | awk '
  function esc(s) { gsub(/\\/,"\\\\",s); gsub(/"/,"\\\"",s); return s }
  function flush() {
    if (res != "") {
      if (!first) printf ",";
      first=0;
      printf "{\"name\":\"%s\",\"resolution\":\"%s\",\"scaled\":\"%s\",\"type\":\"%s\",\"main\":%s}",
        esc(name), esc(res), esc(scaled), esc(dtype), (main=="Yes" ? "true" : "false");
    }
    name=""; res=""; scaled=""; dtype=""; main="";
  }
  BEGIN { first=1; indisp=0 }
  /^ *Displays:$/ { indisp=1; next }
  indisp && /^ *[^ ].*:$/ && !/^ *(Display Type|Resolution|UI Looks like|Main Display|Mirror|Online|Rotation|Connection Type|Automatically Adjust Brightness|Television)/ {
    flush(); name=$0; sub(/^ +/,"",name); sub(/:$/,"",name); next }
  /^ *Resolution: / { res=$0; sub(/^ *Resolution: /,"",res); next }
  /^ *UI Looks like: / { scaled=$0; sub(/^ *UI Looks like: /,"",scaled); next }
  /^ *Display Type: / { dtype=$0; sub(/^ *Display Type: /,"",dtype); next }
  /^ *Main Display: / { main=$0; sub(/^ *Main Display: /,"",main); next }
  END { flush() }')"

# ------------------------------------------------------------------ ストレージ
STORAGE_JSON="$(printf '%s\n' "$STO_TXT" | awk '
  function esc(s) { gsub(/\\/,"\\\\",s); gsub(/"/,"\\\"",s); return s }
  function flush() {
    if (vol != "") {
      if (!first) printf ",";
      first=0;
      printf "{\"volume\":\"%s\",\"model\":\"%s\",\"mediaType\":\"%s\",\"bus\":\"%s\",\"sizeGB\":%.0f,\"freeGB\":%.1f,\"fs\":\"%s\",\"health\":\"%s\",\"internal\":%s}",
        esc(vol), esc(model), esc(medium), esc(proto), cap, free, esc(fs), esc(smart), (internal=="Yes" ? "true" : "false");
    }
    vol=""; model=""; medium=""; proto=""; cap=0; free=0; fs=""; smart=""; internal="";
  }
  BEGIN { first=1 }
  /^ {4}[^ ].*:$/ { flush(); vol=$0; sub(/^ +/,"",vol); sub(/:$/,"",vol); next }
  /^ *Free: / { v=$0; sub(/^ *Free: /,"",v); free=v+0; if (v ~ /TB/) free=free*1024; next }
  /^ *Capacity: / { v=$0; sub(/^ *Capacity: /,"",v); cap=v+0; if (v ~ /TB/) cap=cap*1024; next }
  /^ *File System: / { fs=$0; sub(/^ *File System: /,"",fs); next }
  /^ *Device Name: / { model=$0; sub(/^ *Device Name: /,"",model); next }
  /^ *Medium Type: / { medium=$0; sub(/^ *Medium Type: /,"",medium); next }
  /^ *Protocol: / { proto=$0; sub(/^ *Protocol: /,"",proto); next }
  /^ *S\.M\.A\.R\.T\. Status: / { smart=$0; sub(/^ *S\.M\.A\.R\.T\. Status: /,"",smart); next }
  /^ *Internal: / { internal=$0; sub(/^ *Internal: /,"",internal); next }
  END { flush() }')"

# ---------------------------------------------------------------- バッテリー
BAT_PRESENT=0
BAT_CYCLES=""; BAT_COND=""; BAT_MAXCAP=""; BAT_CHARGE=""; BAT_CHARGING=""
if printf '%s' "$PWR_TXT" | grep -q 'Battery Information'; then
  BAT_PRESENT=1
  BAT_CYCLES="$(f 'Cycle Count' "$PWR_TXT")"
  BAT_COND="$(f 'Condition' "$PWR_TXT")"
  BAT_MAXCAP="$(f 'Maximum Capacity' "$PWR_TXT" | tr -d '%')"
  BAT_CHARGE="$(f 'State of Charge (%)' "$PWR_TXT")"
  BAT_CHARGING="$(f 'Charging' "$PWR_TXT")"
  if [ -z "$BAT_MAXCAP" ]; then
    note "バッテリー最大容量（劣化率）を取得できませんでした。設定 →「バッテリー」で確認できます。"
  fi
fi

# ------------------------------------------------------------------ ネットワーク
NET_JSON="$(networksetup -listallhardwareports 2>/dev/null | awk '
  function esc(s) { gsub(/\\/,"\\\\",s); gsub(/"/,"\\\"",s); return s }
  function flush() {
    if (dev != "" && mac != "" && mac != "N/A") {
      cmd = "ipconfig getifaddr " dev " 2>/dev/null";
      ip=""; cmd | getline ip; close(cmd);
      if (!first) printf ",";
      first=0;
      printf "{\"name\":\"%s\",\"device\":\"%s\",\"mac\":\"%s\",\"ipv4\":%s,\"connected\":%s}",
        esc(port), esc(dev), esc(mac), (ip=="" ? "null" : "\"" esc(ip) "\""), (ip=="" ? "false" : "true");
    }
    port=""; dev=""; mac="";
  }
  BEGIN { first=1 }
  /^Hardware Port: / { flush(); port=$0; sub(/^Hardware Port: /,"",port); next }
  /^Device: / { dev=$0; sub(/^Device: /,"",dev); next }
  /^Ethernet Address: / { mac=$0; sub(/^Ethernet Address: /,"",mac); next }
  END { flush() }')"

# ------------------------------------------------------------------ セキュリティ
SIP_STATUS="$(csrutil status 2>/dev/null | sed -E 's/.*status: ([a-z]+).*/\1/')"
case "$SIP_STATUS" in
  enabled) SIP_STATUS="有効" ;;
  disabled) SIP_STATUS="無効" ;;
  *) SIP_STATUS="" ;;
esac
FV_STATUS="$(fdesetup status 2>/dev/null | head -1)"
case "$FV_STATUS" in
  *"On"*) FV_STATUS="有効" ;;
  *"Off"*) FV_STATUS="無効" ;;
  *) FV_STATUS="" ;;
esac
GK_STATUS="$(spctl --status 2>/dev/null | head -1)"
case "$GK_STATUS" in
  *enabled*) GK_STATUS="有効" ;;
  *disabled*) GK_STATUS="無効" ;;
  *) GK_STATUS="" ;;
esac

# ------------------------------------------------------------------ ベンチマーク
BENCH_JSON="null"
if [ "$DO_BENCH" = "1" ]; then
  echo ""
  printf "  ベンチマーク実行中 (20秒程度)..."
  CPU_SCORE="$(perl -MTime::HiRes=time -e '
    my $t=time; my $a=0; for my $i (1..4000000) { $a += sqrt($i); }
    printf "%d", 4000000/(time-$t)/1000;' 2>/dev/null)"
  TMPF="${TMPDIR:-/tmp}/kanana-spec-bench-$$.bin"
  DISK_W="$(dd if=/dev/zero of="$TMPF" bs=1m count=256 2>&1 | awk '
    /bytes/ { for(i=1;i<=NF;i++) if ($i ~ /^\(/) { gsub(/[(]/,"",$i); printf "%d", $i/1048576 } }')"
  DISK_R="$(dd if="$TMPF" of=/dev/null bs=1m 2>&1 | awk '
    /bytes/ { for(i=1;i<=NF;i++) if ($i ~ /^\(/) { gsub(/[(]/,"",$i); printf "%d", $i/1048576 } }')"
  rm -f "$TMPF"
  BENCH_JSON="{\"cpuSingleScore\":$(jnum "$CPU_SCORE"),\"diskWriteMBps\":$(jnum "$DISK_W"),\"diskReadMBps\":$(jnum "$DISK_R"),\"note\":$(jstr 'perl / dd による簡易計測です。Windows版の数値とは実行環境が異なるため直接比較はできません。読み込みはキャッシュの影響を受けます。')}"
  echo " 完了"
fi

if [ "$IS_ARM" = "1" ]; then
  note "Apple Silicon はユニファイドメモリのため VRAM は独立して存在しません。GPU が利用できる容量は本体メモリと共有です。"
  note "メモリはオンパッケージのため増設できません（スロット情報なし）。"
fi
[ -z "$SERIAL" ] && note "シリアル番号を取得できませんでした。"

# ------------------------------------------------------------------ 組み立て
[ -z "$OUTFILE" ] && OUTFILE="$HOME/spec-$(printf '%s' "$HOSTNAME_S" | tr -cd 'A-Za-z0-9-_')-$(date '+%Y%m%d').json"

cat > "$OUTFILE" <<EOF
{
  "schema": $(jstr "$SCHEMA"),
  "collector": $(jstr "$COLLECTOR"),
  "platform": "macos",
  "generatedAt": $(jstr "$(date '+%Y-%m-%dT%H:%M:%S%z')"),
  "elevated": false,
  "asset": {
    "hostname": $(jstr "$HOSTNAME_S"),
    "manufacturer": "Apple",
    "model": $(jstr "$MODEL_NAME"),
    "modelFamily": $(jstr "$MODEL_ID"),
    "modelNumber": $(jstr "$MODEL_NUMBER"),
    "serial": $(jstr "$SERIAL"),
    "uuid": $(jstr "$UUID_S"),
    "chassis": $(jstr "$CHASSIS"),
    "boardVendor": "Apple",
    "boardModel": $(jstr "$MODEL_ID"),
    "biosVersion": $(jstr "$FIRMWARE"),
    "biosDate": null,
    "osName": $(jstr "$OS_NAME"),
    "osVersion": $(jstr "$OS_VER"),
    "osBuild": $(jstr "$OS_BUILD"),
    "osArch": $(jstr "$OS_ARCH"),
    "osInstallDate": $(jstr "$SETUP_DATE"),
    "lastBoot": $(jstr "$LAST_BOOT"),
    "currentUser": $(jstr "${USER:-}"),
    "domain": null
  },
  "cpu": {
    "model": $(jstr "$CPU_MODEL"),
    "vendor": $(jstr "$CPU_VENDOR"),
    "socketCount": 1,
    "physicalCores": $(jnum "$CPU_PHYS"),
    "logicalCores": $(jnum "$CPU_LOGI"),
    "performanceCores": $(jnum "$CORE_P"),
    "efficiencyCores": $(jnum "$CORE_E"),
    "maxClockMHz": $(jnum "$CPU_MHZ"),
    "l3CacheMB": $(jnum "$L3_MB"),
    "architecture": $(jstr "$OS_ARCH"),
    "appleSilicon": $(jbool "$IS_ARM")
  },
  "memory": {
    "totalGB": $(jnum "$MEM_GB"),
    "installedGB": $(jnum "$MEM_GB"),
    "availableGB": $(jnum "$MEM_FREE_GB"),
    "slotsUsed": $(jnum "$MEM_SLOTS_USED"),
    "slotsTotal": null,
    "type": $(jstr "$MEM_TYPE"),
    "speedMHz": $(jnum "$MEM_SPEED"),
    "upgradeable": $(jstr "$MEM_UPGRADEABLE"),
    "unified": $(jbool "$IS_ARM"),
    "modules": [$MEM_MODULES]
  },
  "gpus": [$GPU_JSON],
  "displays": [$DISPLAY_JSON],
  "storage": [$STORAGE_JSON],
  "volumes": [],
  "battery": {
    "present": $(jbool "$BAT_PRESENT"),
    "chargePercent": $(jnum "$BAT_CHARGE"),
    "status": $(jstr "$(if [ "$BAT_CHARGING" = "Yes" ]; then echo '充電中 / AC接続'; elif [ "$BAT_PRESENT" = "1" ]; then echo 'バッテリー駆動'; fi)"),
    "cycleCount": $(jnum "$BAT_CYCLES"),
    "condition": $(jstr "$BAT_COND"),
    "healthPercent": $(jnum "$BAT_MAXCAP")
  },
  "network": [$NET_JSON],
  "security": {
    "secureBoot": $(jstr "$SIP_STATUS"),
    "fileVault": $(jstr "$FV_STATUS"),
    "gatekeeper": $(jstr "$GK_STATUS")
  },
  "benchmark": $BENCH_JSON,
  "notes": [$NOTES]
}
EOF

echo " 完了"
echo ""
echo "  --- 取得結果（抜粋）---------------------------------------"
echo "  機種      : $MODEL_NAME ($MODEL_ID)"
echo "  シリアル  : $SERIAL"
echo "  チップ    : $CPU_MODEL"
echo "  コア      : ${CPU_PHYS:-?} 物理 / ${CPU_LOGI:-?} 論理${CORE_P:+ (P${CORE_P}/E${CORE_E:-0})}"
echo "  メモリ    : ${MEM_GB:-?} GB ${MEM_TYPE}"
echo "  OS        : $OS_NAME $OS_VER ($OS_BUILD)"
if [ "$BAT_PRESENT" = "1" ]; then
  echo "  バッテリー: 最大容量 ${BAT_MAXCAP:-?}% / ${BAT_CYCLES:-?} 回充電"
fi
echo "  -----------------------------------------------------------"
echo ""
echo "  保存しました: $OUTFILE"
echo "  この JSON を https://kanana-studio.com/tools/spec/ にドラッグ＆ドロップすると"
echo "  詳細な作業適性判定と資産管理用の一覧が表示されます。"
echo ""
if [ "$DO_BENCH" = "0" ]; then
  echo "  ヒント: --bench を付けると簡易ベンチマークも計測します。"
  echo ""
fi
