zooniverse/Cellect

View on GitHub
lib/cellect/server/grouped_workflow.rb

Summary

Maintainability
A
0 mins
Test Coverage
module Cellect
  module Server
    class GroupedWorkflow < Workflow

      # Sets up the new workflow
      def initialize(name, pairwise: false, prioritized: false)
        self.subjects = { }
        super
      end

      def groups
        subjects
      end

      # Returns a group by id
      # if the group_id is supplied it will select or setup this group
      # when no group_id is supplied, it attempts to select a random group
      # finally if no loaded groupes it falls back to creating a new empty group
      def group(group_id = nil)
        group = if group_id
                  fetch_or_setup_group(group_id)
                else
                  subjects.values.sample
                end
        group || fetch_or_setup_group(group_id)
      end

      # Get unseen subjects from a group for a user
      def unseen_for(user_name, group_id: nil, limit: 5)
        group(group_id).subtract user(user_name).seen, limit
      end

      # Get a sample of subjects from a group for a user
      #
      # Accepts a hash in the form:
      #   {
      #     user_id: 123,
      #     group_id: 2,
      #     limit: 5
      #   }
      def sample(opts = { })
        if opts[:user_id]
          unseen_for opts[:user_id], group_id: opts[:group_id], limit: opts[:limit]
        else
          group(opts[:group_id]).sample opts[:limit]
        end
      end

      # Adds or updates a subject in a group
      #
      # Accepts a hash in the form:
      # {
      #   subject_id: 1,
      #   group_id: 2,
      #   priority: 0.5  # (if the workflow is prioritized)
      # }
      def add(opts = { })
        add_group = fetch_or_setup_group(opts[:group_id])

        if prioritized?
          add_group.add opts[:subject_id], opts[:priority]
        else
          add_group.add opts[:subject_id]
        end
      end

      # Removes a subject from a group
      #
      # Accepts a hash in the form:
      # {
      #   group_id: 1,
      #   subject_id: 2
      # }
      def remove(opts = { })
        if group = subjects[opts[:group_id]]
          group.remove opts[:subject_id]
        end
      end

      # General information about this workflow
      def status
        # Get the number of subjects in each group
        group_counts = Hash[*subjects.collect{ |id, set| [id, set.size] }.flatten]

        super.merge({
          grouped: true,
          subjects: group_counts.values.inject(:+),
          groups: group_counts
        })
      end

      def grouped?
        true
      end

      private

      def data_loader
        GroupedLoader.new(self)
      end

      def fetch_or_setup_group(group_id)
        subjects[group_id] ||= set_klass.new
      end
    end
  end
end