lib/ceml/script.rb in ceml-0.3.0 vs lib/ceml/script.rb in ceml-0.3.1

- old
+ new

@@ -1,72 +1,183 @@ module CEML module Script + extend Forwardable + attr_writer :delegate + def delegate; @delegate || CEML.delegate; end - def to_hash *fields - fields.inject({}){ |h, s| x = send(s); h[s] = x if x; h } + # =========== + # = casting = + # =========== + + def locations + @locations ||= (delegate.locations(self) || []) end - def script - text_value + def launchable_location + criteria = awaited_criteria.sort_by{ |c| [-c.complexity, c.min_match] } + locations.find do |l| + people_used = [] + criteria.all?{ |c| folks = l[c.hash] and c.satisfied_by_group?(folks, people_used) } + end end - def title - super && !super.empty? && super.value + # public + def post candidate + criteria = awaited_criteria.select{ |c| c =~ candidate } + criteria.each{ |c| c.list_candidate(candidate) } + not criteria.empty? end - def name - title || label + def awaited_criteria + return [] unless cast.type == :await + return cast.criteria(self) end - def radius - casting_statement.empty? ? nil : casting_statement.radius + + # =============== + # = likelihoods = + # =============== + + def color(odds) + return :red if odds < 0.1 + return :yellow if odds < 0.4 + return :green end - def roles - return [:agents] if casting_statement.empty? - return casting_statement.roles + def likelihood(yesprob, needed, psize) + return 1 if needed <= 0 + return 0 if psize < needed + return (needed..psize).inject(0) do |memo, yes_count| + memo + begin + no_count = psize - yes_count + ways_it_could_happen = psize.choose(yes_count) + prob_of_each = (yesprob ** yes_count) * ((1 - yesprob) ** no_count) + ways_it_could_happen * prob_of_each + end + end end - def dramatis_personae - casting_statement.empty? ? nil : casting_statement + def availabilities(potential_count, committed_count = 0) + return {} unless script.dramatis_personae + min = script.dramatis_personae.min + needed = min - committed_count + possible = potential_count + committed_count + yesprob = 0.7 # just make this up for now + odds = likelihood(yesprob, needed, potential_count) + + { + :odds => odds, :color => color(odds), + :availability_counts => { + :total => possible, + :unknown => potential_count + }, + :estimated_size => yesprob * potential_count + committed_count, + :needed => min + } end - def max_to_invite - dramatis_personae ? dramatis_personae.max : 0 + + # ======== + # = cast = + # ======== + + DefaultDP = Struct.new :radius, :rolenames, :max, :type + + def cast + return casting_statement if respond_to? :casting_statement + return DefaultDP.new nil, [:agents], 0, :nab end + def_delegators :cast, :radius + def_delegator :cast, :max, :max_to_invite + def_delegator :cast, :rolenames, :roles + alias_method :dramatis_personae, :cast alias_method :dp, :dramatis_personae + # casting_statement.roles.names + def simple? (roles - [:agents, :organizer]).empty? end def expand_roles(roles) roles.map{ |r| r == :agent ? [:agent, :agents] : r }.flatten.concat([:both, :all, :everyone]) end + def allowed_roles + allowed_roles = [:organizer, :agents] + allowed_roles += cast.rolenames + allowed_roles.uniq + end + + + # ================ + # = instructions = + # ================ + + def instructions + return super if defined?(super) + return self if Instructions === self + nil + end + def instructions_for(roles) - return [] if !instructions or instructions.empty? + return [] unless instructions return instructions.for(expand_roles(roles)) end def asks(roles) - return [] if instructions.empty? - instructions.asks([*roles]) + return [] unless instructions + instructions.i_asks([*roles]) end + def tell(roles) + return unless instructions + instructions.i_tell([*roles]) + end + + def validate! + return unless instructions + instructions.validate_instructions!(allowed_roles) + end + + def concludes_immediately? + !title and instructions.asks([:agents]).empty? + end + + + # ======= + # = etc = + # ======= + + def to_hash *fields + fields.inject({}){ |h, s| x = send(s); h[s] = x if x; h } + end + + def script + text_value + end + + def title + if defined?(super) + super.title_value + elsif respond_to? :title_value + self.title_value + else nil + end + end + + def name + title || label + end + def params asks(:organizer).map do |ask| [ask.var, ask.var.capitalize, ask.text] end end - def tell(roles) - return nil if instructions.empty? - instructions.tell([*roles]) - end - def type return 'mission' if title return 'unknown' if instructions.empty? return 'question' if not instructions.asks.empty? return 'message' if instructions.tell(:agents) @@ -87,60 +198,7 @@ else "unknown" end end end - - def validate! - instructions.validate!(allowed_roles) unless instructions.empty? - end - - def allowed_roles - allowed_roles = [:organizer, :agents] - allowed_roles += casting_statement.roles unless casting_statement.empty? - allowed_roles - end - - def concludes_immediately? - !title and instructions.asks([:agents]).empty? - end - - def color(odds) - return :red if odds < 0.1 - return :yellow if odds < 0.4 - return :green - end - - def likelihood(yesprob, needed, psize) - return 1 if needed <= 0 - return 0 if psize < needed - return (needed..psize).inject(0) do |memo, yes_count| - memo + begin - no_count = psize - yes_count - ways_it_could_happen = psize.choose(yes_count) - prob_of_each = (yesprob ** yes_count) * ((1 - yesprob) ** no_count) - ways_it_could_happen * prob_of_each - end - end - end - - def availabilities(potential_count, committed_count = 0) - return {} unless script.dramatis_personae - min = script.dramatis_personae.min - needed = min - committed_count - possible = potential_count + committed_count - yesprob = 0.7 # just make this up for now - odds = likelihood(yesprob, needed, potential_count) - - { - :odds => odds, :color => color(odds), - :availability_counts => { - :total => possible, - :unknown => potential_count - }, - :estimated_size => yesprob * potential_count + committed_count, - :needed => min - } - end - end end