package com.bbn.kbp.events2014.transformers;

import com.bbn.kbp.events2014.AnswerKey;
import com.bbn.kbp.events2014.AssessedResponse;
import com.bbn.kbp.events2014.CharOffsetSpan;
import com.bbn.kbp.events2014.KBPString;
import com.bbn.kbp.events2014.KBPTIMEXExpression;
import com.bbn.kbp.events2014.Response;
import com.bbn.kbp.events2014.TypeRoleFillerRealis;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

 * Implements the rule for scoring temporal arguments as described below:
 * We would like to make the following proposed change to the assessment and scoring of *Time*
 * arguments.
 * (1) Systems are required to report CAS for Time arguments in the XXXX-XX-XX timex format (and not
 * the week-based format). Note: This was already true. There is pretty good library support for
 * doing so, see for example: Java: Python:
 * library) Haskell:
 * (2) Assessmentwill judge the context of the temporal CAS in the context as specified in the
 * current guidelines.
 * (3) LDC will *not* do coreference of temporal arguments
 * (4) The scoring metric will 'ignore' times that are subsumed by more specific times for
 * (EventType, Role, CAS, Realis) tuples. That is given correct answerswith: R1:
 * (Transport.Movement, Time, 2014-04-XX, Actual) R2: (Transport.Movement, Time, 2014-XX-XX,
 * Actual)
 * R1 will be 'required' to achieve 100% recall; R2 will be ignored (i.e. not treated as a FA, but
 * also not sufficient to match R1).
 * For participants, this will raise the importance of finding a correct, and most specific date
 * (and in cases where the date is given as e.g. the 15th week of 2014, systems will have to do the
 * temporal resolution.)
public final class OnlyMostSpecificTemporal implements AnswerKeyToResponseMappingRule {

  private static final Logger log = LoggerFactory.getLogger(OnlyMostSpecificTemporal.class);

  private OnlyMostSpecificTemporal() {

  public static ScoringDataTransformation asTransformationForBoth() {
    return ApplyAnswerKeyToResponseMappingRuleToAll.forRuleApplyingToBoth(
        new OnlyMostSpecificTemporal());

  private static ImmutableSet<TypeRoleFillerRealis> computeBannedResponseSignatures(
      final AnswerKey key) {
    final ImmutableSet.Builder<TypeRoleFillerRealis> bannedResponseSignatures =

    for (final AssessedResponse response : key.annotatedResponses()) {
      if (response.assessment().entityCorrectFiller().isPresent()
          && response.assessment().entityCorrectFiller().get().isAcceptable()
          && response.response().isTemporal()) {
        try {
          final KBPTIMEXExpression time = KBPTIMEXExpression.parseTIMEX(

          final TypeRoleFillerRealis responseSignature = responseSignature(response.response());

          for (final KBPTIMEXExpression lessSpecificTimex : time.lessSpecificCompatibleTimes()) {
                KBPString.from(lessSpecificTimex.toString(), DUMMY_OFFSETS)));
        } catch (KBPTIMEXExpression.KBPTIMEXException timexException) {
              "While applying only-most-specific-temporal rule, encountered an illegal temporal "
                  + "expression " + response.response().canonicalArgument().string()
                  + " which was evaluated as "
                  + "correct. Such responses should have incorrect CAS assessments.");


  private static TypeRoleFillerRealis responseSignature(Response response) {
    final TypeRoleFillerRealis responseSignatureWithOffsets =
    return responseSignatureWithOffsets

  private static final CharOffsetSpan DUMMY_OFFSETS = CharOffsetSpan.fromOffsetsOnly(0, 0);

  private static KBPString copyWithDummyOffsets(KBPString s) {
    return KBPString.from(s.string(), DUMMY_OFFSETS);

  public ResponseMapping computeResponseTransformation(final AnswerKey answerKey) {
    final ImmutableSet<TypeRoleFillerRealis> bannedResponseSignatures =

    final ImmutableSet.Builder<Response> toDelete = ImmutableSet.builder();
    for (final Response response : answerKey.allResponses()) {
      if (bannedResponseSignatures.contains(responseSignature(response))) {

    return ResponseMapping.create(ImmutableMap.<Response, Response>of(),;