ceml 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/VERSION +1 -1
- data/beginners-guide.md +7 -7
- data/ceml.gemspec +78 -0
- data/examples/sample_delegate.rb +4 -0
- data/lib/ceml/casting.rb +15 -33
- data/lib/ceml/casting_criterion.rb +39 -0
- data/lib/ceml/instructions.rb +11 -10
- data/lib/ceml/script.rb +136 -78
- data/lib/ceml/tt/casting.treetop +26 -29
- data/lib/ceml/tt/instructions.treetop +4 -8
- data/lib/ceml/tt/lexer.treetop +42 -3
- data/lib/ceml/tt/scripts.treetop +25 -10
- data/lib/ceml.rb +13 -14
- data/test/helper.rb +0 -19
- data/test/test_casting.rb +9 -10
- data/test/test_incident.rb +25 -0
- data/test/test_instructions.rb +2 -2
- data/test/test_scripts.rb +1 -1
- data/try +14 -0
- metadata +7 -7
- data/lib/ceml/tt/casting.rb +0 -618
- data/lib/ceml/tt/instructions.rb +0 -409
- data/lib/ceml/tt/lexer.rb +0 -400
- data/lib/ceml/tt/scripts.rb +0 -345
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.1
|
data/beginners-guide.md
CHANGED
@@ -6,11 +6,11 @@ Thanks for taking an interest in CEML, the Coordinated Event Modeling Language.
|
|
6
6
|
A CEML _script_ is a recipe for action. Just like a recipe, it has three parts: a title, a list of ingredients, and then a section that says what to do with the ingredients. Here's an example:
|
7
7
|
|
8
8
|
"Trade favorite colors"
|
9
|
-
gather 1
|
10
|
-
ask
|
9
|
+
gather 1 guy and 1 girl within 50 feet
|
10
|
+
ask guy re favorite_color:
|
11
11
|
What's your favorite color?
|
12
|
-
tell
|
13
|
-
Someone nearby likes the color |
|
12
|
+
tell girl:
|
13
|
+
Someone nearby likes the color |guy.favorite_color|. Find them.
|
14
14
|
|
15
15
|
In the example, the first line is the title, which is written in double quotes. The second line is the ingredients and how they are obtained. In CEML, the ingredients are usually people (although sometimes they can be places, things, or notes). The remaining lines are the instructions.
|
16
16
|
|
@@ -26,7 +26,7 @@ Whether you write a script compactly with short names for roles and answers or l
|
|
26
26
|
Commands
|
27
27
|
--------
|
28
28
|
|
29
|
-
The above script only uses three CEML commands
|
29
|
+
The above script only uses three CEML commands--*gather*, *ask*, and *tell*--but there aren't many more commands to learn. Only four more, actually: besides *gather*, the other ingredients commands are *await* and *nab*. Besides *ask* and *tell*, the other instructions commands are *assign* and *certify*.
|
30
30
|
|
31
31
|
As a sneak preview, here's an example that uses the other commands:
|
32
32
|
|
@@ -65,7 +65,7 @@ Texts may also contain hyperlinks, which if the player has a smartphone with a w
|
|
65
65
|
Roles
|
66
66
|
-----
|
67
67
|
|
68
|
-
In the examples so far, the words like 'enemy', 'reporter', '
|
68
|
+
In the examples so far, the words like 'enemy', 'reporter', 'guy', 'girl', 'a', 'b', 'signup', 'patient', and 'doctor' are *role names*. Most of the time, a role name can be any word you like. They are just a placeholder to connect *casting commands* like *gather* and *await*, with *coordination commands* like *tell*.
|
69
69
|
|
70
70
|
Squads on Groundcrew, however, can define special meanings for certain roles. So on a particular squad, a 'doctor' might mean someone who's been tagged/certified with the tag 'doctor', and a patient might mean anyone else.
|
71
71
|
|
@@ -120,7 +120,7 @@ Choosing Players: Await, Gather, and Nab.
|
|
120
120
|
|
121
121
|
So what is really the difference between *await*, *gather*, and *nab*, you may be asking? Or perhaps you have already figured it out.
|
122
122
|
|
123
|
-
*Await* defines a kind of trigger
|
123
|
+
*Await* defines a kind of trigger--as soon as the conditions awaited for are met, the script will run.
|
124
124
|
|
125
125
|
await 2-5 level1 players within 50ft
|
126
126
|
assign: shout out "woo-hoo!"
|
data/ceml.gemspec
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{ceml}
|
8
|
+
s.version = "0.3.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Joe Edelman"]
|
12
|
+
s.date = %q{2010-12-26}
|
13
|
+
s.description = %q{a language for coordinating real world events}
|
14
|
+
s.email = %q{joe@citizenlogistics.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.markdown"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
"LICENSE",
|
23
|
+
"Makefile",
|
24
|
+
"README.markdown",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"beginners-guide.md",
|
28
|
+
"ceml.gemspec",
|
29
|
+
"editors/CEML.tmbundle/Syntaxes/ceml.tmLanguage",
|
30
|
+
"editors/CEML.tmbundle/info.plist",
|
31
|
+
"examples/breakfast-exchange.ceml",
|
32
|
+
"examples/citizen-investigation.ceml",
|
33
|
+
"examples/high-fives.ceml",
|
34
|
+
"lib/ceml.rb",
|
35
|
+
"lib/ceml/casting.rb",
|
36
|
+
"lib/ceml/casting_criterion.rb",
|
37
|
+
"lib/ceml/incident.rb",
|
38
|
+
"lib/ceml/instructions.rb",
|
39
|
+
"lib/ceml/script.rb",
|
40
|
+
"lib/ceml/tt/casting.treetop",
|
41
|
+
"lib/ceml/tt/instructions.treetop",
|
42
|
+
"lib/ceml/tt/lexer.treetop",
|
43
|
+
"lib/ceml/tt/scripts.treetop",
|
44
|
+
"test/helper.rb",
|
45
|
+
"test/test_casting.rb",
|
46
|
+
"test/test_incident.rb",
|
47
|
+
"test/test_instructions.rb",
|
48
|
+
"test/test_scripts.rb",
|
49
|
+
"try"
|
50
|
+
]
|
51
|
+
s.homepage = %q{http://github.com/citizenlogistics/ceml}
|
52
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
53
|
+
s.require_paths = ["lib"]
|
54
|
+
s.rubygems_version = %q{1.3.6}
|
55
|
+
s.summary = %q{a language for coordinating real world events}
|
56
|
+
s.test_files = [
|
57
|
+
"test/helper.rb",
|
58
|
+
"test/test_casting.rb",
|
59
|
+
"test/test_incident.rb",
|
60
|
+
"test/test_instructions.rb",
|
61
|
+
"test/test_scripts.rb",
|
62
|
+
"examples/sample_delegate.rb"
|
63
|
+
]
|
64
|
+
|
65
|
+
if s.respond_to? :specification_version then
|
66
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
67
|
+
s.specification_version = 3
|
68
|
+
|
69
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
70
|
+
s.add_runtime_dependency(%q<treetop>, [">= 0"])
|
71
|
+
else
|
72
|
+
s.add_dependency(%q<treetop>, [">= 0"])
|
73
|
+
end
|
74
|
+
else
|
75
|
+
s.add_dependency(%q<treetop>, [">= 0"])
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
data/lib/ceml/casting.rb
CHANGED
@@ -1,52 +1,34 @@
|
|
1
1
|
module CEML
|
2
2
|
module CastingStatement
|
3
3
|
extend Forwardable
|
4
|
-
def_delegators :
|
4
|
+
def_delegators :roles, :names, :[], :min
|
5
|
+
alias_method :rolenames, :names
|
6
|
+
|
7
|
+
def criteria(script)
|
8
|
+
return [] unless type == :await
|
9
|
+
group_by = if radius then [:city] else [] end
|
10
|
+
criteria_by_qualifiers = Hash.new do |h,k|
|
11
|
+
h[k] = CastingCriterion.new(script, k, [], group_by, radius, {})
|
12
|
+
end
|
13
|
+
|
14
|
+
roles.list.each{ |r| criteria_by_qualifiers[r.qualifiers].role_counts[r.name] = r.min }
|
15
|
+
criteria_by_qualifiers.values
|
16
|
+
end
|
5
17
|
|
6
18
|
def type
|
7
19
|
elements.first.text_value.split.first.to_sym
|
8
20
|
end
|
9
21
|
|
10
22
|
def max
|
11
|
-
|
23
|
+
roles.max
|
12
24
|
end
|
13
25
|
|
14
26
|
def radius
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
def in_teams?
|
19
|
-
type == :teams
|
27
|
+
within_phrase.empty? ? 1600 * 50 : within_phrase.distance.meters
|
20
28
|
end
|
21
29
|
|
22
30
|
def nab?
|
23
31
|
type == :nab
|
24
32
|
end
|
25
33
|
end
|
26
|
-
|
27
|
-
|
28
|
-
module CastingRoles
|
29
|
-
def role_nodes
|
30
|
-
return [role] if more_roles.empty?
|
31
|
-
return [role] + more_roles.roles_phrase.role_nodes
|
32
|
-
end
|
33
|
-
|
34
|
-
def roles
|
35
|
-
role_nodes.map{ |r| r.name.to_sym }
|
36
|
-
end
|
37
|
-
|
38
|
-
def [](x)
|
39
|
-
role_nodes.detect{ |r| r.name.to_sym == x }
|
40
|
-
end
|
41
|
-
|
42
|
-
def min
|
43
|
-
role_nodes.map(&:min).inject(0, &:+)
|
44
|
-
end
|
45
|
-
|
46
|
-
def max
|
47
|
-
role_nodes.map(&:max).inject(0, &:+)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
|
52
34
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'geokit'
|
2
|
+
require "forwardable"
|
3
|
+
|
4
|
+
module CEML
|
5
|
+
class Candidate < Struct.new :uid, :tags, :matchables, :lat, :lng
|
6
|
+
include Geokit::Mappable
|
7
|
+
end
|
8
|
+
|
9
|
+
class CastingCriterion < Struct.new :script, :plus_tags, :minus_tags, :grouped_by, :radius, :role_counts
|
10
|
+
extend Forwardable
|
11
|
+
def_delegators :script, :locations
|
12
|
+
def min_match; role_counts.values.reduce(:+); end
|
13
|
+
def complexity; plus_tags.size; end
|
14
|
+
|
15
|
+
def =~(candidate)
|
16
|
+
(plus_tags - candidate.tags).empty? and (minus_tags & candidate.tags).empty?
|
17
|
+
end
|
18
|
+
|
19
|
+
def satisfied_by_group?(people, already_used)
|
20
|
+
if (people - already_used).size >= min_match
|
21
|
+
already_used.concat((people - already_used).first(min_match))
|
22
|
+
true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def list_candidate(candidate)
|
27
|
+
locs = locations.select do |l|
|
28
|
+
star = l.values.flatten.first
|
29
|
+
next unless grouped_by.all?{ |g| candidate.matchables[g] == star.matchables[g] }
|
30
|
+
!radius or candidate.distance_to(star, :meters) <= radius
|
31
|
+
end
|
32
|
+
if locs.empty?
|
33
|
+
new_loc = {}
|
34
|
+
[locations, locs].each{ |l| l << new_loc }
|
35
|
+
end
|
36
|
+
locs.each{ |l| (l[hash] ||= []) << candidate }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/ceml/instructions.rb
CHANGED
@@ -1,29 +1,30 @@
|
|
1
1
|
module CEML
|
2
2
|
module Instructions
|
3
|
-
def
|
3
|
+
def list
|
4
|
+
[instruction_stmt] + more.elements.map(&:instruction_stmt)
|
5
|
+
end
|
6
|
+
|
7
|
+
def validate_instructions!(allowed_roles)
|
4
8
|
extra_roles = roles - allowed_roles
|
5
9
|
raise "unrecognized rolenames: #{extra_roles.inspect}" unless extra_roles.empty?
|
6
|
-
|
7
|
-
# max one tell per role
|
8
|
-
roles.each{ |r| tell([r]) }
|
9
10
|
end
|
10
11
|
|
11
12
|
def roles
|
12
|
-
|
13
|
+
list.map{ |s| s.role.to_sym }.uniq
|
13
14
|
end
|
14
15
|
|
15
16
|
def for(roles)
|
16
|
-
|
17
|
+
list.select{ |s| roles.include?(s.role.to_sym) }
|
17
18
|
end
|
18
19
|
|
19
|
-
def
|
20
|
-
|
20
|
+
def i_asks(roles)
|
21
|
+
list.select do |s|
|
21
22
|
s.text_value =~ /^ask/ && roles.include?(s.role.to_sym)
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
25
|
-
def
|
26
|
-
ss =
|
26
|
+
def i_tell(roles)
|
27
|
+
ss = list.select{ |s| s.text_value =~ /^tell/ && roles.include?(s.role.to_sym) }
|
27
28
|
raise "multiple assignments for role: #{role}" if ss.size > 1
|
28
29
|
ss.first
|
29
30
|
end
|
data/lib/ceml/script.rb
CHANGED
@@ -1,41 +1,100 @@
|
|
1
1
|
module CEML
|
2
2
|
module Script
|
3
|
+
extend Forwardable
|
4
|
+
attr_writer :delegate
|
5
|
+
def delegate; @delegate || CEML.delegate; end
|
3
6
|
|
4
|
-
|
5
|
-
|
7
|
+
# ===========
|
8
|
+
# = casting =
|
9
|
+
# ===========
|
10
|
+
|
11
|
+
def locations
|
12
|
+
@locations ||= (delegate.locations(self) || [])
|
6
13
|
end
|
7
14
|
|
8
|
-
def
|
9
|
-
|
15
|
+
def launchable_location
|
16
|
+
criteria = awaited_criteria.sort_by{ |c| [-c.complexity, c.min_match] }
|
17
|
+
locations.find do |l|
|
18
|
+
people_used = []
|
19
|
+
criteria.all?{ |c| folks = l[c.hash] and c.satisfied_by_group?(folks, people_used) }
|
20
|
+
end
|
10
21
|
end
|
11
22
|
|
12
|
-
|
13
|
-
|
23
|
+
# public
|
24
|
+
def post candidate
|
25
|
+
criteria = awaited_criteria.select{ |c| c =~ candidate }
|
26
|
+
criteria.each{ |c| c.list_candidate(candidate) }
|
27
|
+
not criteria.empty?
|
14
28
|
end
|
15
29
|
|
16
|
-
def
|
17
|
-
|
30
|
+
def awaited_criteria
|
31
|
+
return [] unless cast.type == :await
|
32
|
+
return cast.criteria(self)
|
18
33
|
end
|
19
34
|
|
20
|
-
|
21
|
-
|
35
|
+
|
36
|
+
# ===============
|
37
|
+
# = likelihoods =
|
38
|
+
# ===============
|
39
|
+
|
40
|
+
def color(odds)
|
41
|
+
return :red if odds < 0.1
|
42
|
+
return :yellow if odds < 0.4
|
43
|
+
return :green
|
22
44
|
end
|
23
45
|
|
24
|
-
def
|
25
|
-
return
|
26
|
-
return
|
46
|
+
def likelihood(yesprob, needed, psize)
|
47
|
+
return 1 if needed <= 0
|
48
|
+
return 0 if psize < needed
|
49
|
+
return (needed..psize).inject(0) do |memo, yes_count|
|
50
|
+
memo + begin
|
51
|
+
no_count = psize - yes_count
|
52
|
+
ways_it_could_happen = psize.choose(yes_count)
|
53
|
+
prob_of_each = (yesprob ** yes_count) * ((1 - yesprob) ** no_count)
|
54
|
+
ways_it_could_happen * prob_of_each
|
55
|
+
end
|
56
|
+
end
|
27
57
|
end
|
28
58
|
|
29
|
-
def
|
30
|
-
|
59
|
+
def availabilities(potential_count, committed_count = 0)
|
60
|
+
return {} unless script.dramatis_personae
|
61
|
+
min = script.dramatis_personae.min
|
62
|
+
needed = min - committed_count
|
63
|
+
possible = potential_count + committed_count
|
64
|
+
yesprob = 0.7 # just make this up for now
|
65
|
+
odds = likelihood(yesprob, needed, potential_count)
|
66
|
+
|
67
|
+
{
|
68
|
+
:odds => odds, :color => color(odds),
|
69
|
+
:availability_counts => {
|
70
|
+
:total => possible,
|
71
|
+
:unknown => potential_count
|
72
|
+
},
|
73
|
+
:estimated_size => yesprob * potential_count + committed_count,
|
74
|
+
:needed => min
|
75
|
+
}
|
31
76
|
end
|
32
77
|
|
33
|
-
|
34
|
-
|
78
|
+
|
79
|
+
# ========
|
80
|
+
# = cast =
|
81
|
+
# ========
|
82
|
+
|
83
|
+
DefaultDP = Struct.new :radius, :rolenames, :max, :type
|
84
|
+
|
85
|
+
def cast
|
86
|
+
return casting_statement if respond_to? :casting_statement
|
87
|
+
return DefaultDP.new nil, [:agents], 0, :nab
|
35
88
|
end
|
36
89
|
|
90
|
+
def_delegators :cast, :radius
|
91
|
+
def_delegator :cast, :max, :max_to_invite
|
92
|
+
def_delegator :cast, :rolenames, :roles
|
93
|
+
alias_method :dramatis_personae, :cast
|
37
94
|
alias_method :dp, :dramatis_personae
|
38
95
|
|
96
|
+
# casting_statement.roles.names
|
97
|
+
|
39
98
|
def simple?
|
40
99
|
(roles - [:agents, :organizer]).empty?
|
41
100
|
end
|
@@ -44,14 +103,71 @@ module CEML
|
|
44
103
|
roles.map{ |r| r == :agent ? [:agent, :agents] : r }.flatten.concat([:both, :all, :everyone])
|
45
104
|
end
|
46
105
|
|
106
|
+
def allowed_roles
|
107
|
+
allowed_roles = [:organizer, :agents]
|
108
|
+
allowed_roles += cast.rolenames
|
109
|
+
allowed_roles.uniq
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
# ================
|
114
|
+
# = instructions =
|
115
|
+
# ================
|
116
|
+
|
117
|
+
def instructions
|
118
|
+
return super if defined?(super)
|
119
|
+
return self if Instructions === self
|
120
|
+
nil
|
121
|
+
end
|
122
|
+
|
47
123
|
def instructions_for(roles)
|
48
|
-
return []
|
124
|
+
return [] unless instructions
|
49
125
|
return instructions.for(expand_roles(roles))
|
50
126
|
end
|
51
127
|
|
52
128
|
def asks(roles)
|
53
|
-
return []
|
54
|
-
instructions.
|
129
|
+
return [] unless instructions
|
130
|
+
instructions.i_asks([*roles])
|
131
|
+
end
|
132
|
+
|
133
|
+
def tell(roles)
|
134
|
+
return unless instructions
|
135
|
+
instructions.i_tell([*roles])
|
136
|
+
end
|
137
|
+
|
138
|
+
def validate!
|
139
|
+
return unless instructions
|
140
|
+
instructions.validate_instructions!(allowed_roles)
|
141
|
+
end
|
142
|
+
|
143
|
+
def concludes_immediately?
|
144
|
+
!title and instructions.asks([:agents]).empty?
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
# =======
|
149
|
+
# = etc =
|
150
|
+
# =======
|
151
|
+
|
152
|
+
def to_hash *fields
|
153
|
+
fields.inject({}){ |h, s| x = send(s); h[s] = x if x; h }
|
154
|
+
end
|
155
|
+
|
156
|
+
def script
|
157
|
+
text_value
|
158
|
+
end
|
159
|
+
|
160
|
+
def title
|
161
|
+
if defined?(super)
|
162
|
+
super.title_value
|
163
|
+
elsif respond_to? :title_value
|
164
|
+
self.title_value
|
165
|
+
else nil
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def name
|
170
|
+
title || label
|
55
171
|
end
|
56
172
|
|
57
173
|
def params
|
@@ -60,11 +176,6 @@ module CEML
|
|
60
176
|
end
|
61
177
|
end
|
62
178
|
|
63
|
-
def tell(roles)
|
64
|
-
return nil if instructions.empty?
|
65
|
-
instructions.tell([*roles])
|
66
|
-
end
|
67
|
-
|
68
179
|
def type
|
69
180
|
return 'mission' if title
|
70
181
|
return 'unknown' if instructions.empty?
|
@@ -89,58 +200,5 @@ module CEML
|
|
89
200
|
end
|
90
201
|
end
|
91
202
|
end
|
92
|
-
|
93
|
-
def validate!
|
94
|
-
instructions.validate!(allowed_roles) unless instructions.empty?
|
95
|
-
end
|
96
|
-
|
97
|
-
def allowed_roles
|
98
|
-
allowed_roles = [:organizer, :agents]
|
99
|
-
allowed_roles += casting_statement.roles unless casting_statement.empty?
|
100
|
-
allowed_roles
|
101
|
-
end
|
102
|
-
|
103
|
-
def concludes_immediately?
|
104
|
-
!title and instructions.asks([:agents]).empty?
|
105
|
-
end
|
106
|
-
|
107
|
-
def color(odds)
|
108
|
-
return :red if odds < 0.1
|
109
|
-
return :yellow if odds < 0.4
|
110
|
-
return :green
|
111
|
-
end
|
112
|
-
|
113
|
-
def likelihood(yesprob, needed, psize)
|
114
|
-
return 1 if needed <= 0
|
115
|
-
return 0 if psize < needed
|
116
|
-
return (needed..psize).inject(0) do |memo, yes_count|
|
117
|
-
memo + begin
|
118
|
-
no_count = psize - yes_count
|
119
|
-
ways_it_could_happen = psize.choose(yes_count)
|
120
|
-
prob_of_each = (yesprob ** yes_count) * ((1 - yesprob) ** no_count)
|
121
|
-
ways_it_could_happen * prob_of_each
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
def availabilities(potential_count, committed_count = 0)
|
127
|
-
return {} unless script.dramatis_personae
|
128
|
-
min = script.dramatis_personae.min
|
129
|
-
needed = min - committed_count
|
130
|
-
possible = potential_count + committed_count
|
131
|
-
yesprob = 0.7 # just make this up for now
|
132
|
-
odds = likelihood(yesprob, needed, potential_count)
|
133
|
-
|
134
|
-
{
|
135
|
-
:odds => odds, :color => color(odds),
|
136
|
-
:availability_counts => {
|
137
|
-
:total => possible,
|
138
|
-
:unknown => potential_count
|
139
|
-
},
|
140
|
-
:estimated_size => yesprob * potential_count + committed_count,
|
141
|
-
:needed => min
|
142
|
-
}
|
143
|
-
end
|
144
|
-
|
145
203
|
end
|
146
204
|
end
|
data/lib/ceml/tt/casting.treetop
CHANGED
@@ -3,45 +3,42 @@ grammar Casting
|
|
3
3
|
include Lexer
|
4
4
|
|
5
5
|
rule casting_statement
|
6
|
-
|
6
|
+
('gather' / 'await' / 'nab') ws roles within_phrase:within_phrase? <CastingStatement>
|
7
7
|
end
|
8
8
|
|
9
|
-
rule
|
10
|
-
|
9
|
+
rule within_phrase
|
10
|
+
ws 'within' ws distance
|
11
11
|
end
|
12
12
|
|
13
|
-
rule
|
14
|
-
role
|
13
|
+
rule roles
|
14
|
+
role more:(and role)* {
|
15
|
+
def list
|
16
|
+
[role] + more.elements.map{ |e| e.role }
|
17
|
+
end
|
18
|
+
|
19
|
+
def names; list.map{ |r| r.name.to_sym }; end
|
20
|
+
def [](x); list.detect{ |r| r.name.to_sym == x }; end
|
21
|
+
def min; list.map(&:min).inject(0, &:+); end
|
22
|
+
def max; list.map(&:max).inject(0, &:+); end
|
23
|
+
}
|
15
24
|
end
|
16
25
|
|
17
|
-
rule
|
18
|
-
|
19
|
-
{
|
20
|
-
def meters
|
21
|
-
number.text_value.to_f * case distance_unit.text_value
|
22
|
-
when /^mi/; 1600; when /^k/; 1000; when /^m/; 1;
|
23
|
-
when /^f/; 0.35; when /^b/; 200; else 1; end
|
24
|
-
end
|
25
|
-
}
|
26
|
+
rule qualifier
|
27
|
+
id
|
26
28
|
end
|
27
29
|
|
28
|
-
rule
|
29
|
-
|
30
|
-
{
|
31
|
-
def name; id.text_value; end
|
32
|
-
def min; range.empty? ? 2 : range.min; end
|
33
|
-
def max; range.empty? ? 10000 : range.max; end
|
34
|
-
}
|
30
|
+
rule rolename
|
31
|
+
id
|
35
32
|
end
|
36
33
|
|
37
|
-
rule
|
38
|
-
|
39
|
-
|
40
|
-
def min;
|
41
|
-
def max
|
42
|
-
|
43
|
-
return
|
44
|
-
return
|
34
|
+
rule role
|
35
|
+
(rolename &and / range ws qualifier ws rolename / range ws rolename / qualifier ws rolename / rolename) {
|
36
|
+
def name; if respond_to? :rolename then rolename.text_value else text_value end; end
|
37
|
+
def min; if respond_to? :range then range.min else 2 end; end
|
38
|
+
def max; if respond_to? :range then range.max else 10000 end; end
|
39
|
+
def qualifiers
|
40
|
+
return [qualifier.text_value] if respond_to? :qualifier
|
41
|
+
return []
|
45
42
|
end
|
46
43
|
}
|
47
44
|
end
|
@@ -2,11 +2,7 @@ module CEML
|
|
2
2
|
grammar Instructions
|
3
3
|
include Lexer
|
4
4
|
|
5
|
-
rule
|
6
|
-
instruction+ <Instructions>
|
7
|
-
end
|
8
|
-
|
9
|
-
rule instruction
|
5
|
+
rule instruction_stmt
|
10
6
|
(ask_stmt / tell_stmt / assign_stmt) {
|
11
7
|
|
12
8
|
INTERPOLATE_REGEX = /\|(\w+)\.?(\w+)?\|/
|
@@ -31,15 +27,15 @@ grammar Instructions
|
|
31
27
|
end
|
32
28
|
|
33
29
|
rule tell_stmt
|
34
|
-
'tell' ws id ':' ws? text
|
30
|
+
'tell' ws id ':' ws? text
|
35
31
|
end
|
36
32
|
|
37
33
|
rule assign_stmt
|
38
|
-
'assign' ws id ':' ws? text
|
34
|
+
'assign' ws id ':' ws? text
|
39
35
|
end
|
40
36
|
|
41
37
|
rule ask_stmt
|
42
|
-
'ask' ws id about:(ws 're' ws varname:id)? ':' ws? text
|
38
|
+
'ask' ws id about:(ws 're' ws varname:id)? ':' ws? text
|
43
39
|
end
|
44
40
|
|
45
41
|
end
|