fahstats.inc.php

サマリFolding@home の統計情報を表示
リビジョン1.1
対応バージョン1.5.3
投稿者M.Taniguchi
投稿日2020-04-05 (日) 10:38:06

概要

Folding@home の統計情報を表示するプラグイン。

ユーザー(ドナー)個人統計とチーム統計の2種類を表示できます。

統計情報は公式APIから取得します。
負荷軽減のためと、API側の情報更新頻度が低いうえ応答を返さないこともあるため、結果はキャッシュして一定時間使い回します。
リアルタイム性は低いものとご理解ください。

PukiWiki 1.5.3/PHP 7.4 で動作確認済み。旧バージョンでもおそらく動くと思いますが、PHPは5.2以上が必要です。また、外部のAPIサーバーに接続するためcURLを使います。

※セキュリティホールがあったため修正しました。お使いの方はお手数ですが最新版に更新してください。


使い方


引数


使用例・出力例

#fahstats(FahstatsSample)
DonorFahstatsSample
Date of last Work Unit2020-04-04 20:17:39
Total score20,403,714
Total WUs272
Overall rank (if points are combined)16,076 of 2,506,022
Active clients (within 50 days)2
Active clients (within 7 days)2
#fahstats(999999)
TeamFahstatsSampleTeam
Date of last Work Unit2020-04-04 23:21:25
Active CPUs within 50 days18,791
Team ID999999
Grand score1,066,046,605,865
Work Unit count18,246,554
Team ranking1 of 248,004


コード

fahstats.inc.php
(下記のコードをコピーして、plugin ディレクトリに fahstats.inc.php というファイル名で保存してください)

<?php
/*
PukiWiki - Yet another WikiWikiWeb clone.
fahstats.inc.php, v1.1 2020 M.Taniguchi
License: GPL v3 or (at your option) any later version

Folding@home の統計情報を表示するプラグイン。

ユーザー(ドナー)個人統計とチーム統計の2種類を表示できます。

統計情報は公式APIから取得します。
負荷軽減のためと、もとよりAPI側の情報更新頻度が低いうえ応答を返さないこともあるため、結果はキャッシュして一定時間使い回します。
リアルタイム性は低いものとご理解ください。

【使い方】
#fahstats(ユーザー名)
#fahstats(チームID)
&fahstats(ユーザー名){テキスト};
&fahstats(チームID){テキスト};

【引数】
ユーザー名 … ユーザー名を表す文字列
チームID … チームIDを表す数字
テキスト … 表示する文字列。文字列内の「%キー名%」が対応する値に置換される。キー/値について詳しくは、本プラグイン実行後に生成されるキャッシュファイル cache/fahstats.*.dat 内を参照

【使用例】
#fahstats(FahstatsSample)
#fahstats(999999)
&fahstats(FahstatsSample){%name%さんのポイントは%credit%、処理したワークユニット数は%wus%です。};
&fahstats(999999){%name%チームのポイントは%credit%、処理したワークユニット数は%wus%です。};
*/

define('PLUGIN_FAHSTATS_URL', 'https:/'.'/stats.foldingathome.org/');		// Folding@home統計情報ドメイン
define('PLUGIN_FAHSTATS_URL_DONOR', PLUGIN_FAHSTATS_URL . 'api/donor/');	// Folding@homeドナー情報APIのURL
define('PLUGIN_FAHSTATS_URL_TEAM',  PLUGIN_FAHSTATS_URL . 'api/team/');		// Folding@homeチーム情報APIのURL

define('PLUGIN_FAHSTATS_API_INTERVAL', (4 * 60 * 60));	// APIアクセス間隔(秒)※短くしすぎてサーバーに負荷をかけないよう注意。もとよりAPI側の情報更新頻度は低く(公式には1時間毎)、あまり短くしても無駄
define('PLUGIN_FAHSTATS_API_TIMEOUT', 30);	// APIタイムアウト時間(秒)

define('PLUGIN_FAHSTATS_RECURSIVE', false);	// trueなら入れ子の情報を再帰的に走査する。テキスト引数でより詳細な情報を表示したいときに使う


function plugin_fahstats_convert() {
	list($id) = func_get_args();
	return plugin_fahstats_exec($id);
}

function plugin_fahstats_inline() {
	$args = func_get_args();
	$id = $args[0];
	$text = array_pop($args);
	return plugin_fahstats_exec($id, $text);
}

// 実行
function plugin_fahstats_exec($id, $text = null) {
	$id = trim((string)$id);
	if ($id === '') return;
	$team = is_numeric($id);	// 第1引数が数字ならチームIDとみなす(数字だけの名前のユーザーは勘弁…)

	$cacheFile = CACHE_DIR . 'fahstats' . (($id != '')? '.' . encode($id) : '') . '.dat';	// キャッシュファイルパス
	$data = null;

	// キャッシュファイルがない、またはキャッシュが古くなっていたらAPIから最新情報を取得
	if (!file_exists($cacheFile) || (filemtime($cacheFile) < (time() - max(PLUGIN_FAHSTATS_API_INTERVAL, 600)))) {
		// APIアクセス
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, (($team)? PLUGIN_FAHSTATS_URL_TEAM : PLUGIN_FAHSTATS_URL_DONOR) . rawurlencode($id));
		curl_setopt($ch, CURLOPT_HEADER, false);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($ch, CURLOPT_TIMEOUT, PLUGIN_FAHSTATS_API_TIMEOUT);
		$data = curl_exec($ch);
		curl_close($ch);

		// 成功?
		if ($data) {
			// JSONデコード
			$data = json_decode($data);
			if (!$data || isset($data->error)) return;
			$data = plugin_fahstats_readdata($data);	// 情報を走査

			// キャッシュファイル書き込み
			$fp = fopen($cacheFile, 'w');
			flock($fp, LOCK_EX);
			rewind($fp);
			fwrite($fp, json_encode($data));
			flock($fp, LOCK_UN);
			fclose($fp);
		}
	}

	// 情報がなければキャッシュファイル読み込み
	if (!$data) {
		$fp = fopen($cacheFile, 'r');
		$data = json_decode(fread($fp, filesize($cacheFile)));
		fclose($fp);
	}
	if (!$data) return;

	// デフォルト表示:表形式
	$url = PLUGIN_FAHSTATS_URL;
	$thStyle = ' style="text-align:left;width:21em"';
	$tdStyle = ' style="text-align:left;width:14em"';
	if (!$text) {
		if (!$team) {
			// ドナー情報
			$text = <<<EOT
<table class="style_table" cellspacing="1" border="0">
	<tbody>
		<tr><th class="style_th"${thStyle}">Donor</th><td class="style_td"${tdStyle}><a href="${url}%path%" rel="noopener nofollow external">%name%</a></td></tr>
		<tr><th class="style_th"${thStyle}>Date of last Work Unit</th><td class="style_td"${tdStyle}>%last%</td></tr>
		<tr><th class="style_th"${thStyle}>Total score</th><td class="style_td"${tdStyle}>%credit%</td></tr>
		<tr><th class="style_th"${thStyle}>Total WUs</th><td class="style_td"${tdStyle}>%wus%</td></tr>
		<tr><th class="style_th"${thStyle}>Overall rank (if points are combined)</th><td class="style_td"${tdStyle}>%rank% of %total_users%</td></tr>
		<tr><th class="style_th"${thStyle}>Active clients (within 50 days)</th><td class="style_td"${tdStyle}>%active_50%</td></tr>
		<tr><th class="style_th"${thStyle}>Active clients (within 7 days)</th><td class="style_td"${tdStyle}>%active_7%</td></tr>
	</tbody>
</table>
EOT;
		} else {
			// チーム情報
			$text = <<<EOT
<table class="style_table" cellspacing="1" border="0">
	<tbody>
		<tr><th class="style_th"${thStyle}>Team</th><td class="style_td"${tdStyle}><a href="${url}%path%" rel="noopener nofollow external">%name%</a></td></tr>
		<tr><th class="style_th"${thStyle}>Date of last Work Unit</th><td class="style_td"${tdStyle}>%last%</td></tr>
		<tr><th class="style_th"${thStyle}>Active CPUs within 50 days</th><td class="style_td"${tdStyle}>%active_50%</td></tr>
		<tr><th class="style_th"${thStyle}>Team ID</th><td class="style_td"${tdStyle}>%team%</td></tr>
		<tr><th class="style_th"${thStyle}>Grand score</th><td class="style_td"${tdStyle}>%credit%</td></tr>
		<tr><th class="style_th"${thStyle}>Work Unit count</th><td class="style_td"${tdStyle}>%wus%</td></tr>
		<tr><th class="style_th"${thStyle}>Team ranking</th><td class="style_td"${tdStyle}>%rank% of %total_teams%</td></tr>
	</tbody>
</table>
EOT;
		}
	}

	// テキスト置換
	$search = array();
	$replace = array();
	foreach ($data as $key => $val) {
		$search[] = $key;
		$replace[] = $val;
	}
	$text = str_replace($search, $replace, $text);

	return $text;
}

// 情報を走査
function plugin_fahstats_readdata($data, $prefix = null) {
	if ($prefix) $prefix .= ':';

	$result = array();
	foreach ($data as $key => $val) {
		if (is_array($val) || is_Object($val)) {
			// 入れ子を再帰的に走査
			if (PLUGIN_FAHSTATS_RECURSIVE) {
				$result = array_merge($result, plugin_fahstats_readdata($val, $prefix . $key));
			}
		} else {
			if (is_numeric($val) && strpos($key, 'id') === false && $key != 'team' && $key != 'year') $val = number_format($val);
			$result['%' . $prefix . $key . '%'] = $val;
		}
	}

	return $result;
}


高度な使い方:表形式ではなく、任意の文字列で表示


引数


キー
name名前
creditポイント
wusワークユニット数
last最終処理日時
rank順位
active_50過去50日間の使用クライアント数
active_7過去7日間の使用クライアント数
teamチームID
total_users総ユーザー数
total_teams総チーム数

※ドナー統計時のみ有効、チーム統計時のみ有効な値もあります。他のキー/値など、詳しくは本プラグイン実行後に生成されるキャッシュファイル cache/fahstats.*.dat 内を参照してください。


使用例・出力例

&fahstats(FahstatsSample){%name%さんのポイントは%credit%、処理したワークユニット数は%wus%です。};

FahstatsSampleさんのポイントは20,403,714、処理したワークユニット数は272です。


&fahstats(999999){%name%チームのポイントは%credit%、処理したワークユニット数は%wus%です。};

FahstatsSampleTeamチームのポイントは1,066,046,605,865、処理したワークユニット数は18,246,554です。


ライセンス

GPL v3


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2020-04-07 (火) 12:25:17
Site admin: PukiWiki Development Team

PukiWiki 1.5.3+ © 2001-2020 PukiWiki Development Team. Powered by PHP 5.6.40-0+deb8u11. HTML convert time: 0.241 sec.

OSDN