mjai 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (355) hide show
  1. data/bin/mjai +9 -0
  2. data/bin/mjai-shanten +9 -0
  3. data/bin/mjai-tsumogiri +9 -0
  4. data/lib/mjai/action.rb +41 -0
  5. data/lib/mjai/active_game.rb +230 -0
  6. data/lib/mjai/archive.rb +46 -0
  7. data/lib/mjai/archive_player.rb +47 -0
  8. data/lib/mjai/context.rb +34 -0
  9. data/lib/mjai/file_converter.rb +86 -0
  10. data/lib/mjai/furo.rb +57 -0
  11. data/lib/mjai/game.rb +357 -0
  12. data/lib/mjai/hora.rb +528 -0
  13. data/lib/mjai/jsonizable.rb +171 -0
  14. data/lib/mjai/mentsu.rb +46 -0
  15. data/lib/mjai/mjai_command.rb +93 -0
  16. data/lib/mjai/mjson_archive.rb +25 -0
  17. data/lib/mjai/pai.rb +138 -0
  18. data/lib/mjai/player.rb +340 -0
  19. data/lib/mjai/puppet_player.rb +14 -0
  20. data/lib/mjai/shanten_analysis.rb +273 -0
  21. data/lib/mjai/shanten_player.rb +102 -0
  22. data/lib/mjai/tcp_client_game.rb +63 -0
  23. data/lib/mjai/tcp_game_server.rb +205 -0
  24. data/lib/mjai/tcp_player.rb +66 -0
  25. data/lib/mjai/tenhou_archive.rb +412 -0
  26. data/lib/mjai/tenpai_analysis.rb +62 -0
  27. data/lib/mjai/tsumogiri_player.rb +20 -0
  28. data/lib/mjai/validation_error.rb +7 -0
  29. data/lib/mjai/with_fields.rb +18 -0
  30. data/share/html/css/style.css +77 -0
  31. data/share/html/css/style.scss +106 -0
  32. data/share/html/images/README.txt +1 -0
  33. data/share/html/images/b_1_1.gif +0 -0
  34. data/share/html/images/b_1_2.gif +0 -0
  35. data/share/html/images/b_5_1.gif +0 -0
  36. data/share/html/images/b_5_2.gif +0 -0
  37. data/share/html/images/b_8_1.gif +0 -0
  38. data/share/html/images/b_8_2.gif +0 -0
  39. data/share/html/images/b_9_1.gif +0 -0
  40. data/share/html/images/b_9_2.gif +0 -0
  41. data/share/html/images/blank.png +0 -0
  42. data/share/html/images/c_c_1.gif +0 -0
  43. data/share/html/images/c_c_2.gif +0 -0
  44. data/share/html/images/c_c_3.gif +0 -0
  45. data/share/html/images/c_c_4.gif +0 -0
  46. data/share/html/images/c_e_1.gif +0 -0
  47. data/share/html/images/c_e_2.gif +0 -0
  48. data/share/html/images/c_e_3.gif +0 -0
  49. data/share/html/images/c_e_4.gif +0 -0
  50. data/share/html/images/c_n_1.gif +0 -0
  51. data/share/html/images/c_n_2.gif +0 -0
  52. data/share/html/images/c_n_3.gif +0 -0
  53. data/share/html/images/c_n_4.gif +0 -0
  54. data/share/html/images/c_s_1.gif +0 -0
  55. data/share/html/images/c_s_2.gif +0 -0
  56. data/share/html/images/c_s_3.gif +0 -0
  57. data/share/html/images/c_s_4.gif +0 -0
  58. data/share/html/images/c_w_1.gif +0 -0
  59. data/share/html/images/c_w_2.gif +0 -0
  60. data/share/html/images/c_w_3.gif +0 -0
  61. data/share/html/images/c_w_4.gif +0 -0
  62. data/share/html/images/dice.gif +0 -0
  63. data/share/html/images/p_bk_0.gif +0 -0
  64. data/share/html/images/p_bk_1.gif +0 -0
  65. data/share/html/images/p_bk_2.gif +0 -0
  66. data/share/html/images/p_bk_3.gif +0 -0
  67. data/share/html/images/p_bk_4.gif +0 -0
  68. data/share/html/images/p_bk_5.gif +0 -0
  69. data/share/html/images/p_bk_6.gif +0 -0
  70. data/share/html/images/p_bk_7.gif +0 -0
  71. data/share/html/images/p_ji_c_0.gif +0 -0
  72. data/share/html/images/p_ji_c_1.gif +0 -0
  73. data/share/html/images/p_ji_c_2.gif +0 -0
  74. data/share/html/images/p_ji_c_3.gif +0 -0
  75. data/share/html/images/p_ji_c_4.gif +0 -0
  76. data/share/html/images/p_ji_c_5.gif +0 -0
  77. data/share/html/images/p_ji_c_6.gif +0 -0
  78. data/share/html/images/p_ji_c_7.gif +0 -0
  79. data/share/html/images/p_ji_e_0.gif +0 -0
  80. data/share/html/images/p_ji_e_1.gif +0 -0
  81. data/share/html/images/p_ji_e_2.gif +0 -0
  82. data/share/html/images/p_ji_e_3.gif +0 -0
  83. data/share/html/images/p_ji_e_4.gif +0 -0
  84. data/share/html/images/p_ji_e_5.gif +0 -0
  85. data/share/html/images/p_ji_e_6.gif +0 -0
  86. data/share/html/images/p_ji_e_7.gif +0 -0
  87. data/share/html/images/p_ji_h_0.gif +0 -0
  88. data/share/html/images/p_ji_h_1.gif +0 -0
  89. data/share/html/images/p_ji_h_2.gif +0 -0
  90. data/share/html/images/p_ji_h_3.gif +0 -0
  91. data/share/html/images/p_ji_h_4.gif +0 -0
  92. data/share/html/images/p_ji_h_5.gif +0 -0
  93. data/share/html/images/p_ji_h_6.gif +0 -0
  94. data/share/html/images/p_ji_h_7.gif +0 -0
  95. data/share/html/images/p_ji_n_0.gif +0 -0
  96. data/share/html/images/p_ji_n_1.gif +0 -0
  97. data/share/html/images/p_ji_n_2.gif +0 -0
  98. data/share/html/images/p_ji_n_3.gif +0 -0
  99. data/share/html/images/p_ji_n_4.gif +0 -0
  100. data/share/html/images/p_ji_n_5.gif +0 -0
  101. data/share/html/images/p_ji_n_6.gif +0 -0
  102. data/share/html/images/p_ji_n_7.gif +0 -0
  103. data/share/html/images/p_ji_s_0.gif +0 -0
  104. data/share/html/images/p_ji_s_1.gif +0 -0
  105. data/share/html/images/p_ji_s_2.gif +0 -0
  106. data/share/html/images/p_ji_s_3.gif +0 -0
  107. data/share/html/images/p_ji_s_4.gif +0 -0
  108. data/share/html/images/p_ji_s_5.gif +0 -0
  109. data/share/html/images/p_ji_s_6.gif +0 -0
  110. data/share/html/images/p_ji_s_7.gif +0 -0
  111. data/share/html/images/p_ji_w_0.gif +0 -0
  112. data/share/html/images/p_ji_w_1.gif +0 -0
  113. data/share/html/images/p_ji_w_2.gif +0 -0
  114. data/share/html/images/p_ji_w_3.gif +0 -0
  115. data/share/html/images/p_ji_w_4.gif +0 -0
  116. data/share/html/images/p_ji_w_5.gif +0 -0
  117. data/share/html/images/p_ji_w_6.gif +0 -0
  118. data/share/html/images/p_ji_w_7.gif +0 -0
  119. data/share/html/images/p_ms1_0.gif +0 -0
  120. data/share/html/images/p_ms1_1.gif +0 -0
  121. data/share/html/images/p_ms1_2.gif +0 -0
  122. data/share/html/images/p_ms1_3.gif +0 -0
  123. data/share/html/images/p_ms1_4.gif +0 -0
  124. data/share/html/images/p_ms1_5.gif +0 -0
  125. data/share/html/images/p_ms1_6.gif +0 -0
  126. data/share/html/images/p_ms1_7.gif +0 -0
  127. data/share/html/images/p_ms2_0.gif +0 -0
  128. data/share/html/images/p_ms2_1.gif +0 -0
  129. data/share/html/images/p_ms2_2.gif +0 -0
  130. data/share/html/images/p_ms2_3.gif +0 -0
  131. data/share/html/images/p_ms2_4.gif +0 -0
  132. data/share/html/images/p_ms2_5.gif +0 -0
  133. data/share/html/images/p_ms2_6.gif +0 -0
  134. data/share/html/images/p_ms2_7.gif +0 -0
  135. data/share/html/images/p_ms3_0.gif +0 -0
  136. data/share/html/images/p_ms3_1.gif +0 -0
  137. data/share/html/images/p_ms3_2.gif +0 -0
  138. data/share/html/images/p_ms3_3.gif +0 -0
  139. data/share/html/images/p_ms3_4.gif +0 -0
  140. data/share/html/images/p_ms3_5.gif +0 -0
  141. data/share/html/images/p_ms3_6.gif +0 -0
  142. data/share/html/images/p_ms3_7.gif +0 -0
  143. data/share/html/images/p_ms4_0.gif +0 -0
  144. data/share/html/images/p_ms4_1.gif +0 -0
  145. data/share/html/images/p_ms4_2.gif +0 -0
  146. data/share/html/images/p_ms4_3.gif +0 -0
  147. data/share/html/images/p_ms4_4.gif +0 -0
  148. data/share/html/images/p_ms4_5.gif +0 -0
  149. data/share/html/images/p_ms4_6.gif +0 -0
  150. data/share/html/images/p_ms4_7.gif +0 -0
  151. data/share/html/images/p_ms5_0.gif +0 -0
  152. data/share/html/images/p_ms5_1.gif +0 -0
  153. data/share/html/images/p_ms5_2.gif +0 -0
  154. data/share/html/images/p_ms5_3.gif +0 -0
  155. data/share/html/images/p_ms5_4.gif +0 -0
  156. data/share/html/images/p_ms5_5.gif +0 -0
  157. data/share/html/images/p_ms5_6.gif +0 -0
  158. data/share/html/images/p_ms5_7.gif +0 -0
  159. data/share/html/images/p_ms5r_1.png +0 -0
  160. data/share/html/images/p_ms5r_3.png +0 -0
  161. data/share/html/images/p_ms6_0.gif +0 -0
  162. data/share/html/images/p_ms6_1.gif +0 -0
  163. data/share/html/images/p_ms6_2.gif +0 -0
  164. data/share/html/images/p_ms6_3.gif +0 -0
  165. data/share/html/images/p_ms6_4.gif +0 -0
  166. data/share/html/images/p_ms6_5.gif +0 -0
  167. data/share/html/images/p_ms6_6.gif +0 -0
  168. data/share/html/images/p_ms6_7.gif +0 -0
  169. data/share/html/images/p_ms7_0.gif +0 -0
  170. data/share/html/images/p_ms7_1.gif +0 -0
  171. data/share/html/images/p_ms7_2.gif +0 -0
  172. data/share/html/images/p_ms7_3.gif +0 -0
  173. data/share/html/images/p_ms7_4.gif +0 -0
  174. data/share/html/images/p_ms7_5.gif +0 -0
  175. data/share/html/images/p_ms7_6.gif +0 -0
  176. data/share/html/images/p_ms7_7.gif +0 -0
  177. data/share/html/images/p_ms8_0.gif +0 -0
  178. data/share/html/images/p_ms8_1.gif +0 -0
  179. data/share/html/images/p_ms8_2.gif +0 -0
  180. data/share/html/images/p_ms8_3.gif +0 -0
  181. data/share/html/images/p_ms8_4.gif +0 -0
  182. data/share/html/images/p_ms8_5.gif +0 -0
  183. data/share/html/images/p_ms8_6.gif +0 -0
  184. data/share/html/images/p_ms8_7.gif +0 -0
  185. data/share/html/images/p_ms9_0.gif +0 -0
  186. data/share/html/images/p_ms9_1.gif +0 -0
  187. data/share/html/images/p_ms9_2.gif +0 -0
  188. data/share/html/images/p_ms9_3.gif +0 -0
  189. data/share/html/images/p_ms9_4.gif +0 -0
  190. data/share/html/images/p_ms9_5.gif +0 -0
  191. data/share/html/images/p_ms9_6.gif +0 -0
  192. data/share/html/images/p_ms9_7.gif +0 -0
  193. data/share/html/images/p_no_0.gif +0 -0
  194. data/share/html/images/p_no_1.gif +0 -0
  195. data/share/html/images/p_no_2.gif +0 -0
  196. data/share/html/images/p_no_3.gif +0 -0
  197. data/share/html/images/p_no_4.gif +0 -0
  198. data/share/html/images/p_no_5.gif +0 -0
  199. data/share/html/images/p_no_6.gif +0 -0
  200. data/share/html/images/p_no_7.gif +0 -0
  201. data/share/html/images/p_ps1_0.gif +0 -0
  202. data/share/html/images/p_ps1_1.gif +0 -0
  203. data/share/html/images/p_ps1_2.gif +0 -0
  204. data/share/html/images/p_ps1_3.gif +0 -0
  205. data/share/html/images/p_ps1_4.gif +0 -0
  206. data/share/html/images/p_ps1_5.gif +0 -0
  207. data/share/html/images/p_ps1_6.gif +0 -0
  208. data/share/html/images/p_ps1_7.gif +0 -0
  209. data/share/html/images/p_ps2_0.gif +0 -0
  210. data/share/html/images/p_ps2_1.gif +0 -0
  211. data/share/html/images/p_ps2_2.gif +0 -0
  212. data/share/html/images/p_ps2_3.gif +0 -0
  213. data/share/html/images/p_ps2_4.gif +0 -0
  214. data/share/html/images/p_ps2_5.gif +0 -0
  215. data/share/html/images/p_ps2_6.gif +0 -0
  216. data/share/html/images/p_ps2_7.gif +0 -0
  217. data/share/html/images/p_ps3_0.gif +0 -0
  218. data/share/html/images/p_ps3_1.gif +0 -0
  219. data/share/html/images/p_ps3_2.gif +0 -0
  220. data/share/html/images/p_ps3_3.gif +0 -0
  221. data/share/html/images/p_ps3_4.gif +0 -0
  222. data/share/html/images/p_ps3_5.gif +0 -0
  223. data/share/html/images/p_ps3_6.gif +0 -0
  224. data/share/html/images/p_ps3_7.gif +0 -0
  225. data/share/html/images/p_ps4_0.gif +0 -0
  226. data/share/html/images/p_ps4_1.gif +0 -0
  227. data/share/html/images/p_ps4_2.gif +0 -0
  228. data/share/html/images/p_ps4_3.gif +0 -0
  229. data/share/html/images/p_ps4_4.gif +0 -0
  230. data/share/html/images/p_ps4_5.gif +0 -0
  231. data/share/html/images/p_ps4_6.gif +0 -0
  232. data/share/html/images/p_ps4_7.gif +0 -0
  233. data/share/html/images/p_ps5_0.gif +0 -0
  234. data/share/html/images/p_ps5_1.gif +0 -0
  235. data/share/html/images/p_ps5_2.gif +0 -0
  236. data/share/html/images/p_ps5_3.gif +0 -0
  237. data/share/html/images/p_ps5_4.gif +0 -0
  238. data/share/html/images/p_ps5_5.gif +0 -0
  239. data/share/html/images/p_ps5_6.gif +0 -0
  240. data/share/html/images/p_ps5_7.gif +0 -0
  241. data/share/html/images/p_ps5r_1.png +0 -0
  242. data/share/html/images/p_ps5r_3.png +0 -0
  243. data/share/html/images/p_ps6_0.gif +0 -0
  244. data/share/html/images/p_ps6_1.gif +0 -0
  245. data/share/html/images/p_ps6_2.gif +0 -0
  246. data/share/html/images/p_ps6_3.gif +0 -0
  247. data/share/html/images/p_ps6_4.gif +0 -0
  248. data/share/html/images/p_ps6_5.gif +0 -0
  249. data/share/html/images/p_ps6_6.gif +0 -0
  250. data/share/html/images/p_ps6_7.gif +0 -0
  251. data/share/html/images/p_ps7_0.gif +0 -0
  252. data/share/html/images/p_ps7_1.gif +0 -0
  253. data/share/html/images/p_ps7_2.gif +0 -0
  254. data/share/html/images/p_ps7_3.gif +0 -0
  255. data/share/html/images/p_ps7_4.gif +0 -0
  256. data/share/html/images/p_ps7_5.gif +0 -0
  257. data/share/html/images/p_ps7_6.gif +0 -0
  258. data/share/html/images/p_ps7_7.gif +0 -0
  259. data/share/html/images/p_ps8_0.gif +0 -0
  260. data/share/html/images/p_ps8_1.gif +0 -0
  261. data/share/html/images/p_ps8_2.gif +0 -0
  262. data/share/html/images/p_ps8_3.gif +0 -0
  263. data/share/html/images/p_ps8_4.gif +0 -0
  264. data/share/html/images/p_ps8_5.gif +0 -0
  265. data/share/html/images/p_ps8_6.gif +0 -0
  266. data/share/html/images/p_ps8_7.gif +0 -0
  267. data/share/html/images/p_ps9_0.gif +0 -0
  268. data/share/html/images/p_ps9_1.gif +0 -0
  269. data/share/html/images/p_ps9_2.gif +0 -0
  270. data/share/html/images/p_ps9_3.gif +0 -0
  271. data/share/html/images/p_ps9_4.gif +0 -0
  272. data/share/html/images/p_ps9_5.gif +0 -0
  273. data/share/html/images/p_ps9_6.gif +0 -0
  274. data/share/html/images/p_ps9_7.gif +0 -0
  275. data/share/html/images/p_ss1_0.gif +0 -0
  276. data/share/html/images/p_ss1_1.gif +0 -0
  277. data/share/html/images/p_ss1_2.gif +0 -0
  278. data/share/html/images/p_ss1_3.gif +0 -0
  279. data/share/html/images/p_ss1_4.gif +0 -0
  280. data/share/html/images/p_ss1_5.gif +0 -0
  281. data/share/html/images/p_ss1_6.gif +0 -0
  282. data/share/html/images/p_ss1_7.gif +0 -0
  283. data/share/html/images/p_ss2_0.gif +0 -0
  284. data/share/html/images/p_ss2_1.gif +0 -0
  285. data/share/html/images/p_ss2_2.gif +0 -0
  286. data/share/html/images/p_ss2_3.gif +0 -0
  287. data/share/html/images/p_ss2_4.gif +0 -0
  288. data/share/html/images/p_ss2_5.gif +0 -0
  289. data/share/html/images/p_ss2_6.gif +0 -0
  290. data/share/html/images/p_ss2_7.gif +0 -0
  291. data/share/html/images/p_ss3_0.gif +0 -0
  292. data/share/html/images/p_ss3_1.gif +0 -0
  293. data/share/html/images/p_ss3_2.gif +0 -0
  294. data/share/html/images/p_ss3_3.gif +0 -0
  295. data/share/html/images/p_ss3_4.gif +0 -0
  296. data/share/html/images/p_ss3_5.gif +0 -0
  297. data/share/html/images/p_ss3_6.gif +0 -0
  298. data/share/html/images/p_ss3_7.gif +0 -0
  299. data/share/html/images/p_ss4_0.gif +0 -0
  300. data/share/html/images/p_ss4_1.gif +0 -0
  301. data/share/html/images/p_ss4_2.gif +0 -0
  302. data/share/html/images/p_ss4_3.gif +0 -0
  303. data/share/html/images/p_ss4_4.gif +0 -0
  304. data/share/html/images/p_ss4_5.gif +0 -0
  305. data/share/html/images/p_ss4_6.gif +0 -0
  306. data/share/html/images/p_ss4_7.gif +0 -0
  307. data/share/html/images/p_ss5_0.gif +0 -0
  308. data/share/html/images/p_ss5_1.gif +0 -0
  309. data/share/html/images/p_ss5_2.gif +0 -0
  310. data/share/html/images/p_ss5_3.gif +0 -0
  311. data/share/html/images/p_ss5_4.gif +0 -0
  312. data/share/html/images/p_ss5_5.gif +0 -0
  313. data/share/html/images/p_ss5_6.gif +0 -0
  314. data/share/html/images/p_ss5_7.gif +0 -0
  315. data/share/html/images/p_ss5r_1.png +0 -0
  316. data/share/html/images/p_ss5r_3.png +0 -0
  317. data/share/html/images/p_ss6_0.gif +0 -0
  318. data/share/html/images/p_ss6_1.gif +0 -0
  319. data/share/html/images/p_ss6_2.gif +0 -0
  320. data/share/html/images/p_ss6_3.gif +0 -0
  321. data/share/html/images/p_ss6_4.gif +0 -0
  322. data/share/html/images/p_ss6_5.gif +0 -0
  323. data/share/html/images/p_ss6_6.gif +0 -0
  324. data/share/html/images/p_ss6_7.gif +0 -0
  325. data/share/html/images/p_ss7_0.gif +0 -0
  326. data/share/html/images/p_ss7_1.gif +0 -0
  327. data/share/html/images/p_ss7_2.gif +0 -0
  328. data/share/html/images/p_ss7_3.gif +0 -0
  329. data/share/html/images/p_ss7_4.gif +0 -0
  330. data/share/html/images/p_ss7_5.gif +0 -0
  331. data/share/html/images/p_ss7_6.gif +0 -0
  332. data/share/html/images/p_ss7_7.gif +0 -0
  333. data/share/html/images/p_ss8_0.gif +0 -0
  334. data/share/html/images/p_ss8_1.gif +0 -0
  335. data/share/html/images/p_ss8_2.gif +0 -0
  336. data/share/html/images/p_ss8_3.gif +0 -0
  337. data/share/html/images/p_ss8_4.gif +0 -0
  338. data/share/html/images/p_ss8_5.gif +0 -0
  339. data/share/html/images/p_ss8_6.gif +0 -0
  340. data/share/html/images/p_ss8_7.gif +0 -0
  341. data/share/html/images/p_ss9_0.gif +0 -0
  342. data/share/html/images/p_ss9_1.gif +0 -0
  343. data/share/html/images/p_ss9_2.gif +0 -0
  344. data/share/html/images/p_ss9_3.gif +0 -0
  345. data/share/html/images/p_ss9_4.gif +0 -0
  346. data/share/html/images/p_ss9_5.gif +0 -0
  347. data/share/html/images/p_ss9_6.gif +0 -0
  348. data/share/html/images/p_ss9_7.gif +0 -0
  349. data/share/html/js/archive_player.coffee +379 -0
  350. data/share/html/js/archive_player.js +505 -0
  351. data/share/html/js/dytem.coffee +83 -0
  352. data/share/html/js/dytem.js +128 -0
  353. data/share/html/js/jquery-1.7.2.min.js +4 -0
  354. data/share/html/views/archive_player.erb +61 -0
  355. metadata +435 -0
@@ -0,0 +1,379 @@
1
+ window.console ||= {}
2
+ window.console.log ||= ->
3
+ window.console.error ||= ->
4
+
5
+ TSUPAIS = [null, "E", "S", "W", "N", "P", "F", "C"]
6
+
7
+ TSUPAI_TO_IMAGE_NAME =
8
+ "E": "ji_e"
9
+ "S": "ji_s"
10
+ "W": "ji_w"
11
+ "N": "ji_n"
12
+ "P": "no"
13
+ "F": "ji_h"
14
+ "C": "ji_c"
15
+
16
+ BAKAZE_TO_STR =
17
+ "E": "東"
18
+ "S": "南"
19
+ "W": "西"
20
+ "N": "北"
21
+
22
+ kyokus = []
23
+ currentKyokuId = 0
24
+ currentActionId = 0
25
+ playerInfos = [{}, {}, {}, {}]
26
+
27
+ parsePai = (pai) ->
28
+ if pai.match(/^([1-9])(.)(r)?$/)
29
+ return {
30
+ type: RegExp.$2
31
+ number: parseInt(RegExp.$1)
32
+ red: if RegExp.$3 then true else false
33
+ }
34
+ else
35
+ return {
36
+ type: "t"
37
+ number: TSUPAIS.indexOf(pai)
38
+ red: false
39
+ }
40
+
41
+ comparePais = (lhs, rhs) ->
42
+ parsedLhs = parsePai(lhs)
43
+ lhsRep = parsedLhs.type + parsedLhs.number + (if parsedLhs.red then "1" else "0")
44
+ parsedRhs = parsePai(rhs)
45
+ rhsRep = parsedRhs.type + parsedRhs.number + (if parsedRhs.red then "1" else "0")
46
+ if lhsRep < rhsRep
47
+ return -1
48
+ else if lhsRep > rhsRep
49
+ return 1
50
+ else
51
+ return 0
52
+
53
+ sortPais = (pais) ->
54
+ pais.sort(comparePais)
55
+
56
+ paiToImageUrl = (pai, pose) ->
57
+ if pai
58
+ if pai == "?"
59
+ name = "bk"
60
+ ext = "gif"
61
+ else
62
+ parsedPai = parsePai(pai)
63
+ if parsedPai.type == "t"
64
+ name = TSUPAI_TO_IMAGE_NAME[pai]
65
+ else
66
+ redSuffix = if parsedPai.red then "r" else ""
67
+ name = "#{parsedPai.type}s#{parsedPai.number}#{redSuffix}"
68
+ ext = if parsedPai.red then "png" else "gif"
69
+ if pose == undefined
70
+ pose = 1
71
+ return "http://gimite.net/mjai/images/p_#{name}_#{pose}.#{ext}"
72
+ else
73
+ return "http://gimite.net/mjai/images/blank.png"
74
+
75
+ cloneBoard = (board) ->
76
+ newBoard = {}
77
+ for bk, bv of board
78
+ if bk == "players"
79
+ newBoard[bk] = []
80
+ for player in bv
81
+ newPlayer = {}
82
+ for pk, pv of player
83
+ newPlayer[pk] = pv
84
+ newBoard[bk].push(newPlayer)
85
+ else
86
+ newBoard[bk] = bv
87
+ return newBoard
88
+
89
+ initPlayers = (board) ->
90
+ for player in board.players
91
+ player.tehais = null
92
+ player.furos = []
93
+ player.ho = []
94
+ player.reach = false
95
+ player.reachHoIndex = null
96
+
97
+ removeRed = (pai) ->
98
+ return null if !pai
99
+ if pai.match(/^(.+)r$/)
100
+ return RegExp.$1
101
+ else
102
+ return pai
103
+
104
+ loadAction = (action) ->
105
+
106
+ #console.log(action.type, action)
107
+ if kyokus.length > 0
108
+ kyoku = kyokus[kyokus.length - 1]
109
+ board = cloneBoard(kyoku.actions[kyoku.actions.length - 1].board)
110
+ else
111
+ kyoku = null
112
+ board = null
113
+ if board && ("actor" of action)
114
+ actorPlayer = board.players[action.actor]
115
+ else
116
+ actorPlayer = null
117
+ if board && ("target" of action)
118
+ targetPlayer = board.players[action.target]
119
+ else
120
+ targetPlayer = null
121
+
122
+ switch action.type
123
+ when "start_game"
124
+ for i in [0...4]
125
+ playerInfos[i].name = action.names[i]
126
+ when "end_game"
127
+ null
128
+ when "start_kyoku"
129
+ kyoku =
130
+ actions: []
131
+ doraMarkers: [action.dora_marker]
132
+ bakaze: action.bakaze
133
+ kyokuNum: action.kyoku
134
+ honba: action.honba
135
+ kyokus.push(kyoku)
136
+ prevBoard = board
137
+ board =
138
+ players: [{}, {}, {}, {}]
139
+ initPlayers(board)
140
+ for i in [0...4]
141
+ board.players[i].tehais = action.tehais[i]
142
+ if prevBoard
143
+ board.players[i].score = prevBoard.players[i].score
144
+ else
145
+ board.players[i].score = 25000
146
+ when "end_kyoku"
147
+ null
148
+ when "tsumo"
149
+ actorPlayer.tehais = actorPlayer.tehais.concat([action.pai])
150
+ when "dahai"
151
+ deleteTehai(actorPlayer, action.pai)
152
+ actorPlayer.ho = actorPlayer.ho.concat([action.pai])
153
+ when "reach"
154
+ actorPlayer.reachHoIndex = actorPlayer.ho.length
155
+ when "reach_accepted"
156
+ actorPlayer.reach = true
157
+ when "chi", "pon", "daiminkan"
158
+ targetPlayer.ho = targetPlayer.ho[0...(targetPlayer.ho.length - 1)]
159
+ for pai in action.consumed
160
+ deleteTehai(actorPlayer, pai)
161
+ actorPlayer.furos = actorPlayer.furos.concat([
162
+ type: action.type
163
+ taken: action.pai
164
+ consumed: action.consumed
165
+ target: action.target
166
+ ])
167
+ when "ankan"
168
+ for pai in action.consumed
169
+ deleteTehai(actorPlayer, pai)
170
+ actorPlayer.furos = actorPlayer.furos.concat([
171
+ type: action.type
172
+ consumed: action.consumed
173
+ ])
174
+ when "kakan"
175
+ deleteTehai(actorPlayer, action.pai)
176
+ actorPlayer.furos = actorPlayer.furos.concat([])
177
+ furos = actorPlayer.furos
178
+ for i in [0...furos.length]
179
+ if furos[i].type == "pon" && removeRed(furos[i].taken) == removeRed(action.pai)
180
+ furos[i] =
181
+ type: "kakan"
182
+ taken: action.pai
183
+ consumed: action.consumed
184
+ target: furos[i].target
185
+ when "hora", "ryukyoku"
186
+ null
187
+ when "dora"
188
+ board.doraMarkers = board.doraMarkers.concat([action.dora_marker])
189
+ when "log"
190
+ if kyoku
191
+ kyoku.actions[kyoku.actions.length - 1].log = action.text
192
+ else
193
+ throw "unknown action: #{action.type}"
194
+
195
+ if action.scores
196
+ for i in [0...4]
197
+ board.players[i].score = action.scores[i]
198
+
199
+ if kyoku
200
+ for i in [0...4]
201
+ if i != action.actor
202
+ ripai(board.players[i])
203
+ if action.type != "log"
204
+ action.board = board
205
+ #dumpBoard(board)
206
+ kyoku.actions.push(action)
207
+
208
+ deleteTehai = (player, pai) ->
209
+ player.tehais = player.tehais.concat([])
210
+ idx = player.tehais.lastIndexOf(pai)
211
+ if idx < 0
212
+ idx = player.tehais.lastIndexOf("?")
213
+ throw "pai not in tehai" if idx < 0
214
+ player.tehais[idx] = null
215
+
216
+ ripai = (player) ->
217
+ if player.tehais
218
+ player.tehais = (pai for pai in player.tehais when pai)
219
+ sortPais(player.tehais)
220
+
221
+ dumpBoard = (board) ->
222
+ for i in [0...4]
223
+ player = board.players[i]
224
+ if player.tehais
225
+ tehaisStr = player.tehais.join(" ")
226
+ for furo in player.furos
227
+ consumedStr = furo.consumed.join(" ")
228
+ tehaisStr += " [#{furo.taken}/#{consumedStr}]"
229
+ console.log("[#{i}] tehais: #{tehaisStr}")
230
+ if player.ho
231
+ hoStr = player.ho.join(" ")
232
+ console.log("[#{i}] ho: #{hoStr}")
233
+
234
+ renderPai = (pai, view, pose) ->
235
+ if pose == undefined
236
+ pose = 1
237
+ view.attr("src", paiToImageUrl(pai, pose))
238
+ switch pose
239
+ when 1
240
+ view.addClass("pai")
241
+ view.removeClass("laid-pai")
242
+ when 3
243
+ view.addClass("laid-pai")
244
+ view.removeClass("pai")
245
+ else
246
+ throw("unknown pose")
247
+
248
+ renderPais = (pais, view, poses) ->
249
+ pais ||= []
250
+ poses ||= []
251
+ view.resize(pais.length)
252
+ for i in [0...pais.length]
253
+ renderPai(pais[i], view.at(i), poses[i])
254
+
255
+ renderHo = (player, offset, pais, view) ->
256
+ if player.reachHoIndex == null
257
+ reachIndex = null
258
+ else
259
+ reachIndex = player.reachHoIndex - offset
260
+ view.resize(pais.length)
261
+ for i in [0...pais.length]
262
+ renderPai(pais[i], view.at(i), if i == reachIndex then 3 else 1)
263
+
264
+ renderAction = (action) ->
265
+ #console.log(action.type, action)
266
+ displayAction = {}
267
+ for k, v of action
268
+ if k != "board"
269
+ displayAction[k] = v
270
+ $("#action-label").text(JSON.stringify(displayAction))
271
+ #dumpBoard(action.board)
272
+ kyoku = getCurrentKyoku()
273
+ for i in [0...4]
274
+ player = action.board.players[i]
275
+ view = Dytem.players.at(i)
276
+ infoView = Dytem.playerInfos.at(i)
277
+ infoView.score.text(player.score)
278
+ if !player.tehais
279
+ renderPais([], view.tehais)
280
+ view.tsumoPai.hide()
281
+ else if player.tehais.length % 3 == 2
282
+ renderPais(player.tehais[0...(player.tehais.length - 1)], view.tehais)
283
+ view.tsumoPai.show()
284
+ renderPai(player.tehais[player.tehais.length - 1], view.tsumoPai)
285
+ else
286
+ renderPais(player.tehais, view.tehais)
287
+ view.tsumoPai.hide()
288
+ ho = player.ho || []
289
+ renderHo(player, 0, ho[0...6], view.hoRows.at(0).pais)
290
+ renderHo(player, 6, ho[6...12], view.hoRows.at(1).pais)
291
+ renderHo(player, 12, ho[12...], view.hoRows.at(2).pais)
292
+ view.furos.resize(player.furos.length)
293
+ if player.furos
294
+ j = player.furos.length - 1
295
+ while j >= 0
296
+ furo = player.furos[j]
297
+ furoView = view.furos.at(player.furos.length - 1 - j)
298
+ if furo.type == "ankan"
299
+ pais = ["?"].concat(furo.consumed[0...2]).concat(["?"])
300
+ poses = [1, 1, 1, 1]
301
+ else
302
+ dir = (4 + furo.target - i) % 4
303
+ if furo.type in ["daiminkan", "kakan"]
304
+ laidPos = [null, 3, 1, 0][dir]
305
+ else
306
+ laidPos = [null, 2, 1, 0][dir]
307
+ pais = furo.consumed.concat([])
308
+ poses = [1, 1, 1]
309
+ pais[laidPos...laidPos] = [furo.taken]
310
+ poses[laidPos...laidPos] = [3]
311
+ renderPais(pais, furoView.pais, poses)
312
+ --j
313
+ wanpais = ["?", "?", "?", "?", "?", "?"]
314
+ for i in [0...kyoku.doraMarkers.length]
315
+ wanpais[i + 2] = kyoku.doraMarkers[i]
316
+ renderPais(wanpais, Dytem.wanpais)
317
+
318
+ getCurrentKyoku = ->
319
+ return kyokus[currentKyokuId]
320
+
321
+ renderCurrentAction = ->
322
+ renderAction(getCurrentKyoku().actions[currentActionId])
323
+
324
+ goNext = ->
325
+ return if currentActionId == getCurrentKyoku().actions.length - 1
326
+ ++currentActionId
327
+ $("#action-id-label").val(currentActionId)
328
+ renderCurrentAction()
329
+
330
+ goBack = ->
331
+ return if currentActionId == 0
332
+ --currentActionId
333
+ $("#action-id-label").val(currentActionId)
334
+ renderCurrentAction()
335
+
336
+ $ ->
337
+
338
+ $(window).bind "mousewheel", (e) ->
339
+ e.preventDefault()
340
+ if e.originalEvent.wheelDelta < 0
341
+ goNext()
342
+ else if e.originalEvent.wheelDelta > 0
343
+ goBack()
344
+
345
+ $("#prev-button").click(goBack)
346
+ $("#next-button").click(goNext)
347
+
348
+ $("#go-button").click ->
349
+ currentActionId = parseInt($("#action-id-label").val())
350
+ renderCurrentAction()
351
+
352
+ $("#kyokuSelector").change ->
353
+ currentKyokuId = parseInt($("#kyokuSelector").val())
354
+ currentActionId = 0
355
+ renderCurrentAction()
356
+
357
+ for action in allActions
358
+ loadAction(action)
359
+
360
+ Dytem.init()
361
+ for i in [0...4]
362
+ playerView = Dytem.players.append()
363
+ playerView.addClass("player-#{i}")
364
+ for j in [0...3]
365
+ playerView.hoRows.append()
366
+ playerInfoView = Dytem.playerInfos.append()
367
+ playerInfoView.index.text(i)
368
+ playerInfoView.name.text(playerInfos[i].name)
369
+
370
+ for i in [0...kyokus.length]
371
+ bakazeStr = BAKAZE_TO_STR[kyokus[i].bakaze]
372
+ honba = kyokus[i].honba
373
+ kyokuNum = kyokus[i].kyokuNum
374
+ label = "#{bakazeStr}#{kyokuNum}局 #{honba}本場"
375
+ $("#kyokuSelector").get(0).options[i] = new Option(label, i)
376
+ console.log("loaded")
377
+
378
+ #currentActionId = 78
379
+ renderCurrentAction()
@@ -0,0 +1,505 @@
1
+ var BAKAZE_TO_STR, TSUPAIS, TSUPAI_TO_IMAGE_NAME, cloneBoard, comparePais, currentActionId, currentKyokuId, deleteTehai, dumpBoard, getCurrentKyoku, goBack, goNext, initPlayers, kyokus, loadAction, paiToImageUrl, parsePai, playerInfos, removeRed, renderAction, renderCurrentAction, renderHo, renderPai, renderPais, ripai, sortPais, _base, _base2;
2
+
3
+ window.console || (window.console = {});
4
+
5
+ (_base = window.console).log || (_base.log = function() {});
6
+
7
+ (_base2 = window.console).error || (_base2.error = function() {});
8
+
9
+ TSUPAIS = [null, "E", "S", "W", "N", "P", "F", "C"];
10
+
11
+ TSUPAI_TO_IMAGE_NAME = {
12
+ "E": "ji_e",
13
+ "S": "ji_s",
14
+ "W": "ji_w",
15
+ "N": "ji_n",
16
+ "P": "no",
17
+ "F": "ji_h",
18
+ "C": "ji_c"
19
+ };
20
+
21
+ BAKAZE_TO_STR = {
22
+ "E": "東",
23
+ "S": "南",
24
+ "W": "西",
25
+ "N": "北"
26
+ };
27
+
28
+ kyokus = [];
29
+
30
+ currentKyokuId = 0;
31
+
32
+ currentActionId = 0;
33
+
34
+ playerInfos = [{}, {}, {}, {}];
35
+
36
+ parsePai = function(pai) {
37
+ if (pai.match(/^([1-9])(.)(r)?$/)) {
38
+ return {
39
+ type: RegExp.$2,
40
+ number: parseInt(RegExp.$1),
41
+ red: RegExp.$3 ? true : false
42
+ };
43
+ } else {
44
+ return {
45
+ type: "t",
46
+ number: TSUPAIS.indexOf(pai),
47
+ red: false
48
+ };
49
+ }
50
+ };
51
+
52
+ comparePais = function(lhs, rhs) {
53
+ var lhsRep, parsedLhs, parsedRhs, rhsRep;
54
+ parsedLhs = parsePai(lhs);
55
+ lhsRep = parsedLhs.type + parsedLhs.number + (parsedLhs.red ? "1" : "0");
56
+ parsedRhs = parsePai(rhs);
57
+ rhsRep = parsedRhs.type + parsedRhs.number + (parsedRhs.red ? "1" : "0");
58
+ if (lhsRep < rhsRep) {
59
+ return -1;
60
+ } else if (lhsRep > rhsRep) {
61
+ return 1;
62
+ } else {
63
+ return 0;
64
+ }
65
+ };
66
+
67
+ sortPais = function(pais) {
68
+ return pais.sort(comparePais);
69
+ };
70
+
71
+ paiToImageUrl = function(pai, pose) {
72
+ var ext, name, parsedPai, redSuffix;
73
+ if (pai) {
74
+ if (pai === "?") {
75
+ name = "bk";
76
+ ext = "gif";
77
+ } else {
78
+ parsedPai = parsePai(pai);
79
+ if (parsedPai.type === "t") {
80
+ name = TSUPAI_TO_IMAGE_NAME[pai];
81
+ } else {
82
+ redSuffix = parsedPai.red ? "r" : "";
83
+ name = "" + parsedPai.type + "s" + parsedPai.number + redSuffix;
84
+ }
85
+ ext = parsedPai.red ? "png" : "gif";
86
+ }
87
+ if (pose === void 0) pose = 1;
88
+ return "http://gimite.net/mjai/images/p_" + name + "_" + pose + "." + ext;
89
+ } else {
90
+ return "http://gimite.net/mjai/images/blank.png";
91
+ }
92
+ };
93
+
94
+ cloneBoard = function(board) {
95
+ var bk, bv, newBoard, newPlayer, pk, player, pv, _i, _len;
96
+ newBoard = {};
97
+ for (bk in board) {
98
+ bv = board[bk];
99
+ if (bk === "players") {
100
+ newBoard[bk] = [];
101
+ for (_i = 0, _len = bv.length; _i < _len; _i++) {
102
+ player = bv[_i];
103
+ newPlayer = {};
104
+ for (pk in player) {
105
+ pv = player[pk];
106
+ newPlayer[pk] = pv;
107
+ }
108
+ newBoard[bk].push(newPlayer);
109
+ }
110
+ } else {
111
+ newBoard[bk] = bv;
112
+ }
113
+ }
114
+ return newBoard;
115
+ };
116
+
117
+ initPlayers = function(board) {
118
+ var player, _i, _len, _ref, _results;
119
+ _ref = board.players;
120
+ _results = [];
121
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
122
+ player = _ref[_i];
123
+ player.tehais = null;
124
+ player.furos = [];
125
+ player.ho = [];
126
+ player.reach = false;
127
+ _results.push(player.reachHoIndex = null);
128
+ }
129
+ return _results;
130
+ };
131
+
132
+ removeRed = function(pai) {
133
+ if (!pai) return null;
134
+ if (pai.match(/^(.+)r$/)) {
135
+ return RegExp.$1;
136
+ } else {
137
+ return pai;
138
+ }
139
+ };
140
+
141
+ loadAction = function(action) {
142
+ var actorPlayer, board, furos, i, kyoku, pai, prevBoard, targetPlayer, _i, _j, _len, _len2, _ref, _ref2, _ref3;
143
+ if (kyokus.length > 0) {
144
+ kyoku = kyokus[kyokus.length - 1];
145
+ board = cloneBoard(kyoku.actions[kyoku.actions.length - 1].board);
146
+ } else {
147
+ kyoku = null;
148
+ board = null;
149
+ }
150
+ if (board && ("actor" in action)) {
151
+ actorPlayer = board.players[action.actor];
152
+ } else {
153
+ actorPlayer = null;
154
+ }
155
+ if (board && ("target" in action)) {
156
+ targetPlayer = board.players[action.target];
157
+ } else {
158
+ targetPlayer = null;
159
+ }
160
+ switch (action.type) {
161
+ case "start_game":
162
+ for (i = 0; i < 4; i++) {
163
+ playerInfos[i].name = action.names[i];
164
+ }
165
+ break;
166
+ case "end_game":
167
+ null;
168
+ break;
169
+ case "start_kyoku":
170
+ kyoku = {
171
+ actions: [],
172
+ doraMarkers: [action.dora_marker],
173
+ bakaze: action.bakaze,
174
+ kyokuNum: action.kyoku,
175
+ honba: action.honba
176
+ };
177
+ kyokus.push(kyoku);
178
+ prevBoard = board;
179
+ board = {
180
+ players: [{}, {}, {}, {}]
181
+ };
182
+ initPlayers(board);
183
+ for (i = 0; i < 4; i++) {
184
+ board.players[i].tehais = action.tehais[i];
185
+ if (prevBoard) {
186
+ board.players[i].score = prevBoard.players[i].score;
187
+ } else {
188
+ board.players[i].score = 25000;
189
+ }
190
+ }
191
+ break;
192
+ case "end_kyoku":
193
+ null;
194
+ break;
195
+ case "tsumo":
196
+ actorPlayer.tehais = actorPlayer.tehais.concat([action.pai]);
197
+ break;
198
+ case "dahai":
199
+ deleteTehai(actorPlayer, action.pai);
200
+ actorPlayer.ho = actorPlayer.ho.concat([action.pai]);
201
+ break;
202
+ case "reach":
203
+ actorPlayer.reachHoIndex = actorPlayer.ho.length;
204
+ break;
205
+ case "reach_accepted":
206
+ actorPlayer.reach = true;
207
+ break;
208
+ case "chi":
209
+ case "pon":
210
+ case "daiminkan":
211
+ targetPlayer.ho = targetPlayer.ho.slice(0, (targetPlayer.ho.length - 1));
212
+ _ref = action.consumed;
213
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
214
+ pai = _ref[_i];
215
+ deleteTehai(actorPlayer, pai);
216
+ }
217
+ actorPlayer.furos = actorPlayer.furos.concat([
218
+ {
219
+ type: action.type,
220
+ taken: action.pai,
221
+ consumed: action.consumed,
222
+ target: action.target
223
+ }
224
+ ]);
225
+ break;
226
+ case "ankan":
227
+ _ref2 = action.consumed;
228
+ for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
229
+ pai = _ref2[_j];
230
+ deleteTehai(actorPlayer, pai);
231
+ }
232
+ actorPlayer.furos = actorPlayer.furos.concat([
233
+ {
234
+ type: action.type,
235
+ consumed: action.consumed
236
+ }
237
+ ]);
238
+ break;
239
+ case "kakan":
240
+ deleteTehai(actorPlayer, action.pai);
241
+ actorPlayer.furos = actorPlayer.furos.concat([]);
242
+ furos = actorPlayer.furos;
243
+ for (i = 0, _ref3 = furos.length; 0 <= _ref3 ? i < _ref3 : i > _ref3; 0 <= _ref3 ? i++ : i--) {
244
+ if (furos[i].type === "pon" && removeRed(furos[i].taken) === removeRed(action.pai)) {
245
+ furos[i] = {
246
+ type: "kakan",
247
+ taken: action.pai,
248
+ consumed: action.consumed,
249
+ target: furos[i].target
250
+ };
251
+ }
252
+ }
253
+ break;
254
+ case "hora":
255
+ case "ryukyoku":
256
+ null;
257
+ break;
258
+ case "dora":
259
+ board.doraMarkers = board.doraMarkers.concat([action.dora_marker]);
260
+ break;
261
+ case "log":
262
+ if (kyoku) kyoku.actions[kyoku.actions.length - 1].log = action.text;
263
+ break;
264
+ default:
265
+ throw "unknown action: " + action.type;
266
+ }
267
+ if (action.scores) {
268
+ for (i = 0; i < 4; i++) {
269
+ board.players[i].score = action.scores[i];
270
+ }
271
+ }
272
+ if (kyoku) {
273
+ for (i = 0; i < 4; i++) {
274
+ if (i !== action.actor) ripai(board.players[i]);
275
+ }
276
+ if (action.type !== "log") {
277
+ action.board = board;
278
+ return kyoku.actions.push(action);
279
+ }
280
+ }
281
+ };
282
+
283
+ deleteTehai = function(player, pai) {
284
+ var idx;
285
+ player.tehais = player.tehais.concat([]);
286
+ idx = player.tehais.lastIndexOf(pai);
287
+ if (idx < 0) idx = player.tehais.lastIndexOf("?");
288
+ if (idx < 0) throw "pai not in tehai";
289
+ return player.tehais[idx] = null;
290
+ };
291
+
292
+ ripai = function(player) {
293
+ var pai;
294
+ if (player.tehais) {
295
+ player.tehais = (function() {
296
+ var _i, _len, _ref, _results;
297
+ _ref = player.tehais;
298
+ _results = [];
299
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
300
+ pai = _ref[_i];
301
+ if (pai) _results.push(pai);
302
+ }
303
+ return _results;
304
+ })();
305
+ return sortPais(player.tehais);
306
+ }
307
+ };
308
+
309
+ dumpBoard = function(board) {
310
+ var consumedStr, furo, hoStr, i, player, tehaisStr, _i, _len, _ref, _results;
311
+ _results = [];
312
+ for (i = 0; i < 4; i++) {
313
+ player = board.players[i];
314
+ if (player.tehais) {
315
+ tehaisStr = player.tehais.join(" ");
316
+ _ref = player.furos;
317
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
318
+ furo = _ref[_i];
319
+ consumedStr = furo.consumed.join(" ");
320
+ tehaisStr += " [" + furo.taken + "/" + consumedStr + "]";
321
+ }
322
+ console.log("[" + i + "] tehais: " + tehaisStr);
323
+ }
324
+ if (player.ho) {
325
+ hoStr = player.ho.join(" ");
326
+ _results.push(console.log("[" + i + "] ho: " + hoStr));
327
+ } else {
328
+ _results.push(void 0);
329
+ }
330
+ }
331
+ return _results;
332
+ };
333
+
334
+ renderPai = function(pai, view, pose) {
335
+ if (pose === void 0) pose = 1;
336
+ view.attr("src", paiToImageUrl(pai, pose));
337
+ switch (pose) {
338
+ case 1:
339
+ view.addClass("pai");
340
+ return view.removeClass("laid-pai");
341
+ case 3:
342
+ view.addClass("laid-pai");
343
+ return view.removeClass("pai");
344
+ default:
345
+ throw "unknown pose";
346
+ }
347
+ };
348
+
349
+ renderPais = function(pais, view, poses) {
350
+ var i, _ref, _results;
351
+ pais || (pais = []);
352
+ poses || (poses = []);
353
+ view.resize(pais.length);
354
+ _results = [];
355
+ for (i = 0, _ref = pais.length; 0 <= _ref ? i < _ref : i > _ref; 0 <= _ref ? i++ : i--) {
356
+ _results.push(renderPai(pais[i], view.at(i), poses[i]));
357
+ }
358
+ return _results;
359
+ };
360
+
361
+ renderHo = function(player, offset, pais, view) {
362
+ var i, reachIndex, _ref, _results;
363
+ if (player.reachHoIndex === null) {
364
+ reachIndex = null;
365
+ } else {
366
+ reachIndex = player.reachHoIndex - offset;
367
+ }
368
+ view.resize(pais.length);
369
+ _results = [];
370
+ for (i = 0, _ref = pais.length; 0 <= _ref ? i < _ref : i > _ref; 0 <= _ref ? i++ : i--) {
371
+ _results.push(renderPai(pais[i], view.at(i), i === reachIndex ? 3 : 1));
372
+ }
373
+ return _results;
374
+ };
375
+
376
+ renderAction = function(action) {
377
+ var dir, displayAction, furo, furoView, ho, i, infoView, j, k, kyoku, laidPos, pais, player, poses, v, view, wanpais, _ref, _ref2, _ref3, _ref4;
378
+ displayAction = {};
379
+ for (k in action) {
380
+ v = action[k];
381
+ if (k !== "board") displayAction[k] = v;
382
+ }
383
+ $("#action-label").text(JSON.stringify(displayAction));
384
+ kyoku = getCurrentKyoku();
385
+ for (i = 0; i < 4; i++) {
386
+ player = action.board.players[i];
387
+ view = Dytem.players.at(i);
388
+ infoView = Dytem.playerInfos.at(i);
389
+ infoView.score.text(player.score);
390
+ if (!player.tehais) {
391
+ renderPais([], view.tehais);
392
+ view.tsumoPai.hide();
393
+ } else if (player.tehais.length % 3 === 2) {
394
+ renderPais(player.tehais.slice(0, (player.tehais.length - 1)), view.tehais);
395
+ view.tsumoPai.show();
396
+ renderPai(player.tehais[player.tehais.length - 1], view.tsumoPai);
397
+ } else {
398
+ renderPais(player.tehais, view.tehais);
399
+ view.tsumoPai.hide();
400
+ }
401
+ ho = player.ho || [];
402
+ renderHo(player, 0, ho.slice(0, 6), view.hoRows.at(0).pais);
403
+ renderHo(player, 6, ho.slice(6, 12), view.hoRows.at(1).pais);
404
+ renderHo(player, 12, ho.slice(12), view.hoRows.at(2).pais);
405
+ view.furos.resize(player.furos.length);
406
+ if (player.furos) {
407
+ j = player.furos.length - 1;
408
+ while (j >= 0) {
409
+ furo = player.furos[j];
410
+ furoView = view.furos.at(player.furos.length - 1 - j);
411
+ if (furo.type === "ankan") {
412
+ pais = ["?"].concat(furo.consumed.slice(0, 2)).concat(["?"]);
413
+ poses = [1, 1, 1, 1];
414
+ } else {
415
+ dir = (4 + furo.target - i) % 4;
416
+ if ((_ref = furo.type) === "daiminkan" || _ref === "kakan") {
417
+ laidPos = [null, 3, 1, 0][dir];
418
+ } else {
419
+ laidPos = [null, 2, 1, 0][dir];
420
+ }
421
+ pais = furo.consumed.concat([]);
422
+ poses = [1, 1, 1];
423
+ [].splice.apply(pais, [laidPos, laidPos - laidPos].concat(_ref2 = [furo.taken])), _ref2;
424
+ [].splice.apply(poses, [laidPos, laidPos - laidPos].concat(_ref3 = [3])), _ref3;
425
+ }
426
+ renderPais(pais, furoView.pais, poses);
427
+ --j;
428
+ }
429
+ }
430
+ }
431
+ wanpais = ["?", "?", "?", "?", "?", "?"];
432
+ for (i = 0, _ref4 = kyoku.doraMarkers.length; 0 <= _ref4 ? i < _ref4 : i > _ref4; 0 <= _ref4 ? i++ : i--) {
433
+ wanpais[i + 2] = kyoku.doraMarkers[i];
434
+ }
435
+ return renderPais(wanpais, Dytem.wanpais);
436
+ };
437
+
438
+ getCurrentKyoku = function() {
439
+ return kyokus[currentKyokuId];
440
+ };
441
+
442
+ renderCurrentAction = function() {
443
+ return renderAction(getCurrentKyoku().actions[currentActionId]);
444
+ };
445
+
446
+ goNext = function() {
447
+ if (currentActionId === getCurrentKyoku().actions.length - 1) return;
448
+ ++currentActionId;
449
+ $("#action-id-label").val(currentActionId);
450
+ return renderCurrentAction();
451
+ };
452
+
453
+ goBack = function() {
454
+ if (currentActionId === 0) return;
455
+ --currentActionId;
456
+ $("#action-id-label").val(currentActionId);
457
+ return renderCurrentAction();
458
+ };
459
+
460
+ $(function() {
461
+ var action, bakazeStr, honba, i, j, kyokuNum, label, playerInfoView, playerView, _i, _len, _ref;
462
+ $(window).bind("mousewheel", function(e) {
463
+ e.preventDefault();
464
+ if (e.originalEvent.wheelDelta < 0) {
465
+ return goNext();
466
+ } else if (e.originalEvent.wheelDelta > 0) {
467
+ return goBack();
468
+ }
469
+ });
470
+ $("#prev-button").click(goBack);
471
+ $("#next-button").click(goNext);
472
+ $("#go-button").click(function() {
473
+ currentActionId = parseInt($("#action-id-label").val());
474
+ return renderCurrentAction();
475
+ });
476
+ $("#kyokuSelector").change(function() {
477
+ currentKyokuId = parseInt($("#kyokuSelector").val());
478
+ currentActionId = 0;
479
+ return renderCurrentAction();
480
+ });
481
+ for (_i = 0, _len = allActions.length; _i < _len; _i++) {
482
+ action = allActions[_i];
483
+ loadAction(action);
484
+ }
485
+ Dytem.init();
486
+ for (i = 0; i < 4; i++) {
487
+ playerView = Dytem.players.append();
488
+ playerView.addClass("player-" + i);
489
+ for (j = 0; j < 3; j++) {
490
+ playerView.hoRows.append();
491
+ }
492
+ playerInfoView = Dytem.playerInfos.append();
493
+ playerInfoView.index.text(i);
494
+ playerInfoView.name.text(playerInfos[i].name);
495
+ }
496
+ for (i = 0, _ref = kyokus.length; 0 <= _ref ? i < _ref : i > _ref; 0 <= _ref ? i++ : i--) {
497
+ bakazeStr = BAKAZE_TO_STR[kyokus[i].bakaze];
498
+ honba = kyokus[i].honba;
499
+ kyokuNum = kyokus[i].kyokuNum;
500
+ label = "" + bakazeStr + kyokuNum + "局 " + honba + "本場";
501
+ $("#kyokuSelector").get(0).options[i] = new Option(label, i);
502
+ }
503
+ console.log("loaded");
504
+ return renderCurrentAction();
505
+ });