def calc_block_time(time_t): try: interval = SCHEDULE_INTERVALS[time_t] except KeyError: debug("BLOCK", "Error undefined schedule interval", log=True) return "00:00" hh_start = int(interval[0][:2]) hh_end = int(interval[1][:2]) mm_begin = int(interval[0][3:]) mm_end = int(interval[1][3:]) if hh_start < hh_end: value_hh = random.randint(hh_start, hh_end) if value_hh == hh_start: value_mm = random.randint(mm_begin + 10, 59) elif value_hh == hh_end: value_mm = random.randint(0, mm_end) else: value_mm = random.randint(0, 59) elif hh_start == hh_end: value_hh = hh_start value_mm = random.randint(mm_begin + 10, mm_end - 10) else: value_hh = random.choice[random.randint(hh_start, 23), random.randint(0, hh_end)] if value_hh == hh_start: value_mm = random.randint(mm_begin + 10, 59) elif value_hh == hh_end: value_mm = random.randint(0, mm_end) else: value_mm = random.randint(0, 59) return str(value_hh).zfill(2) + ':' + str(value_mm).zfill(2)
def continue_survey(user, bot, job_queue): user.active_ = True q_set = user.q_set_ q_day = q_set[user.pointer_] q_block = q_day["blocks"][user.block_] question = q_block["questions"][user.question_] if question is not None: message = parse_question(user, question) q_keyboard = get_keyboard(question["choice"], user) try: bot.send_message(chat_id=user.chat_id_, text=message, reply_markup=q_keyboard) debug(flag="MSG", text=str(user.chat_id_) + ": " + message + "\n") except TelegramError as error: if error.message == 'Unauthorized': user.pause() user.set_q_idle(True) if user.job_ is None and ["MANDATORY"] not in q_block["settings"]: user.block_complete_ = True next_day = user.set_next_block() if next_day is None: finished(user, job_queue) return element = user.next_block[2] day_offset = next_day - user.day_ time_t = calc_block_time(element["time"]) due = calc_delta_t(time_t, day_offset, user.timezone_) debug('QUEUE', 'next block in ' + str(due) + ' seconds. User: ' + str(user.chat_id_), log=True) new_job = Job(queue_next, due, repeat=False, context=[user, job_queue]) user.job_ = new_job job_queue.put(new_job) return
def initialize_participants(job_queue: JobQueue): user_map = DataSet() try: # Todo: auto-initalize function db = sqlite3.connect('survey/participants.db') cursor = db.cursor() cursor.execute("SELECT * FROM participants ORDER BY (ID)") participants = cursor.fetchall() # print(participants) for row in participants: user = Participant(row[1], init=False) user.conditions_ = pickle.loads(row[2]) user.data_set_ = pickle.loads(row[0]) user.timezone_ = row[3] user.country_ = row[4] user.gender_ = row[5] user.language_ = row[6] user.question_ = row[7] user.age_ = row[8] user.day_ = row[9] user.q_idle_ = row[10] user.active_ = row[11] user.block_ = row[12] user.pointer_ = row[13] user_map.participants[row[1]] = user if user.language_ != '': q_set = user_map.return_question_set_by_language( user.language_) user.q_set_ = q_set if user.country_ != '' and user.timezone_ != '' and user.gender_ != '': user.set_next_block() next_day = user.set_next_block() if next_day is None and user.active_ and user.pointer_ > -1: finished(user, job_queue) continue element = user.next_block[2] day_offset = next_day - user.day_ time_t = calc_block_time(element["time"]) due = calc_delta_t(time_t, day_offset, user.timezone_) debug('QUEUE', 'next block in ' + str(due) + ' seconds. User: ' + str(user.chat_id_), log=True) new_job = Job(queue_next, due, repeat=False, context=[user, job_queue]) job_queue.put(new_job) except sqlite3.Error as error: print(error) return user_map
def initialize_participants(job_queue: JobQueue): user_map = DataSet() try: # Todo: auto-initalize function db = sqlite3.connect('survey/participants.db') cursor = db.cursor() cursor.execute("SELECT * FROM participants ORDER BY (ID)") participants = cursor.fetchall() # print(participants) for row in participants: user = Participant(row[1], init=False) user.conditions_ = pickle.loads(row[2]) user.data_set_ = pickle.loads(row[0]) user.timezone_ = row[3] user.country_ = row[4] user.gender_ = row[5] user.language_ = row[6] user.question_ = row[7] user.age_ = row[8] user.day_ = row[9] user.q_idle_ = row[10] user.active_ = row[11] user.block_ = row[12] user.pointer_ = row[13] user_map.participants[row[1]] = user if user.language_ != '': q_set = user_map.return_question_set_by_language(user.language_) user.q_set_ = q_set if user.country_ != '' and user.timezone_ != '' and user.gender_ != '': user.set_next_block() next_day = user.set_next_block() if next_day is None and user.active_ and user.pointer_ > -1: finished(user, job_queue) continue element = user.next_block[2] day_offset = next_day - user.day_ time_t = calc_block_time(element["time"]) due = calc_delta_t(time_t, day_offset, user.timezone_) debug('QUEUE', 'next block in ' + str(due) + ' seconds. User: ' + str(user.chat_id_), log=True) new_job = Job(queue_next, due, repeat=False, context=[user, job_queue]) job_queue.put(new_job) except sqlite3.Error as error: print(error) return user_map
def continue_survey(user, bot, job_queue): user.active_ = True q_set = user.q_set_ q_day = q_set[user.pointer_] q_block = q_day["blocks"][user.block_] question = q_block["questions"][user.question_] if question is not None: message = parse_question(user, question) q_keyboard = get_keyboard(question["choice"], user) try: bot.send_message(chat_id=user.chat_id_, text=message, reply_markup=q_keyboard) debug(flag="MSG", text=str(user.chat_id_) + ": " + message + "\n") except TelegramError as error: if error.message == 'Unauthorized': user.pause() user.set_q_idle(True) if user.job_ is None and ["MANDATORY"] not in q_block["settings"]: user.block_complete_ = True next_day = user.set_next_block() if next_day is None: finished(user, job_queue) return element = user.next_block[2] day_offset = next_day - user.day_ time_t = calc_block_time(element["time"]) due = calc_delta_t(time_t, day_offset, user.timezone_) debug('QUEUE', 'next block in ' + str(due) + ' seconds. User: ' + str(user.chat_id_), log=True) new_job = Job(queue_next, due, repeat=False, context=[user, job_queue]) user.job_ = new_job job_queue._put(new_job) return
def question_handler(bot: Bot, update: Update, user_map: DataSet, job_queue: JobQueue): try: # Get the user from the dict and its question_set (by language) user = user_map.participants[update.message.chat_id] # type: Participant # Case for very first question. if user.question_ == -1: user.set_active(True) user.set_language(update.message.text) user.set_block(0) q_set = user_map.return_question_set_by_language(user.language_) user.q_set_ = q_set current_day = q_set[0]["day"] user.set_day(current_day) user.set_block(0) elif user.q_idle_: q_set = user.q_set_ # Get the matching question for the users answer. pointer = user.pointer_ d_prev = q_set[pointer] b_prev = d_prev["blocks"][user.block_] q_prev = b_prev["questions"][user.question_] if not valid_answer(q_prev, update.message.text, user): user.set_q_idle(True) return # Storing the answer and moving on the next question store_answer(user, update.message.text, q_prev, job_queue) user.set_q_idle(False) else: # User has send something without being asked a question. return except KeyError as error: print(error) return if not user.active_: return message, question = find_next_question(user) if question is not None: message = question["text"] q_keyboard = get_keyboard(question["choice"], user) try: bot.send_message(chat_id=user.chat_id_, text=message, reply_markup=q_keyboard) debug(flag="MSG", text=str(user.chat_id_) + ": " + message + "\n") except TelegramError as error: if error.message == 'Unauthorized': user.pause() user.set_q_idle(True) elif user.auto_queue_ is False: user.block_complete_ = True next_day = user.set_next_block() if next_day is None: finished(user, job_queue) return element = user.next_block[2] day_offset = next_day - user.day_ time_t = calc_block_time(element["time"]) due = calc_delta_t(time_t, day_offset, user.timezone_) debug('QUEUE', 'next block in ' + str(due) + ' seconds. User: ' + str(user.chat_id_), log=True) new_job = Job(queue_next, due, repeat=False, context=[user, job_queue]) user.job_ = new_job job_queue.put(new_job)
def queue_next(bot: Bot, job: Job): user = job.context[0] # type: Participant job_queue = job.context[1] if not user.active_: return user.block_complete_ = False user.job_ = None # Stores all unanswered questions to csv prev = user.q_set_[user.pointer_]["blocks"][user.block_]["questions"] for i in range(user.question_, len(prev)): user.increase_question() q_prev = prev[i] store_answer(user, '', q_prev, job_queue) user.set_question(0) user.set_pointer(user.next_block[0]) user.set_block(user.next_block[1]) element = user.next_block[2] user.set_day(user.q_set_[user.pointer_]['day']) if ['MANDATORY'] in element['settings']: user.auto_queue_ = False else: user.auto_queue_ = True # Check if the user is currently active if not user.active_: return try: # Find next question that the user should get. while not user.check_requirements(element["questions"][user.question_]): store_answer(user, '', element["questions"][user.question_], None) user.increase_question() except IndexError: # User did not fulfill any questions for the day so we reschedule. # Set the new day. next_day = user.set_next_block() if user.next_block is None: return finished(user, job_queue) element = user.next_block[2] day_offset = next_day - user.day_ time_t = calc_block_time(element["time"]) due = calc_delta_t(time_t, day_offset, user.timezone_) # Add new job and to queue. The function basically calls itself recursively after x seconds. debug('QUEUE', 'next block in ' + str(due) + ' seconds. User: '******'Unauthorized': user.pause() user.set_q_idle(True) # Check if there is a reason to queue again. if not user.auto_queue_: return # Calculate seconds until question is due. next_day = user.set_next_block() if user.next_block is None: return finished(user, job_queue) element = user.next_block[2] day_offset = next_day - user.day_ time_t = calc_block_time(element["time"]) due = calc_delta_t(time_t, day_offset, user.timezone_) debug('QUEUE', 'next block in ' + str(due) + ' seconds. User: ' + str(user.chat_id_), log=True) new_job = Job(queue_next, due, repeat=False, context=[user, job_queue]) job_queue.put(new_job) return
def store_answer(user, message, question, job_queue): commands = question['commands'] if message != '': for element in commands: # -- DB TRIGGER for storing important user data -- # if element[0] == "TIMEZONE": user.set_timezone(message) elif element[0] == "COUNTRY": user.set_country(message) elif element[0] == "GENDER": user.set_gender(message) elif element[0] == "AGE": user.set_age(message) elif element[0] == "Q_ON": user.auto_queue_ = True next_day = user.set_next_block() if next_day is None: finished(user, job_queue) continue element = user.next_block[2] day_offset = next_day - user.day_ time_t = calc_block_time(element["time"]) due = calc_delta_t(time_t, day_offset, user.timezone_) debug('QUEUE', 'next block in ' + str(due) + ' seconds. User: '******'': timestamp = '' elif user.timezone_ == '': timestamp = datetime.now().isoformat() else: try: timestamp = datetime.now(timezone(user.timezone_)).isoformat() except UnknownTimeZoneError: timestamp = 'Invalid Timezone' q_var = question['variable'] q_text = question['text'] q_text = q_text.replace('\n', ' ') q_text = q_text.replace(';', ',') message = message.replace('\n', ' ') message = message.replace(';', ',') with open('survey/data_incomplete/' + str(user.chat_id_) + '.csv', 'a+', newline='') as user_file: columns = [str(user.chat_id_), user.language_, user.gender_, user.age_, user.country_, user.timezone_, user.day_, user.block_, user.question_, timestamp, q_text, message, q_var] writer = csv.writer(user_file, delimiter=';') writer.writerow(columns) return
def queue_next(bot: Bot, job: Job): user = job.context[0] # type: Participant job_queue = job.context[1] if not user.active_: return user.block_complete_ = False user.job_ = None # Stores all unanswered questions to csv prev = user.q_set_[user.pointer_]["blocks"][user.block_]["questions"] for i in range(user.question_, len(prev)): user.increase_question() q_prev = prev[i] store_answer(user, '', q_prev, job_queue) user.set_question(0) user.set_pointer(user.next_block[0]) user.set_block(user.next_block[1]) element = user.next_block[2] user.set_day(user.q_set_[user.pointer_]['day']) if ['MANDATORY'] in element['settings']: user.auto_queue_ = False else: user.auto_queue_ = True # Check if the user is currently active if not user.active_: return try: # Find next question that the user should get. while not user.check_requirements( element["questions"][user.question_]): store_answer(user, '', element["questions"][user.question_], None) user.increase_question() except IndexError: # User did not fulfill any questions for the day so we reschedule. # Set the new day. next_day = user.set_next_block() if user.next_block is None: return finished(user, job_queue) element = user.next_block[2] day_offset = next_day - user.day_ time_t = calc_block_time(element["time"]) due = calc_delta_t(time_t, day_offset, user.timezone_) # Add new job and to queue. The function basically calls itself recursively after x seconds. debug('QUEUE', 'next block in ' + str(due) + ' seconds. User: '******'Unauthorized': user.pause() user.set_q_idle(True) # Check if there is a reason to queue again. if not user.auto_queue_: return # Calculate seconds until question is due. next_day = user.set_next_block() if user.next_block is None: return finished(user, job_queue) element = user.next_block[2] day_offset = next_day - user.day_ time_t = calc_block_time(element["time"]) due = calc_delta_t(time_t, day_offset, user.timezone_) debug('QUEUE', 'next block in ' + str(due) + ' seconds. User: ' + str(user.chat_id_), log=True) new_job = Job(queue_next, due, repeat=False, context=[user, job_queue]) job_queue._put(new_job) return
def store_answer(user, message, question, job_queue): commands = question['commands'] if message != '': for element in commands: # -- DB TRIGGER for storing important user data -- # if element[0] == "TIMEZONE": user.set_timezone(message) elif element[0] == "COUNTRY": user.set_country(message) elif element[0] == "GENDER": user.set_gender(message) elif element[0] == "AGE": user.set_age(message) elif element[0] == "Q_ON": user.auto_queue_ = True next_day = user.set_next_block() if next_day is None: finished(user, job_queue) continue element = user.next_block[2] day_offset = next_day - user.day_ time_t = calc_block_time(element["time"]) due = calc_delta_t(time_t, day_offset, user.timezone_) debug('QUEUE', 'next block in ' + str(due) + ' seconds. User: '******'': timestamp = '' elif user.timezone_ == '': timestamp = datetime.now().isoformat() else: try: timestamp = datetime.now(timezone(user.timezone_)).isoformat() except UnknownTimeZoneError: timestamp = 'Invalid Timezone' q_var = question['variable'] q_text = question['text'] q_text = q_text.replace('\n', ' ') q_text = q_text.replace(';', ',') message = message.replace('\n', ' ') message = message.replace(';', ',') with open('survey/data_incomplete/' + str(user.chat_id_) + '.csv', 'a+', newline='') as user_file: columns = [ str(user.chat_id_), user.language_, user.gender_, user.age_, user.country_, user.timezone_, user.day_, user.block_, user.question_, timestamp, q_text, message, q_var ] writer = csv.writer(user_file, delimiter=';') writer.writerow(columns) return
def question_handler(bot: Bot, update: Update, user_map: DataSet, job_queue: JobQueue): try: # Get the user from the dict and its question_set (by language) user = user_map.participants[ update.message.chat_id] # type: Participant # Case for very first question. if user.question_ == -1: user.set_active(True) user.set_language(update.message.text) user.set_block(0) q_set = user_map.return_question_set_by_language(user.language_) user.q_set_ = q_set current_day = q_set[0]["day"] user.set_day(current_day) user.set_block(0) elif user.q_idle_: q_set = user.q_set_ # Get the matching question for the users answer. pointer = user.pointer_ d_prev = q_set[pointer] b_prev = d_prev["blocks"][user.block_] q_prev = b_prev["questions"][user.question_] if not valid_answer(q_prev, update.message.text, user): user.set_q_idle(True) return # Storing the answer and moving on the next question store_answer(user, update.message.text, q_prev, job_queue) user.set_q_idle(False) else: # User has send something without being asked a question. return except KeyError as error: print(error) return if not user.active_: return message, question = find_next_question(user) if question is not None: message = question["text"] q_keyboard = get_keyboard(question["choice"], user) try: bot.send_message(chat_id=user.chat_id_, text=message, reply_markup=q_keyboard) debug(flag="MSG", text=str(user.chat_id_) + ": " + message + "\n") except TelegramError as error: if error.message == 'Unauthorized': user.pause() user.set_q_idle(True) elif user.auto_queue_ is False: user.block_complete_ = True next_day = user.set_next_block() if next_day is None: finished(user, job_queue) return element = user.next_block[2] day_offset = next_day - user.day_ time_t = calc_block_time(element["time"]) due = calc_delta_t(time_t, day_offset, user.timezone_) debug('QUEUE', 'next block in ' + str(due) + ' seconds. User: ' + str(user.chat_id_), log=True) new_job = Job(queue_next, due, repeat=False, context=[user, job_queue]) user.job_ = new_job job_queue._put(new_job)