Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
<?php
/*************************************/
/* Just little blurb on how things should work
/* 2 types of projects - Working and Coomplete
/* Working -> display normal info
/* Complete -> display badge consisting of
/* final work and rank
/*
/*************************************/
class User {
private $fbid = NULL; // Facebook ID
private $dnetid = 1; // Distributed ID
private $projects = 0; // Binary encoded project setting
private $db = NULL; // Database handle
private $row_id = NULL; // Internal row ID
public $last_updated = NULL; // Last successful update
/*
Project configuration
*/
// Project bit values // Project - bit
/* Order is important */
private $project_lookup = array("rc572", // RC5-72 - 1
"ogr25", // OGR-25 - 2
"ogr26", // OGR-27 - 4
"ogr27", // OGR-26 - 8
"rc564"); // RC5-64 - 16
// Project list layout (name, (selected, completed, id, long-name, Stats object))
/* Order determins order in layout */
public $project_list = array("rc572" => array(false, true, 8, "RC5-72", NULL),
"ogr27" => array(false, true, 27, "OGR-27", NULL),
"ogr26" => array(false, false, 26, "OGR-26", NULL),
"ogr25" => array(false, false, 25, "OGR-25", NULL),
"rc564" => array(false, false, 5, "RC5-64", NULL));
public function __construct($fbid, $facebook, $db) {
$this->fbid = $fbid;
$this->facebook = $facebook;
$this->db = $db;
// Unused...
$this->max_projects = pow(2, count($this->project_list) - 1);
}
// Load user settings from database
public function load_settings() {
$rs = $this->db->query_first("SELECT * FROM users WHERE fbid='$this->fbid'");
if( !$rs )
return false;
$this->set_dnetid($rs['dnetid']);
$this->set_projects($rs['projects']);
$this->row_id = (int)$rs['id'];
$this->last_updated = strtotime( $rs['last_updated'] );
return true;
}
// Save user settings to database
public function save_settings() {
$data['dnetid'] = $this->dnetid;
$data['projects'] = $this->projects;
$data['fbid'] = $this->fbid;
$this->db->query_insert('users', $data, true);
if($this->db->affected_rows > 0) {
return true;
}
return false;
}
// Load stats for all selected projects
public function load_stats() {
$error = array();
foreach( $this->project_list as &$project ) {
if($project[0]) {
$project[4] = new Stats($this->dnetid, $project[2], $this->row_id, $this->db);
if( $project[4]->load_stats() == false ) {
$error[] = "error loading stats for " . $this->fbid . " => " . $project[3] . "<br />";
}
}
}
//delete reference
unset($project);
if (count($error) > 0 )
return $error;
else
return true;
}
// Update stats for selected projects from stats server
public function update_stats() {
$error = false;
foreach($this->project_list as &$project) {
if($project[0]) {
if($project[4] == NULL)
$project[4] = new Stats($this->dnetid, $project[2], $this->row_id, $this->db);
if(!$project[4]->update_stats()) {
$error = true;
}
}
}
if(!$error)
$this->db->query_update('users', array('last_updated'=>date( 'Y-m-d H:i:s')), "fbid='".$this->fbid."'");
return !$error;
}
/* Private member access */
// Get fbid
public function get_fbid() {
return $this->fbid;
}
// Get dnetid
public function get_dnetid() {
return $this->dnetid;
}
// Get project setting
public function get_projects() {
return $this->projects;
}
// Get project list
/* Possible issues with stats objects */
public function get_project_list() {
return $this->project_list;
}
// Returns true if project is selected, false otherwise
public function is_project_selected($project) {
return $this->project_list[$project][0];
}
// If valid dnetid sets it and returns true, otherwise return false.
public function set_dnetid($dnetid) {
if(!preg_match('/^\d+$/', $dnetid))
return false;
$this->dnetid = (int)$dnetid;
return true;
}
// If valid project sets it and returns true, otherwise return false.
// Updates the internal project selection array
public function set_projects($projects) {
if ( !preg_match('/^\d+$/', $projects) )
return false;
$this->projects = (int)$projects;
for ($i = count($this->project_list) - 1; $i >= 0; $i--) {
$div = pow(2, $i);
if((int)($projects / $div) == 1) {
$this->project_list[$this->project_lookup[$i]][0] = true;
} else {
$this->project_list[$this->project_lookup[$i]][0] = false;
}
$projects = $projects % $div;
}
return true;
}
// Updates profile FBML
public function update_profile() {
$wide = $this->wide_fbml();
$narrow = $this->narrow_fbml();
$header = '<fb:subtitle seeallurl="http://apps.facebook.com/dnetdev/view/' . $this->fbid . '/">';
$header .= '<fb:name uid="profileowner" useyou="true"';
$header .= 'possessive="true" capitalize="true" /> distributed.net stats</fb:subtitle>';
$fbml = $header;
$fbml .= '<fb:narrow><div align="left">' . $narrow . '</div></fb:narrow>';
$fbml .= '<fb:wide><div align="center">' . $wide . '</div></fb:wide>';
$profile = '<div style="height:250px; overflow-y:scroll;">' . $narrow . '</div>';
$this->facebook->api_client->profile_setFBML(NULL, $this->fbid, $fbml, NULL, NULL, $profile);
}
// Clears profile FBML
public function clear_profile() {
$this->facebook->api_client->profile_setFBML(NULL, $this->fbid, NULL, NULL, NULL, NULL);
}
// Creates narrow FBML for profile
// Note: Without <fb:narrow> </fb:narrow>
public function narrow_fbml() {
$fbml =<<<TEXT
<style type="text/css">
<!--
td {
background-color: #eceff6;
}
td.blank {
background-color:#fff;
}
#date {
clear:both;
}
-->
</style>
<div>
TEXT;
foreach($this->project_list as $project)
{
if($project[0])
{
if($stats = $project[4]->get_stats())
{
if($project[1])
{
$columns["project"] = '<td class="blank"></td><td colspan="2" style="text-align: center"><h2><a href="#">' . $project[3] . '</a></h2></td>';
$columns["header"] = '<td class="blank"></td><td>Overall</td><td>Yesterday</td>';
$columns["rank"] = '<td><strong>Rank</strong></td><td>' . $stats['rank'] . ' ' . html_rank_arrow($stats['rank_c']) . "</td><td>" . $stats['rank_d'] . ' ' . html_rank_arrow($stats['rank_d_c']) . "</td>";
$columns["work"] = '<td><strong>Work</strong></td><td>' . $stats['work'] . '</td><td>' . $stats['work_d'] . '</td>';
}
else
{
$columns["project"] = '<td class="blank"></td><td colspan="1" style="text-align: center"><h2><a href="#">' . $project[3] . '</a></h2></td>';
$columns["header"] = '<td class="blank"></td><td>Overall</td>';
$columns["rank"] = '<td><strong>Rank</strong></td><td>' . $stats['rank'] . '</td>';
$columns["work"] = '<td><strong>Work</strong></td><td>' . $stats['work'] . '</td>';
}
$fbml .=<<<TEXT
<div class="stats">
<table border="0" cellpadding="3">
<tbody>
<tr> {$columns['project']} </tr>
<tr> {$columns['header']} </tr>
<tr align="right"> {$columns['rank']} </tr>
<tr align="right"> {$columns['work']} </tr>
</tbody>
</table>
</div>
TEXT;
}
else
{
$fbml .= "Error fetching stats for " . $project[3] . ".";
}
}
}
//appaend $this->last_updated
$fbml .= '</div><div id="date">' . last_updated($this->last_updated) . '</div>';
return $fbml;
}
// Creates wide/normal FBML for profile
// Note: Without <fb:wide> </fb:wide>
public function wide_fbml() {
$fbml =<<<TEXT
<style type="text/css">
<!--
td {
background-color: #eceff6;
}
div.stats {
float:left;
}
#date {
clear:both;
font-size:x-small;
}
-->
</style>
<div class="stats">
<table border="0" cellpadding="3">
<tbody>
<tr>
<td style="background-color:#fff"><h2>&nbsp;</h2></td>
</tr>
<tr>
<td style="background-color:#fff">&nbsp;</td>
</tr>
<tr align="right">
<td><strong>Rank</strong></td>
</tr>
<tr align="right">
<td><strong>Work</strong></td>
</tr>
</tbody>
</table>
</div>
<div>
TEXT;
foreach($this->project_list as $project)
{
if($project[0])
{
if($stats = $project[4]->get_stats())
{
if($project[1])
{
$columns["project"] = '<td colspan="2" style="text-align: center"><h2><a href="#">' . $project[3] . '</a></h2></td>';
$columns["header"] = '<td>Overall</td><td>Yesterday</td>';
$columns["rank"] = '<td>' . $stats['rank'] . ' ' . html_rank_arrow($stats['rank_c']) . "</td><td>" . $stats['rank_d'] . ' ' . html_rank_arrow($stats['rank_d_c']) . "</td>";
$columns["work"] = '<td>' . $stats['work'] . '</td><td>' . $stats['work_d'] . '</td>';
}
else
{
$columns["project"] = '<td colspan="1" style="text-align: center"><h2><a href="#">' . $project[3] . '</a></h2></td>';
$columns["header"] = '<td>Overall</td>';
$columns["rank"] = '<td>' . $stats['rank'] . '</td>';
$columns["work"] = '<td>' . $stats['work'] . '</td>';
}
$fbml .=<<<TEXT
<div class="stats">
<table border="0" cellpadding="3">
<tbody>
<tr> {$columns['project']} </tr>
<tr> {$columns['header']} </tr>
<tr align="right"> {$columns['rank']} </tr>
<tr align="right"> {$columns['work']} </tr>
</tbody>
</table>
</div>
TEXT;
}
else
{
$fbml .= "<p>Error fetching stats for " . $project[3] ."</p>";
}
}
}
//appaend $this->last_updated
$fbml .= '</div><div id="date">' . last_updated($this->last_updated) . '</div>';
return $fbml;
}
}
class Stats {
// Database table names
private $table_list = array(5 => "rc564",
8 => "rc572",
25 => "ogr25",
26 => "ogr26",
27 => "ogr27");
function __construct($dnetid, $project, $row_id, $db){
$this->dnetid = $dnetid;
$this->project = $project;
$this->row_id = $row_id;
$this->db = $db;
// Check whether or not stats have been loaded before using them
$this->stats_loaded = false;
$this->stats = array("id" => $this->row_id,
"name" => NULL, // Name as appears on site
"days" => NULL, // Days working
"updated" => NULL, // When the stats were last updated
"rank" => NULL, // Overall rank
"rank_c" => NULL, // Change in overal rank
"rank_d" => NULL, // Yesterday'a rank
"rank_d_c" => NULL, // Change in yesterday's rank
"work" => NULL, // Overall work
"work_d" => NULL); // Yesterday's work
}
// Return an associative array of stats.
// Return false if stats aren't loaded
public function get_stats(){
if(!$this->stats_loaded){
if(!$this->load_stats()){
return false;
}
}
return $this->stats;
}
// Loads stats from internal database
public function load_stats() {
$table = $this->table_list[$this->project];
$sql = "SELECT * FROM $table WHERE id=$this->row_id";
$rs = $this->db->query_first($sql);
if($rs) {
foreach( $rs as $key => $val) {
$this->stats[$key] = $val;
}
$this->stats_loaded = true;
return true;
} else
return false;
}
// Update stats from stats.distributed.net
public function update_stats(){
$url = "http://stats.distributed.net/participant/psummary_xml.php?project_id=".$this->project."&id=".$this->dnetid;
// use curl to avoid long timeouts
$ch = curl_init();
$timeout = 5; // set to zero for no timeout
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$result = curl_exec($ch);
curl_close($ch);
if($result == false)
{
return false;
}
$xml = simplexml_load_string($result);
if ($xml == false || $xml[0]->getName() != "participant-summary")
{
return false;
}
$this->stats['name'] = $this->db->escape((string)$xml->name);
$this->stats['days'] = (string)$xml->stats->stat[6]->attributes()->value;
$this->stats['updated'] = $this->db->escape((string)$xml['last-update']);
$this->stats['rank'] = (string)$xml->stats->stat[0]->attributes()->value;
$this->stats['rank_c'] = (string)$xml->stats->stat[0]->attributes()->change;
$this->stats['rank_d'] = (string)$xml->stats->stat[1]->attributes()->value;
$this->stats['rank_d_c']= (string)$xml->stats->stat[1]->attributes()->change;
$this->stats['work'] = (string)$xml->stats->stat[2]->attributes()->value;
$this->stats['work_d'] = (string)$xml->stats->stat[3]->attributes()->value;
$table = $this->table_list[$this->project];
$this->db->query_insert($table, $this->stats, true);
$this->stats_loaded = true;
return true;
}
}
// Helper functions
// Generate appropriate arrows for rank change
function html_rank_arrow($change)
{
if ($change > 0) {
return "<span style=\"color: #009900\"><img src=\"http://dnet.exiledcode.ca/images/up.gif\" alt=\"+\">$change</span>";
} elseif ($change < 0) {
$offset = - $change;
return "<span style=\"color: #990000\"><img src=\"http://dnet.exiledcode.ca/images/down.gif\" alt=\"-\">$offset</span>";
} else {
return "<span style=\"color: #000099\"><img src=\"http://dnet.exiledcode.ca/images/right.gif\" >$change</span>";
}
}
// Generate 'Last updated' text (red if date is more than a day old)
function last_updated($date) {
$string = 'Last updated: ' . date( 'd-M-Y \a\t H:i', $date) . ' CST';
if(time() - $date > (24 * 60 * 60)) {
$string = '<span style="color: #990000;">' . $string . '</span>';
}
return $string;
}
// Debug function for arrays
function dump($value,$level=0)
{
if ($level==-1)
{
$trans[' ']='&there4;';
$trans["\t"]='&rArr;';
$trans["\n"]='&para;;';
$trans["\r"]='&lArr;';
$trans["\0"]='&oplus;';
return strtr(htmlspecialchars($value),$trans);
}
if ($level==0) echo '<pre>';
$type= gettype($value);
echo $type;
if ($type=='string')
{
echo '('.strlen($value).')';
$value= dump($value,-1);
}
elseif ($type=='boolean') $value= ($value?'true':'false');
elseif ($type=='object')
{
$props= get_class_vars(get_class($value));
echo '('.count($props).') <u>'.get_class($value).'</u>';
foreach($props as $key=>$val)
{
echo "\n".str_repeat("\t",$level+1).$key.' => ';
dump($value->$key,$level+1);
}
$value= '';
}
elseif ($type=='array')
{
echo '('.count($value).')';
foreach($value as $key=>$val)
{
echo "\n".str_repeat("\t",$level+1).dump($key,-1).' => ';
dump($val,$level+1);
}
$value= '';
}
echo " <b>$value</b>";
if ($level==0) echo '</pre>';
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.