Class: Course::Conditional::UserSatisfiabilityGraph

Inherits:
Object
  • Object
show all
Defined in:
lib/autoload/course/conditional/user_satisfiability_graph.rb

Overview

Satisfiability graph to evaluate the satisfiability of the conditionals for a course user.

Defined Under Namespace

Classes: EdgeSet

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(conditionals) ⇒ UserSatisfiabilityGraph

Initialize a topological sorted satisfiability graph.

Parameters:

  • conditionals (Array<Object>)

    Array of objects with acts_as_conditional

Raises:

  • (ArgumentError)

    When there is a cyclic dependency within the given conditionals


18
19
20
21
22
23
24
25
26
27
# File 'lib/autoload/course/conditional/user_satisfiability_graph.rb', line 18

def initialize(conditionals)
  @edges = EdgeSet.new
  @nodes = conditionals

  begin
    @graph = TSort.tsort(each_node, each_child)
  rescue TSort::Cyclic
    raise ArgumentError, 'Cyclic dependency detected in given conditionals'
  end
end

Class Method Details

.reachable?(source, dest) ⇒ Bool

Return true if the destination node is reachable from the source node

Parameters:

  • source (Object)

    Conditional node as the source

  • dest (Object)

    Conditional node as the destination

Returns:

  • (Bool)

    true if the dest node is reachable from the source node


60
61
62
63
64
65
# File 'lib/autoload/course/conditional/user_satisfiability_graph.rb', line 60

def self.reachable?(source, dest)
  return false unless dest
  return true if source == dest

  dest.specific_conditions.index { |c| reachable?(source, c.dependent_object) }.present?
end

Instance Method Details

#evaluate(course_user) ⇒ Set<Object>

Walk through the graph to evaluate the satisfiability of the conditionals for the course user.

Parameters:

  • course_user (Course::CourseUser)

    whose conditionals are to be evaluated

Returns:

  • (Set<Object>)

    All the satisfied conditions after evaluation


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/autoload/course/conditional/user_satisfiability_graph.rb', line 33

def evaluate(course_user)
  satisfied_conditions = Set.new

  # Walk through the graph to find all the satisfied conditionals
  @graph.each do |conditional|
    # Remove conditional if they are not available.
    unless conditional.satisfiable?
      conditional.precluded_for!(course_user)
      next
    end

    conditions = conditional.specific_conditions.select { |c| c.satisfied_by?(course_user) }
    satisfied_conditions.merge(Set.new(conditions))

    # A conditional is satisfied if all its specific conditions are satisfied
    satisfied = conditions.count == conditional.specific_conditions.count
    satisfied ? conditional.permitted_for!(course_user) : conditional.precluded_for!(course_user)
  end

  satisfied_conditions
end