@@ -75,8 +75,9 @@ <h2>Efficiency Indicators</h2>
7575 < thead >
7676 < tr >
7777 < th > Method</ th >
78- < th > Selected Dataset Fraction (SDF) </ th >
78+
7979 < th > Performance Improvement Ratio (PIR)</ th >
80+ < th > Selected Dataset Fraction (SDF)</ th >
8081 < th > Actions</ th > <!-- NEW column for delete buttons -->
8182 </ tr >
8283 </ thead >
@@ -188,6 +189,9 @@ <h2>Feasibility Indicators</h2>
188189 { method : "CaR" , sdf : 0.0196 , pir : 1.343 } ,
189190 { method : "SelectIT" , sdf : 0.2 , pir : 1.653 }
190191 ] ;
192+ // --- NEW: assign a global order to each work for tie-breaking ---
193+ let nextEfficiencyOrder = 1 ;
194+ efficiencyData . forEach ( d => { d . order = nextEfficiencyOrder ++ ; } ) ;
191195
192196 function linearTransform ( x , x_vals , y_vals ) {
193197 let x1 = x_vals [ 0 ] , x2 = x_vals [ 1 ] ;
@@ -268,14 +272,81 @@ <h2>Feasibility Indicators</h2>
268272 document . getElementById ( "BM" ) . addEventListener ( "input" , updateEfficiencyInputStates ) ;
269273 document . getElementById ( "PIR" ) . addEventListener ( "input" , updateEfficiencyInputStates ) ;
270274
275+ // --- NEW: Function to compute signed efficiency values and sort the efficiencyData array ---
276+ function sortEfficiencyData ( ) {
277+ const canvas = document . getElementById ( "efficiencyCanvas" ) ;
278+ if ( ! canvas ) return ;
279+ const dpr = window . devicePixelRatio || 1 ;
280+ const W = canvas . width / dpr ;
281+ const H = canvas . height / dpr ;
282+ const pad = 60 ;
283+ const innerPad = 20 ;
284+ const minSDFdata = Math . min ( ...efficiencyData . map ( d => d . sdf ) ) ;
285+ const maxSDFdata = Math . max ( ...efficiencyData . map ( d => d . sdf ) ) ;
286+ const minSDF = Math . min ( 0.0 , minSDFdata ) ;
287+ const maxSDF = ( maxSDFdata > 0.2 ? maxSDFdata : 0.2 ) * 1.05 ;
288+ const minPIRdata = Math . min ( ...efficiencyData . map ( d => d . pir ) ) ;
289+ let maxPIR = Math . max ( ...efficiencyData . map ( d => d . pir ) ) ;
290+ const minPIR = minPIRdata * 0.95 ;
291+ maxPIR = ( maxPIR > 1.75 ? maxPIR : 1.75 ) * 1.05 + 0.01 ;
292+ const xScale = val => pad + ( ( val - minSDF ) / ( maxSDF - minSDF ) ) * ( W - 2 * pad ) ;
293+ const yScale = val => ( H - pad ) - ( ( val - minPIR ) / ( maxPIR - minPIR ) ) * ( H - 2 * pad ) ;
294+
295+ const A = efficiencyData . find ( d => d . method === "Instruction-Mining" ) ;
296+ const B = efficiencyData . find ( d => d . method === "InstructionGPT-4" ) ;
297+ if ( ! A || ! B ) return ;
298+ const dx = B . sdf - A . sdf ;
299+ if ( Math . abs ( dx ) < 1e-12 ) return ;
300+ const slope = ( B . pir - A . pir ) / ( B . sdf - A . sdf ) ;
301+ const colorRectLeft = pad + innerPad ;
302+ const colorRectRight = W - pad - innerPad ;
303+ const leftSDF = minSDF + ( ( colorRectLeft - pad ) / ( W - 2 * pad ) ) * ( maxSDF - minSDF ) ;
304+ const rightSDF = minSDF + ( ( colorRectRight - pad ) / ( W - 2 * pad ) ) * ( maxSDF - minSDF ) ;
305+ const yAtLeft = A . pir + slope * ( leftSDF - A . sdf ) ;
306+ const yAtRight = A . pir + slope * ( rightSDF - A . sdf ) ;
307+ const X1 = colorRectLeft ;
308+ const Y1 = yScale ( yAtLeft ) ;
309+ const X2 = colorRectRight ;
310+ const Y2 = yScale ( yAtRight ) ;
311+
312+ // Normal vector of baseline: n = (-(Y2 - Y1), X2 - X1) normalized
313+ const dxBase = X2 - X1 ;
314+ const dyBase = Y2 - Y1 ;
315+ const norm = Math . sqrt ( dxBase * dxBase + dyBase * dyBase ) ;
316+ const nx = - dyBase / norm ;
317+ const ny = dxBase / norm ;
318+
319+ efficiencyData . forEach ( d => {
320+ const px = xScale ( d . sdf ) ;
321+ const py = yScale ( d . pir ) ;
322+ const proj = projectPointToLine ( px , py , X1 , Y1 , X2 , Y2 ) ;
323+ const dxProj = px - proj [ 0 ] ;
324+ const dyProj = py - proj [ 1 ] ;
325+ const distance = Math . sqrt ( dxProj * dxProj + dyProj * dyProj ) ;
326+ const dot = dxProj * nx + dyProj * ny ;
327+ const sign = ( dot >= 0 ) ? 1 : - 1 ;
328+ d . effVal = sign * distance ;
329+ } ) ;
330+
331+ // Sort: descending by effVal, then alphabetically by method name, then by order (old first)
332+ efficiencyData . sort ( ( a , b ) => {
333+ if ( a . effVal !== b . effVal ) {
334+ return a . effVal - b . effVal ;
335+ }
336+ if ( a . method . toLowerCase ( ) < b . method . toLowerCase ( ) ) return - 1 ;
337+ if ( a . method . toLowerCase ( ) > b . method . toLowerCase ( ) ) return 1 ;
338+ return a . order - b . order ;
339+ } ) ;
340+ }
341+
271342 // --- Modified Efficiency Table Update Function ---
272343 function populateEfficiencyTable ( ) {
273344 const effTbody = document . querySelector ( "#efficiencyTable tbody" ) ;
274345 effTbody . innerHTML = "" ;
275346 const SEMInput = document . getElementById ( "SEM" ) . value . trim ( ) ;
276347 const BMInput = document . getElementById ( "BM" ) . value . trim ( ) ;
277- const SDFInput = document . getElementById ( "SDF" ) . value . trim ( ) ;
278348 const PIRInputVal = document . getElementById ( "PIR" ) . value . trim ( ) ;
349+ const SDFInput = document . getElementById ( "SDF" ) . value . trim ( ) ;
279350
280351 // If new efficiency input is provided, update the global efficiencyData array.
281352 if ( SDFInput !== "" ) {
@@ -308,37 +379,43 @@ <h2>Feasibility Indicators</h2>
308379 pirValue = result . result ;
309380 }
310381
311- // Append new entries (one for each SDF value)
382+ // Append new entries (one for each SDF value) with an order property.
312383 for ( let i = 0 ; i < SDF . length ; i ++ ) {
313384 const methodName = methods [ i ] ? methods [ i ] : "Method " + ( efficiencyData . length + 1 ) ;
314385 efficiencyData . push ( {
315386 method : methodName ,
316387 sdf : SDF [ i ] ,
317- pir : pirValue
388+ pir : pirValue ,
389+ order : nextEfficiencyOrder ++
318390 } ) ;
319391 }
320392
321393 // Clear the input fields after adding.
322394 document . getElementById ( "effMethodNames" ) . value = "" ;
323395 document . getElementById ( "SEM" ) . value = "" ;
324396 document . getElementById ( "BM" ) . value = "" ;
325- document . getElementById ( "SDF" ) . value = "" ;
397+
326398 document . getElementById ( "PIR" ) . value = "" ;
399+ document . getElementById ( "SDF" ) . value = "" ;
327400 updateEfficiencyInputStates ( ) ;
328401 }
329402 }
330403
404+ // --- NEW: Sort the efficiencyData array based on computed efficiency values ---
405+ sortEfficiencyData ( ) ;
406+
331407 // Re-populate table from the entire efficiencyData array.
332408 efficiencyData . forEach ( d => {
333409 const tr = document . createElement ( "tr" ) ;
334410 let deleteButtonHTML = "" ;
335411 // Only allow deletion for non-baseline methods.
336412 if ( d . method !== "Instruction-Mining" && d . method !== "InstructionGPT-4" ) {
337- deleteButtonHTML = `<button class="deleteBtn" data-method="${ d . method } ">Delete</button>` ;
413+ deleteButtonHTML = `<button class="deleteBtn" data-method="${ d . method } " data-order=" ${ d . order } " >Delete</button>` ;
338414 }
339415 tr . innerHTML = `<td>${ d . method } </td>
340- <td> ${ d . sdf } </td>
416+
341417 <td>${ ( typeof d . pir === "number" ) ? d . pir . toFixed ( 4 ) : d . pir } </td>
418+ <td>${ d . sdf } </td>
342419 <td>${ deleteButtonHTML } </td>` ;
343420 effTbody . appendChild ( tr ) ;
344421 } ) ;
@@ -347,7 +424,11 @@ <h2>Feasibility Indicators</h2>
347424 document . querySelectorAll ( ".deleteBtn" ) . forEach ( btn => {
348425 btn . addEventListener ( "click" , function ( ) {
349426 const methodToDelete = this . getAttribute ( "data-method" ) ;
350- efficiencyData = efficiencyData . filter ( d => d . method !== methodToDelete ) ;
427+ const orderToDelete = parseInt ( this . getAttribute ( "data-order" ) ) ;
428+ efficiencyData = efficiencyData . filter ( d => {
429+ // Match both method and order to ensure uniqueness.
430+ return ! ( d . method === methodToDelete && d . order === orderToDelete ) ;
431+ } ) ;
351432 populateEfficiencyTable ( ) ;
352433 drawEfficiencyPlot ( ) ;
353434 } ) ;
@@ -930,7 +1011,7 @@ <h2>Feasibility Indicators</h2>
9301011 // ===============================================================
9311012 // Master update and Save functions
9321013 // ===============================================================
933- // Remove the old global update button and use separate ones .
1014+ // Use separate update buttons .
9341015 window . onload = ( ) => {
9351016 populateEfficiencyTable ( ) ;
9361017 populateFeasibilityTable ( ) ;
0 commit comments