emirhanyildirim34555's picture
Publish reviewed research staging to main
6d5d7e5 verified
Raw History Blame Contribute Delete
9.96 kB
'use strict';
const el=id=>document.getElementById(id);
let schema=null,lastResult=null,activeToken='',busy=false;
function status(text,error=false){el('status').textContent=text;el('status').className=error?'error':'';}
function metrics(result){el('metrics').replaceChildren();if(!result)return;const values=result.predictors||result.latent_state||(result.schema==='mri.fitted-research/1'?{raw_reference_distance:result.raw_reference_distance,anomaly_percentile:result.anomaly_percentile,nearest_reference_cluster:result.nearest_reference_cluster}:{});for(const [label,value] of Object.entries(values)){const row=document.createElement('div'),key=document.createElement('dt'),val=document.createElement('dd');key.textContent=label;val.textContent=typeof value==='number'?Number(value.toPrecision(6)).toString():String(value);row.append(key,val);el('metrics').append(row);}}
async function call(path,body){const options={headers:{Authorization:'Bearer '+activeToken},cache:'no-store',credentials:'omit'};if(body!==undefined){options.method='POST';options.headers['Content-Type']='application/json';options.body=typeof body==='string'?body:JSON.stringify(body);}const r=await fetch(path,options);const data=await r.json();if(!r.ok)throw new Error(data.error||data.detail||('HTTP '+r.status));return data;}
function pick(){if(!schema)return;const p=el('product').value,m=schema.models[p];el('scope').textContent=m.scope;el('modelmeta').textContent=m.feature_order.length+' özellik • parametre paketi SHA-256: '+m.parameter_pack_sha256;el('input').value=JSON.stringify(m.synthetic_example,null,2);el('compat-label').hidden=p!=='rhythm';el('synthetic').checked=false;el('compat').checked=false;lastResult=null;metrics(null);el('download').disabled=true;el('output').textContent='Yeni model seçildi; henüz hesaplama yapılmadı.';status('Sentetik örnek yüklendi. Girdiyi ve kapsamı inceleyin.');}
el('connect').addEventListener('click',async()=>{activeToken=el('token').value;try{schema=await call('/research-schema');el('token').value='';el('connection').textContent='Yalnız yerel sunucuya bağlı';for(const id of ['product','input','run','example'])el(id).disabled=false;pick();refreshAdvanced();}catch(e){activeToken='';schema=null;for(const id of ['product','input','run','example'])el(id).disabled=true;el('connection').textContent='Bağlantı başarısız';status(e.message,true);refreshAdvanced();}});
el('product').addEventListener('change',pick);el('example').addEventListener('click',pick);
el('run').addEventListener('click',async()=>{if(busy)return;try{if(!el('synthetic').checked)throw new Error('Önce sentetik girdi onayını işaretleyin.');const p=el('product').value;if(p==='rhythm'&&!el('compat').checked)throw new Error('RAS sürüm farkı onayı gerekli.');const features=JSON.parse(el('input').value);if(!features||Array.isArray(features)||typeof features!=='object')throw new Error('Özellikler JSON nesnesi olmalı.');busy=true;refreshAdvanced();el('connect').disabled=true;el('run').disabled=true;el('product').disabled=true;el('example').disabled=true;lastResult=null;metrics(null);el('download').disabled=true;status('Gerçek parametrelerle hesaplanıyor…');const rawBody='{"features":'+el('input').value+',"synthetic":true,"acknowledge_export_version_mismatch":'+JSON.stringify(el('compat').checked)+'}';lastResult=await call('/research/'+p,rawBody);metrics(lastResult);el('output').textContent=JSON.stringify(lastResult,null,2);el('download').disabled=false;status('Hesaplama tamamlandı • sentetik araştırma girdisi');}catch(e){lastResult=null;metrics(null);el('download').disabled=true;el('output').textContent='Bu giriş için yeni geçerli sonuç üretilmedi.';status(e.message,true);}finally{busy=false;el('run').disabled=!schema;el('product').disabled=!schema;el('example').disabled=!schema;el('connect').disabled=false;refreshAdvanced();}});
el('download').addEventListener('click',()=>{if(!lastResult)return;const url=URL.createObjectURL(new Blob([JSON.stringify(lastResult,null,2)],{type:'application/json'}));const a=document.createElement('a');a.href=url;a.download='humanization-research-result.json';a.click();setTimeout(()=>URL.revokeObjectURL(url),1000);});
el('clear').addEventListener('click',()=>{if(busy){status('Önce yürüyen hesaplamanın bitmesini bekleyin.',true);return;}lastResult=null;metrics(null);schema=null;activeToken='';el('token').value='';el('input').value='';el('output').textContent='Oturum ekranı temizlendi. Önceden dışa aktarılan dosyalar silinmedi.';el('connection').textContent='Bağlantı bekleniyor';el('modelmeta').textContent='';el('scope').textContent='Tekrar bağlanın.';for(const id of ['product','input','run','example','download'])el(id).disabled=true;status('Yerel sayfa oturumu temizlendi.');clearAdvanced();refreshAdvanced();});
// CP08: bounded byte-file and original signal-recipe flows. Nothing is persisted in browser storage.
let lastCapsule=null,lastSignal=null;
function refreshAdvanced(){
for(const id of ['file-input','file-operation','file-modalities','file-run','signal-input','signal-example','signal-run'])el(id).disabled=!schema||busy;
el('file-download').disabled=!lastCapsule||busy;el('signal-download').disabled=!lastSignal||busy;
}
function clearAdvanced(){lastCapsule=null;lastSignal=null;el('file-input').value='';el('signal-input').value='';el('file-output').textContent='Dosya oturumu temizlendi; kaydedilmiş ZIP’ler silinmedi.';el('signal-output').textContent='Sinyal oturumu temizlendi.';for(const id of ['file-synthetic','signal-synthetic','signal-compat'])el(id).checked=false;}
function advancedBusy(value){busy=value;for(const id of ['run','product','example'])el(id).disabled=value||!schema;el('connect').disabled=value;refreshAdvanced();}
function saveBlob(blob,name){const url=URL.createObjectURL(blob),a=document.createElement('a');a.href=url;a.download=name;a.click();setTimeout(()=>URL.revokeObjectURL(url),1000);}
el('signal-example').addEventListener('click',()=>{const samples=[];for(let i=0;i<600;i++){const t=i/50;samples.push([t,.1*Math.sin(3*t),.15*Math.cos(7*t),9.8+.4*Math.sin(2*Math.PI*1.5*t)]);}el('signal-input').value=JSON.stringify({samples,timestamp_unit:'seconds',acceleration_unit:'m/s2',coordinate_frame:'device_xyz',recipe:'archived-build-mvp-signal-rows/1'});el('signal-synthetic').checked=false;el('signal-compat').checked=false;lastSignal=null;refreshAdvanced();});
el('signal-run').addEventListener('click',async()=>{
if(busy||!schema)return;
try{if(!el('signal-synthetic').checked||!el('signal-compat').checked)throw new Error('Sinyal ve açık kabul sınırlarını onaylayın.');
const raw=el('signal-input').value;const x=JSON.parse(raw);if(!x||Array.isArray(x)||typeof x!=='object')throw new Error('Ham sinyal bir JSON nesnesi olmalıdır.');
lastSignal=null;advancedBusy(true);el('signal-output').textContent='Özgün kaynak tarifi ve gerçek parametreler çalışıyor…';
const result=await call('/research/rhythm-signal','{"synthetic":true,"acknowledge_export_version_mismatch":true,"imu":'+raw+'}');
lastSignal=result;el('signal-output').textContent=JSON.stringify(result,null,2);
}catch(e){lastSignal=null;el('signal-output').textContent='Sonuç üretilmedi: '+e.message;}finally{advancedBusy(false);}
});
el('signal-download').addEventListener('click',()=>{if(lastSignal)saveBlob(new Blob([JSON.stringify(lastSignal,null,2)],{type:'application/json'}),'humanization-raw-signal-result.json');});
el('file-run').addEventListener('click',async()=>{
if(busy||!schema)return;
try{const file=el('file-input').files[0];if(!file)throw new Error('Dosya seçin.');if(!el('file-synthetic').checked)throw new Error('Dosyanın sentetik olduğunu onaylayın.');if(file.size<1||file.size>40*1024*1024)throw new Error('Dosya 1 bayt–40 MiB aralığında olmalı.');
const low=file.name.toLowerCase(),kind=low.endsWith('.nii.gz')?'nifti-gzip':low.endsWith('.nii')?'nifti':low.endsWith('.zip')?'capsule-bundle':null;
if(!kind)throw new Error('Desteklenen dosya: .nii, .nii.gz veya kapsül ZIP.');
const operation=el('file-operation').value,modalities=el('file-modalities').value;
if(kind==='capsule-bundle'&&operation!=='qc')throw new Error('Kapsül ZIP’i için yalnız kontrol işlemi seçin.');
if(operation!=='qc'&&!modalities)throw new Error('Dosyadaki kanal düzenini açıkça seçin.');
lastCapsule=null;advancedBusy(true);el('file-output').textContent='Dosya geçici yerel alanda işleniyor…';
const headers={Authorization:'Bearer '+activeToken,'Content-Type':'application/octet-stream','X-Humanization-File-Kind':kind,'X-Humanization-Synthetic':'true'};
if(modalities)headers['X-Humanization-Modalities']=modalities;
const response=await fetch('/research-file/'+operation,{method:'POST',headers,body:file,credentials:'omit',cache:'no-store'});
if(!response.ok){const data=await response.json();throw new Error(data.error||data.detail||('HTTP '+response.status));}
if(operation==='capsule'){
const blob=await response.blob(),expected=response.headers.get('X-Artifact-SHA256');
if(!crypto.subtle)throw new Error('Dosya doğrulaması için yerel güvenli tarayıcı bağlamı gerekli.');
const actual=Array.from(new Uint8Array(await crypto.subtle.digest('SHA-256',await blob.arrayBuffer()))).map(b=>b.toString(16).padStart(2,'0')).join('');
if(actual!==expected)throw new Error('İndirilen kapsül hash’i eşleşmiyor.');
lastCapsule=blob;el('file-output').textContent=JSON.stringify({file_bytes:blob.size,sha256:actual,synthetic:true,spatial_metadata_included:true,clinical_claim:false},null,2);
}else{el('file-output').textContent=JSON.stringify(await response.json(),null,2);}
}catch(e){lastCapsule=null;el('file-output').textContent='Dosya sonucu üretilmedi: '+e.message;}finally{advancedBusy(false);}
});
el('file-download').addEventListener('click',()=>{if(lastCapsule)saveBlob(lastCapsule,'humanization-spatial-capsules.zip');});
refreshAdvanced();