差分

DiceAdapterの途中まで
[[どどんとふ]]からの[[BCDice]]の呼び出し方。このページでは、Rubyで書かれたどどんとふのサーバのダイス関連の処理を扱う。[https://github.com/torgtaitai/DodontoF/tree/d3e4cc374885986efc761cfabbb19e4b35e815e0 v1.49.04.01]のソースコードを参考にしている。

== ファイルの役割 ==

どどんとふのサーバでは、ダイスボットとの通信の処理は以下のファイルに記述されている。

* [https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/src_ruby/dodontof/dice_adapter.rb src_ruby/dodontof/dice_adapter.rb]:BCDiceとのアダプタ
* [https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/src_ruby/diceBotInfos.rb src_ruby/diceBotInfos.rb]:ダイスボットの情報を取得する処理
* [https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb DodontoFServer.rb]:サーバ本体

== src_ruby/dodontof/dice_adapter.rb:BCDiceとのアダプタ ==

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/src_ruby/dodontof/dice_adapter.rb

=== L7-L10:<code>DiceAdapter#initialize</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/src_ruby/dodontof/dice_adapter.rb#L7-L10

アダプタを初期化する。

* <code>@dir</code>:部屋固有のデータ保存ディレクトリが設定される。詳細は「[[#L164-L185:@dice_adapter の初期化]]」で解説する。
* <code>@diceBotTablePrefix</code>:必ず <code>'diceBotTable_'</code> が設定される。

<syntaxhighlight lang="ruby">
def initialize(dir, prefix)
@logger = DodontoF::Logger.instance
@dir = dir
@diceBotTablePrefix = prefix
end
</syntaxhighlight>

=== L13-L34:<code>DiceAdapter#rollDice</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/src_ruby/dodontof/dice_adapter.rb#L13-L34

ダイスロールを行う。メッセージ、ゲームシステム、出目を返すかが指定できる。結果のメッセージ、シークレットダイスかどうか、出目が返る。結果のメッセージの <code>'>'</code> は <code>'→'</code> に置換され、末尾の改行コードは削除される。

<syntaxhighlight lang="ruby">
def rollDice(params)
require 'cgiDiceBot.rb'

message = params['message']
gameType = params['gameType']
isNeedResult = params['isNeedResult']

@logger.debug(message, 'rollDice message')
@logger.debug(gameType, 'rollDice gameType')

bot = CgiDiceBot.new

result, randResults = bot.roll(message, gameType, @dir, @diceBotTablePrefix, isNeedResult)

result.gsub!(/>/, '→')
result.sub!(/\r?\n?\Z/m, '')

@logger.debug(result, 'rollDice result')
@logger.debug(randResults, 'rollDice randResults')

return result, bot.isSecret, randResults
end
</syntaxhighlight>

=== L36-L45:<code>DiceAdapter#getGameCommandInfos</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/src_ruby/dodontof/dice_adapter.rb#L36-L45

<syntaxhighlight lang="ruby">
def getGameCommandInfos
require 'cgiDiceBot.rb'
bot = CgiDiceBot.new
@logger.debug(@dir, 'dir')

commandInfos = bot.getGameCommandInfos(@dir, @diceBotTablePrefix)
@logger.debug(commandInfos, "getGameCommandInfos End commandInfos")

return commandInfos
end
</syntaxhighlight>

== src_ruby/diceBotInfos.rb:ダイスボットの情報を取得する処理 ==

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/src_ruby/diceBotInfos.rb

=== L69-L102:<code>DiceBotInfos.get</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/src_ruby/diceBotInfos.rb#L69-L102

<syntaxhighlight lang="ruby">
# ダイスボットの情報の一覧を取得する
# @param [Array<String>] orderedGameNames 順序付けられたゲーム名の配列
# @param [Boolean] showAllDiceBots すべてのダイスボットを表示するか
# @return [Array<Hash>]
def self.get(orderedGameNames, showAllDiceBots)
diceBots = DiceBotLoader.collectDiceBots

# ゲーム名 => ダイスボットの対応を作る
diceBotFor = Hash[
diceBots.map { |diceBot| [diceBot.gameName, diceBot] }
]
toDiceBot = lambda { |gameName| diceBotFor[gameName] }

orderedEnabledDiceBots = orderedGameNames.
map(&toDiceBot).
# ゲーム名が誤記されていた場合nilになるので除く
compact

orderedDiceBots =
if showAllDiceBots
disabledGameNames = diceBotFor.keys - orderedGameNames
orderedDisabledDiceBots = disabledGameNames.
sort.
map(&toDiceBot)

# 一覧に記載されていたゲーム→記載されていなかったゲームの順
orderedEnabledDiceBots + orderedDisabledDiceBots
else
orderedEnabledDiceBots
end

# 指定なし→各ゲーム→基本の順で返す
[NONE_DICE_BOT_INFO] + orderedDiceBots.map(&:info) + [BASE_DICE_BOT_INFO]
end
</syntaxhighlight>

=== L104-150:<code>DiceBotInfos.withTableCommands</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/src_ruby/diceBotInfos.rb#L104-150

<syntaxhighlight lang="ruby">
# テーブルのコマンドも加えたダイスボットの情報の一覧を取得する
# @param [Array<String>] orderedGameNames 順序付けられたゲーム名の配列
# @param [Boolean] showAllDiceBots すべてのダイスボットを表示するか
# @param [Array<Hash>] commandInfos テーブルのコマンドの情報の配列
# @return [Array<Hash>]
#
# このメソッドは、ダイスボットから返された情報を破壊しない。
def self.withTableCommands(orderedGameNames, showAllDiceBots, commandInfos)
diceBotInfos = self.get(orderedGameNames, showAllDiceBots)

# ゲームタイプ => ダイスボット情報のインデックスの対応を作る
diceBotInfoIndexFor = Hash[
diceBotInfos.each_with_index.map { |info, i| [info[KEY_GAME_TYPE], i] }
]
allGameTypes = diceBotInfoIndexFor.keys

# ゲームタイプ => 追加するコマンドの一覧の対応を作る
commandsToAdd = commandInfos.reduce({}) { |acc, commandInfo|
gameType = commandInfo[KEY_GAME_TYPE]
command = commandInfo[KEY_COMMAND]

# ゲームタイプ未指定ならすべてのゲームタイプに追加する
targetGameTypes = gameType.empty? ? allGameTypes : [gameType]

targetGameTypes.each do |targetGameType|
acc[targetGameType] ||= []
acc[targetGameType] << command
end

acc
}

commandsToAdd.each do |gameType, commands|
diceBotInfoIndex = diceBotInfoIndexFor[gameType]
next unless diceBotInfoIndex

originalInfo = diceBotInfos[diceBotInfoIndex]

# ダイスボットから返された情報を破壊しないようにして更新する
diceBotInfos[diceBotInfoIndex] = originalInfo.merge({
KEY_PREFIXS => originalInfo[KEY_PREFIXS] + commands
})
end

diceBotInfos
end
</syntaxhighlight>

== DodontoFServer.rb:サーバ本体 ==

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb

=== L164-L185:<code>@dice_adapter</code> の初期化 ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L164-L185

<syntaxhighlight lang="ruby">
def initialize(saveDirInfo, cgiParams)
@cgiParams = cgiParams
@saveDirInfo = saveDirInfo

@logger = DodontoF::Logger.instance
@cgi = nil

@jsonpCallBack = nil
@isWebIf = false
@isRecordEmpty = false

initSaveFiles(getRequestData('room'))
@dice_adapter = DodontoF::DiceAdapter.new(getDiceBotExtraTableDirName, 'diceBotTable_')

@fullBackupFileBaseName = "DodontoFFullBackup"

@allSaveDataFileExt = '.tar.gz'
@defaultAllSaveData = 'default.sav'
@defaultChatPallete = 'default.cpd'

@card = nil
end
</syntaxhighlight>

<code>getDiceBotExtraTableDirName</code>([https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3727-L3729 L3727-L3729])では、<code>getRoomLocalSpaceDirName</code>([https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3262-L3265 L3262-L3265])、<code>getRoomLocalSpaceDirNameByRoomNo</code>([https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3267-L3273 L3267-L3273])を経由して、<code>$imageUploadDir</code> の中の部屋固有のディレクトリを返す。

=== L1193-L1210:<code>getWebIfServerInfo</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L1193-L1210

Webインターフェースのサーバ情報を返すコマンド。<code>getDiceBotInfos</code> でダイスボットの情報を取得する。

<syntaxhighlight lang="ruby">
def getWebIfServerInfo()
jsonData = {
"maxRoom" => ($saveDataMaxCount - 1),
'isNeedCreatePassword' => (not $createPlayRoomPassword.empty?),
'result' => 'OK',
}

if( getWebIfRequestBoolean("card", false) )
cardInfos = getCardsInfo.collectCardTypeAndTypeName($cardOrder)
jsonData["cardInfos"] = cardInfos
end

if( getWebIfRequestBoolean("dice", false) )
jsonData['diceBotInfos'] = getDiceBotInfos()
end

return jsonData
end
</syntaxhighlight>

=== L2090:<code>getLoginInfo</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L2090

ダイスボット情報の取得を行う。

<syntaxhighlight lang="ruby">
diceBotInfos = getDiceBotInfos()
</syntaxhighlight>

=== L2266-L2280:<code>getDiceBotInfos</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L2266-L2280

ダイスボット情報取得処理の実装。部屋に入っているかどうかで、テーブルのコマンドも含めた情報を返すかどうかを決定している。

<syntaxhighlight lang="ruby">
def getDiceBotInfos
@logger.debug("getDiceBotInfos() Begin")

require 'diceBotInfos'

orderedGameNames = $diceBotOrder.split("\n")

if @saveDirInfo.getSaveDataDirIndex != -1
DiceBotInfos.withTableCommands(orderedGameNames,
$isDisplayAllDice,
@dice_adapter.getGameCommandInfos)
else
DiceBotInfos.get(orderedGameNames, $isDisplayAllDice)
end
end
</syntaxhighlight>

=== L2542-2556:<code>save</code>, <code>getDiceTableData</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L2542-2556

部屋のデータの保存時に、独自の表についての情報を取得する。

<syntaxhighlight lang="ruby">
def save()
isAddPlayRoomInfo = true
extension = @@saveFileExtension

addInfos = {}
addInfos[$diceBotTableSaveKey] = getDiceTableData()

saveSelectFiles($saveFiles.keys, extension, isAddPlayRoomInfo, addInfos)
end

def getDiceTableData()
tableInfos = @dice_adapter.getBotTableInfosFromDir
tableInfos.each{|i| i.delete('fileName') }
return tableInfos
end
</syntaxhighlight>

=== L2806-L2817:<code>getBotTableInfos</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L2806-L2817

独自の表についての情報を取得する。

<syntaxhighlight lang="ruby">
def getBotTableInfos()
@logger.debug("getBotTableInfos Begin")
result = {
"resultText"=> "OK",
}

result["tableInfos"] = @dice_adapter.getBotTableInfosFromDir

@logger.debug(result, "result")
@logger.debug("getBotTableInfos End")
return result
end
</syntaxhighlight>

=== L2819-L2835:<code>addBotTable</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L2819-L2835

独自の表を追加する。

<syntaxhighlight lang="ruby">
def addBotTable()
result = {}

params = getParamsFromRequestData()
result['resultText'] = @dice_adapter.addBotTableMain(params)

if( result['resultText'] != "OK" )
return result
end

@logger.debug("addBotTableMain called")

result = getBotTableInfos()
@logger.debug(result, "addBotTable result")

return result
end
</syntaxhighlight>

=== L2837-L2849:<code>changeBotTable</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L2837-L2849

独自の表を変更する。

<syntaxhighlight lang="ruby">
def changeBotTable()
params = getParamsFromRequestData()

result = {}
result['resultText'] = @dice_adapter.changeBotTableMain(params)

if( result['resultText'] != "OK" )
return result
end

result = getBotTableInfos()
return result
end
</syntaxhighlight>

=== L2851-L2855:<code>removeBotTable</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L2851-L2855

独自の表を削除する。

<syntaxhighlight lang="ruby">
def removeBotTable()
params = getParamsFromRequestData()
@dice_adapter.removeBotTableMain(params)
return getBotTableInfos()
end
</syntaxhighlight>

=== L3458-L3459:<code>loadSaveFileDataFilterByTargets</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3458-L3459

セーブデータの部分読み込み処理の一部。独自の表を読み込む。

<syntaxhighlight lang="ruby">
when "diceBotTable"
loadDiceBotTable(jsonData)
</syntaxhighlight>

=== L3511-L3531:<code>loadDiceBotTable</code>, <code>getDiceBotTableString</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3511-L3531

独自の表を読み込む。

<syntaxhighlight lang="ruby">
def loadDiceBotTable(jsonData)

data = jsonData[$diceBotTableSaveKey]
return if( data.nil? )

data.each do |info|
info['table'] = getDiceBotTableString(info['table'])
@dice_adapter.addBotTableMain(info)
end

end

def getDiceBotTableString(table)

lines = []
table.each do |line|
lines << line.join(":")
end

return lines.join("\n")
end
</syntaxhighlight>

=== L3632-L3657:<code>sendDiceBotChatMessage</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3632-L3657

BCDiceにコマンドを送る処理。<code>回数 コマンド</code> という形で送信回数が指定されていた場合は、指定された回数だけコマンドをBCDiceに送る。

<syntaxhighlight lang="ruby">
def sendDiceBotChatMessage
@logger.debug('sendDiceBotChatMessage')

params = getParamsFromRequestData()

repeatCount = getDiceBotRepeatCount(params)

results = []

repeatCount.times do |i|

paramsClone = params.clone
paramsClone['message'] += " \##{ i + 1 }" if( repeatCount > 1 )

result = sendDiceBotChatMessageOnece( paramsClone )
@logger.debug(result, "sendDiceBotChatMessageOnece result")

next if( result.nil? )

results << result
end

@logger.debug(results, "sendDiceBotChatMessage results")

return results
end
</syntaxhighlight>

=== L3659-L3669:<code>getDiceBotRepeatCount</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3659-L3669

コマンド送信回数を1〜20回に制限する。最近のRubyでは <code>(params['repeatCount'] || 1).clamp(1, 20)</code> と簡潔に書ける。

<syntaxhighlight lang="ruby">
def getDiceBotRepeatCount(params)
repeatCountLimit = 20

repeatCount = params['repeatCount']

repeatCount ||= 1
repeatCount = 1 if( repeatCount < 1 )
repeatCount = repeatCountLimit if( repeatCount > repeatCountLimit )

return repeatCount
end
</syntaxhighlight>

=== L3672-L3709:<code>sendDiceBotChatMessageOnece</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3672-L3709

BCDiceに1回分(おそらく <code>Onece</code> は <code>once</code> のスペルミス)のコマンドを送る処理。<code>getRollDiceResult</code> でダイスロールした結果を取得する。<code>sendChatMessageByChatData</code>([https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3817-3839 L3817-3839])で、その結果を含むメッセージを送信する。

<syntaxhighlight lang="ruby">
def sendDiceBotChatMessageOnece(params)

rolledMessage, isSecret, secretMessage = getRollDiceResult( params )

senderName = params['name']
unless /\t/ === senderName
state = params['state']
senderName += ("\t" + state) unless( state.empty? )
end

chatData = {
"senderName" => senderName,
"message" => rolledMessage,
"color" => params['color'],
"uniqueId" => '0',
"channel" => params['channel']
}

sendto = params['sendto']
unless( sendto.nil? )
chatData['sendto'] = sendto
chatData['sendtoName'] = sendtoName
end

@logger.debug(chatData, 'sendDiceBotChatMessageOnece chatData')

sendChatMessageByChatData(chatData)


result = nil
if( isSecret )
params['isSecret'] = isSecret
params['message'] = secretMessage
result = params
end

return result
end
</syntaxhighlight>

=== L3672-L3725:<code>getRollDiceResult</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3672-L3709

BCDiceでダイスを振る。シークレットダイスかどうかも考慮してメッセージを加工し、返す。

<syntaxhighlight lang="ruby">
def getRollDiceResult( params )
params['originalMessage'] = params['message']
rollResult, isSecret, randResults = @dice_adapter.rollDice(params)

secretMessage = ""
if( isSecret )
secretMessage = params['message'] + rollResult
else
params['message'] += rollResult
end

rolledMessage = getRolledMessage(params, isSecret, randResults)

return rolledMessage, isSecret, secretMessage
end
</syntaxhighlight>

=== L3732-L3762:<code>getRolledMessage</code> ===

https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3732-L3709

ダイスロールの結果を入力として、どどんとふクライアントでの表示に必要な情報を付加する。シークレットダイスの場合に結果を隠すことと、「!」の数でサイコロを強調できるようにすることが目的のようだ。

<syntaxhighlight lang="ruby">
def getRolledMessage(params, isSecret, randResults)
@logger.debug("getRolledMessage Begin")

@logger.debug(isSecret, "isSecret")
@logger.debug(randResults, "randResults")

if( isSecret )
params['message'] = getLanguageKey('secretDice')
randResults = randResults.collect{|value, max| [0, 0] }
end

message = params['message']

if( randResults.nil? )
@logger.debug("randResults is nil")
return message
end


data = {
"chatMessage" => message,
"randResults" => randResults,
"uniqueId" => params['uniqueId'],
"power" => getDiceBotPower(params),
}

text = "###CutInCommand:rollVisualDice###" + getJsonString(data)
@logger.debug(text, "getRolledMessage End text")

return text
end
</syntaxhighlight>

[[Category:BCDice/TRPGツールからの呼び出し方]]
{{DEFAULTSORT:ととんとふ}}