Major refactor of charts
This commit is contained in:
parent
a0796dacc5
commit
3f3f27d4c8
|
@ -1,11 +1,42 @@
|
||||||
from flask import Flask, jsonify, request, json, Response, send_from_directory, abort
|
from flask import Flask, g, jsonify, request, json, Response, send_from_directory, abort
|
||||||
from flask_cors import CORS
|
from flask_cors import CORS
|
||||||
import orjson, os
|
import orjson, os
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import time
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
CORS(app)
|
CORS(app)
|
||||||
|
|
||||||
FILES_DIRECTORY = '../data/'
|
FILES_DIRECTORY = '../data/'
|
||||||
|
today = datetime.datetime.today()
|
||||||
|
|
||||||
|
@app.before_request
|
||||||
|
def start_timer():
|
||||||
|
g.start = time.time()
|
||||||
|
|
||||||
|
@app.after_request
|
||||||
|
def log(response):
|
||||||
|
now = time.time()
|
||||||
|
duration = round(now - g.start, 4)
|
||||||
|
dt = datetime.datetime.fromtimestamp(now).strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
log_entry = {
|
||||||
|
'timestamp': dt,
|
||||||
|
'duration': duration,
|
||||||
|
'method': request.method,
|
||||||
|
'url': request.url,
|
||||||
|
'status': response.status_code,
|
||||||
|
'remote_addr': request.remote_addr,
|
||||||
|
'user_agent': request.user_agent.string,
|
||||||
|
}
|
||||||
|
|
||||||
|
log_line = ','.join(f'{key}={value}' for key, value in log_entry.items())
|
||||||
|
|
||||||
|
with open('api_logs.txt', 'a') as f:
|
||||||
|
f.write(log_line + '\n')
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
@app.route('/bitcoin_business_growth_by_country', methods=['GET'])
|
@app.route('/bitcoin_business_growth_by_country', methods=['GET'])
|
||||||
def business_growth():
|
def business_growth():
|
||||||
|
@ -29,8 +60,18 @@ def business_growth():
|
||||||
countries = [name.strip() for name in country_names.split(",")]
|
countries = [name.strip() for name in country_names.split(",")]
|
||||||
filtered_data = [item for item in filtered_data if item['country_name'] in countries]
|
filtered_data = [item for item in filtered_data if item['country_name'] in countries]
|
||||||
|
|
||||||
if cumulative_period_type:
|
if cumulative_period_type == "1 day":
|
||||||
filtered_data = [item for item in filtered_data if item['cumulative_period_type'] == cumulative_period_type]
|
delta = today - datetime.timedelta(days=2)
|
||||||
|
filtered_data = [item for item in filtered_data if item['cumulative_period_type'] == cumulative_period_type and delta <= datetime.datetime.strptime(item['date'], '%Y-%m-%d')]
|
||||||
|
elif cumulative_period_type == "7 day":
|
||||||
|
delta = today - datetime.timedelta(days=7)
|
||||||
|
filtered_data = [item for item in filtered_data if item['cumulative_period_type'] == cumulative_period_type and delta <= datetime.datetime.strptime(item['date'], '%Y-%m-%d')]
|
||||||
|
elif cumulative_period_type == "28 day":
|
||||||
|
delta = today - datetime.timedelta(days=28)
|
||||||
|
filtered_data = [item for item in filtered_data if item['cumulative_period_type'] == cumulative_period_type and delta <= datetime.datetime.strptime(item['date'], '%Y-%m-%d')]
|
||||||
|
elif cumulative_period_type == "365 day":
|
||||||
|
delta = today - datetime.timedelta(days=365)
|
||||||
|
filtered_data = [item for item in filtered_data if item['cumulative_period_type'] == cumulative_period_type and delta <= datetime.datetime.strptime(item['date'], '%Y-%m-%d')]
|
||||||
|
|
||||||
# Sort by date
|
# Sort by date
|
||||||
sorted_data = sorted(filtered_data, key=lambda x: x['date'], reverse=True)
|
sorted_data = sorted(filtered_data, key=lambda x: x['date'], reverse=True)
|
||||||
|
@ -40,14 +81,36 @@ def business_growth():
|
||||||
|
|
||||||
@app.route('/get_json/<filename>', methods=['GET'])
|
@app.route('/get_json/<filename>', methods=['GET'])
|
||||||
def get_json(filename):
|
def get_json(filename):
|
||||||
|
|
||||||
|
period = request.args.get('period')
|
||||||
|
|
||||||
file_path = os.path.join(FILES_DIRECTORY, filename)
|
file_path = os.path.join(FILES_DIRECTORY, filename)
|
||||||
if not os.path.isfile(file_path):
|
if not os.path.isfile(file_path):
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
with open(file_path, 'r') as file:
|
with open(file_path, 'r') as f:
|
||||||
data = json.load(file)
|
data = orjson.loads(f.read())
|
||||||
|
|
||||||
return jsonify(data)
|
if period == "last 7 days":
|
||||||
|
delta = today - datetime.timedelta(days=7)
|
||||||
|
filtered_data = [item for item in data if delta <= datetime.datetime.strptime(item['date'], '%Y-%m-%d') <= today]
|
||||||
|
sorted_data = sorted(filtered_data, key=lambda x: x['date'])
|
||||||
|
elif period == "last 28 days":
|
||||||
|
delta = today - datetime.timedelta(days=28)
|
||||||
|
filtered_data = [item for item in data if delta <= datetime.datetime.strptime(item['date'], '%Y-%m-%d') <= today]
|
||||||
|
sorted_data = sorted(filtered_data, key=lambda x: x['date'])
|
||||||
|
elif period == "last 365 days":
|
||||||
|
delta = today - datetime.timedelta(days=365)
|
||||||
|
filtered_data = [item for item in data if delta <= datetime.datetime.strptime(item['date'], '%Y-%m-%d') <= today]
|
||||||
|
sorted_data = sorted(filtered_data, key=lambda x: x['date'])
|
||||||
|
elif period == "last 2 years":
|
||||||
|
delta = today - datetime.timedelta(days=730)
|
||||||
|
filtered_data = [item for item in data if delta <= datetime.datetime.strptime(item['date'], '%Y-%m-%d') <= today]
|
||||||
|
sorted_data = sorted(filtered_data, key=lambda x: x['date'])
|
||||||
|
else:
|
||||||
|
sorted_data = sorted(data, key=lambda x: x['date'])
|
||||||
|
|
||||||
|
return jsonify(sorted_data)
|
||||||
|
|
||||||
@app.route('/download/<filename>', methods=['GET'])
|
@app.route('/download/<filename>', methods=['GET'])
|
||||||
def download_file(filename):
|
def download_file(filename):
|
||||||
|
|
|
@ -11,7 +11,7 @@ tags: ["QGIS", "SRTM", "DEM", "Raster", "download"]
|
||||||
{{< figure src="/pics/blog/batch-import-postgis-rasters/singapore-final.webp" width="300">}}
|
{{< figure src="/pics/blog/batch-import-postgis-rasters/singapore-final.webp" width="300">}}
|
||||||
Download the Digital Elevation Model featured in [this](/blog/batch-import-postgis-rasters/) blog.
|
Download the Digital Elevation Model featured in [this](/blog/batch-import-postgis-rasters/) blog.
|
||||||
|
|
||||||
{{< download-data src="https://api.baseddata.io/download/singapore-srtm-dem.tif" name="singapore-srtm-dem.tif" >}}
|
{{< download-data src="/singapore-srtm-dem.tif" name="singapore-srtm-dem.tif" >}}
|
||||||
|
|
||||||
#### Citations
|
#### Citations
|
||||||
NASA Shuttle Radar Topography Mission (SRTM)(2013). Shuttle Radar Topography Mission (SRTM) Global. Distributed by OpenTopography. https://doi.org/10.5069/G9445JDF. Accessed: 2024-08-06
|
NASA Shuttle Radar Topography Mission (SRTM)(2013). Shuttle Radar Topography Mission (SRTM) Global. Distributed by OpenTopography. https://doi.org/10.5069/G9445JDF. Accessed: 2024-08-06
|
||||||
|
|
|
@ -8,13 +8,12 @@ summary: "This analysis uses OpenStreetMaps data to chart the yearly growth of b
|
||||||
tags: ["Bitcoin", "Stats", "OpenStreetMaps"]
|
tags: ["Bitcoin", "Stats", "OpenStreetMaps"]
|
||||||
---
|
---
|
||||||
|
|
||||||
The table below illustrates growth of businesses worldwide that accept bitcoin as payment for products or services. The accompanying chart displays the yearly cumulative number of bitcoin-accepting businesses for the countries selected in the table. The data is sourced from OpenStreetMaps and is updated approximately every 2 hours.
|
The table below illustrates growth of businesses worldwide that accept bitcoin as payment for products or services. The accompanying chart displays the cumulative number of bitcoin-accepting businesses for the countries selected in the table. The data is sourced from OpenStreetMaps and is updated approximately every 2 hours.
|
||||||
|
|
||||||
You can select the growth period of interest from the drop-down, which updates the values in the table. The table shows the ***Previous*** value, which was the number of businesses *n* days ago specified in the drop-down. The ***Current*** value is the number of businesses as of the latest update. The table also shows the ***Absolute Difference***, and the ***Percent Difference*** between this period.
|
You can select the growth period of interest from the drop-down, which updates the values in the table. The table shows the ***Previous*** value, which was the number of businesses *n* days ago specified in the drop-down. The ***Current*** value is the number of businesses as of the latest update. The table also shows the ***Absolute Difference***, and the ***Percent Difference*** between this period.
|
||||||
|
|
||||||
The chart always reflects the countries selected in the table. There is a zoom feature on the chart to focus in on a period of interest.
|
The chart always reflects the countries selected in the table.
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
Select growth period: {{< dropdown-filter id=cumulative_period_type select="365 day,28 day,7 day,1 day" >}}
|
|
||||||
{{< chart src="/js/bitcoin-business-growth-chart.js" >}}
|
{{< chart src="/js/bitcoin-business-growth-chart.js" >}}
|
||||||
{{< table src="/js/bitcoin-business-growth-table.js" >}}
|
{{< table src="/js/bitcoin-business-growth-table.js" >}}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
baseURL = 'https://baseddata.io/'
|
baseURL = 'baseddata.io'
|
||||||
languageCode = 'en-gb'
|
languageCode = 'en-gb'
|
||||||
title = 'Based Data'
|
title = 'Based Data'
|
||||||
|
|
||||||
|
[params]
|
||||||
|
apiURL = 'http://localhost:5000'
|
||||||
|
|
||||||
[markup.highlight]
|
[markup.highlight]
|
||||||
pygmentsUseClasses = false
|
pygmentsUseClasses = false
|
||||||
codeFences = true
|
codeFences = true
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.1/dist/echarts.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.1/dist/echarts.min.js"></script>
|
||||||
<section class="chart-container">
|
<section class="chart-container">
|
||||||
|
<div id="chart-modifiers"></div>
|
||||||
<div id="chart">
|
<div id="chart">
|
||||||
<canvas id="{{ .id }}"></canvas>
|
|
||||||
<script src="{{ .src }}"></script>
|
<script src="{{ .src }}"></script>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<p id="price"></p>
|
<p id="price"></p>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
fetch("https://api.baseddata.io/get_json/final__price.json")
|
fetch(`${"{{ .Site.Params.apiURL }}"}/get_json/final__price.json`)
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
var lastElement = data[data.length - 1];
|
var lastElement = data[data.length - 1];
|
||||||
|
|
|
@ -1,2 +1,5 @@
|
||||||
{{ $id := .Get "src" | md5 }}
|
<script>
|
||||||
{{ partial "chart.html" (dict "src" (.Get "src") "id" $id) }}
|
const apiURL = "{{ .Site.Params.apiURL }}";
|
||||||
|
</script>
|
||||||
|
{{ $id := .Get "src" | md5 }} {{ partial "chart.html" (dict "src" (.Get "src")
|
||||||
|
"id" $id) }}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<script>
|
<script>
|
||||||
async function downloadFile(url, name) {
|
async function downloadFile(url, name) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(url);
|
const response = await fetch(`${"{{ .Site.Params.apiURL }}"}/download${url}`);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error('Network response was not ok');
|
throw new Error('Network response was not ok');
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
<select id={{ .Get "id" }} class="dropdownFilter">
|
|
||||||
{{ with .Get "select" }}
|
|
||||||
{{ range $index, $element := split . "," }}
|
|
||||||
<option value="{{ $element }}">{{ $element }}</option>
|
|
||||||
{{ end }}
|
|
||||||
</select>
|
|
||||||
{{ end }}
|
|
|
@ -16,4 +16,9 @@
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
#chart-modifiers {
|
||||||
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
let chartData = [];
|
let chartData = [];
|
||||||
let myChart;
|
let myChart;
|
||||||
|
|
||||||
async function fetchDataForChart(str) {
|
let periodIndex = 3;
|
||||||
|
|
||||||
|
const periods = ["1 day", "7 day", "28 day", "365 day"];
|
||||||
|
|
||||||
|
async function fetchDataForChart(str, period) {
|
||||||
try {
|
try {
|
||||||
const apiEndpoint = `${apiURL}/bitcoin_business_growth_by_country?cumulative_period_type=365 day&countries=${str}`;
|
const apiEndpoint = `${apiURL}/bitcoin_business_growth_by_country?cumulative_period_type=${period}&countries=${str}`;
|
||||||
console.log("Fetching from " + apiEndpoint);
|
console.log("Fetching from " + apiEndpoint);
|
||||||
const response = await fetch(apiEndpoint);
|
const response = await fetch(apiEndpoint);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
|
@ -70,30 +74,35 @@ function handleCheckboxChange(event) {
|
||||||
if (event.target.type === "checkbox") {
|
if (event.target.type === "checkbox") {
|
||||||
const boxChecked = event.target.checked;
|
const boxChecked = event.target.checked;
|
||||||
const boxId = event.target.id;
|
const boxId = event.target.id;
|
||||||
|
let selectedPeriod = getPeriodFromDropdown();
|
||||||
// Remove unchecked boxes
|
// Remove unchecked boxes
|
||||||
if (boxChecked === false) {
|
if (boxChecked === false) {
|
||||||
delete chartData[boxId];
|
delete chartData[boxId];
|
||||||
updateChart();
|
updateChart();
|
||||||
// Add checked boxes
|
// Add checked boxes
|
||||||
} else {
|
} else {
|
||||||
fetchDataForChart(boxId);
|
fetchDataForChart(boxId, selectedPeriod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("reloadTable", () => {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
myChart = echarts.init(document.getElementById("chart"));
|
periodDropdown(periods, periodIndex);
|
||||||
jsonTableCheckedBoxes = document.querySelectorAll(
|
document.addEventListener("reloadTable", () => {
|
||||||
'#jsonTableContainer input[type="checkbox"]:checked',
|
myChart = echarts.init(document.getElementById("chart"));
|
||||||
);
|
jsonTableCheckedBoxes = document.querySelectorAll(
|
||||||
const checkedBoxes = Array.from(jsonTableCheckedBoxes).map(
|
'#jsonTableContainer input[type="checkbox"]:checked',
|
||||||
(checkbox) => checkbox.id,
|
);
|
||||||
);
|
const checkedBoxes = Array.from(jsonTableCheckedBoxes).map(
|
||||||
const str = checkedBoxes.join(",");
|
(checkbox) => checkbox.id,
|
||||||
chartData = [];
|
);
|
||||||
fetchDataForChart(str);
|
const str = checkedBoxes.join(",");
|
||||||
|
let selectedPeriod = getPeriodFromDropdown();
|
||||||
|
chartData = [];
|
||||||
|
fetchDataForChart(str, selectedPeriod);
|
||||||
|
|
||||||
jsonTable = document.getElementById("jsonTableContainer");
|
jsonTable = document.getElementById("jsonTableContainer");
|
||||||
jsonTable.removeEventListener("change", handleCheckboxChange);
|
jsonTable.removeEventListener("change", handleCheckboxChange);
|
||||||
jsonTable.addEventListener("change", handleCheckboxChange);
|
jsonTable.addEventListener("change", handleCheckboxChange);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
async function fetchDataForTable() {
|
async function fetchDataForTable() {
|
||||||
try {
|
try {
|
||||||
const dropdown = document.querySelector(".dropdownFilter");
|
selectedPeriod = getPeriodFromDropdown();
|
||||||
let selectedIndex = dropdown.selectedIndex;
|
|
||||||
let selectedValue = dropdown.options[selectedIndex].value;
|
|
||||||
const apiEndpoint = `${apiURL}/bitcoin_business_growth_by_country?latest_date=true`;
|
const apiEndpoint = `${apiURL}/bitcoin_business_growth_by_country?latest_date=true`;
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
apiEndpoint + `&cumulative_period_type=${selectedValue}`,
|
apiEndpoint + `&cumulative_period_type=${selectedPeriod}`,
|
||||||
);
|
);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
@ -88,10 +86,10 @@ function createTable(data) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.onload = () => {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
const dropdown = document.querySelector(".dropdownFilter");
|
const dropdown = document.getElementById("select-period-dropdown");
|
||||||
fetchDataForTable();
|
fetchDataForTable();
|
||||||
dropdown.addEventListener("change", () => {
|
dropdown.addEventListener("change", () => {
|
||||||
fetchDataForTable();
|
fetchDataForTable();
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
|
|
|
@ -1,9 +1,18 @@
|
||||||
let dataArr = [];
|
let dataArr = [];
|
||||||
const myChart = echarts.init(document.getElementById("chart"));
|
const myChart = echarts.init(document.getElementById("chart"));
|
||||||
|
const filename = "final__price.json";
|
||||||
|
|
||||||
async function fetchDataForChart() {
|
const periods = [
|
||||||
|
"all time",
|
||||||
|
"last 7 days",
|
||||||
|
"last 28 days",
|
||||||
|
"last 365 days",
|
||||||
|
"last 2 years",
|
||||||
|
];
|
||||||
|
|
||||||
|
async function fetchDataForChart(selectedValue) {
|
||||||
try {
|
try {
|
||||||
const apiEndpoint = `${apiURL}/get_json/final__price.json`;
|
const apiEndpoint = `${apiURL}/get_json/${filename}?period=${selectedValue}`;
|
||||||
const response = await fetch(apiEndpoint);
|
const response = await fetch(apiEndpoint);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
@ -27,7 +36,7 @@ function initEchart(dataArr) {
|
||||||
axisLine: axisLine,
|
axisLine: axisLine,
|
||||||
},
|
},
|
||||||
grid: grid,
|
grid: grid,
|
||||||
dataZoom: dataZoom(),
|
dataZoom: dataZoom(0),
|
||||||
yAxis: [
|
yAxis: [
|
||||||
{
|
{
|
||||||
type: "value",
|
type: "value",
|
||||||
|
@ -62,4 +71,14 @@ function initEchart(dataArr) {
|
||||||
myChart.setOption(option);
|
myChart.setOption(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchDataForChart();
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
let periodIndex = 2;
|
||||||
|
periodDropdown(periods, periodIndex);
|
||||||
|
fetchDataForChart(periods[periodIndex]);
|
||||||
|
const selectElement = document.getElementById("select-period-dropdown");
|
||||||
|
|
||||||
|
selectElement.addEventListener("change", function (event) {
|
||||||
|
const selectedValue = event.target.value;
|
||||||
|
fetchDataForChart(selectedValue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -106,6 +106,35 @@ function nFormatter(value, digits) {
|
||||||
: "0";
|
: "0";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function periodDropdown(periods, defaultIndex = 0) {
|
||||||
|
const modifiers = document.getElementById("chart-modifiers");
|
||||||
|
const dropdownContainer = document.createElement("div");
|
||||||
|
const dropdown = document.createElement("select");
|
||||||
|
const textNode = document.createTextNode("Select period: ");
|
||||||
|
|
||||||
|
dropdownContainer.id = "dropdown-container";
|
||||||
|
dropdown.id = "select-period-dropdown";
|
||||||
|
dropdownContainer.appendChild(textNode);
|
||||||
|
dropdownContainer.appendChild(dropdown);
|
||||||
|
modifiers.appendChild(dropdownContainer);
|
||||||
|
|
||||||
|
periods.forEach((period, index) => {
|
||||||
|
const option = document.createElement("option");
|
||||||
|
if (index === defaultIndex) {
|
||||||
|
option.selected = true;
|
||||||
|
}
|
||||||
|
option.value = period;
|
||||||
|
option.textContent = period;
|
||||||
|
dropdown.appendChild(option);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPeriodFromDropdown() {
|
||||||
|
let dropdown = document.getElementById("select-period-dropdown");
|
||||||
|
let selectedIndex = dropdown.selectedIndex;
|
||||||
|
return dropdown.options[selectedIndex].value;
|
||||||
|
}
|
||||||
|
|
||||||
window.addEventListener("resize", function () {
|
window.addEventListener("resize", function () {
|
||||||
if (myChart != null && myChart != undefined) {
|
if (myChart != null && myChart != undefined) {
|
||||||
myChart.resize();
|
myChart.resize();
|
||||||
|
|
|
@ -1,9 +1,18 @@
|
||||||
let dataArr = [];
|
let dataArr = [];
|
||||||
const myChart = echarts.init(document.getElementById("chart"));
|
const myChart = echarts.init(document.getElementById("chart"));
|
||||||
|
const filename = "final__feerate_percentiles.json";
|
||||||
|
|
||||||
async function fetchDataForChart() {
|
const periods = [
|
||||||
|
"all time",
|
||||||
|
"last 7 days",
|
||||||
|
"last 28 days",
|
||||||
|
"last 365 days",
|
||||||
|
"last 2 years",
|
||||||
|
];
|
||||||
|
|
||||||
|
async function fetchDataForChart(selectedValue) {
|
||||||
try {
|
try {
|
||||||
const apiEndpoint = `${apiURL}/get_json/final__feerate_percentiles.json`;
|
const apiEndpoint = `${apiURL}/get_json/${filename}?period=${selectedValue}`;
|
||||||
const response = await fetch(apiEndpoint);
|
const response = await fetch(apiEndpoint);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
@ -38,7 +47,7 @@ function initEchart(dataArr) {
|
||||||
axisLine: axisLine,
|
axisLine: axisLine,
|
||||||
},
|
},
|
||||||
grid: grid,
|
grid: grid,
|
||||||
dataZoom: dataZoom((start = 98)),
|
dataZoom: dataZoom(0),
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
type: "line",
|
type: "line",
|
||||||
|
@ -104,4 +113,15 @@ function initEchart(dataArr) {
|
||||||
|
|
||||||
myChart.setOption(option);
|
myChart.setOption(option);
|
||||||
}
|
}
|
||||||
fetchDataForChart();
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
let periodIndex = 2;
|
||||||
|
periodDropdown(periods, periodIndex);
|
||||||
|
fetchDataForChart(periods[periodIndex]);
|
||||||
|
const selectElement = document.getElementById("select-period-dropdown");
|
||||||
|
|
||||||
|
selectElement.addEventListener("change", function (event) {
|
||||||
|
const selectedValue = event.target.value;
|
||||||
|
fetchDataForChart(selectedValue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
let dataArr = [];
|
let dataArr = [];
|
||||||
const myChart = echarts.init(document.getElementById("chart"));
|
const myChart = echarts.init(document.getElementById("chart"));
|
||||||
|
const filename = "final__hashrate.json";
|
||||||
|
const periods = [
|
||||||
|
"all time",
|
||||||
|
"last 7 days",
|
||||||
|
"last 28 days",
|
||||||
|
"last 365 days",
|
||||||
|
"last 2 years",
|
||||||
|
];
|
||||||
|
|
||||||
async function fetchDataForChart() {
|
async function fetchDataForChart(selectedValue) {
|
||||||
try {
|
try {
|
||||||
const apiEndpoint = `${apiURL}/get_json/final__hashrate.json`;
|
const apiEndpoint = `${apiURL}/get_json/${filename}?period=${selectedValue}`;
|
||||||
const response = await fetch(apiEndpoint);
|
const response = await fetch(apiEndpoint);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
@ -32,7 +40,7 @@ function initEchart(dataArr) {
|
||||||
axisLine: axisLine,
|
axisLine: axisLine,
|
||||||
},
|
},
|
||||||
grid: grid,
|
grid: grid,
|
||||||
dataZoom: dataZoom(),
|
dataZoom: dataZoom(0),
|
||||||
yAxis: [
|
yAxis: [
|
||||||
{
|
{
|
||||||
type: "value",
|
type: "value",
|
||||||
|
@ -105,4 +113,15 @@ function initEchart(dataArr) {
|
||||||
|
|
||||||
myChart.setOption(option);
|
myChart.setOption(option);
|
||||||
}
|
}
|
||||||
fetchDataForChart();
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
let periodIndex = 2;
|
||||||
|
periodDropdown(periods, periodIndex);
|
||||||
|
fetchDataForChart(periods[periodIndex]);
|
||||||
|
const selectElement = document.getElementById("select-period-dropdown");
|
||||||
|
|
||||||
|
selectElement.addEventListener("change", function (event) {
|
||||||
|
const selectedValue = event.target.value;
|
||||||
|
fetchDataForChart(selectedValue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
let dataArr = [];
|
let dataArr = [];
|
||||||
const myChart = echarts.init(document.getElementById("chart"));
|
const myChart = echarts.init(document.getElementById("chart"));
|
||||||
|
const filename = "final__miner_rewards.json";
|
||||||
|
const periods = [
|
||||||
|
"all time",
|
||||||
|
"last 7 days",
|
||||||
|
"last 28 days",
|
||||||
|
"last 365 days",
|
||||||
|
"last 2 years",
|
||||||
|
];
|
||||||
|
|
||||||
async function fetchDataForChart() {
|
async function fetchDataForChart(selectedValue) {
|
||||||
try {
|
try {
|
||||||
const apiEndpoint = `${apiURL}/get_json/${filename}?period=${selectedValue}`;
|
const apiEndpoint = `${apiURL}/get_json/${filename}?period=${selectedValue}`;
|
||||||
const response = await fetch(apiEndpoint);
|
const response = await fetch(apiEndpoint);
|
||||||
|
@ -16,9 +24,37 @@ async function fetchDataForChart() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function initEchart(dataArr) {
|
function initEchart(dataArr) {
|
||||||
|
console.log(dataArr);
|
||||||
const option = {
|
const option = {
|
||||||
backgroundColor: backgroundColor,
|
backgroundColor: backgroundColor,
|
||||||
tooltip: tooltip,
|
tooltip: {
|
||||||
|
...tooltip,
|
||||||
|
formatter: function (params) {
|
||||||
|
let colors = ["#ee6666", "#000000", "#b0da9d", "#8699d5"];
|
||||||
|
let colorSpan = (color) =>
|
||||||
|
'<span style="display:inline-block;margin-right:1px;border-radius:5px;width:9px;height:9px;background-color:' +
|
||||||
|
color +
|
||||||
|
'"></span>';
|
||||||
|
let tooltip = "<p>" + params[0].axisValue + "</p>";
|
||||||
|
params.reverse().forEach((item, index) => {
|
||||||
|
let color = colors[index % colors.length];
|
||||||
|
let labels =
|
||||||
|
"<p>" +
|
||||||
|
colorSpan(color) +
|
||||||
|
" " +
|
||||||
|
item.seriesName +
|
||||||
|
": " +
|
||||||
|
nFormatter(item.data, 3);
|
||||||
|
("</p>");
|
||||||
|
tooltip += labels;
|
||||||
|
});
|
||||||
|
|
||||||
|
return tooltip;
|
||||||
|
},
|
||||||
|
valueFormatter(value, index) {
|
||||||
|
return nFormatter(value, 3);
|
||||||
|
},
|
||||||
|
},
|
||||||
toolbox: toolboxParams,
|
toolbox: toolboxParams,
|
||||||
xAxis: {
|
xAxis: {
|
||||||
data: dataArr.map((row) => row.date),
|
data: dataArr.map((row) => row.date),
|
||||||
|
@ -27,13 +63,13 @@ function initEchart(dataArr) {
|
||||||
axisLine: axisLine,
|
axisLine: axisLine,
|
||||||
},
|
},
|
||||||
grid: grid,
|
grid: grid,
|
||||||
dataZoom: dataZoom(97),
|
dataZoom: dataZoom(0),
|
||||||
yAxis: [
|
yAxis: [
|
||||||
{
|
{
|
||||||
type: "value",
|
type: "value",
|
||||||
name: "Rewards (USD)",
|
name: "Rewards (USD)",
|
||||||
nameLocation: "middle",
|
nameLocation: "middle",
|
||||||
nameGap: 35,
|
nameGap: 30,
|
||||||
nameTextStyle: textStyleMain,
|
nameTextStyle: textStyleMain,
|
||||||
position: "left",
|
position: "left",
|
||||||
alignTicks: true,
|
alignTicks: true,
|
||||||
|
@ -51,7 +87,7 @@ function initEchart(dataArr) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "value",
|
type: "value",
|
||||||
name: "Block Subsidy (BTC)",
|
name: "Subsidy (BTC)",
|
||||||
nameLocation: "middle",
|
nameLocation: "middle",
|
||||||
nameGap: 20,
|
nameGap: 20,
|
||||||
nameTextStyle: {
|
nameTextStyle: {
|
||||||
|
@ -74,8 +110,7 @@ function initEchart(dataArr) {
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
type: "line",
|
type: "line",
|
||||||
name: "Daily Subsidy (USD)",
|
name: "Subsidy (USD)",
|
||||||
smooth: true,
|
|
||||||
stack: "Total",
|
stack: "Total",
|
||||||
areaStyle: {},
|
areaStyle: {},
|
||||||
symbol: "none",
|
symbol: "none",
|
||||||
|
@ -86,8 +121,7 @@ function initEchart(dataArr) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "line",
|
type: "line",
|
||||||
name: "Daily Fees (USD)",
|
name: "Fees (USD)",
|
||||||
smooth: true,
|
|
||||||
stack: "Total",
|
stack: "Total",
|
||||||
areaStyle: {},
|
areaStyle: {},
|
||||||
symbol: "none",
|
symbol: "none",
|
||||||
|
@ -98,8 +132,7 @@ function initEchart(dataArr) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "line",
|
type: "line",
|
||||||
name: "Daily Total Reward (USD)",
|
name: "Total (USD)",
|
||||||
smooth: true,
|
|
||||||
symbol: "none",
|
symbol: "none",
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
width: 1,
|
width: 1,
|
||||||
|
@ -123,4 +156,14 @@ function initEchart(dataArr) {
|
||||||
myChart.setOption(option);
|
myChart.setOption(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchDataForChart();
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
let periodIndex = 2;
|
||||||
|
periodDropdown(periods, periodIndex);
|
||||||
|
fetchDataForChart(periods[periodIndex]);
|
||||||
|
const selectElement = document.getElementById("select-period-dropdown");
|
||||||
|
|
||||||
|
selectElement.addEventListener("change", function (event) {
|
||||||
|
const selectedValue = event.target.value;
|
||||||
|
fetchDataForChart(selectedValue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in New Issue