<commit_before>package turkey
package tasks

import turkey.util._

import com.amazonaws.mturk.requester.{HIT => MTurkHIT}
import com.amazonaws.mturk.requester.{Assignment => MTurkAssignment}
import com.amazonaws.mturk.requester.QualificationRequirement
import com.amazonaws.mturk.requester.ReviewPolicy
import com.amazonaws.mturk.requester.PolicyParameter
import com.amazonaws.mturk.requester.AssignmentStatus
import com.amazonaws.mturk.service.axis.RequesterService
import com.amazonaws.mturk.dataschema.QuestionFormAnswersType

import java.util.Calendar

import scala.util.Try
import scala.concurrent.duration._

import akka.stream.scaladsl.Flow

import upickle.default._

/** Specifies a kind of task to run on MTurk.
  *
  * The code defining an individual task type will be here.
  * An instance of this class will correspond to a single HIT Type ID,
  * which is Mechanical Turk's way of categorizing HITs uploaded to the system.
  * This specifies the method to convert from `Prompt`s
  * (as in, the type parameter seen all over this project) into XML strings
  * that are POSTed to the MTurk API as questions shown to annotators.
  * It also has a method for converting from annotator responses (also XML strings)
  * into `Response`s.
  *
  * To implement the actual logic & interface of a task, the work is done in the client-side code.
  *
  * TaskSpecification is also responsible for holding HIT Type ID of its HIT Type.
  *
  * @tparam Prompt
  * @tparam Response
  */
sealed trait TaskSpecification {
  type Prompt
  implicit val promptWriter: Writer[Prompt]
  type Response
  implicit val responseReader: Reader[Response]
  type ApiRequest
  implicit val apiRequestReader: Reader[ApiRequest]
  type ApiResponse
  implicit val apiResponseWriter: Writer[ApiResponse]
  implicit val config: TaskConfig

  val taskKey: String
  val hitType: HITType
  val apiFlow: Flow[ApiRequest, ApiResponse, Any]
  val samplePrompt: Prompt
  val frozenHITTypeId: Option[String]

  /** The HIT Type ID for this task.
    *
    * When this is accessed with a certain set of parameters for the first time,
    * a new HIT Type ID will be registered on Amazon's systems.
    * Subsequent calls with the same parameters will always return this same value,
    * for the life of the HIT Type (which I believe expires 30 days after the last time it is used.
    * It may be 90 days. TODO check on that. But it doesn't really matter...)
    *
    * I'm not 100% sure this needs to be lazy... but it's not hurting anyone as it is.
    */
  final lazy val hitTypeId = frozenHITTypeId.getOrElse(
    config.service.registerHITType(
      autoApprovalDelay,
      assignmentDuration,
      reward,
      title,
      keywords,
      description,
      qualRequirements)
  )

  /** Creates a HIT on MTurk.<commit_msg>Fix silly error, oops.<commit_after>package turkey
package tasks

import turkey.util._

import com.amazonaws.mturk.requester.{HIT => MTurkHIT}
import com.amazonaws.mturk.requester.{Assignment => MTurkAssignment}
import com.amazonaws.mturk.requester.QualificationRequirement
import com.amazonaws.mturk.requester.ReviewPolicy
import com.amazonaws.mturk.requester.PolicyParameter
import com.amazonaws.mturk.requester.AssignmentStatus
import com.amazonaws.mturk.service.axis.RequesterService
import com.amazonaws.mturk.dataschema.QuestionFormAnswersType

import java.util.Calendar

import scala.util.Try
import scala.concurrent.duration._

import akka.stream.scaladsl.Flow

import upickle.default._

/** Specifies a kind of task to run on MTurk.
  *
  * The code defining an individual task type will be here.
  * An instance of this class will correspond to a single HIT Type ID,
  * which is Mechanical Turk's way of categorizing HITs uploaded to the system.
  * This specifies the method to convert from `Prompt`s
  * (as in, the type parameter seen all over this project) into XML strings
  * that are POSTed to the MTurk API as questions shown to annotators.
  * It also has a method for converting from annotator responses (also XML strings)
  * into `Response`s.
  *
  * To implement the actual logic & interface of a task, the work is done in the client-side code.
  *
  * TaskSpecification is also responsible for holding HIT Type ID of its HIT Type.
  *
  * @tparam Prompt
  * @tparam Response
  */
sealed trait TaskSpecification {
  type Prompt
  implicit val promptWriter: Writer[Prompt]
  type Response
  implicit val responseReader: Reader[Response]
  type ApiRequest
  implicit val apiRequestReader: Reader[ApiRequest]
  type ApiResponse
  implicit val apiResponseWriter: Writer[ApiResponse]
  implicit val config: TaskConfig

  val taskKey: String
  val hitType: HITType
  val apiFlow: Flow[ApiRequest, ApiResponse, Any]
  val samplePrompt: Prompt
  val frozenHITTypeId: Option[String]

  /** The HIT Type ID for this task.
    *
    * When this is accessed with a certain set of parameters for the first time,
    * a new HIT Type ID will be registered on Amazon's systems.
    * Subsequent calls with the same parameters will always return this same value,
    * for the life of the HIT Type (which I believe expires 30 days after the last time it is used.
    * It may be 90 days. TODO check on that. But it doesn't really matter...)
    *
    * I'm not 100% sure this needs to be lazy... but it's not hurting anyone as it is.
    */
  final lazy val hitTypeId = frozenHITTypeId.getOrElse(
    config.service.registerHITType(
      hitType.autoApprovalDelay,
      hitType.assignmentDuration,
      hitType.reward,
      hitType.title,
      hitType.keywords,
      hitType.description,
      hitType.qualRequirements)
  )

  /** Creates a HIT on MTurk.
{'fraction_non_alphanumeric': 0.06471521777464292, 'fraction_numerical': 0.0024687004055722094, 'mean_word_length': 3.7345575959933224, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1889039', 'n_tokens_mistral': 1689, 'n_tokens_neox': 1665, 'n_words': 644}