Restyle
This commit is contained in:
parent
374d90b8e3
commit
ee5df0c4c7
|
@ -41,33 +41,11 @@
|
|||
</p>
|
||||
<h3>Analisi dei dati della campagna vaccinale</h3>
|
||||
<p class="mb-2">
|
||||
La campagna vaccinale in Italia è iniziata da poco e chiaramente non è ancora a regime. La stima qui effettuata
|
||||
sarà via via più affidabile con l'aumentare dei dati e indica il tempo che mancherebbe al raggiungimento
|
||||
La stima qui effettuata indica il tempo che mancherebbe al raggiungimento
|
||||
dell'immunità di gregge qualora si tenesse il ritmo degli ultimi 7 giorni. <br />
|
||||
</p>
|
||||
<hr>
|
||||
<div class="text-center">
|
||||
In Italia sono state somministrate <br />
|
||||
<span class="text-big">
|
||||
<!-- totalDoses -->
|
||||
dosi di vaccino</span> <br />
|
||||
che corrispondono a <br />
|
||||
<span class="text-big">
|
||||
<!-- totalVaccinations -->
|
||||
persone vaccinate,</span> <br />
|
||||
ovvero <br />
|
||||
<span class="text-big">
|
||||
<!-- totalVaccinationsPerc -->
|
||||
della popolazione.
|
||||
</span> <br />
|
||||
Ne abbiamo vaccinate <br />
|
||||
<span class="text-big">
|
||||
<!-- totalVaccinationsLastWeek -->
|
||||
nell'ultima settimana,</span> <br />
|
||||
con un ritmo di <br />
|
||||
<span class="text-big">
|
||||
<!-- vaccinesPerDay -->
|
||||
vaccinati al giorno.</span> <br />
|
||||
Continuando di questo passo, raggiungeremo l'immunità di gregge il <br />
|
||||
<span class="text-bigger">
|
||||
<!-- hitDate -->
|
||||
|
@ -81,13 +59,13 @@
|
|||
giorni.
|
||||
</span>
|
||||
</div>
|
||||
<img alt="Grafico vaccinati ultima settimana" src="plot.png" class="img-fluid">
|
||||
<hr>
|
||||
<p class="pt-2 notes">
|
||||
I dati non comprendono quelli del giorno attuale perché solitamente incompleti.
|
||||
</p>
|
||||
<p class="pt-2 notes">
|
||||
Dal 2 febbraio 2021 il grafico mostra i dati delle persone vaccinate,
|
||||
ovvero di chi ha ricevuto entrambe le dosi.
|
||||
Dal 21 maggio 2021 vengono mostrati due differenti grafici per differenziare
|
||||
le prime e le seconde dosi.
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
|
@ -0,0 +1,87 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Source: https://github.com/MarcoBuster/quanto-manca/blob/master/template.html -->
|
||||
<html lang="it">
|
||||
<head>
|
||||
<title>@itavscovidbot</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
|
||||
<style>
|
||||
.text-big {
|
||||
font-size: 130%;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
top: -5px;
|
||||
margin-bottom: -4px;
|
||||
}
|
||||
.text-bigger {
|
||||
font-size: 200%;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
top: -6px;
|
||||
margin-bottom: -4px;
|
||||
}
|
||||
p.notes{
|
||||
padding-top: 0px !important;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.box {
|
||||
text-align: center;
|
||||
padding: 10px 0px;
|
||||
margin: 5px -7px;
|
||||
border: 1px solid black;
|
||||
border-radius: 5px;
|
||||
}
|
||||
#content {
|
||||
padding: 35px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-2 pt-2 px-xl-5" id="content">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="box">
|
||||
<h1>
|
||||
<!-- totalVaccinations -->
|
||||
</h1>
|
||||
Somministrazioni
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="box">
|
||||
<h1>
|
||||
<!-- totalVaccinationsPerc -->
|
||||
</h1>
|
||||
/ 100%
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="box">
|
||||
<h1>
|
||||
<!-- totalVaccinationsLastWeek -->
|
||||
</h1>
|
||||
Questa settimana
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="box">
|
||||
<h1>
|
||||
<!-- vaccinesPerDay -->
|
||||
</h1>
|
||||
Media settimanale
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<img alt="Grafico vaccinati ultima settimana" src="plot.png" class="img-fluid">
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
189
bot.py
189
bot.py
|
@ -5,6 +5,7 @@ import secrets
|
|||
import schedule
|
||||
import time
|
||||
from dotenv import load_dotenv
|
||||
from telegram import InputMediaPhoto
|
||||
from telegram.ext import Updater
|
||||
from telegram.ext import CommandHandler
|
||||
from pymongo import MongoClient
|
||||
|
@ -61,6 +62,101 @@ db = client['bot']
|
|||
|
||||
|
||||
|
||||
def progress(first, second, total = ITALIAN_POPULATION):
|
||||
|
||||
progress_length = 20
|
||||
|
||||
# first : total = x : 100
|
||||
first_perc = (first * 100) / total
|
||||
# second : total = x : 100
|
||||
second_perc = (second * 100) / total
|
||||
|
||||
# first_perc : x = 100 : progress_length
|
||||
first_cycle = int(first_perc / (100 / progress_length))
|
||||
# second_perc : x = 100 : progress_length
|
||||
second_cycle = int(second_perc / (100 / progress_length))
|
||||
|
||||
# first progress
|
||||
first_progress = ''
|
||||
for i in range(0, first_cycle):
|
||||
first_progress = first_progress + '▓'
|
||||
for i in range(0, progress_length - first_cycle):
|
||||
first_progress = first_progress + '░'
|
||||
# second progress
|
||||
second_progress = ''
|
||||
for i in range(0, second_cycle):
|
||||
second_progress = second_progress + '▓'
|
||||
for i in range(0, progress_length - second_cycle):
|
||||
second_progress = second_progress + '░'
|
||||
|
||||
return first_progress, second_progress
|
||||
|
||||
|
||||
|
||||
def generate(df, target = 'totale', template = 'template.html'):
|
||||
|
||||
# Get data from df
|
||||
totalVaccines = sum(df[target])
|
||||
lastWeekData = df.loc[df.index > df.index[-1] - td(days=7)]
|
||||
vaccinesPerDayAverage = sum(lastWeekData[target]) / 7
|
||||
remainingDays = (HIT - totalVaccines) / vaccinesPerDayAverage
|
||||
hitDate = df.index[-1] + td(days=remainingDays)
|
||||
|
||||
# Generate plot
|
||||
plt.ylabel('Vaccinati' if target == 'seconda_dose' else 'Somministrazioni')
|
||||
plt.xlabel("Ultima settimana")
|
||||
plt.grid(True)
|
||||
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
|
||||
plt.gca().xaxis.set_major_locator(mdates.AutoDateLocator())
|
||||
plt.gcf().autofmt_xdate()
|
||||
plt.bar(lastWeekData.index, height=lastWeekData[target])
|
||||
# Trendline
|
||||
z = np.polyfit(range(0, 7), lastWeekData[target], 2)
|
||||
p = np.poly1d(z)
|
||||
plt.plot(lastWeekData.index, p(range(0, 7)), "r--")
|
||||
# Secret 4 filenames
|
||||
sf = secrets.token_hex(16)
|
||||
# Generate plot filename
|
||||
plot_filename = 'plot_' + sf + '.png'
|
||||
# Create plot image/png
|
||||
plt.savefig('out/' + plot_filename, dpi=300, bbox_inches='tight')
|
||||
# Flush the plot
|
||||
plt.clf()
|
||||
# Generate tmp webpage/html filename
|
||||
webpage_filename = 'tmp_' + sf + '.html'
|
||||
# Generate template
|
||||
with open(template, 'r+') as f:
|
||||
with open('out/' + webpage_filename, 'w+') as wf:
|
||||
for line in f.read().splitlines():
|
||||
if "<!-- totalVaccinations -->" in line:
|
||||
line = f"{totalVaccines}"
|
||||
elif "<!-- totalVaccinationsPerc -->" in line:
|
||||
line = f"{str(round(totalVaccines / ITALIAN_POPULATION * 100, 2)).replace('.', ',')}%"
|
||||
elif "<!-- totalVaccinationsLastWeek -->" in line:
|
||||
line = f"{int(vaccinesPerDayAverage*7)}"
|
||||
elif "<!-- vaccinesPerDay -->" in line:
|
||||
line = f"{int(vaccinesPerDayAverage)}"
|
||||
elif "<!-- hitDate -->" in line:
|
||||
line = f"{hitDate.strftime('%d/%m/%Y')}"
|
||||
elif "<!-- hitHour -->" in line:
|
||||
line = f"{hitDate.strftime('%H:%M:%S')}"
|
||||
elif "<!-- daysRemaining -->" in line:
|
||||
line = f"{int(remainingDays)}"
|
||||
elif "plot.png" in line:
|
||||
line = line.replace('plot.png', plot_filename)
|
||||
wf.write("\n" + line)
|
||||
# Generate plot filename
|
||||
results_filename = 'results_' + sf + '.png'
|
||||
# Create results image/png
|
||||
imgkit.from_file('out/' + webpage_filename, 'out/' + results_filename)
|
||||
|
||||
# Return out data
|
||||
return {
|
||||
'plot': 'out/' + plot_filename,
|
||||
'results': 'out/' + results_filename,
|
||||
'webpage': 'out/' + webpage_filename
|
||||
}
|
||||
|
||||
|
||||
# Function to get data
|
||||
def download():
|
||||
|
@ -97,69 +193,16 @@ def download():
|
|||
if dt.now() - df_vaccines.index[-1] < td(days=1):
|
||||
df_vaccines = df_vaccines[:-1] # Ignore the current day because it's often incomplete
|
||||
|
||||
totalDoses = sum(df_doses["totale"])
|
||||
totalVaccines = sum(df_vaccines["seconda_dose"])
|
||||
lastWeekData = df_vaccines.loc[df_vaccines.index > df_vaccines.index[-1] - td(days=7)]
|
||||
vaccinesPerDayAverage = sum(lastWeekData["seconda_dose"]) / 7
|
||||
remainingDays = (HIT - totalVaccines) / vaccinesPerDayAverage
|
||||
hitDate = df_vaccines.index[-1] + td(days=remainingDays)
|
||||
# Generata images
|
||||
intro = generate(df_vaccines, 'seconda_dose', 'assets/templates/intro.html')
|
||||
plot1 = generate(df_doses, 'totale', 'assets/templates/plot.html')
|
||||
plot2 = generate(df_vaccines, 'seconda_dose', 'assets/templates/plot.html')
|
||||
|
||||
# Generate plot
|
||||
plt.ylabel("Vaccinati al giorno")
|
||||
plt.xlabel("Ultima settimana")
|
||||
plt.grid(True)
|
||||
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
|
||||
plt.gca().xaxis.set_major_locator(mdates.AutoDateLocator())
|
||||
plt.gcf().autofmt_xdate()
|
||||
plt.bar(lastWeekData.index, height=lastWeekData["seconda_dose"])
|
||||
# Trendline
|
||||
z = np.polyfit(range(0, 7), lastWeekData["seconda_dose"], 2)
|
||||
p = np.poly1d(z)
|
||||
plt.plot(lastWeekData.index, p(range(0, 7)), "r--")
|
||||
# Secret 4 filenames
|
||||
sf = secrets.token_hex(16)
|
||||
# Generate plot filename
|
||||
plot_filename = 'plot_' + sf + '.png'
|
||||
# Create plot image/png
|
||||
plt.savefig('out/' + plot_filename, dpi=300, bbox_inches='tight')
|
||||
# Flush the plot
|
||||
plt.clf()
|
||||
# Generate tmp webpage/html filename
|
||||
webpage_filename = 'tmp_' + sf + '.html'
|
||||
# Generate template
|
||||
with open('template.html', 'r+') as f:
|
||||
with open('out/' + webpage_filename, 'w+') as wf:
|
||||
for line in f.read().splitlines():
|
||||
if "<!-- totalDoses -->" in line:
|
||||
line = f"{totalDoses}"
|
||||
elif "<!-- totalVaccinations -->" in line:
|
||||
line = f"{totalVaccines}"
|
||||
elif "<!-- totalVaccinationsPerc -->" in line:
|
||||
line = f"{str(round(totalVaccines / ITALIAN_POPULATION * 100, 2)).replace('.', ',')}%"
|
||||
elif "<!-- totalVaccinationsLastWeek -->" in line:
|
||||
line = f"{int(vaccinesPerDayAverage*7)}"
|
||||
elif "<!-- vaccinesPerDay -->" in line:
|
||||
line = f"{int(vaccinesPerDayAverage)}"
|
||||
elif "<!-- hitDate -->" in line:
|
||||
line = f"{hitDate.strftime('%d/%m/%Y')}"
|
||||
elif "<!-- hitHour -->" in line:
|
||||
line = f"{hitDate.strftime('%H:%M:%S')}"
|
||||
elif "<!-- daysRemaining -->" in line:
|
||||
line = f"{int(remainingDays)}"
|
||||
elif "plot.png" in line:
|
||||
line = line.replace('plot.png', plot_filename)
|
||||
wf.write("\n" + line)
|
||||
# Generate plot filename
|
||||
results_filename = 'results_' + sf + '.png'
|
||||
# Create results image/png
|
||||
imgkit.from_file('out/' + webpage_filename, 'out/' + results_filename)
|
||||
# Generate progression
|
||||
progression = [sum(df_doses['totale']), sum(df_vaccines['seconda_dose'])]
|
||||
|
||||
return intro, plot1, plot2, progression
|
||||
|
||||
# Return out data
|
||||
return {
|
||||
'plot': 'out/' + plot_filename,
|
||||
'results': 'out/' + results_filename,
|
||||
'webpage': 'out/' + webpage_filename
|
||||
}
|
||||
|
||||
|
||||
# Help command
|
||||
|
@ -291,15 +334,27 @@ def news(update, context):
|
|||
def get(update, context):
|
||||
|
||||
# Download data
|
||||
data = download()
|
||||
intro, plot1, plot2, progression = download()
|
||||
|
||||
# Send photo
|
||||
context.bot.send_photo(chat_id=update.effective_chat.id, photo=open(data['results'], 'rb'), caption="")
|
||||
# Send photos
|
||||
p1 = open(intro['results'], 'rb')
|
||||
p2 = open(plot1['results'], 'rb')
|
||||
p3 = open(plot2['results'], 'rb')
|
||||
|
||||
first, second = progress(progression[0], progression[1])
|
||||
caption = 'Prima Dose\n' + first + '\nSeconda Dose\n' + second
|
||||
|
||||
p1 = InputMediaPhoto(media=p1, caption=caption)
|
||||
p2 = InputMediaPhoto(media=p2)
|
||||
p3 = InputMediaPhoto(media=p3)
|
||||
|
||||
context.bot.send_media_group(chat_id=update.effective_chat.id, media=[p1, p2, p3])
|
||||
|
||||
# Remove tmp files
|
||||
os.remove(data['plot'])
|
||||
os.remove(data['webpage'])
|
||||
os.remove(data['results'])
|
||||
for data in [intro, plot1, plot2]:
|
||||
os.remove(data['plot'])
|
||||
os.remove(data['webpage'])
|
||||
os.remove(data['results'])
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue