Class: CEML::Driver

Inherits:
Object
  • Object
show all
Defined in:
lib/ceml/driver.rb

Constant Summary collapse

PLAYERS =
{}
INCIDENTS =
{}
SCRIPTS =
Hash.new{ |h,k| h[k] = [] }
LOCATIONS =
Hash.new{ |h,k| h[k] = [] }
JUST_SAID =
{}

Instance Method Summary collapse

Instance Method Details

#add_script(script_collection_id, script) ⇒ Object



44
45
46
# File 'lib/ceml/driver.rb', line 44

def add_script script_collection_id, script
  SCRIPTS[script_collection_id] << script
end

#launch(id, script_collection_id, roleset, *cast) ⇒ Object



67
68
69
70
71
72
73
74
75
# File 'lib/ceml/driver.rb', line 67

def launch id, script_collection_id, roleset, *cast
  script = SCRIPTS[script_collection_id].select{ |s| s.roles_to_cast == roleset }.sort_by{ rand }.first
  unless script
    rolesets = SCRIPTS[script_collection_id].map(&:roles_to_cast)
    raise "matching roleset not found: #{roleset.inspect} in #{rolesets.inspect}"
  end
  log "launching #{script.bytecode.inspect} with cast #{cast.inspect}"
  push id, script.bytecode, *cast
end

#log(s) ⇒ Object



39
40
41
# File 'lib/ceml/driver.rb', line 39

def log(s)
  # puts s
end

#ping(script_collection_id, roleset, candidate, involvement = :sticky) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/ceml/driver.rb', line 83

def ping script_collection_id, roleset, candidate, involvement = :sticky
  puts "CEML: TOP PING: #{candidate.inspect}"
  return unless roleset.any?{ |r| r.fits? candidate }
  candidate[:ts] = CEML.clock
  already_launched_with = nil
  run_after = []

  puts "CEML: INSIDE PING"
  with_confluences script_collection_id, roleset do |confluences|
    live_with = confluences.select{ |c| c.live_with?(candidate) }
    if not live_with.empty?
      puts "CEML: LIVE WITH DETECTED"
      already_launched_with = live_with.first.incident_id
      live_with.each{ |c| c.rm candidate } if involvement != :sticky
      break if involvement != :released
    end

    locs = confluences.group_by{ |l| l.stage_with_candidate(candidate) }
    if locs[:joinable]
      log "joining..."
      first = locs[:joinable].shift
      first.push candidate unless first.incident_id == already_launched_with
      # JOIN THEM
      run_after << [:push, first.incident_id, nil, candidate]

    elsif locs[:launchable]
      log "launching..."
      first = locs[:launchable].shift
      first.push candidate
      cast = first.cast
      first.incident_id = gen_code
      (locs[:launchable] + (locs[:listable]||[])).each{ |l| l.rm *cast }
      # LAUNCH
      run_after << [:launch, first.incident_id, script_collection_id, roleset, *cast]

    elsif locs[:listable]
      log "listing..."
      locs[:listable].each{ |l| l.push candidate }

    else
      c = Confluence.new(roleset)
      log "start-listing..."
      if c.stage_with_candidate(candidate) == :launchable
        log "start-launching..."
        c.push candidate
        c.incident_id = gen_code
        run_after << [:launch, c.incident_id, script_collection_id, roleset, candidate]
      else
        c.push candidate
      end
      confluences << c
    end
    confluences.delete_if(&:over?)
  end

  run_after.each do |cmd|
    send(*cmd)
  end

  if already_launched_with and involvement == :sticky
    puts "PUSHING INSTEAD"
    push already_launched_with, nil, candidate
  end
end

#ping_all(script_collection_id, candidate, release = false) ⇒ Object



48
49
50
51
# File 'lib/ceml/driver.rb', line 48

def ping_all script_collection_id, candidate, release = false
  candidate[:script_collection_id] = script_collection_id
  SCRIPTS[script_collection_id].each{ |s| ping script_collection_id, s.roles_to_cast, candidate, release }
end

#player_said(data, what) ⇒ Object



186
187
188
189
# File 'lib/ceml/driver.rb', line 186

def player_said(data, what)
  JUST_SAID[data[:player][:id]] = what
  puts "Said #{what.inspect}"
end

#post(incident_id, *updated_players) ⇒ Object Also known as: run



154
155
156
# File 'lib/ceml/driver.rb', line 154

def post incident_id, *updated_players
  push incident_id, nil, *updated_players
end

#push(incident_id, script, *updated_players) ⇒ Object



148
149
150
151
152
# File 'lib/ceml/driver.rb', line 148

def push incident_id, script, *updated_players
  with_incident incident_id, script do |incident, players, |
    subpost incident, players, , *updated_players
  end
end

#release(p) ⇒ Object



57
58
59
60
61
62
63
64
65
# File 'lib/ceml/driver.rb', line 57

def release p
  p[:tags] -= ['new']
  if p[:released] =~ /^(\w+)=/
    p[:tags].delete_if{ |t| t =~ /^#{$1}=/ }
  end
  p[:tags] += [p[:released]]
  [:pc, :roles, :released].each{ |sym| p.delete(sym) }
  (p[:matchables]||={}).update (p[:qs_answers]||{})
end

#released_from_all(script_collection_id, candidate) ⇒ Object



53
54
55
# File 'lib/ceml/driver.rb', line 53

def released_from_all script_collection_id, candidate
  SCRIPTS[script_collection_id].each{ |s| release script_collection_id, s.roles_to_cast, candidate }
end

#subpost(incident, players, metadata, *updated_players) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/ceml/driver.rb', line 160

def subpost incident, players, , *updated_players
  updated_players.each do |player|
    player_id = player[:id]
    player[:roles] = Set.new([*player[:roles] || []])
    player[:roles] << :agents << :players << :both << :all << :each << :everyone
    if existing_player = players.find{ |p| p[:id] == player_id }
      existing_player[:roles] += player.delete :roles
      existing_player.update player
    else
      players << player
    end
  end
  incident.run(players) do |player, meth, what|
    meth = "player_#{meth}"
    log "[#{incident.id}] #{meth}: #{player[:id]} #{what.inspect}"
    if respond_to? meth
      .update :player => player, :players => players, :id => incident.id
      result = send(meth, , what)
      .delete :player
      .delete :players
      result
    end
  end
end

#to_bytecode(bytecode_or_script) ⇒ Object



30
31
32
33
34
35
36
37
# File 'lib/ceml/driver.rb', line 30

def to_bytecode bytecode_or_script
  case bytecode_or_script
  when String;       return CEML.parse(:script, bytecode_or_script).bytecode
  when CEML::Script; return bytecode_or_script.bytecode
  when Array;        return bytecode_or_script
  else return nil
  end
end

#with_confluences(script_collection_id, roleset) {|| ... } ⇒ Object

Yields:

  • ()


79
80
81
# File 'lib/ceml/driver.rb', line 79

def with_confluences script_collection_id, roleset
  yield LOCATIONS["#{script_collection_id}:#{roleset.hash}"]
end

#with_incident(id, script = nil, metadata = {}) {|, , metadata| ... } ⇒ Object Also known as: start

Yields:

  • (, , metadata)


14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/ceml/driver.rb', line 14

def with_incident(id, script = nil,  = {})
  id ||= rand(36**10).to_s(36)
  PLAYERS[id] ||= []
  INCIDENTS[id] ||= CEML::Incident.new to_bytecode(script), id if script
  raise "no incident #{id}" unless INCIDENTS[id]
  yield INCIDENTS[id], PLAYERS[id],  if block_given?

  PLAYERS[id].select{ |p| p[:released] }.each do |p|
    release p
    ping_all p[:script_collection_id], p
  end

  id
end