Switching the crystal functions to faaso

This commit is contained in:
2024-08-17 19:28:10 -03:00
parent 8846ad3841
commit 33c95bca6b
23 changed files with 668 additions and 400 deletions

11
historico/README.md Normal file
View File

@ -0,0 +1,11 @@
# Readme for Historico
This is a funko using the Crystal runtime for [FaaSO](https://git.ralsina.me/ralsina/faaso)
## What is Historico
Write here what it is
## How to use Historico
And so on.

View File

66
historico/funko.cr Normal file
View File

@ -0,0 +1,66 @@
require "json"
require "kemal"
require "pg"
require "pool/connection"
# get credentials from secrets
USER = File.read("/secrets/user").strip
PASS = File.read("/secrets/pass").strip
DBHOST = File.read("/secrets/dbhost").strip
DBURL = "postgres://#{USER}:#{PASS}@#{DBHOST}:5432/nombres"
puts "Connnecting to #{DBURL}"
# Create a connection pool to the database
pg = ConnectionPool.new(capacity: 5, timeout: 0.01.seconds) do
PG.connect(DBURL)
end
# Connect to the database and get information about
# the requested names
get "/" do |env|
# Names are query parameters
# Split by commas, capitalize and take the first 5
names = env.params.query["names"]
.split(",").map(&.strip.capitalize)[..4]
# Prepare results table
results = [] of Array(String)
results << ["Año"] + names
(1922..2015).each do |anio|
results << [anio.to_s]
end
# Connect using credentials provided
pg.connection do |cursor|
# Get the information for each name
names.map do |name|
# Normalize: remove diacritics etc.
name = name.unicode_normalize(:nfkd)
.chars.reject! { |character|
!character.ascii_letter? && (character != ' ')
}.join("").downcase
counter_per_year = {} of Int32 => Int32
cursor.query("
SELECT anio::integer, contador::integer
FROM nombres WHERE nombre = $1", name) do |result_set|
result_set.each do
counter_per_year[result_set.read(Int32)] = result_set.read(Int32)
end
end
(1922..2015).each do |anio|
results[anio - 1921] << counter_per_year.fetch(anio, 0).to_s
end
end
end
results.to_json
end
# The `/ping/` endpoint is configured in the container as a healthcheck
# You can make it better by checking that your database is responding
# or whatever checks you think are important
#
get "/ping/" do
pg.connection.exec("SELECT 42")
"OK"
end

11
historico/funko.yml Normal file
View File

@ -0,0 +1,11 @@
name: historico
runtime: kemal
options:
shard_build_options: ""
ship_packages: []
devel_packages: []
healthcheck_options: "--interval=1m --timeout=2s --start-period=2s --retries=3"
healthcheck_command: "curl --fail http://localhost:3000/ping || exit 1"
copy_from_build:
- "public public"
- "bin/funko ."

View File

@ -1,66 +0,0 @@
import unicodedata
import urllib
from collections import defaultdict as ddict
from dataclasses import dataclass
from json import loads
import pygal
import pyrqlite.dbapi2 as dbapi2
import requests
connection = dbapi2.connect(
host="10.61.0.1",
user="root",
port=4001,
password="",
)
def remove_accents(input_str):
nfkd_form = unicodedata.normalize("NFKD", input_str)
return "".join([c for c in nfkd_form if not unicodedata.combining(c)])
def handle(req):
"""handle a request to the function
Args:
req (str): request body
{"i": ["nombre1, nombre2"]}
"""
nombres = []
try:
nombres = loads(req)
nombres = nombres["i"].split(",")
nombres = [remove_accents(x.strip().lower()) for x in nombres]
nombres = [n for n in nombres if n]
except Exception:
pass
if not nombres:
nombres = ["maria", "juan"]
chart = pygal.Line(
height=200, fill=True, human_readable=True, show_minor_x_labels=False
)
chart.x_labels = [str(x) for x in range(1922, 2015)]
chart.x_labels_major = [str(x) if x % 10 == 0 else "" for x in range(1922, 2015)]
for nombre in nombres:
datos = ddict(int)
with connection.cursor() as cursor:
sql = """
SELECT anio, contador, nombre
FROM nombres
WHERE nombre = :nombre
ORDER BY anio
"""
cursor.execute(sql, {"nombre": nombre})
datos.update({r["anio"]: r["contador"] for r in cursor.fetchall()})
chart.add(nombre.title(), [datos[x] for x in range(1922, 2015)])
chart.x_labels = [str(n) for n in range(1922, 2015)]
chart.x_labels_major = [str(n) for n in range(1920, 2020, 10)]
# return Response(chart.render(is_unicode=True), mimetype="image/svg+xml")
return chart.render(is_unicode=True), 200, {"Content-Type": "image/svg+xml"}

109
historico/public/index.html Normal file
View File

@ -0,0 +1,109 @@
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script
type="text/javascript"
src="https://www.gstatic.com/charts/loader.js"
></script>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<!-- Font -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@300..700&display=swap"
rel="stylesheet">
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.colors.min.css"
/>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Kode+Mono&display=swap"
rel="stylesheet"
/>
<script type="text/javascript">
google.charts.load("current", { packages: ["corechart"] });
google.charts.setOnLoadCallback(drawChart);
async function drawChart() {
fetch(
"/faaso/historico/?" +
new URLSearchParams({
names: document.getElementById("nombres").value,
})
)
.then((response) => response.json())
.then((json) => {
var data = [json[0]];
data.push(
...json
.slice(1)
.map((item) => item.map((value) => parseInt(value)))
);
data = google.visualization.arrayToDataTable(data);
var options = {
title: "",
animation: {
startup: true,
duration: 1000,
easing: "out",
},
backgroundColor: "#1c212c",
vAxis: {
minValue: 0,
gridlines: { color: "#666" },
minorGridlines: { color: "#1c212c" },
textStyle: { color: "#aaa" }
},
hAxis: {
gridlines: { color: "#666" },
minorGridlines: { color: "#1c212c" },
textStyle: { color: "#aaa" }
},
legend: { position: "bottom", textStyle: { color: "#aaa" } },
};
var chart = new google.visualization.LineChart(
document.getElementById("chart")
);
chart.draw(data, options);
});
}
</script>
<style>
html * {
font-family: 'Quicksand', sans-serif;
}
</style>
</head>
<body>
<main class="container" style="text-align: center">
<header>
<h1>Popularidad de Nombres en Argentina</h1>
</header>
<div id="chart" style="width: 80vw; height: 50vh; margin: auto"></div>
<form
role="search"
onSubmit="return false;"
style="margin: auto; margin-top: 2em; width: 80%"
>
<input
type="search"
name="nombres"
id="nombres"
placeholder="Nombres separados con comas"
aria-label="Search"
/>
<input type="submit" value="Buscar" onCLick="drawChart();" />
</form>
</main>
</body>
</html>

View File

@ -1,3 +0,0 @@
pygal
requests
pyrqlite

14
historico/shard.yml Normal file
View File

@ -0,0 +1,14 @@
name: historico
version: 0.1.0
targets:
funko:
main: main.cr
dependencies:
kemal:
github: kemalcr/kemal
pg:
github: will/crystal-pg
pool:
github: ysbaddaden/pool