def executereminders(bot, _): now = datetime.datetime.now() users_to_notify = db.get_values("meditationreminders", value=now.hour) for user in users_to_notify: user_id = user[0] user_midnight_utc = user[ 2] # Will be an int like 2, meaning midnight is at 2AM UTC for the user # We don't want to notify if the user already meditated today # Because of timezones, 'today' probably means something different for user # So we check between their midnight and now if user_midnight_utc > now.hour: start_check_period = get_x_days_before(now, 1).replace( hour=user_midnight_utc, minute=0, second=0) else: start_check_period = now.replace(hour=user_midnight_utc, minute=0, second=0) meditations = db.get_values("meditation", start_date=start_check_period, end_date=now, user_id=user_id) meditations_len = len(meditations) if meditations_len == 0: bot.send_message(chat_id=user_id, text="Hey! You asked me to send you a private message to remind you to meditate! 🙏 "\ "You can turn off these notifications with `/reminders off`. 🕑")
def get_standard_deviation(field): db.connect_db() values = db.get_values(field) stddev = statistics.pstdev(values) return stddev
def find_rating_change(table, user_id, new_value): now = datetime.datetime.now() yesterday = get_x_days_before(now, 1) # We want to find change in rating between current value and most recent value in 24 last hours ratings_last_day = db.get_values(table, start_date=yesterday, end_date=now, user_id=user_id) difference_str = "" if len(ratings_last_day) > 1: ratings_last_day.sort(key=lambda r: r[2], reverse=True) difference = new_value - ratings_last_day[1][1] difference_str = ' ({})'.format( "{:+}".format(difference) if difference else "no change") return difference_str
def generate_timelog_report_from(table, filename, user, start_date, end_date, all_data=False): user_id = None if all_data else user.id username = "******" if all_data else get_name(user) results = db.get_values(table, start_date=start_date, end_date=end_date, user_id=user_id) dates_to_value_mapping = defaultdict(int) for result in results: dates_to_value_mapping[result[2].date()] += result[1] dates = dates_to_value_mapping.keys() values = dates_to_value_mapping.values() total = sum(values) if table == "meditation": units = "minutes" elif table == "sleep": units = "hours" _, axis = plt.subplots() x_limits = get_chart_x_limits(start_date, end_date, dates) axis.set_xlim(x_limits) axis.xaxis_date() plt.bar(dates, values, align='center', alpha=0.5) plt.ylabel(table.title()) interval = (x_limits[1] - x_limits[0]).days # Try to keep the ticks on the x axis readable by limiting to max of 10 if interval > 10: axis.xaxis.set_major_locator( mdates.DayLocator(interval=math.ceil(interval / 10))) axis.xaxis.set_minor_locator(mdates.DayLocator()) else: axis.xaxis.set_major_locator(mdates.DayLocator()) axis.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m')) plt.title('{}\'s {} chart\n{} days report. Total: {:.1f} {}'.format( username, table, interval, total, units)) plt.savefig(filename) plt.close()
def journallookup(bot, update): user_id = update.message.from_user.id username = get_name(update.message.from_user) parts = update.message.text.split(' ') datestring = " ".join(parts) # Parse the string - prefer DMY to MDY - most of world uses DMY dateinfo = dateparser.parse(datestring, settings={ 'DATE_ORDER': 'DMY', 'STRICT_PARSING': True }) if dateinfo is not None: dateinfo = dateinfo.date() start_of_day = datetime.datetime(dateinfo.year, dateinfo.month, dateinfo.day) end_of_day = start_of_day + datetime.timedelta(days=1) entries = db.get_values("journal", start_date=start_of_day, end_date=end_of_day, user_id=user_id) entries_len = len(entries) try: bot.deleteMessage(chat_id=update.message.chat.id, message_id=update.message.message_id) except BadRequest: pass if entries_len == 0: bot.send_message( chat_id=update.message.chat.id, text="📓 {} had no journal entries on {}. 📓".format( username, dateinfo.isoformat())) for entry in entries: # Separate entry for each message, or we'll hit the telegram length limit for many (or just a few long ones) in one day bot.send_message(chat_id=update.message.chat.id, text="📓 Journal entry by {}, dated {}: {}".format( username, entry[2].strftime("%a. %d %B %Y %I:%M%p %Z"), entry[1])) else: bot.send_message( chat_id=update.message.from_user.id, text="Sorry, I couldn't understand that date format. 🤔")
def generate_linechart_report_from(table, filename, user, start_date, end_date): user_id = user.id username = get_name(user) results = db.get_values(table, start_date=start_date, end_date=end_date, user_id=user_id) results = sorted(results, key=lambda x: x[2]) ratings = [x[1] for x in results] dates = [x[2] for x in results] average = float(sum(ratings)) / max(len(ratings), 1) _, axis = plt.subplots() x_limits = get_chart_x_limits(start_date, end_date, [x.date() for x in dates]) axis.set_xlim(x_limits) axis.set_ylim([0, 10]) interval = (x_limits[1] - x_limits[0]).days # Try to keep the ticks on the x axis readable by limiting to max of 10 if interval > 10: axis.xaxis.set_major_locator( mdates.DayLocator(interval=math.ceil(interval / 10))) axis.xaxis.set_minor_locator(mdates.DayLocator()) else: axis.xaxis.set_major_locator(mdates.DayLocator()) axis.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m')) plt.title('{}\'s {} chart\n{} days report. Average: {:.2f}'.format( username, table, interval, average)) plt.ylabel(table.title()) plt.plot(dates, ratings) plt.savefig(filename) plt.close()
def make_histogram(field, xlabel, min_value, max_value, step_size, step_size_tick): db.connect_db() values = db.get_values(field) data = [ go.Histogram(x=values, marker=dict(color='#a8a8a8', line=dict(width=2, color='#000000')), xbins=dict(start=min_value, end=max_value, size=step_size)) ] layout = go.Layout(xaxis=dict(title=xlabel, tick0=0, dtick=step_size_tick, tickfont=dict(size=20), titlefont=dict(size=20)), yaxis=dict(title='Projekt', tickfont=dict(size=20), titlefont=dict(size=20))) fig = go.Figure(data=data, layout=layout) plotly.offline.plot(fig, filename=('histogram ' + field))