diff --git a/README.md b/README.md index 16d03cd..7f61a57 100644 --- a/README.md +++ b/README.md @@ -23,4 +23,4 @@ Il bot è stato sviluppato da [@derogab](https://github.com/derogab) e il codice I dati mostrati sono scaricati dagli [Open Data ufficiali](https://github.com/italia/covid19-opendata-vaccini) sui vaccini in Italia. -I grafici sono automaticamente generati mediante il codice della [repository pubblica](https://github.com/MarcoBuster/quanto-manca) di [@MarcoBuster](https://github.com/MarcoBuster). +Fino alla [v1.0.0](https://github.com/derogab/ITAvsCOVIDbot/releases/tag/v1.0.0) i grafici sono automaticamente generati mediante il codice della [repository pubblica](https://github.com/MarcoBuster/quanto-manca) di [@MarcoBuster](https://github.com/MarcoBuster). Dalla [v2.0.0](https://github.com/derogab/ITAvsCOVIDbot/releases/tag/v2.0.0) sono invece utilizzati dei grafici differenti costruiti sulla base dei precedenti. diff --git a/assets/images/logo.png b/assets/images/logo.png index b758fd9..5f8370e 100644 Binary files a/assets/images/logo.png and b/assets/images/logo.png differ diff --git a/template.html b/assets/templates/intro.html similarity index 66% rename from template.html rename to assets/templates/intro.html index 813d78f..d8d3e0d 100644 --- a/template.html +++ b/assets/templates/intro.html @@ -41,33 +41,11 @@

Analisi dei dati della campagna vaccinale

- 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.


- In Italia sono state somministrate
- - - dosi di vaccino
- che corrispondono a
- - - persone vaccinate,
- ovvero
- - - della popolazione. -
- Ne abbiamo vaccinate
- - - nell'ultima settimana,
- con un ritmo di
- - - vaccinati al giorno.
Continuando di questo passo, raggiungeremo l'immunità di gregge il
@@ -81,13 +59,13 @@ giorni.
- Grafico vaccinati ultima settimana +

I dati non comprendono quelli del giorno attuale perché solitamente incompleti.

- Dal 2 febbraio 2021 il grafico mostra i dati delle persone vaccinate, - ovvero di chi ha ricevuto entrambe le dosi. + Dal 21 maggio 2021 sono mostrati due differenti grafici per differenziare + le prime e le seconde dosi.

diff --git a/assets/templates/plot.html b/assets/templates/plot.html new file mode 100644 index 0000000..7b321a5 --- /dev/null +++ b/assets/templates/plot.html @@ -0,0 +1,88 @@ + + + + + @itavscovidbot + + + + + + +
+ +
+
+
+

+ +

+ Somministrazioni + +
+
+
+
+

+ +

+ / 100% +
+
+
+
+
+
+

+ +

+ Questa settimana +
+
+
+
+

+ +

+ Media settimanale +
+
+
+ +
+ + Grafico vaccinati ultima settimana + +
+ + \ No newline at end of file diff --git a/bot.py b/bot.py index 1bfb18a..c2e107c 100644 --- a/bot.py +++ b/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 @@ -52,7 +53,7 @@ mongodb_pass = os.environ.get('MONGODB_PASS') if mongodb_user is None or mongodb_pass is None: print('No mongodb auth.') exit() -mongodb_uri = 'mongodb://' + mongodb_user + ':' + mongodb_pass + '@db:27017', +mongodb_uri = 'mongodb://' + mongodb_user + ':' + mongodb_pass + '@db:27017' # Init mongodb database client = MongoClient(mongodb_uri) @@ -61,59 +62,57 @@ db = client['bot'] +def progress(first, second, total = ITALIAN_POPULATION): -# Function to get data -def download(): - - # Download from open data - r = requests.get(DATA_URL) - # Create dataframe from data - df = pd.read_csv( - io.StringIO(r.text), - index_col="data_somministrazione", - ) - # Set date as index - df.index = pd.to_datetime( - df.index, - format="%Y-%m-%d", - ) - # Sort value based on date - df.sort_values('data_somministrazione') - # Delete sum data if already exists - df = df[df["area"] != "ITA"] - # Set target counters to numeric - df["totale"] = pd.to_numeric(df["totale"]) - df["seconda_dose"] = pd.to_numeric(df["seconda_dose"]) - # Group by day and sum counters - df_doses = df.groupby(['data_somministrazione'])['totale'].sum().reset_index() - df_vaccines = df.groupby(['data_somministrazione'])['seconda_dose'].sum().reset_index() - # Re-set date as ID in new dataframe - df_doses = df_doses.set_index('data_somministrazione') - df_vaccines = df_vaccines.set_index('data_somministrazione') + progress_length = 20 - # If there are current day data... - if dt.now() - df_doses.index[-1] < td(days=1): - df_doses = df_doses[:-1] # Ignore the current day because it's often incomplete - if dt.now() - df_vaccines.index[-1] < td(days=1): - df_vaccines = df_vaccines[:-1] # Ignore the current day because it's often incomplete + # first : total = x : 100 + first_perc = (first * 100) / total + # second : total = x : 100 + second_perc = (second * 100) / total - 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 + # 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, template): + + # 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_vaccines.index[-1] + td(days=remainingDays) + hitDate = df.index[-1] + td(days=remainingDays) + first_or_second = 'Seconda Dose' if target == 'seconda_dose' else 'Prima Dose' if target == 'prima_dose' else 'Totale' # Generate plot - plt.ylabel("Vaccinati al giorno") + plt.ylabel(first_or_second) 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"]) + plt.bar(lastWeekData.index, height=lastWeekData[target]) # Trendline - z = np.polyfit(range(0, 7), lastWeekData["seconda_dose"], 2) + 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 @@ -127,13 +126,13 @@ def download(): # Generate tmp webpage/html filename webpage_filename = 'tmp_' + sf + '.html' # Generate template - with open('template.html', 'r+') as f: + with open(template, 'r+') as f: with open('out/' + webpage_filename, 'w+') as wf: for line in f.read().splitlines(): - if "" in line: - line = f"{totalDoses}" - elif "" in line: + if "" in line: line = f"{totalVaccines}" + elif "" in line: + line = f"{first_or_second}" elif "" in line: line = f"{str(round(totalVaccines / ITALIAN_POPULATION * 100, 2)).replace('.', ',')}%" elif "" in line: @@ -162,6 +161,53 @@ def download(): } +# Function to get data +def download(): + + # Download from open data + r = requests.get(DATA_URL) + # Create dataframe from data + df = pd.read_csv( + io.StringIO(r.text), + index_col="data_somministrazione", + ) + # Set date as index + df.index = pd.to_datetime( + df.index, + format="%Y-%m-%d", + ) + # Sort value based on date + df.sort_values('data_somministrazione') + # Delete sum data if already exists + df = df[df["area"] != "ITA"] + # Set target counters to numeric + df["prima_dose"] = pd.to_numeric(df["prima_dose"]) + df["seconda_dose"] = pd.to_numeric(df["seconda_dose"]) + # Group by day and sum counters + df_first = df.groupby(['data_somministrazione'])['prima_dose'].sum().reset_index() + df_second = df.groupby(['data_somministrazione'])['seconda_dose'].sum().reset_index() + # Re-set date as ID in new dataframe + df_first = df_first.set_index('data_somministrazione') + df_second = df_second.set_index('data_somministrazione') + + # If there are current day data... + if dt.now() - df_first.index[-1] < td(days=1): + df_first = df_first[:-1] # Ignore the current day because it's often incomplete + if dt.now() - df_second.index[-1] < td(days=1): + df_second = df_second[:-1] # Ignore the current day because it's often incomplete + + # Generata images + intro = generate(df_second, 'seconda_dose', 'assets/templates/intro.html') + plot1 = generate(df_first, 'prima_dose', 'assets/templates/plot.html') + plot2 = generate(df_second, 'seconda_dose', 'assets/templates/plot.html') + + # Generate progression + progression = [sum(df_first['prima_dose']), sum(df_second['seconda_dose'])] + + return intro, plot1, plot2, progression + + + # Help command def help(update, context): @@ -291,15 +337,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']) diff --git a/docker-compose.yml b/docker-compose.yml index 09acf9e..801e25d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,14 +1,15 @@ -version: "3.5" +version: '3.7' networks: itavscovidbot.network: name: itavscovidbot.network + driver: bridge services: db: - image: mongo + image: mongo:latest container_name: itavscovidbot.db restart: unless-stopped env_file: @@ -21,11 +22,9 @@ services: db.web: depends_on: - db - image: mongo-express + image: mongo-express:latest container_name: itavscovidbot.db.web restart: unless-stopped - links: - - db env_file: - ./db/web/.env ports: @@ -36,13 +35,10 @@ services: app: depends_on: - db - - db.web build: context: . container_name: itavscovidbot.app restart: unless-stopped - links: - - db env_file: - ./.env networks: