ceml 0.7.3 → 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
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