diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..19f4038
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+__pycache__/
+venv/
+.idea/
+
diff --git a/app_instance.py b/app_instance.py
new file mode 100644
index 0000000..c773f22
--- /dev/null
+++ b/app_instance.py
@@ -0,0 +1,11 @@
+import responder
+
+# CORS wasn't demoed in the course, but is required to be used from
+# external apps like movie exploder.
+
+cors_params = {
+ 'allow_origins': '*',
+ 'allow_methods': '*',
+}
+
+api = responder.API(cors=True, cors_params=cors_params)
\ No newline at end of file
diff --git a/css/docs.css b/css/docs.css
new file mode 100644
index 0000000..aca49e8
--- /dev/null
+++ b/css/docs.css
@@ -0,0 +1,33 @@
+.request {
+ font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
+ font-weight: bold;
+ border: 1px solid gray;
+ border-radius: 5px;
+ padding: 10px;
+ font-size: 24px;
+}
+
+.get {
+ color: #2b542c;
+ background-color: #beffbd;
+}
+
+.post {
+ color: #ae5900;
+ background-color: #ffc79d;
+}
+
+.response_formats span {
+ font-weight: bold;
+ color: darkred;
+ font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
+}
+
+pre {
+ font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
+}
+
+ul li {
+ font-size: 18px;
+ margin-bottom: 10px;
+}
\ No newline at end of file
diff --git a/css/theme.css b/css/theme.css
new file mode 100644
index 0000000..d913390
--- /dev/null
+++ b/css/theme.css
@@ -0,0 +1,184 @@
+@import url(//fonts.googleapis.com/css?family=Open+Sans:300,400,600,700);
+
+body {
+ font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-weight: 300;
+ color: black;
+ background: white;
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-weight: 300;
+}
+
+p {
+ font-weight: 300;
+}
+
+.font-normal {
+ font-weight: 400;
+}
+
+.font-semi-bold {
+ font-weight: 600;
+}
+
+.font-bold {
+ font-weight: 700;
+}
+
+.starter-template {
+ margin-top: 25px;
+}
+
+.starter-template .content {
+ margin-left: 10px;
+}
+
+.starter-template .content h1 {
+ margin-top: 10px;
+ font-size: 60px;
+}
+
+.starter-template .content h1 .smaller {
+ font-size: 40px;
+}
+
+.starter-template .content .lead {
+ font-size: 25px;
+}
+
+.starter-template .links {
+ float: right;
+ right: 0;
+ margin-top: 125px;
+}
+
+.starter-template .links ul {
+ display: block;
+ padding: 0;
+ margin: 0;
+}
+
+.starter-template .links ul li {
+ list-style: none;
+ display: inline;
+ margin: 0 10px;
+}
+
+.starter-template .links ul li:first-child {
+ margin-left: 0;
+}
+
+.starter-template .links ul li:last-child {
+ margin-right: 0;
+}
+
+.starter-template .links ul li.current-version {
+ font-weight: 400;
+}
+
+.starter-template .links ul li a, a {
+ text-decoration: underline;
+}
+
+.starter-template .links ul li a:hover, a:hover {
+ text-decoration: underline;
+}
+
+.starter-template .links ul li .icon-muted {
+ margin-right: 5px;
+}
+
+.starter-template .copyright {
+ margin-top: 10px;
+ font-size: 0.9em;
+ text-transform: lowercase;
+ float: right;
+ right: 0;
+}
+
+@media (max-width: 1199px) {
+ .starter-template .content h1 {
+ font-size: 45px;
+ }
+
+ .starter-template .content h1 .smaller {
+ font-size: 30px;
+ }
+
+ .starter-template .content .lead {
+ font-size: 20px;
+ }
+}
+
+@media (max-width: 991px) {
+ .starter-template {
+ margin-top: 0;
+ }
+
+ .starter-template .logo {
+ margin: 40px auto;
+ }
+
+ .starter-template .content {
+ margin-left: 0;
+ text-align: center;
+ }
+
+ .starter-template .content h1 {
+ margin-bottom: 20px;
+ }
+
+ .starter-template .links {
+ float: none;
+ text-align: center;
+ margin-top: 60px;
+ }
+
+ .starter-template .copyright {
+ float: none;
+ text-align: center;
+ }
+}
+
+@media (max-width: 767px) {
+ .starter-template .content h1 .smaller {
+ font-size: 25px;
+ display: block;
+ }
+
+ .starter-template .content .lead {
+ font-size: 16px;
+ }
+
+ .starter-template .links {
+ margin-top: 40px;
+ }
+
+ .starter-template .links ul li {
+ display: block;
+ margin: 0;
+ }
+
+ .starter-template .links ul li .icon-muted {
+ display: none;
+ }
+
+ .starter-template .copyright {
+ margin-top: 20px;
+ }
+}
+
+
+.disclaimer {
+ margin-top: 20px;
+ font-style: italic;
+
+}
\ No newline at end of file
diff --git a/routes.py b/routes.py
new file mode 100644
index 0000000..66432f9
--- /dev/null
+++ b/routes.py
@@ -0,0 +1,12 @@
+# noinspection PyUnresolvedReferences
+from app_instance import api
+# noinspection PyUnresolvedReferences
+from views.api_views import *
+# noinspection PyUnresolvedReferences
+from views.home import *
+# noinspection PyUnresolvedReferences
+from views.temp_css import *
+# noinspection PyUnresolvedReferences
+from views.player import *
+
+api.add_route("/static", static=True)
diff --git a/server.py b/server.py
old mode 100644
new mode 100755
index a949963..a715376
--- a/server.py
+++ b/server.py
@@ -1,90 +1,48 @@
-import time
+#!/usr/bin/env python3
+
import random
-
-
-# Karten: 1-13 in Blau, Rot, Gelb, Gruen und 4xZ und 4xN
-
-
-def chunks(lst, n):
- """Yield successive n-sized chunks from lst."""
- for i in range(0, len(lst), n):
- yield lst[i:i + n]
-
-
-class Card:
- def __init__(self, color, value):
- self.color = color
- self.value = value
-
- def __str__(self):
- sc = self.color if self.color else ' '
- sv = str(self.value)
- return sc+' '+sv
-
- def __repr__(self):
- return str(self)
-
-class Player:
- def __init__(self, name, player_id):
- self.name = name
- self.id = player_id
- self.cards = []
-
- def deal_cards(self, cards):
- self.cards = cards
-
- def show_cards(self):
- print(self.cards)
-
-
-class WizGame:
- def __init__(self):
- self.players = []
- self.card_deck = []
-
- def create_deck(self):
- for color in ["blue", "red", "green", "yellow"]:
- for val in range(1,14):
- self.card_deck.append(Card(color, val))
- for _ in range(1,5):
- self.card_deck.append(Card(None, 'Z'))
- for _ in range(1,5):
- self.card_deck.append(Card(None, 'N'))
- print("carddeck:")
- print(self.card_deck)
-
- def deal_cards(self):
- random.shuffle(self.card_deck)
- num_cards = int(len(self.card_deck)/len(self.players))
- print(num_cards)
- cs = list(chunks(self.card_deck, num_cards))
- for i in range(len(self.players)):
- self.players[i].deal_cards(cs[i])
- self.players[i].show_cards()
-
- def add_player(self, name: str, player_id):
- if len(self.players) < 6:
- self.players.append((Player(name, player_id)))
-
-
+import socket
+import responder
+from app_instance import api
+from routes import *
+import wiz_game
def main():
print("main started")
- w = WizGame()
- w.create_deck()
- w.add_player("p1", 1)
- w.add_player("p2", 2)
- w.add_player("p3", 3)
- w.add_player("p4", 4)
- w.deal_cards()
- print("round 2")
- w.deal_cards()
- print("round 3")
- w.deal_cards()
- print("round 4")
- w.deal_cards()
+
+ random.seed()
+
+ wiz_game.the_game.create_deck()
+ wiz_game.the_game.add_player("p1", 1)
+ wiz_game.the_game.add_player("p2", 2)
+ wiz_game.the_game.add_player("p3", 3)
+ wiz_game.the_game.add_player("p4", 4)
+ wiz_game.the_game.deal_cards(4)
+
+ api.run(port=19203, address="127.0.0.1")
exit(0)
+# w.create_deck()
+# w.add_player("p1", 1)
+# w.add_player("p2", 2)
+# w.add_player("p3", 3)
+# w.add_player("p4", 4)
+# w.deal_cards(1)
+# print("round 2")
+# w.deal_cards(2)
+# print("round 3")
+# w.deal_cards(3)
+# print("round 4")
+# w.deal_cards(4)
+# print("round 12")
+# w.deal_cards(12)
+# print("round 13")
+# w.deal_cards(13)
+# print("round 14")
+# w.deal_cards(14)
+# print("round 15")
+# w.deal_cards(15)
+
if __name__ == '__main__':
main()
diff --git a/templates/home/index.html b/templates/home/index.html
new file mode 100644
index 0000000..ee1c4fb
--- /dev/null
+++ b/templates/home/index.html
@@ -0,0 +1,51 @@
+{% extends "/shared/_layout.html" %}
+
+{% block content %}
+
+
+
Gambling Foo A RESTful gaming service
+
+ Play a nice game of cards?
+
+ Endpoints
+
+
+
+
+ Spam Bacon Sausage + Spam
+ Spam Spam Spam Spam Spam
+ Spam Baked Beans Spam
+ Spam Spam + Spam
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/home/player.html b/templates/home/player.html
new file mode 100644
index 0000000..116824f
--- /dev/null
+++ b/templates/home/player.html
@@ -0,0 +1,50 @@
+{% extends "/shared/_layout.html" %}
+
+{% block content %}
+
+
+
Gambling Foo A RESTful gaming service
+
+ Play a nice game of cards?
+
+ Player {{player}} view
+
+
+ {% for card in cards %}
+
+ >card {{loop.index}} is: {{card}}
+
+ {% endfor %}
+
+
+
+
+
+
+ Spam Bacon Sausage + Spam
+ Spam Spam Spam Spam Spam
+ Spam Baked Beans Spam
+ Spam Spam + Spam
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/shared/_layout.html b/templates/shared/_layout.html
new file mode 100644
index 0000000..b30976f
--- /dev/null
+++ b/templates/shared/_layout.html
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+ MovieDB Service
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{% block content %}{% endblock %}
+
+
+
+
+
+ Copyright © Talk Python Training
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/views/api_views.py b/views/api_views.py
new file mode 100644
index 0000000..862e389
--- /dev/null
+++ b/views/api_views.py
@@ -0,0 +1,39 @@
+from responder import Response
+
+from app_instance import api
+
+response_count_max = 10
+
+
+@api.route("/api/search/{keyword}")
+def search_keyword(req, resp, keyword: str):
+ resp.media = {'keyword': keyword, 'hits': "movie_dicts", 'truncated_results': "limited"}
+
+
+@api.route("/api/director/{director_name}")
+def search_director(_, resp, director_name: str):
+ resp.media = {'keyword': director_name, 'hits': "movies_dicts", 'truncated_results': "limited"}
+
+
+@api.route("/api/movie/genre/{genre}")
+def movies_by_genre(_, resp: Response, genre: str):
+ resp.media = {'genre': genre, 'hits': "hits_dicts", 'truncated_results': "limited"}
+
+
+@api.route("/api/movie/{imdb_number}")
+def search_imdb(_, resp, imdb_number: str):
+ resp.media = {'foo': "bar"}
+
+
+@api.route("/api/movie/top")
+def top_movies(_, resp: Response):
+ resp.media = {'keyword': "keyword", 'hits': "hits_dicts", 'truncated_results': "limited"}
+
+
+@api.route("/api/movie/genre/all")
+def all_genres(_, resp: Response):
+ resp.media = {"all": "stuff"}
+
+@api.route("/api/shuffle")
+def cards_shuffle(_, resp: Response):
+ resp.media = {"shuffled": "done"}
\ No newline at end of file
diff --git a/views/home.py b/views/home.py
new file mode 100644
index 0000000..87636b5
--- /dev/null
+++ b/views/home.py
@@ -0,0 +1,6 @@
+from app_instance import api
+
+
+@api.route("/")
+def index(req, resp):
+ resp.content = api.template('home/index.html')
diff --git a/views/player.py b/views/player.py
new file mode 100644
index 0000000..6e2da52
--- /dev/null
+++ b/views/player.py
@@ -0,0 +1,11 @@
+from app_instance import api
+
+from wiz_game import the_game
+
+
+@api.route("/player/{player}")
+def index(req, resp, player: str):
+ p = int(player)
+ print(p)
+ print(the_game.players)
+ resp.content = api.template('home/player.html', player=player, cards=the_game.players[p].cards)
diff --git a/views/temp_css.py b/views/temp_css.py
new file mode 100644
index 0000000..35ee358
--- /dev/null
+++ b/views/temp_css.py
@@ -0,0 +1,22 @@
+import os
+
+from app_instance import api
+
+
+# This sucks. But at the moment I'm publishing this code / video
+# Responder has developed a bug where it cannot serve static files
+# See https://github.com/kennethreitz/responder/issues/337
+#
+# This is just a work around so you all can enjoy the course.
+
+@api.route("/css/{file}")
+def css(req, resp, file):
+ resp.headers['Content-Type'] = 'text/css'
+ full_file = os.path.join(
+ os.path.dirname(__file__),
+ '..',
+ 'css',
+ file
+ )
+ with open(full_file, encoding='utf-8') as fin:
+ resp.content = fin.read()
diff --git a/wiz_game.py b/wiz_game.py
new file mode 100644
index 0000000..30c1e1f
--- /dev/null
+++ b/wiz_game.py
@@ -0,0 +1,83 @@
+
+import random
+
+def chunks(lst, n):
+ """Yield successive n-sized chunks from lst."""
+ for i in range(0, len(lst), n):
+ yield lst[i:i + n]
+
+
+class Card:
+ def __init__(self, color, value):
+ self.color = color
+ self.value = value
+
+ def __str__(self):
+ sc = self.color if self.color else ' '
+ sv = str(self.value)
+ return sc+' '+sv
+
+ def __repr__(self):
+ return str(self)
+
+
+class Player:
+ def __init__(self, name, player_id):
+ self.name = name
+ self.id = player_id
+ self.cards = []
+
+ def set_cards(self, cards):
+ self.cards = cards
+
+ def show_cards(self):
+ print(self.cards)
+
+
+class WizGame:
+ def __init__(self):
+ self.players = []
+ self.card_deck = []
+ self.trump_color = None
+
+ def create_deck(self):
+ for color in ["b", "r", "g", "y"]:
+ for val in range(1,14):
+ self.card_deck.append(Card(color, val))
+ for _ in range(1,5):
+ self.card_deck.append(Card(None, 'Z'))
+ for _ in range(1,5):
+ self.card_deck.append(Card(None, 'N'))
+ print("carddeck:")
+ print(self.card_deck)
+
+ def set_trump_color(self, card: Card):
+ if card.color:
+ self.trump_color = card.color
+ elif card.value == 'Z':
+ self.trump_color = 'choose'
+ else:
+ self.trump_color = None
+
+ def deal_cards(self, cards_per_player):
+ random.shuffle(self.card_deck)
+ cs = list(chunks(self.card_deck, cards_per_player))
+ for idx,p in enumerate(self.players):
+ p.set_cards(cs[idx])
+ p.show_cards()
+ if len(cs) > len(self.players):
+ cc = cs[len(self.players)]
+ c = cc[0]
+ print("trump card: {}".format(c))
+ self.set_trump_color(c)
+ else:
+ self.trump_color = None
+ print("trump color: {}".format(self.trump_color))
+
+ def add_player(self, name: str, player_id):
+ if len(self.players) < 6:
+ self.players.append((Player(name, player_id)))
+
+
+the_game = WizGame()
+