Skip to content

Commit

Permalink
Add import ltr format (#204)
Browse files Browse the repository at this point in the history
  • Loading branch information
epugh authored Nov 2, 2020
1 parent 6a4c2c3 commit b245319
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 24 deletions.
2 changes: 1 addition & 1 deletion app/assets/javascripts/components/export_case/_modal.html
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ <h3 class="modal-title">Export Case: <span class="modal-case">{{ ctrl.theCase.ca
<input type="radio" id="ltr" name="exportSelection" value="ltr" ng-model="ctrl.options.which">
<label for="ltr">Learning to Rank</label>
<span class="help-block">
LTR uses a rather odd format of <code>rating qid:queryid # docid</code>, eg <code>1 qid:23 # 193</code>.
LTR uses a rather odd format of <code>rating qid:queryid # docid query</code>, eg <code>3 qid:1 # 1370 star trek</code>.
</span>
</div>
</div>
Expand Down
19 changes: 15 additions & 4 deletions app/assets/javascripts/components/import_ratings/_modal.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,28 @@ <h2>CSV</h2>

<div class="form-group">
<input type="radio" id="rre" name="importSelection" value="rre" ng-model="ctrl.options.which">
<label for="rre">RRE</label>
<label for="rre">Rated Ranking Evaluator</label>
<span class="help-block">
Quepid only imports the ratings part of the <a href="https://github.com/SeaseLtd/rated-ranking-evaluator/wiki/What%20We%20Need%20To%20Provide#ratings" target="_blank">RRE judgement</a> file.
</span>
<p>Select RRE ratings file to import:</p>
<!-- this onchange is a code smell. -->
<input type="file" id="file" name="file"
<input type="file" id="rreFile" name="rreFile"
accept="application/json"
onchange="angular.element(this).scope().pickedFile()"/>

onchange="angular.element(this).scope().pickedRREFile()"/>
</div>

<div class="form-group">
<input type="radio" id="ltr" name="importSelection" value="ltr" ng-model="ctrl.options.which">
<label for="ltr">Learning to Rank</label>
<span class="help-block">
LTR uses a rather odd format of <code>rating qid:queryid # docid query</code>, eg <code>3 qid:1 # 1370 star trek</code>. We ignore the <code>qid:queryid</code> and use the <code>query</code> for matching up to existing queries.
</span>
<p>Select LTR ratings file to import:</p>
<!-- this onchange is a code smell. -->
<input type="file" id="ltrFile" name="ltrFile"
accept="text/plain"
onchange="angular.element(this).scope().pickedLTRFile()"/>
</div>

</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ angular.module('QuepidApp')
content: null
};

ctrl.ltr = {
content: null
};

ctrl.options = {
which: 'undefined'
};
Expand All @@ -39,24 +43,9 @@ angular.module('QuepidApp')
}
},true);

// doesn't appear to work.
$scope.$watch('ctrl.rre.content', function(newVal, oldVal) {
if (newVal !== oldVal) {
ctrl.options.which = 'rre';
}
},true);

// doesn't appear to work.
$scope.$watch('ctrl.rre', function(newVal, oldVal) {
if (newVal !== oldVal) {
if (oldVal.content !== newVal.content) {
ctrl.options.which = 'rre';
}
}
},true);

$scope.pickedFile = function() {
var f = document.getElementById('file').files[0],
$scope.pickedRREFile = function() {
var f = document.getElementById('rreFile').files[0],
r = new FileReader();

// This next two lines don't seem to trigger the watches that I wanted.
Expand All @@ -71,6 +60,22 @@ angular.module('QuepidApp')
r.readAsText(f);
};

$scope.pickedLTRFile = function() {
var f = document.getElementById('ltrFile').files[0],
r = new FileReader();

// This next two lines don't seem to trigger the watches that I wanted.
ctrl.options.which = 'ltr';
ctrl.loading = true;
r.onloadend = function(e) {
var data = e.target.result;
ctrl.ltr.content = data;
ctrl.loading = false;
};

r.readAsText(f);
};

ctrl.ok = function () {
if ( ctrl.options.which === 'csv' ) {
ctrl.checkCSVHeaders();
Expand Down Expand Up @@ -115,6 +120,23 @@ angular.module('QuepidApp')
$uibModalInstance.close(error);
});
}
else if (ctrl.options.which === 'ltr' ) {
importRatingsSvc.importLTRFormat(
ctrl.theCase,
ctrl.ltr.content,
ctrl.clearQueries
).then(function() {
ctrl.loading = false;
$uibModalInstance.close();
},
function(response) {
var error = 'Unable to import ratings from LTR: ';
error += response.status;
error += ' - ' + response.statusText;
ctrl.loading = false;
$uibModalInstance.close(error);
});
}
}
};

Expand Down
13 changes: 13 additions & 0 deletions app/assets/javascripts/services/importRatingsSvc.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ angular.module('QuepidApp')
// Functions
self.importCSVFormat = importCSVFormat;
self.importRREFormat = importRREFormat;
self.importLTRFormat = importLTRFormat;

function importCSVFormat(theCase, csv, clearQueries) {
var ratings = [];
Expand Down Expand Up @@ -46,5 +47,17 @@ angular.module('QuepidApp')
return $http.post('/api/import/ratings?file_format=rre', data);

}

function importLTRFormat(theCase, ltrText, clearQueries) {

var data = {
ltr_text: ltrText,
case_id: theCase.caseNo,
clear_queries: clearQueries,
};

return $http.post('/api/import/ratings?file_format=ltr', data);

}
}
]);
37 changes: 37 additions & 0 deletions app/controllers/api/v1/import/ratings_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class RatingsController < Api::ApiController
before_action :check_case

# rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/AbcSize
def create
file_format = params[:file_format]
file_format = 'hash' unless params[:file_format]
Expand All @@ -31,6 +32,18 @@ def create
end
end
end
elsif 'ltr' == file_format
# normalize the LTR ratings format to the default hash format.

# What do we do about qid? Do we assume that qid is in Quepid already?
ratings = []
ltr_text = params[:ltr_text]
ltr_lines = ltr_text.split(/\n+/)

ltr_lines.each do |ltr_line|
rating = rating_from_ltr_line ltr_line
ratings << rating
end
end

options = {
Expand All @@ -55,7 +68,31 @@ def create
end
# rubocop:enable Lint/RescueException
end

def rating_from_ltr_line ltr_line
# Pattern: 3 qid:1 # 1370 star trek
ltr_line = ltr_line.strip
first_chunk = ltr_line.index(' ')
rating = ltr_line[0..first_chunk].strip
ltr_line = ltr_line[first_chunk..-1].strip
second_chunk_begin = ltr_line.index('#')
ltr_line = ltr_line[second_chunk_begin + 1..-1].strip
second_chunk_end = ltr_line.index(' ')
doc_id = ltr_line[0..second_chunk_end].strip

ltr_line = ltr_line[second_chunk_end..-1]

query_text = ltr_line.strip

rating = {
query_text: query_text,
doc_id: doc_id,
rating: rating,
}
rating
end
# rubocop:enable Metrics/MethodLength
# rubocop:enable Metrics/AbcSize
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion app/views/api/v1/export/ratings/show.txt.erb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<%
@case.queries.sort_by(&:id).each do |query|
query.ratings.each do |rating| %>
<%=rating.rating%> qid:<%=query.id%> # <%=rating.doc_id %>; "<%=query.query_text%>"
<%=rating.rating%> qid:<%=query.id%> # <%=rating.doc_id %> <%=query.query_text%>
<%
end
end %>
2 changes: 1 addition & 1 deletion test/controllers/api/v1/export/ratings_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class RatingsControllerTest < ActionController::TestCase
# For whatever reason the response.body is blank.
# We want to test both the format of the lines and
# that specifically for LTR that the export is based on the qid.
# assert response.body.include?("<%=rating.rating%> qid:<%=query.id%> # <%=rating.doc_id %>; \"<%=query.query_text%>\"")
# assert response.body.include?("<%=rating.rating%> qid:<%=query.id%> # <%=rating.doc_id %> <%=query.query_text%>")

# rubocop:enable Lint/UselessAssignment
# rubocop:enable Metrics/LineLength
Expand Down
14 changes: 14 additions & 0 deletions test/controllers/api/v1/import/ratings_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,20 @@ class RatingsControllerTest < ActionController::TestCase
end
end
end

describe '#create from LTR' do
test 'convert a ltr line into a rating' do
rating = @controller.rating_from_ltr_line('0 qid:2 # 9755 "star trek"')
assert_equal '0', rating[:rating]
assert_equal '9755', rating[:doc_id]
assert_equal '"star trek"', rating[:query_text]

rating = @controller.rating_from_ltr_line(' 0 qid:2 # 9755 star trek')
assert_equal '0', rating[:rating]
assert_equal '9755', rating[:doc_id]
assert_equal 'star trek', rating[:query_text]
end
end
end
end
end
Expand Down

0 comments on commit b245319

Please sign in to comment.