スクフェス 自動ランキング取得(VB.NET)~パケット取得ver.
スクフェスをPCでプレイする2~キーボードマッピングの追加 - Future Convergence PRJ.まで設定されていることを前提として、イベントの順位情報を自動で取得するプログラムのメモ。
[処理の流れ]
① パケット監視開始(非同期処理)
② BlueStacksからキーボード入力
③ パケットからデータ取得できればパケット監視終了、一定時間待ってもデータが得られなければパケット監視中断
④ 取得したデータ(③で中断した場合は空)からどの画面かを判別して次のキーボード入力内容決定
⑤ ランキングデータがすべて取得できたら終了、まだなら①に戻る
あとはこれをガシガシコーディングするだけなんだけど、デリゲートでの非同期処理は中断できないなど想定外の事態(無知なだけ)に遭遇してだいぶ時間がかかった。できあがったソースは以下の通り。長いし汚いけど、とりあえず動くからOK。使ってる技術は以下の記事を参照。
VB.NETでパケットキャプチャ2~HTTPリクエストボディ・レスポンスボディの取得 - Future Convergence PRJ.
VB.NETでJson形式のデータの取り扱い~Json.NETを使ってみる - Future Convergence PRJ.
SchoolIdolChaserMain.vb
Imports System.Text Imports System.IO Imports SchoolIdolChaser.SchoolIdleChaserConstant Imports Newtonsoft.Json Module SchoolIdolChaserMain 'ランキングデータ Public Structure RankingData Public TotalCnt As Integer Public Ranking As Integer Public Score As Integer Public Sub New(ByVal x_TotalCnt As Integer, ByVal x_Ranking As Integer, ByVal x_Score As Integer) TotalCnt = x_TotalCnt Ranking = x_Ranking Score = x_Score End Sub End Structure 'ネットワーク出力データ(パケットキャプチャ出力) Public Structure OutputData Public RequestMethod As String Public RequestBody As String Public ResponseStatus As String Public ResponseBody As String Public Sub New(ByVal x_RequestMethod As String, ByVal x_RequestBody As String, ByVal x_ResponseStatus As String, ByVal x_ResponseBody As String) RequestMethod = x_RequestMethod RequestBody = x_RequestBody ResponseStatus = x_ResponseStatus ResponseBody = x_ResponseBody End Sub End Structure '画面状態 Public Structure DspStatus Public Reliability As Integer Public Status As Integer Public Sub New(ByVal x_Reliability As Integer, ByVal x_Status As Integer) Reliability = x_Reliability Status = x_Status End Sub End Structure '文字コード Private m_Enc As Encoding = Encoding.UTF8 Private m_EncShiftJis As Encoding = Encoding.GetEncoding("shift-jis") '取得するランキング Private m_TargetList As Byte() = New Byte() {I_RANK_A, I_RANK_B, I_RANK_C, I_RANK_D, I_RANK_E, I_RANK_F, I_RANK_G, I_RANK_S} '画面状態が分からない時の入力(繰り返し) Private m_UnknownList As Byte() = New Byte() {I_NO, I_CLOSE, I_NO, I_OK, I_INVITE, I_HOME} '別スレッドのパケットキャプチャが終了したかどうかの判定フラグ Private m_IsThreadEnd As Boolean = False '別スレッドのパケットキャプチャからの戻り値として使用 Private m_Output As OutputData = Nothing Sub Main() Using wsLog As New System.IO.StreamWriter(LOG_FILE, True, m_EncShiftJis) For tryCount As Integer = 1 To 3 Try '自プロセスをアクティブにする Dim myPs As Process = Process.GetCurrentProcess Interaction.AppActivate(myPs.Id) Threading.Thread.Sleep(1000) wsLog.WriteLine("{0} 処理スタート", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")) Execute(wsLog) Exit For Catch ex As Exception wsLog.WriteLine("{0} 予期せぬ例外が発生[{1}回目]", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), tryCount) wsLog.WriteLine(ex) Threading.Thread.Sleep(180000) End Try Next wsLog.WriteLine("{0} 処理終了", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")) End Using End Sub ''' <summary> ''' このプログラムのメイン処理 ''' キー入力した後のパケットキャプチャから状態を判別して次のキー入力を行う。 ''' ランキングデータがすべて取得するか、キー入力数が最大になった場合に処理終了。 ''' </summary> ''' <param name="wsLog"></param> ''' <remarks></remarks> Sub Execute(ByRef wsLog As System.IO.StreamWriter) Dim rankingDataList As New Dictionary(Of Byte, RankingData) Dim dsp As DspStatus = New DspStatus(RELIABILITY_HIGH - 1, S_HOME) Dim unknownCount As Integer = 0 Dim totalCount As Integer = 1 Dim input As Byte = I_HOME Dim output As OutputData = New OutputData("", "", "", "") Dim isEnd As Boolean = False While True wsLog.WriteLine("{0} インプット[{1}/{2}回目]", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), totalCount, MAX_COUNT) m_IsThreadEnd = False m_Output = New OutputData("", "", "", "") output = New OutputData("", "", "", "") 'ネットワークからデータを取得するスレッドを開始 Dim t As New Threading.Thread(New Threading.ThreadStart(AddressOf GetOutputData)) t.IsBackground = True t.Start() 'Blue Stacksのプロセスをアクティブにする Dim ps() As Process = Process.GetProcessesByName("HD-Frontend") If ps.Length > 0 Then ActiveWindow(ps(0).MainWindowHandle) Interaction.AppActivate(ps(0).Id) End If Threading.Thread.Sleep(1000) 'キー入力 InputAction(input) Console.Write("待機中") For timerCount As Integer = 0 To 4 If m_IsThreadEnd Then 'Exit For End If Threading.Thread.Sleep(1000) Console.Write(".") Next If m_IsThreadEnd Then Console.WriteLine() Console.WriteLine("値取得完了") output = m_Output Else Console.WriteLine() Console.WriteLine("値取得中断") t.Abort() End If dsp = GetDspStatus(dsp, input, output) wsLog.WriteLine("{0} requestMethod={1}", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), output.RequestMethod) If dsp.Reliability > RELIABILITY_LOW Then '画面状態が判明している時 If dsp.Status = S_HOME Then 'ホーム画面の時 wsLog.WriteLine("{0} ホーム画面", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")) wsLog.Flush() isEnd = True For i As Integer = 0 To m_TargetList.Length - 1 isEnd = isEnd And rankingDataList.ContainsKey(m_TargetList(i)) If Not isEnd Then Exit For End If Next If isEnd Then Exit While Else input = I_EVE End If ElseIf dsp.Status = S_EVE Then 'イベント画面の時 wsLog.WriteLine("{0} イベント画面", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")) wsLog.Flush() input = I_RANKING ElseIf dsp.Status = S_RANKING Then 'ランキング画面の時 wsLog.WriteLine("{0} ランキング画面", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")) wsLog.Flush() If input = I_RANKING Then rankingDataList(I_RANK_S) = GetRankingData(output) Else rankingDataList(input) = GetRankingData(output) End If input = I_HOME For i As Integer = 0 To m_TargetList.Length - 1 If Not rankingDataList.ContainsKey(m_TargetList(i)) Then InputAction(I_RANKING_SELECT) Threading.Thread.Sleep(2000) input = m_TargetList(i) Exit For End If Next ElseIf dsp.Status = S_INVITE Then '勧誘画面の時 wsLog.WriteLine("{0} 勧誘画面", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")) wsLog.Flush() input = I_HOME Else wsLog.WriteLine("{0} 画面不明1", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")) wsLog.Flush() input = I_UNKNOWN End If Else '画面状態が不明な時 wsLog.WriteLine("{0} 画面不明2", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")) wsLog.Flush() input = I_UNKNOWN End If If input = I_UNKNOWN Then input = m_UnknownList(unknownCount) unknownCount = unknownCount + 1 If unknownCount >= m_UnknownList.Length Then unknownCount = 0 End If End If wsLog.WriteLine("{0} 次のインプット=[{1}]", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), input) If totalCount >= MAX_COUNT Then Exit While End If totalCount = totalCount + 1 End While 'ランキングデータを出力する Using wsRank As New System.IO.StreamWriter(RANKING_FILE, True, m_EncShiftJis) If isEnd Then wsRank.WriteLine("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},{16},{17}", _ DateTime.Now.ToString("yyyy/MM/dd HH:mm"), rankingDataList(I_RANK_S).TotalCnt, _ rankingDataList(I_RANK_S).Score, rankingDataList(I_RANK_A).Score, rankingDataList(I_RANK_B).Score, _ rankingDataList(I_RANK_C).Score, rankingDataList(I_RANK_D).Score, rankingDataList(I_RANK_E).Score, _ rankingDataList(I_RANK_F).Score, rankingDataList(I_RANK_G).Score, _ rankingDataList(I_RANK_S).Ranking, rankingDataList(I_RANK_A).Ranking, rankingDataList(I_RANK_B).Ranking, _ rankingDataList(I_RANK_C).Ranking, rankingDataList(I_RANK_D).Ranking, rankingDataList(I_RANK_E).Ranking, _ rankingDataList(I_RANK_F).Ranking, rankingDataList(I_RANK_G).Ranking) Else wsRank.WriteLine("{0},,,,,,,,,,,,,,,,,", DateTime.Now.ToString("yyyy/MM/dd HH:mm")) End If wsRank.Flush() End Using End Sub ''' <summary> ''' 画面の状態を返す ''' </summary> ''' <param name="currentStatus"></param> ''' <param name="input"></param> ''' <param name="output"></param> ''' <returns></returns> ''' <remarks></remarks> Private Function GetDspStatus(ByVal currentStatus As DspStatus, ByVal input As Byte, ByVal output As OutputData) As DspStatus Dim updatedStatus As DspStatus = New DspStatus(RELIABILITY_LOW, S_UNKNOWN) If output.RequestMethod.Contains(O_HOME) Then 'ホーム画面確定の時 updatedStatus.Reliability = RELIABILITY_HIGH updatedStatus.Status = S_HOME ElseIf output.RequestMethod.Contains(O_RANKING) Then 'ランキング画面確定の時 updatedStatus.Reliability = RELIABILITY_HIGH updatedStatus.Status = S_RANKING ElseIf output.RequestMethod.Contains(O_INVITE) Then '勧誘画面確定の時 updatedStatus.Reliability = RELIABILITY_HIGH updatedStatus.Status = S_INVITE Else '通信から画面特定不可の時 If currentStatus.Reliability > RELIABILITY_LOW Then If currentStatus.Status = S_HOME Then 'ホーム画面で If input = I_HOME Then 'ホームボタンを押した時 updatedStatus.Reliability = currentStatus.Reliability - 1 updatedStatus.Status = S_HOME ElseIf input = I_EVE Then 'イベントボタンを押した時 updatedStatus.Reliability = currentStatus.Reliability - 1 updatedStatus.Status = S_EVE Else 'それ以外 updatedStatus.Reliability = RELIABILITY_LOW updatedStatus.Status = S_UNKNOWN End If ElseIf currentStatus.Status = S_EVE Then 'イベント画面で If input = I_HOME Then 'ホームボタンを押した時 updatedStatus.Reliability = currentStatus.Reliability - 1 updatedStatus.Status = S_HOME Else 'それ以外 updatedStatus.Reliability = RELIABILITY_LOW updatedStatus.Status = S_UNKNOWN End If ElseIf currentStatus.Status = S_RANKING Then 'ランキング画面で If input = I_HOME Then 'ホームボタンを押した時 updatedStatus.Reliability = currentStatus.Reliability - 1 updatedStatus.Status = S_HOME ElseIf input = I_BACK Then '戻るを押した時 updatedStatus.Reliability = currentStatus.Reliability - 1 updatedStatus.Status = S_EVE Else 'それ以外 updatedStatus.Reliability = RELIABILITY_LOW updatedStatus.Status = S_UNKNOWN End If ElseIf currentStatus.Status = S_INVITE Then '勧誘画面で If input = I_HOME Then 'ホームボタンを押した時 updatedStatus.Reliability = currentStatus.Reliability - 1 updatedStatus.Status = S_HOME Else 'それ以外 updatedStatus.Reliability = RELIABILITY_LOW updatedStatus.Status = S_UNKNOWN End If Else updatedStatus.Reliability = RELIABILITY_LOW updatedStatus.Status = S_UNKNOWN End If End If End If Return updatedStatus End Function ''' <summary> ''' Json形式のデータからランキング情報を取得する ''' </summary> ''' <param name="output"></param> ''' <returns></returns> ''' <remarks></remarks> Private Function GetRankingData(ByVal output As OutputData) As RankingData Dim ranking As RankingData = New RankingData(-1, -1, -1) 'Json文字列をJson形式データに復元する Dim jsonObj As Object = JsonConvert.DeserializeObject(output.ResponseBody) If jsonObj(JSON_STATUS_CODE) = "200" Then If jsonObj(JSON_RESPONSE_DATA) IsNot Nothing Then ranking.TotalCnt = jsonObj(JSON_RESPONSE_DATA)(JSON_TOTAL_CNT) For Each item In jsonObj(JSON_RESPONSE_DATA)(JSON_ITEMS) ranking.Ranking = item(JSON_RANK) ranking.Score = item(JSON_SCORE) Next End If End If Return ranking End Function ''' <summary> ''' バイトコードで指定したキーを押す ''' </summary> ''' <param name="input"></param> ''' <remarks></remarks> Private Sub InputAction(ByVal input As Byte) win32api.keybd_event(input, 0, 0, 0) win32api.keybd_event(input, 0, 2, 0) End Sub ''' <summary> ''' スクフェスサーバとのパケットデータを取得する ''' </summary> ''' <remarks></remarks> Private Sub GetOutputData() Dim output As OutputData = New OutputData("", "", "", "") Dim isBuffered As Boolean = False Dim contentBuff As Byte() = Nothing Dim contentCounter As Integer = 0 Dim contentSize As Integer = 0 Dim isGzip As Boolean = False Dim isReqest As Boolean = False Dim socket As New Net.Sockets.Socket(Net.Sockets.AddressFamily.InterNetwork, Net.Sockets.SocketType.Raw, Net.Sockets.ProtocolType.IP) socket.Bind(New Net.IPEndPoint(Net.IPAddress.Parse(MY_IP_ADDRESS), 0)) socket.SetSocketOption(Net.Sockets.SocketOptionLevel.IP, Net.Sockets.SocketOptionName.AcceptConnection, True) socket.IOControl(Net.Sockets.IOControlCode.ReceiveAll, New Byte() {1, 0, 0, 0}, New Byte() {0, 0, 0, 0}) While True Dim buff As Byte() = New Byte(4095) {} socket.Receive(buff) 'IPパケットのサイズを取得 Dim packetSize As Integer = buff(2) * 256 + buff(3) 'プロトコル番号を取得 Dim protocolNum As Integer = buff(9) '送信元IPを取得 Dim srcIPAddress As String = String.Format("{0}.{1}.{2}.{3}", buff(12), buff(13), buff(14), buff(15)) '送信先IPを取得 Dim dstIPAddress As String = String.Format("{0}.{1}.{2}.{3}", buff(16), buff(17), buff(18), buff(19)) 'スクフェスサーバとのTCP通信のみ処理 If (srcIPAddress = TARGET_IP_ADDRESS Or dstIPAddress = TARGET_IP_ADDRESS) And protocolNum = 6 Then 'TCPの場合ヘッダ長を取得 Dim tcpHeaderLength As Integer = Convert.ToInt32(Convert.ToString(buff(32), 2).PadLeft(8, "0").Substring(0, 4), 2) * 4 'パケットの中身を文字列として取得 Dim packetStr As String = m_Enc.GetString(buff, IP_HEADER_LENGTH + tcpHeaderLength, packetSize) If isBuffered Then 'バッファリング待機中の場合 For i As Integer = IP_HEADER_LENGTH + tcpHeaderLength To packetSize - 1 contentBuff(contentCounter) = buff(i) contentCounter = contentCounter + 1 'ContentSizeを超えるデータ量だった場合は中断(パケット取り違えの場合) If contentCounter >= contentBuff.Length Then Exit For End If Next 'もしパケットにContent-Lengthが含まれていたらバッファリングは中断する If packetStr.Contains("Content-Length:") Then isBuffered = False End If End If If Not isBuffered Then 'バッファリング待機なしの場合 'コンテンツバッファカウンターのクリア contentCounter = 0 'Content-Lengthのクリア contentSize = 0 'リクエストかレスポンスかの判定 isReqest = False 'リクエストヘッダー-メソッドの取得 Dim rGet As New RegularExpressions.Regex("(GET.+?\r\n)", RegularExpressions.RegexOptions.IgnoreCase Or RegularExpressions.RegexOptions.Singleline) Dim mcGet As RegularExpressions.MatchCollection = rGet.Matches(packetStr) For Each m As RegularExpressions.Match In mcGet '正規表現に一致したグループの文字列を表示 output.RequestMethod = m.Groups(1).Value.Replace(Chr(13), "").Replace(Chr(10), "") isReqest = True Exit For Next Dim rPost As New RegularExpressions.Regex("(POST.+?\r\n)", RegularExpressions.RegexOptions.IgnoreCase Or RegularExpressions.RegexOptions.Singleline) Dim mcPost As RegularExpressions.MatchCollection = rPost.Matches(packetStr) For Each m As RegularExpressions.Match In mcPost '正規表現に一致したグループの文字列を表示 output.RequestMethod = m.Groups(1).Value.Replace(Chr(13), "").Replace(Chr(10), "") isReqest = True Exit For Next 'レスポンスヘッダ-ステータスの取得 Dim rStatus As New RegularExpressions.Regex("(HTTP/1.1 200 OK)", RegularExpressions.RegexOptions.IgnoreCase Or RegularExpressions.RegexOptions.Singleline) Dim mcStatus As RegularExpressions.MatchCollection = rStatus.Matches(packetStr) For Each m As RegularExpressions.Match In mcStatus '正規表現に一致したグループの文字列を表示 output.ResponseStatus = m.Groups(1).Value.Replace(Chr(13), "").Replace(Chr(10), "") isReqest = False Exit For Next 'httpヘッダのContent-Lengthを取得 If packetStr.Contains("Content-Length:") Then Dim rContentLength As New RegularExpressions.Regex("Content-Length: ([0-9]+)", RegularExpressions.RegexOptions.IgnoreCase Or RegularExpressions.RegexOptions.Singleline) Dim mcrContentLength As System.Text.RegularExpressions.MatchCollection = rContentLength.Matches(packetStr) For Each m As System.Text.RegularExpressions.Match In mcrContentLength '正規表現に一致したグループの文字列を表示 contentSize = m.Groups(1).Value Exit For Next End If If contentSize > 0 Then 'gzipかどうかの判別 isGzip = packetStr.Contains("Content-Encoding: gzip") 'Contentがスタートする場所を取得 Dim contentStart As Integer = packetSize For i As Integer = 4 To packetSize - 1 If buff(i - 4) = 13 AndAlso buff(i - 3) = 10 AndAlso buff(i - 2) = 13 AndAlso buff(i - 1) = 10 Then contentStart = i Exit For End If Next 'Contentの取得 contentBuff = New Byte(contentSize - 1) {} For i As Integer = contentStart To packetSize - 1 contentBuff(contentCounter) = buff(i) contentCounter = contentCounter + 1 Next End If End If If contentSize > 0 AndAlso contentBuff IsNot Nothing Then If contentCounter >= contentSize - 1 Then 'コンテンツが全部取得できた isBuffered = False If isGzip Then 'GZIPファイルの書き出し Using fs As New System.IO.FileStream(GZIP_TEMP_FILE, System.IO.FileMode.Create, System.IO.FileAccess.Write) fs.Write(contentBuff, 0, contentBuff.Length) End Using 'GZIPファイルの読み込み&解凍書き出し Dim gzipFileStrm As New System.IO.FileStream(GZIP_TEMP_FILE, System.IO.FileMode.Open, System.IO.FileAccess.Read) Using gzipStrm As New System.IO.Compression.GZipStream(gzipFileStrm, System.IO.Compression.CompressionMode.Decompress) Using outFileStrm As New System.IO.FileStream(CONTENT_TEMP_FILE, System.IO.FileMode.Create, System.IO.FileAccess.Write) Dim gzipBuff(1024) As Byte While True '書庫から展開されたデータを読み込む Dim readSize As Integer = gzipStrm.Read(gzipBuff, 0, gzipBuff.Length) '最後まで読み込んだ時は、ループを抜ける If readSize = 0 Then Exit While End If '展開先のファイルに書き込む outFileStrm.Write(gzipBuff, 0, readSize) End While End Using End Using '全読み込み Using sr As New System.IO.StreamReader(CONTENT_TEMP_FILE, m_Enc) If isReqest Then output.RequestBody = sr.ReadToEnd Else output.ResponseBody = sr.ReadToEnd End If End Using File.Delete(CONTENT_TEMP_FILE) File.Delete(GZIP_TEMP_FILE) Else If isReqest Then output.RequestBody = m_Enc.GetString(contentBuff, 0, contentSize) Else output.ResponseBody = m_Enc.GetString(contentBuff, 0, contentSize) End If End If Else 'コンテンツが全部取得できていないので次のパケットを待つ isBuffered = True End If End If If isBuffered = False And output.RequestMethod <> "" And output.ResponseStatus <> "" Then m_Output = output m_IsThreadEnd = True Exit While End If End If End While End Sub Private Sub ActiveWindow(ByVal hWnd As IntPtr) SwitchToThisWindow(hWnd, True) End Sub <Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _ Private Sub SwitchToThisWindow(ByVal hWnd As IntPtr, ByVal fAltTab As Boolean) End Sub End Module Class win32api Public Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Integer, ByVal dwExtraInfo As Integer) End Class
定数は以下のクラスで定義。スクフェスサーバのIPアドレスやURIは伏せてあるので、動かしたいなら調べて設定する必要がある。
SchoolIdleChaserConstant.vb
Public Class SchoolIdleChaserConstant '# '# ユーザ設定にかかわる定数 '# '自分のIPアドレス Public Const MY_IP_ADDRESS As String = "192.168.3.XXX" 'スクフェスサーバのIPアドレス Public Const TARGET_IP_ADDRESS As String = "ここにスクフェスのサーバのIPアドレスを設定する" 'ランキングファイルパス Public Const RANKING_FILE As String = "C:\test\ranking.txt" 'ログファイルパス Public Const LOG_FILE As String = "C:\test\log.txt" 'GZIPの一時ファイルパス Public Const GZIP_TEMP_FILE As String = "C:\test\gzip_temp.gz" 'GZIP解凍の一時ファイルパス Public Const CONTENT_TEMP_FILE As String = "C:\test\content_temp.txt" '# '# システム固有の定数 '# 'キー入力の最大回数(超えた場合処理を終了) Public Const MAX_COUNT As Integer = 200 'IPヘッダ長 Public Const IP_HEADER_LENGTH As Integer = 20 '画面状態の信頼度 Public Const RELIABILITY_HIGH As Integer = 5 Public Const RELIABILITY_LOW As Integer = 1 'キーマッピング Public Const I_UNKNOWN As Byte = 0 Public Const I_HOME As Byte = AscW("H") Public Const I_EVE As Byte = AscW("V") Public Const I_RANKING As Byte = AscW("R") Public Const I_RANKING_SELECT As Byte = AscW("J") Public Const I_RANK_S As Byte = AscW("S") Public Const I_RANK_A As Byte = AscW("A") Public Const I_RANK_B As Byte = AscW("B") Public Const I_RANK_C As Byte = AscW("C") Public Const I_RANK_D As Byte = AscW("D") Public Const I_RANK_E As Byte = AscW("E") Public Const I_RANK_F As Byte = AscW("F") Public Const I_RANK_G As Byte = AscW("G") Public Const I_BACK As Byte = AscW("Q") Public Const I_INVITE As Byte = AscW("I") Public Const I_OK As Byte = AscW("O") Public Const I_CLOSE As Byte = AscW("X") Public Const I_YES As Byte = AscW("Y") Public Const I_NO As Byte = AscW("N") '画面判別 Public Const O_HOME As String = "ここにホーム画面のURIを設定する" Public Const O_RANKING As String = "ここにイベントのランキング画面のURIを設定する" Public Const O_INVITE As String = "ここに勧誘画面のURIを設定する" '画面状態 Public Const S_UNKNOWN As Integer = 0 Public Const S_HOME As Integer = 1 Public Const S_EVE As Integer = 2 Public Const S_RANKING As Integer = 3 Public Const S_INVITE As Integer = 4 'JSONパラメータ Public Const JSON_STATUS_CODE As String = "status_code" Public Const JSON_RESPONSE_DATA As String = "response_data" Public Const JSON_TOTAL_CNT As String = "total_cnt" Public Const JSON_ITEMS As String = "items" Public Const JSON_RANK As String = "rank" Public Const JSON_SCORE As String = "score" End Class