ceml 0.8.0 → 0.9.0

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