Class: ActiveFacts::Metamodel::Reading

Inherits:
Object
  • Object
show all
Defined in:
lib/activefacts/metamodel/metamodel.rb,
lib/activefacts/metamodel/extensions.rb

Instance Method Summary collapse

Instance Method Details

#expand(frequency_constraints = [], define_role_names = nil, literals = [], &subscript_block) ⇒ Object

The frequency_constraints array here, if supplied, may provide for each role either:

  • a PresenceConstraint to be verbalised against the relevant role, or
  • a String, used as a definite or indefinite article on the relevant role, or
  • an array containing two strings (an article and a super-type name) The order in the array is the same as the reading's role-sequence. REVISIT: This should probably be changed to be the fact role sequence.

define_role_names here is false (use defined names), true (define names) or nil (neither)



896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
# File 'lib/activefacts/metamodel/extensions.rb', line 896

def expand(frequency_constraints = [], define_role_names = nil, literals = [], &subscript_block)
  expanded = "#{text}"
  role_refs = role_sequence.all_role_ref.sort_by{|role_ref| role_ref.ordinal}
  (0...role_refs.size).each{|i|
      role_ref = role_refs[i]
      role = role_ref.role
      l_adj = "#{role_ref.leading_adjective}".sub(/(\b-\b|.\b|.\Z)/, '\1-').sub(/\b--\b/,'-- ').sub(/- /,'-  ')
      l_adj = nil if l_adj == ""
      # Double the space to compensate for space removed below
      t_adj = "#{role_ref.trailing_adjective}".sub(/\w+$/,' -\0').sub(/--\w*$/, ' \0')
      t_adj = nil if t_adj == ""

      expanded.gsub!(/\{#{i}\}/) do
          role_ref = role_refs[i]
          if role_ref.role
            player = role_ref.role.object_type
            role_name = role.role_name
            role_name = nil if role_name == ""
            if role_name && define_role_names == false
              l_adj = t_adj = nil   # When using role names, don't add adjectives
            end

            freq_con = frequency_constraints[i]
            freq_con = freq_con.frequency if freq_con && freq_con.is_a?(ActiveFacts::Metamodel::PresenceConstraint)
            if freq_con.is_a?(Array)
              freq_con, player_name = *freq_con
            else
              player_name = player.name
            end
          else
            # We have an unknown role. The reading cannot be correctly expanded
            player_name = "UNKNOWN"
            role_name = nil
            freq_con = nil
          end

          literal = literals[i]
          words = [
            freq_con ? freq_con : nil,
            l_adj,
            define_role_names == false && role_name ? role_name : player_name,
            t_adj,
            define_role_names && role_name && player_name != role_name ? "(as #{role_name})" : nil,
            # Can't have both a literal and a value constraint, but we don't enforce that here:
            literal ? literal : nil
          ]
          if (subscript_block)
            words = subscript_block.call(role_ref, *words)
          end
          words.compact*" "
      end
  }
  expanded.gsub!(/ ?- ?/, '-')        # Remove single spaces around adjectives
  #trace "Expanded '#{expanded}' using #{frequency_constraints.inspect}"
  expanded
end

#expand_with_final_presence_constraint(&b) ⇒ Object



971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
# File 'lib/activefacts/metamodel/extensions.rb', line 971

def expand_with_final_presence_constraint &b
  # Arrange the roles in order they occur in this reading:
  role_refs = role_sequence.all_role_ref_in_order
  role_numbers = text.scan(/\{(\d)\}/).flatten.map{|m| Integer(m) }
  roles = role_numbers.map{|m| role_refs[m].role }
  fact_constraints = fact_type.internal_presence_constraints

  # Find the constraints that constrain frequency over each role we can verbalise:
  frequency_constraints = []
  roles.each do |role|
    frequency_constraints <<
      if (role == roles.last)   # On the last role of the reading, emit any presence constraint
        constraint = fact_constraints.
          detect do |c|  # Find a UC that spans all other Roles
            c.is_a?(ActiveFacts::Metamodel::PresenceConstraint) &&
              roles-c.role_sequence.all_role_ref.map(&:role) == [role]
          end
        constraint && constraint.frequency
      else
        nil
      end
  end

  expand(frequency_constraints) { |*a| b && b.call(*a) }
end

#role_numbersObject

Return the array of the numbers of the RoleRefs inserted into this reading from the role_sequence



967
968
969
# File 'lib/activefacts/metamodel/extensions.rb', line 967

def role_numbers
  text.scan(/\{(\d)\}/).flatten.map{|m| Integer(m) }
end

#words_and_role_refsObject



953
954
955
956
957
958
959
960
961
962
963
964
# File 'lib/activefacts/metamodel/extensions.rb', line 953

def words_and_role_refs
  text.
  scan(/(?: |\{[0-9]+\}|[^{} ]+)/).   # split up the text into words
  reject{|s| s==' '}.                 # Remove white space
  map do |frag|                       # and go through the bits
    if frag =~ /\{([0-9]+)\}/
      role_sequence.all_role_ref.detect{|rr| rr.ordinal == $1.to_i}
    else
      frag
    end
  end
end