Advertisement
LunaeStellsr

umamusume-guildstat

Mar 6th, 2021
2,223
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 6.85 KB | None | 0 0
  1. require 'win32/api'
  2. require 'win32con'
  3. require 'win32con/keymap'
  4. include Win32CON
  5.  
  6. require 'rtesseract'
  7.  
  8. SendMessage = Win32::API.new('SendMessage', 'LLLL', 'L', 'user32')
  9. GetWindowThreadProcessId = Win32::API.new('GetWindowThreadProcessId', 'LL', 'L', 'user32')
  10. GetAsyncKeyState = Win32::API.new('GetAsyncKeyState', 'L', 'L', 'user32')
  11. GetCursorPos = Win32::API.new('GetCursorPos', 'P', 'V', 'user32')
  12. SetCursorPos = Win32::API.new('SetCursorPos', 'LL', 'V', 'user32')
  13. MouseEvent = Win32::API.new('mouse_event', "LLLLL", 'V', 'user32')
  14. GetForegroundWindow = Win32::API.new('GetForegroundWindow', 'V', 'L', 'user32')
  15. KeybdEvent = Win32::API.new('keybd_event', 'LLLP', 'V', 'user32')
  16. GetSystemMetrics = Win32::API.new('GetSystemMetrics', 'L', 'L', 'user32')
  17.  
  18. EnumWindows     = Win32::API.new('EnumWindows', 'KL', 'L', 'user32')
  19. GetWindowText   = Win32::API.new('GetWindowText', 'LPI', 'I', 'user32')
  20.  
  21. def wait(n); sleep(n); end
  22. alias :uwait :wait
  23.  
  24. module Input
  25.   @keystate  = Array.new(0xff){0}
  26.   @mouse_pos = [0,0]
  27.  
  28.   module_function
  29.   def mouse_pos(real=false)
  30.     if real
  31.       pos = [0, 0].pack("LL"); GetCursorPos.call(pos);
  32.       @mouse_pos = pos.unpack("LL")
  33.     end
  34.     return @mouse_pos
  35.   end
  36.  
  37.   def update
  38.     0xff.times do |i|
  39.       @keystate[i] = (GetAsyncKeyState.call(i) & 0x8000) > 0 ? @keystate[i] + 1 : 0
  40.     end
  41.     pos = [0, 0].pack("LL"); GetCursorPos.call(pos);
  42.     @mouse_pos = pos.unpack("LL")
  43.   end
  44.  
  45.   def trigger?(kcode)
  46.     @keystate[kcode] == 1
  47.   end
  48.  
  49.   def keystate; @keystate; end
  50.  
  51.   def mouse_rdown(use_msg, apply_pos)
  52.     if use_msg
  53.       SendMessage.call($APP_Hwnd, WM_RBUTTONDOWN, 0, 0)
  54.     else
  55.       mx = apply_pos ? (@mouse_pos[0] * 0xffff / $PrimaryScreenWidth).to_i  : 0
  56.       my = apply_pos ? (@mouse_pos[1] * 0xffff / $PrimaryScreenHeight).to_i : 0
  57.       flag  = MOUSEEVENTF_RIGHTDOWN
  58.       flag |= MOUSEEVENTF_ABSOLUTE if apply_pos
  59.       MouseEvent.call(flag, mx, my, 0, 0)
  60.     end
  61.     $flag_pressed = true
  62.   end
  63.  
  64.   def mouse_rup(use_msg, apply_pos)
  65.     mx = apply_pos ? @mouse_pos[0] : 0
  66.     my = apply_pos ? @mouse_pos[1] : 0
  67.     if use_msg
  68.       SendMessage.call($APP_Hwnd, WM_RBUTTONUP, 0, 0)
  69.     else
  70.       mx = apply_pos ? (@mouse_pos[0] * 0xffff / $PrimaryScreenWidth).to_i  : 0
  71.       my = apply_pos ? (@mouse_pos[1] * 0xffff / $PrimaryScreenHeight).to_i : 0
  72.       flag  = MOUSEEVENTF_RIGHTUP
  73.       flag |= MOUSEEVENTF_ABSOLUTE if apply_pos
  74.       MouseEvent.call(flag, mx, my, 0, 0)
  75.     end
  76.     $flag_pressed = false
  77.   end
  78.  
  79.   def mouse_ldown(use_msg,apply_pos)
  80.     if use_msg
  81.       SendMessage.call($APP_Hwnd, WM_LBUTTONDOWN, 0, 0)
  82.     else
  83.       mx = apply_pos ? (@mouse_pos[0] * 0xffff / $PrimaryScreenWidth).to_i  : 0
  84.       my = apply_pos ? (@mouse_pos[1] * 0xffff / $PrimaryScreenHeight).to_i : 0
  85.       flag  = MOUSEEVENTF_LEFTDOWN
  86.       flag |= MOUSEEVENTF_ABSOLUTE if apply_pos
  87.       MouseEvent.call(flag, mx, my, 0, 0)
  88.     end
  89.     $flag_pressed = true
  90.   end
  91.  
  92.   def mouse_lup(use_msg,apply_pos)
  93.     if use_msg
  94.       SendMessage.call($APP_Hwnd, WM_LBUTTONUP, 0, 0)
  95.     else
  96.       mx = apply_pos ? (@mouse_pos[0] * 0xffff / $PrimaryScreenWidth).to_i  : 0
  97.       my = apply_pos ? (@mouse_pos[1] * 0xffff / $PrimaryScreenHeight).to_i : 0
  98.       flag  = MOUSEEVENTF_LEFTUP
  99.       flag |= MOUSEEVENTF_ABSOLUTE if apply_pos
  100.       MouseEvent.call(flag, mx, my, 0, 0)
  101.     end
  102.     $flag_pressed = false
  103.   end
  104.  
  105.   def click_l(use_msg,apply_pos)
  106.     mouse_ldown(use_msg,apply_pos)
  107.     wait(0.03)
  108.     mouse_lup(use_msg,apply_pos)
  109.   end
  110.  
  111.   def click_r(use_msg,apply_pos)
  112.     mouse_rdown(use_msg,apply_pos)
  113.     wait(0.03)
  114.     mouse_rup(use_msg,apply_pos)
  115.   end
  116.  
  117.   def key_down(kid, use_msg=true)
  118.     if use_msg
  119.       SendMessage.call($APP_Hwnd, WM_KEYDOWN, kid, 0)
  120.     else
  121.       KeybdEvent.call(kid, 0, 0, 0)
  122.     end
  123.     $flag_pressed = true
  124.   end
  125.  
  126.   def key_up(kid, use_msg=true)
  127.     if use_msg
  128.       SendMessage.call($APP_Hwnd, WM_KEYUP, kid, 0)
  129.     else
  130.       KeybdEvent.call(kid, 0, 2, 0)
  131.     end
  132.     $flag_pressed = false
  133.   end
  134.  
  135.   def trigger_key(kid, use_msg=true)
  136.     key_down(kid, use_msg)
  137.     wait(0.03)
  138.     key_up(kid, use_msg)
  139.   end
  140.  
  141.   def set_cursor(x,y,use_event=false)
  142.     @mouse_pos = [x,y]
  143.     return SetCursorPos.call(x,y) unless use_event
  144.     x = (x * 0xffff / $PrimaryScreenWidth).to_i
  145.     y = (y * 0xffff / $PrimaryScreenHeight).to_i
  146.     MouseEvent.call(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, x, y, 0, 0)
  147.   end
  148.  
  149.   def moveto(x,y,speed=nil)
  150.     cx,cy = @mouse_pos
  151.     dx = x - cx; dy = y - cy;
  152.     if speed.nil?
  153.       default_speed = 10
  154.       cnt = (Math.hypot(dx,dy) / default_speed).to_i
  155.       if cnt > 42 # prevent it takes too long
  156.         speed = (Math.hypot(dx,dy) / 42).to_i
  157.         cnt   = 42
  158.       else
  159.         speed = default_speed
  160.       end
  161.     else
  162.       cnt = (Math.hypot(dx,dy) / speed).to_i
  163.     end
  164.     angle = Math.atan2(dy, dx)
  165.     dx = speed * Math.cos(angle)
  166.     dy = speed * Math.sin(angle)
  167.     cnt.times{ cx += dx; cy += dy; self.set_cursor(cx, cy, false); wait(0.01);}
  168.     self.set_cursor(x, y, false); self.set_cursor(x, y, false);
  169.   end
  170. end
  171.  
  172. class Integer
  173.   def to_tris
  174.     ret = ''
  175.     self.to_s.each_char.reverse_each.each_with_index do |n,i|
  176.       ret += ',' if i > 0 && i%3 == 0
  177.       ret += n
  178.     end
  179.     ret.reverse
  180.   end
  181. end
  182.  
  183. def scroll_down # scroll down to next 3 members
  184.   Input.update
  185.   Input.set_cursor(1194,776)
  186.   Input.mouse_ldown(false,false)
  187.   sleep(0.5)
  188.   Input.moveto(1194,334, 2)
  189.   sleep(0.5)
  190.   Input.mouse_lup(false,false)
  191. end
  192.  
  193. # OCR can't identify names 100% correctly
  194. $members = ['雪楓Yuki','SuSu','Qazqazqa','chimo','仙人','伏黒ツバキ','レイ','—Yukihana-','亜夜','turtle','yuan-0512','トワイルナスティア','小藍藍藍','柊','ミク','zeta','アメシスト','skifu','M子','BearMochi','なまやん','神無','星露','米豆緑','余','Guozi','J','CM','AscroZ','ming']
  195. $scores  = []
  196.  
  197. def do_capture
  198.   system("screenshot-cmd.exe -wt BlueStacks -rc 788 520 1050 890")
  199.   image = RTesseract.new('screenshot.png', lang: 'jpn+chi_tra')
  200.   puts image.to_s
  201.   image.to_s.split(/[\r\n]+/).each do |line|
  202.     next unless line.strip.end_with? '人'
  203.     number = ''
  204.     line = line.split(/(\s||)/).last
  205.     line.each_char{|ch| number += ch if ch.match(/\d/)}
  206.     $scores << number.to_i
  207.   end
  208. end
  209.  
  210. (ARGV[0].to_i / 3).times do
  211.   do_capture
  212.   scroll_down
  213. end
  214.  
  215. dict = Hash[$members.zip $scores]
  216. sign_delta = "▲"
  217. puts "馬娘コネ 每周進度報告 (結算時間: #{Time.now.to_s.split('+').first})"
  218. puts "成員數 #{ARGV[0].to_i}/30"
  219. puts "總粉絲數 #{$scores.sum.to_tris} 排名 #{ARGV[1]}位 (#{ARGV[2]})"
  220. puts "======= 成員概況 ======="
  221. dict.each do |k,v|
  222.   delta = 0
  223.   puts "#{k}: #{v.to_tris} (#{sign_delta} #{delta})"
  224. end
  225. puts "======================="
  226.  
  227. File.open("data/#{Time.now.to_s.split.first}.dat", 'wb') do |fp|
  228.   Marshal.dump(dict, fp)
  229. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement