先週Steamでハロウィンセールをやっていたのに欲しいものが何一つなく、積みゲーを増やせなかった山本です。

さて前回に引き続き、Steamの積みゲーを調べていきます。

金額を調べる

金額を調べます、ゲームの情報は「GetSchemaForGame」というAPIがありますので、金額は恐らくそこに含まれているでしょう。

Example URL: http://api.steampowered.com/ISteamUserStats/GetSchemaForGame/v2/?key=XXXXXXXXXXXXXXXXX&appid=218620
Arguments
  appid
    The AppID of the game you want stats of
  format
    Output format. json (default), xml or vdf.

ドキュメントを見ると、keyとappidを渡せとなっていますね。

では今回は特に理由があるわけではないですが、「And Yet It Moves」の情報を調べてみます。

steam_015

ValveTestApp18700?IDを間違えましたかね?

きっと間違えたんだと思うので、他のIDで再度試してみます。

steam_016

steam_018

……なんで?

とりあえず、総当りで3~40タイトルぐらいで調べたところ、ようやくタイトルが取れるものが見つかりました。

steam_017

一応、使い方は間違っていなかったようです、ですがゲーム名が違っていたり、取れなかったりと、このAPIは使えなさそうです。

しかも、取れたゲームであっても金額が含まれていません。

どうやら、使うべきAPIを間違えてしまったようです。

再度金額を調べる

さて、気を撮り直して、ゲーム情報を取れるAPIを再度調べてみましょう?

どうやらStorefrontAPIというものがあり、appdetailsであれば金額が取れそうだと分かりました。

http://store.steampowered.com/api/appdetails?appids=18700

steam_008

おお、なんか一杯情報が取れてる。
ただ、情報が少し多いようなので関係あるところだけ抽出しました。

steam_009

タイトルと金額が取れました。

currencyもJPYとなっており、円に対応されています。

そして金額も、initialとfinalがあり、discount_percentもあることから元値から割引値、割引率まで取得できるようです。

これで、積みゲーの金額を出そうと思ったのですが……。

この「98000」というのが気になります。
「And Yet It Moves」は低価格なゲームだったと記憶していました。

そもそも、一本で10万近いゲームってSteamにあったか?

steam_010

Steam上で確認しましたが「¥980」となっています。

よくわからないので、ドキュメントを見てみましょう。

price_overview (Optional)
  Omitted if free-to-play.
  currency
    Currency prices are denoted in. 
  initial
    Pre-discount price. 
  final
    Post-discount price. 
  discount_percent

なるほど、金額はオプションでフリーゲームでは除かれるらしいですね。

で、なぜ金額が100倍になっているのでしょうか?
ドキュメントでは全く触れられていません。

仕方がないので、少しググったんですが、全く情報が見つかりません。

確かに、何も考えずに100分の一にすれば金額が取れるのですが、あまり根拠なく除算するのには抵抗を感じます。

と思っていたところ

steam_012

Steamウォレットに小数点以下の金額がありますね。

下二桁は一円以下の金額を示していたんですね。

ええ、きっとそうです。実のところ納品物でもないので、下二桁は小数点で進めることにします。

積みゲーを計算する

さて、積みゲーをの金額を計算していこうと思います。

まず、積みゲーの基準です。

プレイ時間が0分のものは間違いなく、積みゲーであろうと思われますが起動確認だけ行って、全くプレイしていないものも積みゲーなのではないかと考えます。

ですので、プレイ時間が60分以下のものを積みゲーとして扱います。

………62本ほどありました。

流石に62本分、毎回金額を問い合わせるはどうかと思いますし、パラメータ名がappidsとなっているので複数個受け付けられそうです。

appids
  CSV of app IDs to return details of. 

ドキュメントにはCSVとありました。

カンマで区切れということでしょうか?

http://store.steampowered.com/api/appdetails?appids=18700,200260

steam_013

nullだってさ。

カンマ区切りではないのかと思ったのですが、同じく「CSV of app IDs」となっている他のAPIを使うと

http://store.steampowered.com/api/appuserdetails/?appids=18700,200260

steam_019

2つとも取れてますね。
なので、カンマ区切りでも問題はなさそうに思えます。

この件、よく分からないのでググった印象ですが、どうもバグっぽいですね。

仕方がないので、一個づつ回していきます。

購入時の金額を調べる

次に購入時の金額を調べようと思います。

先程使ったAPIで購入時の金額を取れないかとも考えたのですが、引数がゲームのIDだけで、ユーザのIDを受けるわけではないのでこのAPIでは無理だと考えれれます。

そこで、ドキュメントにあるAPIを片っ端から試していったのですが、残念ながらどこにも購入時の金額が含まれるものがありませんでした。
それどころか、購入日時が含まれるものすら見つかりませんでした。

一応、過去の金額についてはSteam DatabaseやProSteamerを確認すれば取ることは出来そうです。
Steam Databaseでは過去の金額を調べるAPIがあり(過去1年?ぐらいしか取れない)、しかも円で金額が取れるようになっていました。

ProSteamerはAPIこそ無いですが、過去の金額が掲載されていますので、htmlを解析でもすれば過去の金額は取れそうです。ただしドルですが。

実は、Steamでは昔はドル決済でしたが、2014年8月から日本版は円での決済になりました。

その為、過去の金額を算出するには2014年8月以前はドルで、それ以降は円で計算する必要があります。

どちらかの通貨に統合して計算をすることも可能ですが、その場合には過去の為替レートの情報が必要です。

とはいえ、為替レート取得のAPIがあるようですので、これは難しくないようです。
そもそも、過去のレートですからAPIがなくとも、過去の為替データを定期的に取り込むだけで問題は解決しそうです。

最も、使用されるレートが購入日なのか口座引き落としのタイミングなのかを把握する必要だけはありますが。

と、長々となりましたが結論を言ってしますと、結局購入日が分からないとどうにも出来ないということです。

非常に口惜しいところではございますが、購入時の金額を調べるのは断念せざるせざるをえないようです。

自分の積みゲーを調べる

仕方がないので、今取れる情報だけで、積みゲーの数と金額を調べるツールを作成しました。

積みゲーの数と、その比率、そしてそのゲームの定価と現在の価格が分かるようになっています。

/works/steam/550.php

<?php
  require_once 'underscore.php';

  $key    = !empty($_POST['key']) && preg_match('/^[0-9A-Z]{1,}$/', $_POST['key']) ? $_POST['key'] : '';
  $userid = !empty($_POST['userid']) ? (int)$_POST['userid'] : '';
  $border = !empty($_POST['border']) ? (int)$_POST['border'] : 60;
  $rows   = array();

  if ($key && $userid)
  {
    $profile  = getApiResponse('http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/', array('key' => $key, 'steamids' => $userid));
    $player   = array_pop($profile['response']['players']);

    $ret  = getApiResponse('http://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/', array('key' => $key, 'steamid' => $userid, 'include_appinfo' => 1));

    $list = __::sortBy($ret['response']['games'], function ($item)
    {
      return $item['playtime_forever'];
    });

    krsort($list);

    $sum  = 0;
    $rows = array();

    $initialSum = 0;
    $finalSum   = 0;

    foreach ($list as $r)
    {
      if ($r['playtime_forever'] <= $border)
      {
        $response = array_shift(getApiResponse('http://store.steampowered.com/api/appdetails', array('appids' => $r['appid'])));
        usleep(100000);

        $initialSum += $response['data']['price_overview']['initial'];
        $finalSum   += $response['data']['price_overview']['final'];

        $unopenCount++;
      }

      $sum += $r['playtime_forever'];
      $rows[] = array(
        'name'   => $r['name'],
        'date'   => sprintf('%dh %dm', $r['playtime_forever'] / 60, $r['playtime_forever'] % 60),
        'minute' => $r['playtime_forever'],
      );
    }
  }

  function getApiResponse($url, $params = array())
  {
    return json_decode(file_get_contents($url.'?'.http_build_query($params)), true);
  }
?><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
<script src="https://code.jquery.com/jquery-1.11.3.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</head>
<body>
  <div class="container">
    <?php if ($key && $userid):?>
      <div class="row">
        <h2><?php echo $player ? $player['personaname'].'さんの' : '';?>Steam貢献度</h2>
        <table class="table">
          <tr>
            <th>総プレイ時間</th>
            <td><?php echo floor($sum / 60)?>時間<?php echo ($sum % 60)?>分<td>
          </tr>
          <tr>
            <th>総購入本数</th>
            <td><?php echo count($list)?>本<td>
          </tr>
          <tr>
            <th>積みゲー基準時間</th>
            <td><?php echo $border?>分<td>
          </tr>
          <tr>
            <th>積みゲー数</th>
            <td><?php echo $unopenCount?>本<td>
          </tr>
          <tr>
            <th>積みゲー率</th>
            <td><?php echo round($unopenCount / count($list) * 100, 2)?>%<td>
          </tr>
          <tr>
            <th>積みゲー金額(標準値)</th>
            <td>&yen;<?php echo number_format($initialSum / 100); ?><td>
          </tr>
          <tr>
            <th>積みゲー金額(現在値)</th>
            <td>&yen;<?php echo number_format($finalSum / 100); ?><td>
          </tr>
        </table>
        <p>
          金額は現在の金額であり、購入時の金額ではありません。
        </p>

      </div>
      <div class="row">
        <h2>ゲーム一覧</h2>
        <table class="table">
          <tr>
            <th>title</th>
            <th>time</th>
          </tr>
          <?php foreach ($rows as $row):?>
          <tr <?php if($row['minute'] <= $border):?>class="warning"<?php endif;?>>
            <td><?php echo $row['name']?></td>
            <td><?php echo $row['date']?></td>
          </tr>
          <?php endforeach;?>
        </table>
      </div>
    <?php else:?>
      <h2>キー入力</h2>
      <form method="post">
        <div class="form-group">
          <label class="control-label">Steam Web Api Key</label>
          <input type="" name ="key" pattern="^[0-9A-Z]+$" class="form-control" required="required" placeholder="API KEY">
        </div>
        <div class="form-group">
          <label class="control-label">Steam Id</label>
          <input type="" name ="userid" pattern="^[0-9]+$" class="form-control" required="required" placeholder="ID">
        </div>
        <div class="form-group">
          <label class="control-label">時間</label>
          <p>積みゲーとは
            <select name="border">
              <option value="240">240</option>
              <option value="180">180</option>
              <option value="120">120</option>
              <option value="60" selected="selected">60</option>
              <option value="30">30</option>
              <option value="20">20</option>
              <option value="10">10</option>
              <option value="5">5</option>
              <option value="0">0</option>
            </select>
            分以下のものである</p>
        </div>

        <div class="form-group">
            <button type="submit" class="btn btn-primary">Send</button>
        </div>
      </form>
    <?php endif;?>
  </div>
  <footer class="footer">
    <div class="container">
      <p class="text-muted text-right">&copy;2015 ADjust Co.,Ltd.</p>
    </div>
  </footer>
</body>
</html>
  • 使ってみる
    まずは私の積みゲーです。

steam_020

積みゲー率は60%ぐらいで、総額で10万ぐらいになっています。

この金額は定価なので、60~75%あたりでいつも買っていることを考えると25,000~40,000ぐらいになるかと思いますね。

私の積みゲーを落ちに使おうと思っていたのですが、思ったほど大した事がなくて残念です。

仕方がありませんので、社内の猛者の積みゲーを拝見することとしましょう。

候補としてA氏とT氏が居たのですが、A氏は我らの期待を裏切り積みゲーが殆どない体たらくでした。

仕方がないので、弊社の誇る神ゲーマーT氏の積みゲーを見てみましょう。

steam_000.php

一見すると積みゲー率が少ないかのようにも見えますが、総購入本数が多いために比率が下がっているだけで、積みゲー本数で見れば私を圧倒しています。
そして、何よりもプレイ時間が凄いですね。

CODのプレイ時間だけで、私の総プレイ時間と変わらないとは、さすがに神ゲーマーは格が違った。

まとめ

今回のまとめですが、まさか購入日が取れないとは考えもしませんでした。
おかげで、購入日の金額が取れず、正直片手落ちです。

いっそ、購入メールを全て一つのZIPに纏めて、アップロードしてもらったりすると、購入日と購入金額が取れるのでは?とも思いました。
なんかそれは違う気もしますが。。。。

もし、購入日が取れる方法が見つかりましたら、第三回目をやるかもしれません。

前置きはさておき、今回の結果により、私はProSteamerとしては、まだまだだであることがよく分かりました。
積みゲー本数であれば、それなりではありますが、購入本数そしてプレイ時間では圧倒的に後塵を拝しています。
これからも偉大なるT氏を目標として、精進して行きたいと思います。