<commit_before>Subject = require('models/subject')
User = require 'zooniverse/lib/models/user'
Experiments = require 'lib/experiments'
Api = require 'zooniverse/lib/api'
AnalyticsLogger = require 'lib/analytics'

# An Experimental Subject is a specialized subject for use in SerengetiInterestingAnimalsExperiment1 (in future can be generalized to other experiments)
class ExperimentalSubject extends Subject
  @configure "ExperimentalSubject", 'zooniverseId', 'workflowId', 'location', 'coords', 'metadata'

  # override parent as we need additional info
  @fromJSON: (raw) =>
    if !Experiments.sources[raw.zooniverse_id]?
      Experiments.sources[raw.zooniverse_id]=Experiments.SOURCE_NORMAL

    subject = @create
      id: raw.id
      zooniverseId: raw.zooniverse_id
      workflowId: raw.workflow_ids[0]
      location: raw.location
      coords: raw.coords
      metadata: raw.metadata
    # Preload images.
    (new Image).src = src for src in subject.location.standard
    subject

  # same as parent, but this one logs experimental insertions as they are presented to the user, and marks them as seen
  @selectFirstNonEmptySubject: ->
    first = @first()
    first?.destroy() if first?.metadata.empty
    numberOfSubjectsAlreadyLoaded = @count()
    if numberOfSubjectsAlreadyLoaded is 0
      @trigger 'no-subjects'
    else
      subject = @first()
      if Experiments.ACTIVE_EXPERIMENT? && Experiments.ACTIVE_EXPERIMENT=="SerengetiInterestingAnimalsExperiment1"
        if Experiments.sources[subject.zooniverseId] == Experiments.SOURCE_INSERTED
          AnalyticsLogger.logEvent 'insertion','specific'
        else if Experiments.sources[subject.zooniverseId] == Experiments.SOURCE_RANDOM
          AnalyticsLogger.logEvent 'insertion','random'
        @markAsSeen subject.zooniverseId
      subject.select()

  # get a specific subject by ID from the API and instantiate it as a model
  @subjectFetch: (subjectID) =>
    subjectFetcher = new $.Deferred

    getter = Api.get("/projects/serengeti/subjects/#{subjectID}").deferred

    getter.done (rawSubject) =>
      subjectFetcher.resolve (@fromJSON rawSubject)

    getter.fail =>
      # resort to a random image
      @fetch(1).done (rawSubject) =>
        rawSubject.missing = true
        subjectFetcher.resolve (@fromJSON rawSubject)

    subjectFetcher.promise()

  # instantiates more subjects, at random but does not do anything with them
  @loadMoreRandomSubjects: (numberOfSubjectsToFetch) =>
    @fetch numberOfSubjectsToFetch unless numberOfSubjectsToFetch < 1

  # instantiates more subjects, according to experiment, but doesn't do anything with them
  @loadMoreExperimentalSubjects: (numberOfSubjectsToFetch) =>
    if numberOfSubjectsToFetch >= 1
      backgroundFetcher = @getNextSubjectIDs numberOfSubjectsToFetch
      backgroundFetcher
      .then (response) =>
        if response?
          Experiments.currentParticipant = response.participant
          nextSubjectIDs = response.nextSubjectIDs
          if nextSubjectIDs? && nextSubjectIDs.length == 0
            # TODO add some fallback code here (end of experiment)
          else
            for subjectID in nextSubjectIDs
              do (subjectID) =>
                if subjectID == "RANDOM"
                  backgroundFetcher.then =>
                    @fetch(1)
                    .then (subject) =>
                      if subject?
                        Experiments.sources[subject[0].zooniverseId]=Experiments.SOURCE_RANDOM
                else
                  backgroundFetcher.then =>
                    @subjectFetch(subjectID)
                    .then (subject) =>
                      if subject?
                        Experiments.sources[subjectID]=Experiments.SOURCE_INSERTED<commit_msg>alert when finished (for QA only). Add details to Geordi logging.<commit_after>Subject = require('models/subject')
User = require 'zooniverse/lib/models/user'
Experiments = require 'lib/experiments'
Api = require 'zooniverse/lib/api'
AnalyticsLogger = require 'lib/analytics'

# An Experimental Subject is a specialized subject for use in SerengetiInterestingAnimalsExperiment1 (in future can be generalized to other experiments)
class ExperimentalSubject extends Subject
  @configure "ExperimentalSubject", 'zooniverseId', 'workflowId', 'location', 'coords', 'metadata'

  # override parent as we need additional info
  @fromJSON: (raw) =>
    if !Experiments.sources[raw.zooniverse_id]?
      Experiments.sources[raw.zooniverse_id]=Experiments.SOURCE_NORMAL

    subject = @create
      id: raw.id
      zooniverseId: raw.zooniverse_id
      workflowId: raw.workflow_ids[0]
      location: raw.location
      coords: raw.coords
      metadata: raw.metadata
    # Preload images.
    (new Image).src = src for src in subject.location.standard
    subject

  # same as parent, but this one logs experimental insertions as they are presented to the user, and marks them as seen
  @selectFirstNonEmptySubject: ->
    first = @first()
    first?.destroy() if first?.metadata.empty
    numberOfSubjectsAlreadyLoaded = @count()
    if numberOfSubjectsAlreadyLoaded is 0
      @trigger 'no-subjects'
    else
      subject = @first()
      if Experiments.ACTIVE_EXPERIMENT? && Experiments.ACTIVE_EXPERIMENT=="SerengetiInterestingAnimalsExperiment1"
        if Experiments.sources[subject.zooniverseId] == Experiments.SOURCE_INSERTED
          AnalyticsLogger.logEvent 'insertion','specific',User.current?.zooniverse_id,subject.zooniverseId
        else if Experiments.sources[subject.zooniverseId] == Experiments.SOURCE_RANDOM
          AnalyticsLogger.logEvent 'insertion','random',User.current?.zooniverse_id,subject.zooniverseId
        @markAsSeen subject.zooniverseId
      subject.select()

  # get a specific subject by ID from the API and instantiate it as a model
  @subjectFetch: (subjectID) =>
    subjectFetcher = new $.Deferred

    getter = Api.get("/projects/serengeti/subjects/#{subjectID}").deferred

    getter.done (rawSubject) =>
      subjectFetcher.resolve (@fromJSON rawSubject)

    getter.fail =>
      # resort to a random image
      @fetch(1).done (rawSubject) =>
        rawSubject.missing = true
        subjectFetcher.resolve (@fromJSON rawSubject)

    subjectFetcher.promise()

  # instantiates more subjects, at random but does not do anything with them
  @loadMoreRandomSubjects: (numberOfSubjectsToFetch) =>
    @fetch numberOfSubjectsToFetch unless numberOfSubjectsToFetch < 1

  # instantiates more subjects, according to experiment, but doesn't do anything with them
  @loadMoreExperimentalSubjects: (numberOfSubjectsToFetch) =>
    if numberOfSubjectsToFetch >= 1
      backgroundFetcher = @getNextSubjectIDs numberOfSubjectsToFetch
      backgroundFetcher
      .then (response) =>
        if response?
          Experiments.currentParticipant = response.participant
          nextSubjectIDs = response.nextSubjectIDs
          if nextSubjectIDs? && nextSubjectIDs.length == 0
            Experiments.currentParticipant.cohort = Experiments.COHORT_CONTROL
            Experiments.currentCohort = Experiments.COHORT_CONTROL
            Experiments.currentParticipant.active = false
            alert "You have now completed your experiment. Thanks for participating"
          else
            for subjectID in nextSubjectIDs
              do (subjectID) =>
                if subjectID == "RANDOM"
                  backgroundFetcher.then =>
                    @fetch(1)
                    .then (subject) =>
                      if subject?
                        Experiments.sources[subject[0].zooniverseId]=Experiments.SOURCE_RANDOM
                else
                  backgroundFetcher.then =>
                    @subjectFetch(subjectID)
                    .then (subject) =>
                      if subject?
                        Experiments.sources[subjectID]=Experiments.SOURCE_INSERTED
{'fraction_non_alphanumeric': 0.08042488619119878, 'fraction_numerical': 0.0025290844714213456, 'mean_word_length': 2.9505494505494507, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 33, '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': '4108899', 'n_tokens_mistral': 2157, 'n_tokens_neox': 2085, 'n_words': 540}