ORES RC filters

https://www.mediawiki.org/wiki/ORES/RCFilters#Choosing_thresholds_for_a_new_modelhttps://www.mediawiki.org/wiki/ORES/RCFilters#Choosing_thresholds_for_a_new_model

by Gergő Tisza

HTML

<div id="dataTable"></div>

CSS

#dataTable table {
    width: 100%;
    background-color: #f8f9fa;
    border-collapse: collapse;
}

#dataTable tr.wiki-divider {
    background-color: #eaecf0;
}

#dataTable th {
    /* make sticky */
    position: sticky;
    top: 0;
    z-index: 1;

    background-color: #eaecf0;
    padding: 0.2em 0.4em;
    text-align: center;
}

#dataTable td {
    border: 1px solid #a2a9b1;
    padding: 0.2em 0.4em;
}

/* right-align numeric rows */
#dataTable td:nth-child(4),
#dataTable td:nth-child(5),
#dataTable td:nth-child(7),
#dataTable td:nth-child(8) {
    text-align: right;
}

JavaScript

// which wikis and precision/recall thresholds to get stats for
let oresWikis = [ 'ukwiki' ];
let oresLevels = [
	{ precision: 0.15 },
	{ precision: 0.40 },
	{ precision: 0.45 },
	{ precision: 0.50 },
	{ precision: 0.595 },
	{ precision: 0.75 },
	{ precision: 0.80 },
	{ precision: 0.90 },
	{ precision: 0.95 },
	{ precision: 0.98 },
	{ precision: 0.99 },
	{ precision: 0.997 },
	{ precision: 0.998 },
	{ precision: 0.999 },
	{ recall: 0.90 }
];
// don't attempt to get more info objects than this at one time - T232855
let oresChunkLength = 15;

/**
 * Display data as a HTML table
 * @param {Object[]} data
 */
function renderDataTable( data ) {
    let tableColumns = [
        'wiki',
        'model',
        'outcome',
        'filter type',
        'min',
        'max',
        'condition',
        'precision',
        'recall',
    ];

	let html = '<table><tr>' + tableColumns.map( text => `<th>${text}</th>` ).join( '' ) + '</tr>';
    let wiki = null;
    for ( let row of data ) {
		if ( !row.stats ) {
        	row.stats = { threshold: NaN, precision: NaN, recall: NaN };
        }
    	if ( row.wiki !== wiki ) {
            if ( wiki ) {
        		html += `<tr class="wiki-divider"><td colspan="${tableColumns.length}"></td></tr>`
            }
            wiki = row.wiki;
        }
		let rowText = [
            row.wiki,
            row.model,
            row.outcome,
            ( ( row.model === 'goodfaith' ) ^ ( row.outcome === 'true' ) ) ? 'bad' : 'good',
            row.outcome === 'true' ? +parseFloat( row.stats.threshold ).toFixed( 3 ) : 0,
            row.outcome === 'true' ? 1 : +parseFloat( 1 - row.stats.threshold ).toFixed( 3 ),
            row.name,
            row.stats.precision,
            row.stats.recall,
        ];
        html += '<tr>' + rowText.map( text => `<td>${text}</td>` ).join( '' ) + '</tr>';
    }
    html += '</table>'
    $( '#dataTable' ).html( html );
}

/**
 * @param {String[]} wikis
 * @param {Object[]} levels as { precision: <n>...