commit 8d70549f4025f9877762ea0137302f5c7424b3b7
Author: PixelstoMotors <studio@adaptdesign.jp>
Date:   Sun Nov 1 19:21:23 2026 +0900

    観察シート：1つの作業を10回測ったら早いとき・遅いときも出す（画面・送る文・取り込みの値の案）
    
    - 速い方の4分の1と遅い方の4分の1を外した幅。シートと field_import.py で同じ計算
    - 試算・前提の表には入れない。記録として残すだけ
    
    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01LevEXTjmDgrBZ74rhCRBtF

diff --git a/public/sim/serving-robot-observation.html b/public/sim/serving-robot-observation.html
index e5342b8..8007b94 100644
--- a/public/sim/serving-robot-observation.html
+++ b/public/sim/serving-robot-observation.html
@@ -267,6 +267,10 @@ function T(k){var a=TASKS.concat([ROBOT]);for(var i=0;i<a.length;i++)if(a[i].k==
 function cnt(k){return S.recs.filter(function(r){return r.k===k;}).length;}
 function jp(sec){sec=Math.max(0,Math.round(sec));var m=Math.floor(sec/60),s=sec%60;return m?(m+'分'+(s?s+'秒':'')):s+'秒';}
 function clock(ms){var s=Math.max(0,Math.floor(ms/1000));return Math.floor(s/60)+':'+String(s%60).padStart(2,'0');}
+var SPREAD=10;
+// 早いとき・遅いとき：速い方の4分の1と遅い方の4分の1を外した幅（取り込みの道具 field_import.py と同じ計算）。SPREAD 回に届くまでは出さない
+function qt(b,p){var h=(b.length-1)*p,i=Math.floor(h);return i+1<b.length?b[i]+(b[i+1]-b[i])*(h-i):b[i];}
+function spread(a){if(a.length<SPREAD)return null;var b=a.slice().sort(function(x,y){return x-y;});return [qt(b,.25),qt(b,.75)];}
 function med(a){if(!a.length)return null;var b=a.slice().sort(function(x,y){return x-y;}),m=Math.floor(b.length/2);return b.length%2?b[m]:(b[m-1]+b[m])/2;}
 function buzz(){try{navigator.vibrate&&navigator.vibrate(15);}catch(e){}}
 var toastTimer=null;
@@ -315,7 +319,7 @@ function hasRecs(){return !!(S.recs.length||S.arrivals.length||S.leaves.length);
 function renderSum(){
   var rows=tasks().filter(function(t){return cnt(t.k);}).map(function(t){var a=S.recs.filter(function(r){return r.k===t.k;});var m=med(a.map(function(r){return r.sec;}));
     var extra='';if(t.k==='robot'&&a.length){var st=a.reduce(function(s,r){return s+(r.stops||0);},0),hp=a.filter(function(r){return r.helps;}).length;extra='<small>止まった'+st+'回・人が動かした'+a.reduce(function(s,r){return s+(r.helps||0);},0)+'回</small>';}
-    return '<div class="row"><b>'+t.t+'</b><span class="v">'+(m==null?'<span class="num">—</span>':'<span class="num">'+jp(m)+'</span>')+'<small>'+a.length+'回測った'+(a.length&&a.length<GOAL?'（あと'+(GOAL-a.length)+'回）':'')+'</small>'+extra+'</span></div>';});
+    return '<div class="row"><b>'+t.t+'</b><span class="v">'+(m==null?'<span class="num">—</span>':'<span class="num">'+jp(m)+'</span>')+(function(w){return w?'<small>早いとき'+jp(w[0])+'・遅いとき'+jp(w[1])+'</small>':'';})(spread(a.map(function(r){return r.sec;})))+'<small>'+a.length+'回測った'+(a.length&&a.length<GOAL?'（あと'+(GOAL-a.length)+'回）':'')+'</small>'+extra+'</span></div>';});
   var f=flow();
   if(f){
     var sub=f.aRate==null?'<small>15分以上数えると、1時間あたりと回転率が出ます</small>':'<small>1時間に 来店 約'+Math.round(f.aRate)+'組・会計 約'+Math.round(f.dRate)+'組</small>';
@@ -379,7 +383,7 @@ $('fTables').addEventListener('input',function(e){S.store.tables=e.target.value=
 /* 送る */
 function summaryText(){
   var L=['観察シートの記録','目的：'+(PURPOSE[S.purpose]||''),'お店：'+(S.store.name||'（未入力）')+'　スタッフ'+S.store.staff+'人'+(S.purpose==='post'?'　ロボット'+S.store.robots+'台':''),'時間帯：'+(S.store.time||'')+(S.store.tags&&S.store.tags.length?'　'+S.store.tags.join('・'):''),(S.store.note?'メモ：'+S.store.note:'')].filter(Boolean);
-  tasks().forEach(function(t){var a=S.recs.filter(function(r){return r.k===t.k;}).map(function(r){return r.sec;});if(a.length)L.push(t.t+'：だいたい'+jp(med(a))+'（'+a.length+'回）');});
+  tasks().forEach(function(t){var a=S.recs.filter(function(r){return r.k===t.k;}).map(function(r){return r.sec;});if(a.length){var w=spread(a);L.push(t.t+'：だいたい'+jp(med(a))+(w?'・早いとき'+jp(w[0])+'・遅いとき'+jp(w[1]):'')+'（'+a.length+'回）');}});
   var f=flow();if(S.store.tables)L.splice(3,0,'卓の数：約'+S.store.tables+'卓');
   if(f){L.push('出入り：入ってきた'+f.a+'組・会計した'+f.d+'組'+(S.store.occ0!==''&&S.store.occ0!=null?'（数えはじめに'+S.store.occ0+'卓にお客さん）':''));
     if(f.aRate!=null)L.push('1時間あたり：来店 約'+Math.round(f.aRate)+'組・会計 約'+Math.round(f.dRate)+'組');
diff --git a/tools/serving_sim/README.md b/tools/serving_sim/README.md
index b77d472..5084bd0 100644
--- a/tools/serving_sim/README.md
+++ b/tools/serving_sim/README.md
@@ -69,6 +69,7 @@ python3 field_import.py <field のフォルダ> 届いた文.txt     # field の
 
 決まり（2026-10-31 エイイチと決めた）：
 - 値は中央値。店ごとに15回に届くまでは「参考」
+- 1つの店で10回以上測った作業は、早いとき・遅いとき（速い方の4分の1と遅い方の4分の1を外した幅）も出す。シートの画面・送る文と同じ計算。試算には入れず、記録として残す（2026-11-01 決定）
 - 標準の値を置き換える候補にするのは、2店以上・合わせて15回以上そろったとき。表は自動で書き換えない。proposal.md の案と差を見て、エイイチが承認してから直す
 - 表に入れるときは basis を「現場」、n に回数、source に店の数と期間を書く。店の名前は書かない
 
