From 858f49404779455fa5c7e7375172e9dfe98588fd Mon Sep 17 00:00:00 2001 From: Filip Gralinski Date: Sat, 8 Sep 2018 09:12:47 +0200 Subject: [PATCH] Scores are sorted correctly with N/A and Infinity values correctly handled --- Handler/Shared.hs | 15 ++ Handler/ShowChallenge.hs | 5 + static/js/datatables-extended.js | 158 +++++++++++++++++++++ templates/challenge-all-submissions.julius | 6 +- templates/default-layout-wrapper.hamlet | 1 + templates/show-challenge.julius | 8 +- 6 files changed, 190 insertions(+), 3 deletions(-) create mode 100644 static/js/datatables-extended.js diff --git a/Handler/Shared.hs b/Handler/Shared.hs index a145e66..7021783 100644 --- a/Handler/Shared.hs +++ b/Handler/Shared.hs @@ -37,6 +37,11 @@ import System.IO.Unsafe (unsafePerformIO) import Text.Regex.TDFA +import Data.Aeson.Types +import GEval.Core + +import qualified Data.Vector as DV + arena :: Handler FilePath arena = do app <- getYesod @@ -386,3 +391,13 @@ unwantedLocalIds = ["git", isLocalIdAcceptable :: Text -> Bool isLocalIdAcceptable localId = match localIdRegexp (unpack localId) && not (localId `elem` unwantedLocalIds) + +-- need to transfer the information into a JS script +getIsHigherTheBetterArray :: [Test] -> Value +getIsHigherTheBetterArray = Array + . DV.fromList + . map (convertIsHigherTheBetter + . getMetricOrdering + . testMetric) + where convertIsHigherTheBetter TheHigherTheBetter = Bool True + convertIsHigherTheBetter _ = Bool False diff --git a/Handler/ShowChallenge.hs b/Handler/ShowChallenge.hs index 1006532..baabc60 100644 --- a/Handler/ShowChallenge.hs +++ b/Handler/ShowChallenge.hs @@ -103,6 +103,8 @@ showChallengeWidget muserId = $(widgetFile "show-challenge") where leaderboardWithRanks = zip [1..] leaderboard maybeRepoLink = getRepoLink repo + delta = Number 4 + higherTheBetterArray = getIsHigherTheBetterArray [test] getRepoLink :: Repo -> Maybe Text getRepoLink repo @@ -570,6 +572,7 @@ getAllParams entries = sort $ concat $ map (\entry -> map (parameterName . entityVal) (tableEntryParams entry)) entries + challengeAllSubmissionsWidget :: Maybe UserId -> Challenge -> RepoScheme @@ -580,6 +583,8 @@ challengeAllSubmissionsWidget :: Maybe UserId -> WidgetFor App () challengeAllSubmissionsWidget muserId challenge scheme challengeRepo submissions tests params = $(widgetFile "challenge-all-submissions") + where delta = Number 3 + higherTheBetterArray = getIsHigherTheBetterArray $ map entityVal tests paramGraphsWidget :: Challenge -> [Entity Test] -> [Text] -> WidgetFor App () paramGraphsWidget challenge tests params = $(widgetFile "param-graphs") diff --git a/static/js/datatables-extended.js b/static/js/datatables-extended.js new file mode 100644 index 0000000..136ee14 --- /dev/null +++ b/static/js/datatables-extended.js @@ -0,0 +1,158 @@ +/** + * Based on absolute-order Datatables plug-in by Allan Jardine + */ + +(function( factory ){ + if ( typeof define === 'function' && define.amd ) { + // AMD + define( ['jquery', 'datatables.net'], function ( $ ) { + return factory( $, window, document ); + } ); + } + else if ( typeof exports === 'object' ) { + // CommonJS + module.exports = function (root, $) { + if ( ! root ) { + root = window; + } + + if ( ! $ || ! $.fn.dataTable ) { + $ = require('datatables.net')(root, $).$; + } + + return factory( $, root, root.document ); + }; + } + else { + // Browser + factory( jQuery, window, document ); + } +}(function( $, window, document, undefined ) { +'use strict'; + +function extractValue(a) { + if ( typeof a === 'string' ) { + var m = a.match(/ b) ? 1 : 0)); +} + +// Unique value allowing multiple absolute ordering use cases on a single page. +var _unique = 0; + +// Function to encapsulate code that is common to both the string and number +// ordering plug-ins. +var _setup = function ( isHigherTheBetter ) { + var o = { + name: 'absoluteOrder'+(_unique++), + alwaysHighest: {}, + alwaysLowest: {} + }; + + // In order to provide performance, the symbols that are to be looked for + // are stored as parameter keys in an object, allowing O(1) lookup, rather + // than O(n) if it were in an array. + + o.alwaysHighest["Infinity"] = 1 + if (isHigherTheBetter) { + o.alwaysLowest["N/A"] = -1 + } else { + o.alwaysHighest["N/A"] = 2 + } + + // Ascending ordering method + o.asc = function ( a, b ) { + a = extractValue(a) + b = extractValue(b) + + if ( o.alwaysLowest[ a ] && o.alwaysLowest[ b ] ) { + return toSign(o.alwaysLowest[a], o.alwaysLowest[b]); + } + else if ( o.alwaysHighest[ a ] && o.alwaysHighest[ b ] ) { + return toSign(o.alwaysHighest[a], o.alwaysHighest[b]); + } + else if ( o.alwaysLowest[ a ] || o.alwaysHighest[ b ] ) { + return -1; + } + else if ( o.alwaysHighest[ a ] || o.alwaysLowest[ b ] ) { + return 1; + } + + a = extractNumber(a); + b = extractNumber(b); + + return toSign(a, b); + }; + + // Descending ordering method + o.desc = function ( a, b ) { + a = extractValue(a) + b = extractValue(b) + + if ( o.alwaysLowest[ a ] && o.alwaysLowest[ b ] ) { + return toSign(o.alwaysLowest[b], o.alwaysLowest[a]); + } + else if ( o.alwaysHighest[ a ] && o.alwaysHighest[ b ] ) { + return toSign(o.alwaysHighest[b], o.alwaysHighest[a]); + } + else if ( o.alwaysLowest[ a ] || o.alwaysHighest[ b ] ) { + return 1; + } + else if ( o.alwaysHighest[ a ] || o.alwaysLowest[ b ] ) { + return -1; + } + + a = extractNumber(a); + b = extractNumber(b); + + return toSign(b, a); + }; + + return o; +}; + +// Number based ordering - strips out everything but the number information +$.fn.dataTable.extendedOrderNumber = function ( isHigherTheBetter ) { + var conf = _setup( isHigherTheBetter ); + + $.fn.dataTable.ext.type.order[ conf.name+'-asc' ] = function ( a, b ) { + return conf.asc( a, b, true ); + }; + $.fn.dataTable.ext.type.order[ conf.name+'-desc' ] = function ( a, b ) { + return conf.desc( a, b, true ); + }; + + return conf.name; +}; + +$.fn.dataTable.getColumnDef = function (ix, isHigherTheBetter) { + return { + type: $.fn.dataTable.extendedOrderNumber(isHigherTheBetter), + targets: ix + }; +} + +$.fn.dataTable.getColumnDefs = function (delta, isHigherTheBetterArray) { + var ix = delta; + + return isHigherTheBetterArray.map(isHigherTheBetter => $.fn.dataTable.getColumnDef(ix++, isHigherTheBetter)); +}; + +})); diff --git a/templates/challenge-all-submissions.julius b/templates/challenge-all-submissions.julius index ddbdfe7..4e411fd 100644 --- a/templates/challenge-all-submissions.julius +++ b/templates/challenge-all-submissions.julius @@ -5,8 +5,12 @@ } }); + var columnDefs = $.fn.dataTable.getColumnDefs(#{delta}, #{higherTheBetterArray}); + $(document).ready(function() { $("table").DataTable({ 'pageLength': 50, - 'order': [[1, 'desc']]}); + 'order': [[1, 'desc']], + 'columnDefs': columnDefs + }); } ); diff --git a/templates/default-layout-wrapper.hamlet b/templates/default-layout-wrapper.hamlet index 415c5bc..7e3a472 100644 --- a/templates/default-layout-wrapper.hamlet +++ b/templates/default-layout-wrapper.hamlet @@ -16,6 +16,7 @@ $newline never