unageanu-jiji 1.1.4 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (233) hide show
  1. data/ChangeLog +24 -1
  2. data/README +0 -0
  3. data/base/shared_lib/moving_average.rb +34 -33
  4. data/base/shared_lib/system/cross.rb +76 -0
  5. data/base/shared_lib/system/position_manager.rb +160 -0
  6. data/base/shared_lib/system/signal.rb +347 -0
  7. data/html/css/datatable.css +4 -4
  8. data/html/css/default.css +57 -5
  9. data/html/css/treeview.css +205 -0
  10. data/html/img/bin_closed.png +0 -0
  11. data/html/img/bin_empty.png +0 -0
  12. data/html/img/button_add_small.gif +0 -0
  13. data/html/img/button_add_small_gray.gif +0 -0
  14. data/html/img/button_add_small_over.gif +0 -0
  15. data/html/img/button_mkcol.gif +0 -0
  16. data/html/img/button_mkcol_gray.gif +0 -0
  17. data/html/img/button_mkcol_over.gif +0 -0
  18. data/html/img/button_remove_small.gif +0 -0
  19. data/html/img/button_remove_small_gray.gif +0 -0
  20. data/html/img/button_remove_small_over.gif +0 -0
  21. data/html/img/button_rename.gif +0 -0
  22. data/html/img/button_rename_gray.gif +0 -0
  23. data/html/img/button_rename_over.gif +0 -0
  24. data/html/img/control_play.png +0 -0
  25. data/html/img/control_play_blue.png +0 -0
  26. data/html/img/folder.png +0 -0
  27. data/html/img/folder_brick.png +0 -0
  28. data/html/img/folder_user.png +0 -0
  29. data/html/{js/codepress/images → img}/line-numbers.png +0 -0
  30. data/html/img/page_white_ruby.png +0 -0
  31. data/html/img/sidebar_agent_edit.png +0 -0
  32. data/html/img/sidebar_agent_edit_over.png +0 -0
  33. data/html/img/sidebar_agent_edit_s.png +0 -0
  34. data/html/img/yui/treeview-sprite.gif +0 -0
  35. data/html/index.html +34 -18
  36. data/html/js/agent-editor/agent-editor-page.js +324 -0
  37. data/html/js/agent-editor/agent-editor.js +363 -0
  38. data/html/js/agent-editor/agent-list-tree.js +251 -0
  39. data/html/js/agent-selector.js +23 -28
  40. data/html/js/app.js +63 -91
  41. data/html/js/bt-create-page.js +25 -19
  42. data/html/js/container-min.js +1 -1
  43. data/html/js/container.js +944 -0
  44. data/html/js/edit_area/autocompletion.js +11 -13
  45. data/html/js/edit_area/edit_area.css +79 -40
  46. data/html/js/edit_area/edit_area.js +255 -226
  47. data/html/js/edit_area/edit_area_compressor.php +4 -4
  48. data/html/js/edit_area/edit_area_full.gz +0 -0
  49. data/html/js/edit_area/edit_area_full.js +31 -31
  50. data/html/js/edit_area/edit_area_full_with_plugins.gz +0 -0
  51. data/html/js/edit_area/edit_area_full_with_plugins.js +31 -31
  52. data/html/js/edit_area/edit_area_functions.js +448 -341
  53. data/html/js/edit_area/edit_area_loader.js +409 -397
  54. data/html/js/edit_area/elements_functions.js +120 -123
  55. data/html/js/edit_area/highlight.js +305 -197
  56. data/html/js/edit_area/images/goto.png +0 -0
  57. data/html/js/edit_area/images/help.png +0 -0
  58. data/html/js/edit_area/images/redo.png +0 -0
  59. data/html/js/edit_area/images/save.png +0 -0
  60. data/html/js/edit_area/images/search.png +0 -0
  61. data/html/js/edit_area/images/undo.png +0 -0
  62. data/html/js/edit_area/images/word_wrap.gif +0 -0
  63. data/html/js/edit_area/keyboard.js +5 -5
  64. data/html/js/edit_area/langs/bg.js +73 -0
  65. data/html/js/edit_area/langs/cs.js +2 -0
  66. data/html/js/edit_area/langs/de.js +2 -0
  67. data/html/js/edit_area/langs/dk.js +2 -0
  68. data/html/js/edit_area/langs/en.js +2 -0
  69. data/html/js/edit_area/langs/eo.js +2 -0
  70. data/html/js/edit_area/langs/es.js +2 -0
  71. data/html/js/edit_area/langs/fi.js +67 -0
  72. data/html/js/edit_area/langs/fr.js +2 -0
  73. data/html/js/edit_area/langs/hr.js +2 -0
  74. data/html/js/edit_area/langs/it.js +2 -0
  75. data/html/js/edit_area/langs/ja.js +2 -0
  76. data/html/js/edit_area/langs/mk.js +2 -0
  77. data/html/js/edit_area/langs/nl.js +2 -0
  78. data/html/js/edit_area/langs/pl.js +2 -0
  79. data/html/js/edit_area/langs/pt.js +2 -0
  80. data/html/js/edit_area/langs/ru.js +2 -0
  81. data/html/js/edit_area/langs/sk.js +2 -0
  82. data/html/js/edit_area/langs/zh.js +67 -0
  83. data/html/js/edit_area/manage_area.js +362 -205
  84. data/html/js/edit_area/plugins/charmap/langs/bg.js +12 -0
  85. data/html/js/edit_area/plugins/charmap/langs/zh.js +6 -0
  86. data/html/js/edit_area/plugins/test/langs/bg.js +10 -0
  87. data/html/js/edit_area/plugins/test/langs/zh.js +4 -0
  88. data/html/js/edit_area/reg_syntax/java.js +56 -0
  89. data/html/js/edit_area/reg_syntax/ruby.js +9 -9
  90. data/html/js/edit_area/reg_syntax.js +15 -13
  91. data/html/js/edit_area/regexp.js +36 -32
  92. data/html/js/edit_area/resize_area.js +43 -47
  93. data/html/js/edit_area/search_replace.js +29 -29
  94. data/html/js/edit_area/template.html +6 -4
  95. data/html/js/json-broker-client.js +23 -17
  96. data/html/js/result-page.js +107 -57
  97. data/html/js/rt-setting-page.js +38 -15
  98. data/html/js/sidebar.js +41 -27
  99. data/html/js/templates.js +167 -32
  100. data/html/js/utils.js +143 -7
  101. data/html/js/yui/treeview.js +3671 -0
  102. data/html/swf/chart.swf +0 -0
  103. data/html/test/agent_editor_spec.js +815 -0
  104. data/html/test/index.html +40 -0
  105. data/html/test/jsspec/JSSpec.css +224 -0
  106. data/html/test/jsspec/JSSpec.js +1549 -0
  107. data/html/test/jsspec/diff_match_patch.js +1 -0
  108. data/html/test/utils_spec.js +111 -0
  109. data/lib/jiji/agent/agent.rb +69 -12
  110. data/lib/jiji/agent/agent_manager.rb +18 -12
  111. data/lib/jiji/agent/agent_registry.rb +35 -121
  112. data/lib/jiji/collector.rb +16 -6
  113. data/lib/jiji/command.rb +46 -5
  114. data/lib/jiji/dao/file_system_dao.rb +158 -0
  115. data/lib/jiji/dao/timed_data_dao.rb +2 -0
  116. data/lib/jiji/dao/trade_result_dao.rb +1 -1
  117. data/lib/jiji/error.rb +24 -8
  118. data/lib/jiji/migration/migrator1_2_0.rb +67 -0
  119. data/lib/jiji/models.rb +82 -24
  120. data/lib/jiji/operator.rb +55 -51
  121. data/lib/jiji/output.rb +85 -29
  122. data/lib/jiji/output_manager.rb +84 -0
  123. data/lib/jiji/plugin/embedded/single_click_client.rb +2 -2
  124. data/lib/jiji/plugin/securities_plugin.rb +0 -1
  125. data/lib/jiji/process.rb +229 -208
  126. data/lib/jiji/process_manager.rb +190 -96
  127. data/lib/jiji/registry.rb +87 -19
  128. data/lib/jiji/server.rb +1 -0
  129. data/lib/jiji/service/agent_service.rb +147 -48
  130. data/lib/jiji/service/output_service.rb +37 -17
  131. data/lib/jiji/service/process_service.rb +3 -5
  132. data/lib/jiji/service/trade_result_service.rb +4 -5
  133. data/lib/jiji/util/file_lock.rb +4 -4
  134. data/lib/jiji/util/include_proxy.rb +17 -0
  135. data/lib/jiji/util/json_broker.rb +6 -4
  136. data/lib/jiji/util/util.rb +1 -1
  137. data/swf/chart/fx/chart/Chart.as +7 -0
  138. data/swf/chart/fx/chart/ui/graph/GraphManager.as +15 -2
  139. data/test/ProcessTest/agents/foo.rb +10 -0
  140. data/test/ProcessTest/conf/configuration.yaml +3 -0
  141. data/test/agent/agent_tests.rb +10 -0
  142. data/test/agent/test_AgentManager.rb +28 -12
  143. data/test/agent/test_AgentRegistry.rb +194 -99
  144. data/test/agent/test_PeriodicallyAgent.rb +1 -2
  145. data/test/agent/test_Permitter.rb +1 -2
  146. data/test/all_tests.rb +7 -19
  147. data/test/dao/dao_tests.rb +9 -0
  148. data/test/dao/test_FileSystemDao.rb +431 -0
  149. data/test/dao/test_RateDao.rb +5 -7
  150. data/test/dao/test_TradeResultDao.rb +1 -2
  151. data/test/migration/migration_tests.rb +10 -0
  152. data/test/migration/migrator1_2_0test_data/basic/out/M2NlOTA2ODEtZDdlNi00NWU1LWIwNDQtMjBmODY2ZGNkNzBj/56e75YuV5bmz5Z2H57ea/meta.yaml +8 -0
  153. data/test/migration/migrator1_2_0test_data/basic/out/MDVhYzcxMjYtMGFlMS00Mzk0LWEyNmUtYjVjZjgwNDA0ZmE2/56e75YuV5bmz5Z2H57ea/meta.yaml +8 -0
  154. data/test/migration/migrator1_2_0test_data/basic/out/MzA1YTk0NDgtNzhjNi00NDk3LTk2NTktYzE1ZjBhNzdiYjNj/56e75YuV5bmz5Z2H57ea/meta.yaml +8 -0
  155. data/test/migration/migrator1_2_0test_data/basic/out/YjRkOTI1MzEtZTM4MS00YjQwLTg1ZTQtMWFmZDRlNDUwMzBm/56e75YuV5bmz5Z2H57ea/meta.yaml +9 -0
  156. data/test/migration/migrator1_2_0test_data/basic/props.yaml +85 -0
  157. data/test/migration/migrator1_2_0test_data/illegal_props/out/M2NlOTA2ODEtZDdlNi00NWU1LWIwNDQtMjBmODY2ZGNkNzBj/56e75YuV5bmz5Z2H57ea/meta.yaml +8 -0
  158. data/test/migration/migrator1_2_0test_data/illegal_props/out/MDVhYzcxMjYtMGFlMS00Mzk0LWEyNmUtYjVjZjgwNDA0ZmE2/56e75YuV5bmz5Z2H57ea/meta.yaml +8 -0
  159. data/test/migration/migrator1_2_0test_data/illegal_props/out/MzA1YTk0NDgtNzhjNi00NDk3LTk2NTktYzE1ZjBhNzdiYjNj/56e75YuV5bmz5Z2H57ea/meta.yaml +8 -0
  160. data/test/migration/migrator1_2_0test_data/illegal_props/out/YjRkOTI1MzEtZTM4MS00YjQwLTg1ZTQtMWFmZDRlNDUwMzBm/56e75YuV5bmz5Z2H57ea/meta.yaml +9 -0
  161. data/test/migration/migrator1_2_0test_data/illegal_props/props.yaml +1 -0
  162. data/test/migration/migrator1_2_0test_data/no_outs/props.yaml +85 -0
  163. data/test/migration/migrator1_2_0test_data/no_props/out/M2NlOTA2ODEtZDdlNi00NWU1LWIwNDQtMjBmODY2ZGNkNzBj/56e75YuV5bmz5Z2H57ea/meta.yaml +8 -0
  164. data/test/migration/migrator1_2_0test_data/no_props/out/MDVhYzcxMjYtMGFlMS00Mzk0LWEyNmUtYjVjZjgwNDA0ZmE2/56e75YuV5bmz5Z2H57ea/meta.yaml +8 -0
  165. data/test/migration/migrator1_2_0test_data/no_props/out/MzA1YTk0NDgtNzhjNi00NDk3LTk2NTktYzE1ZjBhNzdiYjNj/56e75YuV5bmz5Z2H57ea/meta.yaml +8 -0
  166. data/test/migration/migrator1_2_0test_data/no_props/out/YjRkOTI1MzEtZTM4MS00YjQwLTg1ZTQtMWFmZDRlNDUwMzBm/56e75YuV5bmz5Z2H57ea/meta.yaml +9 -0
  167. data/test/migration/test_Migrator.rb +1 -1
  168. data/test/migration/test_Migrator1_0_3.rb +1 -1
  169. data/test/migration/test_Migrator1_1_0.rb +1 -1
  170. data/test/migration/test_Migrator1_2_0.rb +94 -0
  171. data/test/plugin/embedded/test_SingleClickClient.rb +1 -2
  172. data/test/plugin/plugin_tests.rb +8 -0
  173. data/test/plugin/test_Loader.rb +1 -1
  174. data/test/shared/rate.csv +144 -0
  175. data/test/shared/shared_tests.rb +9 -0
  176. data/test/shared/test_Cross.rb +144 -0
  177. data/test/shared/test_PositionManager.rb +285 -0
  178. data/test/shared/test_Signal.rb +65 -0
  179. data/test/test_Output.rb +28 -21
  180. data/test/test_OutputManager.rb +162 -0
  181. data/test/test_Output_registry.rb +6 -17
  182. data/test/test_Process.rb +434 -222
  183. data/test/test_ProcessManager.rb +458 -101
  184. data/test/test_utils.rb +71 -8
  185. data/test/util/test_BlockToSession.rb +1 -2
  186. data/test/util/test_CSV.rb +1 -2
  187. data/test/util/test_SynchronizeInterceptor.rb +1 -2
  188. data/test/util/util_tests.rb +9 -0
  189. metadata +127 -47
  190. data/html/js/agent-editor-page.js +0 -440
  191. data/html/js/codepress/codepress.css +0 -21
  192. data/html/js/codepress/codepress.html +0 -35
  193. data/html/js/codepress/codepress.js +0 -138
  194. data/html/js/codepress/engines/gecko.js +0 -293
  195. data/html/js/codepress/engines/khtml.js +0 -0
  196. data/html/js/codepress/engines/msie.js +0 -304
  197. data/html/js/codepress/engines/older.js +0 -0
  198. data/html/js/codepress/engines/opera.js +0 -260
  199. data/html/js/codepress/images/line-numbers.gif +0 -0
  200. data/html/js/codepress/index.html +0 -443
  201. data/html/js/codepress/languages/asp.css +0 -71
  202. data/html/js/codepress/languages/asp.js +0 -117
  203. data/html/js/codepress/languages/autoit.css +0 -13
  204. data/html/js/codepress/languages/autoit.js +0 -32
  205. data/html/js/codepress/languages/csharp.css +0 -9
  206. data/html/js/codepress/languages/csharp.js +0 -25
  207. data/html/js/codepress/languages/css.css +0 -10
  208. data/html/js/codepress/languages/css.js +0 -23
  209. data/html/js/codepress/languages/generic.css +0 -9
  210. data/html/js/codepress/languages/generic.js +0 -25
  211. data/html/js/codepress/languages/html.css +0 -13
  212. data/html/js/codepress/languages/html.js +0 -59
  213. data/html/js/codepress/languages/java.css +0 -7
  214. data/html/js/codepress/languages/java.js +0 -24
  215. data/html/js/codepress/languages/javascript.css +0 -8
  216. data/html/js/codepress/languages/javascript.js +0 -30
  217. data/html/js/codepress/languages/perl.css +0 -11
  218. data/html/js/codepress/languages/perl.js +0 -27
  219. data/html/js/codepress/languages/php.css +0 -12
  220. data/html/js/codepress/languages/php.js +0 -61
  221. data/html/js/codepress/languages/ruby.css +0 -10
  222. data/html/js/codepress/languages/ruby.js +0 -26
  223. data/html/js/codepress/languages/sql.css +0 -10
  224. data/html/js/codepress/languages/sql.js +0 -30
  225. data/html/js/codepress/languages/text.css +0 -5
  226. data/html/js/codepress/languages/text.js +0 -9
  227. data/html/js/codepress/languages/vbscript.css +0 -71
  228. data/html/js/codepress/languages/vbscript.js +0 -117
  229. data/html/js/codepress/languages/xsl.css +0 -15
  230. data/html/js/codepress/languages/xsl.js +0 -103
  231. data/html/js/codepress/license.txt +0 -458
  232. data/html/js/edit_area/images/Thumbs.db +0 -0
  233. data/test/plugin/test_gem/a/lib/jiji_plugin_test.rb +0 -6
@@ -0,0 +1 @@
1
+ function diff_match_patch(){this.Diff_Timeout=1.0;this.Diff_EditCost=4;this.Diff_DualThreshold=32;this.Match_Balance=0.5;this.Match_Threshold=0.5;this.Match_MinLength=100;this.Match_MaxLength=1000;this.Patch_Margin=4;function getMaxBits(){var maxbits=0;var oldi=1;var newi=2;while(oldi!=newi){maxbits++;oldi=newi;newi=newi<<1}return maxbits}this.Match_MaxBits=getMaxBits()}var DIFF_DELETE=-1;var DIFF_INSERT=1;var DIFF_EQUAL=0;diff_match_patch.prototype.diff_main=function(text1,text2,opt_checklines){if(text1==text2){return[[DIFF_EQUAL,text1]]}if(typeof opt_checklines=='undefined'){opt_checklines=true}var checklines=opt_checklines;var commonlength=this.diff_commonPrefix(text1,text2);var commonprefix=text1.substring(0,commonlength);text1=text1.substring(commonlength);text2=text2.substring(commonlength);commonlength=this.diff_commonSuffix(text1,text2);var commonsuffix=text1.substring(text1.length-commonlength);text1=text1.substring(0,text1.length-commonlength);text2=text2.substring(0,text2.length-commonlength);var diffs=this.diff_compute(text1,text2,checklines);if(commonprefix){diffs.unshift([DIFF_EQUAL,commonprefix])}if(commonsuffix){diffs.push([DIFF_EQUAL,commonsuffix])}this.diff_cleanupMerge(diffs);return diffs};diff_match_patch.prototype.diff_compute=function(text1,text2,checklines){var diffs;if(!text1){return[[DIFF_INSERT,text2]]}if(!text2){return[[DIFF_DELETE,text1]]}var longtext=text1.length>text2.length?text1:text2;var shorttext=text1.length>text2.length?text2:text1;var i=longtext.indexOf(shorttext);if(i!=-1){diffs=[[DIFF_INSERT,longtext.substring(0,i)],[DIFF_EQUAL,shorttext],[DIFF_INSERT,longtext.substring(i+shorttext.length)]];if(text1.length>text2.length){diffs[0][0]=diffs[2][0]=DIFF_DELETE}return diffs}longtext=shorttext=null;var hm=this.diff_halfMatch(text1,text2);if(hm){var text1_a=hm[0];var text1_b=hm[1];var text2_a=hm[2];var text2_b=hm[3];var mid_common=hm[4];var diffs_a=this.diff_main(text1_a,text2_a,checklines);var diffs_b=this.diff_main(text1_b,text2_b,checklines);return diffs_a.concat([[DIFF_EQUAL,mid_common]],diffs_b)}if(checklines&&text1.length+text2.length<250){checklines=false}var linearray;if(checklines){var a=this.diff_linesToChars(text1,text2);text1=a[0];text2=a[1];linearray=a[2]}diffs=this.diff_map(text1,text2);if(!diffs){diffs=[[DIFF_DELETE,text1],[DIFF_INSERT,text2]]}if(checklines){this.diff_charsToLines(diffs,linearray);this.diff_cleanupSemantic(diffs);diffs.push([DIFF_EQUAL,'']);var pointer=0;var count_delete=0;var count_insert=0;var text_delete='';var text_insert='';while(pointer<diffs.length){if(diffs[pointer][0]==DIFF_INSERT){count_insert++;text_insert+=diffs[pointer][1]}else if(diffs[pointer][0]==DIFF_DELETE){count_delete++;text_delete+=diffs[pointer][1]}else{if(count_delete>=1&&count_insert>=1){var a=this.diff_main(text_delete,text_insert,false);diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert);pointer=pointer-count_delete-count_insert;for(var j=a.length-1;j>=0;j--){diffs.splice(pointer,0,a[j])}pointer=pointer+a.length}count_insert=0;count_delete=0;text_delete='';text_insert=''}pointer++}diffs.pop()}return diffs};diff_match_patch.prototype.diff_linesToChars=function(text1,text2){var linearray=[];var linehash={};linearray.push('');function diff_linesToCharsMunge(text){var chars='';while(text){var i=text.indexOf('\n');if(i==-1){i=text.length}var line=text.substring(0,i+1);text=text.substring(i+1);if(linehash.hasOwnProperty?linehash.hasOwnProperty(line):(linehash[line]!==undefined)){chars+=String.fromCharCode(linehash[line])}else{linearray.push(line);linehash[line]=linearray.length-1;chars+=String.fromCharCode(linearray.length-1)}}return chars}var chars1=diff_linesToCharsMunge(text1);var chars2=diff_linesToCharsMunge(text2);return[chars1,chars2,linearray]};diff_match_patch.prototype.diff_charsToLines=function(diffs,linearray){for(var x=0;x<diffs.length;x++){var chars=diffs[x][1];var text=[];for(var y=0;y<chars.length;y++){text.push(linearray[chars.charCodeAt(y)])}diffs[x][1]=text.join('')}};diff_match_patch.prototype.diff_map=function(text1,text2){var ms_end=(new Date()).getTime()+this.Diff_Timeout*1000;var max_d=text1.length+text2.length-1;var doubleEnd=this.Diff_DualThreshold*2<max_d;var v_map1=[];var v_map2=[];var v1={};var v2={};v1[1]=0;v2[1]=0;var x,y;var footstep;var footsteps={};var done=false;var hasOwnProperty=!!(footsteps.hasOwnProperty);var front=(text1.length+text2.length)%2;for(var d=0;d<max_d;d++){if(this.Diff_Timeout>0&&(new Date()).getTime()>ms_end){return null}v_map1[d]={};for(var k=-d;k<=d;k+=2){if(k==-d||k!=d&&v1[k-1]<v1[k+1]){x=v1[k+1]}else{x=v1[k-1]+1}y=x-k;if(doubleEnd){footstep=x+','+y;if(front&&(hasOwnProperty?footsteps.hasOwnProperty(footstep):(footsteps[footstep]!==undefined))){done=true}if(!front){footsteps[footstep]=d}}while(!done&&x<text1.length&&y<text2.length&&text1.charAt(x)==text2.charAt(y)){x++;y++;if(doubleEnd){footstep=x+','+y;if(front&&(hasOwnProperty?footsteps.hasOwnProperty(footstep):(footsteps[footstep]!==undefined))){done=true}if(!front){footsteps[footstep]=d}}}v1[k]=x;v_map1[d][x+','+y]=true;if(x==text1.length&&y==text2.length){return this.diff_path1(v_map1,text1,text2)}else if(done){v_map2=v_map2.slice(0,footsteps[footstep]+1);var a=this.diff_path1(v_map1,text1.substring(0,x),text2.substring(0,y));return a.concat(this.diff_path2(v_map2,text1.substring(x),text2.substring(y)))}}if(doubleEnd){v_map2[d]={};for(var k=-d;k<=d;k+=2){if(k==-d||k!=d&&v2[k-1]<v2[k+1]){x=v2[k+1]}else{x=v2[k-1]+1}y=x-k;footstep=(text1.length-x)+','+(text2.length-y);if(!front&&(hasOwnProperty?footsteps.hasOwnProperty(footstep):(footsteps[footstep]!==undefined))){done=true}if(front){footsteps[footstep]=d}while(!done&&x<text1.length&&y<text2.length&&text1.charAt(text1.length-x-1)==text2.charAt(text2.length-y-1)){x++;y++;footstep=(text1.length-x)+','+(text2.length-y);if(!front&&(hasOwnProperty?footsteps.hasOwnProperty(footstep):(footsteps[footstep]!==undefined))){done=true}if(front){footsteps[footstep]=d}}v2[k]=x;v_map2[d][x+','+y]=true;if(done){v_map1=v_map1.slice(0,footsteps[footstep]+1);var a=this.diff_path1(v_map1,text1.substring(0,text1.length-x),text2.substring(0,text2.length-y));return a.concat(this.diff_path2(v_map2,text1.substring(text1.length-x),text2.substring(text2.length-y)))}}}}return null};diff_match_patch.prototype.diff_path1=function(v_map,text1,text2){var path=[];var x=text1.length;var y=text2.length;var last_op=null;for(var d=v_map.length-2;d>=0;d--){while(1){if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty((x-1)+','+y):(v_map[d][(x-1)+','+y]!==undefined)){x--;if(last_op===DIFF_DELETE){path[0][1]=text1.charAt(x)+path[0][1]}else{path.unshift([DIFF_DELETE,text1.charAt(x)])}last_op=DIFF_DELETE;break}else if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty(x+','+(y-1)):(v_map[d][x+','+(y-1)]!==undefined)){y--;if(last_op===DIFF_INSERT){path[0][1]=text2.charAt(y)+path[0][1]}else{path.unshift([DIFF_INSERT,text2.charAt(y)])}last_op=DIFF_INSERT;break}else{x--;y--;if(last_op===DIFF_EQUAL){path[0][1]=text1.charAt(x)+path[0][1]}else{path.unshift([DIFF_EQUAL,text1.charAt(x)])}last_op=DIFF_EQUAL}}}return path};diff_match_patch.prototype.diff_path2=function(v_map,text1,text2){var path=[];var x=text1.length;var y=text2.length;var last_op=null;for(var d=v_map.length-2;d>=0;d--){while(1){if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty((x-1)+','+y):(v_map[d][(x-1)+','+y]!==undefined)){x--;if(last_op===DIFF_DELETE){path[path.length-1][1]+=text1.charAt(text1.length-x-1)}else{path.push([DIFF_DELETE,text1.charAt(text1.length-x-1)])}last_op=DIFF_DELETE;break}else if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty(x+','+(y-1)):(v_map[d][x+','+(y-1)]!==undefined)){y--;if(last_op===DIFF_INSERT){path[path.length-1][1]+=text2.charAt(text2.length-y-1)}else{path.push([DIFF_INSERT,text2.charAt(text2.length-y-1)])}last_op=DIFF_INSERT;break}else{x--;y--;if(last_op===DIFF_EQUAL){path[path.length-1][1]+=text1.charAt(text1.length-x-1)}else{path.push([DIFF_EQUAL,text1.charAt(text1.length-x-1)])}last_op=DIFF_EQUAL}}}return path};diff_match_patch.prototype.diff_commonPrefix=function(text1,text2){if(!text1||!text2||text1.charCodeAt(0)!==text2.charCodeAt(0)){return 0}var pointermin=0;var pointermax=Math.min(text1.length,text2.length);var pointermid=pointermax;var pointerstart=0;while(pointermin<pointermid){if(text1.substring(pointerstart,pointermid)==text2.substring(pointerstart,pointermid)){pointermin=pointermid;pointerstart=pointermin}else{pointermax=pointermid}pointermid=Math.floor((pointermax-pointermin)/2+pointermin)}return pointermid};diff_match_patch.prototype.diff_commonSuffix=function(text1,text2){if(!text1||!text2||text1.charCodeAt(text1.length-1)!==text2.charCodeAt(text2.length-1)){return 0}var pointermin=0;var pointermax=Math.min(text1.length,text2.length);var pointermid=pointermax;var pointerend=0;while(pointermin<pointermid){if(text1.substring(text1.length-pointermid,text1.length-pointerend)==text2.substring(text2.length-pointermid,text2.length-pointerend)){pointermin=pointermid;pointerend=pointermin}else{pointermax=pointermid}pointermid=Math.floor((pointermax-pointermin)/2+pointermin)}return pointermid};diff_match_patch.prototype.diff_halfMatch=function(text1,text2){var longtext=text1.length>text2.length?text1:text2;var shorttext=text1.length>text2.length?text2:text1;if(longtext.length<10||shorttext.length<1){return null}var dmp=this;function diff_halfMatchI(longtext,shorttext,i){var seed=longtext.substring(i,i+Math.floor(longtext.length/4));var j=-1;var best_common='';var best_longtext_a,best_longtext_b,best_shorttext_a,best_shorttext_b;while((j=shorttext.indexOf(seed,j+1))!=-1){var prefixLength=dmp.diff_commonPrefix(longtext.substring(i),shorttext.substring(j));var suffixLength=dmp.diff_commonSuffix(longtext.substring(0,i),shorttext.substring(0,j));if(best_common.length<suffixLength+prefixLength){best_common=shorttext.substring(j-suffixLength,j)+shorttext.substring(j,j+prefixLength);best_longtext_a=longtext.substring(0,i-suffixLength);best_longtext_b=longtext.substring(i+prefixLength);best_shorttext_a=shorttext.substring(0,j-suffixLength);best_shorttext_b=shorttext.substring(j+prefixLength)}}if(best_common.length>=longtext.length/2){return[best_longtext_a,best_longtext_b,best_shorttext_a,best_shorttext_b,best_common]}else{return null}}var hm1=diff_halfMatchI(longtext,shorttext,Math.ceil(longtext.length/4));var hm2=diff_halfMatchI(longtext,shorttext,Math.ceil(longtext.length/2));var hm;if(!hm1&&!hm2){return null}else if(!hm2){hm=hm1}else if(!hm1){hm=hm2}else{hm=hm1[4].length>hm2[4].length?hm1:hm2}var text1_a,text1_b,text2_a,text2_b;if(text1.length>text2.length){text1_a=hm[0];text1_b=hm[1];text2_a=hm[2];text2_b=hm[3]}else{text2_a=hm[0];text2_b=hm[1];text1_a=hm[2];text1_b=hm[3]}var mid_common=hm[4];return[text1_a,text1_b,text2_a,text2_b,mid_common]};diff_match_patch.prototype.diff_cleanupSemantic=function(diffs){var changes=false;var equalities=[];var lastequality=null;var pointer=0;var length_changes1=0;var length_changes2=0;while(pointer<diffs.length){if(diffs[pointer][0]==DIFF_EQUAL){equalities.push(pointer);length_changes1=length_changes2;length_changes2=0;lastequality=diffs[pointer][1]}else{length_changes2+=diffs[pointer][1].length;if(lastequality!==null&&(lastequality.length<=length_changes1)&&(lastequality.length<=length_changes2)){diffs.splice(equalities[equalities.length-1],0,[DIFF_DELETE,lastequality]);diffs[equalities[equalities.length-1]+1][0]=DIFF_INSERT;equalities.pop();equalities.pop();pointer=equalities.length?equalities[equalities.length-1]:-1;length_changes1=0;length_changes2=0;lastequality=null;changes=true}}pointer++}if(changes){this.diff_cleanupMerge(diffs)}this.diff_cleanupSemanticLossless(diffs)};diff_match_patch.prototype.diff_cleanupSemanticLossless=function(diffs){function diff_cleanupSemanticScore(one,two,three){var whitespace=/\s/;var score=0;if(one.charAt(one.length-1).match(whitespace)||two.charAt(0).match(whitespace)){score++}if(two.charAt(two.length-1).match(whitespace)||three.charAt(0).match(whitespace)){score++}return score}var pointer=1;while(pointer<diffs.length-1){if(diffs[pointer-1][0]==DIFF_EQUAL&&diffs[pointer+1][0]==DIFF_EQUAL){var equality1=diffs[pointer-1][1];var edit=diffs[pointer][1];var equality2=diffs[pointer+1][1];var commonOffset=this.diff_commonSuffix(equality1,edit);if(commonOffset){var commonString=edit.substring(edit.length-commonOffset);equality1=equality1.substring(0,equality1.length-commonOffset);edit=commonString+edit.substring(0,edit.length-commonOffset);equality2=commonString+equality2}var bestEquality1=equality1;var bestEdit=edit;var bestEquality2=equality2;var bestScore=diff_cleanupSemanticScore(equality1,edit,equality2);while(edit.charAt(0)===equality2.charAt(0)){equality1+=edit.charAt(0);edit=edit.substring(1)+equality2.charAt(0);equality2=equality2.substring(1);var score=diff_cleanupSemanticScore(equality1,edit,equality2);if(score>=bestScore){bestScore=score;bestEquality1=equality1;bestEdit=edit;bestEquality2=equality2}}if(diffs[pointer-1][1]!=bestEquality1){diffs[pointer-1][1]=bestEquality1;diffs[pointer][1]=bestEdit;diffs[pointer+1][1]=bestEquality2}}pointer++}};diff_match_patch.prototype.diff_cleanupEfficiency=function(diffs){var changes=false;var equalities=[];var lastequality='';var pointer=0;var pre_ins=false;var pre_del=false;var post_ins=false;var post_del=false;while(pointer<diffs.length){if(diffs[pointer][0]==DIFF_EQUAL){if(diffs[pointer][1].length<this.Diff_EditCost&&(post_ins||post_del)){equalities.push(pointer);pre_ins=post_ins;pre_del=post_del;lastequality=diffs[pointer][1]}else{equalities=[];lastequality=''}post_ins=post_del=false}else{if(diffs[pointer][0]==DIFF_DELETE){post_del=true}else{post_ins=true}if(lastequality&&((pre_ins&&pre_del&&post_ins&&post_del)||((lastequality.length<this.Diff_EditCost/2)&&(pre_ins+pre_del+post_ins+post_del)==3))){diffs.splice(equalities[equalities.length-1],0,[DIFF_DELETE,lastequality]);diffs[equalities[equalities.length-1]+1][0]=DIFF_INSERT;equalities.pop();lastequality='';if(pre_ins&&pre_del){post_ins=post_del=true;equalities=[]}else{equalities.pop();pointer=equalities.length?equalities[equalities.length-1]:-1;post_ins=post_del=false}changes=true}}pointer++}if(changes){this.diff_cleanupMerge(diffs)}};diff_match_patch.prototype.diff_cleanupMerge=function(diffs){diffs.push([DIFF_EQUAL,'']);var pointer=0;var count_delete=0;var count_insert=0;var text_delete='';var text_insert='';var commonlength;while(pointer<diffs.length){if(diffs[pointer][0]==DIFF_INSERT){count_insert++;text_insert+=diffs[pointer][1];pointer++}else if(diffs[pointer][0]==DIFF_DELETE){count_delete++;text_delete+=diffs[pointer][1];pointer++}else{if(count_delete!==0||count_insert!==0){if(count_delete!==0&&count_insert!==0){commonlength=this.diff_commonPrefix(text_insert,text_delete);if(commonlength!==0){if((pointer-count_delete-count_insert)>0&&diffs[pointer-count_delete-count_insert-1][0]==DIFF_EQUAL){diffs[pointer-count_delete-count_insert-1][1]+=text_insert.substring(0,commonlength)}else{diffs.splice(0,0,[DIFF_EQUAL,text_insert.substring(0,commonlength)]);pointer++}text_insert=text_insert.substring(commonlength);text_delete=text_delete.substring(commonlength)}commonlength=this.diff_commonSuffix(text_insert,text_delete);if(commonlength!==0){diffs[pointer][1]=text_insert.substring(text_insert.length-commonlength)+diffs[pointer][1];text_insert=text_insert.substring(0,text_insert.length-commonlength);text_delete=text_delete.substring(0,text_delete.length-commonlength)}}if(count_delete===0){diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert,[DIFF_INSERT,text_insert])}else if(count_insert===0){diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert,[DIFF_DELETE,text_delete])}else{diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert,[DIFF_DELETE,text_delete],[DIFF_INSERT,text_insert])}pointer=pointer-count_delete-count_insert+(count_delete?1:0)+(count_insert?1:0)+1}else if(pointer!==0&&diffs[pointer-1][0]==DIFF_EQUAL){diffs[pointer-1][1]+=diffs[pointer][1];diffs.splice(pointer,1)}else{pointer++}count_insert=0;count_delete=0;text_delete='';text_insert=''}}if(diffs[diffs.length-1][1]===''){diffs.pop()}var changes=false;pointer=1;while(pointer<diffs.length-1){if(diffs[pointer-1][0]==DIFF_EQUAL&&diffs[pointer+1][0]==DIFF_EQUAL){if(diffs[pointer][1].substring(diffs[pointer][1].length-diffs[pointer-1][1].length)==diffs[pointer-1][1]){diffs[pointer][1]=diffs[pointer-1][1]+diffs[pointer][1].substring(0,diffs[pointer][1].length-diffs[pointer-1][1].length);diffs[pointer+1][1]=diffs[pointer-1][1]+diffs[pointer+1][1];diffs.splice(pointer-1,1);changes=true}else if(diffs[pointer][1].substring(0,diffs[pointer+1][1].length)==diffs[pointer+1][1]){diffs[pointer-1][1]+=diffs[pointer+1][1];diffs[pointer][1]=diffs[pointer][1].substring(diffs[pointer+1][1].length)+diffs[pointer+1][1];diffs.splice(pointer+1,1);changes=true}}pointer++}if(changes){this.diff_cleanupMerge(diffs)}};diff_match_patch.prototype.diff_addIndex=function(diffs){var i=0;for(var x=0;x<diffs.length;x++){diffs[x].push(i);if(diffs[x][0]!==DIFF_DELETE){i+=diffs[x][1].length}}};diff_match_patch.prototype.diff_xIndex=function(diffs,loc){var chars1=0;var chars2=0;var last_chars1=0;var last_chars2=0;var x;for(x=0;x<diffs.length;x++){if(diffs[x][0]!==DIFF_INSERT){chars1+=diffs[x][1].length}if(diffs[x][0]!==DIFF_DELETE){chars2+=diffs[x][1].length}if(chars1>loc){break}last_chars1=chars1;last_chars2=chars2}if(diffs.length!=x&&diffs[x][0]===DIFF_DELETE){return last_chars2}return last_chars2+(loc-last_chars1)};diff_match_patch.prototype.diff_prettyHtml=function(diffs){this.diff_addIndex(diffs);var html=[];for(var x=0;x<diffs.length;x++){var m=diffs[x][0];var t=diffs[x][1];var i=diffs[x][2];t=t.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');t=t.replace(/\n/g,'&para;<BR>');if(m===DIFF_DELETE){html.push('<DEL STYLE="background:#FFE6E6;" TITLE="i=',i,'">',t,'</DEL>')}else if(m===DIFF_INSERT){html.push('<INS STYLE="background:#E6FFE6;" TITLE="i=',i,'">',t,'</INS>')}else{html.push('<SPAN TITLE="i=',i,'">',t,'</SPAN>')}}return html.join('')};diff_match_patch.prototype.diff_text1=function(diffs){var txt=[];for(var x=0;x<diffs.length;x++){if(diffs[x][0]!==DIFF_INSERT){txt.push(diffs[x][1])}}return txt.join('')};diff_match_patch.prototype.diff_text2=function(diffs){var txt=[];for(var x=0;x<diffs.length;x++){if(diffs[x][0]!==DIFF_DELETE){txt.push(diffs[x][1])}}return txt.join('')};diff_match_patch.prototype.diff_toDelta=function(diffs){var txt=[];for(var x=0;x<diffs.length;x++){switch(diffs[x][0]){case DIFF_DELETE:txt.push('-',diffs[x][1].length,'\t');break;case DIFF_EQUAL:txt.push('=',diffs[x][1].length,'\t');break;case DIFF_INSERT:txt.push('+',encodeURI(diffs[x][1]),'\t');break;default:alert('Invalid diff operation in diff_toDelta()')}}return txt.join('').replace(/%20/g,' ')};diff_match_patch.prototype.diff_fromDelta=function(text1,delta){var diffs=[];var pointer=0;var tokens=delta.split(/\t/g);for(var x=0;x<tokens.length;x++){var param=tokens[x].substring(1);switch(tokens[x].charAt(0)){case'-':case'=':var n=parseInt(param,10);if(isNaN(n)||n<0){alert('Invalid number in diff_fromDelta()')}else{var text=text1.substring(pointer,pointer+=n);if(tokens[x].charAt(0)=='='){diffs.push([DIFF_EQUAL,text])}else{diffs.push([DIFF_DELETE,text])}}break;case'+':diffs.push([DIFF_INSERT,decodeURI(param)]);break;default:if(tokens[x]){alert('Invalid diff operation in diff_fromDelta()')}}}if(pointer!=text1.length){alert('Text length mismatch in diff_fromDelta()')}return diffs};diff_match_patch.prototype.match_main=function(text,pattern,loc){loc=Math.max(0,Math.min(loc,text.length-pattern.length));if(text==pattern){return 0}else if(text.length===0){return null}else if(text.substring(loc,loc+pattern.length)==pattern){return loc}else{return this.match_bitap(text,pattern,loc)}};diff_match_patch.prototype.match_bitap=function(text,pattern,loc){if(pattern.length>this.Match_MaxBits){return alert('Pattern too long for this browser.')}var s=this.match_alphabet(pattern);var score_text_length=text.length;score_text_length=Math.max(score_text_length,this.Match_MinLength);score_text_length=Math.min(score_text_length,this.Match_MaxLength);var dmp=this;function match_bitapScore(e,x){var d=Math.abs(loc-x);return(e/pattern.length/dmp.Match_Balance)+(d/score_text_length/(1.0-dmp.Match_Balance))}var score_threshold=this.Match_Threshold;var best_loc=text.indexOf(pattern,loc);if(best_loc!=-1){score_threshold=Math.min(match_bitapScore(0,best_loc),score_threshold)}best_loc=text.lastIndexOf(pattern,loc+pattern.length);if(best_loc!=-1){score_threshold=Math.min(match_bitapScore(0,best_loc),score_threshold)}var matchmask=1<<(pattern.length-1);best_loc=null;var bin_min,bin_mid;var bin_max=Math.max(loc+loc,text.length);var last_rd;for(var d=0;d<pattern.length;d++){var rd=Array(text.length);bin_min=loc;bin_mid=bin_max;while(bin_min<bin_mid){if(match_bitapScore(d,bin_mid)<score_threshold){bin_min=bin_mid}else{bin_max=bin_mid}bin_mid=Math.floor((bin_max-bin_min)/2+bin_min)}bin_max=bin_mid;var start=Math.max(0,loc-(bin_mid-loc)-1);var finish=Math.min(text.length-1,pattern.length+bin_mid);if(text.charAt(finish)==pattern.charAt(pattern.length-1)){rd[finish]=(1<<(d+1))-1}else{rd[finish]=(1<<d)-1}for(var j=finish-1;j>=start;j--){if(d===0){rd[j]=((rd[j+1]<<1)|1)&s[text.charAt(j)]}else{rd[j]=((rd[j+1]<<1)|1)&s[text.charAt(j)]|((last_rd[j+1]<<1)|1)|((last_rd[j]<<1)|1)|last_rd[j+1]}if(rd[j]&matchmask){var score=match_bitapScore(d,j);if(score<=score_threshold){score_threshold=score;best_loc=j;if(j>loc){start=Math.max(0,loc-(j-loc))}else{break}}}}if(match_bitapScore(d+1,loc)>score_threshold){break}last_rd=rd}return best_loc};diff_match_patch.prototype.match_alphabet=function(pattern){var s=Object();for(var i=0;i<pattern.length;i++){s[pattern.charAt(i)]=0}for(var i=0;i<pattern.length;i++){s[pattern.charAt(i)]|=1<<(pattern.length-i-1)}return s};diff_match_patch.prototype.patch_addContext=function(patch,text){var pattern=text.substring(patch.start2,patch.start2+patch.length1);var padding=0;while(text.indexOf(pattern)!=text.lastIndexOf(pattern)&&pattern.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin){padding+=this.Patch_Margin;pattern=text.substring(patch.start2-padding,patch.start2+patch.length1+padding)}padding+=this.Patch_Margin;var prefix=text.substring(patch.start2-padding,patch.start2);if(prefix!==''){patch.diffs.unshift([DIFF_EQUAL,prefix])}var suffix=text.substring(patch.start2+patch.length1,patch.start2+patch.length1+padding);if(suffix!==''){patch.diffs.push([DIFF_EQUAL,suffix])}patch.start1-=prefix.length;patch.start2-=prefix.length;patch.length1+=prefix.length+suffix.length;patch.length2+=prefix.length+suffix.length};diff_match_patch.prototype.patch_make=function(text1,text2,opt_diffs){var diffs;if(typeof opt_diffs!='undefined'){diffs=opt_diffs}else{diffs=this.diff_main(text1,text2,true);if(diffs.length>2){this.diff_cleanupSemantic(diffs);this.diff_cleanupEfficiency(diffs)}}if(diffs.length===0){return[]}var patches=[];var patch=new patch_obj();var char_count1=0;var char_count2=0;var prepatch_text=text1;var postpatch_text=text1;for(var x=0;x<diffs.length;x++){var diff_type=diffs[x][0];var diff_text=diffs[x][1];if(patch.diffs.length===0&&diff_type!==DIFF_EQUAL){patch.start1=char_count1;patch.start2=char_count2}if(diff_type===DIFF_INSERT){patch.diffs.push(diffs[x]);patch.length2+=diff_text.length;postpatch_text=postpatch_text.substring(0,char_count2)+diff_text+postpatch_text.substring(char_count2)}else if(diff_type===DIFF_DELETE){patch.length1+=diff_text.length;patch.diffs.push(diffs[x]);postpatch_text=postpatch_text.substring(0,char_count2)+postpatch_text.substring(char_count2+diff_text.length)}else if(diff_type===DIFF_EQUAL&&diff_text.length<=2*this.Patch_Margin&&patch.diffs.length!==0&&diffs.length!=x+1){patch.diffs.push(diffs[x]);patch.length1+=diff_text.length;patch.length2+=diff_text.length}if(diff_type===DIFF_EQUAL&&diff_text.length>=2*this.Patch_Margin){if(patch.diffs.length!==0){this.patch_addContext(patch,prepatch_text);patches.push(patch);patch=new patch_obj();prepatch_text=postpatch_text}}if(diff_type!==DIFF_INSERT){char_count1+=diff_text.length}if(diff_type!==DIFF_DELETE){char_count2+=diff_text.length}}if(patch.diffs.length!==0){this.patch_addContext(patch,prepatch_text);patches.push(patch)}return patches};diff_match_patch.prototype.patch_apply=function(patches,text){this.patch_splitMax(patches);var results=[];var delta=0;for(var x=0;x<patches.length;x++){var expected_loc=patches[x].start2+delta;var text1=this.diff_text1(patches[x].diffs);var start_loc=this.match_main(text,text1,expected_loc);if(start_loc===null){results.push(false)}else{results.push(true);delta=start_loc-expected_loc;var text2=text.substring(start_loc,start_loc+text1.length);if(text1==text2){text=text.substring(0,start_loc)+this.diff_text2(patches[x].diffs)+text.substring(start_loc+text1.length)}else{var diffs=this.diff_main(text1,text2,false);this.diff_cleanupSemanticLossless(diffs);var index1=0;var index2;for(var y=0;y<patches[x].diffs.length;y++){var mod=patches[x].diffs[y];if(mod[0]!==DIFF_EQUAL){index2=this.diff_xIndex(diffs,index1)}if(mod[0]===DIFF_INSERT){text=text.substring(0,start_loc+index2)+mod[1]+text.substring(start_loc+index2)}else if(mod[0]===DIFF_DELETE){text=text.substring(0,start_loc+index2)+text.substring(start_loc+this.diff_xIndex(diffs,index1+mod[1].length))}if(mod[0]!==DIFF_DELETE){index1+=mod[1].length}}}}}return[text,results]};diff_match_patch.prototype.patch_splitMax=function(patches){for(var x=0;x<patches.length;x++){if(patches[x].length1>this.Match_MaxBits){var bigpatch=patches[x];patches.splice(x,1);var patch_size=this.Match_MaxBits;var start1=bigpatch.start1;var start2=bigpatch.start2;var precontext='';while(bigpatch.diffs.length!==0){var patch=new patch_obj();var empty=true;patch.start1=start1-precontext.length;patch.start2=start2-precontext.length;if(precontext!==''){patch.length1=patch.length2=precontext.length;patch.diffs.push([DIFF_EQUAL,precontext])}while(bigpatch.diffs.length!==0&&patch.length1<patch_size-this.Patch_Margin){var diff_type=bigpatch.diffs[0][0];var diff_text=bigpatch.diffs[0][1];if(diff_type===DIFF_INSERT){patch.length2+=diff_text.length;start2+=diff_text.length;patch.diffs.push(bigpatch.diffs.shift());empty=false}else{diff_text=diff_text.substring(0,patch_size-patch.length1-this.Patch_Margin);patch.length1+=diff_text.length;start1+=diff_text.length;if(diff_type===DIFF_EQUAL){patch.length2+=diff_text.length;start2+=diff_text.length}else{empty=false}patch.diffs.push([diff_type,diff_text]);if(diff_text==bigpatch.diffs[0][1]){bigpatch.diffs.shift()}else{bigpatch.diffs[0][1]=bigpatch.diffs[0][1].substring(diff_text.length)}}}precontext=this.diff_text2(patch.diffs);precontext=precontext.substring(precontext.length-this.Patch_Margin);var postcontext=this.diff_text1(bigpatch.diffs).substring(0,this.Patch_Margin);if(postcontext!==''){patch.length1+=postcontext.length;patch.length2+=postcontext.length;if(patch.diffs.length!==0&&patch.diffs[patch.diffs.length-1][0]===DIFF_EQUAL){patch.diffs[patch.diffs.length-1][1]+=postcontext}else{patch.diffs.push([DIFF_EQUAL,postcontext])}}if(!empty){patches.splice(x++,0,patch)}}}}};diff_match_patch.prototype.patch_toText=function(patches){var text=[];for(var x=0;x<patches.length;x++){text.push(patches[x])}return text.join('')};diff_match_patch.prototype.patch_fromText=function(textline){var patches=[];var text=textline.split('\n');while(text.length!==0){var m=text[0].match(/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/);if(!m){return alert('Invalid patch string:\n'+text[0])}var patch=new patch_obj();patches.push(patch);patch.start1=parseInt(m[1],10);if(m[2]===''){patch.start1--;patch.length1=1}else if(m[2]=='0'){patch.length1=0}else{patch.start1--;patch.length1=parseInt(m[2],10)}patch.start2=parseInt(m[3],10);if(m[4]===''){patch.start2--;patch.length2=1}else if(m[4]=='0'){patch.length2=0}else{patch.start2--;patch.length2=parseInt(m[4],10)}text.shift();while(text.length!==0){var sign=text[0].charAt(0);var line=decodeURIComponent(text[0].substring(1));if(sign=='-'){patch.diffs.push([DIFF_DELETE,line])}else if(sign=='+'){patch.diffs.push([DIFF_INSERT,line])}else if(sign==' '){patch.diffs.push([DIFF_EQUAL,line])}else if(sign=='@'){break}else if(sign===''){}else{return alert('Invalid patch mode: "'+sign+'"\n'+line)}text.shift()}}return patches};function patch_obj(){this.diffs=[];this.start1=null;this.start2=null;this.length1=0;this.length2=0}patch_obj.prototype.toString=function(){var coords1,coords2;if(this.length1===0){coords1=this.start1+',0'}else if(this.length1==1){coords1=this.start1+1}else{coords1=(this.start1+1)+','+this.length1}if(this.length2===0){coords2=this.start2+',0'}else if(this.length2==1){coords2=this.start2+1}else{coords2=(this.start2+1)+','+this.length2}var txt=['@@ -',coords1,' +',coords2,' @@\n'];for(var x=0;x<this.diffs.length;x++){switch(this.diffs[x][0]){case DIFF_DELETE:txt.push('-');break;case DIFF_EQUAL:txt.push(' ');break;case DIFF_INSERT:txt.push('+');break;default:alert('Invalid diff operation in patch_obj.toString()')}txt.push(encodeURI(this.diffs[x][1]),'\n')}return txt.join('').replace(/%20/g,' ')};
@@ -0,0 +1,111 @@
1
+
2
+ describe('util.PathUtils#basenameの動作確認', {
3
+ '"aaa/bbb.txt" → "bbb.txt" ': function() {
4
+ value_of(util.PathUtils.basename("aaa/bbb.txt")).should_be("bbb.txt");
5
+ },
6
+ '"/aaa/ccc/bbb" → "bbb" ': function() {
7
+ value_of(util.PathUtils.basename("/aaa/ccc/bbb")).should_be("bbb");
8
+ },
9
+ '"aaa/日本語" → "日本語" ': function() {
10
+ value_of(util.PathUtils.basename("aaa/日本語")).should_be("日本語");
11
+ },
12
+ '"日本語" (スラッシュを含まない) → "日本語" ': function() {
13
+ value_of(util.PathUtils.basename("日本語")).should_be("日本語");
14
+ },
15
+ '"日本語/" (スラッシュが末尾) → "" ': function() {
16
+ value_of(util.PathUtils.basename("日本語/")).should_be("");
17
+ },
18
+ '"/" (スラッシュのみ) → "" ': function() {
19
+ value_of(util.PathUtils.basename("/")).should_be("");
20
+ },
21
+ '"" (空文字列) → "" ': function() {
22
+ value_of(util.PathUtils.basename("")).should_be("");
23
+ },
24
+ 'null → "" ': function() {
25
+ value_of(util.PathUtils.basename(null)).should_be("");
26
+ },
27
+ 'undefined → "" ': function() {
28
+ value_of(util.PathUtils.basename(undefined)).should_be("");
29
+ }
30
+ });
31
+
32
+ describe('util.PathUtils#dirnameの動作確認', {
33
+ '"aaa/bbb.txt" → "aaa" ': function() {
34
+ value_of(util.PathUtils.dirname("aaa/bbb.txt")).should_be("aaa");
35
+ },
36
+ '"/aaa/ccc/bbb" → "/aaa/ccc" ': function() {
37
+ value_of(util.PathUtils.dirname("/aaa/ccc/bbb")).should_be("/aaa/ccc");
38
+ },
39
+ '"/a/日本語/日本語" → "/a/日本語" ': function() {
40
+ value_of(util.PathUtils.dirname("/a/日本語/日本語")).should_be("/a/日本語");
41
+ },
42
+ '"日本語" (スラッシュを含まない) → "" ': function() {
43
+ value_of(util.PathUtils.dirname("日本語")).should_be("");
44
+ },
45
+ '"日本語/" (スラッシュが末尾) → "" ': function() {
46
+ value_of(util.PathUtils.dirname("日本語/")).should_be("日本語");
47
+ },
48
+ '"/" (スラッシュのみ) → "" ': function() {
49
+ value_of(util.PathUtils.dirname("/")).should_be("");
50
+ },
51
+ '"" (空文字列) → "" ': function() {
52
+ value_of(util.PathUtils.dirname("")).should_be("");
53
+ },
54
+ 'null → "" ': function() {
55
+ value_of(util.PathUtils.dirname(null)).should_be("");
56
+ },
57
+ 'undefined → "" ': function() {
58
+ value_of(util.PathUtils.dirname(undefined)).should_be("");
59
+ }
60
+ });
61
+
62
+ describe('util.PathUtils#isChildの動作確認', {
63
+ 'path:"aaa/bbb/ccc", dir:"aaa/bbb", → true ': function() {
64
+ value_of(util.PathUtils.isChild("aaa/bbb/ccc", "aaa/bbb")).should_be(true);
65
+ },
66
+ 'path:"aaa/bbb/ccc", dir:"aaa", → true ': function() {
67
+ value_of(util.PathUtils.isChild("aaa/bbb/ccc", "aaa")).should_be(true);
68
+ },
69
+ 'path:"aaa/bbb/ccc", dir:"aaa/ccc", → false ': function() {
70
+ value_of(util.PathUtils.isChild("aaa/bbb/ccc", "aaa/ccc")).should_be(false);
71
+ },
72
+ 'path:"aaa/bbb/ccc", dir:"aaa/bbbb", → false': function() {
73
+ value_of(util.PathUtils.isChild("aaa/bbb/ccc", "aaa/bbbb")).should_be(false);
74
+ },
75
+ 'path:"aaa/bbb/ccc", dir:"aaa/bb", → false': function() {
76
+ value_of(util.PathUtils.isChild("aaa/bbb/ccc", "aaa/bb")).should_be(false);
77
+ },
78
+ 'path:"日本語/ccc", dir:"日本語", → true': function() {
79
+ value_of(util.PathUtils.isChild("日本語/ccc", "日本語")).should_be(true);
80
+ },
81
+ 'path:"/日本語/ccc", dir:"", → true': function() {
82
+ value_of(util.PathUtils.isChild("/日本語/ccc", "")).should_be(true);
83
+ },
84
+ 'path:"", dir:"", → true': function() {
85
+ value_of(util.PathUtils.isChild("", "")).should_be(false);
86
+ }
87
+ });
88
+
89
+ describe('util.PathUtils#normarizeの動作確認', {
90
+ '基本のパターン': function() {
91
+ value_of(util.PathUtils.normarize([
92
+ "aaa/bbb",
93
+ "aaa",
94
+ "aa",
95
+ "aa/xx",
96
+ "aa/cc/dd",
97
+ "aa/cc",
98
+ "bb/dd/ss",
99
+ "bb/dd",
100
+ "cc/xx"
101
+ ])).should_be([
102
+ "aa",
103
+ "aaa",
104
+ "bb/dd",
105
+ "cc/xx"
106
+ ]);
107
+ },
108
+ '空の配列': function() {
109
+ value_of(util.PathUtils.normarize([])).should_be([]);
110
+ }
111
+ });
@@ -4,26 +4,65 @@ require "jiji/models"
4
4
  require 'jiji/util/util'
5
5
  require 'jiji/operator'
6
6
  require 'jiji/output'
7
+ require 'jiji/util/include_proxy'
7
8
 
8
9
  module JIJI
9
10
 
10
- # エージェントを示すマーカーモジュール
11
+ #===エージェントを示すマーカーモジュール
12
+ #JIJIではこのモジュールをincludeしたクラスがエージェントとして認識されます。
13
+ #
11
14
  module Agent
12
- # プロパティ設定後に呼び出される。
15
+
16
+ module Shared #:nodoc:
17
+ @@deleates = {}
18
+ def self.const_missing(id)
19
+ super unless @@deleates
20
+ result = nil
21
+ @@deleates.each_pair{|k,v|
22
+ if v.const_defined?(id)
23
+ result = v.const_get(id)
24
+ break
25
+ end
26
+ }
27
+ result ? result : super
28
+ end
29
+ def self.method_missing(name,*args, &block)
30
+ super unless @@deleates
31
+ target = nil
32
+ @@deleates.each_pair{|k,v|
33
+ if v.respond_to?(name)
34
+ target = v
35
+ break
36
+ end
37
+ }
38
+ target ? target.send( name, *args, &block ) : super
39
+ end
40
+ def self._delegates
41
+ @@deleates
42
+ end
43
+ end
44
+
45
+ #====エージェントの登録後に1度だけ呼び出される関数。
46
+ #必要に応じてオーバーライドしてください。コンストラクタと違いこのメソッドではoperatorやoutput,loggerが使用可能です。
13
47
  def init( )
14
48
  end
15
- # 次のレートを受け取る
49
+ #====レート情報が通知されるメソッドです。
50
+ #エージェントが動作している間順次呼び出されます。
51
+ #このメソッドをオーバーライドして、シグナルの計算や取り引きを行うロジックを実装してください
52
+ #rates:: JIJI::Rates
16
53
  def next_rates( rates )
17
54
  end
18
- # 設定可能なプロパティの一覧を返す
55
+ #====設定可能なプロパティの一覧を返します。
56
+ #必要に応じてオーバーライドしてください。
57
+ #戻り値:: JIJI::Agent::Propertyの配列
19
58
  def property_infos
20
59
  []
21
60
  end
22
- # 設定されたプロパティを取得する
61
+ #====設定されたプロパティを取得します。
23
62
  def properties
24
63
  @properties
25
64
  end
26
- # プロパティを設定する
65
+ #====プロパティを設定します。
27
66
  def properties=( properties )
28
67
  @properties = properties
29
68
  properties.each_pair {|k,v|
@@ -31,7 +70,8 @@ module JIJI
31
70
  }
32
71
  end
33
72
 
34
- # エージェントの説明を返す
73
+ #====エージェントの説明を返します。
74
+ #必要に応じてオーバーライドしてください。
35
75
  def description
36
76
  ""
37
77
  end
@@ -43,28 +83,41 @@ module JIJI
43
83
  # データの出力先
44
84
  attr :output, true
45
85
 
46
- # エージェントのプロパティ
86
+ #===エージェントのプロパティ
47
87
  class Property
48
88
  include JIJI::Util::Model
49
89
  include JIJI::Util::JsonSupport
90
+ #====コンストラクタ
91
+ #id:: プロパティID
92
+ #name:: UIでの表示名
93
+ #default_value:: プロパティの初期値
94
+ #type:: 種類
50
95
  def initialize( id, name, default_value=nil, type=:string )
51
96
  @id = id
52
97
  @name = name
53
98
  @default = default_value
54
99
  @type = type
55
100
  end
101
+ #プロパティID。
102
+ #JIJI::Agent#properties=(props)で渡されるハッシュのキーになります。設定必須です。
56
103
  attr :id, true
57
- attr :name, true # UIでの表示用の名前
58
- attr :default, true # 初期値
104
+ # UIでの表示名。設定必須です。
105
+ attr :name, true
106
+ # プロパティの初期値。
107
+ attr :default, true
108
+ # 種類。:string or :numberが指定可能。指定しない場合、:stringが指定されたものとみなされます。
59
109
  attr :type, true
60
110
  end
61
111
 
62
112
  end
63
113
 
64
-
65
- # 一定期間ごとに通知を受け取るエージェントの基底クラス。
114
+ #===一定期間ごとに通知を受け取るエージェントの基底クラス。
66
115
  class PeriodicallyAgent
67
116
  include JIJI::Agent
117
+ include_proxy JIJI::Agent::Shared
118
+
119
+ #====コンストラクタ
120
+ #period:: レートの通知を受け取る間隔(分)の初期値
68
121
  def initialize( period=10 )
69
122
  @period = period
70
123
  @start = nil
@@ -85,6 +138,10 @@ module JIJI
85
138
  def property_infos
86
139
  super() + [Property.new(:period, "レートの通知を受け取る間隔(分)", 10, :number)]
87
140
  end
141
+ #====レート情報が通知されるメソッドです。
142
+ #エージェントが動作している間順次呼び出されます。
143
+ #このメソッドをオーバーライドして、シグナルの計算や取り引きを行うロジックを実装してください
144
+ #rates:: JIJI::PeriodicallyRates
88
145
  def next_period_rates( rates )
89
146
  end
90
147
  end
@@ -15,12 +15,17 @@ module JIJI
15
15
 
16
16
  include JIJI::AgentUtil
17
17
  include Enumerable
18
- State = Struct.new( :agent, :output, :active )
19
-
20
- def initialize( id, registry, logger, failsafe=true )
21
- @id = id
18
+ State = Struct.new( :agent, :output, :operator, :active )
19
+
20
+ #コンストラクタ
21
+ #process_id:: プロセスID
22
+ #agent_registry:: エージェントレジストリ
23
+ #logger:: ロガー
24
+ #failsafe:: レートを通知した際にエージェントで発生したエラーを無視するかどうか?
25
+ def initialize( process_id, agent_registry, logger, failsafe=true )
26
+ @process_id = process_id
22
27
  @agents = {}
23
- @agent_registry = registry
28
+ @agent_registry = agent_registry
24
29
  @logger = logger
25
30
  # エージェントでエラーが発生した場合にエラーを無視し実行を継続するか
26
31
  # true の場合、ログ出力後エラーを握って処理を継続(RMTはこちらで動作する)
@@ -29,19 +34,20 @@ module JIJI
29
34
  end
30
35
 
31
36
  # エージェントを追加する
32
- def add( id, agent, name="" )
33
- if @agents.key? id
34
- raise UserError.new( JIJI::ERROR_ALREADY_EXIST, "agent is already exist. id=#{id}")
37
+ def add( agent_id, agent, agent_name="" )
38
+ if @agents.key? agent_id
39
+ raise UserError.new( JIJI::ERROR_ALREADY_EXIST, "agent is already exist. id=#{agent_id}")
35
40
  end
36
- output = @registry.output( @id, id )
37
- op = AgentOperator.new( @operator, name )
41
+ output = @output_manager.create( @process_id, agent_id )
42
+ output.agent_name = agent_name
43
+ op = AgentOperator.new( @operator, agent_name )
38
44
  safe( conf.get( [:agent,:safe_level], 4) ){
39
45
  agent.operator = op
40
46
  agent.logger = @logger
41
47
  agent.output = output
42
48
  agent.init
43
49
  }
44
- @agents[id] = State.new( agent, output, true )
50
+ @agents[agent_id] = State.new( agent, output, op, true )
45
51
  end
46
52
 
47
53
  # エージェントを破棄する
@@ -126,7 +132,7 @@ module JIJI
126
132
  attr :trade_result_dao, true
127
133
  attr :operator, true
128
134
  attr :conf, true
129
- attr :registry, true
135
+ attr :output_manager, true
130
136
  end
131
137
 
132
138
  end
@@ -4,40 +4,10 @@ require 'jiji/agent/agent'
4
4
  require 'jiji/agent/util'
5
5
  require 'jiji/util/file_lock'
6
6
  require 'set'
7
+ require 'logger'
7
8
 
8
9
  module JIJI
9
-
10
- module Agent
11
- module Shared
12
- @@deleates = {}
13
- def self.const_missing(id)
14
- super unless @@deleates
15
- result = nil
16
- @@deleates.each_pair{|k,v|
17
- if v.const_defined?(id)
18
- result = v.const_get(id)
19
- break
20
- end
21
- }
22
- result ? result : super
23
- end
24
- def self.method_missing(name,*args, &block)
25
- super unless @@deleates
26
- target = nil
27
- @@deleates.each_pair{|k,v|
28
- if v.respond_to?(name)
29
- target = v
30
- break
31
- end
32
- }
33
- target ? target.send( name, *args, &block ) : super
34
- end
35
- def self._delegates
36
- @@deleates
37
- end
38
- end
39
- end
40
-
10
+
41
11
  #==エージェントレジストリ
42
12
  class AgentRegistry
43
13
 
@@ -46,10 +16,7 @@ module JIJI
46
16
 
47
17
  def initialize( agent_dir, shared_lib_dir )
48
18
  @agent_dir = agent_dir
49
- FileUtils.mkdir_p @agent_dir
50
19
  @shared_lib_dir = shared_lib_dir
51
- FileUtils.mkdir_p @shared_lib_dir
52
-
53
20
  @agents = {}
54
21
  end
55
22
 
@@ -78,7 +45,7 @@ module JIJI
78
45
  raise UserError.new( JIJI::ERROR_NOT_FOUND,
79
46
  "agent class not found. name=#{name}")
80
47
  end
81
- m = @agents[$2]
48
+ m = @agents["agents/#{$2}"]
82
49
  unless m
83
50
  raise UserError.new( JIJI::ERROR_NOT_FOUND,
84
51
  "agent class not found. name=#{name}")
@@ -126,118 +93,64 @@ module JIJI
126
93
  }
127
94
  end
128
95
 
129
- # ファイル名の一覧を得る。
130
- def files( type=:agent )
131
- lock(type) {
132
- Dir.glob( "#{dir(type)}/*.rb" ).map {|item|
133
- { "name" =>File.basename(item),
134
- "update"=>File.mtime(item).to_i }
135
- }.sort_by {|item| item["name"] }
136
- }
137
- end
138
-
139
- # エージェントファイルの本文を取得する。
140
- def get_file(file, type=:agent )
141
- lock(type) {
142
- file = "#{dir(type)}/#{file}"
143
- unless File.exist? file
144
- raise UserError.new( JIJI::ERROR_NOT_FOUND,
145
- "#{type} file not found. file_name=#{file}}")
146
- end
147
- IO.read(file)
148
- }
149
- end
150
-
151
96
  # エージェント置き場から、エージェントをロードする。
97
+ # 起動時に一度だけ呼ばれる。
152
98
  def load_all
153
- lock(:shared_lib) {
154
- Dir.glob( "#{@shared_lib_dir}/*.rb" ) {|shared_lib_file|
155
- inner_load( shared_lib_file, :shared_lib )
156
- }
157
- }
158
- lock(:agent) {
159
- Dir.glob( "#{@agent_dir}/*.rb" ) {|agent_file|
160
- inner_load( agent_file, :agent )
99
+ [@agent_dir,@shared_lib_dir].each {|d|
100
+ @file_dao.list( d, true ).each {|item|
101
+ next if item[:type] == :directory
102
+ begin
103
+ inner_load( item[:path] )
104
+ rescue Exception
105
+ # ログ出力のみ行い、例外は握る。
106
+ server_logger.error( $! )
107
+ end
161
108
  }
162
109
  }
163
110
  end
164
111
 
165
112
  # 特定のファイルをロードする。
166
113
  def load(file)
167
- file = "#{@agent_dir}/#{file}"
168
- unless File.exist? file
169
- raise UserError.new( JIJI::ERROR_NOT_FOUND,
170
- "agent file not found. file_name=#{file}}")
171
- end
172
- lock(:agent) { inner_load( file ) }
114
+ inner_load( file )
173
115
  end
174
116
 
175
- # ファイルを追加/更新する。
176
- def add_file( file_name, body, type=:agent )
177
- lock(type) {
178
- file = "#{dir(type)}/#{file_name}"
179
- File.open( file, "w" ) {|f|
180
- f.puts body
181
- }
182
- inner_load( file, type )
183
- }
184
- end
185
-
186
- # ファイルを破棄する
187
- def remove_file( file_name, type=:agent )
188
- lock(type) {
189
- file = "#{dir(type)}/#{file_name}"
190
- unless File.exist? file
191
- raise UserError.new( JIJI::ERROR_NOT_FOUND,
192
- "#{type} file not found. file_name=#{file_name}")
193
- end
194
- FileUtils.rm_rf file
195
- @agents.delete file_name if type==:agent
196
- }
117
+ # 特定のファイルをアンロードする。
118
+ def unload(file)
119
+ if file =~ /^#{@agent_dir}\/.*/
120
+ @agents.delete file
121
+ else
122
+ JIJI::Agent::Shared._delegates.delete file
123
+ end
197
124
  end
198
125
 
199
126
  attr :conf, true
200
-
127
+ attr :file_dao, true
128
+ attr :server_logger, true
201
129
  private
202
130
 
203
- # 種別に対応するディレクトリ名を得る。
204
- def dir( type )
205
- return type == :agent ? @agent_dir : @shared_lib_dir
206
- end
207
-
208
- def inner_load( file, type=:agent )
209
- error = nil
210
- body = IO.read(file).taint
131
+ def inner_load( file )
132
+ body = @file_dao.get(file).taint
211
133
  m = Module.new.taint
212
- if type == :agent
213
- @agents[ File.basename(file) ] = m
134
+ if file =~ /^#{@agent_dir}\/.*/
135
+ @agents[ file ] = m
136
+ elsif file =~ /^#{@shared_lib_dir}\/.*/
137
+ JIJI::Agent::Shared._delegates[ file ] = m
214
138
  else
215
- JIJI::Agent::Shared._delegates[ File.basename(file) ] = m
139
+ return # agent,shared_lib配下のファイル以外は読み込まない。
216
140
  end
217
141
  safe( conf.get( [:agent,:safe_level], 4) ){
218
- begin
219
- m.module_eval( body, file, 1 )
220
- rescue Exception => e
221
- # エラーになっても読み込みは継続。
222
- # 戻り値としてエラーの情報を返す
223
- error = e.to_s
224
- end
142
+ m.module_eval( body, file, 1 )
225
143
  }
226
- return error ? error : :success
227
144
  end
228
145
 
229
- def lock( type=:agent )
230
- DirLock.new( dir(type) ).writelock {
231
- yield if block_given?
232
- }
233
- end
234
146
  def find_agent( file, m, checked, &block )
235
147
  return if checked.include? m
236
148
  checked << m
237
149
  m.constants.each {|name|
238
150
  cl = m.const_get name
239
- begin
240
- block.call( "#{get_name(cl.name)}@#{file}" ) if cl.kind_of?(Class) && cl < JIJI::Agent
151
+ agent_file = file.sub( /^#{@agent_dir}\/?/, "" )
152
+ begin
153
+ block.call( "#{get_name(cl.name)}@#{agent_file}" ) if cl.kind_of?(Class) && cl < JIJI::Agent
241
154
  rescue Exception
242
155
  end
243
156
  find_agent( file, cl, checked, &block ) if cl.kind_of?(Module)
@@ -246,6 +159,7 @@ module JIJI
246
159
  def get_name( name )
247
160
  name.split("::", 2)[1]
248
161
  end
162
+
249
163
  end
250
164
 
251
165
  end
@@ -111,12 +111,7 @@ module JIJI
111
111
  @end_mutex.synchronize { @alive = false }
112
112
 
113
113
  # リスナに通知
114
- @listeners.each {|l|
115
- begin
116
- l.on_finished( @state, Time.at(@now) ) if l.respond_to? :on_finished
117
- rescue Exception
118
- end
119
- }
114
+ callback( :on_finished, @state, Time.at(@now || Time.now) )
120
115
  }
121
116
  end
122
117
  end
@@ -136,6 +131,14 @@ module JIJI
136
131
  }
137
132
  end
138
133
  end
134
+ # リスナにイベントを通知する
135
+ def callback( method, *args )
136
+ @listeners.each {|l|
137
+ JIJI::Util.log_if_error( @logger ) {
138
+ l.send(method, *args ) if l.respond_to? method
139
+ }
140
+ }
141
+ end
139
142
  end
140
143
 
141
144
  #
@@ -156,12 +159,17 @@ module JIJI
156
159
  end
157
160
  def collect
158
161
  JIJI::Util.log_if_error_and_throw( @logger ) {
162
+ callback( :on_progress_changed, @progress )
159
163
  begin
160
164
  pairs = @dao.list_pairs
161
165
  if pairs.length > 0
162
166
  @start_date = @start_date || Time.at( @dao.dao(pairs[0]).first_time(:raw) )
163
167
  @end_date = @end_date || Time.at( @dao.dao(pairs[0]).last_time(:raw) )
168
+ else
169
+ @start_date = @start_date || 0
170
+ @end_date = @end_date || Time.now
164
171
  end
172
+ @now = @start_date.to_i
165
173
  @dao.each_all_pair_rates(:raw, @start_date, @end_date ) {|rates|
166
174
  each_rate(rates)
167
175
  # キャンセルチェック
@@ -174,6 +182,7 @@ module JIJI
174
182
  @state_mutex.synchronize {
175
183
  @progress = 100
176
184
  }
185
+ callback( :on_progress_changed, @progress )
177
186
  end
178
187
  }
179
188
  end
@@ -207,6 +216,7 @@ module JIJI
207
216
  all = @end_date.to_i - @start_date.to_i
208
217
  @progress = ( current*100 / all ).to_i
209
218
  }
219
+ callback( :on_progress_changed, @progress )
210
220
  end
211
221
  end
212
222
  end