Skip to content

Commit

Permalink
Convert to web app
Browse files Browse the repository at this point in the history
  • Loading branch information
christarazi committed Dec 13, 2016
1 parent a63a1ae commit bd74ee5
Show file tree
Hide file tree
Showing 9 changed files with 354 additions and 11 deletions.
111 changes: 111 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@

# Created by https://www.gitignore.io/api/python,git,vim

### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# dotenv
.env

# virtualenv
.venv/
venv/
ENV/

# Spyder project settings
.spyderproject

# Rope project settings
.ropeproject


### Git ###
*.orig


### Vim ###
# swap
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
# session
Session.vim
# temporary
.netrwhist
*~
# auto-generated tag files
tags
1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: gunicorn app:app
39 changes: 39 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from flask import Flask, render_template, redirect, \
url_for, request, flash, escape

import os
import draw # Import simulator code

app = Flask(__name__)

app.secret_key = os.urandom(24)

@app.route("/", methods=["GET", "POST"])
def index():
if request.method == "POST":
try:
draws = None
n = int(escape(request.form["simulations"]))
if n > 1000000:
flash("Error: 1,000,000 is the maximum number of simulations.")
elif n < 1:
flash("Error: Number must be greater than zero.")
else:
draws = draw.execute_simulation(n)
return render_template("results.html", draws=draws, n=n)
except Exception as e:
print(e)
flash("Error: Tricky tricky, only numbers are accepted here.")
# else:

return render_template("form.html")

if __name__ == "__main__":
app.run()

@app.context_processor
def utility_processor():
def format_odds(odds):
return "{0:.5}".format(odds)

return dict(format_odds=format_odds)
27 changes: 16 additions & 11 deletions draw.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@
("H", "SPA", "Sevilla")
]

if len(sys.argv) != 2:
print("Usage:", sys.argv[0], "<num of simulations>")
sys.exit(-1)
# if len(sys.argv) != 2:
# print("Usage:", sys.argv[0], "<num of simulations>")
# sys.exit(-1)

valid_draws = defaultdict(list) # Holds all valid draws
draws = {} # Holds the count of the simulations
n = int(sys.argv[1]) # Number of simulations
# n = int(sys.argv[1]) # Number of simulations

def init_draws():
for winner in group_winners:
Expand Down Expand Up @@ -112,12 +112,17 @@ def simulate_draw():

# -----------------------------------------------------------------------------

init_draws()
for i in range(n):
simulate_draw()
def execute_simulation(n):
init_draws()
for i in range(n):
simulate_draw()

for match, count in draws.items():
if count != 0:
print("{:18} {} {:18}".format(match[0][2], "vs", match[1][2]),
"|", count, "/", n, "=", "{0:.5}".format(count / n))
# for match, count in draws.items():
# if count != 0:
# print("{:18} {} {:18}".format(match[0][2], "vs", match[1][2]),
# "|", count, "/", n, "=", "{0:.5}".format(count / n))
return draws

if __name__ == "__main__":
execute_simulation()

7 changes: 7 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
click==6.6
Flask==0.11.1
gunicorn==19.6.0
itsdangerous==0.24
Jinja2==2.8
MarkupSafe==0.23
Werkzeug==0.11.11
1 change: 1 addition & 0 deletions runtime.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
python-3.5.2
10 changes: 10 additions & 0 deletions templates/form.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{% extends "index.html" %}
{% block body %}
<form class="pure-form pure-form-stacked" action="{{ url_for('index') }}" method=post>
<label for="simulations">
Number of simulations:
</label>
<input id="simulations" name="simulations" type="number">
<button type="submit" class="pure-button pure-button-primary">Run</button>
</form>
{% endblock %}
141 changes: 141 additions & 0 deletions templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>UCL Draw Simulator</title>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/build/pure-min.css">
<link rel="stylesheet" href="https://unpkg.com/[email protected]/build/grids-responsive-min.css">
</head>
<body>
<style>
/*
* -- MENU STYLES --
* I want to customize how my .pure-menu looks at the top of the page
*/
.home-menu {
padding: 0.5em;
text-align: center;
box-shadow: 0 1px 1px rgba(0,0,0, 0.10);
}

.home-menu {
background: #2d3e50;
}
.pure-menu.pure-menu-fixed {
/* Fixed menus normally have a border at the bottom. */
border-bottom: none; z-index: 4;
}

.home-menu .pure-menu-heading {
color: white;
font-weight: 400;
font-size: 120%;
}

.home-menu .pure-menu-selected a {
color: white;
}

.home-menu a {
color: #6FBEF3;
}
.home-menu li a:hover,
.home-menu li a:focus {
background: none;
border: none;
color: #AECFE5;
}

/*
* -- TABLET (AND UP) MEDIA QUERIES --
* On tablets and other medium-sized devices, we want to customize some
* of the mobile styles.
*/
@media (min-width: 48em) {

/* We increase the body font size */
body {
font-size: 16px;
}
/* We want to give the content area some more padding */
.main {
padding: 1em;
}

/* We can align the menu header to the left, but float the
menu items to the right. */
.home-menu {
text-align: left;
}
.home-menu ul {
float: right;
}
}
</style>
<style scoped>
.button-success,
.button-error,
.button-warning,
.button-secondary {
color: white;
border-radius: 4px;
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
}

.button-success {
background: rgb(28, 184, 65); /* this is a green */
}

.button-error {
background: rgb(202, 60, 60); /* this is a maroon */
}

.button-warning {
background: rgb(223, 117, 20); /* this is an orange */
}

.button-secondary {
background: rgb(66, 184, 221); /* this is a light blue */
}
</style>
<style>
.header {
display: inline-block;
}

.main {
padding: 2em;
color: black;
}
</style>
<div class="content">

<div class="header">
<div class="home-menu pure-menu pure-menu-horizontal pure-menu-fixed">
<a class="pure-menu-heading" href="{{ url_for('index') }}">UCL Draw</a>
<ul class="pure-menu-list">
<li class="pure-menu-item"><a href="{{ url_for('index') }}" class="pure-menu-link">Home</a></li>
<li class="pure-menu-item"><a href="https://github.com/christarazi/ucl_draw" class="pure-menu-link">GitHub</a></li>
</ul>
</div>
</div>

<div class="main">
<h2>UCL Round of 16 Draw Simulator 2016-2017</h2>
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class=flashes>
{% for message in messages %}
<p class="button-error pure-button">{{ message }}</p>
{% endfor %}
</div>
{% endif %}
{% endwith %}
{% block body %}{% endblock %}
</div>

</div>
</body>
</html>

28 changes: 28 additions & 0 deletions templates/results.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{% extends "index.html" %}
{% block body %}
<div class=results>
<pre>Number of simulations: {{ n }}</pre><br>
<table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th>Winner</th>
<th>Runner-up</th>
<th>Count</th>
<th>Odds</th>
</tr>
</thead>
<tbody>
{% for match, count in draws.items() %}
{% if count != 0 %}
<tr>
<td>{{ match[0][2] }}</td>
<td>{{ match[1][2] }}</td>
<td>{{ count }}</td>
<td>{{ format_odds(count / n) }}</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

0 comments on commit bd74ee5

Please sign in to comment.