Skip to content

Commit

Permalink
Add new manual_graph code
Browse files Browse the repository at this point in the history
  • Loading branch information
KrauseFx committed May 17, 2022
1 parent d13f7ce commit 16960e9
Show file tree
Hide file tree
Showing 5 changed files with 239 additions and 0 deletions.
7 changes: 7 additions & 0 deletions manual_graph/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
source "https://rubygems.org"

gem "sequel"
gem "pry"
gem "pg"
gem "sinatra"
gem "puma"
38 changes: 38 additions & 0 deletions manual_graph/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
GEM
remote: https://rubygems.org/
specs:
coderay (1.1.3)
method_source (1.0.0)
mustermann (1.1.1)
ruby2_keywords (~> 0.0.1)
nio4r (2.5.8)
pg (1.3.5)
pry (0.14.1)
coderay (~> 1.1)
method_source (~> 1.0)
puma (5.6.4)
nio4r (~> 2.0)
rack (2.2.3)
rack-protection (2.2.0)
rack
ruby2_keywords (0.0.5)
sequel (5.56.0)
sinatra (2.2.0)
mustermann (~> 1.0)
rack (~> 2.2)
rack-protection (= 2.2.0)
tilt (~> 2.0)
tilt (2.0.10)

PLATFORMS
arm64-darwin-21

DEPENDENCIES
pg
pry
puma
sequel
sinatra

BUNDLED WITH
2.3.9
12 changes: 12 additions & 0 deletions manual_graph/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# manual graph

## Running

```
export DATABASE_URL=""
bundle exec ruby server.rb
```

```
open index.html
```
115 changes: 115 additions & 0 deletions manual_graph/frontend.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<html>

<head>
<script src="https://cdn.plot.ly/plotly-2.12.1.min.js"></script>
<meta charset="utf-8">
</head>

<body>
<input type="text" placeholder="key" value="mood" id="keySelector" onkeydown="keyDown(this)" />
<input type="button" value="Get Data" id="keyButton" />
<div id='myGraph' />
</body>

<script type="text/javascript">
document.getElementById("keyButton").onclick = function() {
getData(document.getElementById("keySelector").value)
}

function keyDown(el) {
if (event.key === 'Enter') {
getData(document.getElementById("keySelector").value)
}
}

function getData(key) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
renderKey(JSON.parse(xhr.responseText), key);
}
}
xhr.open("GET", "http://127.0.0.1:8080?key=" + key, true);
xhr.send();
}

function renderKey(data, key) {
var trace1 = {
x: Object.keys(data),
y: Object.values(data).map(function(v) {
return v["day"]
}),
mode: 'markers',
marker: {
color: 'rgb(219, 64, 82)',
size: 4
},
name: 'Values'
};

var trace5 = {
x: Object.keys(data),
y: Object.values(data).map(function(v) {
return v["week"]
}),
mode: 'lines',
line: {
color: 'rgba(100, 200, 191)',
width: 2
},
name: 'Weekly'
};


var trace2 = {
x: Object.keys(data),
y: Object.values(data).map(function(v) {
return v["month"]
}),
mode: 'lines',
line: {
color: 'rgb(55, 128, 191)',
width: 4
},
name: 'Monthly'
};

var trace3 = {
x: Object.keys(data),
y: Object.values(data).map(function(v) {
return v["quarter"]
}),
mode: 'lines',
line: {
color: 'rgb(128, 0, 128)',
width: 2
},
name: "Quarter"
};

var trace4 = {
x: Object.keys(data),
y: Object.values(data).map(function(v) {
return v["year"]
}),
mode: 'lines',
line: {
color: 'rgb(128, 0, 128)',
width: 0.5
},
name: "Year"
};


var traces = [trace1, trace5, trace2, trace3, trace4];

var layout = {
title: key + ' over time'
};

Plotly.newPlot('myGraph', traces, layout);
}
getData("mood");
</script>

</html>
67 changes: 67 additions & 0 deletions manual_graph/server.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
require "json"
require "sinatra"
require "sequel"
require "pry"

class Server
def fetch(key:)
return cache[key] if cache.key?(key)

date = Date.new(2020, 1, 1)
result = {}
while date < Date.today - 1
date += 1
puts "fetch data for #{date}"
result[date] = process_date(date, key)
end
cache[key] = result
return result
end

def process_date(date, key)
raise "invalid key" unless key.match(/^[[:alpha:][:blank:]]+$/)
# Find the timestamp of the end of a given day
eod_timestamp = (date + 1).to_time.to_i * 1000

day_timestamp = date.to_time.to_i * 1000
week_timestamp = (date - 7).to_time.to_i * 1000
month_timestamp = (date - 30).to_time.to_i * 1000
quarter_timestamp = (date - 90).to_time.to_i * 1000
year_timestamp = (date - 365).to_time.to_i * 1000
all_time_timestamp = 0

query = "SELECT "
query += "(SELECT ROUND(AVG(value::numeric), 4) FROM raw_data WHERE timestamp > #{day_timestamp} AND timestamp <= #{eod_timestamp} AND key='#{key}') as day,"
query += "(SELECT ROUND(AVG(value::numeric), 4) FROM raw_data WHERE timestamp > #{week_timestamp} AND timestamp <= #{eod_timestamp} AND key='#{key}') as week,"
query += "(SELECT ROUND(AVG(value::numeric), 4) FROM raw_data WHERE timestamp > #{month_timestamp} AND timestamp <= #{eod_timestamp} AND key='#{key}') as month,"
query += "(SELECT ROUND(AVG(value::numeric), 4) FROM raw_data WHERE timestamp > #{quarter_timestamp} AND timestamp <= #{eod_timestamp} AND key='#{key}') as quarter,"
query += "(SELECT ROUND(AVG(value::numeric), 4) FROM raw_data WHERE timestamp > #{year_timestamp} AND timestamp <= #{eod_timestamp} AND key='#{key}') as year,"
query += "(SELECT ROUND(AVG(value::numeric), 4) FROM raw_data WHERE timestamp > #{all_time_timestamp} AND timestamp <= #{eod_timestamp} AND key='#{key}') as all_time"

return db[query].to_a.first.collect { |k, v| [k, v ? v.to_f : nil] }.to_h # convert BigFloat
end

def db
@_db ||= Sequel.connect(ENV.fetch("DATABASE_URL"))
end

def raw_data
@_raw_data ||= db[:raw_data]
end

def cache
@_cache ||= {}
end
end



# Sinatra API get request for JSON data
server = Server.new
get '/' do
content_type 'application/json'
response['Access-Control-Allow-Origin'] = '*'

server.fetch(key: params.fetch("key")).to_json
end

0 comments on commit 16960e9

Please sign in to comment.