11 Commits
v0.1 ... v0.3

Author SHA1 Message Date
b5a4493af5 Updated Readme TOC 2019-07-05 23:35:22 +01:00
c51a4e7f5a Updated README and added LICENSE 2019-07-05 23:33:04 +01:00
4dbdc02d15 Added info about brown bottles 2019-07-05 22:49:48 +01:00
6392a582a5 Adjusted CSS, added background 2019-07-05 22:40:05 +01:00
dd3ba8cec8 Success styling 2019-07-04 23:18:24 +01:00
dfb4a7a761 Changed success box styling 2019-07-04 23:10:35 +01:00
72ae7c3835 Change dockerfile python path 2019-07-04 22:53:08 +01:00
aa2911d969 Updated tests 2019-07-04 22:45:54 +01:00
62dcad7946 Working simple letter assignment without updated tests 2019-07-04 21:51:03 +01:00
8df55ad17a Update README.md
Deleted README
2019-07-04 18:45:57 +00:00
508f309223 Added README 2019-07-04 18:44:50 +00:00
15 changed files with 296 additions and 7 deletions

3
.gitignore vendored
View File

@@ -1,4 +1,5 @@
venv/
.idea/
.pytest_cache
*_pycache_*
*_pycache_*
*.db

View File

@@ -6,4 +6,4 @@ COPY . /app
WORKDIR /app
RUN pip3 install -r requirements.txt
ENTRYPOINT ["python3"]
CMD ["app.py"]
CMD ["web/app.py"]

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
The MIT License
Copyright (c) 2010-2019 Sean Cusack
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

96
README.md Normal file
View File

@@ -0,0 +1,96 @@
<!-- PROJECT LOGO -->
<br />
<p align="center">
<img src="logo.png" alt="Logo" width="80" height="80">
<h3 align="center">Wigan Homebrew Club Competition Entry</h3>
<p align="center">
A project to facilitate anonymous entry into Wigan HBC competitions!
<br />
<br />
<a href="https://wiganhomebrew.cusack.cloud/">View Demo</a>
·
<a href="https://git.cusack.cloud/acid/wiganhbc-competition/issues">Report Bug</a>
·
<a href="https://git.cusack.cloud/acid/wiganhbc-competition/issues">Request Feature</a>
</p>
</p>
<!-- TABLE OF CONTENTS -->
## Table of Contents
* [About the Project](#about-the-project)
* [Built With](#built-with)
* [Getting Started](#getting-started)
* [Prerequisites](#prerequisites)
* [Running The Project](#running-the-project)
* [Roadmap](#roadmap)
* [License](#license)
* [Contact](#contact)
<!-- ABOUT THE PROJECT -->
## About The Project
![Screen Shot](screenshot.PNG)
This project is to allow homebrew club members to be given an identifying number/letter to put on their bottles for competitions. The goal is to allow all members to take part with no invigilator/organiser required.
### Built With
This project is built in python and deployed in docker.
* [Flask](http://flask.pocoo.org/)
* [Bootstrap](https://getbootstrap.com)
* [Docker](https://www.docker.com/)
<!-- GETTING STARTED -->
## Getting Started
### Prerequisites
For development you need to have python3 installed along with pip. You can then set up a virtualenv and install requirements
```sh
pip install -r requirements.txt
```
### Running the project
A sample Dockerfile is included. Please note that you must supply an HBC_DB_PATH environmental variable. Below is a sample docker compose that can be used after you clone this repo.
```yaml
version: '3'
services:
wiganhomebrew:
container_name: wiganhomebrew
build: <relative path to repo directory>
restart: always
environment:
- HBC_DB_PATH=/data
volumes:
- sqlite-database-volume:/data
ports:
- 5000:5000
volumes:
sqlite-database-volume:
```
<!-- ROADMAP -->
## Roadmap
See the [open issues](https://git.cusack.cloud/acid/wiganhbc-competition/issues) for a list of proposed features (and known issues).
<!-- LICENSE -->
## License
Distributed under the MIT License. See `LICENSE` for more information.
<!-- CONTACT -->
## Contact
Sean Cusack - seancusack@gmail.com
Project Link: [https://git.cusack.cloud/acid/wiganhbc-competition](https://git.cusack.cloud/acid/wiganhbc-competition)

BIN
logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -4,7 +4,9 @@ certifi==2019.6.16
chardet==3.0.4
Click==7.0
colorama==0.4.1
dominate==2.3.5
Flask==1.0.3
Flask-Bootstrap==3.3.7.1
idna==2.8
importlib-metadata==0.18
itsdangerous==1.1.0
@@ -16,9 +18,11 @@ pluggy==0.12.0
py==1.8.0
pyparsing==2.4.0
pytest==5.0.0
pytest-env==0.6.2
requests==2.22.0
six==1.12.0
urllib3==1.25.3
visitor==0.1.3
wcwidth==0.1.7
Werkzeug==0.15.4
zipp==0.5.1

BIN
screenshot.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 932 KiB

View File

@@ -1,7 +1,6 @@
import pytest
from web import app
@pytest.fixture
def client():
app.app.config['TESTING'] = True
@@ -12,4 +11,15 @@ def client():
def test_root_page(client):
rv = client.get('/')
assert b'Hello World!' in rv.data
assert rv.status_code == 200
assert b'Please enter your first name and initial' in rv.data
def test_generate_first(client):
rv2 = client.post('/generate', data=dict(name='tester'), follow_redirects=True)
assert rv2.status_code == 200
assert b'Please mark all of your bottlecaps with the following identifier: <strong>A' in rv2.data
def test_generate_second(client):
rv = client.post('/generate', data=dict(name='tester'), follow_redirects=True)
assert rv.status_code == 200
assert b'Please mark all of your bottlecaps with the following identifier: <strong>B' in rv.data

View File

@@ -1,3 +1,5 @@
[pytest]
filterwarnings =
ignore::DeprecationWarning
ignore::DeprecationWarning
env =
HBC_DB_PATH=tests

10
user_experience.md Normal file
View File

@@ -0,0 +1,10 @@
# User Goals
* Obtain a letter for their brew
* The letter should be different to everyone elses
* If they forget they should get a new letter
* If we run out of letters hand out numbers instead
# Security Concerns
* Nobody should see what anyone else has
* It would be nice to be able to dump out a list at the end of who's who

View File

@@ -1,11 +1,63 @@
from flask import Flask
from flask import Flask, render_template, request
from flask_bootstrap import Bootstrap
import sqlite3
import os
import string
app = Flask(__name__)
Bootstrap(app)
def get_db_connection():
db_path = os.environ.get('HBC_DB_PATH')
if not db_path:
raise Exception("DB Path not defined")
return sqlite3.connect(db_path + '/hbc.db')
def db_setup():
conn = get_db_connection()
sql_create_table = """ CREATE TABLE IF NOT EXISTS brewers (
id integer PRIMARY KEY,
name text NOT NULL,
identifier text NOT NULL );"""
c = conn.cursor()
c.execute(sql_create_table)
conn.close()
db_setup()
brew_name = "Fruit Beer"
brew_month = "October"
identifiers = list(string.ascii_uppercase) + list(range(1, 100))
def get_identifier(name):
conn = get_db_connection()
c = conn.cursor()
for identifier in identifiers:
c.execute('''SELECT identifier FROM brewers WHERE identifier=?''', (str(identifier),))
data = c.fetchone()
if data is None:
print("Assigning " + identifier + " to " + name)
c.execute("INSERT INTO brewers (name,identifier) VALUES(?, ?)",(name, identifier) )
conn.commit()
conn.close()
return identifier
@app.route('/')
def hello_world():
return 'Hello World!'
return render_template('index.html', brew_name=brew_name, brew_month=brew_month)
@app.route('/generate', methods=["POST"])
def generate():
identifier = get_identifier(request.form['name'])
return render_template('generate.html', brew_name=brew_name, brew_month=brew_month, identifier=identifier)
if __name__ == '__main__':

BIN
web/static/background3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

32
web/static/mystyle.css Normal file
View File

@@ -0,0 +1,32 @@
body {
background: url('background3.jpg') no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
background-size: cover;
-o-background-size: cover;
}
.content-div {
background-color: rgba(255,255,255,0.6);
padding-left: 5ch;
padding-right: 5ch;
padding-top: 5ch;
padding-bottom: 5ch;
border-radius: 25px;
}
#my-jumbotron {
//background-color: rgba(50,50,50,0.9);
margin-top: 20px;
margin-bottom: 50px;
padding: 2rem 1rem;
border-radius: 1rem;
background: #282020; /* fallback for old browsers */
background: -webkit-linear-gradient(to right, rgba(54, 55, 57, 0.9), rgba(75, 87, 90, 0.9), rgba(40, 32, 32, 0.9)); /* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to right, rgba(54, 55, 57, 0.9), rgba(75, 87, 90, 0.9), rgba(40, 32, 32, 0.9)); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
}
.my-title {
color: floralwhite;
font-size: 3em;
}

View File

@@ -0,0 +1,27 @@
{% extends "bootstrap/base.html" %}
{% block styles %}
{{super()}}
<link rel="stylesheet"
href="{{url_for('static', filename='mystyle.css')}}">
{% endblock %}
{% block title %}Wigan Homebrew Club Competition Entry{% endblock %}
{% block content %}
<div class="container">
<div class="jumbotron text-center" id="my-jumbotron">
<h2 class="my-title">Wigan Homebrew Club Competition Entry</h2>
</div>
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8 content-div">
<p>You have been entered into the competition to brew a <strong>{{ brew_name }}</strong>, which will be judged at the meeting in <strong>{{ brew_month }}</strong>.</p>
<p>To make sure your beer isn't easily identifiable, most people tend to use brown bottles of either 330ml or 500ml size. You probably don't want to put your own label on the bottle!</p>
<br/>
<div class="alert alert-success lead" role="alert"> <span class="glyphicon glyphicon-tags" aria-hidden="true"></span> &nbsp; &nbsp;Please mark all of your bottlecaps with the following identifier: <strong>{{ identifier }}</strong></div>
</div>
</div>
</div>
{% endblock %}

34
web/templates/index.html Normal file
View File

@@ -0,0 +1,34 @@
{% extends "bootstrap/base.html" %}
{% block styles %}
{{super()}}
<link rel="stylesheet"
href="{{url_for('static', filename='mystyle.css')}}">
{% endblock %}
{% block title %}Wigan Homebrew Club Competition Entry{% endblock %}
{% block content %}
<div class="container">
<div class="jumbotron text-center" id="my-jumbotron">
<h2 class="my-title">Wigan Homebrew Club Competition Entry</h2>
</div>
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8 content-div">
<p>The next competition brew will be a <strong>{{ brew_name }}</strong>. It will be judged at the meeting in <strong>{{ brew_month }}</strong></p>
<br/>
<p>If you would like to enter the competition, please enter your name below to generate a letter/number that will be used to identify your entry</p>
<hr>
<form action="{{ url_for('generate') }}" method="POST">
<div class="form-group">
<label for="name">Please enter your first name and initial (or nickname)</label>
<input name="name" type="text" id="name" class="form-control input-lg" placeholder="eg: Sean C">
</div>
<button type="submit" class="btn btn-primary">Enter Competition</button>
</form>
</div>
</div>
</div>
{% endblock %}