roby 0.8.0 → 3.0.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.
Files changed (644) hide show
  1. checksums.yaml +7 -0
  2. data/.deep-cover.rb +3 -0
  3. data/.gitattributes +1 -0
  4. data/.gitignore +24 -0
  5. data/.simplecov +10 -0
  6. data/.travis.yml +17 -0
  7. data/.yardopts +4 -0
  8. data/Gemfile +15 -0
  9. data/README.md +11 -0
  10. data/Rakefile +47 -177
  11. data/benchmark/{alloc_misc.rb → attic/alloc_misc.rb} +2 -2
  12. data/benchmark/{discovery_latency.rb → attic/discovery_latency.rb} +19 -19
  13. data/benchmark/{garbage_collection.rb → attic/garbage_collection.rb} +9 -9
  14. data/benchmark/{genom.rb → attic/genom.rb} +0 -0
  15. data/benchmark/attic/transactions.rb +62 -0
  16. data/benchmark/plan_basic_operations.rb +28 -0
  17. data/benchmark/relations/graph.rb +63 -0
  18. data/benchmark/ruby/identity.rb +18 -0
  19. data/benchmark/ruby/set_intersect_vs_hash_merge.rb +39 -0
  20. data/benchmark/ruby/yield_vs_block.rb +35 -0
  21. data/benchmark/run +5 -0
  22. data/benchmark/synthetic_plan_modifications_with_transactions.rb +79 -0
  23. data/benchmark/transactions.rb +99 -51
  24. data/bin/roby +38 -197
  25. data/bin/roby-display +14 -0
  26. data/bin/roby-log +3 -176
  27. data/doc/guide/{src → attic}/abstraction/achieve_with.page +1 -1
  28. data/doc/guide/{src → attic}/abstraction/forwarding.page +1 -1
  29. data/doc/guide/{src → attic}/abstraction/hierarchy.page +1 -1
  30. data/doc/guide/{src → attic}/abstraction/index.page +1 -1
  31. data/doc/guide/{src → attic}/abstraction/task_models.page +1 -1
  32. data/doc/guide/{overview.rdoc → attic/cycle/api_overview.rdoc} +6 -1
  33. data/doc/guide/{src → attic}/cycle/cycle-overview.png +0 -0
  34. data/doc/guide/{src → attic}/cycle/cycle-overview.svg +0 -0
  35. data/doc/guide/attic/cycle/error_handling.page +98 -0
  36. data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.png +0 -0
  37. data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.svg +0 -0
  38. data/doc/guide/{src/cycle/error_handling.page → attic/cycle/error_sources.page} +46 -89
  39. data/doc/guide/{src → attic}/cycle/garbage_collection.page +1 -1
  40. data/doc/guide/{src → attic}/cycle/index.page +1 -1
  41. data/doc/guide/{src → attic}/cycle/propagation.page +11 -1
  42. data/doc/guide/{src → attic}/cycle/propagation_diamond.png +0 -0
  43. data/doc/guide/{src → attic}/cycle/propagation_diamond.svg +0 -0
  44. data/doc/guide/attic/plans/building_plans.page +89 -0
  45. data/doc/guide/attic/plans/code.page +192 -0
  46. data/doc/guide/{src/basics → attic/plans}/events.page +3 -4
  47. data/doc/guide/attic/plans/index.page +7 -0
  48. data/doc/guide/{plan_modifications.rdoc → attic/plans/plan_modifications.rdoc} +5 -3
  49. data/doc/guide/{src/basics → attic/plans}/plan_objects.page +2 -1
  50. data/doc/guide/attic/plans/querying_plans.page +5 -0
  51. data/doc/guide/{src/basics → attic/plans}/tasks.page +20 -20
  52. data/doc/guide/config.yaml +7 -4
  53. data/doc/guide/ext/extended_menu.rb +29 -0
  54. data/doc/guide/ext/init.rb +6 -0
  55. data/doc/guide/ext/rdoc_links.rb +7 -6
  56. data/doc/guide/src/advanced_concepts/history.page +5 -0
  57. data/doc/guide/src/advanced_concepts/index.page +11 -0
  58. data/doc/guide/src/advanced_concepts/recognizing_patterns.page +83 -0
  59. data/doc/guide/src/advanced_concepts/scheduling.page +87 -0
  60. data/doc/guide/src/advanced_concepts/transactions.page +5 -0
  61. data/doc/guide/src/advanced_concepts/unreachability.page +42 -0
  62. data/doc/guide/src/base.template +96 -0
  63. data/doc/guide/src/basics_shell_header.txt +5 -7
  64. data/doc/guide/src/building/action_coordination.page +96 -0
  65. data/doc/guide/src/building/actions.page +124 -0
  66. data/doc/guide/src/building/file_layout.page +71 -0
  67. data/doc/guide/src/building/index.page +50 -0
  68. data/doc/guide/src/building/patterns.page +86 -0
  69. data/doc/guide/src/building/patterns_forwarding.png +0 -0
  70. data/doc/guide/src/building/patterns_forwarding.svg +277 -0
  71. data/doc/guide/src/building/runtime.page +95 -0
  72. data/doc/guide/src/building/task_models.page +94 -0
  73. data/doc/guide/src/building/tasks.page +284 -0
  74. data/doc/guide/src/concepts/error_handling.page +100 -0
  75. data/doc/guide/src/concepts/exception_propagation.png +0 -0
  76. data/doc/guide/src/concepts/exception_propagation.svg +445 -0
  77. data/doc/guide/src/concepts/execution.page +85 -0
  78. data/doc/guide/src/concepts/execution.png +0 -0
  79. data/doc/guide/src/concepts/execution.svg +573 -0
  80. data/doc/guide/src/concepts/execution_cycle.png +0 -0
  81. data/doc/guide/src/concepts/garbage_collection.page +57 -0
  82. data/doc/guide/src/concepts/index.page +27 -0
  83. data/doc/guide/src/concepts/plans.page +101 -0
  84. data/doc/guide/src/concepts/policy.page +31 -0
  85. data/doc/guide/src/concepts/reactor.page +61 -0
  86. data/doc/guide/src/concepts/simple_plan_example.png +0 -0
  87. data/doc/guide/src/concepts/simple_plan_example.svg +376 -0
  88. data/doc/guide/src/default.template +9 -74
  89. data/doc/guide/src/event_relations/forward.page +71 -0
  90. data/doc/guide/src/event_relations/index.page +12 -0
  91. data/doc/guide/src/event_relations/scheduling_constraints.page +43 -0
  92. data/doc/guide/src/event_relations/signal.page +55 -0
  93. data/doc/guide/src/event_relations/temporal_constraints.page +77 -0
  94. data/doc/guide/src/htmldoc.metainfo +21 -8
  95. data/doc/guide/src/index.page +8 -3
  96. data/doc/guide/src/{introduction/install.page → installation/index.page} +37 -25
  97. data/doc/guide/src/installation/publications.page +14 -0
  98. data/doc/guide/src/{introduction → installation}/videos.page +14 -7
  99. data/doc/guide/src/interacting/index.page +16 -0
  100. data/doc/guide/src/interacting/run.page +33 -0
  101. data/doc/guide/src/interacting/shell.page +95 -0
  102. data/doc/guide/src/plugins/creating_plugins.page +72 -0
  103. data/doc/guide/src/plugins/index.page +27 -5
  104. data/doc/guide/src/plugins/{fault_tolerance.page → standard_plugins/fault_tolerance.page} +2 -2
  105. data/doc/guide/src/plugins/standard_plugins/index.page +11 -0
  106. data/doc/guide/src/plugins/{subsystems.page → standard_plugins/subsystems.page} +2 -2
  107. data/doc/guide/src/style_screen.css +687 -0
  108. data/doc/guide/src/task_relations/dependency.page +107 -0
  109. data/doc/guide/src/task_relations/executed_by.page +77 -0
  110. data/doc/guide/src/task_relations/index.page +12 -0
  111. data/doc/guide/src/task_relations/new_relations.page +119 -0
  112. data/doc/guide/src/task_relations/planned_by.page +46 -0
  113. data/doc/guide/src/tutorial/app.page +117 -0
  114. data/doc/guide/src/{basics → tutorial}/code_examples.page +6 -5
  115. data/doc/guide/src/{basics → tutorial}/dry.page +15 -15
  116. data/doc/guide/src/{basics → tutorial}/errors.page +43 -68
  117. data/doc/guide/src/tutorial/events.page +195 -0
  118. data/doc/guide/src/{basics → tutorial}/hierarchy.page +53 -52
  119. data/doc/guide/src/tutorial/index.page +13 -0
  120. data/doc/guide/src/tutorial/log_replay/goForward_1.png +0 -0
  121. data/doc/guide/src/tutorial/log_replay/goForward_2.png +0 -0
  122. data/doc/guide/src/tutorial/log_replay/goForward_3.png +0 -0
  123. data/doc/guide/src/{basics → tutorial}/log_replay/goForward_4.png +0 -0
  124. data/doc/guide/src/tutorial/log_replay/goForward_5.png +0 -0
  125. data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_1.png +0 -0
  126. data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_2.png +0 -0
  127. data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_3.png +0 -0
  128. data/doc/guide/src/tutorial/log_replay/moveto_code_error.png +0 -0
  129. data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_1.png +0 -0
  130. data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_2.png +0 -0
  131. data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_3.png +0 -0
  132. data/doc/guide/src/tutorial/log_replay/plan_repair_4.png +0 -0
  133. data/doc/guide/src/tutorial/log_replay/roby_log_main_window.png +0 -0
  134. data/doc/guide/src/{basics → tutorial}/log_replay/roby_log_relation_window.png +0 -0
  135. data/doc/guide/src/{basics → tutorial}/log_replay/roby_replay_event_representation.png +0 -0
  136. data/doc/guide/src/tutorial/relations_display.page +153 -0
  137. data/doc/guide/src/{basics → tutorial}/roby_cycle_overview.png +0 -0
  138. data/doc/guide/src/tutorial/shell.page +121 -0
  139. data/doc/guide/src/{basics → tutorial}/summary.page +1 -1
  140. data/doc/guide/src/tutorial/tasks.page +374 -0
  141. data/lib/roby.rb +102 -47
  142. data/lib/roby/actions.rb +17 -0
  143. data/lib/roby/actions/action.rb +80 -0
  144. data/lib/roby/actions/interface.rb +45 -0
  145. data/lib/roby/actions/library.rb +23 -0
  146. data/lib/roby/actions/models/action.rb +224 -0
  147. data/lib/roby/actions/models/coordination_action.rb +58 -0
  148. data/lib/roby/actions/models/interface.rb +22 -0
  149. data/lib/roby/actions/models/interface_base.rb +294 -0
  150. data/lib/roby/actions/models/library.rb +12 -0
  151. data/lib/roby/actions/models/method_action.rb +90 -0
  152. data/lib/roby/actions/task.rb +114 -0
  153. data/lib/roby/and_generator.rb +125 -0
  154. data/lib/roby/app.rb +2795 -829
  155. data/lib/roby/app/autotest_console_reporter.rb +138 -0
  156. data/lib/roby/app/base.rb +21 -0
  157. data/lib/roby/app/cucumber.rb +2 -0
  158. data/lib/roby/app/cucumber/controller.rb +439 -0
  159. data/lib/roby/app/cucumber/helpers.rb +280 -0
  160. data/lib/roby/app/cucumber/world.rb +32 -0
  161. data/lib/roby/app/debug.rb +136 -0
  162. data/lib/roby/app/gen.rb +2 -0
  163. data/lib/roby/app/rake.rb +178 -38
  164. data/lib/roby/app/robot_config.rb +9 -0
  165. data/lib/roby/app/robot_names.rb +115 -0
  166. data/lib/roby/app/run.rb +3 -2
  167. data/lib/roby/app/scripts.rb +72 -0
  168. data/lib/roby/app/scripts/autotest.rb +173 -0
  169. data/lib/roby/app/scripts/display.rb +2 -0
  170. data/lib/roby/app/scripts/restart.rb +52 -0
  171. data/lib/roby/app/scripts/results.rb +17 -8
  172. data/lib/roby/app/scripts/run.rb +155 -24
  173. data/lib/roby/app/scripts/shell.rb +147 -62
  174. data/lib/roby/app/scripts/test.rb +107 -22
  175. data/lib/roby/app/test_reporter.rb +74 -0
  176. data/lib/roby/app/test_server.rb +159 -0
  177. data/lib/roby/app/vagrant.rb +47 -0
  178. data/lib/roby/backports.rb +16 -0
  179. data/lib/roby/cli/display.rb +190 -0
  180. data/lib/roby/cli/exceptions.rb +17 -0
  181. data/lib/roby/cli/gen/actions/class.rb +5 -0
  182. data/lib/roby/cli/gen/actions/test.rb +6 -0
  183. data/lib/roby/cli/gen/app/.yardopts +6 -0
  184. data/lib/roby/cli/gen/app/README.md +28 -0
  185. data/lib/roby/cli/gen/app/Rakefile +15 -0
  186. data/{app → lib/roby/cli/gen/app}/config/app.yml +29 -39
  187. data/lib/roby/cli/gen/app/models/.gitattributes +1 -0
  188. data/{app → lib/roby/cli/gen/app/scripts}/controllers/.gitattributes +0 -0
  189. data/{app/data/.gitattributes → lib/roby/cli/gen/app/test/.gitignore} +0 -0
  190. data/lib/roby/cli/gen/class/class.rb +6 -0
  191. data/lib/roby/cli/gen/class/test.rb +7 -0
  192. data/lib/roby/cli/gen/helpers.rb +203 -0
  193. data/lib/roby/cli/gen/module/module.rb +5 -0
  194. data/lib/roby/cli/gen/module/test.rb +6 -0
  195. data/lib/roby/cli/gen/roby_app/config/init.rb +17 -0
  196. data/lib/roby/cli/gen/roby_app/config/robots/robot.rb +40 -0
  197. data/lib/roby/cli/gen/task/class.rb +44 -0
  198. data/lib/roby/cli/gen/task/test.rb +6 -0
  199. data/lib/roby/cli/gen_main.rb +120 -0
  200. data/lib/roby/cli/log.rb +276 -0
  201. data/lib/roby/cli/log/flamegraph.html +499 -0
  202. data/lib/roby/cli/log/flamegraph_renderer.rb +88 -0
  203. data/lib/roby/cli/main.rb +153 -0
  204. data/lib/roby/coordination.rb +60 -0
  205. data/lib/roby/coordination/action_script.rb +25 -0
  206. data/lib/roby/coordination/action_state_machine.rb +125 -0
  207. data/lib/roby/coordination/actions.rb +106 -0
  208. data/lib/roby/coordination/base.rb +145 -0
  209. data/lib/roby/coordination/calculus.rb +40 -0
  210. data/lib/roby/coordination/child.rb +28 -0
  211. data/lib/roby/coordination/event.rb +29 -0
  212. data/lib/roby/coordination/fault_handler.rb +25 -0
  213. data/lib/roby/coordination/fault_handling_task.rb +13 -0
  214. data/lib/roby/coordination/fault_response_table.rb +110 -0
  215. data/lib/roby/coordination/models/action_script.rb +64 -0
  216. data/lib/roby/coordination/models/action_state_machine.rb +224 -0
  217. data/lib/roby/coordination/models/actions.rb +191 -0
  218. data/lib/roby/coordination/models/arguments.rb +55 -0
  219. data/lib/roby/coordination/models/base.rb +176 -0
  220. data/lib/roby/coordination/models/capture.rb +86 -0
  221. data/lib/roby/coordination/models/child.rb +35 -0
  222. data/lib/roby/coordination/models/event.rb +41 -0
  223. data/lib/roby/coordination/models/exceptions.rb +42 -0
  224. data/lib/roby/coordination/models/fault_handler.rb +219 -0
  225. data/lib/roby/coordination/models/fault_response_table.rb +77 -0
  226. data/lib/roby/coordination/models/root.rb +22 -0
  227. data/lib/roby/coordination/models/script.rb +283 -0
  228. data/lib/roby/coordination/models/task.rb +184 -0
  229. data/lib/roby/coordination/models/task_from_action.rb +50 -0
  230. data/lib/roby/coordination/models/task_from_as_plan.rb +33 -0
  231. data/lib/roby/coordination/models/task_from_instanciation_object.rb +31 -0
  232. data/lib/roby/coordination/models/task_from_variable.rb +27 -0
  233. data/lib/roby/coordination/models/task_with_dependencies.rb +48 -0
  234. data/lib/roby/coordination/models/variable.rb +32 -0
  235. data/lib/roby/coordination/script.rb +200 -0
  236. data/lib/roby/coordination/script_instruction.rb +12 -0
  237. data/lib/roby/coordination/task.rb +45 -0
  238. data/lib/roby/coordination/task_base.rb +69 -0
  239. data/lib/roby/coordination/task_script.rb +293 -0
  240. data/lib/roby/coordination/task_state_machine.rb +308 -0
  241. data/lib/roby/decision_control.rb +33 -21
  242. data/lib/roby/distributed_object.rb +76 -0
  243. data/lib/roby/droby.rb +17 -0
  244. data/lib/roby/droby/droby_id.rb +6 -0
  245. data/lib/roby/droby/enable.rb +153 -0
  246. data/lib/roby/droby/event_logger.rb +189 -0
  247. data/lib/roby/droby/event_logging.rb +57 -0
  248. data/lib/roby/droby/exceptions.rb +14 -0
  249. data/lib/roby/droby/identifiable.rb +22 -0
  250. data/lib/roby/droby/logfile.rb +141 -0
  251. data/lib/roby/droby/logfile/client.rb +176 -0
  252. data/lib/roby/droby/logfile/file_format.md +97 -0
  253. data/lib/roby/droby/logfile/index.rb +117 -0
  254. data/lib/roby/droby/logfile/reader.rb +139 -0
  255. data/lib/roby/droby/logfile/server.rb +199 -0
  256. data/lib/roby/droby/logfile/writer.rb +114 -0
  257. data/lib/roby/droby/marshal.rb +264 -0
  258. data/lib/roby/droby/marshallable.rb +12 -0
  259. data/lib/roby/droby/null_event_logger.rb +25 -0
  260. data/lib/roby/droby/object_manager.rb +205 -0
  261. data/lib/roby/droby/peer_id.rb +6 -0
  262. data/lib/roby/droby/plan_rebuilder.rb +373 -0
  263. data/lib/roby/droby/rebuilt_plan.rb +160 -0
  264. data/lib/roby/droby/remote_droby_id.rb +6 -0
  265. data/lib/roby/droby/timepoints.rb +205 -0
  266. data/lib/roby/droby/timepoints_ctf.metadata.erb +101 -0
  267. data/lib/roby/droby/timepoints_ctf.rb +125 -0
  268. data/lib/roby/droby/v5.rb +14 -0
  269. data/lib/roby/droby/v5/builtin.rb +120 -0
  270. data/lib/roby/droby/v5/droby_class.rb +45 -0
  271. data/lib/roby/droby/v5/droby_constant.rb +81 -0
  272. data/lib/roby/droby/v5/droby_dump.rb +1026 -0
  273. data/lib/roby/droby/v5/droby_id.rb +44 -0
  274. data/lib/roby/droby/v5/droby_model.rb +82 -0
  275. data/lib/roby/droby/v5/peer_id.rb +10 -0
  276. data/lib/roby/droby/v5/remote_droby_id.rb +42 -0
  277. data/lib/roby/event.rb +79 -957
  278. data/lib/roby/event_constraints.rb +835 -0
  279. data/lib/roby/event_generator.rb +1047 -0
  280. data/lib/roby/event_structure/causal_link.rb +6 -0
  281. data/lib/roby/event_structure/forwarding.rb +6 -0
  282. data/lib/roby/event_structure/precedence.rb +7 -0
  283. data/lib/roby/event_structure/signal.rb +8 -0
  284. data/lib/roby/event_structure/temporal_constraints.rb +640 -0
  285. data/lib/roby/exceptions.rb +446 -152
  286. data/lib/roby/executable_plan.rb +549 -0
  287. data/lib/roby/execution_engine.rb +1997 -950
  288. data/lib/roby/filter_generator.rb +26 -0
  289. data/lib/roby/gui/chronicle_view.rb +225 -0
  290. data/lib/roby/gui/chronicle_widget.rb +925 -0
  291. data/lib/roby/gui/dot_id.rb +11 -0
  292. data/lib/roby/gui/exception_view.rb +44 -0
  293. data/lib/roby/gui/log_display.rb +273 -0
  294. data/lib/roby/gui/model_views.rb +2 -0
  295. data/lib/roby/gui/model_views/action_interface.rb +53 -0
  296. data/lib/roby/gui/model_views/task.rb +47 -0
  297. data/lib/roby/gui/model_views/task.rhtml +41 -0
  298. data/lib/roby/gui/object_info_view.rb +89 -0
  299. data/lib/roby/gui/plan_dot_layout.rb +427 -0
  300. data/lib/roby/gui/plan_rebuilder_widget.rb +357 -0
  301. data/lib/roby/gui/qt4_toMSecsSinceEpoch.rb +8 -0
  302. data/lib/roby/gui/relations_view.rb +278 -0
  303. data/lib/roby/gui/relations_view/relations.ui +139 -0
  304. data/lib/roby/gui/relations_view/relations_canvas.rb +1088 -0
  305. data/lib/roby/gui/relations_view/relations_config.rb +292 -0
  306. data/lib/roby/gui/relations_view/relations_view.ui +53 -0
  307. data/lib/roby/gui/scheduler_view.css +24 -0
  308. data/lib/roby/gui/scheduler_view.rb +46 -0
  309. data/lib/roby/gui/scheduler_view.rhtml +53 -0
  310. data/lib/roby/gui/stepping.rb +93 -0
  311. data/lib/roby/gui/stepping.ui +181 -0
  312. data/lib/roby/gui/styles.rb +81 -0
  313. data/lib/roby/gui/task_display_configuration.rb +42 -0
  314. data/lib/roby/gui/task_state_at.rb +38 -0
  315. data/lib/roby/hooks.rb +26 -0
  316. data/lib/roby/interface.rb +136 -469
  317. data/lib/roby/interface/async.rb +20 -0
  318. data/lib/roby/interface/async/action_monitor.rb +188 -0
  319. data/lib/roby/interface/async/interface.rb +498 -0
  320. data/lib/roby/interface/async/job_monitor.rb +213 -0
  321. data/lib/roby/interface/async/log.rb +238 -0
  322. data/lib/roby/interface/async/new_job_listener.rb +79 -0
  323. data/lib/roby/interface/async/ui_connector.rb +183 -0
  324. data/lib/roby/interface/client.rb +553 -0
  325. data/lib/roby/interface/command.rb +24 -0
  326. data/lib/roby/interface/command_argument.rb +16 -0
  327. data/lib/roby/interface/command_library.rb +92 -0
  328. data/lib/roby/interface/droby_channel.rb +174 -0
  329. data/lib/roby/interface/exceptions.rb +22 -0
  330. data/lib/roby/interface/interface.rb +655 -0
  331. data/lib/roby/interface/job.rb +47 -0
  332. data/lib/roby/interface/rest.rb +10 -0
  333. data/lib/roby/interface/rest/api.rb +29 -0
  334. data/lib/roby/interface/rest/helpers.rb +24 -0
  335. data/lib/roby/interface/rest/server.rb +212 -0
  336. data/lib/roby/interface/server.rb +154 -0
  337. data/lib/roby/interface/shell_client.rb +468 -0
  338. data/lib/roby/interface/shell_subcommand.rb +24 -0
  339. data/lib/roby/interface/subcommand_client.rb +35 -0
  340. data/lib/roby/interface/tcp.rb +168 -0
  341. data/lib/roby/models/arguments.rb +112 -0
  342. data/lib/roby/models/plan_object.rb +83 -0
  343. data/lib/roby/models/task.rb +835 -0
  344. data/lib/roby/models/task_event.rb +62 -0
  345. data/lib/roby/models/task_service.rb +78 -0
  346. data/lib/roby/or_generator.rb +88 -0
  347. data/lib/roby/plan.rb +1751 -864
  348. data/lib/roby/plan_object.rb +611 -0
  349. data/lib/roby/plan_service.rb +200 -0
  350. data/lib/roby/promise.rb +332 -0
  351. data/lib/roby/queries.rb +23 -0
  352. data/lib/roby/queries/and_matcher.rb +32 -0
  353. data/lib/roby/queries/any.rb +27 -0
  354. data/lib/roby/queries/code_error_matcher.rb +58 -0
  355. data/lib/roby/queries/event_generator_matcher.rb +9 -0
  356. data/lib/roby/queries/execution_exception_matcher.rb +165 -0
  357. data/lib/roby/queries/index.rb +165 -0
  358. data/lib/roby/queries/localized_error_matcher.rb +149 -0
  359. data/lib/roby/queries/matcher_base.rb +107 -0
  360. data/lib/roby/queries/none.rb +27 -0
  361. data/lib/roby/queries/not_matcher.rb +30 -0
  362. data/lib/roby/queries/op_matcher.rb +8 -0
  363. data/lib/roby/queries/or_matcher.rb +30 -0
  364. data/lib/roby/queries/plan_object_matcher.rb +363 -0
  365. data/lib/roby/queries/query.rb +188 -0
  366. data/lib/roby/queries/task_event_generator_matcher.rb +86 -0
  367. data/lib/roby/queries/task_matcher.rb +344 -0
  368. data/lib/roby/relations.rb +42 -678
  369. data/lib/roby/relations/bidirectional_directed_adjacency_graph.rb +492 -0
  370. data/lib/roby/relations/directed_relation_support.rb +268 -0
  371. data/lib/roby/relations/event_relation_graph.rb +19 -0
  372. data/lib/roby/relations/fork_merge_visitor.rb +154 -0
  373. data/lib/roby/relations/graph.rb +533 -0
  374. data/lib/roby/relations/models/directed_relation_support.rb +11 -0
  375. data/lib/roby/relations/models/graph.rb +75 -0
  376. data/lib/roby/relations/models/task_relation_graph.rb +18 -0
  377. data/lib/roby/relations/space.rb +380 -0
  378. data/lib/roby/relations/task_relation_graph.rb +20 -0
  379. data/lib/roby/robot.rb +85 -38
  380. data/lib/roby/schedulers/basic.rb +155 -25
  381. data/lib/roby/schedulers/null.rb +20 -0
  382. data/lib/roby/schedulers/reporting.rb +31 -0
  383. data/lib/roby/schedulers/state.rb +129 -0
  384. data/lib/roby/schedulers/temporal.rb +91 -0
  385. data/lib/roby/singletons.rb +87 -0
  386. data/lib/roby/standalone.rb +4 -2
  387. data/lib/roby/standard_errors.rb +405 -82
  388. data/lib/roby/state.rb +6 -3
  389. data/lib/roby/state/conf_model.rb +5 -0
  390. data/lib/roby/state/events.rb +181 -95
  391. data/lib/roby/state/goal_model.rb +77 -0
  392. data/lib/roby/state/open_struct.rb +591 -0
  393. data/lib/roby/state/open_struct_model.rb +68 -0
  394. data/lib/roby/state/pos.rb +45 -45
  395. data/lib/roby/state/shapes.rb +11 -11
  396. data/lib/roby/state/state_model.rb +303 -0
  397. data/lib/roby/state/task.rb +43 -0
  398. data/lib/roby/support.rb +88 -148
  399. data/lib/roby/task.rb +1361 -1750
  400. data/lib/roby/task_arguments.rb +428 -0
  401. data/lib/roby/task_event.rb +127 -0
  402. data/lib/roby/task_event_generator.rb +337 -0
  403. data/lib/roby/task_service.rb +6 -0
  404. data/lib/roby/task_structure/conflicts.rb +104 -0
  405. data/lib/roby/task_structure/dependency.rb +932 -0
  406. data/lib/roby/task_structure/error_handling.rb +118 -0
  407. data/lib/roby/task_structure/executed_by.rb +234 -0
  408. data/lib/roby/task_structure/planned_by.rb +90 -0
  409. data/lib/roby/tasks/aggregator.rb +37 -0
  410. data/lib/roby/tasks/external_process.rb +275 -0
  411. data/lib/roby/tasks/group.rb +27 -0
  412. data/lib/roby/tasks/null.rb +19 -0
  413. data/lib/roby/tasks/parallel.rb +43 -0
  414. data/lib/roby/tasks/sequence.rb +88 -0
  415. data/lib/roby/tasks/simple.rb +21 -0
  416. data/lib/roby/{thread_task.rb → tasks/thread.rb} +50 -24
  417. data/lib/roby/tasks/timeout.rb +17 -0
  418. data/lib/roby/tasks/virtual.rb +55 -0
  419. data/lib/roby/template_plan.rb +7 -0
  420. data/lib/roby/test/aruba_minitest.rb +74 -0
  421. data/lib/roby/test/assertion.rb +16 -0
  422. data/lib/roby/test/assertions.rb +490 -0
  423. data/lib/roby/test/common.rb +368 -591
  424. data/lib/roby/test/dsl.rb +149 -0
  425. data/lib/roby/test/error.rb +18 -0
  426. data/lib/roby/test/event_reporter.rb +83 -0
  427. data/lib/roby/test/execution_expectations.rb +1134 -0
  428. data/lib/roby/test/expect_execution.rb +151 -0
  429. data/lib/roby/test/minitest_helpers.rb +166 -0
  430. data/lib/roby/test/roby_app_helpers.rb +200 -0
  431. data/lib/roby/test/run_planners.rb +155 -0
  432. data/lib/roby/test/self.rb +112 -0
  433. data/lib/roby/test/spec.rb +198 -0
  434. data/lib/roby/test/tasks/empty_task.rb +4 -4
  435. data/lib/roby/test/tasks/goto.rb +28 -27
  436. data/lib/roby/test/teardown_plans.rb +100 -0
  437. data/lib/roby/test/testcase.rb +239 -307
  438. data/lib/roby/test/tools.rb +159 -155
  439. data/lib/roby/test/validate_state_machine.rb +75 -0
  440. data/lib/roby/transaction.rb +1125 -0
  441. data/lib/roby/transaction/event_generator_proxy.rb +63 -0
  442. data/lib/roby/transaction/plan_object_proxy.rb +99 -0
  443. data/lib/roby/transaction/plan_service_proxy.rb +43 -0
  444. data/lib/roby/transaction/proxying.rb +120 -0
  445. data/lib/roby/transaction/task_event_generator_proxy.rb +19 -0
  446. data/lib/roby/transaction/task_proxy.rb +135 -0
  447. data/lib/roby/until_generator.rb +30 -0
  448. data/lib/roby/version.rb +5 -0
  449. data/lib/roby/yard.rb +169 -0
  450. data/lib/yard-roby.rb +1 -0
  451. data/manifest.xml +32 -6
  452. data/roby.gemspec +59 -0
  453. metadata +788 -587
  454. data/Manifest.txt +0 -321
  455. data/NOTES +0 -4
  456. data/README.txt +0 -166
  457. data/TODO.txt +0 -146
  458. data/app/README.txt +0 -24
  459. data/app/Rakefile +0 -8
  460. data/app/config/ROBOT.rb +0 -5
  461. data/app/config/init.rb +0 -33
  462. data/app/config/roby.yml +0 -3
  463. data/app/controllers/ROBOT.rb +0 -2
  464. data/app/planners/ROBOT/main.rb +0 -6
  465. data/app/planners/main.rb +0 -5
  466. data/app/scripts/distributed +0 -3
  467. data/app/scripts/generate/bookmarks +0 -3
  468. data/app/scripts/replay +0 -3
  469. data/app/scripts/results +0 -3
  470. data/app/scripts/run +0 -3
  471. data/app/scripts/server +0 -3
  472. data/app/scripts/shell +0 -3
  473. data/app/scripts/test +0 -3
  474. data/app/tasks/.gitattributes +0 -0
  475. data/app/tasks/ROBOT/.gitattributes +0 -0
  476. data/bin/roby-shell +0 -25
  477. data/doc/guide/src/basics/app.page +0 -139
  478. data/doc/guide/src/basics/index.page +0 -11
  479. data/doc/guide/src/basics/log_replay/goForward_1.png +0 -0
  480. data/doc/guide/src/basics/log_replay/goForward_2.png +0 -0
  481. data/doc/guide/src/basics/log_replay/goForward_3.png +0 -0
  482. data/doc/guide/src/basics/log_replay/goForward_5.png +0 -0
  483. data/doc/guide/src/basics/log_replay/plan_repair_4.png +0 -0
  484. data/doc/guide/src/basics/log_replay/roby_log_main_window.png +0 -0
  485. data/doc/guide/src/basics/relations_display.page +0 -203
  486. data/doc/guide/src/basics/shell.page +0 -102
  487. data/doc/guide/src/default.css +0 -319
  488. data/doc/guide/src/introduction/index.page +0 -29
  489. data/doc/guide/src/introduction/publications.page +0 -14
  490. data/doc/guide/src/relations/dependency.page +0 -89
  491. data/doc/guide/src/relations/index.page +0 -12
  492. data/ext/droby/dump.cc +0 -175
  493. data/ext/droby/extconf.rb +0 -3
  494. data/ext/graph/algorithm.cc +0 -746
  495. data/ext/graph/extconf.rb +0 -7
  496. data/ext/graph/graph.cc +0 -575
  497. data/ext/graph/graph.hh +0 -183
  498. data/ext/graph/iterator_sequence.hh +0 -102
  499. data/ext/graph/undirected_dfs.hh +0 -226
  500. data/ext/graph/undirected_graph.hh +0 -421
  501. data/lib/roby/app/scripts/generate/bookmarks.rb +0 -162
  502. data/lib/roby/app/scripts/replay.rb +0 -31
  503. data/lib/roby/app/scripts/server.rb +0 -18
  504. data/lib/roby/basic_object.rb +0 -151
  505. data/lib/roby/config.rb +0 -14
  506. data/lib/roby/distributed.rb +0 -36
  507. data/lib/roby/distributed/base.rb +0 -448
  508. data/lib/roby/distributed/communication.rb +0 -875
  509. data/lib/roby/distributed/connection_space.rb +0 -616
  510. data/lib/roby/distributed/distributed_object.rb +0 -206
  511. data/lib/roby/distributed/drb.rb +0 -62
  512. data/lib/roby/distributed/notifications.rb +0 -531
  513. data/lib/roby/distributed/peer.rb +0 -555
  514. data/lib/roby/distributed/protocol.rb +0 -529
  515. data/lib/roby/distributed/proxy.rb +0 -343
  516. data/lib/roby/distributed/subscription.rb +0 -311
  517. data/lib/roby/distributed/transaction.rb +0 -498
  518. data/lib/roby/external_process_task.rb +0 -225
  519. data/lib/roby/graph.rb +0 -160
  520. data/lib/roby/log.rb +0 -3
  521. data/lib/roby/log/chronicle.rb +0 -303
  522. data/lib/roby/log/console.rb +0 -74
  523. data/lib/roby/log/data_stream.rb +0 -275
  524. data/lib/roby/log/dot.rb +0 -279
  525. data/lib/roby/log/event_stream.rb +0 -161
  526. data/lib/roby/log/file.rb +0 -396
  527. data/lib/roby/log/gui/basic_display.ui +0 -83
  528. data/lib/roby/log/gui/basic_display_ui.rb +0 -89
  529. data/lib/roby/log/gui/chronicle.rb +0 -26
  530. data/lib/roby/log/gui/chronicle_view.rb +0 -40
  531. data/lib/roby/log/gui/chronicle_view.ui +0 -70
  532. data/lib/roby/log/gui/chronicle_view_ui.rb +0 -90
  533. data/lib/roby/log/gui/data_displays.rb +0 -171
  534. data/lib/roby/log/gui/data_displays.ui +0 -155
  535. data/lib/roby/log/gui/data_displays_ui.rb +0 -146
  536. data/lib/roby/log/gui/notifications.rb +0 -26
  537. data/lib/roby/log/gui/relations.rb +0 -269
  538. data/lib/roby/log/gui/relations.ui +0 -123
  539. data/lib/roby/log/gui/relations_ui.rb +0 -120
  540. data/lib/roby/log/gui/relations_view.rb +0 -185
  541. data/lib/roby/log/gui/relations_view.ui +0 -149
  542. data/lib/roby/log/gui/relations_view_ui.rb +0 -144
  543. data/lib/roby/log/gui/replay.rb +0 -366
  544. data/lib/roby/log/gui/replay_controls.rb +0 -206
  545. data/lib/roby/log/gui/replay_controls.ui +0 -282
  546. data/lib/roby/log/gui/replay_controls_ui.rb +0 -249
  547. data/lib/roby/log/gui/runtime.rb +0 -130
  548. data/lib/roby/log/hooks.rb +0 -186
  549. data/lib/roby/log/logger.rb +0 -203
  550. data/lib/roby/log/notifications.rb +0 -244
  551. data/lib/roby/log/plan_rebuilder.rb +0 -468
  552. data/lib/roby/log/relations.rb +0 -1084
  553. data/lib/roby/log/server.rb +0 -547
  554. data/lib/roby/log/sqlite.rb +0 -47
  555. data/lib/roby/log/timings.rb +0 -233
  556. data/lib/roby/plan-object.rb +0 -371
  557. data/lib/roby/planning.rb +0 -13
  558. data/lib/roby/planning/loops.rb +0 -309
  559. data/lib/roby/planning/model.rb +0 -1012
  560. data/lib/roby/planning/task.rb +0 -180
  561. data/lib/roby/query.rb +0 -655
  562. data/lib/roby/relations/conflicts.rb +0 -67
  563. data/lib/roby/relations/dependency.rb +0 -358
  564. data/lib/roby/relations/ensured.rb +0 -19
  565. data/lib/roby/relations/error_handling.rb +0 -22
  566. data/lib/roby/relations/events.rb +0 -7
  567. data/lib/roby/relations/executed_by.rb +0 -208
  568. data/lib/roby/relations/influence.rb +0 -10
  569. data/lib/roby/relations/planned_by.rb +0 -63
  570. data/lib/roby/state/information.rb +0 -55
  571. data/lib/roby/state/state.rb +0 -367
  572. data/lib/roby/task-operations.rb +0 -186
  573. data/lib/roby/task_index.rb +0 -80
  574. data/lib/roby/test/distributed.rb +0 -230
  575. data/lib/roby/test/tasks/simple_task.rb +0 -23
  576. data/lib/roby/transactions.rb +0 -507
  577. data/lib/roby/transactions/proxy.rb +0 -325
  578. data/plugins/fault_injection/History.txt +0 -4
  579. data/plugins/fault_injection/README.txt +0 -34
  580. data/plugins/fault_injection/Rakefile +0 -12
  581. data/plugins/fault_injection/TODO.txt +0 -0
  582. data/plugins/fault_injection/app.rb +0 -52
  583. data/plugins/fault_injection/fault_injection.rb +0 -89
  584. data/plugins/fault_injection/test/test_fault_injection.rb +0 -78
  585. data/plugins/subsystems/README.txt +0 -37
  586. data/plugins/subsystems/Rakefile +0 -13
  587. data/plugins/subsystems/app.rb +0 -182
  588. data/plugins/subsystems/test/app/README +0 -24
  589. data/plugins/subsystems/test/app/Rakefile +0 -8
  590. data/plugins/subsystems/test/app/config/app.yml +0 -71
  591. data/plugins/subsystems/test/app/config/init.rb +0 -12
  592. data/plugins/subsystems/test/app/config/roby.yml +0 -3
  593. data/plugins/subsystems/test/app/planners/main.rb +0 -20
  594. data/plugins/subsystems/test/app/scripts/distributed +0 -3
  595. data/plugins/subsystems/test/app/scripts/replay +0 -3
  596. data/plugins/subsystems/test/app/scripts/results +0 -3
  597. data/plugins/subsystems/test/app/scripts/run +0 -3
  598. data/plugins/subsystems/test/app/scripts/server +0 -3
  599. data/plugins/subsystems/test/app/scripts/shell +0 -3
  600. data/plugins/subsystems/test/app/scripts/test +0 -3
  601. data/plugins/subsystems/test/app/tasks/services.rb +0 -15
  602. data/plugins/subsystems/test/test_subsystems.rb +0 -78
  603. data/test/distributed/test_communication.rb +0 -195
  604. data/test/distributed/test_connection.rb +0 -284
  605. data/test/distributed/test_execution.rb +0 -378
  606. data/test/distributed/test_mixed_plan.rb +0 -341
  607. data/test/distributed/test_plan_notifications.rb +0 -238
  608. data/test/distributed/test_protocol.rb +0 -525
  609. data/test/distributed/test_query.rb +0 -106
  610. data/test/distributed/test_remote_plan.rb +0 -491
  611. data/test/distributed/test_transaction.rb +0 -466
  612. data/test/mockups/external_process +0 -28
  613. data/test/mockups/tasks.rb +0 -27
  614. data/test/planning/test_loops.rb +0 -432
  615. data/test/planning/test_model.rb +0 -427
  616. data/test/planning/test_task.rb +0 -126
  617. data/test/relations/test_conflicts.rb +0 -42
  618. data/test/relations/test_dependency.rb +0 -324
  619. data/test/relations/test_ensured.rb +0 -38
  620. data/test/relations/test_executed_by.rb +0 -224
  621. data/test/relations/test_planned_by.rb +0 -56
  622. data/test/suite_core.rb +0 -29
  623. data/test/suite_distributed.rb +0 -10
  624. data/test/suite_planning.rb +0 -4
  625. data/test/suite_relations.rb +0 -8
  626. data/test/tasks/test_external_process.rb +0 -126
  627. data/test/tasks/test_thread_task.rb +0 -70
  628. data/test/test_bgl.rb +0 -528
  629. data/test/test_event.rb +0 -969
  630. data/test/test_exceptions.rb +0 -591
  631. data/test/test_execution_engine.rb +0 -987
  632. data/test/test_gui.rb +0 -20
  633. data/test/test_interface.rb +0 -43
  634. data/test/test_log.rb +0 -125
  635. data/test/test_log_server.rb +0 -133
  636. data/test/test_plan.rb +0 -418
  637. data/test/test_query.rb +0 -424
  638. data/test/test_relations.rb +0 -260
  639. data/test/test_state.rb +0 -432
  640. data/test/test_support.rb +0 -16
  641. data/test/test_task.rb +0 -1181
  642. data/test/test_testcase.rb +0 -138
  643. data/test/test_transactions.rb +0 -610
  644. data/test/test_transactions_proxy.rb +0 -216
@@ -0,0 +1,44 @@
1
+ <% indent, open_code, close_code = ::Roby::CLI::Gen.in_module(*class_name[0..-2]) %>
2
+ <%= open_code %>
3
+ <%= indent %>class <%= class_name.last %> < Roby::Task
4
+ <%= indent %> # You usually want this
5
+ <%= indent %> terminates
6
+ <%= indent %>
7
+ <%= indent %> # Declare an argument to the task. Use default: VALUE to set up a default
8
+ <%= indent %> # value. The default can be nil
9
+ <%= indent %> # argument :arg[, default: 1]
10
+ <%= indent %>
11
+ <%= indent %> # Declare a new event. This defines updated_event which returns a
12
+ <%= indent %> # Roby::EventGenerator
13
+ <%= indent %> # event :updated
14
+ <%= indent %>
15
+ <%= indent %> # Add forwarding to say "when event X is emitted, event Y should". This is
16
+ <%= indent %> # usually used to make a task finish when an event is emitted
17
+ <%= indent %> # forward :X => :Y
18
+ <%= indent %>
19
+ <%= indent %> # Poll block. The given code is called at each Roby execution cycle as long
20
+ <%= indent %> # as the task is running
21
+ <%= indent %> # poll do
22
+ <%= indent %> # puts "Called !"
23
+ <%= indent %> # end
24
+ <%= indent %>
25
+ <%= indent %> # Script. This is the recommended way to implement functionality in tasks.
26
+ <%= indent %> # It executes instructions in sequence, in a way that is compatible with
27
+ <%= indent %> # Roby's reactor. For instance, below, block given to 'execute' will only be
28
+ <%= indent %> # executed once the updated event is emitted
29
+ <%= indent %> #
30
+ <%= indent %> # WARNING: the top level of the script is evaluated at loading time.
31
+ <%= indent %> #
32
+ <%= indent %> # See the documentation of Roby::Coordination::Models::TaskScript. The API
33
+ <%= indent %> # calls are the calls available on the script
34
+ <%= indent %> #
35
+ <%= indent %> # script do
36
+ <%= indent %> # # Waits for an event to be emitted
37
+ <%= indent %> # wait updated_event
38
+ <%= indent %> # execute do
39
+ <%= indent %> # # The code in this block is going to be called at runtime, unlike the
40
+ <%= indent %> # # code at the script level
41
+ <%= indent %> # end
42
+ <%= indent %> # end
43
+ <%= indent %>end
44
+ <%= close_code %>
@@ -0,0 +1,6 @@
1
+ require '<%= require_path %>'
2
+ <% indent, open, close = ::Roby::CLI::Gen.in_module(*class_name[0..-2]) %>
3
+ <%= open %>
4
+ <%= indent %>describe <%= class_name.last %> do
5
+ <%= indent %>end
6
+ <%= close %>
@@ -0,0 +1,120 @@
1
+ require 'roby/cli/gen/helpers'
2
+ require 'thor'
3
+
4
+ module Roby
5
+ module CLI
6
+ class GenMain < Thor
7
+ include Thor::Actions
8
+
9
+
10
+ namespace :gen
11
+ source_paths << File.join(__dir__, 'gen')
12
+
13
+ desc "app [DIR]", "creates a new app scaffold in the current directory, or DIR if given"
14
+ option :quiet, type: :boolean, default: false
15
+ def app(dir = nil, init_path: 'roby_app', robot_path: 'roby_app')
16
+ if dir
17
+ if File.exist?(dir)
18
+ raise CLIInvalidArguments, "#{dir} already exists"
19
+ end
20
+ else
21
+ dir = Dir.pwd
22
+ end
23
+
24
+ directory 'app/', dir, verbose: !options[:quiet]
25
+ copy_file File.join(init_path, 'config' , 'init.rb'), File.join(dir, 'config', 'init.rb'), verbose: !options[:quiet]
26
+ template File.join(robot_path, 'config', "robots", "robot.rb"),
27
+ File.join(dir, "config", "robots", "default.rb"),
28
+ context: Gen.make_context('robot_name' => 'default'),
29
+ verbose: !options[:quiet]
30
+ dir
31
+ end
32
+
33
+ desc "robot ROBOT_NAME", "creates a new robot configuration"
34
+ def robot(name, robot_path: 'roby_app')
35
+ Roby.app.require_app_dir(needs_current: true)
36
+ Roby.app.load_base_config
37
+
38
+ template File.join(robot_path, 'config', "robots", "robot.rb"),
39
+ File.join("config", "robots", "#{name}.rb"),
40
+ context: Gen.make_context('robot_name' => name)
41
+ end
42
+
43
+ desc "action ACTION_FILE_OR_CLASS", "create a new action interface at the provided file"
44
+ option :robot, aliases: 'r', desc: 'the robot name for robot-specific scaffolding',
45
+ type: :string, default: nil
46
+ def actions(name)
47
+ Roby.app.require_app_dir(needs_current: true)
48
+ Roby.app.load_base_config
49
+
50
+ file_name, class_name = Gen.resolve_name(
51
+ 'actions', name, options[:robot], ['models', 'actions'], ["Actions"])
52
+
53
+ template File.join('actions', 'class.rb'),
54
+ File.join('models', 'actions', *file_name) + ".rb",
55
+ context: Gen.make_context('class_name' => class_name)
56
+ template File.join('actions', "test.rb"),
57
+ File.join('test', 'actions', *file_name[0..-2], "test_#{file_name[-1]}.rb"),
58
+ context: Gen.make_context(
59
+ 'class_name' => class_name,
60
+ 'require_path' => File.join('models', "actions", *file_name))
61
+ end
62
+
63
+ desc "class CLASS_NAME", "creates a new utility class in lib/"
64
+ def klass(name)
65
+ Roby.app.require_app_dir(needs_current: true)
66
+ Roby.app.load_base_config
67
+
68
+ file_name, class_name = Gen.resolve_name(
69
+ 'class', name, nil, ['lib', Roby.app.app_name], [])
70
+
71
+ template File.join('class', 'class.rb'),
72
+ File.join('lib', Roby.app.app_name, *file_name) + ".rb",
73
+ context: Gen.make_context('class_name' => class_name)
74
+ template File.join('class', "test.rb"),
75
+ File.join('test', 'lib', *file_name[0..-2], "test_#{file_name[-1]}.rb"),
76
+ context: Gen.make_context(
77
+ 'class_name' => class_name,
78
+ 'require_path' => File.join(Roby.app.app_name, *file_name))
79
+ end
80
+
81
+ desc "module MODULE_NAME", "creates a new utility module in lib/"
82
+ def module(name)
83
+ Roby.app.require_app_dir(needs_current: true)
84
+ Roby.app.load_base_config
85
+
86
+ file_name, class_name = Gen.resolve_name(
87
+ 'module', name, nil, ['lib', Roby.app.app_name], [])
88
+
89
+ template File.join('module', 'module.rb'),
90
+ File.join('lib', Roby.app.app_name, *file_name) + ".rb",
91
+ context: Gen.make_context('module_name' => class_name)
92
+ template File.join('module', "test.rb"),
93
+ File.join('test', 'lib', *file_name[0..-2], "test_#{file_name[-1]}.rb"),
94
+ context: Gen.make_context(
95
+ 'module_name' => class_name,
96
+ 'require_path' => File.join(Roby.app.app_name, *file_name))
97
+ end
98
+
99
+ desc "task NAME", "creates a new Roby task model"
100
+ option :robot, aliases: 'r', desc: 'the robot name for robot-specific scaffolding',
101
+ type: :string, default: nil
102
+ def task(name)
103
+ Roby.app.require_app_dir(needs_current: true)
104
+ Roby.app.load_base_config
105
+
106
+ file_name, class_name = Gen.resolve_name(
107
+ 'tasks', name, options[:robot], ['models', 'tasks'], ["Tasks"])
108
+
109
+ template File.join('task', 'class.rb'),
110
+ File.join('models', 'tasks', *file_name) + ".rb",
111
+ context: Gen.make_context('class_name' => class_name)
112
+ template File.join('task', "test.rb"),
113
+ File.join('test', 'tasks', *file_name[0..-2], "test_#{file_name[-1]}.rb"),
114
+ context: Gen.make_context(
115
+ 'class_name' => class_name,
116
+ 'require_path' => File.join('models', "tasks", *file_name))
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,276 @@
1
+ require 'roby'
2
+ require 'thor'
3
+
4
+ Roby.app.guess_app_dir
5
+
6
+ module Roby
7
+ module CLI
8
+ class Log < Thor
9
+ no_commands do
10
+ def handle_file_argument(file = nil)
11
+
12
+ if file
13
+ return file if File.file?(file)
14
+ Roby.app.setup_robot_names_from_config_dir
15
+ if !Roby.app.robot_name?(file)
16
+ raise ArgumentError, "expected #{file} to either the path to a log file, or a robot name to get the last log file from this robot configuration"
17
+ end
18
+ Roby.app.robot(file)
19
+ end
20
+ Roby.app.log_current_file
21
+ end
22
+ end
23
+
24
+ desc 'upgrade-format', 'upgrades an older Roby log file to the newest version'
25
+ def upgrade_format(file)
26
+ require 'roby/log/upgrade'
27
+ Roby::Log::Upgrade.to_new_format(file)
28
+ end
29
+
30
+ desc 'rebuild-index', 'rebuilds the index of an existing log file'
31
+ def rebuild_index(file = nil)
32
+ file = handle_file_argument(file)
33
+ require 'roby/droby/logfile/reader'
34
+ Roby::DRoby::Logfile::Reader.open(file).
35
+ rebuild_index
36
+ end
37
+
38
+ desc 'timepoints', 'extract timepoint information from the log file'
39
+ option :raw, desc: 'display the timpoints as they appear instead of formatting them per-thread and per-group',
40
+ type: :boolean, default: false
41
+ option :flamegraph, type: :string, desc: 'path to a HTML file that will display a flame graph'
42
+ option :ctf, type: :boolean, desc: 'generate a CTF file suitable to be analyzed by e.g. Trace Compass'
43
+ def timepoints(file = nil)
44
+ file = handle_file_argument(file)
45
+
46
+ require 'roby/droby/logfile/reader'
47
+ require 'roby/droby/timepoints'
48
+ require 'roby/droby/timepoints_ctf'
49
+ require 'roby/cli/log/flamegraph_renderer'
50
+
51
+ stream = Roby::DRoby::Logfile::Reader.open(file)
52
+
53
+ if options[:raw]
54
+ current_context = Hash.new
55
+ while data = stream.load_one_cycle
56
+ data.each_slice(4) do |m, sec, usec, args|
57
+ thread_id, thread_name, timepoint_name = *args
58
+ path = (current_context[thread_id] ||= [thread_name])
59
+
60
+ if m == :timepoint
61
+ puts "#{Roby.format_time(Time.at(sec, usec))} #{path.join("/")}/#{timepoint_name}"
62
+ elsif m == :timepoint_group_start
63
+ puts "#{Roby.format_time(Time.at(sec, usec))} #{path.join("/")}/#{timepoint_name} {"
64
+ path.push timepoint_name
65
+ elsif m == :timepoint_group_end
66
+ path.pop
67
+ puts "#{Roby.format_time(Time.at(sec, usec))} #{path.join("/")}/#{timepoint_name} }"
68
+ end
69
+ end
70
+ end
71
+ return
72
+ end
73
+
74
+
75
+ analyzer = Roby::DRoby::Timepoints::Analysis.new
76
+ if options[:ctf]
77
+ analyzer = Roby::DRoby::Timepoints::CTF.new
78
+ else
79
+ analyzer = Roby::DRoby::Timepoints::Analysis.new
80
+ end
81
+ while data = stream.load_one_cycle
82
+ data.each_slice(4) do |m, sec, usec, args|
83
+ if m == :timepoint
84
+ analyzer.add Time.at(sec, usec), *args
85
+ elsif m == :timepoint_group_start
86
+ analyzer.group_start Time.at(sec, usec), *args
87
+ elsif m == :timepoint_group_end
88
+ analyzer.group_end Time.at(sec, usec), *args
89
+ end
90
+ end
91
+ end
92
+
93
+ if options[:ctf]
94
+ path = Pathname.new(file).expand_path.sub_ext('.ctf')
95
+ path.mkpath
96
+ puts "saving in #{path}"
97
+ analyzer.save(path)
98
+ elsif options[:flamegraph]
99
+ graph = analyzer.flamegraph
100
+ graph = graph.map do |name, duration|
101
+ [name, (duration * 1000).round]
102
+ end
103
+ File.open(options[:flamegraph], 'w') do |io|
104
+ io.write FlamegraphRenderer.new(graph).graph_html
105
+ end
106
+ else
107
+ puts analyzer.format
108
+ end
109
+ exit 0
110
+ end
111
+
112
+ desc 'stats', 'show general timing statistics'
113
+ option :save, type: :string, desc: 'file to save the CSV data to'
114
+ def stats(file = nil)
115
+ file = handle_file_argument(file)
116
+
117
+ require 'roby/droby/logfile/reader'
118
+ stream = Roby::DRoby::Logfile::Reader.open(file)
119
+ index = stream.index
120
+
121
+ cycle_count = index.size
122
+
123
+ if cycle_count == 0
124
+ puts "empty log file"
125
+ exit 0
126
+ end
127
+
128
+ timespan = index.range
129
+ puts "#{cycle_count} cycles between #{timespan.first.to_hms} and #{timespan.last.to_hms}"
130
+ process_utime = index.inject(0) { |old, info| old + info[:utime] }
131
+ process_stime = index.inject(0) { |old, info| old + info[:stime] }
132
+ real_time = timespan.last - timespan.first
133
+ ratio = (process_utime + process_stime) / real_time
134
+ puts "Time: %.2fs user / %.2fs sys / %.2fs real (%i%% CPU use)" %
135
+ [process_utime, process_stime, real_time, ratio * 100]
136
+
137
+ min, max = nil
138
+ event_count = index.inject(0) do |total, cycle_info|
139
+ count = cycle_info[:event_count]
140
+ min = count if !min || min > count
141
+ max = count if !max || max < count
142
+ total + count
143
+ end
144
+ puts "#{event_count} log events, #{event_count / cycle_count} events/cycle (min: #{min}, max: #{max})"
145
+
146
+ io = STDOUT
147
+ if options[:save]
148
+ io = File.open(options[:save], 'w')
149
+ end
150
+
151
+ header = %w{0_actual_start 1_cycle_index 2_log_queue_size 3_plan_task_count 4_plan_event_count 5_utime 6_stime 7_dump_time 8_duration 9_total_allocated_objects 10_minor 11_major 12_live_object_count 13_oob_removed 14_gc_total_time}
152
+ formatting = %w{%i %i %i %i %.3f %.3f %.3f %.3f %i %i %i %i %i %.3f}
153
+ formatting = formatting.join(",")
154
+
155
+ puts header.join(",")
156
+ index.each do |info|
157
+ gc = info[:gc]
158
+ oob_gc = info[:pre_oob_gc] || gc
159
+ start_sec, start_usec = info[:start]
160
+ start = Time.at(start_sec, start_usec)
161
+
162
+ io.puts (start + info[:actual_start]).strftime("%H:%M:%S.%3N") + " " + formatting % [
163
+ *info.values_at(:cycle_index, :log_queue_size, :plan_task_count, :plan_event_count, :utime, :stime, :dump_time, :end),
164
+ gc[:total_allocated_objects],
165
+ gc[:minor_gc_count],
166
+ gc[:major_gc_count],
167
+ gc[:total_allocated_objects] - gc[:total_freed_objects],
168
+ gc[:total_freed_objects] - oob_gc[:total_freed_objects],
169
+ info[:gc_total_time] || 0]
170
+ end
171
+
172
+ exit(0)
173
+ end
174
+
175
+ desc 'decode', 'show the raw events from the logfile'
176
+ option :replay, type: :string,
177
+ desc: "replay the log stream into a plan, add =debug to display more debugging information. Mainly useful to debug issues with the plan rebuilder",
178
+ default: 'normal'
179
+ def decode(file = nil)
180
+ file = handle_file_argument(file)
181
+
182
+ require 'roby/droby/logfile/reader'
183
+ require 'roby/droby/plan_rebuilder'
184
+
185
+ stream = Roby::DRoby::Logfile::Reader.open(file)
186
+ if replay = options[:replay]
187
+ replay_debug = (replay == 'debug')
188
+ rebuilder = Roby::DRoby::PlanRebuilder.new
189
+ end
190
+
191
+ while data = stream.load_one_cycle
192
+ data.each_slice(4) do |m, sec, usec, args|
193
+ header = "#{Time.at(sec, usec)} #{m} "
194
+ puts "#{header} #{args.map(&:to_s).join(" ")}"
195
+ header = " " * header.size
196
+ if rebuilder
197
+ begin
198
+ rebuilder.process_one_event(m, sec, usec, args)
199
+ if replay_debug
200
+ if m == :merged_plan
201
+ puts "Merged plan"
202
+ plan = args[1]
203
+ puts " #{plan.tasks.size} tasks: #{plan.tasks.map { |id, _| id.to_s }.join(", ")}"
204
+ puts " #{plan.task_events.size} task events: #{plan.task_events.map { |id, _| id.to_s }.join(", ")}"
205
+ puts " #{plan.free_events.size} events: #{plan.free_events.map { |id, _| id.to_s }.join(", ")}"
206
+ end
207
+ pp rebuilder
208
+ end
209
+ rescue Roby::DRoby::UnknownSibling
210
+ # Add some more debugging information
211
+ pp rebuilder
212
+ raise
213
+ end
214
+ end
215
+ end
216
+ if rebuilder
217
+ rebuilder.clear_integrated
218
+ end
219
+ end
220
+ end
221
+
222
+ desc 'repair', 'attempt to repair a broken log file'
223
+ def repair(file)
224
+ require 'roby/droby/logfile/reader'
225
+ logfile = Roby::DRoby::Logfile::Reader.open(file)
226
+ last_cycle = nil
227
+ while !logfile.eof?
228
+ current_pos = logfile.tell
229
+ begin
230
+ last_cycle = logfile.load_one_cycle
231
+ rescue Roby::DRoby::Logfile::TruncatedFileError
232
+ stat = File.stat(file)
233
+ puts "last chunk(s) in the file seem to have only been partially written."
234
+ puts "truncating at #{current_pos} out of #{stat.size} (removing #{stat.size - current_pos} bytes)"
235
+ if last_cycle
236
+ info = last_cycle.last.last
237
+ end_time = Time.at(*info[:start]) + info[:end]
238
+ puts "the repaired file ends at #{end_time}"
239
+ else
240
+ puts "there are no valid cycles in the truncated file"
241
+ end
242
+ FileUtils.cp file, "#{file}.broken"
243
+ puts "the original has been saved as '#{file}.broken'"
244
+ File.open(file, 'a+') do |io|
245
+ io.truncate(current_pos)
246
+ end
247
+ break
248
+ end
249
+ end
250
+ ensure logfile.close
251
+ end
252
+
253
+ desc 'current', 'full path to the current log file'
254
+ option :dir, aliases: 'd', type: :boolean
255
+ def current(robot_name = nil)
256
+ if robot_name
257
+ Roby.app.setup_robot_names_from_config_dir
258
+ Roby.app.robot(robot_name)
259
+ end
260
+ if options[:dir]
261
+ puts Roby.app.log_current_dir
262
+ else
263
+ puts Roby.app.log_current_file
264
+ end
265
+ end
266
+
267
+ desc 'display', "start roby-display to visualize the log file's contents"
268
+ def display(file = nil)
269
+ file = handle_file_argument(file)
270
+ require 'roby/cli/display'
271
+ Display.new.file(file)
272
+ end
273
+ end
274
+ end
275
+ end
276
+
@@ -0,0 +1,499 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ /**INCLUDES**/
5
+
6
+ <meta charset=utf-8 />
7
+
8
+ <title>Flame Graph of Page</title>
9
+ <style>
10
+ .info {min-height: 50px; margin: 10px; }
11
+ .legend div {
12
+ display: block;
13
+ float: left;
14
+ width: 150px;
15
+ margin: 0 8px 8px;
16
+ padding: 4px;
17
+ height: 50px;
18
+ }
19
+ .code {
20
+ font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace;
21
+ }
22
+ #frameinfo table .sample-info {
23
+ width: 200px;
24
+ color: #333;
25
+ font-size: 12px;
26
+ }
27
+ #frameinfo table {
28
+ border-collapse: collapse;
29
+ }
30
+ #frameinfo table tr {
31
+ border-bottom: 1px solid #eee;
32
+ margin-top: 5px;
33
+ }
34
+ #frameinfo td {
35
+ padding: 5px;
36
+ }
37
+ #frameinfo-wrapper {
38
+ position: fixed;
39
+ z-index: 1;
40
+ opacity: 0.7;
41
+ background-color: black;
42
+ width: 100%;
43
+ height: 100%;
44
+ top: 0;
45
+ left: 0;
46
+ display: none;
47
+ }
48
+ #frameinfo {
49
+ position: fixed;
50
+ padding: 10px;
51
+ z-index: 2;
52
+ opacity: 1.0;
53
+ top: 0;
54
+ margin-top: 50px;
55
+ margin-left: 40px;
56
+ width: 80%;
57
+ height: 80%;
58
+ background-color: white;
59
+ border: 2px solid #666;
60
+ display: none;
61
+ overflow: auto;
62
+ }
63
+ </style>
64
+ </head>
65
+ <body>
66
+ <div class="graph"></div>
67
+ <div class="info code"></div>
68
+ <div class="legend"></div>
69
+ <div id="frameinfo-wrapper"></div>
70
+ <div id="frameinfo">
71
+ <h3>Frame Info</h3>
72
+ <table>
73
+ </table>
74
+ </div>
75
+ <script>
76
+
77
+ var data = /**DATA**/;
78
+ var maxX = 0;
79
+ var maxY = 0;
80
+
81
+ debounce = function(func, wait, trickle) {
82
+ var timeout;
83
+
84
+ timeout = null;
85
+ return function() {
86
+ var args, context, currentWait, later;
87
+ context = this;
88
+ args = arguments;
89
+ later = function() {
90
+ timeout = null;
91
+ return func.apply(context, args);
92
+ };
93
+
94
+ if (timeout && trickle) {
95
+ // already queued, let it through
96
+ return;
97
+ }
98
+
99
+ if (typeof wait === "function") {
100
+ currentWait = wait();
101
+ } else {
102
+ currentWait = wait;
103
+ }
104
+
105
+ if (timeout) {
106
+ clearTimeout(timeout);
107
+ }
108
+
109
+ timeout = setTimeout(later, currentWait);
110
+ return timeout;
111
+ };
112
+ };
113
+
114
+
115
+ var guessGem = function(frame)
116
+ {
117
+ var split = frame.split('/gems/');
118
+ if(split.length == 1) {
119
+ split = frame.split('/app/');
120
+ if(split.length == 1) {
121
+ split = frame.split('/lib/');
122
+ }
123
+
124
+ split = split[Math.max(split.length-2,0)].split('/');
125
+ return split[split.length-1].split(':')[0];
126
+ }
127
+ else
128
+ {
129
+ return split[split.length -1].split('/')[0];
130
+ }
131
+ }
132
+
133
+ var guessMethod = function(frame) {
134
+ var split = frame.split('`');
135
+ if(split.length == 2) {
136
+ var fullMethod = split[1].split("'")[0];
137
+ split = fullMethod.split("#");
138
+ if(split.length == 2) {
139
+ return split[1];
140
+ }
141
+ return split[0];
142
+ }
143
+ return '?';
144
+ }
145
+
146
+ var guessFile = function(frame) {
147
+ var split = frame.split(".rb:");
148
+ if(split.length == 2) {
149
+ split = split[0].split('/');
150
+ return split[split.length - 1];
151
+ }
152
+ return "";
153
+ }
154
+
155
+ $.each(data, function(){
156
+ maxX = Math.max(maxX, this.x + this.width);
157
+ maxY = Math.max(maxY, this.y);
158
+ this.shortName = this.frame;
159
+ });
160
+
161
+ var width = $(window).width();
162
+ var height = $(window).height() / 1.2;
163
+
164
+ $('.graph').width(width).height(height);
165
+
166
+ var xScale = d3.scale.linear()
167
+ .domain([0, maxX])
168
+ .range([0, width]);
169
+
170
+ var yScale = d3.scale.linear()
171
+ .domain([0, maxY])
172
+ .range([0,height]);
173
+
174
+ var realHeight = 0;
175
+ var debouncedHeightCheck = debounce(function(){
176
+ if (realHeight > 15) {
177
+ svg.selectAll('text').attr('display','show');
178
+ } else {
179
+ svg.selectAll('text').attr('display','none');
180
+ }
181
+ }, 200);
182
+
183
+ function zoom()
184
+ {
185
+ svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")");
186
+
187
+ realHeight = yScale(1) * d3.event.scale;
188
+ debouncedHeightCheck();
189
+ }
190
+
191
+ var svg = d3.select(".graph")
192
+ .append("svg")
193
+ .attr("width", "100%")
194
+ .attr("height", "100%")
195
+ .attr("pointer-events", "all")
196
+ .append('svg:g')
197
+ .call(d3.behavior.zoom().on("zoom", zoom))
198
+ .append('svg:g');
199
+
200
+
201
+ // so zoom works everywhere
202
+ svg.append("rect")
203
+ .attr("x",function(d) { return xScale(0); })
204
+ .attr("y",function(d) { return yScale(0);})
205
+ .attr("width", function(d){return xScale(maxX);})
206
+ .attr("height", yScale(maxY))
207
+ .attr("fill", "white");
208
+
209
+ var color = function() {
210
+ var r = parseInt(205 + Math.random() * 50);
211
+ var g = parseInt(Math.random() * 230);
212
+ var b = parseInt(Math.random() * 55);
213
+ return "rgb(" + r + "," + g + "," + b + ")";
214
+ }
215
+ var info = {};
216
+
217
+ // http://stackoverflow.com/questions/1960473/unique-values-in-an-array
218
+ Array.prototype.getUnique = function() {
219
+ var o = {}, a = []
220
+ for (var i = 0; i < this.length; i++) o[this[i]] = 1
221
+ for (var e in o) a.push(e)
222
+ return a
223
+ }
224
+
225
+ var samplePercent = function(samples, exclusive){
226
+ var info = " (" + samples +
227
+ " sample" + (samples == 1 ? "" : "s") + " - " +
228
+ ((samples / maxX) * 100).toFixed(2) + "%) ";
229
+ if (exclusive) {
230
+ info += " (" + exclusive +
231
+ " exclusive - " +
232
+ ((exclusive / maxX) * 100).toFixed(2) + "%) ";
233
+ }
234
+ return info;
235
+ }
236
+
237
+ var mouseover = function(d) {
238
+ var i = info[d.frame];
239
+ $('.info').text( d.frame + " " + samplePercent(i.samples.length, d.topFrame ? d.topFrame.exclusiveCount : 0));
240
+ d3.selectAll(i.nodes)
241
+ .attr('opacity',0.5);
242
+ };
243
+
244
+ var mouseout = function(d) {
245
+ var i = info[d.frame];
246
+ $('.info').text("");
247
+ d3.selectAll(i.nodes)
248
+ .attr('opacity',1);
249
+ };
250
+
251
+ var backtrace = function(frame){
252
+ for(var i=0; i<data.length; i++){
253
+ if(frame === data[i]){ break; }
254
+ }
255
+
256
+ frames = [frame];
257
+ var depth = frame.y;
258
+
259
+ while(i > 0){
260
+ if(depth == -1) break;
261
+
262
+ if(data[i].y === depth-1) {
263
+ frames.push(data[i]);
264
+ depth--;
265
+ }
266
+
267
+ i--;
268
+ }
269
+
270
+ return frames;
271
+ }
272
+
273
+ $('#frameinfo-wrapper').click(function(d){
274
+ $(this).hide();
275
+ $('#frameinfo').hide();
276
+ });
277
+
278
+ var click = function(d){
279
+ var trace = backtrace(d);
280
+
281
+ var link = function(path, dest){
282
+ return path.replace(/[^\/]+:\d+/, function(x){ return "<a target='_blank' href='"+ dest +"'>" + x + "</a>"})
283
+ };
284
+
285
+ var linkify = function(path){
286
+ var split = path.split("/")[0].split("-");
287
+ if(["activerecord","actionpack","railties","activesupport", "rails"].indexOf(split[0]) > -1) {
288
+ var github = "https://github.com/rails/rails/blob/";
289
+ var file = path.split(":")[0].split("/");
290
+ if(split[0] === "rails") {
291
+ file.shift();
292
+ } else {
293
+ file[0] = split[0];
294
+ }
295
+
296
+ github += (split[1].length < 6 ? "v" : "") + split[1] + "/";
297
+ github += file.join("/");
298
+ github += "#L" + parseInt(path.split(":")[1]);
299
+
300
+ return link(path, github);
301
+ }
302
+ return path;
303
+ }
304
+
305
+ var simplify = function(frame){
306
+ var split = frame.split('/gems/');
307
+ if(split.length > 1){
308
+ var path = linkify(split.pop());
309
+ return "<span class='full-location'>" + split.join('/gems/') + "/</span>" + path;
310
+ } else {
311
+ return frame;
312
+ }
313
+ }
314
+
315
+ var table = trace.map(function(f){
316
+ var i = info[f.frame];
317
+ return "<tr><td class='code'>" + simplify(f.frame) + "</td><td class='sample-info'>" +
318
+ samplePercent(i.samples.length, f.topFrame ? f.topFrame.exclusiveCount : 0) +
319
+ "</td></tr>";
320
+ }).join("\n");
321
+
322
+ var table = $('#frameinfo table').html(table);
323
+ table.find(".full-location").hide().after("<span class='expand'>&hellip; </span>");
324
+ table.find(".expand").css({cursor: "pointer"}).click(function(){
325
+ $(this).hide().parent().find(".full-location").show();
326
+ });
327
+
328
+ $('#frameinfo-wrapper').show();
329
+ $('#frameinfo').show();
330
+ };
331
+
332
+ // http://stackoverflow.com/a/7419630
333
+ var rainbow = function(numOfSteps, step) {
334
+ // This function generates vibrant, "evenly spaced" colours (i.e. no clustering). This is ideal for creating easily distiguishable vibrant markers in Google Maps and other apps.
335
+ // Adam Cole, 2011-Sept-14
336
+ // HSV to RBG adapted from: http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
337
+ var r, g, b;
338
+ var h = step / numOfSteps;
339
+ var i = ~~(h * 6);
340
+ var f = h * 6 - i;
341
+ var q = 1 - f;
342
+ switch(i % 6){
343
+ case 0: r = 1, g = f, b = 0; break;
344
+ case 1: r = q, g = 1, b = 0; break;
345
+ case 2: r = 0, g = 1, b = f; break;
346
+ case 3: r = 0, g = q, b = 1; break;
347
+ case 4: r = f, g = 0, b = 1; break;
348
+ case 5: r = 1, g = 0, b = q; break;
349
+ }
350
+ var c = "#" + ("00" + (~ ~(r * 255)).toString(16)).slice(-2) + ("00" + (~ ~(g * 255)).toString(16)).slice(-2) + ("00" + (~ ~(b * 255)).toString(16)).slice(-2);
351
+ return (c);
352
+ }
353
+
354
+ // assign some colors, analyze samples per gem
355
+ var gemStats = {}
356
+ var topFrames = {}
357
+ var lastFrame = {frame: 'd52e04d-df28-41ed-a215-b6ec840a8ea5', x: -1}
358
+
359
+ $.each(data, function(){
360
+
361
+ var gem = guessGem(this.frame);
362
+ var stat = gemStats[gem];
363
+
364
+ if(!stat) {
365
+ gemStats[gem] = stat = {name: gem, samples: [], frames: []};
366
+ }
367
+
368
+ stat.frames.push(this.frame);
369
+ for(var j=0; j < this.width; j++){
370
+ stat.samples.push(this.x + j);
371
+ }
372
+ // This assumes the traversal is in order
373
+ if (lastFrame.x != this.x) {
374
+ var topFrame = topFrames[lastFrame.frame]
375
+ if (!topFrame) {
376
+ topFrames[lastFrame.frame] = topFrame = {exclusiveCount: 0}
377
+ }
378
+ topFrame.exclusiveCount += 1;
379
+ lastFrame.topFrame = topFrame;
380
+ }
381
+ lastFrame = this;
382
+
383
+ });
384
+
385
+ var topFrame = topFrames[lastFrame.frame]
386
+ if (!topFrame) {
387
+ topFrames[lastFrame.frame] = topFrame = {exclusiveCount: 0}
388
+ }
389
+ topFrame.exclusiveCount += 1;
390
+ lastFrame.topFrame = topFrame;
391
+
392
+ var totalGems = 0;
393
+ $.each(gemStats, function(k,stat){
394
+ totalGems++;
395
+ stat.samples = stat.samples.getUnique();
396
+ });
397
+
398
+
399
+ var gemsSorted = _(gemStats).pairs()
400
+ .sortBy(function(item){
401
+ return -item[1].samples.length;
402
+ })
403
+ .map(function(item){return item[1]})
404
+ .value();
405
+
406
+ var currentIndex = 0;
407
+ _.each(gemsSorted, function(stat){
408
+
409
+ stat.color = rainbow(totalGems, currentIndex);
410
+
411
+ for(var x=0; x < stat.frames.length; x++) {
412
+ info[stat.frames[x]] = {nodes: [], samples: [], color: stat.color};
413
+ }
414
+
415
+ currentIndex += 1;
416
+ });
417
+
418
+
419
+
420
+ // see: http://bl.ocks.org/mundhradevang/1387786
421
+ function fontSize(d,i) {
422
+ var size = yScale(1) / 3;
423
+ // var words = d.shortName.split(' ');
424
+ var word = d.shortName; // words[0];
425
+ var width = xScale(d.width+100);
426
+ var height = yScale(1);
427
+ var length = 0;
428
+ d3.select(this).style("font-size", size + "px").text(word);
429
+ while((size > 12.1) && ((this.getBBox().width >= width) || (this.getBBox().height >= height)))
430
+ {
431
+ size -= 0.1;
432
+ d3.select(this).style("font-size", size + "px");
433
+ }
434
+
435
+ d3.select(this).attr("dy", size);
436
+ }
437
+
438
+ svg.selectAll("g")
439
+ .data(data)
440
+ .enter()
441
+ .append("g")
442
+ .each(function(){
443
+ d3.select(this)
444
+ .append("rect")
445
+ .attr("x",function(d) { return xScale(d.x-1); })
446
+ .attr("y",function(d) { return yScale(maxY - d.y);})
447
+ .attr("width", function(d){return xScale(d.width);})
448
+ .attr("height", yScale(1))
449
+ .attr("fill", function(d){
450
+ var i = info[d.frame];
451
+ if(!i) {
452
+ info[d.frame] = i = {nodes: [], samples: [], color: color()};
453
+ }
454
+ i.nodes.push(this);
455
+ for(var j=0; j < d.width; j++){
456
+ i.samples.push(d.x + j);
457
+ }
458
+ return i.color;
459
+ })
460
+ .on("click", click)
461
+ .on("mouseover", mouseover)
462
+ .on("mouseout", mouseout)
463
+ .attr("cursor", "pointer");
464
+
465
+ d3.select(this)
466
+ .append("text")
467
+ .attr("x",function(d) { return xScale(d.x - 0.98); })
468
+ .attr("y",function(d) { return yScale(maxY - d.y);})
469
+ .on("click", click)
470
+ .on("mouseover", mouseover)
471
+ .on("mouseout", mouseout)
472
+ .each(fontSize)
473
+ .attr("cursor", "pointer")
474
+ .attr("display", "none");
475
+
476
+ });
477
+
478
+
479
+ // Samples may overlap on the same line
480
+ for (var r in info) {
481
+ if (info[r].samples) {
482
+ info[r].samples = info[r].samples.getUnique();
483
+ }
484
+ };
485
+
486
+
487
+ // render the legend
488
+ _.each(gemsSorted, function(gem){
489
+ var node = $("<div></div>")
490
+ .css("background-color", gem.color)
491
+ .text(gem.name + " " + samplePercent(gem.samples.length)) ;
492
+ $('.legend').append(node);
493
+ });
494
+
495
+
496
+
497
+ </script>
498
+ </body>
499
+ </html>