ふかふかブログ

興味のあることについてゆる~く書きます

最近使っているガジェット(オーディオ周り編)

※この記事は Splathon Advent Calendar 2025 の6日目の記事になります。

昨日は あすみすさんの 【スプラトゥーン3】ガチマ戦記|XP2500の壁を越えるまででした。

XP2500の壁を越えるまでの熱い話があって大変興味深かったですね!

さて、 最近知人がリモートワークやオンラインゲームの通話・音声周りを整えたいという相談があり、自分が使っているガジェットを紹介する機会があったので誰かのためになるかもと思いここにも残しておきます。

気になる製品があれば個別に聞いてもらえるとある程度お答えできるかと思います。

1. 軟骨伝導イヤホン

kakaku.com

  • 製品名: ATH-CC500BT2
  • 用途: おもにジム、保育園送迎
  • ひとこと: 以前はShokzを使っていたがこっちのほうが気持ち音質がいい。

2. ヘッドホン

kakaku.com

  • 製品名: MDR-ZX110
  • 用途: 仕事用、通話しながらやるゲーム用
  • ひとこと: 軽い、側圧が弱いので長時間つけても苦にならない

3. 無線ヘッドホン

kakaku.com

  • 製品名: WH-1000XM5
  • 用途: 集中したいとき、通話せずにやるゲーム用
  • ひとこと: ノイキャン優秀、長時間つけたあと外すと世界の煩さに気づいてしまう

4. 無線イヤホン

kakaku.com

  • 製品名: INZONE Buds WF-G700N
  • 用途: スト6用
  • ひとこと: ノイキャンそこそこ、無線助かる

5. マイク

kakaku.com

  • 製品名: AT2020
  • 用途: 仕事&ゲーム通話用
  • ひとこと: こだわりないので人気のやつ

6. オーディオインターフェース

kakaku.com

  • 製品名: ZG01
  • 用途: Switchのゲームしながら通話したいだけ
  • ひとこと: 用途に対しての値段が割に合わないのでおすすめしない

7. USBスピーカー

kakaku.com

  • 製品名: MM-SPUTC1BK
  • 用途: 耳だけ通話に参加するとき、子どもとPCでゲームするとき
  • ひとこと: USB接続助かる

以上、明日はつっちーさんの「細かすぎて伝わらないミュージカルの好きな演出n選」です。

細かすぎて伝わらないシリーズ大好きなので気になりますね!

スプラトゥーン3プレイヤー向け!ストリートファイター6で自分に合ったキャラを見つけよう

※この記事は Splathon Advent Calendar 2024 の15日目の記事になります。

スプラトゥーンプレイヤーのみなさまこんにちは。ふかふかです。

「たまには息抜きでほかのゲームもやってみたいな。」「ストリートファイター6って面白そうだけど、格闘ゲームは難しそう...」そんな風に思っている方も多いのではないでしょうか?

この記事では、普段皆さんが使用しているブキ種ごとに、プレイスタイルの似ているストリートファイター6のキャラクターを紹介していきます。 キャラ選びの参考にしていただければ。

※初めての方想定ということで追加キャラクター(DLC)は除外してあります。

※この記事を書いている人は現時点で初心者なので以下の文章はイメージを多く含んでいます。迷ったらお近くの有識者に聞いてください。

シューター使いにおすすめのキャラ:ケン、リュウ

シューターの特徴といえば、 バランスが良く、汎用性が高いプレイスタイル ですよね。どの距離でも安定した戦いが可能で、初めての人でも扱いやすいのが魅力です。

ストリートファイター6でこの特徴に当てはまるのが ケン、リュウ です。ケン、リュウは「波動拳」や「昇竜拳」など、 オーソドックスで扱いやすい技を持つバランス型キャラクター です。攻めるも守るも自在で、初心者から上級者まで幅広いプレイヤーに愛されています。


ローラー使いにおすすめのキャラ:ザンギエフ

ローラーを使うプレイヤーは、 近距離戦に強く、一撃必殺を狙うパワープレイ を得意としているはず。地形やタイミングを駆使して相手に強力な一撃を叩き込むスタイルです。

ザンギエフは 近距離での投げ技が非常に強力 なキャラクター。間合いを詰めて相手を掴むことで、試合の流れを一気に変えることが可能です。ローラーの「確実に仕留める」感覚をザンギエフでも活かしてみましょう!


チャージャー使いにおすすめのキャラ:JP

チャージャー使いは、 狙いを定めて正確にヒットさせるスナイパー的なプレイ を得意とします。遠距離からの精密な攻撃が魅力ですよね。

ストリートファイター6では、 遠距離戦が得意なJP がまさにチャージャー使いにぴったりのキャラクターです。JPは飛び道具を駆使して、 安全な位置から相手を追い詰める戦術 が可能。慎重かつ冷静なプレイスタイルをチャージャーの感覚で楽しめます。


スロッシャー使いにおすすめのキャラ:マリーザ

スロッシャー使いは、 曲線的な攻撃で相手の隙を突く のが得意。立ち位置や角度を考えながら攻撃を仕掛ける戦術が特徴です。

マリーザは、 パワーと範囲攻撃 を併せ持つキャラクター。広い攻撃範囲で相手を圧倒しつつ、大技で確実にダメージを与えるスタイルが、スロッシャーの戦い方と似ています。スロッシャーの立ち回りを活かしつつ、パワフルな攻撃を楽しめます!


スピナー使いにおすすめのキャラ:キャミィ

スピナーは、 素早い動きで相手を翻弄し、連続攻撃でプレッシャーを与えるスタイル が特徴。機動力を活かした戦術が得意な人に向いています。

キャミィは、 高い機動力と連続技の豊富さ で知られるキャラクターです。素早い移動技「スパイラルアロー」や、空中からの奇襲技で相手をかき乱すことができます。スピナーのスピード感と攻撃力を活かしたプレイがそのままフィットするでしょう。


マニューバー使いにおすすめのキャラ:ジェイミー

マニューバー使いは、 機動力とステップを活かしたトリッキーな動き が特徴。攻撃と回避を両立しつつ、狙いを定めて仕掛ける戦術を得意とします。

ジェイミーは、 ステップや動きの自由度が高い キャラクターで、攻撃中に次々と動きを変えて相手を翻弄するのが得意です。マニューバーの「動きながら攻める」スタイルを存分に活かせるでしょう。


シェルター使いにおすすめのキャラ:ブランカ

シェルター使いは、 防御と攻撃を兼ね備えたプレイスタイル が特徴。守りを固めながら、じっくりと攻撃のチャンスを狙います。

ブランカは、 トリッキーな動きと強力な防御能力 を持つキャラクター。電撃を使ったカウンターや独特の動きで、守りを固めつつ攻撃に転じる戦い方が可能です。シェルターの「攻防一体」の感覚をそのまま活かせます。


ブラスター使いにおすすめのキャラ:ケン

ブラスターは、 爆発的な威力と範囲攻撃を活かした戦術 が特徴。近~中距離で相手に一気にプレッシャーを与えるプレイが得意です。

ケンは、リュウよりも攻撃的でスピード感のあるプレイスタイルを持つキャラクター。 突進技や素早い連続攻撃 を駆使して、一気に攻め立てることができます。ブラスタ―の「攻めの圧」をそのまま格闘ゲームで表現できるでしょう。


フデ使いにおすすめのキャラ:キンバリー

フデ使いは、 独特な動きとテクニカルな操作で相手を混乱させる プレイスタイルが魅力。狭い範囲でも素早く動ける人にぴったりです。

ストリートファイター6では、 トリッキーな動きとスピード を持つキンバリーがフデ使いにおすすめです。高速移動や奇襲技を駆使しながら、 相手を翻弄する戦術 を楽しめます。フデの繊細なコントロールがキンバリーでも活かされるはず!


ストリンガー使いにおすすめのキャラ:ダルシム

ストリンガー使いは、 長射程を活かして遠距離から攻撃する戦術 が得意。距離を保ちながら相手にダメージを与えるプレイが特徴です。

ダルシムは、 長いリーチを持つ通常技と飛び道具 を活かして遠距離戦を得意とするキャラクターです。ストリンガーの「遠距離からの精密攻撃」の感覚をそのまま楽しむことができます。


ワイパー使いにおすすめのキャラ:ルーク

ワイパー使いは、 スピード感と切れ味のある攻撃 を得意とします。相手の隙を突いて一気に攻める戦術が特徴です。

ルークは、 スピーディーで攻撃力の高いコンボ を持つキャラクター。素早い動きと強力な連続技で、ワイパーのスピード感をそのまま再現するようなプレイスタイルを楽しめます。


以上、スプラトゥーン3プレイヤー向け!ストリートファイター6で自分に合ったキャラを見つけようでした。 明日はtorakouさんの「クルーズ旅行の感想」です。お楽しみに~。

ブラウザ&OBSで実現する簡単映像注釈テクニック

ブラウザ&OBSで実現する簡単映像注釈テクニック

はじめに

この記事ではブラウザとOBSを使って映像に注釈(線など)を入れる方法を紹介します。 映像に注釈を入れる方法はいろいろありますが、ここではOBSのウィンドウキャプチャ(≠画面キャプチャ)を使う方法を紹介します。

対象読者

  • ゲーム画面にリアルタイムで書き込みながらワイワイ作戦会議したい
  • 配信中にゲーム画面に書き込みたい(画面キャプチャはセキュリティの関係上したくない)

実際の動作

見ていただいたほうがわかりやすいと思うので画像と動画を貼ります。

注釈を入れている画像
ブラウザ側側でビデオキャプチャを取り込んでいる様子

youtu.be

導入方法(10分)

  1. GitHub - nohararc/obs-browser-simple-annotator の obs-browser-simple-annotator.htmlをダウンロードし、ブラウザで開く
  2. (ここでキャプチャボードの映像が映らない場合は、使いたいキャプチャボードだけ有効にするorカメラを選択するコードを追加するなりしてください)
  3. OBSの ソース > ウィンドウキャプチャ で先ほどのhtmlを開いているブラウザを選択する
  4. 3で追加したウィンドウキャプチャのサイズと位置をいい感じに調整する、細かい調整が必要な場合、ここが一番時間がかかるかもしれません。自動でいい感じにできる方法ご存じの方は教えてください。

使い方

  • 基本的な操作手順
    • 左クリックで赤い線
    • 右クリックで青い線
    • 'c'で注釈クリア

技術的な仕組み

  • HTMLのvideo要素でカメラ(今回はキャプチャボード)表示部分を実装
  • HTMLのcanvas要素で注釈部分を実装
    • 見やすさのために若干影を入れている。フロントエンドに明るくないのでPRお待ちしております。
  • OBSの仮想カメラを使うほうがよりシンプルになるのですが、なぜかOBSのカメラはOSから見えなかったのでこの実装になっています
  • NDI等を駆使してiPadで書き込み→OBSに流し込む方法も調査したが時間かかりそうなので今回はパス

github.com

動作環境

  • Windows11
  • OBS Studio 30.2.2(64bit)

スプラトゥーン3のスケジュールをGoogleカレンダーに登録してみなイカ

こちらの記事の令和最新版です。 www.nohara.dev ↑上の記事にある方法では現在動きません。

前回はGoogleカレンダーの更新/インポート間隔が調整できない(1日?)問題があったためスプラトゥーンのスケジュールとは相性が合わずでした。 そこで今回は自分のカレンダーに登録する形で実装したいと思います。

2024/09/01追記

リファクタリングした

2024/02/04追記

他人にカレンダーを見られたとき大変な反応をされることに気づいたので過去分を削除する処理を入れました。 一度過去分を削除したあとはoneDayBeforeを使うことで前日のものだけを削除できます。

実行環境

  • Google App Script
  • Googleカレンダー

完成イメージ

画像では例としてXマッチのガチエリアのみ表示しています。 バンカラマッチのスケジュールを登録したい場合の方法は後述します

作成手順

  1. Googleドライブを開き、右クリック→その他→Google App Scriptを選択

  1. 今あるコードをすべて削除し、以下のコードをコピーペースト

     // Splatoon 3のバンカラマッチ(チャレンジ)スケジュールを取得するAPIのURL
     const API_URL = 'https://spla3.yuu26.com/api/bankara-challenge/schedule';
     // Splatoon 3のXマッチスケジュールを取得するAPIのURL
     // const API_URL = 'https://spla3.yuu26.com/api/x/schedule';
    
     // APIリクエスト時に使用するユーザーエージェント
     const USER_AGENT = '@あなたのX id等';
     // カレンダーに登録する有効なルール(ゲームモード)のリスト
     const VALID_RULES = ['ガチエリア', 'ガチヤグラ', 'ガチアサリ'];
    
     /**
     * Splatoon 3のスケジュールを取得し、カレンダーに登録する主要な関数
     */
     function getSplatoon3Schedule() {
     const calendar = CalendarApp.getDefaultCalendar();
     const schedule = fetchSchedule();
    
     if (schedule) {
         processSchedule(schedule, calendar);
         deletePastEvents(calendar);
     }
     }
    
     /**
     * APIからスケジュールを取得する関数
     * @returns {Array|null} 成功時はスケジュールの配列、失敗時はnull
     */
     function fetchSchedule() {
     const options = {
         'headers': { "user-agent": USER_AGENT }
     };
    
     try {
         const response = UrlFetchApp.fetch(API_URL, options);
         if (response.getResponseCode() === 200) {
         return JSON.parse(response.getContentText()).results;
         }
     } catch (error) {
         console.error("Failed to fetch schedule:", error);
     }
     return null;
     }
    
     /**
     * 取得したスケジュールを処理し、カレンダーにイベントを追加する関数
     * @param {Array} events - スケジュールイベントの配列
     * @param {Calendar} calendar - イベントを追加するカレンダーオブジェクト
     */
     function processSchedule(events, calendar) {
     events.forEach(event => {
         const { start_time, end_time, rule, stages } = event;
         const startTime = new Date(start_time);
         const endTime = new Date(end_time);
         const title = `${rule.name} ${stages[0].name} ${stages[1].name}`;
    
         // 有効なルールの場合のみイベントを作成
         if (VALID_RULES.includes(rule.name)) {
         createEvent(calendar, startTime, endTime, title);
         }
     });
     }
    
     /**
     * カレンダーに新しいイベントを作成する関数(重複チェック付き)
     * @param {Calendar} calendar - イベントを追加するカレンダーオブジェクト
     * @param {Date} startTime - イベントの開始時間
     * @param {Date} endTime - イベントの終了時間
     * @param {string} title - イベントのタイトル
     */
     function createEvent(calendar, startTime, endTime, title) {
     const existingEvents = calendar.getEvents(startTime, endTime);
     const isDuplicate = existingEvents.some(event => event.getTitle() === title);
    
     if (!isDuplicate) {
         calendar.createEvent(title, startTime, endTime);
         console.log(`${title} ${startTime} has been registered.`);
     }
     }
    
     /**
     * 過去のイベントを削除する関数
     * @param {Calendar} calendar - イベントを削除するカレンダーオブジェクト
     */
     function deletePastEvents(calendar) {
     const now = new Date();
     const oneDayBefore = new Date(now.getTime() - (24 * 60 * 60 * 1000));
     const events = calendar.getEvents(oneDayBefore, now);
    
     events.forEach(event => {
         // イベントが終了済みで、かつ有効なルールで始まるタイトルの場合に削除
         if (event.getEndTime() < now && VALID_RULES.some(rule => event.getTitle().startsWith(rule))) {
         event.deleteEvent();
         console.log('Deleted: ' + event.getTitle());
         }
     });
     }
    
  2. Ctrl-sまたは上部アイコンからプロジェクトを保存し、実行します

  3. 権限の承認を求められるので承認します 警告が出ますが詳細から承認できます

  4. 実行ログをみて xx has been registerd. と出ていればうまくカレンダーに登録されています

  5. 続いて定期実行のために、画面左のメニューからトリガーを選択し、時間の間隔を選択(時間)を2時間に変更します

  6. 2時間以上経過後、スケジュールが自動で登録されていれば成功です

Xマッチ、エリア以外の情報が欲しい場合

  • バンカラマッチの情報が欲しい場合
    • コードの冒頭にあるURLのx部分をbankara-challengeまたはbankara-open に変更する
  • エリア以外の情報が欲しい場合
    • コード後ろのほうにあるガチエリア部分をガチヤグラ, ガチホコバトル, ガチアサリに変更する
  • 詳細は Spla3 API - スプラトゥーン3のステージ情報API を参照
  • サーモンランのスケジュールも登録できますがサーモンランの場合はそこまでリアルタイム性が求められないと思うのですでに有志の方が作られたサーモンランカレンダーを利用するのがお勧めです。

https://splamp.info/salmon/schedule/howto.phpsplamp.info

お前もドライブワイパー使いにならないか?

こんにちは、ふかふかです。

Splathonアドベントカレンダー8日目の記事です。

7日目は寒いのはイヤッッッさんの"めしのこと"についてでした。

おいしそうなご飯ばかりでお腹がすきましたね。

早速白ご飯.com登録しました。

この記事ではドライブワイパー使いを増やすべくドライブワイパーの基本的なことについて紹介したいと思います。

書いている人のスプラ歴

Splathonで私を知らない人も多くいると思うので簡単に自己紹介しておきます。

  • Splatoon2から始めて3も合わせると約2500時間プレイ(2022.12.8時点)
  • Splatoon2 H3リールガンで最高Xパワー2500程度
  • Splatoon3 ドライブワイパーでXパワー2200程度、H3亜種がでたらH3持つかも...
  • 中射程シューター、塗り武器、使っていて楽しいブキが好き
  • 味方にバフをかける、サポートよりの戦法が好き

ドライブワイパー基本性能wiki参考

メイン-射程

ドライブワイパーは横振り・縦振りの2種類の攻撃手段がありますがそれぞれ射程とダメージが異なります。

横振り

スプラシューターより長く、プライムシューターより短い

縦振り

プライムシューターより長く、ボトルガイザーより短い *1

メイン-ダメージ

横振り 30ダメージ
横振り(ワイパー部分) 15ダメージ
縦振り 60ダメージ
縦振り(直撃) 120ダメージ

サブ-トーピード

直撃(トピコロ含む) 60ダメージ
爆風 35ダメージ
散弾 12ダメージ

コンボ

Splatoonでのイカ(タコ)ちゃんのHP100を削るためにドライブワイパーではいくつかのコンボが考えられます。代表的なものをいくつか書いておきます。

縦振り+横振りx2

一番基本的なコンボ。60+30x2で120ダメージ。縦振りは前入力することで前にステップしながら放つことができるため後ろに下がりそうな敵には前入力して横振りで追撃。逆に詰めてきそうな相手には縦振りを当てた後、下がりながら横振り。

縦振りx2

敵の高台下からこちらに気づいていない長射程にダメージを与えるのに有効。縦に判定が広いのでローラーの縦振りに近い攻撃ができる。プライムなどのほぼ同射程シューターとは引き撃ちで対応。

横振りx4

一撃が重い相手(ブラスター等)に使う。横振り時のヒト移動速度が非常に高いため敵の攻撃を避けながら対面できる。ただしキル速度はかなり遅いので敵のカバーには注意。

縦振り(直撃)

ロマン。基本狙って使うことはない。こちらに気づいていない長射程、オブジェクト周りで混戦状態のときに使う場合がある程度。

ドライブワイパーの特徴

縦振り(直撃)ヒット音が気持ちいい

非常に重要な部分。

つまらないものは、それだけで良いブキではありえない。 某フロムゲー*2より

通常のヒット音ではなく特殊ヒット音が鳴る。気持ち良すぎて多用したくなるが、直撃だけを狙う動きはかなり弱い。外すとモデラーにすら対面負けすることがあるので注意。

横振り時のヒト移動速度が速い

横振りをしながら左右に移動することで敵の攻撃をかわすことができる。なお、射撃中にはヒト移動速度アップギアの効果は乗らない。 2022年11月30日ver2.0.0アップデートで横振りの塗りと当たり判定が強化された*3。一度使って手放したあなたも再度持ってみよう。

高い対物性能

ドライブワイパー含むワイパー種は高い対物性能を持っており、設置系スペシャルやサブに強く出れる。 いくつか例を出す。

ホップソナー

縦振り+横振りそれぞれ一発ずつ or 縦振り(直撃)

ナイスダマ

縦振り(直撃)x3でキル

スプリンクラー

横振り一発

おすすめyoutuber(動画)

文字より動画がいいという方にはこちらを

最後に

ギア構成&立ち回り編も書きたかったけどもうお昼休み終わるのでこのくらいで。

明日はfei_komeさんの"ハクスラゲー「GrimDawn」面白いぞ!という話"です。 ハクスラゲー好きなので楽しみ。

*1:画像はsplatool様より https://splatool.net/rangemanage.html

*2:Bloodborne

*3:当たり判定のほうは正確にはバグ修正

DiscordのテキストをVOICEROIDが読み上げてくれるBOTを作ってみた(続編)

f:id:nohararc:20200710033123p:plain

前回までのあらすじ

DiscordのテキストをVOICEROIDが読み上げてくれるBOTを作ってみたが、導入方法が面倒であまり評判が良くなかった nohararc.hatenablog.jp

実際に動いている様子

youtu.be 画像で利用させていただいた素材*1

想定読者

  • discordのテキスト読み上げbotを作ってみたい方
  • discordを利用しているが自分の声で話すのは恥ずかしい方
  • voiceroid買ったはいいが使い道がなくて余らせている方

環境

動作確認は以下の環境で行っています。

  • Windows10 64bit
  • Python3.9.1(32bit)
  • VOICEROID2

前回との変更点

導入方法をできるだけシンプルにすべく構成を変更し初心者でも1時間あれば導入できる(ふかふか調べ)ようにした。

前回はhttpサーバー部分の手順が若干難しくつまずく方が多かった。

今回は直接voiceroid2のdllを叩くプログラムを作成するつもりであったが既にその部分はNkyokuさんが用途に合うものを作っていたため存分に活用させて頂いております。感謝。

導入方法

  1. VOICEROID2が動いているPC上にPython3をインストールする
  2. ffmpegをインストールしパスを通しておく
  3. ここのCode -> Download ZIP からソースコードをダウンロードしzipファイルを解凍する
  4. READMEを参考に進める

うまく動かなかった、こういった機能は実装できないかなどの相談はTwitterGitHubにお願いします。

スプラコンペを雑に振り返る

スプラコンペとは

ProbSpaceで開催されたスプラトゥーンの勝敗を予測するコンペで2020/8/19~2020/10/18にわたり開催されました。 利用できるデータは、ブキ・ルール・ランクなど試合が始まる前のデータのみ(試合中のキル・デス数などは利用できない)。 prob.space

個人的な振り返り

テーブルデータを触るのがほぼ初めてだったので初めの提出に一苦労しました。予測精度55-56%当たりからほぼ精度が上がらずそこからは放置...。

自分の最終的な順位はCatboostで予測した55%で71/288位、思っていたより良かった。ちなみに1位の方は58%の予測精度でした。

スプラトゥーン2を2000時間程度やっている身からしても予測精度が60%いかないと考えていたので概ね想定通り。

時間がなくて取り組めなかったものとしては、

  • NNでの予測
  • train/testのリーク確認
  • データ水増し

がありました。

おそらく効いたであろう特徴量

興味深いトピック

今回のデータを使って気になるデータを計算してみた

※ データ数が少なく実際の統計値とは大きく外れている可能性があります。気になる人は自分で計算してみよう! 真面目に見たい場合はstat.inkさんなどのサイトをお勧めします。

ロングブラスターとL3リールガンDの勝率比較

  • ロングブラスター

    • エリアの勝率: 43.09%
    • アサリの勝率: 49.01%
    • ヤグラの勝率: 49.17%
    • ホコの勝率: 47.56%
    • ナワバリの勝率: 47.10%
  • L3リールガンD

    • エリアの勝率: 51.56%
    • アサリの勝率: 57.96%
    • ヤグラの勝率: 54.95%
    • ホコの勝率: 54.33%
    • ナワバリの勝率: 60.53%
  • ソイチューバー

    • エリアの勝率: 37.93%
    • アサリの勝率: 36.36%
    • ヤグラの勝率: 42.11%
    • ホコの勝率: 42.59%
    • ナワバリの勝率: 45.71%

こんな感じで計算

def win_rate(df, weapon_key):
  A_ = df.loc[(df["A1-weapon"] == weapon_key) |
              (df["A2-weapon"] == weapon_key) |
              (df["A3-weapon"] == weapon_key) |
              (df["A4-weapon"] == weapon_key), ["y"]]
  A_win = A_.loc[A_["y"] == 1]  # y=1のときAの勝利

  B_ = df.loc[(df["B1-weapon"] == weapon_key) |
              (df["B2-weapon"] == weapon_key) |
              (df["B3-weapon"] == weapon_key) |
              (df["B4-weapon"] == weapon_key), ["y"]]
  B_win = B_[B_["y"] == 0]  # y=0のときBの勝利

  return (len(A_win) + len(B_win)) / (len(A_) + len(B_))