Spaces:
Running
Running
Per-board participation guide with a ready-to-paste prompt and a runnable skeleton
Browse filesA generic guide makes each entrant adapt it to their board, and most drop out at that step. The guide tab now fills in this board target, split year, experimental error and baselines, so the prompt and the starter script can be copied as they are.
- i18n.js +50 -2
- index.html +119 -1
i18n.js
CHANGED
|
@@ -171,7 +171,31 @@ ko: {
|
|
| 171 |
|
| 172 |
secOpen: "๊ฐ์ค ์์ ",
|
| 173 |
openLead: "๊ฐ ๋ถ๋ฌธ์ ํ๋์์๊ณผ ์คํ ์ค์ฐจ๊ฐ ํ๋ณด๋ ๋ค์ ์ฝ๋๋ค. ํ๋ณด๋์ง ์์ ๋ถ๋ฌธ์ ์ด์ง ์์ต๋๋ค.",
|
| 174 |
-
learnMore: "์์ธํ"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 175 |
},
|
| 176 |
|
| 177 |
en: {
|
|
@@ -355,6 +379,30 @@ en: {
|
|
| 355 |
secOpen: "Opening next",
|
| 356 |
openLead: "A board opens only once its holdout and experimental error are established. " +
|
| 357 |
"Boards without them are not opened.",
|
| 358 |
-
learnMore: "Detail"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 359 |
}
|
| 360 |
};
|
|
|
|
| 171 |
|
| 172 |
secOpen: "๊ฐ์ค ์์ ",
|
| 173 |
openLead: "๊ฐ ๋ถ๋ฌธ์ ํ๋์์๊ณผ ์คํ ์ค์ฐจ๊ฐ ํ๋ณด๋ ๋ค์ ์ฝ๋๋ค. ํ๋ณด๋์ง ์์ ๋ถ๋ฌธ์ ์ด์ง ์์ต๋๋ค.",
|
| 174 |
+
learnMore: "์์ธํ",
|
| 175 |
+
|
| 176 |
+
tabGuide: "์ฐธ์ฌ ๊ฐ์ด๋",
|
| 177 |
+
gdIntro: "์์ธก ๋๊ตฌ๋ฅผ ์ฒ์ ๋ง๋์ ๋ค๋ฉด ์๋ ์์๋๋ก ํ์๋ฉด ๋ฉ๋๋ค. " +
|
| 178 |
+
"์ง์ ์ฝ๋ฉํ์
๋ ๋๊ณ , ์๋ ํ๋กฌํํธ๋ฅผ ์ธ์ด๋ชจ๋ธ์ ๊ทธ๋๋ก ๋ถ์ฌ ๋ฃ์ผ์
๋ ๋ฉ๋๋ค.",
|
| 179 |
+
gdWhat: "๋ฌด์์ ๋ง๋๋๊ฐ",
|
| 180 |
+
gdWhatD: "ํํฉ๋ฌผ ๊ตฌ์กฐ(SMILES)๋ฅผ ๋ฐ์ <b>๊ฐ ํ๋</b>๋ฅผ ๋ด๋๋ ํจ์์
๋๋ค. " +
|
| 181 |
+
"๊ทธ ๊ฐ์ด ์ค์ธก๊ณผ ์ผ๋ง๋ ๊ฐ๊น์ด์ง๋ก ์ฑ์ ํฉ๋๋ค.",
|
| 182 |
+
gdPrompt: "์ธ์ด๋ชจ๋ธ์ฉ ํ๋กฌํํธ",
|
| 183 |
+
gdPromptD: "์๋๋ฅผ ํต์งธ๋ก ๋ณต์ฌํด Claude ยท GPT ยท Gemini ๋ฑ์ ๋ถ์ฌ ๋ฃ์ผ์ญ์์ค. " +
|
| 184 |
+
"์ด ๋ถ๋ฌธ์ ๊ฐ์ด ์ด๋ฏธ ์ฑ์์ ธ ์์ต๋๋ค.",
|
| 185 |
+
gdCopy: "๋ณต์ฌ", gdCopied: "๋ณต์ฌ๋จ",
|
| 186 |
+
gdStarter: "๋ฐ๋ก ๋๋ ค๋ณผ ์ ์๋ ๋ผ๋",
|
| 187 |
+
gdStarterD: "์ง์ ์ง์๋ ค๋ฉด ์ด ๋ผ๋์์ ์์ํ์ญ์์ค. ํ๋ จ ์๋ฃ๋ฅผ ๋ฐ์ ์ง๋ฌธ์ ๋ง๋ค๊ณ " +
|
| 188 |
+
"๋ชจ๋ธ์ ํ์ตํด ์ ์ถ ํ์ผ๊น์ง ์๋๋ค.",
|
| 189 |
+
gdRules: "์ง์ผ์ผ ํ ๊ฒ",
|
| 190 |
+
gdR1: "๊ธฐ์ค์ผ ์ดํ ์ต์ด ๋ณด๊ณ ๋ ํํฉ๋ฌผ์ ํ์ต์ ์ฐ์ง ๋ง์ญ์์ค. ๊ทธ๊ฒ์ด ํ
์คํธ์
์
๋๋ค.",
|
| 191 |
+
gdR2: "๊ฐ์ ํํฉ๋ฌผ์ด ์ฌ๋ฌ ๋
ผ๋ฌธ์ ์์ผ๋ฉด InChIKey ๋ก ์ ์ด ์ค์๊ฐ์ ์ฐ์ญ์์ค. " +
|
| 192 |
+
"๋ฌธ์์ด๋ก ์ ์ผ๋ฉด ๊ฐ์ ๋ถ์๊ฐ ์ฌ๋ฌ ๋ฒ ๋ค์ด๊ฐ๋๋ค.",
|
| 193 |
+
gdR3: "์ ๋ต์ ์กฐํํด ์ฑ์ฐ์ง ๋ง์ญ์์ค. ์์ธก๊ฐ์ด ์ค์ธก๊ณผ ์์ ์๋ฆฌ๊น์ง ์ผ์นํ๋ ๋ฐ๋๋ฅผ " +
|
| 194 |
+
"๊ฒ์ฌํด ์์ํ์ ํจ๊ป ํ์ํฉ๋๋ค.",
|
| 195 |
+
gdR4: "๋ฐฉ๋ฒ์๋ ์ ํ์ด ์์ต๋๋ค. ์ง๋ฌธ+ํธ๋ฆฌ ยท ๊ทธ๋ํ ์ ๊ฒฝ๋ง ยท ์ฌ์ ํ์ต ๋ชจ๋ธ ยท ๋ฌผ๋ฆฌ ๊ณ์ฐ " +
|
| 196 |
+
"๋ฌด์์ด๋ ์ข์ต๋๋ค.",
|
| 197 |
+
gdTarget: "๋์ด์ผ ํ ์ ",
|
| 198 |
+
gdTargetD: "๊ธฐ์ค์ ์ ๋์ง ๋ชปํ๋ฉด ์์ํ์์ ๊ทธ ์๋์ ํ์๋ฉ๋๋ค.",
|
| 199 |
},
|
| 200 |
|
| 201 |
en: {
|
|
|
|
| 379 |
secOpen: "Opening next",
|
| 380 |
openLead: "A board opens only once its holdout and experimental error are established. " +
|
| 381 |
"Boards without them are not opened.",
|
| 382 |
+
learnMore: "Detail",
|
| 383 |
+
|
| 384 |
+
tabGuide: "Guide",
|
| 385 |
+
gdIntro: "If this is your first predictor, follow the steps below. Write it yourself, " +
|
| 386 |
+
"or paste the prompt into a language model as it is.",
|
| 387 |
+
gdWhat: "What you are building",
|
| 388 |
+
gdWhatD: "A function that takes a structure (SMILES) and returns <b>one number</b>. " +
|
| 389 |
+
"We score how close that number is to the measured value.",
|
| 390 |
+
gdPrompt: "Prompt for a language model",
|
| 391 |
+
gdPromptD: "Copy the whole block into Claude, GPT, Gemini or similar. " +
|
| 392 |
+
"The values for this board are already filled in.",
|
| 393 |
+
gdCopy: "Copy", gdCopied: "Copied",
|
| 394 |
+
gdStarter: "A skeleton you can run",
|
| 395 |
+
gdStarterD: "If you would rather write it yourself, start here. It pulls the training data, " +
|
| 396 |
+
"builds fingerprints, fits a model and writes the submission file.",
|
| 397 |
+
gdRules: "Rules to observe",
|
| 398 |
+
gdR1: "Do not train on compounds first reported on or after the split year. That is the test set.",
|
| 399 |
+
gdR2: "Fold duplicate measurements by InChIKey and take the median. Folding by SMILES string " +
|
| 400 |
+
"leaves the same molecule in several times.",
|
| 401 |
+
gdR3: "Do not fill predictions by looking up the answer. We measure how many predictions match " +
|
| 402 |
+
"the measured value to the decimal and show it on the leaderboard.",
|
| 403 |
+
gdR4: "There is no restriction on method. Fingerprints and trees, graph networks, pretrained " +
|
| 404 |
+
"models, physics-based calculation โ all are fine.",
|
| 405 |
+
gdTarget: "Lines to cross",
|
| 406 |
+
gdTargetD: "A submission that does not clear a baseline is shown below it on the leaderboard.",
|
| 407 |
}
|
| 408 |
};
|
index.html
CHANGED
|
@@ -469,7 +469,7 @@ async function board(name,tab){
|
|
| 469 |
const b=BOARDS[name]||await j("/api/board/"+encodeURIComponent(name));
|
| 470 |
const cat=CATS.categories.find(c=>(c.boards||[]).includes(name));
|
| 471 |
const cn=cat?(L==="ko"?cat.name:cat.en):"";
|
| 472 |
-
const TT=[["rank",t.tabRank],["submit",t.tabSubmit],["info",t.tabInfo]];
|
| 473 |
app.innerHTML=W(`
|
| 474 |
<div class="crumb"><a href="#/">${t.all}</a> โบ <a href="#/c/${cat?cat.id:""}">${esc(cn)}</a> โบ ${esc(b.board)}</div>
|
| 475 |
<h1 class="ttl">${esc(b.board)}<span class="chip">${b.split_grade}/${b.answer_grade}</span></h1>
|
|
@@ -480,6 +480,7 @@ async function board(name,tab){
|
|
| 480 |
<div id="pane"><div class="skel" style="margin-top:20px"></div></div>`);
|
| 481 |
if(tab==="rank")return paneRank(b);
|
| 482 |
if(tab==="submit")return paneSubmit(b);
|
|
|
|
| 483 |
paneInfo(b);
|
| 484 |
}
|
| 485 |
|
|
@@ -511,6 +512,123 @@ async function paneRank(b){
|
|
| 511 |
: t.noEntries}</p>`;
|
| 512 |
}
|
| 513 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 514 |
function paneInfo(b){
|
| 515 |
const nf=b.noise_floor, bl=b.baselines;
|
| 516 |
$("#pane").innerHTML=`
|
|
|
|
| 469 |
const b=BOARDS[name]||await j("/api/board/"+encodeURIComponent(name));
|
| 470 |
const cat=CATS.categories.find(c=>(c.boards||[]).includes(name));
|
| 471 |
const cn=cat?(L==="ko"?cat.name:cat.en):"";
|
| 472 |
+
const TT=[["rank",t.tabRank],["submit",t.tabSubmit],["guide",t.tabGuide],["info",t.tabInfo]];
|
| 473 |
app.innerHTML=W(`
|
| 474 |
<div class="crumb"><a href="#/">${t.all}</a> โบ <a href="#/c/${cat?cat.id:""}">${esc(cn)}</a> โบ ${esc(b.board)}</div>
|
| 475 |
<h1 class="ttl">${esc(b.board)}<span class="chip">${b.split_grade}/${b.answer_grade}</span></h1>
|
|
|
|
| 480 |
<div id="pane"><div class="skel" style="margin-top:20px"></div></div>`);
|
| 481 |
if(tab==="rank")return paneRank(b);
|
| 482 |
if(tab==="submit")return paneSubmit(b);
|
| 483 |
+
if(tab==="guide")return paneGuide(b);
|
| 484 |
paneInfo(b);
|
| 485 |
}
|
| 486 |
|
|
|
|
| 512 |
: t.noEntries}</p>`;
|
| 513 |
}
|
| 514 |
|
| 515 |
+
/* ๋ถ๋ฌธ ๊ฐ์ด ์ฑ์์ง ์ฐธ์ฌ ๊ฐ์ด๋. ์ผ๋ฐ๋ฌธ์ผ๋ก ๋๋ฉด ์ฐธ๊ฐ์๊ฐ ์๊ธฐ ๋ถ๋ฌธ์ ๋ง๊ฒ ๊ณ ์ณ์ผ ํ๊ณ ,
|
| 516 |
+
๋๋ถ๋ถ ๊ทธ ๋จ๊ณ์์ ๋จ์ด์ง๋ค. */
|
| 517 |
+
function promptFor(b){
|
| 518 |
+
const nf=(b.noise_floor||{}).sd_single;
|
| 519 |
+
const bl=Object.entries(b.baselines||{})
|
| 520 |
+
.map(([k,v])=>` ${k}: ${v.mae!=null?("MAE "+f(v.mae)):("AUROC "+f(v.auroc))}`).join("\n");
|
| 521 |
+
const unit = b.type && b.type.indexOf("logS")>=0
|
| 522 |
+
? "logS = log10(์ฉํด๋ in mol/L)"
|
| 523 |
+
: b.threshold==null ? "๋ถ๋ฌธ ์ ์๊ฐ" : "p ์ค์ผ์ผ = -log10(๋๋ in M)";
|
| 524 |
+
return [
|
| 525 |
+
`๋๋ ์ ์ฝ ์์ธก ๋๊ตฌ ์ํ๋ LEADBOARD ์ "${b.board}" ๋ถ๋ฌธ์ ์ฐธ๊ฐํ๋ค.`,
|
| 526 |
+
`์๋ ์กฐ๊ฑด๋๋ก ์์ธก ํ์ผ์ ๋ง๋๋ Python ์คํฌ๋ฆฝํธ๋ฅผ ์์ฑํด ๋ฌ๋ผ.`,
|
| 527 |
+
``,
|
| 528 |
+
`[๊ณผ์ ]`,
|
| 529 |
+
` ์
๋ ฅ ${b.board.toLowerCase()}_test.json โ compound_id ์ SMILES ๋ง ๋ค์ด ์๋ค (${b.n_test}๊ฐ)`,
|
| 530 |
+
` ์ถ๋ ฅ predictions.csv โ ๋ ์ด: compound_id,prediction`,
|
| 531 |
+
` ์์ธก๊ฐ ${unit}`,
|
| 532 |
+
b.target && b.target!=="โ" ? ` ๋์ ${b.target} ยท ${b.type}` : ` ๋์ ${b.type}`,
|
| 533 |
+
``,
|
| 534 |
+
`[ํ์ต ์๋ฃ]`,
|
| 535 |
+
b.cut ? ` ChEMBL ์์ ${b.target} ์ ${b.type} ํ์ฑ์ ๋ฐ์ ์ด๋ค.` : ` ๊ณต๊ฐ ์๋ฃ๋ฅผ ์ง์ ํ๋ ์ด์
ํด ์ด๋ค.`,
|
| 536 |
+
b.cut ? ` โ
${b.cut}๋
์ดํ ์ฒ์ ๋ณด๊ณ ๋ ํํฉ๋ฌผ์ ํ์ต์ ๋ฃ์ง ๋ง ๊ฒ โ ๊ทธ๊ฒ์ด ํ
์คํธ์
์ด๋ค.` : ``,
|
| 537 |
+
` ๊ฐ์ ํํฉ๋ฌผ์ด ์ฌ๋ฌ ๋
ผ๋ฌธ์ ์์ผ๋ฉด InChIKey ๋ก ์ ์ด ์ค์๊ฐ์ ์ธ ๊ฒ.`,
|
| 538 |
+
``,
|
| 539 |
+
`[์ ์ฝ]`,
|
| 540 |
+
` ๋ฐฉ๋ฒ์ ์ ํ์ ์๋ค. ์ง๋ฌธ+ํธ๋ฆฌ, ๊ทธ๋ํ ์ ๊ฒฝ๋ง, ์ฌ์ ํ์ต ๋ชจ๋ธ, ๋ฌผ๋ฆฌ ๊ณ์ฐ ๋ชจ๋ ๊ฐ๋ฅ.`,
|
| 541 |
+
` ์ ๋ต์ ์กฐํํด ์ฑ์ฐ์ง ๋ง ๊ฒ. ์์ธก๊ฐ์ด ์ค์ธก๊ณผ ์์ ์๋ฆฌ๊น์ง ์ผ์นํ๋ ๋ฐ๋๋ฅผ ๊ฒ์ฌํ๋ค.`,
|
| 542 |
+
``,
|
| 543 |
+
`[ํ๊ฐ]`,
|
| 544 |
+
` ์ฃผ์งํ ${b.metric==="auroc"?"AUROC (๋์์๋ก ์ข์)":"MAE (๋ฎ์์๋ก ์ข์)"}`,
|
| 545 |
+
nf ? ` ์ด ๋ถ๋ฌธ์ ์คํ ์ฌํ ์ค์ฐจ๋ ${f(nf)} ์ด๋ค. ๊ทธ๋ณด๋ค ์์ ์ฐจ์ด๋ ์์๋ก ์ธ์ ๋์ง ์๋๋ค.` : ``,
|
| 546 |
+
` ๋์ด์ผ ํ ๊ธฐ์ค์ :`,
|
| 547 |
+
bl,
|
| 548 |
+
``,
|
| 549 |
+
`์คํฌ๋ฆฝํธ๋ ์๋ฃ ์์ง โ ์ ์ โ ํน์ง โ ํ์ต โ ์์ธก โ CSV ์ ์ฅ๊น์ง ํ ํ์ผ๋ก ์์ฑํด ๋ฌ๋ผ.`
|
| 550 |
+
].filter(x=>x!==``||true).join("\n");
|
| 551 |
+
}
|
| 552 |
+
|
| 553 |
+
function starterFor(b){
|
| 554 |
+
return [
|
| 555 |
+
`# ${b.board} ์ ์ถ ๋ผ๋`,
|
| 556 |
+
`import json, math, requests, numpy as np`,
|
| 557 |
+
`from rdkit import Chem`,
|
| 558 |
+
`from rdkit.Chem import rdFingerprintGenerator`,
|
| 559 |
+
`import lightgbm as lgb`,
|
| 560 |
+
``,
|
| 561 |
+
`# 1) ํ๋ จ ์๋ฃ (ChEMBL ์์ ๋ฐ๋๋ค)`,
|
| 562 |
+
`API = "https://www.ebi.ac.uk/chembl/api/data/activity.json"`,
|
| 563 |
+
`rows, off = [], 0`,
|
| 564 |
+
`while True:`,
|
| 565 |
+
` q = {"target_chembl_id": "${b.target}", "standard_type": "${b.type}",`,
|
| 566 |
+
` "standard_relation": "=", "limit": 1000, "offset": off}`,
|
| 567 |
+
` d = requests.get(API, params=q, timeout=120).json()`,
|
| 568 |
+
` rows += d["activities"]; off += 1000`,
|
| 569 |
+
` if off >= d["page_meta"]["total_count"]: break`,
|
| 570 |
+
``,
|
| 571 |
+
`# 2) ์ ์ โ InChIKey ๋ก ์ ๊ณ , ๊ธฐ์ค์ผ ์ดํ๋ ๋ฒ๋ฆฐ๋ค`,
|
| 572 |
+
`rec = {}`,
|
| 573 |
+
`for r in rows:`,
|
| 574 |
+
` s, v, u, y = r["canonical_smiles"], r["standard_value"], r["standard_units"], r["document_year"]`,
|
| 575 |
+
` if not (s and v and u == "nM" and y): continue`,
|
| 576 |
+
` m = Chem.MolFromSmiles(s)`,
|
| 577 |
+
` if m is None or float(v) <= 0: continue`,
|
| 578 |
+
` k = Chem.MolToInchiKey(m)`,
|
| 579 |
+
` rec.setdefault(k, {"y": [], "p": [], "m": m})`,
|
| 580 |
+
` rec[k]["y"].append(int(y)); rec[k]["p"].append(9.0 - math.log10(float(v)))`,
|
| 581 |
+
`train = {k: v for k, v in rec.items() if min(v["y"]) < ${b.cut||2022}} # โ
ํ
์คํธ์
์ ์ธ`,
|
| 582 |
+
``,
|
| 583 |
+
`# 3) ํน์ง ยท ํ์ต`,
|
| 584 |
+
`gen = rdFingerprintGenerator.GetMorganGenerator(radius=2, fpSize=2048)`,
|
| 585 |
+
`X = np.array([gen.GetFingerprintAsNumPy(v["m"]) for v in train.values()])`,
|
| 586 |
+
`Y = np.array([float(np.median(v["p"])) for v in train.values()])`,
|
| 587 |
+
`model = lgb.LGBMRegressor(n_estimators=500, learning_rate=0.05).fit(X, Y)`,
|
| 588 |
+
``,
|
| 589 |
+
`# 4) ์์ธก ยท ์ ์ฅ`,
|
| 590 |
+
`test = json.load(open("${b.board.toLowerCase()}_test.json", encoding="utf-8"))`,
|
| 591 |
+
`Xt = np.array([gen.GetFingerprintAsNumPy(Chem.MolFromSmiles(c["smiles"]))`,
|
| 592 |
+
` for c in test["compounds"]])`,
|
| 593 |
+
`p = model.predict(Xt)`,
|
| 594 |
+
`with open("predictions.csv", "w") as f:`,
|
| 595 |
+
` f.write("compound_id,prediction\n")`,
|
| 596 |
+
` for c, v in zip(test["compounds"], p):`,
|
| 597 |
+
` f.write("%s,%.4f\n" % (c["compound_id"], v))`
|
| 598 |
+
].join("\n");
|
| 599 |
+
}
|
| 600 |
+
|
| 601 |
+
function paneGuide(b){
|
| 602 |
+
const pr=promptFor(b), sk=starterFor(b);
|
| 603 |
+
const bl=Object.entries(b.baselines||{}).sort((x,y)=>
|
| 604 |
+
(x[1].mae!=null?x[1].mae:-x[1].auroc)-(y[1].mae!=null?y[1].mae:-y[1].auroc));
|
| 605 |
+
$("#pane").innerHTML=`
|
| 606 |
+
<p class="lede" style="margin:6px 0 18px">${t.gdIntro}</p>
|
| 607 |
+
<h3>${t.gdWhat}</h3><p class="dim" style="font-size:14.5px">${t.gdWhatD}</p>
|
| 608 |
+
<h3>${t.gdPrompt}</h3><p class="dim" style="font-size:14px">${t.gdPromptD}</p>
|
| 609 |
+
<div style="position:relative">
|
| 610 |
+
<button class="btn" id="cp1" style="position:absolute;right:12px;top:12px;padding:6px 13px;font-size:12px">${t.gdCopy}</button>
|
| 611 |
+
<pre class="fig" style="white-space:pre-wrap;margin:0">${esc(pr)}</pre></div>
|
| 612 |
+
<h3>${t.gdStarter}</h3><p class="dim" style="font-size:14px">${t.gdStarterD}</p>
|
| 613 |
+
<div style="position:relative">
|
| 614 |
+
<button class="btn" id="cp2" style="position:absolute;right:12px;top:12px;padding:6px 13px;font-size:12px">${t.gdCopy}</button>
|
| 615 |
+
<pre class="fig" style="white-space:pre;overflow-x:auto;margin:0;font-size:12px">${esc(sk)}</pre></div>
|
| 616 |
+
<h3>${t.gdTarget}</h3><p class="dim" style="font-size:14px">${t.gdTargetD}</p>
|
| 617 |
+
<div class="tw"><table><thead><tr><th style="text-align:left;width:auto">${t.baseH}</th>
|
| 618 |
+
<th>MAE</th><th>AUROC</th></tr></thead><tbody>
|
| 619 |
+
${bl.map(([k,v])=>`<tr><td style="text-align:left">${esc(k)}</td>
|
| 620 |
+
<td>${v.mae!=null?f(v.mae):"โ"}</td><td>${v.auroc!=null?f(v.auroc):"โ"}</td></tr>`).join("")}
|
| 621 |
+
</tbody></table></div>
|
| 622 |
+
<h3>${t.gdRules}</h3>
|
| 623 |
+
<ol class="cl" style="grid-template-columns:1fr">
|
| 624 |
+
${[t.gdR1,t.gdR2,t.gdR3,t.gdR4].map(x=>`<li><span>${x}</span></li>`).join("")}
|
| 625 |
+
</ol>`;
|
| 626 |
+
const wireCopy=(id,txt)=>{const el=$("#"+id); if(!el)return;
|
| 627 |
+
el.onclick=async()=>{try{await navigator.clipboard.writeText(txt);
|
| 628 |
+
el.textContent=t.gdCopied; setTimeout(()=>el.textContent=t.gdCopy,1600);}catch(e){}};};
|
| 629 |
+
wireCopy("cp1",pr); wireCopy("cp2",sk);
|
| 630 |
+
}
|
| 631 |
+
|
| 632 |
function paneInfo(b){
|
| 633 |
const nf=b.noise_floor, bl=b.baselines;
|
| 634 |
$("#pane").innerHTML=`
|