Plant seeds

路頭に迷ってしまいそうな大学院生が、どこかに書かなければ忘れてしまいそうな大切なことをここに残していきます。

AoCHD.jpの戦績データ分析日記1 ~HTMLParserでスクレイピング~

最近は研究のモチベーションをどこかに置いてきてしまった僕です。

わりと気分転換にゲームをやっているんですが、最近はAge of Empire ii しかやっていません。(もしやっているかたいたら一緒にやりましょう)

Age of Empire ii は日本にもいくつかコミュニティがあって、そのうちの一つであるAoCHD.jpにちょうど去年から参加させてもらっています。ここは、常連の博士後期課程の方もいたりして安心しながらやってしまえるのがよくないです

さて、このゲームはもともと1999年に発売されたもの(パッケージ版)で、僕は物心ついた頃からプレイしていました。というのも、幼少期にお父さんがやっていたのをずっと横で見ていたからです。自分で国を作ってバトルする感じがとてもおもしろくてたまらなかったですね。そんなこんなでSteam版が発売されて、オンライン対戦の仕組みがかなり強化されまして気軽に対戦ができるようになりました(それまではIPによる接続のみのサポート)。

それでプレイしていくうちに今までよりもはまりだし、そのうちゲーム上で日本人に出会いAoCHD.jpの存在を知りました。コミュニティに入っているなかでどうやれば強くなるのか、どんな戦略があるのかなどを学びました。「ああこのゲームはこんなに面白かったのか」と、あのときから16年後に知ることになるわけです(笑)

 

しかし、Steam版のゲームではマッチングシステムはあるもののチームの強さを公平にわける仕組みが存在しません。おそらくその不便さに対抗しようと日本人が立ち上がって作ったコミュニティがそれなのです。

基本的にこのコミュニティの参加者はレートが付与されます。まずはチャットで参加者を募ります。4vs4のゲームなので8人集まったら参加者の名前を入力としてチームの振り分けを自動的に行わせます。その後プレイをしてどちらのチームが勝利したのかを報告してその勝敗によってレートが上がったり下がったりする仕組みです。

しかし、この現状のレートシステムに不満が多いという現状もあります。レートの値をその人の実力(ゲーム上における最低限の技能)で定義しているのですが実際はその通りになっていなかったり、レートが大きい人とレートが小さい人が混ざったときに本当にその割り振り方でよかったのかといわれたりといった問題です。

また、次のような問題もあります。基本的に僕はゲームに時間を割くことができないので他の人に比べて強くなることができません(このコミュニティの方はかなりプレイしていてどんどん強くなっていく)。このような初心者の中でまったりやりたい人にとって非常に居心地の悪い環境であるということです。このコミュニティの「初心者は徹底的に囲っていきましょう」という方針と矛盾しています。

具体的にいうと、まず時間のある初心者はどんどん強くなっていくためレートがそれなりに上がってしまいます。そのため、低レートの人口が減ります。一方、時間のない初心者はこのような低レートの人口が少ない中でプレイすることができないため、高レートの人たちとプレイせざるを得ないのです。そうすると高レートの人からはこうしてほしいなどのアドバイスや要求をもらうのですが時間がなくてそれに応えることができません。この後ろめたさから辞めてしまう人は少なからずあると思います(実際僕もそうでした。)

たくさんの問題点を提起したところで、実際にこのコミュニティの健全性みたいなものを確かめてみたいと思い、データの分析を始めてみることにしました。

 

Pythonの標準のHTMLParserを使います。まずURIなんですが、

http://aochd.jp/player/playerdetail/player_id/97/rate_id/97

これはfunction_test_user1といって、初めて入る人がどれだけ強いかを見積もってそれに近いレートをテスト的に与えるためのダミーユーザーのうちの1つなので、これを使って説明します。player_idの子リソースとして同じidを持つrate_idがあるのがリソース設計的にどうなのかというツッコミはおいておきます。

http://aochd.jp/player/playerdetail/player_id/:id/rate_id/:id

といったルールで:idを1~現存する最大のidまでGET送信して返ってきたレスポンスボディをHTMLParserでパースします。

運がいいことにこのHTMLはh1タグが唯一ユーザ名のところにあるためこれを手がかりにしてデータがあるdivタグを探します。このようにして、まずユーザの現在のステータスみたいなものを取得していきます。ページでいうところのユーザ名とレート詳細の下のテーブルの中の値です。そして、とってきた値を永続化させるためにpandasのDataFrameを使ってcsvで保存します。

データの概観をみるため、2つのグラフを作成しました。

f:id:rtok:20180521113829p:plain

まずはレートのヒストグラムです。binの数は30としました。その根拠としては、レートは大体0~3000と言われていて1100代1600代といった切り分け方をして呼ばれることが多いので、ナイーブに階級幅を100としたかったからです。

このヒストグラムを見て分かることは初心者と上級者のなかにそれぞれ二つの大きな山があるような双峰性の分布であることです。

実際「レート1000を越えるのが初心者の壁だ」と言われているので、その直感にすごく近いことが驚きでした。

しかし、実際にこのコミュニティにいると1000未満のユーザーは全然いない(10%にも満たない)ため直近のプレイがいつかどうかについてもこれから考慮してやる必要がありそうなこともわかりました。

 

f:id:rtok:20180521114305p:plain

次は相関分析です。ピアソンの相関の方法を用いて作りました。

Unnamed: 0 はID、c-losは連敗数、c-winは連勝数、continuousは今の段階でどれだけ連勝、連敗しているか、loseは負けた回数、winは勝った回数、max-rateはレートの最大値、rateはレートです。

結論からいうとこの生のデータからは大した新しい発見は得られませんでした。適切に前処理を行うなどしたほうがいいと思います。

max-rateとrateの相関が強いのは当たり前ですね(人は何度もやればうまくなるから)。winとloseの相関が強いのはチームの振り分けシステムがある程度機能していることを示唆しています(勝ち数と負け数がほぼ同数であるということ)。

一番意味がある分析結果として、IDとレートは負の相関を持つということがわかったことでしょうか(笑)IDは順番に付与されているのでIDが古い(=古参)の人はレートが高く、IDが新しい(=新参)の人はレートが低いということなのでしょうか。

 

今回はスクレイピングをやって概観を見ただけなのでまだまだ課題が残っています。また暇な時にやってアウトプットできたらと思います。

HTMLParserの使い方に関してはQiitaで書いてみようと思います。

 

qiita.com