diff --git a/abot.py b/abot.py index 08c2b98..c2eacb3 100644 --- a/abot.py +++ b/abot.py @@ -7,7 +7,7 @@ from utils import * import manager DATABASE = 'abot.sqlite' -DEBUG = False +DEBUG = True SECRET_KEY = 'otwet6oi539iosf' QUESTIONS = 'questions' # path to questions @@ -51,7 +51,8 @@ def preview(key): ) @app.route('/vote//') -def vote(key, token): +@app.route('/vote/') +def vote(key, token = None): if not is_key(key): return render_template('blank.html', message = "Unknown key") form = parse_form(key) @@ -61,8 +62,9 @@ def vote(key, token): return render_template('blank.html', message = "Not published") if is_expired(form): return render_template('blank.html', message = "Voting has closed") - if has_voted(key, token): - return render_template('blank.html', message = "Token already used") + if is_closed_vote(form): + if has_voted(key, token): + return render_template('blank.html', message = "Token already used") valid_for = time_to_expiry(form) return render_template('vote.html', form = form, key = key, token = token, valid_for = valid_for) @@ -81,13 +83,17 @@ def save_vote(): return render_template('blank.html', message = "Not published") if is_expired(form): return render_template('blank.html', message = "Voting has closed") - if has_voted(key, token): - return render_template('blank.html', message = "Token already used") + if is_closed_vote(form): + if has_voted(key, token): + return render_template('blank.html', message = "Token already used") create_result_table(key) write_vote(key, token, request.form, form) # using request. + summary = '' + if is_show_results(form): + summary = get_html_summary(key) - return render_template('thank_you.html') + return render_template('thank_you.html', summary = summary) if __name__ == "__main__": manager.main(DATABASE, QUESTIONS) diff --git a/manager.py b/manager.py index 9345787..3905e18 100644 --- a/manager.py +++ b/manager.py @@ -135,6 +135,10 @@ def list_question_sets(options): def summary(options): + print(get_summary(options)) + + +def get_summary(options): if not is_key(options.name, options): raise Exception("%s does not exist, or is not a valid question set name"%( options.name, )) db = open_db(options.db) @@ -146,8 +150,8 @@ def summary(options): ) matching_tables = cur.fetchall() if len(matching_tables) == 0: - print("No votes yet") - return + return "No votes yet" + token_table = get_voter_table_name(options.name) cur.execute( "SELECT name FROM sqlite_master WHERE type='table' AND name=?;", @@ -197,21 +201,20 @@ def summary(options): try: if options.tsv: - summary_tsv(questions, answers, tokens) + return summary_tsv(questions, answers, tokens) else: - summary_list(questions, answers, tokens) + return summary_list(questions, answers, tokens) except AttributeError: - summary_list(questions, answers, tokens) + return summary_list(questions, answers, tokens) def summary_list(questions, answers, tokens): - print( - """# Tokens for this question set: -# used: {used}, unused: {unused}, total: {total}""".format_map(tokens) - ) + s = """# Tokens for this question set: +# used: {used}, unused: {unused}, total: {total} +""".format_map(tokens) for q,a in zip(questions, answers): sum_answers = sum([answers[q]['answers'][x] for x in answers[q]['answers']]) - print("\n%s\n# Answers total: %d"%( q, sum_answers, )) + s += "\n%s\n# Answers total: %d\n"%( q, sum_answers, ) sorted_answers = sorted( [(x, answers[q]['answers'][x]) for x in answers[q]['answers']], key = lambda i: -i[1] @@ -229,33 +232,34 @@ def summary_list(questions, answers, tokens): prefix = "----\n> " postfix = "" - print("%s%s%s"%( + s += "%s%s%s\n"%( prefix, answer[0], postfix - )) + ) + return s def summary_tsv(questions, answers, tokens): - print( - '''Tokens\tUsed\tUnused\tTotal -""\t"{used}"\t"{unused}"\t"{total}"'''.format_map(tokens) - ) - print('"Question"\t"Question type"\t"Answer"\t"Count"') + s = '''Tokens\tUsed\tUnused\tTotal +""\t"{used}"\t"{unused}"\t"{total}" +'''.format_map(tokens) + s += '"Question"\t"Question type"\t"Answer"\t"Count"\n' good_characters = dict.fromkeys(range(32)) for q,a in zip(questions, answers): sum_answers = sum([answers[q]['answers'][x] for x in answers[q]['answers']]) - print('"%s"\t"%s"\t""\t"%d"'%( q, answers[q]['answer_type'], sum_answers, )) + s += '"%s"\t"%s"\t""\t"%d"\n'%( q, answers[q]['answer_type'], sum_answers, ) sorted_answers = sorted( [(x, answers[q]['answers'][x]) for x in answers[q]['answers']], key = lambda i: -i[1] ) for answer in sorted_answers: - print('""\t""\t""%s\t"%d"'%( + s += '""\t""\t""%s\t"%d"\n'%( answer[0].translate(good_characters), answer[1], - )) + ) + return s def clear_votes(options): diff --git a/static/style.css b/static/style.css index 061b9ff..0542068 100644 --- a/static/style.css +++ b/static/style.css @@ -32,3 +32,13 @@ table.entriesall { border-collapse: collapse; } textarea { width: 90%; } + +.header { + text-align: right; + font-size: small; +} +.footer { + margin-top: 2em; + text-align: left; + font-size: small; +} diff --git a/templates/layout.html b/templates/layout.html index 50fb244..be87c62 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -6,7 +6,22 @@ + +
+
+Read more about me at the bottom! +
{% block body %}{% endblock %} +
+
diff --git a/templates/thank_you.html b/templates/thank_you.html index 7c6ccac..54a6671 100644 --- a/templates/thank_you.html +++ b/templates/thank_you.html @@ -4,5 +4,6 @@ Thank you for the vote! +{{ summary|safe }} {% endblock %} diff --git a/utils.py b/utils.py index 2b40da6..c67aaa7 100644 --- a/utils.py +++ b/utils.py @@ -16,6 +16,7 @@ def create_result_table(key): ) g.db.commit() + def create_voter_table(db, name): table_name = get_voter_table_name(name) cur = db.cursor() @@ -29,6 +30,7 @@ def create_voter_table(db, name): ) db.commit() + def get_voter_table_name(key): return key + "__voters" @@ -37,7 +39,14 @@ def get_result_table_name(key): return key +def get_html_summary(key): + # TODO + return '' + + def has_voted(key, token): + if token == None: + return True cur = g.db.cursor() cur.execute( "SELECT token FROM %s WHERE token = ? AND answered = 'true'"%( @@ -50,15 +59,21 @@ def has_voted(key, token): return len(cur.fetchall()) > 0 +def is_closed_vote(form): + return form['vote_style'] == 'closed' + + def is_draft(form): return form['draft'] + def is_expired(form): if form['expires'] == None: return False return datetime.now(timezone.utc) > form['expires'] + def is_key(key, cli_opts = False): key = secure_filename(key) @@ -74,10 +89,17 @@ def is_key(key, cli_opts = False): ) ) + +def is_show_results(form): + return form['show_results'] + + def parse_form(key): form = { 'expires': None, 'draft': False, + 'vote_style': "closed", + 'show_results': False, 'questions': [] } key = secure_filename(key) @@ -87,15 +109,24 @@ def parse_form(key): for row in fp: if row.strip() == "": continue + rowsl = row.lower().rstrip() if row.startswith("#"): continue - if row.lower().startswith("expires: "): + if rowsl.startswith("expires: "): form['expires'] = parse_row_date(row) continue - if row.lower().startswith("draft: "): - if row.lower().rstrip() == "draft: true": + if rowsl.startswith("draft: "): + if rowsl == "draft: true": form['draft'] = True continue + if rowsl.startswith("vote_style: "): + if rowsl == "vote_style: open": + form['vote_style'] = "open" + continue + if rowsl.startswith("show_results: "): + if rowsl == "show_results: true": + form['show_results'] = True + continue if row.startswith("- "): if current_question == None: continue @@ -157,9 +188,11 @@ def write_vote(key, token, answers, form): answer_type = "open" if answer == None: continue + if answer_type == None: + continue for single in answer: cur.execute( - "INSERT INTO %s VALUES (?, ?, ?)"%( + "INSERT INTO `%s` VALUES (?, ?, ?)"%( key, ), ( @@ -168,15 +201,15 @@ def write_vote(key, token, answers, form): answer_type ) ) - - cur.execute( - "UPDATE %s SET answered = 'true' WHERE token = ?"%( - get_voter_table_name(key), - ), - ( - token, + if is_closed_vote(form): + cur.execute( + "UPDATE %s SET answered = 'true' WHERE token = ?"%( + get_voter_table_name(key), + ), + ( + token, + ) ) - ) g.db.commit()