lib/activefacts/vocabulary/extensions.rb in activefacts-0.8.10 vs lib/activefacts/vocabulary/extensions.rb in activefacts-0.8.12

- old
+ new

@@ -51,10 +51,14 @@ def reading_preferably_starting_with_role role all_reading_by_ordinal.detect do |reading| reading.text =~ /\{\d\}/ and reading.role_sequence.all_role_ref_in_order[$1.to_i].role == role end || preferred_reading end + + def all_role_in_order + all_role.sort_by{|r| r.ordinal} + end end class Role def describe(highlight = nil) object_type.name + (self == highlight ? "*" : "") @@ -177,11 +181,11 @@ end end class EntityType def preferred_identifier - #return @preferred_identifier if @preferred_identifier + return @preferred_identifier if @preferred_identifier if fact_type # For a nested fact type, the PI is a unique constraint over N or N-1 roles fact_roles = Array(fact_type.all_role) debug :pi, "Looking for PI on nested fact type #{name}" do @@ -388,43 +392,47 @@ 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 - la = "#{role_ref.leading_adjective}".sub(/(.\b|.\Z)/, '\1-').sub(/- /,'- ') - la = nil if la == "" + 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 - ta = "#{role_ref.trailing_adjective}".sub(/(\b.|\A.)/, '-\1').sub(/ -/,' -') - ta = nil if ta == "" + # REVISIT: hyphenated trailing adjectives are not correctly represented here + t_adj = "#{role_ref.trailing_adjective}".sub(/(\b.|\A.)/, '-\1').sub(/ -/,' -') + t_adj = nil if t_adj == "" - expanded.gsub!(/\{#{i}\}/) { + expanded.gsub!(/\{#{i}\}/) do role_ref = role_refs[i] player = role_ref.role.object_type role_name = role.role_name role_name = nil if role_name == "" if role_name && define_role_names == false - la = ta = nil # When using role names, don't add adjectives + l_adj = t_adj = nil # When using role names, don't add adjectives end - fc = frequency_constraints[i] - fc = fc.frequency if fc && fc.is_a?(ActiveFacts::Metamodel::PresenceConstraint) - if fc.is_a?(Array) - fc, player_name = *fc + 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 literal = literals[i] - [ - fc ? fc : nil, - la, + words = [ + freq_con ? freq_con : nil, + l_adj, define_role_names == false && role_name ? role_name : player_name, - ta, + 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 - ].compact*" " + - (subscript_block ? subscript_block.call(role_ref) : "") - } + ] + if (subscript_block) + words = subscript_block.call(role_ref, *words) + end + words.compact*" " + end } expanded.gsub!(/ ?- ?/, '-') # Remove single spaces around adjectives #debug "Expanded '#{expanded}' using #{frequency_constraints.inspect}" expanded end @@ -439,10 +447,41 @@ else frag end end end + + # Return the array of the numbers of the RoleRefs inserted into this reading from the role_sequence + def role_numbers + text.scan(/\{(\d)\}/).flatten.map{|m| Integer(m) } + end + + 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 end class ValueConstraint def describe "restricted to {"+ @@ -480,20 +519,20 @@ min_literal = min.literal.inspect.gsub(/\A"|"\Z/,"'") # Escape string characters else min_literal = min.literal end else - min_literal = infinity ? "INFINITY" : "" + min_literal = infinity ? "-Infinity" : "" end if max = value_range.maximum_bound max = max.value if max.is_a_string max_literal = max.literal.inspect.gsub(/\A"|"\Z/,"'") # Escape string characters else max_literal = max.literal end else - max_literal = infinity ? "INFINITY" : "" + max_literal = infinity ? "Infinity" : "" end min_literal + (min_literal != (max&&max_literal) ? (".." + max_literal) : "") end