inital db
This commit is contained in:
commit
a3b496744c
12 changed files with 508 additions and 0 deletions
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
*.pyc
|
||||
app.db
|
||||
./tmp
|
||||
./build/*
|
||||
.idea
|
||||
env
|
||||
venv
|
||||
*.sublime*
|
||||
18
README.rst
Normal file
18
README.rst
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
Base Skeleton to start your application using Flask-AppBuilder
|
||||
--------------------------------------------------------------
|
||||
|
||||
- Install it::
|
||||
|
||||
pip install flask-appbuilder
|
||||
git clone https://github.com/dpgaspar/Flask-AppBuilder-Skeleton.git
|
||||
|
||||
- Run it::
|
||||
|
||||
$ export FLASK_APP=app
|
||||
# Create an admin user
|
||||
$ flask fab create-admin
|
||||
# Run dev server
|
||||
$ flask run
|
||||
|
||||
|
||||
That's it!!
|
||||
32
app/__init__.py
Normal file
32
app/__init__.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import logging
|
||||
|
||||
from flask import Flask
|
||||
from flask_appbuilder import AppBuilder, SQLA
|
||||
|
||||
"""
|
||||
Logging configuration
|
||||
"""
|
||||
|
||||
logging.basicConfig(format="%(asctime)s:%(levelname)s:%(name)s:%(message)s")
|
||||
logging.getLogger().setLevel(logging.DEBUG)
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config.from_object("config")
|
||||
db = SQLA(app)
|
||||
appbuilder = AppBuilder(app, db.session)
|
||||
|
||||
|
||||
"""
|
||||
from sqlalchemy.engine import Engine
|
||||
from sqlalchemy import event
|
||||
|
||||
#Only include this for SQLLite constraints
|
||||
@event.listens_for(Engine, "connect")
|
||||
def set_sqlite_pragma(dbapi_connection, connection_record):
|
||||
# Will force sqllite contraint foreign keys
|
||||
cursor = dbapi_connection.cursor()
|
||||
cursor.execute("PRAGMA foreign_keys=ON")
|
||||
cursor.close()
|
||||
"""
|
||||
|
||||
from . import views
|
||||
164
app/models.py
Normal file
164
app/models.py
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
from flask_appbuilder import Model
|
||||
from sqlalchemy import Column, Integer, String, ForeignKey, Boolean
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
"""
|
||||
|
||||
You can use the extra Flask-AppBuilder fields and Mixin's
|
||||
|
||||
AuditMixin will add automatic timestamp of created and modified by who
|
||||
|
||||
|
||||
"""
|
||||
|
||||
class Spieler(Model):
|
||||
id = Column(Integer, primary_key=True)
|
||||
name = Column(String())
|
||||
|
||||
def __repr__(self):
|
||||
return self.name
|
||||
|
||||
class Spiel(Model):
|
||||
id = Column(Integer, primary_key=True)
|
||||
|
||||
spieler1_id = Column(Integer, ForeignKey('spieler.id'))
|
||||
spieler1 = relationship('Spieler', foreign_keys=[spieler1_id])
|
||||
spieler2_id = Column(Integer, ForeignKey('spieler.id'))
|
||||
spieler2 = relationship('Spieler', foreign_keys=[spieler2_id])
|
||||
spieler3_id = Column(Integer, ForeignKey('spieler.id'))
|
||||
spieler3 = relationship('Spieler', foreign_keys=[spieler3_id])
|
||||
spieler4_id = Column(Integer, ForeignKey('spieler.id'))
|
||||
spieler4 = relationship('Spieler', foreign_keys=[spieler4_id])
|
||||
|
||||
spieltyp = Column(String())
|
||||
|
||||
leger1 = Column(Boolean)
|
||||
leger2 = Column(Boolean)
|
||||
leger3 = Column(Boolean)
|
||||
leger4 = Column(Boolean)
|
||||
|
||||
spieler = Column(Integer(), nullable=True)
|
||||
mitspieler = Column(Integer(), nullable=True)
|
||||
|
||||
kontra = Column(Integer(), default=0)
|
||||
tout = Column(Boolean, default=False)
|
||||
sie = Column(Boolean, default=False)
|
||||
|
||||
schneider = Column(Integer(), default=0)
|
||||
|
||||
# Hat der Spielr gewonnen?
|
||||
gewonnen = Column(Boolean, nullable=True)
|
||||
# Wenn Ramsch gespielt wird
|
||||
durchmarsch = Column(Boolean)
|
||||
verlierer1 = Column(Boolean)
|
||||
verlierer2 = Column(Boolean)
|
||||
verlierer3 = Column(Boolean)
|
||||
verlierer4 = Column(Boolean)
|
||||
jungfrau1 = Column(Boolean())
|
||||
jungfrau2 = Column(Boolean())
|
||||
jungfrau3 = Column(Boolean())
|
||||
jungfrau4 = Column(Boolean())
|
||||
|
||||
|
||||
# Bonus info
|
||||
farbe = Column(String())
|
||||
|
||||
def spielwert(self):
|
||||
grundtarif = 20
|
||||
extras = 10
|
||||
solo = 50
|
||||
|
||||
result = [0,0,0,0]
|
||||
|
||||
if self.spieltyp == "Sauspiel":
|
||||
spieler = set([self.spieler-1,self.mitspieler-1])
|
||||
nichtspieler = list(set([0,1,2,3])-spieler)
|
||||
if self.gewonnen:
|
||||
result[self.spieler-1] = grundtarif
|
||||
result[self.mitspieler-1] = grundtarif
|
||||
result[nichtspieler[0]] = -grundtarif
|
||||
result[nichtspieler[1]] = -grundtarif
|
||||
else:
|
||||
result[self.spieler-1] = -grundtarif
|
||||
result[self.mitspieler-1] = -grundtarif
|
||||
result[nichtspieler[0]] = grundtarif
|
||||
result[nichtspieler[1]] = grundtarif
|
||||
elif self.spieltyp == "Wenz" or self.spieltyp == "Solo":
|
||||
spieler = set([self.spieler-1])
|
||||
nichtspieler = list(set([0,1,2,3])-spieler)
|
||||
if self.gewonnen:
|
||||
result[self.spieler-1] = solo
|
||||
result[nichtspieler[0]] = -solo
|
||||
result[nichtspieler[1]] = -solo
|
||||
result[nichtspieler[2]] = -solo
|
||||
else:
|
||||
result[self.spieler-1] = -solo
|
||||
result[nichtspieler[0]] = solo
|
||||
result[nichtspieler[1]] = solo
|
||||
result[nichtspieler[2]] = solo
|
||||
elif self.spieltyp == "Ramsch":
|
||||
|
||||
if self.durchmarsch:
|
||||
if self.verlierer1:
|
||||
result[0] = -solo
|
||||
else:
|
||||
result[0] = 3*solo
|
||||
if self.verlierer2:
|
||||
result[1] = -solo
|
||||
else:
|
||||
result[1] = 3*solo
|
||||
if self.verlierer3:
|
||||
result[2] = -solo
|
||||
else:
|
||||
result[2] = 3*solo
|
||||
if self.verlierer4:
|
||||
result[3] = -solo
|
||||
else:
|
||||
result[3] = 3*solo
|
||||
else:
|
||||
nGewinner = 0
|
||||
if not self.verlierer1:
|
||||
result[0] = grundtarif * (self.jungfrau1 + 1)
|
||||
nGewinner += 1 + self.jungfrau1
|
||||
if not self.verlierer2:
|
||||
result[1] = grundtarif * (self.jungfrau2 + 1)
|
||||
nGewinner += 1 + self.jungfrau2
|
||||
if not self.verlierer3:
|
||||
result[2] = grundtarif * (self.jungfrau3 + 1)
|
||||
nGewinner += 1 + self.jungfrau3
|
||||
if not self.verlierer4:
|
||||
result[3] = grundtarif * (self.jungfrau4 + 1)
|
||||
nGewinner += 1 + self.jungfrau4
|
||||
|
||||
if self.verlierer1:
|
||||
result[0] = -nGewinner*grundtarif
|
||||
if self.verlierer2:
|
||||
result[1] = -nGewinner*grundtarif
|
||||
if self.verlierer3:
|
||||
result[2] = -nGewinner*grundtarif
|
||||
if self.verlierer4:
|
||||
result[3] = -nGewinner*grundtarif
|
||||
|
||||
result = [i * (self.schneider * extras+grundtarif) /grundtarif for i in result]
|
||||
|
||||
if self.leger1 or self.leger2 or self.leger3 or self.leger4:
|
||||
result = [2*i for i in result]
|
||||
|
||||
result = [2**self.kontra*i for i in result]
|
||||
if self.tout:
|
||||
result = [2*i for i in result]
|
||||
if self.sie:
|
||||
result = [4*i for i in result]
|
||||
|
||||
return {
|
||||
self.spieler1: result[0],
|
||||
self.spieler2: result[1],
|
||||
self.spieler3: result[2],
|
||||
self.spieler4: result[3],
|
||||
}
|
||||
|
||||
def check(self):
|
||||
if sum(self.spielwert().values())==0:
|
||||
return u"\U0001F44D"
|
||||
else:
|
||||
return u"\U0001F44E"
|
||||
7
app/templates/404.html
Normal file
7
app/templates/404.html
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{% extends "appbuilder/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<h2><center>{{_('Page not found')}}<center></h2>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
BIN
app/translations/pt/LC_MESSAGES/messages.mo
Normal file
BIN
app/translations/pt/LC_MESSAGES/messages.mo
Normal file
Binary file not shown.
24
app/translations/pt/LC_MESSAGES/messages.po
Normal file
24
app/translations/pt/LC_MESSAGES/messages.po
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# Portuguese translations for PROJECT.
|
||||
# Copyright (C) 2015 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2015.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2015-10-26 13:23+0000\n"
|
||||
"PO-Revision-Date: 2015-10-26 13:22+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: pt <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.0\n"
|
||||
|
||||
#: app/templates/404.html:4
|
||||
msgid "Page not found"
|
||||
msgstr "Página não encontrada"
|
||||
|
||||
116
app/views.py
Normal file
116
app/views.py
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
from flask import render_template
|
||||
from flask_appbuilder.models.sqla.interface import SQLAInterface
|
||||
from flask_appbuilder import ModelView, ModelRestApi
|
||||
from wtforms.validators import AnyOf
|
||||
from wtforms.fields import SelectField
|
||||
|
||||
from .models import Spiel, Spieler
|
||||
from . import appbuilder, db
|
||||
|
||||
"""
|
||||
Create your Model based REST API::
|
||||
|
||||
class MyModelApi(ModelRestApi):
|
||||
datamodel = SQLAInterface(MyModel)
|
||||
|
||||
appbuilder.add_api(MyModelApi)
|
||||
|
||||
|
||||
Create your Views::
|
||||
|
||||
|
||||
class MyModelView(ModelView):
|
||||
datamodel = SQLAInterface(MyModel)
|
||||
|
||||
|
||||
Next, register your Views::
|
||||
|
||||
|
||||
appbuilder.add_view(
|
||||
MyModelView,
|
||||
"My View",
|
||||
icon="fa-folder-open-o",
|
||||
category="My Category",
|
||||
category_icon='fa-envelope'
|
||||
)
|
||||
"""
|
||||
|
||||
"""
|
||||
Application wide 404 error handler
|
||||
"""
|
||||
|
||||
|
||||
@appbuilder.app.errorhandler(404)
|
||||
def page_not_found(e):
|
||||
return (
|
||||
render_template(
|
||||
"404.html", base_template=appbuilder.base_template, appbuilder=appbuilder
|
||||
),
|
||||
404,
|
||||
)
|
||||
|
||||
|
||||
db.create_all()
|
||||
|
||||
|
||||
class MySpielView(ModelView):
|
||||
datamodel = SQLAInterface(Spiel)
|
||||
# form_overrides = dict(
|
||||
# spieltyp=SelectField
|
||||
# )
|
||||
# form_args = {
|
||||
# 'spieltyp': {
|
||||
# 'validators': [AnyOf(['Sauspiel', 'Wenz', 'Solo', 'Ramsch'])],
|
||||
# 'choices': [(0,'Sauspiel'), (1,'Wenz'), (2,'Solo'), (3,'Ramsch')],
|
||||
# "label": "Typ"
|
||||
# },
|
||||
# 'sie': {
|
||||
# "label": "SieSie"
|
||||
# }
|
||||
|
||||
|
||||
# }
|
||||
# add_columns = ['spieler1','spieler2','spieler3','spieler4']
|
||||
|
||||
list_columns = ('spieler1','spieler2','spieler3','spieler4', "spielwert", "check")
|
||||
# column_list = (Spiel.spieler1, Spiel.spieler2, Spiel.spieler3, Spiel.spieler4)
|
||||
|
||||
show_fieldsets = [
|
||||
(
|
||||
'Spieler',
|
||||
{'fields':['spieler1','spieler2','spieler3','spieler4']}
|
||||
),
|
||||
(
|
||||
'Leger',
|
||||
{'fields':['leger1','leger2','leger3','leger4'],
|
||||
'expanded':False}
|
||||
),
|
||||
(
|
||||
'Spiel',
|
||||
{'fields':['spieltyp']}
|
||||
),
|
||||
|
||||
]
|
||||
|
||||
validators_columns = {
|
||||
'spieltyp':[AnyOf(['Sauspiel', 'Wenz', 'Solo', 'Ramsch'])],
|
||||
}
|
||||
|
||||
class MySpielerView(ModelView):
|
||||
datamodel = SQLAInterface(Spieler)
|
||||
|
||||
|
||||
appbuilder.add_view(
|
||||
MySpielView,
|
||||
"Spiel",
|
||||
icon="fa-folder-open-o",
|
||||
category="Schafkopf",
|
||||
category_icon='fa-envelope'
|
||||
)
|
||||
appbuilder.add_view(
|
||||
MySpielerView,
|
||||
"Spieler",
|
||||
icon="fa-folder-open-o",
|
||||
category="Schafkopf",
|
||||
category_icon='fa-envelope'
|
||||
)
|
||||
3
babel/babel.cfg
Normal file
3
babel/babel.cfg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[python: **.py]
|
||||
[jinja2: **/templates/**.html]
|
||||
encoding = utf-8
|
||||
23
babel/messages.pot
Normal file
23
babel/messages.pot
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# Translations template for PROJECT.
|
||||
# Copyright (C) 2015 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2015.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2015-10-26 13:23+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.0\n"
|
||||
|
||||
#: app/templates/404.html:4
|
||||
msgid "Page not found"
|
||||
msgstr ""
|
||||
|
||||
110
config.py
Normal file
110
config.py
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
import os
|
||||
from flask_appbuilder.security.manager import (
|
||||
AUTH_OID,
|
||||
AUTH_REMOTE_USER,
|
||||
AUTH_DB,
|
||||
AUTH_LDAP,
|
||||
AUTH_OAUTH,
|
||||
)
|
||||
|
||||
basedir = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
# Your App secret key
|
||||
SECRET_KEY = "\2\1thisismyscretkey\1\2\e\y\y\h"
|
||||
|
||||
# The SQLAlchemy connection string.
|
||||
SQLALCHEMY_DATABASE_URI = "sqlite:///" + os.path.join(basedir, "app.db")
|
||||
# SQLALCHEMY_DATABASE_URI = 'mysql://myapp@localhost/myapp'
|
||||
# SQLALCHEMY_DATABASE_URI = 'postgresql://root:password@localhost/myapp'
|
||||
|
||||
# Flask-WTF flag for CSRF
|
||||
CSRF_ENABLED = True
|
||||
|
||||
# ------------------------------
|
||||
# GLOBALS FOR APP Builder
|
||||
# ------------------------------
|
||||
# Uncomment to setup Your App name
|
||||
# APP_NAME = "My App Name"
|
||||
|
||||
# Uncomment to setup Setup an App icon
|
||||
# APP_ICON = "static/img/logo.jpg"
|
||||
|
||||
# ----------------------------------------------------
|
||||
# AUTHENTICATION CONFIG
|
||||
# ----------------------------------------------------
|
||||
# The authentication type
|
||||
# AUTH_OID : Is for OpenID
|
||||
# AUTH_DB : Is for database (username/password()
|
||||
# AUTH_LDAP : Is for LDAP
|
||||
# AUTH_REMOTE_USER : Is for using REMOTE_USER from web server
|
||||
AUTH_TYPE = AUTH_DB
|
||||
|
||||
# Uncomment to setup Full admin role name
|
||||
# AUTH_ROLE_ADMIN = 'Admin'
|
||||
|
||||
# Uncomment to setup Public role name, no authentication needed
|
||||
# AUTH_ROLE_PUBLIC = 'Public'
|
||||
|
||||
# Will allow user self registration
|
||||
# AUTH_USER_REGISTRATION = True
|
||||
|
||||
# The default user self registration role
|
||||
# AUTH_USER_REGISTRATION_ROLE = "Public"
|
||||
|
||||
# When using LDAP Auth, setup the ldap server
|
||||
# AUTH_LDAP_SERVER = "ldap://ldapserver.new"
|
||||
|
||||
# Uncomment to setup OpenID providers example for OpenID authentication
|
||||
# OPENID_PROVIDERS = [
|
||||
# { 'name': 'Yahoo', 'url': 'https://me.yahoo.com' },
|
||||
# { 'name': 'AOL', 'url': 'http://openid.aol.com/<username>' },
|
||||
# { 'name': 'Flickr', 'url': 'http://www.flickr.com/<username>' },
|
||||
# { 'name': 'MyOpenID', 'url': 'https://www.myopenid.com' }]
|
||||
# ---------------------------------------------------
|
||||
# Babel config for translations
|
||||
# ---------------------------------------------------
|
||||
# Setup default language
|
||||
BABEL_DEFAULT_LOCALE = "en"
|
||||
# Your application default translation path
|
||||
BABEL_DEFAULT_FOLDER = "translations"
|
||||
# The allowed translation for you app
|
||||
LANGUAGES = {
|
||||
"en": {"flag": "gb", "name": "English"},
|
||||
"pt": {"flag": "pt", "name": "Portuguese"},
|
||||
"pt_BR": {"flag": "br", "name": "Pt Brazil"},
|
||||
"es": {"flag": "es", "name": "Spanish"},
|
||||
"de": {"flag": "de", "name": "German"},
|
||||
"zh": {"flag": "cn", "name": "Chinese"},
|
||||
"ru": {"flag": "ru", "name": "Russian"},
|
||||
"pl": {"flag": "pl", "name": "Polish"},
|
||||
}
|
||||
# ---------------------------------------------------
|
||||
# Image and file configuration
|
||||
# ---------------------------------------------------
|
||||
# The file upload folder, when using models with files
|
||||
UPLOAD_FOLDER = basedir + "/app/static/uploads/"
|
||||
|
||||
# The image upload folder, when using models with images
|
||||
IMG_UPLOAD_FOLDER = basedir + "/app/static/uploads/"
|
||||
|
||||
# The image upload url, when using models with images
|
||||
IMG_UPLOAD_URL = "/static/uploads/"
|
||||
# Setup image size default is (300, 200, True)
|
||||
# IMG_SIZE = (300, 200, True)
|
||||
|
||||
# Theme configuration
|
||||
# these are located on static/appbuilder/css/themes
|
||||
# you can create your own and easily use them placing them on the same dir structure to override
|
||||
# APP_THEME = "bootstrap-theme.css" # default bootstrap
|
||||
# APP_THEME = "cerulean.css"
|
||||
# APP_THEME = "amelia.css"
|
||||
# APP_THEME = "cosmo.css"
|
||||
# APP_THEME = "cyborg.css"
|
||||
# APP_THEME = "flatly.css"
|
||||
# APP_THEME = "journal.css"
|
||||
# APP_THEME = "readable.css"
|
||||
# APP_THEME = "simplex.css"
|
||||
# APP_THEME = "slate.css"
|
||||
# APP_THEME = "spacelab.css"
|
||||
# APP_THEME = "united.css"
|
||||
# APP_THEME = "yeti.css"
|
||||
3
run.py
Normal file
3
run.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
from app import app
|
||||
|
||||
app.run(host="0.0.0.0", port=8080, debug=True)
|
||||
Loading…
Add table
Add a link
Reference in a new issue