やってみたこと
マイクラのHIVEっていうゲーム(サーバ)がありますが、各種情報がとれるようにAPIが公開されています。
APIを叩くとJSONで返ってくるので、WEBで表示するプログラムをGASで作ってみました。
Swagger
下記にAPIが公開されています。
ゲーム名やゲーマータグを入れればJSONが見えるので、わざわざ作る必要もないっちゃないのですが、GASをたまに作らないと忘れちゃうので作ってみました。
設計
GASでWEB画面を2つ作ることにしました。
- API呼び出し&結果表示画面
- 入力画面
API呼び出し&結果表示用 Google Spread Sheet
まず、入力画面用のGASを書くために、スプレッドシートを作りました。
さらにいうと、今回はレベル計算をしたかったのでデータベース代わりにしています。
下記に自分のXPからレベルを出す表があるので、この表をスプレッドシートにコピペして、ウニョウニョ編集して、テーブル化しました。
↓↓↓↓↓ こんな感じで・・
取得できるJSONの確認
前記のSwaggerで全部のデータのJSONを取得してみて、このスプレッドシートにコピペして、内容を調べました。
コード.gs
doGetでHTMLServiceを使います。
上記で調べた内容も反映します。このときも、スプレッドシートで関数を使って、GASのコードを生成しちゃえば、エディタでコピペするより簡単ですね。
例えば、
html.activated = jsonData['activated'];
だったら、A列に内容を並べておいて、
="html."&A1&" = jsonData['"&A1&"'];"
ってやれば、コードがスプレッドシート上で一発で完成!
なにげに、スプレッドシート+GASの組み合わせって便利ですね。
API仕様
doGet(e) の e にパラメータで入れられますので、今回は下記な感じになります。
var gamename = encodeURI(e.parameter.gamename);
var gamertag = encodeURI(e.parameter.gamertag);
var targetperiod = encodeURI(e.parameter.targetperiod);
PlayHIVE APIのURLを下記のように生成します。
全期間の場合:
https://api.playhive.com/v0/game/all/[gamename]/[gamertag]
月間の場合;
https://api.playhive.com/v0/game/monthly/player/[gamename]/[gamertag]
APIはfetchで呼ぶ
response = UrlFetchApp.fetch(url);
responseCode = response.getResponseCode()
response にAPIの呼び出し結果が帰ってきます。
JSON を Parse
jsonData = JSON.parse(response);
xp = jsonData['xp'];
これで、response内のJSONをperseしてくれて、値がとれるんです。
なんて便利なの!! GAS!
HTMLService
html = HtmlService.createTemplateFromFile("index");
これで、 index.html
と doGetを紐づけます。
htmlオブジェクトにとりあえず、全部の値をいれちゃいましょー。
例)
html.xp = jsonData['xp'];
最後に下記でHTML化します。
ところで、Metaタグは、最初index.htmlに書いたんですが、反映されず、ググったところ、ここに書かないといけないという先人からの情報があり、ここに入れています。
const htmlOutput = html.evaluate();
htmlOutput.addMetaTag('viewport', 'width=device-width, initial-scale=1');
return htmlOutput;
レベルの計算
スプレッドシートの内容を、一旦data配列に読み込んじゃいます、
const sheet = SpreadsheetApp.getActive().getSheetByName('level');
const lastRow = sheet.getLastRow();
const lastColumn = sheet.getLastColumn();
data = sheet.getDataRange().getValues();
で、面倒なんで、なめちゃいました。
lv=0;
for(i=0;i<lastRow;i++) {
if (data[i][0]==gamename) if (xp > data[i][1]) lv = data[i][2];
}
return lv;
でも、ほんとに、GAS便利だなぁ・・
というわけで、「コード.gs」の完成です。
function doGet(e) {
var gamename = encodeURI(e.parameter.gamename);
var gamertag = encodeURI(e.parameter.gamertag);
var targetperiod = encodeURI(e.parameter.targetperiod);
url = "https://api.playhive.com/v0/game/all/"+gamename+"/"+gamertag; // デフォルトは「All(全期間)」
if (targetperiod=="monthly") url = "https://api.playhive.com/v0/game/monthly/player/"+gamename+"/"+gamertag; // 「monthly(月間)」
response = UrlFetchApp.fetch(url);
responseCode = response.getResponseCode()
if (responseCode != 200) {
return -1;
}
jsonData = JSON.parse(response);
html = HtmlService.createTemplateFromFile("index");
html.gamename = gamename;
html.targetperiod = targetperiod;
html.activated = jsonData['activated'];
html.assists = jsonData['assists'];
html.blocks_destroyed = jsonData['blocks_destroyed'];
html.blocks_placed = jsonData['blocks_placed'];
html.checkpoints = jsonData['checkpoints'];
html.coins = jsonData['coins'];
html.cows = jsonData['cows'];
html.crates = jsonData['crates'];
html.deathmatches = jsonData['deathmatches'];
html.deaths = jsonData['deaths'];
html.final_kills = jsonData['final_kills'];
html.flags_captured = jsonData['flags_captured'];
html.flags_returned = jsonData['flags_returned'];
html.human_index = jsonData['human_index'];
html.index = jsonData['index'];
html.kills = jsonData['kills'];
html.m_solo_deaths = jsonData['m_solo_deaths'];
html.m_solo_goals = jsonData['m_solo_goals'];
html.m_solo_kills = jsonData['m_solo_kills'];
html.m_solo_played = jsonData['m_solo_played'];
html.m_solo_victories = jsonData['m_solo_victories'];
html.maps_completed = jsonData['maps_completed'];
html.maps_completed_without_dying = jsonData['maps_completed_without_dying'];
html.murderer_eliminations = jsonData['murderer_eliminations'];
html.murders = jsonData['murders'];
html.mystery_chests_destroyed = jsonData['mystery_chests_destroyed'];
html.ores_mined = jsonData['ores_mined'];
html.played = jsonData['played'];
html.powerups_collected = jsonData['powerups_collected'];
html.prestige = jsonData['prestige'];
html.projectiles_fired = jsonData['projectiles_fired'];
html.rating_good_received = jsonData['rating_good_received'];
html.rounds_survived = jsonData['rounds_survived'];
html.spells_used = jsonData['spells_used'];
html.treasure_destroyed = jsonData['treasure_destroyed'];
html.uncapped_xp = jsonData['uncapped_xp'];
html.victories = jsonData['victories'];
html.username = jsonData['username'];
html.xp = jsonData['xp'];
html.lv =getLevel(gamename,jsonData['xp']);
const htmlOutput = html.evaluate();
htmlOutput.addMetaTag('viewport', 'width=device-width, initial-scale=1');
htmlOutput.setTitle("The HIVE Ranking");
htmlOutput.setFaviconUrl("https://support.playhive.com/content/images/size/w256h256/2021/11/favicontest.png");
return htmlOutput;
}
function getLevel(gamename,xp) {
const sheet = SpreadsheetApp.getActive().getSheetByName('level');
const lastRow = sheet.getLastRow();
const lastColumn = sheet.getLastColumn();
data = sheet.getDataRange().getValues();
lv=0;
for(i=0;i<lastRow;i++) {
if (data[i][0]==gamename) if (xp > data[i][1]) lv = data[i][2];
}
return lv;
}
index.html の作成
App Script の画面のファイルのところの「+」を押すと、「HTML」があるので、選びます。「index」と入れて、「index.html」を書きます。
内容的には、PlayHIVEのAPIで取得した内容を表で表示しているだけです。
ちなみに、
<?=gamename ?>
みたいに書くと、「コード.gs」で、htmlオブジェクトに埋め込んだ内容が取り出せます。
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<?!= HtmlService.createHtmlOutputFromFile("css").getContent(); ?>
</head>
<body>
<div>
<img src="https://support.playhive.com/content/images/2021/11/Hive---Yellow---Small.png" style="display: block; margin: auto;" />
</div>
<br>
<div>
<table>
<tbody>
<tr><td> GameName </td><td> <?=gamename ?> </td></tr>
<tr><td> UserName</td><td> <?=username ?> </td></tr>
<tr></tr>
<tr><td> Prestige </td><td> <?=prestige ?> </td></tr>
<tr><td> Level </td><td> <?=lv ?> </td></tr>
<tr><td> Ranking </td><td> <?=human_index ?> </td></tr>
</tbody>
</table>
<br><br>
</div>
</body>
</html>
css.html の作成
せっかくなので、cssも作ります。
App Script の画面のファイルのところの「+」を押すと、「HTML」があるので、選びます。「css」と入れて、「css.html」を書きます。
「index.html」に、
<?!= HtmlService.createHtmlOutputFromFile("css").getContent(); ?>
を書くことで、cssのファイルも読み込みます。
cssの詳細は省略します。
<style>
body {
background-image: url(https://いい感じの背景画像ーほげほげ.jpg);
background-size: cover;
color: white;
font-size: x-large;
font-family: "Arial Black","ヒラギノ角ゴ ProN W3", HiraKakuProN-W3, 游ゴシック, "Yu Gothic", メイリオ, Meiryo, Verdana, Helvetica, Arial, sans-serif;
}
table {
margin: auto;
border-collapse: collapse;
}
th, td {
border: solid 2px white;
}
</style>
デプロイ
画面右上のほうの「デプロイ」→「新規デプロイ」でデプロイします。
一応、これでAPI部分は完成。
補足
GASの画面構成が変わってわかってなかったのですが、下記画像のように「デプロイの管理」からデプロイすれば、URLを固定できるようです。めでたしめでたし。
入力画面用 Google Spread Sheet
入力画面もGASで作っちゃいましょう。
WEBサーバを準備しないでよいので、便利です、URLは長いですが・・
コード.js
HTML化するだけなので、簡単です。
function doGet(e) {
html = HtmlService.createTemplateFromFile("index");
const htmlOutput = html.evaluate();
htmlOutput.addMetaTag('viewport', 'width=device-width, initial-scale=1');
htmlOutput.setTitle("The HIVE Player Profile");
htmlOutput.setFaviconUrl("https://support.playhive.com/content/images/size/w256h256/2021/11/favicontest.png");
return htmlOutput;
}
index.html
入力画面を作ります。ありがちなコードを書いて、GETで、API部分のデプロイ後のURLを書けばOK
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<?!= HtmlService.createHtmlOutputFromFile("css").getContent(); ?>
</head>
<body>
<div>
<img src="https://support.playhive.com/content/images/2021/11/Hive---Yellow---Small.png" style="display: block; margin: auto;" />
</div>
<br>
<div>
<table>
<tbody>
<tr><td> Please input your info </td></tr>
</tbody>
</table>
</div>
<div>
<form action="さっきデプロイしたGASのURL" method="get">
<table>
<tbody>
<tr><td>
<p>Game Name :
<select name=gamename>
<option value=sky>SKY</option>
<option value=wars>Wars</option>
<option value=murder>Murder</option>
<option value=grav>Grav</option>
<option value=party>Party</option>
<option value=drop>Drop</option>
<option value=dr>DR</option>
<option value=hide>Hide</option>
<option value=sg>SG</option>
<option value=ctf>CTF</option>
<option value=ground>Ground</option>
<option value=bridge>Bridge</option>
<option value=build>Build</option>
</select>
</p>
<p>Gamer Tag :
<input type="text" name=gamertag>
</p>
<p> Target Period:
<select name=targetperiod>
<option value=all>ALL</option>
<option value=monthly>Monthly</option>
</p>
</td></tr>
<tr><td>
<input type="submit" value="Submit">
</td></tr>
</tbody>
</table>
</div>
</form>
</body>
</html>
「css.html」は、API部分と同じです。
デプロイ
画面右上のほうの「デプロイ」→「新規デプロイ」でデプロイします。2回目からは「デプロイの管理」で。
一応、これで入力画面部分も完成。
完成スクショ
下記な感じです。
(ゲーマータグはリーダーボードの乗っている方のゲーマータグをお借りしました。)
ちなみに、GASでHTML化すると、こんなメッセージがヘッダーにでます。
↓
なんか、バグってるかも・・
まぁ。いいか・・