ceml 0.7.3 → 0.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.3
1
+ 0.7.4
data/ceml.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ceml}
8
- s.version = "0.7.3"
8
+ s.version = "0.7.4"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Joe Edelman"]
@@ -49,6 +49,7 @@ Gem::Specification.new do |s|
49
49
  "test/test_casting.rb",
50
50
  "test/test_incident.rb",
51
51
  "test/test_instructions.rb",
52
+ "test/test_release.rb",
52
53
  "test/test_scripts.rb",
53
54
  "try"
54
55
  ]
@@ -62,6 +63,7 @@ Gem::Specification.new do |s|
62
63
  "test/test_casting.rb",
63
64
  "test/test_incident.rb",
64
65
  "test/test_instructions.rb",
66
+ "test/test_release.rb",
65
67
  "test/test_scripts.rb"
66
68
  ]
67
69
 
data/lib/ceml/driver.rb CHANGED
@@ -39,16 +39,23 @@ module CEML
39
39
  SCRIPTS[script_collection_id] << script
40
40
  end
41
41
 
42
- def ping_all script_collection_id, candidate
43
- SCRIPTS[script_collection_id].each{ |s| ping script_collection_id, s.roles_to_cast, candidate }
42
+ def ping_all script_collection_id, candidate, release = false
43
+ candidate[:script_collection_id] = script_collection_id
44
+ SCRIPTS[script_collection_id].each{ |s| ping script_collection_id, s.roles_to_cast, candidate, release }
44
45
  end
45
46
 
47
+ def released_from_all script_collection_id, candidate
48
+ SCRIPTS[script_collection_id].each{ |s| release script_collection_id, s.roles_to_cast, candidate }
49
+ end
50
+
51
+
46
52
  def launch script_collection_id, roleset, *cast
47
53
  script = SCRIPTS[script_collection_id].select{ |s| s.roles_to_cast == roleset }.sort_by{ rand }.first
48
54
  unless script
49
55
  rolesets = SCRIPTS[script_collection_id].map(&:roles_to_cast)
50
56
  raise "matching roleset not found: #{roleset.inspect} in #{rolesets.inspect}"
51
57
  end
58
+ log "launching #{script.bytecode.inspect} with cast #{cast.inspect}"
52
59
  push nil, script.bytecode, *cast
53
60
  end
54
61
 
@@ -58,8 +65,7 @@ module CEML
58
65
  yield LOCATIONS["#{script_collection_id}:#{roleset.hash}"]
59
66
  end
60
67
 
61
-
62
- def ping script_collection_id, roleset, candidate
68
+ def ping script_collection_id, roleset, candidate, involvement = :sticky
63
69
  return unless roleset.any?{ |r| r.fits? candidate }
64
70
  candidate[:ts] = CEML.clock
65
71
  already_launched_with = nil
@@ -68,14 +74,15 @@ module CEML
68
74
  live_with = confluences.select{ |c| c.live_with?(candidate) }
69
75
  if not live_with.empty?
70
76
  already_launched_with = live_with.first.incident_id
71
- break
77
+ live_with.each{ |c| c.rm candidate } if involvement != :sticky
78
+ break if involvement != :released
72
79
  end
73
80
 
74
81
  locs = confluences.group_by{ |l| l.stage_with_candidate(candidate) }
75
82
  if locs[:joinable]
76
83
  log "joining..."
77
84
  first = locs[:joinable].shift
78
- first.push candidate
85
+ first.push candidate unless first.incident_id == already_launched_with
79
86
  push first.incident_id, nil, candidate # JOIN THEM
80
87
 
81
88
  elsif locs[:launchable]
@@ -105,7 +112,8 @@ module CEML
105
112
  confluences.delete_if(&:over?)
106
113
  end
107
114
 
108
- if already_launched_with
115
+ if already_launched_with and involvement == :sticky
116
+ puts "PUSHING INSTEAD"
109
117
  push already_launched_with, nil, candidate
110
118
  end
111
119
  end
@@ -152,5 +160,25 @@ module CEML
152
160
  JUST_SAID[data[:player][:id]] = what
153
161
  puts "Said #{what.inspect}"
154
162
  end
163
+
164
+ # def player_start(data, what)
165
+ # puts "STARTED #{data[:player].inspect}"
166
+ # end
167
+
168
+ def player_released(data, tag)
169
+ p = data[:player].dup
170
+ p[:tags] -= ['new']
171
+ if tag =~ /^(\w+)=/
172
+ p[:tags].delete_if{ |t| t =~ /^#{$1}=/ }
173
+ end
174
+ p[:tags] += [tag]
175
+ p.delete :pc
176
+ p.delete :roles
177
+ data[:player][:released] = true
178
+ # data[:players].delete_if{ |pl| pl[:id] == p[:id] }
179
+ puts "released: #{p.inspect} with #{tag}"
180
+ # puts "remaining players: #{data[:players].inspect}"
181
+ ping_all p[:script_collection_id], p, true
182
+ end
155
183
  end
156
184
  end
data/lib/ceml/incident.rb CHANGED
@@ -28,8 +28,12 @@ module CEML
28
28
  def run(players, &blk)
29
29
  @players = players
30
30
  @callback = blk
31
- :loop while players.any? do |@this|
32
- # puts "seq for roles: #{roles.inspect} #{seq.inspect}"
31
+ puts "playing with #{@players.map{|p|p[:id]}}"
32
+ :loop while @players.any? do |thing|
33
+ @this = thing
34
+ next if thing[:released]
35
+ puts "trying #{@this[:id]}"
36
+ puts "not yet released"
33
37
  next unless instr = seq[pc]
34
38
  instr = instr.dup
35
39
  if rolematch(instr.shift)
@@ -37,6 +41,7 @@ module CEML
37
41
  next unless send(*instr)
38
42
  cb(*instr)
39
43
  end
44
+ # next if @this[:released]
40
45
  this[:pc]+=1
41
46
  end
42
47
  @callback = @players = nil
@@ -116,7 +121,8 @@ module CEML
116
121
 
117
122
  def answered_q q
118
123
  got or return false
119
- qs_answers[q[:key]] = got
124
+ this[:last_answer] = qs_answers[q[:key]] = got
125
+ this[:last_answer_recognized] = recognized
120
126
  handled!
121
127
  true
122
128
  end
@@ -152,6 +158,23 @@ module CEML
152
158
  end
153
159
  end
154
160
 
161
+ def last_answer_match?(value)
162
+ case value
163
+ when :yes; this[:last_answer_recognized] == :yes
164
+ when :no; this[:last_answer_recognized] == :no
165
+ end
166
+ end
167
+
168
+ def expectation(type, value)
169
+ if type == :if then last_answer_match?(value) else !last_answer_match?(value) end
170
+ end
171
+
172
+ def release x
173
+ return true if x[:cond] and not expectation(*x[:cond])
174
+ cb :released, x[:tag]
175
+ false
176
+ end
177
+
155
178
  def null_assign
156
179
  say :proceed
157
180
  true
@@ -7,7 +7,7 @@ grammar Casting
7
7
  end
8
8
 
9
9
  rule modifier_phrase
10
- over_phrase / within_phrase
10
+ over_phrase / within_phrase / with_matching_phrase
11
11
  end
12
12
 
13
13
  rule over_phrase
@@ -18,6 +18,10 @@ grammar Casting
18
18
  ws 'within' ws distance
19
19
  end
20
20
 
21
+ rule with_matching_phrase
22
+ ws 'with' ws 'matching' ws thing:id
23
+ end
24
+
21
25
  rule roles
22
26
  role more:(and role)* {
23
27
  def list
@@ -3,7 +3,7 @@ grammar Instructions
3
3
  include Lexer
4
4
 
5
5
  rule basic_statement
6
- (ask_stmt / tell_stmt / assign_stmt / record_stmt / set_stmt / sync_stmt) {
6
+ (ask_stmt / tell_stmt / assign_stmt / record_stmt / set_stmt / sync_stmt / release_stmt) {
7
7
 
8
8
  def delay
9
9
  if parent.respond_to? :later and not parent.later.empty?
@@ -12,27 +12,31 @@ grammar Instructions
12
12
  end
13
13
 
14
14
  def role; id.text_value.to_sym; end
15
- def text; super.text_value; end
15
+ def text; defined?(super) && super.text_value; end
16
16
  def var
17
- return varname.text_value if cmd == :record or cmd == :set
18
- (!defined?(:about) || about.empty?) ? nil : about.varname.text_value;
17
+ return varname.text_value if cmd == :record or cmd == :set or cmd == :release
18
+ (!respond_to?(:about) || about.empty?) ? nil : about.varname.text_value;
19
19
  end
20
20
  def key; var || text; end
21
21
  def cmd; text_value.split.first.to_sym; end
22
+ def cond
23
+ (!respond_to?(:condition) || condition.empty?) ? nil : condition.value
24
+ end
22
25
 
23
26
  def bytecode
24
27
  code = []
25
28
  code.concat [[[role], :start_delay, delay],
26
29
  [[role], :complete_delay]] if delay
27
30
  code.concat case cmd
28
- when :record; [[[role], :answered_q, {:key => key}]]
29
- when :set; [[[role], :set, {:key => key, :value => text}]]
30
- when :ask; [[[role], :ask_q, {:text => text}],
31
- [[role], :answered_q, {:key => key}]]
32
- when :tell; [[[role], :send_msg, {:text => text}]]
33
- when :assign; [[[role], :assign, {:text => text}],
34
- [[role], :complete_assign, {:text => text}]]
35
- when :sync; [[[role], :sync]]
31
+ when :record; [[[role], :answered_q, {:key => key}]]
32
+ when :set; [[[role], :set, {:key => key, :value => text}]]
33
+ when :ask; [[[role], :ask_q, {:text => text}],
34
+ [[role], :answered_q, {:key => key}]]
35
+ when :tell; [[[role], :send_msg, {:text => text}]]
36
+ when :assign; [[[role], :assign, {:text => text}],
37
+ [[role], :complete_assign, {:text => text}]]
38
+ when :release; [[[role], :release, {:tag => key, :cond => cond}]]
39
+ when :sync; [[[role], :sync]]
36
40
  end
37
41
  code
38
42
  end
@@ -70,5 +74,18 @@ grammar Instructions
70
74
  rule sync_stmt
71
75
  'sync' ws id
72
76
  end
77
+
78
+ rule release_stmt
79
+ 'release' ws id ws 'as' ws varname:id condition:condition?
80
+ end
81
+
82
+ rule condition
83
+ ws type:('if' / 'else') ws thing:id {
84
+ def value
85
+ [type.text_value.to_sym, thing.text_value.to_sym]
86
+ end
87
+ }
88
+ end
89
+
73
90
  end
74
91
  end
@@ -38,7 +38,7 @@ grammar Lexer
38
38
  end
39
39
 
40
40
  rule id
41
- !(reserved_word ws) [a-zA-Z_]+
41
+ !(reserved_word ws) [a-zA-Z_] [a-zA-Z_0-9=]*
42
42
  end
43
43
 
44
44
  rule duration
data/test/helper.rb CHANGED
@@ -33,7 +33,11 @@ class Test::Unit::TestCase
33
33
  iid = CEML::Driver::INCIDENTS.keys.find do |iid|
34
34
  CEML::Driver::PLAYERS[iid].find{ |p| p[:id] == id }
35
35
  end
36
- DRIVER.post iid, :id => id, :received => str
36
+ if str == 'y'
37
+ DRIVER.post iid, :id => id, :received => str, :recognized => :yes
38
+ else
39
+ DRIVER.post iid, :id => id, :received => str
40
+ end
37
41
  end
38
42
 
39
43
  def player id, *roles
@@ -0,0 +1,106 @@
1
+ require 'ceml'
2
+ require 'test/helper'
3
+
4
+ class TestRelease < Test::Unit::TestCase
5
+
6
+ def test_release_syntax
7
+ s = CEML.parse(:script, "release all as booger")
8
+ assert l=s.bytecode.find{ |line| line[1] == :release }
9
+ assert_equal 'booger', l[2][:tag]
10
+
11
+ s = CEML.parse(:script, "release all as booger if yes")
12
+ puts s.bytecode.inspect
13
+ assert l=s.bytecode.find{ |line| line[1] == :release }
14
+ assert_equal 'booger', l[2][:tag]
15
+ assert_equal :if, l[2][:cond][0]
16
+ assert_equal :yes, l[2][:cond][1]
17
+ end
18
+
19
+ def test_release_and_catch
20
+ s1 = "await 1 new signup\nrelease signup as confused"
21
+ s2 = "await 1 confused booger\ntell booger: you're okay dude"
22
+ f = scriptfam s1, s2
23
+ play do
24
+ ping f, :id => 'sam', :tags => ['new']
25
+ told 'sam', /okay dude/
26
+ end
27
+ end
28
+
29
+ def test_conditional_release_and_catch
30
+ s1 = "await 1 new signup\nask signup re coffee: want some?\nrelease signup as confused if yes"
31
+ s2 = "await 1 confused booger\ntell booger: you're okay dude"
32
+ f = scriptfam s1, s2
33
+ play do
34
+ ping f, :id => 'sam', :tags => ['new']
35
+ asked 'sam', /want/
36
+ says 'sam', 'y'
37
+ told 'sam', /okay dude/
38
+ end
39
+ end
40
+
41
+
42
+ SAM_IAN_SIGNUP_SCRIPTS = <<XXXX
43
+ await 1 new signup
44
+ ask signup re first_name:
45
+ Thanks for signing up for Infatuated!
46
+ What's your first name?
47
+ ask signup re couple:
48
+ Do you have an Infatuated Match Card you want to use?
49
+ (These are available at the Infatuated table on the first floor.)
50
+ release signup as stage=couple if yes
51
+ ask signup re tags:
52
+ Who are you and who are you looking for tonight? (text back one: w4w, w4m, m4m, or m4w)
53
+
54
+ await stage=couple player
55
+ ask player re code:
56
+ Type in your Infatuated Match Card code now.
57
+ release player as stage=coded
58
+
59
+ await 1 stage=coded alpha and 1 stage=coded beta with matching code
60
+ release alpha as alpha
61
+ release beta as beta
62
+
63
+ await 1 w4w alpha and 1 w4w beta
64
+ release alpha as alpha
65
+ release beta as beta
66
+
67
+ await 1 w4m alpha and 1 m4w beta
68
+ release alpha as alpha
69
+ release beta as beta
70
+
71
+ await 1 m4m alpha and 1 m4m beta
72
+ release alpha as alpha
73
+ release beta as beta
74
+
75
+ await 1 m4w alpha and 1 w4m beta
76
+ release alpha as alpha
77
+ release beta as beta
78
+
79
+ await 1 alpha alpha, 1 beta beta over 5 minutes
80
+ tell both: Your date has started, |her.first_name|, |buddy.first_name|
81
+ XXXX
82
+
83
+
84
+ def test_couple
85
+ f = scriptfam *CEML.parse(:scripts, SAM_IAN_SIGNUP_SCRIPTS)
86
+ play do
87
+ ping f, :id => 'Sara', :tags => ['new']
88
+ ping f, :id => 'Jon', :tags => ['new']
89
+ asked 'Sara', /Thanks/
90
+ says 'Sara', 'Sara'
91
+ asked 'Sara', /Match Card/
92
+ says 'Sara', 'y'
93
+ asked 'Jon', /Thanks/
94
+ says 'Jon', 'Jon'
95
+ asked 'Jon', /Match Card/
96
+ says 'Jon', 'y'
97
+ asked 'Sara', /code now/
98
+ says 'Sara', 'xyzzy'
99
+ asked 'Jon', /code now/
100
+ says 'Jon', 'xyZZy '
101
+ told 'Sara', /started, Sara, Jon/
102
+ told 'Jon', /started, Jon, Sara/
103
+ end
104
+ end
105
+
106
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 7
8
- - 3
9
- version: 0.7.3
8
+ - 4
9
+ version: 0.7.4
10
10
  platform: ruby
11
11
  authors:
12
12
  - Joe Edelman
@@ -71,6 +71,7 @@ files:
71
71
  - test/test_casting.rb
72
72
  - test/test_incident.rb
73
73
  - test/test_instructions.rb
74
+ - test/test_release.rb
74
75
  - test/test_scripts.rb
75
76
  - try
76
77
  has_rdoc: true
@@ -108,4 +109,5 @@ test_files:
108
109
  - test/test_casting.rb
109
110
  - test/test_incident.rb
110
111
  - test/test_instructions.rb
112
+ - test/test_release.rb
111
113
  - test/test_scripts.rb