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