/** * @return an array of 1..2 values of the values for the particular row, * maybe formatted with {@link #graph_number_format()}. */ function getTickerData($row) { if (isset($row['balance_closing'])) { return array(graph_number_format(demo_scale($row['balance_closing']))); } else { return array(graph_number_format(demo_scale($row['balance']))); } }
public function getData($days) { $key_column = array('type' => 'string', 'title' => ct("Currency")); $columns = array(); // get data // TODO could probably cache this $q = db()->prepare("SELECT SUM(balance) AS balance, exchange, MAX(created_at) AS created_at FROM balances WHERE user_id=? AND is_recent=1 AND currency=? GROUP BY exchange"); $q->execute(array($this->getUser(), $this->currency)); $balances = $q->fetchAll(); // need to also get address balances $summary_balances = get_all_summary_instances($this->getUser()); // get additional balances $data = array(); if (isset($summary_balances['blockchain' . $this->currency]) && $summary_balances['blockchain' . $this->currency]['balance'] != 0) { $balances[] = array("balance" => $summary_balances['blockchain' . $this->currency]['balance'], "exchange" => "blockchain", "created_at" => $summary_balances['blockchain' . $this->currency]['created_at']); } if (isset($summary_balances['offsets' . $this->currency]) && $summary_balances['offsets' . $this->currency]['balance'] != 0) { $balances[] = array("balance" => $summary_balances['offsets' . $this->currency]['balance'], "exchange" => "offsets", "created_at" => $summary_balances['offsets' . $this->currency]['created_at']); } // sort by balance usort($balances, array($this, 'sort_by_balance_desc')); $last_updated = find_latest_created_at($balances); // apply demo_scale and calculate total summary $data = array(); $total = 0; foreach ($balances as $b) { if ($b['balance'] != 0) { $columns[] = array('type' => 'number', 'title' => get_exchange_name($b['exchange'])); $data[] = demo_scale($b['balance']); $total += demo_scale($b['balance']); } } // return a more helpful message if there is no data if (!$data) { throw new NoDataGraphException_AddAccountsAddresses(); } // sort data by balance $data = array(get_currency_abbr($this->currency) => $data); return array('key' => $key_column, 'columns' => $columns, 'data' => $data, 'last_updated' => $last_updated); }
public function getData($days) { $key_column = array('type' => 'string', 'title' => ct("Currency")); $columns = array(); // get all balances $balances = get_all_summary_instances($this->getUser()); $last_updated = find_latest_created_at($balances, "total"); // and convert them using the most recent rates $rates = get_all_recent_rates(); // create data // TODO refactor this into generic any-currency balances $data = array(); if (isset($balances['totalbtc']) && $balances['totalbtc']['balance'] != 0) { $columns[] = array('type' => 'number', 'title' => get_currency_abbr('btc')); $data[] = graph_number_format(demo_scale($balances['totalbtc']['balance'])); } foreach (get_all_currencies() as $cur) { // if the key is a currency, use the same currency colour across all graphs (#293) $color = array_search($cur, get_all_currencies()); if ($cur == 'btc') { continue; } if (!is_fiat_currency($cur) && isset($balances['total' . $cur]) && $balances['total' . $cur]['balance'] != 0 && isset($rates['btc' . $cur])) { $columns[] = array('type' => 'number', 'title' => get_currency_abbr($cur), 'color' => $color); $data[] = graph_number_format(demo_scale($balances['total' . $cur]['balance'] * $rates['btc' . $cur]['bid'])); } if (is_fiat_currency($cur) && isset($balances['total' . $cur]) && $balances['total' . $cur]['balance'] != 0 && isset($rates[$cur . 'btc']) && $rates[$cur . 'btc']['ask']) { $columns[] = array('type' => 'number', 'title' => get_currency_abbr($cur), 'color' => $color); $data[] = graph_number_format(demo_scale($balances['total' . $cur]['balance'] / $rates[$cur . 'btc']['ask'])); } } // display a helpful message if there's no data if (!$data) { throw new NoDataGraphException_AddAccountsAddresses(); } // sort data by balance arsort($data); $data = array(get_currency_abbr('btc') => $data); return array('key' => $key_column, 'columns' => $columns, 'data' => $data, 'last_updated' => $last_updated); }
public function getData($days) { $key_column = array('type' => 'string', 'title' => ct("Currency")); $columns = array(); $columns[] = array('type' => 'string', 'title' => ct("Exchange"), 'heading' => true); $columns[] = array('type' => 'string', 'title' => ct("Converted fiat")); // a table of each crypto2xxx value // get all balances $currencies = get_crypto_conversion_summary_types($this->getUser()); $last_updated = false; // create data $data = array(); foreach ($currencies as $key => $c) { $q = db()->prepare("SELECT * FROM summary_instances WHERE user_id=? AND summary_type=? AND is_recent=1"); $q->execute(array($this->getUser(), "crypto2" . $key)); if ($balance = $q->fetch()) { $data[] = array($c['short_title'], currency_format($c['currency'], demo_scale($balance['balance']), 4)); $last_updated = max($last_updated, strtotime($balance['created_at'])); } } return array('key' => $key_column, 'columns' => $columns, 'data' => $data, 'last_updated' => $last_updated, 'add_more_currencies' => true, 'no_header' => true); }
public function getData($days) { $key_column = array('type' => 'string', 'title' => ct("Currency")); $columns = array(); $columns[] = array('type' => 'string', 'title' => ct("Currency"), 'heading' => true); $columns[] = array('type' => 'string', 'title' => ct("Total")); // a table of each currency // get all balances $balances = get_all_summary_instances($this->getUser()); $summaries = get_all_summary_currencies($this->getUser()); $currencies = get_all_currencies(); $last_updated = find_latest_created_at($balances, "total"); // create data $data = array(); foreach ($currencies as $c) { if (isset($summaries[$c])) { $balance = isset($balances['total' . $c]) ? $balances['total' . $c]['balance'] : 0; $data[] = array("<span title=\"" . htmlspecialchars(get_currency_name($c)) . "\">" . get_currency_abbr($c) . "</span>", currency_format($c, demo_scale($balance), 4)); } } return array('key' => $key_column, 'columns' => $columns, 'data' => $data, 'last_updated' => $last_updated, 'add_more_currencies' => true, 'no_header' => true); }
public function getData($days) { $columns = array(); $key_column = array('type' => 'date', 'title' => ct("Date")); // $columns = $this->getTickerColumns(); // TODO extra_days_necessary $extra_days = 10; $sources = $this->getCompositionSources($days, $extra_days); $args = $this->getCompositionArgs(); $data = array(); $last_updated = false; $exchanges_found = array(); $maximum_balances = array(); // only used to check for non-zero accounts $data_temp = array(); $hide_missing_data = !require_get("debug_show_missing_data", false); $latest = array(); foreach ($sources as $source) { $q = db()->prepare($source['query']); $q->execute($args); while ($ticker = $q->fetch()) { $key = date('Y-m-d', strtotime($ticker[$source['key']])); if (!isset($data_temp[$key])) { $data_temp[$key] = array(); } if (!isset($data_temp[$key][$ticker['exchange']])) { $data_temp[$key][$ticker['exchange']] = 0; } $data_temp[$key][$ticker['exchange']] += $ticker[$source['balance_key']]; $last_updated = max($last_updated, strtotime($ticker['created_at'])); $exchanges_found[$ticker['exchange']] = $ticker['exchange']; if (!isset($maximum_balances[$ticker['exchange']])) { $maximum_balances[$ticker['exchange']] = 0; } $maximum_balances[$ticker['exchange']] = max($ticker[$source['balance_key']], $maximum_balances[$ticker['exchange']]); if (!isset($latest[$ticker['exchange']])) { $latest[$ticker['exchange']] = 0; } $latest[$ticker['exchange']] = max($latest[$ticker['exchange']], strtotime($ticker[$source['key']])); } } // get rid of any exchange summaries that had zero data foreach ($maximum_balances as $key => $balance) { if ($balance == 0) { foreach ($data_temp as $dt_key => $values) { unset($data_temp[$dt_key][$key]); } unset($exchanges_found[$key]); } } // sort by date so we can get previous dates if necessary for missing data ksort($data_temp); $data = array(); // add headings after we know how many exchanges we've found $first_heading = array('title' => t("Date")); $headings = array($first_heading); $i = 0; // sort them so they're always in the same order ksort($exchanges_found); foreach ($exchanges_found as $key => $ignored) { $headings[$key] = array('title' => $this->getHeadingTitle($key, $args)); } // $data[0] = $headings; // add '0' for exchanges that we've found at one point, but don't have a data point // but reset to '0' for exchanges that are no longer present (i.e. from graph_data_balances archives) // this fixes a bug where old securities data is still displayed as present in long historical graphs $previous_row = array(); foreach ($data_temp as $date => $values) { $row = array(); foreach ($exchanges_found as $key => $ignored) { if (!$hide_missing_data || strtotime($date) <= $latest[$key]) { if (!isset($values[$key])) { $row[$key] = graph_number_format(isset($previous_row[$key]) ? $previous_row[$key] : 0); } else { $row[$key] = graph_number_format(demo_scale($values[$key])); } } else { $row[$key] = graph_number_format(0); } } if (count($row) > 0) { // don't add empty rows $data[$date] = $row; $previous_row = $row; } } // sort each row by the biggest value in the most recent data // so e.g. BTC comes first, LTC comes second, regardless of order of summary_instances, balances etc $keys = array_keys($data); // we can only sort if we actually have data if (count($keys) == 0) { // bail early throw new NoDataGraphException_AddCurrencies(); } $last_row = $data[$keys[count($keys) - 1]]; arsort($last_row); $data_temp = array(); foreach ($data as $row => $columns) { $temp = array(); foreach ($last_row as $key => $ignored) { $temp[$key] = $columns[$key]; } $data_temp[$row] = $temp; } $data = $data_temp; // convert columns and data into numeric indices $result_columns = array(); $result_column_map = array(); foreach ($columns as $key => $column) { $result_columns[] = array('type' => 'number', 'title' => $this->getHeadingTitle($key, $args)); // if the key is a currency, use the same currency colour across all graphs if (in_array(strtolower($key), get_all_currencies())) { $result_columns[count($result_columns) - 1]['color'] = array_search(strtolower($key), get_all_currencies()); } $result_column_map[$key] = count($result_columns) - 1; } $result_data = array(); foreach ($data as $date => $row) { $new_row = array(); foreach ($row as $key => $value) { $new_row[$result_column_map[$key]] = $value; } $result_data[$date] = $new_row; } // find the last row, and calculate its total for later $last_row = array(); $last_row_total = 0; foreach ($result_data as $date => $row) { $last_row = $row; } foreach ($row as $value) { $last_row_total += $value; } // sort the last row, and then use this new order to resort all // of the columns and data arsort($last_row); $sorted_columns = array(); $sorted_data = array(); foreach ($last_row as $i => $ignored) { $sorted_columns[] = $result_columns[$i]; } foreach ($result_data as $date => $rows) { $sorted_row = array(); foreach ($last_row as $i => $ignored) { $sorted_row[] = $rows[$i]; } $sorted_rows[$date] = $sorted_row; } return array('key' => $key_column, 'columns' => $sorted_columns, 'data' => $sorted_rows, 'last_updated' => $last_updated, 'last_row_total' => $last_row_total); }
} // need to also get address balances $summary_balances = get_all_summary_instances(); foreach ($balances as $currency => $data) { if (isset($summary_balances['blockchain' . $currency]) && $summary_balances['blockchain' . $currency]['balance'] != 0) { if (!isset($balances[$currency]['blockchain'])) { $balances[$currency]['blockchain'] = 0; } $balances[$currency]['blockchain'] += demo_scale($summary_balances['blockchain' . $currency]['balance']); $last_updated['blockchain'] = $summary_balances['blockchain' . $currency]['created_at']; } if (isset($summary_balances['offsets' . $currency]) && $summary_balances['offsets' . $currency]['balance'] != 0) { if (!isset($balances[$currency]['offsets'])) { $balances[$currency]['offsets'] = 0; } $balances[$currency]['offsets'] += demo_scale($summary_balances['offsets' . $currency]['balance']); $last_updated['offsets'] = $summary_balances['offsets' . $currency]['created_at']; } } // remove empty currencies $temp = array(); foreach ($balances as $cur => $data) { if ($data) { $temp[$cur] = $data; } } ksort($temp); $balances = $temp; // now print out tabs and tables for each currency ?>
$pages = $q->fetchAll(); // get all of our latest balances, ignoring currencies we're not interested in $balances = array(); $last_updated = array(); require __DIR__ . "/../graphs/util.php"; foreach (get_all_summary_currencies() as $cur => $summary) { $balances[$cur] = array(); } $q = db()->prepare("SELECT * FROM hashrates WHERE user_id=? AND is_recent=1"); $q->execute(array(user_id())); while ($balance = $q->fetch()) { if (isset($balances[$balance['currency']])) { if (!isset($balances[$balance['currency']][$balance['exchange']])) { $balances[$balance['currency']][$balance['exchange']] = 0; } $balances[$balance['currency']][$balance['exchange']] += demo_scale($balance['mhash']); $last_updated[$balance['exchange']] = $balance['created_at']; } } // remove empty currencies $temp = array(); foreach ($balances as $cur => $data) { if ($data) { $temp[$cur] = $data; } } ksort($temp); $balances = $temp; // now print out tabs and tables for each currency ?>
/** * Renders a collection of $sources with a given set of arguments $args, a user ID $user_id * and a heading callback function $get_heading_title. * * @param $has_subheadings true (default), false (no subheading), 'last_total' (total the most recent data) * @param $stacked if true, renders the graph as a stacked graph rather than line graph. defaults to false. * @param $make_proportional if true, converts all values to proportional data w.r.t. each date point, up to 100%. defaults to false. */ function render_sources_graph($graph, $sources, $args, $user_id, $get_heading_title, $has_subheadings = true, $stacked = false, $make_proportional = false) { $data = array(); $last_updated = false; $days = get_graph_days($graph); $extra_days = extra_days_necessary($graph); $exchanges_found = array(); $maximum_balances = array(); // only used to check for non-zero accounts $data_temp = array(); $hide_missing_data = !require_get("debug_show_missing_data", false); $latest = array(); foreach ($sources as $source) { $q = db()->prepare($source['query']); $q_args = $args; $q_args['user_id'] = $user_id; $q->execute($q_args); while ($ticker = $q->fetch()) { $key = date('Y-m-d', strtotime($ticker[$source['key']])); if (!isset($data_temp[$key])) { $data_temp[$key] = array(); } if (!isset($data_temp[$key][$ticker['exchange']])) { $data_temp[$key][$ticker['exchange']] = 0; } $data_temp[$key][$ticker['exchange']] += $ticker[$source['balance_key']]; $last_updated = max($last_updated, strtotime($ticker['created_at'])); $exchanges_found[$ticker['exchange']] = $ticker['exchange']; if (!isset($maximum_balances[$ticker['exchange']])) { $maximum_balances[$ticker['exchange']] = 0; } $maximum_balances[$ticker['exchange']] = max($ticker[$source['balance_key']], $maximum_balances[$ticker['exchange']]); if (!isset($latest[$ticker['exchange']])) { $latest[$ticker['exchange']] = 0; } $latest[$ticker['exchange']] = max($latest[$ticker['exchange']], strtotime($ticker[$source['key']])); } } // get rid of any exchange summaries that had zero data foreach ($maximum_balances as $key => $balance) { if ($balance == 0) { foreach ($data_temp as $dt_key => $values) { unset($data_temp[$dt_key][$key]); } unset($exchanges_found[$key]); } } // sort by date so we can get previous dates if necessary for missing data ksort($data_temp); $data = array(); // add headings after we know how many exchanges we've found $first_heading = array('title' => t("Date")); if ($make_proportional) { $first_heading['min'] = 0; $first_heading['max'] = 100; } $headings = array($first_heading); $i = 0; // sort them so they're always in the same order ksort($exchanges_found); foreach ($exchanges_found as $key => $ignored) { $headings[$key] = array('title' => $get_heading_title($key, $args), 'line_width' => 2, 'color' => default_chart_color(in_array(strtolower($key), get_all_currencies()) ? array_search(strtolower($key), get_all_currencies()) : $i++)); } $data[0] = $headings; // add '0' for exchanges that we've found at one point, but don't have a data point // but reset to '0' for exchanges that are no longer present (i.e. from graph_data_balances archives) // this fixes a bug where old securities data is still displayed as present in long historical graphs $previous_row = array(); foreach ($data_temp as $date => $values) { $row = array('new Date(' . date('Y, n-1, j', strtotime($date)) . ')'); foreach ($exchanges_found as $key => $ignored) { if (!$hide_missing_data || strtotime($date) <= $latest[$key]) { if (!isset($values[$key])) { $row[$key] = graph_number_format(isset($previous_row[$key]) ? $previous_row[$key] : 0); } else { $row[$key] = graph_number_format(demo_scale($values[$key])); } } else { $row[$key] = graph_number_format(0); } } if (count($row) > 1) { // don't add empty rows $data[$date] = $row; $previous_row = $row; } } // make proportional? if ($make_proportional) { $data_temp = array(); foreach ($data as $row => $columns) { $row_temp = array(); if ($row == 0) { foreach ($columns as $key => $value) { if ($key !== 0) { $value['title'] .= " %"; } $row_temp[$key] = $value; } } else { $total = 0; foreach ($columns as $key => $value) { $total += $key === 0 ? 0 : $value; } foreach ($columns as $key => $value) { $row_temp[$key] = $key === 0 ? $value : graph_number_format($total == 0 ? 0 : $value / $total * 100); } } $data_temp[$row] = $row_temp; } $data = $data_temp; } // sort each row by the biggest value in the most recent data // so e.g. BTC comes first, LTC comes second, regardless of order of summary_instances, balances etc $keys = array_keys($data); $last_row = $data[$keys[count($keys) - 1]]; arsort($last_row); $data_temp = array(); foreach ($data as $row => $columns) { $temp = array(); $temp[0] = $columns[0]; // keep row 0 the same foreach ($last_row as $key => $ignored) { if ($key !== 0) { $temp[$key] = $columns[$key]; } } $data_temp[$row] = $temp; } $data = $data_temp; if (count($data) > 1) { // calculate deltas if necessary $data = calculate_graph_deltas($graph, $data); // calculate technicals // (only if there is at least one point of data, otherwise calculate_technicals() will throw an error) $data = calculate_technicals($graph, $data); // discard early data $data = discard_early_data($data, $days); // sort by key, but we only want values // we also need to sort by time *before* calculating subheadings uksort($data, 'cmp_time'); if ($has_subheadings) { if ($has_subheadings == 'last_total') { $graph['subheading'] = format_subheading_values_subtotal($graph, $data); } else { $graph['subheading'] = format_subheading_values($graph, $data); } } $graph['last_updated'] = $last_updated; render_linegraph_date($graph, array_values($data), $stacked); } else { if ($user_id == get_site_config('system_user_id')) { render_text($graph, t("No data to display.")); // or Invalid balance type. } else { render_text($graph, t("Either you have not enabled this balance, or your summaries for this balance have not yet been updated by :site_name.") . "<br><a class=\"add_accounts\" href=\"" . htmlspecialchars(url_for('wizard_currencies')) . "\">" . ht("Configure currencies") . "</a>"); } } }