ceml 0.8.0 → 0.9.0

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.8.0
1
+ 0.9.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ceml}
8
- s.version = "0.8.0"
8
+ s.version = "0.9.0"
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"]
12
- s.date = %q{2011-05-27}
12
+ s.date = %q{2011-06-07}
13
13
  s.description = %q{a language for coordinating real world events}
14
14
  s.email = %q{joe@citizenlogistics.com}
15
15
  s.extra_rdoc_files = [
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
24
24
  "Rakefile",
25
25
  "VERSION",
26
26
  "ceml.gemspec",
27
+ "cemltest",
27
28
  "editors/CEML.tmbundle/Syntaxes/ceml.tmLanguage",
28
29
  "editors/CEML.tmbundle/info.plist",
29
30
  "examples/breakfast-exchange.ceml",
@@ -48,10 +49,11 @@ Gem::Specification.new do |s|
48
49
  "lib/ceml/lang/tt/scripts.rb",
49
50
  "lib/ceml/lang/tt/scripts.treetop",
50
51
  "lib/ceml/models.rb",
51
- "lib/ceml/models/audition.rb",
52
52
  "lib/ceml/models/bundle.rb",
53
53
  "lib/ceml/models/cast.rb",
54
54
  "lib/ceml/models/castable.rb",
55
+ "lib/ceml/models/casting_pool.rb",
56
+ "lib/ceml/models/casting_tokens.rb",
55
57
  "lib/ceml/models/incident.rb",
56
58
  "lib/ceml/models/incident_model.rb",
57
59
  "lib/ceml/models/incident_role_slot.rb",
@@ -59,6 +61,7 @@ Gem::Specification.new do |s|
59
61
  "lib/ceml/models/queue.rb",
60
62
  "lib/ceml/models/waiting_room.rb",
61
63
  "lib/ceml/processor.rb",
64
+ "lib/ceml/recognizer.rb",
62
65
  "test/askchain.ceml",
63
66
  "test/compliment.ceml",
64
67
  "test/dialogues/accept.ceml",
@@ -0,0 +1,15 @@
1
+ #! /usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'ceml'
4
+
5
+ f = ARGV.shift
6
+ name = File.basename(f, '.ceml')
7
+ err, log = CEML.test(File.new(f).read)
8
+ if !err
9
+ puts "PASS cemltest #{name}. logged #{log.split("\n").size} lines"
10
+ elsif RuntimeError === err
11
+ puts log
12
+ raise "ERROR with cemltest #{name}: #{err.message}!"
13
+ else
14
+ raise err
15
+ end
@@ -2,17 +2,40 @@ require 'forwardable'
2
2
 
3
3
  require 'ceml/models'
4
4
  require 'ceml/lang'
5
+ require 'ceml/recognizer'
5
6
  require 'ceml/processor'
7
+ require 'stringio'
6
8
 
7
9
  module CEML
8
10
  extend self
9
11
  @extra_seconds = 0
12
+ @log_io = STDERR
13
+ attr_reader :tells
10
14
  def clock; Time.now.utc.to_i + @extra_seconds; end
11
15
  def incr_clock(s); @extra_seconds += s; end
12
16
  def dur(n, unit)
13
17
  n * case unit
14
18
  when /^h/; 60*60; when /^mi/; 60; else 1; end
15
19
  end
20
+
21
+ def capture_log
22
+ log = ""
23
+ err = nil
24
+ prev_io, @log_io = @log_io, StringIO.new(log)
25
+ yield
26
+ rescue Exception => err
27
+ @log_io.puts "\nERROR: #{err}\n\n\n"
28
+ ensure
29
+ @log_io = prev_io
30
+ return err, log
31
+ end
32
+
33
+ def log lvl, msg
34
+ if lvl > 1
35
+ msg = " #{msg}"
36
+ end
37
+ @log_io.puts msg
38
+ end
16
39
  end
17
40
 
18
41
  module CEML
@@ -39,4 +62,46 @@ module CEML
39
62
  end
40
63
  result
41
64
  end
65
+
66
+ def test test, p = CEML::Processor
67
+ scripts, test = test.split("\n---\n")
68
+ s = CEML.parse(:scripts, scripts).map(&:castable)
69
+ bundle_id = gen_code # s.hash.to_s
70
+ @tells = Hash.new{ |h,k| h[k] = [] }
71
+ p.set_bundle(bundle_id, s)
72
+ p.reset_bundle(bundle_id)
73
+ pl = Set.new
74
+ CEML.capture_log do
75
+ test.each_line do |line|
76
+ line = line.strip
77
+ next if line =~ /^#/ or line =~ /^\s*$/
78
+ CEML.log 1, "#{line}"
79
+ case line
80
+ when /^(\w+) *< *(.*)$/
81
+ player_id, msg = $1, $2
82
+ heard = tells[player_id].shift
83
+ next if msg.empty? and !heard
84
+ raise "Expected silence from #{player_id}, got #{heard}" if msg.empty? and heard
85
+ raise "Expected #{player_id} < #{msg}, got silence" if !msg.empty? and !heard
86
+ heard = (heard||={})[:msg] || (heard||={})[:q] || ''
87
+ raise "Expected #{player_id} < #{msg}, got #{heard}" unless heard =~ /#{msg}/
88
+ next
89
+ when /^(\w+) *> *(.*)$/
90
+ player_id, msg = $1, $2
91
+ player = {:id => player_id, :received => msg }
92
+ if !pl.include?(player_id)
93
+ player[:tags] = ['new']
94
+ p.reset_player(bundle_id, player_id)
95
+ pl << player_id
96
+ end
97
+ player[:recognized] = CEML::Recognizer.recognize(msg)
98
+ p.ping(bundle_id, player)
99
+ when /^\((\d+)\s*(\w+)\)$/
100
+ CEML.incr_clock CEML.dur($1.to_i, $2)
101
+ p.run_latest
102
+ end
103
+ p.run
104
+ end
105
+ end
106
+ end
42
107
  end
@@ -6,7 +6,8 @@ Redis::Objects.redis = Redis.new
6
6
  require 'ceml/models/cast'
7
7
  require 'ceml/models/castable'
8
8
  require 'ceml/models/incident'
9
- require 'ceml/models/audition'
9
+ require 'ceml/models/casting_pool'
10
+ require 'ceml/models/casting_tokens'
10
11
  require 'ceml/models/incident_model'
11
12
  require 'ceml/models/incident_role_slot'
12
13
  require 'ceml/models/player'
@@ -3,31 +3,68 @@ module CEML
3
3
  include Redis::Objects
4
4
  value :castables, :marshal => true
5
5
 
6
- def clear_from_all_rooms(player_id)
7
- Audition.new(player_id).clear_from_all_rooms
8
- end
6
+ # =============
7
+ # = castables =
8
+ # =============
9
9
 
10
10
  def find_castables(stanza_name = nil)
11
11
  return castables.value unless stanza_name
12
12
  return [castables.value.find{ |c| c.stanza_name == stanza_name }]
13
13
  end
14
14
 
15
+
16
+ # =================
17
+ # = waiting rooms =
18
+ # =================
19
+
20
+ def clear_from_all_rooms(player_id)
21
+ CastingPool.destroy_everywhere(id, player_id)
22
+ end
23
+
15
24
  def all_rooms
16
25
  find_castables.map(&:all_rooms).flatten.uniq
17
26
  end
18
27
 
19
28
  def reset
20
- all_rooms.each(&:clear)
29
+ # puts "TOTAL RESET"
30
+ CastingTokens.destroy_all(id)
31
+ all_rooms.each{ |room| room.waiting_incident_roles.clear }
21
32
  end
22
33
 
23
34
  def rooms_for_player(player, stanza_name = nil)
24
- roomnames = find_castables(stanza_name).map{ |c| c.waiting_rooms_for_player(player, stanza_name) }.flatten.uniq
25
- roomnames.map{ |r| WaitingRoom.new(r) }
35
+ find_castables(stanza_name).map{ |c| c.waiting_rooms_for_player(player, stanza_name) }.flatten.uniq
36
+ end
37
+
38
+ def register_in_rooms(player, stanza_name = nil)
39
+ room_ids = rooms_for_player(player, stanza_name)
40
+ CastingPool.new(room_ids).post(id, player[:id])
26
41
  end
27
42
 
43
+ def reset_player(player_id)
44
+ CastingPool.destroy_everywhere(id, player_id)
45
+ Player.new(player_id).reset
46
+ end
47
+
48
+ def grab_cast?(player, castable, seeded_p)
49
+ room_ids = castable.hot_waiting_rooms_given_player(player, seeded_p)
50
+ # CEML.log 1, "Checking cast for #{castable.stanza_name}: #{room_ids.inspect}"
51
+ casting_pool = CastingPool.new(room_ids)
52
+ loop do
53
+ hot_players = casting_pool.hot_players + [player]
54
+ # CEML.log 1, "Hot players: #{hot_players.inspect}"
55
+ return nil unless cast = castable.cast_from(hot_players)
56
+ return cast if casting_pool.claim(cast.player_ids - [player[:id]])
57
+ sleep 0.02
58
+ end
59
+ end
60
+
61
+ # ==============================
62
+ # = incident joining/launching =
63
+ # ==============================
64
+
28
65
  def join_running_incident?(player, stanza_name = nil)
29
- rooms_for_player(player, stanza_name).each do |room|
30
- if incident_id = room.audition_for_incidents(player)
66
+ rooms_for_player(player, stanza_name).each do |room_id|
67
+ if incident_id = WaitingRoom.new(room_id).audition_for_incidents(player)
31
68
  return incident_id
32
69
  end
33
70
  end
@@ -37,7 +74,8 @@ module CEML
37
74
  def cast_player?(player, stanza_name = nil)
38
75
  incident_id = gen_code
39
76
  find_castables(stanza_name).each do |castable|
40
- if cast = castable.cast_player?(incident_id, player, stanza_name)
77
+ if cast = grab_cast?(player, castable, seeded=stanza_name)
78
+ castable.advertise_roles(incident_id, cast)
41
79
  i = IncidentModel.new(incident_id)
42
80
  i.bytecode.value = castable.bytecode
43
81
  i.add_castings(cast.castings)
@@ -48,16 +86,7 @@ module CEML
48
86
  end
49
87
 
50
88
  def absorb?(player, stanza_name = nil)
51
- x = join_running_incident?(player, stanza_name)
52
- puts "X1: #{x.inspect}"
53
- return x if x
54
- x = cast_player?(player, stanza_name)
55
- puts "X2: #{x.inspect}"
56
- x
57
- end
58
-
59
- def register_in_rooms(player, stanza_name = nil)
60
- Audition.new("#{player[:id]}").list_in_rooms(rooms_for_player(player, stanza_name)) ##{gen_code}:
89
+ join_running_incident?(player, stanza_name) or cast_player?(player, stanza_name)
61
90
  end
62
91
 
63
92
  end
@@ -102,6 +102,7 @@ module CEML
102
102
 
103
103
  class Tagspec < Struct.new :with, :without
104
104
  def =~(c)
105
+ return false if (c[:tags]||[]).include?('new') and not with.include?('new')
105
106
  with.all?{ |t| (c[:tags]||[]).include?(t) } and without.all?{ |t| !(c[:tags]||[]).include?(t) }
106
107
  end
107
108
  end
@@ -1,30 +1,12 @@
1
1
  module CEML
2
- class Castable < Struct.new :type, :stanza_name, :matching, :radius, :timewindow, :roles, :bytecode
2
+ class Castable < Struct.new :type, :stanza_name, :matching, :radius, :timewindow, :roles, :bytecode, :bundle_id
3
3
 
4
- def cast_player?(incident_id, player, seeded=false)
5
- room_ids = hot_waiting_rooms_given_player(player, seeded)
6
- hotties = Audition.from_rooms(room_ids)
7
- # puts "hotties are... #{hotties.inspect} from rooms #{room_ids.inspect}"
8
- hot_players = hotties.keys.map{ |id| Player.new(id).data.value } + [player]
9
- # puts "casting from #{hot_players.inspect}"
10
- if cast = cast_from(hot_players)
11
- puts "...cast with cast #{cast.player_ids.inspect}"
12
- audition_ids = (cast.player_ids & hotties.keys).map{ |id| hotties[id] }
13
- puts "consuming #{audition_ids.inspect}"
14
- if Audition.consume(audition_ids, room_ids)
15
- # post audition signs in waiting rooms for remaining parts
16
- with_open_roles(cast) do |idx, role, count|
17
- waiting_rooms_to_watch(role, cast).each do |room|
18
- room.list_job(incident_id, idx, role.name, count)
19
- end
20
- end
21
- return cast
22
- else
23
- sleep 0.02
24
- return cast_player?(incident_id, player)
4
+ def advertise_roles(incident_id, cast)
5
+ with_open_roles(cast) do |idx, role, count|
6
+ waiting_rooms_to_watch(role, cast).each do |room|
7
+ room.list_job(incident_id, idx, role.name, count)
25
8
  end
26
9
  end
27
- return
28
10
  end
29
11
 
30
12
  def waiting_rooms_for_player(player, seeded=false)
@@ -37,8 +19,8 @@ module CEML
37
19
 
38
20
  def hot_waiting_rooms_given_player(player, seeded=false)
39
21
  rooms = waiting_rooms_for_player(player, seeded)
40
- roles.each{ |r| rooms.concat(["#{stanza_name}:#{r.name}", *r.tagspec.with]) }
41
- rooms << "#{stanza_name}:*"
22
+ roles.each{ |r| rooms.concat(["#{bundle_id}:#{stanza_name}:#{r.name}", *r.tagspec.with]) }
23
+ rooms << "#{bundle_id}:#{stanza_name}:*"
42
24
  # rooms << 'generic'
43
25
  rooms.uniq
44
26
  end
@@ -47,8 +29,8 @@ module CEML
47
29
  # skip for now: radius, timewindow, matching, general
48
30
  result = []
49
31
  if stanza_name
50
- result << "#{stanza_name}:#{role.name}"
51
- result << "#{stanza_name}:*"
32
+ result << "#{bundle_id}:#{stanza_name}:#{role.name}"
33
+ result << "#{bundle_id}:#{stanza_name}:*"
52
34
  end
53
35
  if !role.tagspec.with.empty?
54
36
  result.concat role.tagspec.with
@@ -0,0 +1,26 @@
1
+ module CEML
2
+ class CastingPool < Struct.new :room_ids
3
+ def self.destroy_everywhere(bundle_id, player_id)
4
+ CastingTokens.destroy([player_id])
5
+ end
6
+
7
+ def player_ids
8
+ tokens = CastingTokens.all_tokens(room_ids)
9
+ @tokens_by_player_id = tokens.inject({}){ |m,o| m[o]=o; m }
10
+ @tokens_by_player_id.keys
11
+ end
12
+
13
+ def hot_players
14
+ player_ids.map{ |id| Player.new(id).data.value }
15
+ end
16
+
17
+ def claim(player_ids)
18
+ tokens = @tokens_by_player_id.values_at(*player_ids)
19
+ CastingTokens.collect(tokens)
20
+ end
21
+
22
+ def post(bundle_id, player_id)
23
+ CastingTokens.post(bundle_id, player_id, room_ids)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,51 @@
1
+ module CEML
2
+ class Audition < Struct.new(:id)
3
+ include Redis::Objects
4
+ set :rooms
5
+ end
6
+
7
+ module CastingTokens
8
+ def self.post(bundle_id, token, room_ids)
9
+ room_ids << bundle_id
10
+ room_ids.each do |room_id|
11
+ Audition.new(token).rooms << room_id
12
+ WaitingRoom.new(room_id).waiting_auditions << token
13
+ end
14
+ end
15
+
16
+ def self.all_tokens(room_ids)
17
+ rooms = room_ids.map{ |r| WaitingRoom.new(r) }
18
+ rooms.map{ |r| r.waiting_auditions.members }.flatten.uniq
19
+ end
20
+
21
+ def self.destroy_all(bundle_id)
22
+ all = WaitingRoom.new(bundle_id).waiting_auditions.members
23
+ # puts "DESTROYING tokens: #{all.inspect}"
24
+ destroy(all)
25
+ end
26
+
27
+ def self.destroy(tokens)
28
+ roomsets = tokens.map{ |id| Audition.new(id).rooms }
29
+ rooms = roomsets.map(&:members).flatten.uniq
30
+ # puts "Consuming ids #{ids.inspect} from rooms #{rooms.inspect}"
31
+ # TODO: install new redis and re-enable watchlist
32
+ # redis.watch(*roomsets.map(&:key))
33
+ # redis.multi do
34
+ # rooms = roomsets.first.union(roomsets[1,-1]) || []
35
+ rooms.product(tokens).each do |r, id|
36
+ # puts "DELETING #{id} from room #{r}"
37
+ WaitingRoom.new(r).waiting_auditions.delete(id)
38
+ end
39
+ roomsets.map(&:clear)
40
+ # end
41
+ true
42
+ end
43
+
44
+ # this one should collect none unless all can be collected
45
+ # using multi/exec
46
+ def self.collect(tokens)
47
+ destroy(tokens)
48
+ end
49
+
50
+ end
51
+ end
@@ -31,13 +31,14 @@ module CEML
31
31
  guyroles = roles.to_a - [:everyone, :players, :them, :all, :either, :each, :agents, :both]
32
32
  instr ||= []
33
33
 
34
- puts "[#{id}] #{p[:id]}(#{guyroles}) ##{pc} #{state} -- #{instr[1]}/#{instr[0]} -- #{instr[2].inspect}"
34
+ # CEML.log 3, "#{p[:id]}: #{state} -- #{instr[1]}/#{instr[0]} -- #{instr[2].inspect} -- #{id}##{pc}(#{guyroles})"
35
35
  end
36
36
 
37
-
38
37
  def run(players, &blk)
39
38
  @players = players
40
39
  @callback = blk
40
+ was_blocked = {}
41
+ # CEML.log 1, "running players: #{players.inspect}"
41
42
 
42
43
  loop do
43
44
  players = @players
@@ -45,24 +46,25 @@ module CEML
45
46
  players.each do |p|
46
47
  @this = p
47
48
  instr = seq[pc]
49
+ # log "running: #{pc}: #{instr.inspect}"
48
50
  unless instr = seq[pc]
49
- log 'off schedule'
50
51
  @players.delete(p)
51
- cb :released
52
52
  next
53
53
  end
54
54
  instr = instr.dup
55
55
  rolespec = instr.shift
56
56
  if not rolematch(rolespec)
57
- log "skipping[#{rolespec}]"
57
+ # log "skipping[#{rolespec}]"
58
58
  this[:pc]+=1
59
59
  advanced = true
60
60
  else
61
61
  instr << role_info if instr.first == :start #tmp hack
62
62
  if send(*instr)
63
63
  log 'completed'
64
+ was_blocked[p] = false
64
65
  else
65
- log 'blocked'
66
+ log 'blocked' unless was_blocked[p]
67
+ was_blocked[p] = true
66
68
  next
67
69
  end
68
70
  cb(*instr)
@@ -20,13 +20,13 @@ module CEML
20
20
  folks.each do |player|
21
21
  Player.new(player[:id]).touch(id)
22
22
  player_roles[player[:id]] = [rolename.to_sym]
23
- puts "ADDED(#{id}) #{player[:id]} = #{rolename.to_sym}"
23
+ CEML.log 3, "#{player[:id]}: added as #{rolename.to_sym} (#{id})"
24
24
  end
25
25
  end
26
26
  end
27
27
 
28
28
  def release(player_id)
29
- puts "Releasing player #{player_id} from incident #{id}"
29
+ CEML.log 3, "#{player_id}: releasing from incident #{id}"
30
30
  Player.new(player_id).clear_incident(id)
31
31
  player_roles.delete(player_id)
32
32
  end
@@ -51,17 +51,17 @@ module CEML
51
51
  metadata, player_data = *data.value
52
52
  metadata ||= { :id => id }
53
53
  player_data ||= {}
54
- puts "[#{id}] Player data loaded: #{player_data.inspect}"
55
54
  players = []
56
55
 
57
- puts "[#{id}] Player roles: #{player_roles.all.inspect}"
56
+ CEML.log 3, ">>> #{player_roles.all.inspect} (#{id})"
58
57
  player_roles.each do |player_id, roles|
59
- puts "#{id}: #{player_id.inspect} => #{roles.inspect}, #{player_data[player_id].inspect}"
58
+ CEML.log 3, "#{player_id}: casted as #{roles.inspect} -- #{id}: #{player_data[player_id].inspect}"
60
59
  player = { :id => player_id, :roles => Set.new(roles) }
61
60
  player[:roles] << :agents << :players << :both << :all << :each << :everyone << :them << :either
62
61
  player.merge! player_data[player_id] if player_data[player_id]
63
62
  p = Player.new(player_id)
64
63
  stored_player = p.data.value
64
+ PLAYER_THREAD_FIELDS.each{ |x| stored_player.delete x }
65
65
  msg = p.message.value
66
66
  player.merge! msg if msg
67
67
  player.merge! stored_player if stored_player
@@ -86,8 +86,9 @@ module CEML
86
86
  players.each do |p|
87
87
  Player.new(p[:id]).message.value = p.like(:received, :recognized, :situation)
88
88
  player_data[p[:id]] = p.like *PLAYER_THREAD_FIELDS
89
+ # PLAYER_THREAD_FIELDS.each{ |x| p.delete x }
89
90
  end
90
- puts "Player data saving: #{player_data.inspect}"
91
+ # CEML.log 1, "Player data saving: #{player_data.inspect}"
91
92
  data.value = [metadata, player_data]
92
93
 
93
94
  if next_run = players.map{ |p| p[:continue_at] }.compact.min
@@ -6,17 +6,20 @@ module CEML
6
6
  value :message, :marshal => true
7
7
  sorted_set :current_incidents
8
8
 
9
- def touch(incident_id)
10
- current_incidents[incident_id] = Time.now.to_i
11
- end
12
-
13
9
  def reset
14
- Audition.new(id).clear_from_all_rooms
15
10
  data.clear
16
11
  message.clear
17
12
  current_incidents.clear
18
13
  end
19
14
 
15
+ # =============
16
+ # = incidents =
17
+ # =============
18
+
19
+ def touch(incident_id)
20
+ current_incidents[incident_id] = Time.now.to_i
21
+ end
22
+
20
23
  def top_incident_id
21
24
  current_incidents.last
22
25
  end
@@ -31,6 +34,11 @@ module CEML
31
34
  current_incidents.delete(id)
32
35
  end
33
36
 
37
+
38
+ # ========
39
+ # = data =
40
+ # ========
41
+
34
42
  def self.update bundle_id, player, cb_obj, &blk
35
43
  player[:bundle_id] = player[:squad_id] = bundle_id
36
44
  new(player[:id].to_s).update player, cb_obj, &blk
@@ -69,7 +77,7 @@ module CEML
69
77
  new_message, player = split(player)
70
78
  merge_new_player_data(player)
71
79
  cmd = new_message[:recognized]
72
- if cmd and cb_obj.recognize_override(cmd, new_message, player, self)
80
+ if cmd and cb_obj and cb_obj.recognize_override(cmd, new_message, player, self)
73
81
  message.delete
74
82
  else
75
83
  message.value = new_message
@@ -5,18 +5,11 @@ module CEML
5
5
  set :waiting_auditions
6
6
  set :waiting_incident_roles
7
7
 
8
- def clear
9
- waiting_auditions.each do |audition_id|
10
- Audition.new(audition_id).clear_from_all_rooms(id)
11
- end
12
- waiting_incident_roles.clear
13
- end
14
-
15
8
  def audition_for_incidents(player)
16
- # puts "auditioning #{player[:id]} for incidents in room #{id}"
17
- waiting_incident_roles.members.each do |key|
9
+ reorder = waiting_incident_roles.members.sort_by{ |irs| irs.split(':')[1] }
10
+ reorder.each do |key|
18
11
  incident_id, idx, role, count = *key.split(':')
19
- # puts "checking against #{incident_id}: #{role}"
12
+ CEML.log 3, "#{player[:id]}: auditioning against #{incident_id}: #{role}"
20
13
  count = count.to_i
21
14
  role_slot = IncidentRoleSlot.new(incident_id, role, count)
22
15
  next unless role_slot.reserve_spot!
@@ -30,11 +23,6 @@ module CEML
30
23
  def list_job(incident_id, idx, rolename, count)
31
24
  waiting_incident_roles << [incident_id, idx, rolename, count].join(':')
32
25
  end
33
-
34
- def add(audition_id)
35
- puts "adding #{audition_id} to waiting room #{id.inspect}"
36
- waiting_auditions << audition_id
37
- end
38
26
  end
39
27
 
40
28
  end
@@ -15,6 +15,7 @@ module CEML
15
15
 
16
16
  def set_bundle(id, castables)
17
17
  # log "set_bundle(): #{id}, #{castables.inspect}"
18
+ castables.each{ |c| c.bundle_id = id }
18
19
  Bundle.new(id).castables = castables
19
20
  end
20
21
 
@@ -62,7 +63,7 @@ module CEML
62
63
  end
63
64
 
64
65
  def reset_player(bundle_id, player_id)
65
- Player.new(player_id).reset
66
+ Bundle.new(bundle_id).reset_player(player_id)
66
67
  end
67
68
 
68
69
  # =============
@@ -70,9 +71,10 @@ module CEML
70
71
  # =============
71
72
 
72
73
  def simple_audition(bundle_id, player)
73
- log "audition(): #{bundle_id}, #{player[:id]}"
74
+ # log "audition(): #{bundle_id}, #{player[:id]}"
74
75
  b = Bundle.new(bundle_id)
75
- b.clear_from_all_rooms(player)
76
+ b.clear_from_all_rooms(player[:id])
77
+
76
78
  if incident_id = b.absorb?(player)
77
79
  IncidentModel.new(incident_id).run(self)
78
80
  return true
@@ -82,13 +84,20 @@ module CEML
82
84
  end
83
85
 
84
86
  def seed(bundle_id, stanza_name, player)
85
- log "seed(): #{bundle_id}, #{stanza_name}, #{player[:id]}"
87
+ # log "seed(): #{bundle_id}, #{stanza_name}, #{player[:id]}"
88
+ player[:tags].delete('new')
89
+ Player.new(player[:id]).merge_new_player_data(player)
90
+
91
+ # CEML.log 1, "UPDATED"
92
+
86
93
  b = Bundle.new(bundle_id)
87
94
  if incident_id = b.absorb?(player, stanza_name)
88
95
  IncidentModel.new(incident_id).run(self)
89
- return true
96
+ true
97
+ else
98
+ b.register_in_rooms(player, stanza_name)
99
+ false
90
100
  end
91
- b.register_in_rooms(player, stanza_name)
92
101
  end
93
102
 
94
103
  # =============
@@ -107,16 +116,16 @@ module CEML
107
116
  if incident
108
117
  incident.release(player_obj.id)
109
118
  unlatch(player[:squad_id], player[:id], incident.id)
110
- player_obj.reset
119
+ reset_player(player[:squad_id], player[:id])
111
120
  tell(player[:squad_id], player[:id], :message, :msg => 'aborted')
112
121
  else
113
- player_obj.reset
122
+ reset_player(player[:squad_id], player[:id])
114
123
  tell(player[:squad_id], player[:id], :message, :msg => 'nothing to abort from')
115
124
  end
116
125
  end
117
126
 
118
127
  def log(s)
119
- puts s
128
+ CEML.log 1, s
120
129
  end
121
130
 
122
131
  def player_said(data, what)
@@ -127,11 +136,8 @@ module CEML
127
136
  #no op
128
137
  end
129
138
 
130
- JUST_SAID = {}
131
139
  def tell(sqid, player_id, key, meta)
132
- JUST_SAID[player_id] ||= []
133
- JUST_SAID[player_id] << meta.merge(:key => key)
134
- # puts "Said #{key} #{meta.inspect}"
140
+ CEML.tells[player_id] << meta.merge(:key => key) if CEML.tells
135
141
  end
136
142
 
137
143
  def player_answered_q(data, what)
@@ -142,8 +148,8 @@ module CEML
142
148
  def player_seeded(data, what)
143
149
  p = data[:player].dup
144
150
  p.delete(:roles)
145
- p[:seeded] = "#{what[:target]}:#{what[:role]}"
146
- puts "SEEDED #{p[:id]} AS #{what[:target]}:#{what[:role]}"
151
+ p[:seeded] = "#{p[:bundle_id]}:#{what[:target]}:#{what[:role]}"
152
+ CEML.log 3, "#{p[:id]}: seeded as #{p[:seeded]}"
147
153
 
148
154
  self.class.seed(p[:bundle_id], what[:target], p)
149
155
  end
@@ -0,0 +1,9 @@
1
+ module CEML
2
+ class Recognizer
3
+ def self.recognize msg
4
+ return :yes if msg == 'y' || msg =~ /^yes/i
5
+ return :abort if msg == 'abort'
6
+ return :done if msg =~ /^done/i || msg == 'd'
7
+ end
8
+ end
9
+ end
@@ -81,41 +81,43 @@ D < Please text
81
81
  D > done
82
82
  D <
83
83
 
84
- // K > Kiley
85
- // K < Welcome
86
- // K < You wanna
87
- // K > Yes
88
- // K < Awesome!
89
- // (20s)
90
- // K < If you want to opt out
91
- //
92
- // P > Paul
93
- // P < Welcome
94
- // P < You wanna
95
- // P > Yes
96
- // P < Awesome!
97
- // (20s)
98
- // P < If you want to opt out
99
- //
100
- // D < Amazing work
101
- // D > Yes
102
- // D < new challenge
103
- // D > Wave and smile at three strangers on the street
104
- // D < Thanks for playing
105
- // K < Another player has issued
106
- // K > Yes
107
- // K < Please text
108
- // K > done
109
- // K <
110
- //
111
- // # (challenge_loop2)
112
- // # K < Amazing work
113
- // # K > Yes
114
- // # K < new challenge
115
- // # K > Wave and smile at three strangers on the street
116
- // # K < Thanks for playing
117
- // # P < Another player has issued
118
- // # P > Yes
119
- // # P < Please text
120
- // # P > done
121
- // # P <
84
+ K > Kiley
85
+
86
+ P > Paul
87
+ P < Welcome
88
+ P < You wanna
89
+ P > Yes
90
+
91
+ # P < Awesome!
92
+ # (20s)
93
+ # P < If you want to opt out
94
+ #
95
+ # K < Welcome
96
+ # K < You wanna
97
+ # K > Yes
98
+ # K < Awesome!
99
+ # (20s)
100
+ # K < If you want to opt out
101
+ #
102
+ # D < Amazing work
103
+ # D > Yes
104
+ # D < new challenge
105
+ # D > Wave and smile at three strangers on the street
106
+ # D < Thanks for playing
107
+ # K < Another player has issued
108
+ # K > Yes
109
+ # K < Please text
110
+ # K > done
111
+ # K <
112
+ #
113
+ # (challenge_loop2)
114
+ # K < Amazing work
115
+ # K > Yes
116
+ # K < new challenge
117
+ # K > Wave and smile at three strangers on the street
118
+ # K < Thanks for playing
119
+ # P < Another player has issued
120
+ # P > Yes
121
+ # P < Please text
122
+ # P > done
123
+ # P <
@@ -18,7 +18,7 @@ class Test::Unit::TestCase
18
18
  end
19
19
  if script
20
20
  @iid = gen_code
21
- puts "launching w. bytecode #{script.bytecode.inspect}"
21
+ # puts "launching w. bytecode #{script.bytecode.inspect}"
22
22
  CEML::Processor.launch(@iid, script.bytecode)
23
23
  CEML::Processor.run
24
24
  end
@@ -40,7 +40,7 @@ class Test::Unit::TestCase
40
40
  player = {:id => id.to_s, :received => str}
41
41
  player[:recognized] = :yes if str.downcase == 'y' || str.downcase == 'yes'
42
42
  player[:recognized] = :abort if str == 'abort'
43
- puts "SAYING(#{id}): #{str}"
43
+ # puts "SAYING(#{id}): #{str}"
44
44
  CEML::Processor.ping(nil, player)
45
45
  CEML::Processor.run
46
46
  end
@@ -8,51 +8,20 @@ class TestCemlTests < Test::Unit::TestCase
8
8
  CEML::Queue.new.calls.clear
9
9
  end
10
10
 
11
- def test_cemltests
12
- Dir["test/dialogues/*.ceml"].each do |f|
13
- name = File.basename(f, '.ceml')
14
- test = File.new(f).read
15
- scripts, test = test.split("\n---\n")
16
-
17
- puts "Running cemltest #{name}..."
18
-
19
- s = CEML.parse(:scripts, scripts).map(&:castable)
20
- bundle_id = s.hash.to_s
21
- CEML::Processor.set_bundle(bundle_id, s)
22
- CEML::Processor.reset_bundle(bundle_id)
23
- pl = Set.new
24
- play do
25
- test.each_line do |line|
26
- puts ">>>> #{line}"
27
- case line.strip
28
- when /^(\w+) *< *(.*)$/
29
- if $2.empty?
30
- silent $1
31
- else
32
- told $1, /#{$2}/
33
- end
34
- when /^(\w+) *> *(.*)$/
35
- player_id, msg = $1, $2
36
- player = {:id => player_id, :received => msg }
37
- if !pl.include?(player_id)
38
- player[:tags] = ['new']
39
- pl << player_id
40
- end
41
- player[:recognized] = :yes if msg == 'y' || msg =~ /^yes/i
42
- player[:recognized] = :abort if msg == 'abort'
43
- player[:recognized] = :done if msg =~ /^done/i || msg == 'd'
44
- CEML::Processor.ping(bundle_id, player)
45
- CEML::Processor.run
46
- when /^\((\d+)\s*(\w+)\)$/
47
- CEML.incr_clock CEML.dur($1.to_i, $2)
48
- CEML::Processor.run_latest
49
- CEML::Processor.run
50
- when /^#/
51
- else "Skipping line #{line}..."
52
- end
53
- end
54
- end
11
+ def run_cemltest f
12
+ name = File.basename(f, '.ceml')
13
+ err, log = CEML.test(File.new(f).read)
14
+ if !err
15
+ puts "PASS cemltest #{name}. logged #{log.split("\n").size} lines"
16
+ elsif RuntimeError === err
17
+ puts log
18
+ raise "ERROR with cemltest #{name}: #{err.message}!"
19
+ else
20
+ raise err
55
21
  end
56
22
  end
57
23
 
24
+ def test_cemltests
25
+ Dir["test/dialogues/*.ceml"].each{ |f| run_cemltest(f) }
26
+ end
58
27
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ceml
3
3
  version: !ruby/object:Gem::Version
4
- hash: 63
4
+ hash: 59
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 8
8
+ - 9
9
9
  - 0
10
- version: 0.8.0
10
+ version: 0.9.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Joe Edelman
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-27 00:00:00 -07:00
18
+ date: 2011-06-07 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -49,6 +49,7 @@ files:
49
49
  - Rakefile
50
50
  - VERSION
51
51
  - ceml.gemspec
52
+ - cemltest
52
53
  - editors/CEML.tmbundle/Syntaxes/ceml.tmLanguage
53
54
  - editors/CEML.tmbundle/info.plist
54
55
  - examples/breakfast-exchange.ceml
@@ -73,10 +74,11 @@ files:
73
74
  - lib/ceml/lang/tt/scripts.rb
74
75
  - lib/ceml/lang/tt/scripts.treetop
75
76
  - lib/ceml/models.rb
76
- - lib/ceml/models/audition.rb
77
77
  - lib/ceml/models/bundle.rb
78
78
  - lib/ceml/models/cast.rb
79
79
  - lib/ceml/models/castable.rb
80
+ - lib/ceml/models/casting_pool.rb
81
+ - lib/ceml/models/casting_tokens.rb
80
82
  - lib/ceml/models/incident.rb
81
83
  - lib/ceml/models/incident_model.rb
82
84
  - lib/ceml/models/incident_role_slot.rb
@@ -84,6 +86,7 @@ files:
84
86
  - lib/ceml/models/queue.rb
85
87
  - lib/ceml/models/waiting_room.rb
86
88
  - lib/ceml/processor.rb
89
+ - lib/ceml/recognizer.rb
87
90
  - test/askchain.ceml
88
91
  - test/compliment.ceml
89
92
  - test/dialogues/accept.ceml
@@ -1,65 +0,0 @@
1
- module CEML
2
-
3
- class Audition < Struct.new(:id) # "#{code}:#{player_id}"
4
- include Redis::Objects
5
- set :rooms
6
-
7
- def list_in_rooms(da_rooms)
8
- # p "Listing in rooms #{da_rooms.map(&:id)}"
9
- da_rooms.each{ |room| self.rooms << room.id; room.add(id) }
10
- end
11
-
12
- def clear_from_all_rooms(*extra_rooms)
13
- rooms_to_clear = rooms.members + extra_rooms
14
- redis.multi do
15
- rooms_to_clear.each do |r|
16
- WaitingRoom.new(r).waiting_auditions.delete(id)
17
- end
18
- redis.del rooms.key
19
- end
20
- end
21
-
22
- def self.consume(ids, extra_rooms = [])
23
- roomsets = ids.map{ |id| Audition.new(id).rooms }
24
- rooms = (roomsets.map(&:members) + extra_rooms).flatten.uniq
25
- # puts "Consuming ids #{ids.inspect} from rooms #{rooms.inspect}"
26
- # TODO: install new redis and re-enable watchlist
27
- # redis.watch(*roomsets.map(&:key))
28
- # redis.multi do
29
- # rooms = roomsets.first.union(roomsets[1,-1]) || []
30
- rooms.each do |r|
31
- # puts "PROCESSING ROOM #{r.key}"
32
- ids.each do |id|
33
- # puts "DELETING #{id} from room #{r}"
34
- WaitingRoom.new(r).waiting_auditions.delete(id)
35
- end
36
- end
37
- roomsets.map(&:clear)
38
- # end
39
- true
40
- end
41
-
42
- def self.from_rooms(room_ids)
43
- players = {}
44
- rooms = room_ids.map{ |r| WaitingRoom.new(r) }
45
- auditions = rooms.map{ |r| r.waiting_auditions.members }.flatten
46
-
47
- # clear old style
48
- auditions.each do |a|
49
- next unless a =~ /:/
50
- Audition.new(a).rooms.clear
51
- rooms.each{ |r| r.waiting_auditions.delete(a) }
52
- end
53
-
54
- puts "Auditions found: #{auditions.inspect}"
55
- auditions.each do |audition|
56
- # next if audition =~ /:/
57
- # code, player_id = audition.split(':')
58
- player_id = audition
59
- players[player_id] ||= audition
60
- end
61
- players
62
- end
63
- end
64
-
65
- end