138 lines
3.9 KiB
JavaScript
138 lines
3.9 KiB
JavaScript
|
|
const rate = (v) => `${(v * 100).toFixed(2).replace(".", ",")}%`;
|
|
|
|
export function SkippedRows({ audit, legacy = false, status = "completed" }) {
|
|
if (!audit) {
|
|
return legacy
|
|
? <p>Rincian baris yang dilewati belum dicatat untuk versi lama ini.</p>
|
|
: null;
|
|
}
|
|
|
|
return (
|
|
<div className="models-audit">
|
|
<p>
|
|
<b>
|
|
{audit.uploaded_rows} diunggah → {audit.accepted_rows} diterima →{" "}
|
|
{audit.skipped_rows.length} dilewati.
|
|
</b>
|
|
</p>
|
|
|
|
{audit.selected_column && (
|
|
<p>
|
|
Kolom yang digunakan: <b>{audit.selected_column}</b>
|
|
</p>
|
|
)}
|
|
|
|
<p>
|
|
{status === "completed" && audit.accepted_rows > 0
|
|
? `Data latih: ${audit.training_before} sebelum penambahan → ${audit.training_before + audit.accepted_rows} setelah training berhasil.`
|
|
: `Data latih tetap ${audit.training_before}.`}
|
|
</p>
|
|
|
|
{!!audit.skipped_rows.length && (
|
|
<details className="models-skipped-details">
|
|
<summary>
|
|
Lihat Data yang Dilewati ({audit.skipped_rows.length})
|
|
</summary>
|
|
|
|
<p className="models-skip-note">
|
|
Nomor baris adalah urutan record CSV, termasuk judul kolom
|
|
sebagai baris 1. Ulasan dengan baris baru di dalam tanda
|
|
kutip dihitung satu record.
|
|
</p>
|
|
|
|
<div className="models-table models-skipped-scroll">
|
|
<table className="models-skipped-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Baris CSV</th>
|
|
<th>Ulasan</th>
|
|
<th>Alasan dilewati</th>
|
|
</tr>
|
|
</thead>
|
|
|
|
<tbody>
|
|
{audit.skipped_rows.map((r) => (
|
|
<tr key={r.source_row_number}>
|
|
<td>{r.source_row_number}</td>
|
|
|
|
<td className="models-skipped-text">
|
|
{r.text || "(kosong)"}
|
|
</td>
|
|
|
|
<td>
|
|
<span className="models-skip-reason">
|
|
{r.reason}
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</details>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function VersionComparison({ selected, original }) {
|
|
if (!original || selected.version === "v1") {
|
|
return (
|
|
<p>
|
|
Model penelitian awal: {selected.jumlah_data_training} data latih
|
|
dan {selected.jumlah_data_testing} data uji.
|
|
</p>
|
|
);
|
|
}
|
|
|
|
const metrics = [
|
|
["Akurasi", m => m.akurasi],
|
|
["Precision", m => m.classification_report["weighted avg"].precision],
|
|
["Recall", m => m.classification_report["weighted avg"].recall],
|
|
["F1-Score", m => m.classification_report["weighted avg"]["f1-score"]]
|
|
];
|
|
|
|
return (
|
|
<div>
|
|
<h3>Perbandingan dengan model awal v1</h3>
|
|
|
|
<p>
|
|
{selected.jumlah_data_training} data latih. Evaluasi pada{" "}
|
|
{selected.jumlah_data_testing} data uji tetap yang sama.
|
|
</p>
|
|
|
|
<div className="models-table">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Metrik</th>
|
|
<th>v1</th>
|
|
<th>{selected.version}</th>
|
|
<th>Selisih (poin persentase)</th>
|
|
</tr>
|
|
</thead>
|
|
|
|
<tbody>
|
|
{metrics.map(([name, get]) => (
|
|
<tr key={name}>
|
|
<th>{name}</th>
|
|
<td>{rate(get(original))}</td>
|
|
<td>{rate(get(selected))}</td>
|
|
<td>
|
|
{((get(selected) - get(original)) * 100).toFixed(2)}
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<p>
|
|
Precision, Recall, dan F1-Score menggunakan weighted average,
|
|
yaitu rata-rata yang memperhitungkan jumlah data pada setiap kelas.
|
|
</p>
|
|
</div>
|
|
);
|
|
}
|