diff --git a/manual_graph/Gemfile b/manual_graph/Gemfile new file mode 100644 index 0000000..246c7ef --- /dev/null +++ b/manual_graph/Gemfile @@ -0,0 +1,7 @@ +source "https://rubygems.org" + +gem "sequel" +gem "pry" +gem "pg" +gem "sinatra" +gem "puma" diff --git a/manual_graph/Gemfile.lock b/manual_graph/Gemfile.lock new file mode 100644 index 0000000..a61e6d7 --- /dev/null +++ b/manual_graph/Gemfile.lock @@ -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 diff --git a/manual_graph/README.md b/manual_graph/README.md new file mode 100644 index 0000000..a275447 --- /dev/null +++ b/manual_graph/README.md @@ -0,0 +1,12 @@ +# manual graph + +## Running + +``` +export DATABASE_URL="" +bundle exec ruby server.rb +``` + +``` +open index.html +``` diff --git a/manual_graph/frontend.html b/manual_graph/frontend.html new file mode 100644 index 0000000..0c11ccd --- /dev/null +++ b/manual_graph/frontend.html @@ -0,0 +1,115 @@ + + + + + + + + + + +
+ + + + + \ No newline at end of file diff --git a/manual_graph/server.rb b/manual_graph/server.rb new file mode 100644 index 0000000..d7fa52e --- /dev/null +++ b/manual_graph/server.rb @@ -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 +