Module: Bcpm::Player
- Defined in:
- lib/bcpm/player.rb
Overview
Manages player packages.
Class Method Summary collapse
-
.ant_config(simulator_config) ⇒ Object
The contents of an Ant configuration file (build.xml) pointing to a simulator config file.
-
.checkpoint(repo_uri, repo_branch, local_name) ⇒ Object
Downloads player code from a repository for one-time use, without linking it to the repository.
-
.configure(local_path) ⇒ Object
Configures a player’s source code project.
-
.create(local_name) ⇒ Object
Creates a player from the built-in template.
-
.default_local_root ⇒ Object
The directory containing all players code.
-
.eclipse_classpath(local_path) ⇒ Object
The contents of an Eclipse .classpath for a player project.
-
.eclipse_project(local_path) ⇒ Object
The contents of an Eclipse .project file for a player project.
-
.has_suite?(local_path) ⇒ Boolean
True if a battlecode distribution is installed on the local machine.
-
.install(repo_uri, repo_branch) ⇒ Object
Clones a player code from a repository, and sets it up for development on the local machine.
-
.list ⇒ Object
All installed players.
-
.list_active ⇒ Object
All installed players who are properly hooked into the distribution.
-
.local_root ⇒ Object
The directory containing all players code.
-
.new_suite(local_path) ⇒ Object
Creates a Suite instance for running all the tests.
-
.package_path(local_path, name_override = nil, silent = false) ⇒ Object
Extracts the path to a player’s source package given their repository.
-
.player_name(repo_uri) ⇒ Object
Extracts the player name out of the git repository URI for the player’s code.
-
.reconfigure(local_name) ⇒ Object
Re-configures a player’s source code project.
-
.rename(local_path, old_name) ⇒ Object
Renames a player to match its path on the local system.
-
.run_case(case_name, live, local_name, branch = 'master') ⇒ Object
Runs a case in the test suite against a player codebase.
-
.run_suite(local_name) ⇒ Object
Runs the player’s test suite.
-
.suite_files(local_path) ⇒ Object
All the test cases in the suite of the given player.
-
.uninstall(local_name) ⇒ Object
Undoes the effects of an install or checkpoint call.
-
.uninstall_all ⇒ Object
Cleans up all the installed players.
-
.wired?(player_name) ⇒ Boolean
True if the given player name is installed and wired.
-
.write_template(local_path) ⇒ Object
Writes the built-in player template.
Class Method Details
.ant_config(simulator_config) ⇒ Object
The contents of an Ant configuration file (build.xml) pointing to a simulator config file.
268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/bcpm/player.rb', line 268 def self.ant_config(simulator_config) contents = File.read Bcpm::Dist.ant_file # Point to the distribution instead of current root. contents.gsub! 'basedir="."', 'basedir="' + Bcpm::Dist.dist_path + '"' contents.gsub! '<property name="path.base" location="."', '<property name="path.base" location="' + Bcpm::Dist.dist_path + '"' # Set VM memory. contents.gsub! /\<jvmarg\s+value\=\"\-Xmx.*\"/, "<jvmarg value=\"-Xmx#{Bcpm::Match::vm_ram}m\"" # Replace hardcoded bc.conf reference. contents.gsub! 'bc.conf', simulator_config contents end |
.checkpoint(repo_uri, repo_branch, local_name) ⇒ Object
Downloads player code from a repository for one-time use, without linking it to the repository.
Returns the path to the player on the local system, or nil if something went wrong.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/bcpm/player.rb', line 34 def self.checkpoint(repo_uri, repo_branch, local_name) old_name = player_name repo_uri local_path = File.join local_root, local_name if File.exist?(local_path) puts "Player already installed at #{local_path}!" return nil end if old_name == repo_uri return nil unless Bcpm::Git.checkpoint_local_repo(File.join(local_root, old_name), local_path) else return nil unless Bcpm::Git.checkpoint_repo(repo_uri, repo_branch, local_path) end if local_name == old_name source_path = package_path(local_path) else source_path = rename(local_path, old_name) end unless source_path puts "Repository #{repo_uri} doesn't seem to contain a player!" FileUtils.rm_rf local_path return nil end Bcpm::Dist.add_player source_path configure local_path local_path end |
.configure(local_path) ⇒ Object
Configures a player’s source code project.
155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/bcpm/player.rb', line 155 def self.configure(local_path) File.open File.join(local_path, '.project'), 'wb' do |f| f.write eclipse_project(local_path) end File.open File.join(local_path, '.classpath'), 'wb' do |f| f.write eclipse_classpath(local_path) end File.open File.join(local_path, 'build.xml'), 'wb' do |f| f.write ant_config('bc.conf') end end |
.create(local_name) ⇒ Object
Creates a player from the built-in template.
Returns the path to the player on the local system, or nil if something went wrong.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/bcpm/player.rb', line 65 def self.create(local_name) old_name = 'template' local_path = File.join local_root, local_name if File.exist?(local_path) puts "Player already installed at #{local_path}!" return nil end write_template local_path unless source_path = rename(local_path, old_name) puts "Repository #{repo_uri} doesn't seem to contain a player!" FileUtils.rm_rf local_path return nil end Bcpm::Dist.add_player source_path configure local_path local_path end |
.default_local_root ⇒ Object
The directory containing all players code.
175 176 177 178 179 180 181 182 |
# File 'lib/bcpm/player.rb', line 175 def self.default_local_root path = Dir.pwd unless File.exist?(File.join(path, '.metadata')) puts "Please chdir into your Eclipse workspace!" exit 1 end path end |
.eclipse_classpath(local_path) ⇒ Object
The contents of an Eclipse .classpath for a player project.
283 284 285 286 287 288 289 290 291 292 293 294 295 |
# File 'lib/bcpm/player.rb', line 283 def self.eclipse_classpath(local_path) jar_path = File.join Bcpm::Dist.dist_path, 'lib', 'battlecode-server.jar' <<END_CONFIG <?xml version="1.0" encoding="UTF-8"?> <classpath> <classpathentry kind="src" path="src"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry kind="lib" path="#{jar_path}"/> <classpathentry kind="output" path="bin"/> </classpath> END_CONFIG end |
.eclipse_project(local_path) ⇒ Object
The contents of an Eclipse .project file for a player project.
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
# File 'lib/bcpm/player.rb', line 298 def self.eclipse_project(local_path) project_name = File.basename local_path <<END_CONFIG <?xml version="1.0" encoding="UTF-8"?> <projectDescription> <name>#{project_name}</name> <comment></comment> <projects> </projects> <buildSpec> <buildCommand> <name>org.eclipse.jdt.core.javabuilder</name> <arguments> </arguments> </buildCommand> </buildSpec> <natures> <nature>org.eclipse.jdt.core.javanature</nature> </natures> </projectDescription> END_CONFIG end |
.has_suite?(local_path) ⇒ Boolean
True if a battlecode distribution is installed on the local machine.
150 151 152 |
# File 'lib/bcpm/player.rb', line 150 def self.has_suite?(local_path) File.exist? File.join(local_path, 'suite') end |
.install(repo_uri, repo_branch) ⇒ Object
Clones a player code from a repository, and sets it up for development on the local machine.
Returns the player’s name, or nil if something went wrong.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/bcpm/player.rb', line 11 def self.install(repo_uri, repo_branch) name = player_name repo_uri local_path = File.join local_root, name if File.exist?(local_path) puts "Player already installed at #{local_path}!" return nil end return nil unless Bcpm::Git.clone_repo(repo_uri, repo_branch, local_path) unless source_path = package_path(local_path) puts "Repository #{repo_uri} doesn't seem to contain a player!" FileUtils.rm_rf local_path return nil end Bcpm::Dist.add_player source_path configure local_path name end |
.list ⇒ Object
All installed players.
This might contain false positives.
187 188 189 190 191 |
# File 'lib/bcpm/player.rb', line 187 def self.list Dir.glob(File.join(local_root, '*', '.project')).map do |project_file| File.basename File.dirname(project_file) end end |
.list_active ⇒ Object
All installed players who are properly hooked into the distribution.
These players can be used into tests and simulations.
196 197 198 |
# File 'lib/bcpm/player.rb', line 196 def self.list_active list.select { |player_name| wired? player_name } end |
.local_root ⇒ Object
The directory containing all players code.
170 171 172 |
# File 'lib/bcpm/player.rb', line 170 def self.local_root Bcpm::Config[:player_root] ||= default_local_root end |
.new_suite(local_path) ⇒ Object
Creates a Suite instance for running all the tests.
138 139 140 141 142 |
# File 'lib/bcpm/player.rb', line 138 def self.new_suite(local_path) suite = Bcpm::Tests::Suite.new local_path suite.add_cases suite_files(local_path) suite end |
.package_path(local_path, name_override = nil, silent = false) ⇒ Object
Extracts the path to a player’s source package given their repository.
Args:
local_path:: path to the player's git repository on the local machine
name_override:: (optional) supplies the player name; if not set, the name is extracted from
the path, by convention
silent:: if set, won't output errors that help the user debug the problem
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/bcpm/player.rb', line 243 def self.package_path(local_path, name_override = nil, silent = false) # All the packages should be in the 'src' directory. source_dir = File.join local_path, 'src' unless File.exist? source_dir puts "Missing src directory" unless silent return nil end # Ignore maintainance files/folder such as .gitignore / .svn. package_dirs = Dir.glob(File.join(source_dir, '*')). reject { |path| File.basename(path)[0, 1] == '.' } unless package_dirs.length == 1 puts "src directory doesn't contain exactly one package directory!" unless silent return nil end path = package_dirs.first unless (name_override || File.basename(local_path)) == File.basename(path) puts "The package in the src directory doesn't match the player name!" unless silent return nil end path end |
.player_name(repo_uri) ⇒ Object
Extracts the player name out of the git repository URI for the player’s code.
213 214 215 216 217 |
# File 'lib/bcpm/player.rb', line 213 def self.player_name(repo_uri) name = File.basename(repo_uri) name = name[0...-4] if name[-4, 4] == '.git' name end |
.reconfigure(local_name) ⇒ Object
Re-configures a player’s source code project.
97 98 99 100 101 102 103 104 105 106 |
# File 'lib/bcpm/player.rb', line 97 def self.reconfigure(local_name) local_path = File.join local_root, local_name unless source_path = package_path(local_path) puts "Directory #{local_path} doesn't seem to contain a player!" FileUtils.rm_rf local_path return nil end Bcpm::Dist.add_player source_path configure local_path end |
.rename(local_path, old_name) ⇒ Object
Renames a player to match its path on the local system.
Returns the path to the player’s source package.
222 223 224 225 226 227 228 229 230 231 232 233 234 |
# File 'lib/bcpm/player.rb', line 222 def self.rename(local_path, old_name) new_name = File.basename local_path return nil unless old_source_dir = package_path(local_path, old_name) new_source_dir = File.join File.dirname(old_source_dir), new_name FileUtils.mv old_source_dir, new_source_dir Dir.glob(File.join(new_source_dir, '**', '*.java')).each do |file| contents = File.read file contents.gsub! /(^|[^A-Za-z0-9_.])#{old_name}([^A-Za-z0-9_]|$)/, "\\1#{new_name}\\2" File.open(file, 'wb') { |f| f.write contents } end new_source_dir end |
.run_case(case_name, live, local_name, branch = 'master') ⇒ Object
Runs a case in the test suite against a player codebase.
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/bcpm/player.rb', line 119 def self.run_case(case_name, live, local_name, branch = 'master') local_path = File.join local_root, local_name unless has_suite? local_path puts "No test suite found at #{local_path}!" return false end case_file = case_name + '.rb' files = suite_files(local_path).select { |file| File.basename(file) == case_file } unless files.length == 1 puts "Ambiguous case name! It matched #{files.count} cases.\n#{files.join("\n")}\n" return false end suite = Bcpm::Tests::Suite.new(local_path) suite.add_cases files suite.run live end |
.run_suite(local_name) ⇒ Object
Runs the player’s test suite.
109 110 111 112 113 114 115 116 |
# File 'lib/bcpm/player.rb', line 109 def self.run_suite(local_name) local_path = File.join local_root, local_name unless has_suite? local_path puts "No test suite found at #{local_path}!" return false end new_suite(local_path).run false end |
.suite_files(local_path) ⇒ Object
All the test cases in the suite of the given player.
145 146 147 |
# File 'lib/bcpm/player.rb', line 145 def self.suite_files(local_path) Dir.glob File.join(local_path, 'suite', '**', '*.rb') end |
.uninstall(local_name) ⇒ Object
Undoes the effects of an install or checkpoint call.
Returns true for success, or false if something went wrong.
87 88 89 90 91 92 93 94 |
# File 'lib/bcpm/player.rb', line 87 def self.uninstall(local_name) local_path = File.join local_root, local_name source_path = package_path local_path Bcpm::Dist.remove_player source_path if source_path return false unless File.exist? local_path FileUtils.rm_rf local_path true end |
.uninstall_all ⇒ Object
Cleans up all the installed players.
208 209 210 |
# File 'lib/bcpm/player.rb', line 208 def self.uninstall_all list_good.each { |player_name| uninstall player_name } end |
.wired?(player_name) ⇒ Boolean
True if the given player name is installed and wired.
201 202 203 204 205 |
# File 'lib/bcpm/player.rb', line 201 def self.wired?(player_name) local_path = File.join local_root, player_name source_path = package_path local_path, nil, true (source_path && Bcpm::Dist.contains_player?(source_path)) ? true : false end |
.write_template(local_path) ⇒ Object
Writes the built-in player template.
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 |
# File 'lib/bcpm/player.rb', line 323 def self.write_template(local_path) src_path = File.join local_path, 'src', 'template' FileUtils.mkdir_p src_path File.open File.join(src_path, 'RobotPlayer.java'), 'wb' do |f| f.write <<END_SOURCE package template; import battlecode.common.RobotController; public class RobotPlayer implements Runnable { public static RobotController rc; public RobotPlayer(RobotController controller) { rc = controller; } public void run() { while (true) { rc.yield(); } } } END_SOURCE end src_path = File.join local_path, 'src', 'template', 'test', 'players' FileUtils.mkdir_p src_path File.open File.join(src_path, 'RobotPlayer.java'), 'wb' do |f| f.write <<END_SOURCE package template.test.players; import battlecode.common.RobotController; public class RobotPlayer implements Runnable { public static RobotController rc; public RobotPlayer(RobotController controller) { rc = controller; } public void run() { while (true) { rc.yield(); } } } END_SOURCE end suite_path = File.join local_path, 'suite' FileUtils.mkdir_p suite_path File.open File.join(suite_path, 'win_vs_yield.rb'), 'wb' do |f| f.write <<END_SOURCE vs 'yield' suite_map '#{Bcpm::Dist.maps.first}' replace_class 'RobotPlayer', 'test.players.RobotPlayer' match do it 'must win in any way' do should_win end end END_SOURCE end maps_path = File.join suite_path, 'maps' FileUtils.mkdir_p maps_path Bcpm::Dist.copy_map Bcpm::Dist.maps.first, maps_path File.open File.join(local_path, '.gitignore'), 'wb' do |f| f.write <<END_SOURCE # Auto-generated by bcpm. build.xml .classpath .project # Build output. bin # Temporary files. ~* .DS_Store END_SOURCE end end |