require "http/client" require "http/headers" require "http/request" require "ishi/html" require "json" require "uuid" require "db" require "pg" USER = File.read("/var/openfaas/secrets/nombres-user").strip PASS = File.read("/var/openfaas/secrets/nombres-pass").strip class Handler def format_buffer(buffer, canvas_name, title = "") # Process the gnuplot output so it works in the page # # buffer is the Ishi output # name is a string to replace for gnuplot_canvas so # we can have multiple charts in a page # title is added on top of the chart html = buffer.to_s.split("\n") html = html[html.index("")] html = "#{title}" + html.join("\n") + %(
Sorry, your browser seems not to support the HTML 5 canvas element
) # This ID needs to be unique in case # we have 2 charts in the same page html.gsub("gnuplot_canvas", canvas_name) end def query(sql) # Runs a SQL query against the database. # # Returns an array of values [[Year,Count]...] # Or nil if there are no results DB.open("postgres://#{USER}:#{PASS}@10.61.0.1:5432/nombres") do |cursor| cursor.query sql do |result_set| result = [] of Tuple(Int32, Int32) result_set.each do year = result_set.read(Int32) contador = result_set.read(Int32) result.push({year, contador}) end return result end end # No result, return nil nil end nombres = [] of String def normalize_name(s) # Remove diacritics, turn lowercase normalized = s.unicode_normalize(:nfkd).chars normalized.reject! { |character| !character.ascii_letter? }.join("").downcase end def run(request : HTTP::Request) unless (body = request.body).nil? query = JSON.parse(body) nombres = query["i"].as_s.split(",").map(&.strip) nombres.reject! { |nombre| nombre.size == 0 } end if nombres.nil? || nombres.empty? nombres = ["maria", "juan"] end # Remove all diacritics and whatnot nombres = nombres.map { |nombre| normalize_name nombre } puts "Processing #{nombres}" buffer = IO::Memory.new Ishi.new(buffer) do canvas_size(800, 300) show_key(true) xrange(1922..2015) nombres.map { |nombre| sql = "SELECT anio::integer, contador::integer FROM nombres WHERE nombre = '#{nombre}' ORDER BY anio" x = Array(Int32).new y = Array(Int32).new results = query(sql) if results.nil? # No results, all 0s x = (1922..2015).to_a y = x.map { |_| 0 } else # We got results values = Hash(Int32, Int32).new(default_value: 0) results.map { |row| values[row[0]] = row[1] } (1922..2015).map { |year| x << year y << values[year] # Defaults to 0, so we have the whole set } end plot(x, y, title: nombre.titleize, style: :lines, linewidth: 3) } end puts "After Ishi" { body: format_buffer(buffer, "historico"), status_code: 200, headers: HTTP::Headers{"Content-Type" => "text/html"}, } end end