diff --git a/README.md b/README.md index 734affc..86c7ab6 100644 --- a/README.md +++ b/README.md @@ -84,3 +84,6 @@ The base for building games is: * Enhance the Challenge class - abstract away writing information? * Implement dependencies / providers for challenges * Add an easy to use CLI (Steven might like click) +* Write nice code to easily retrieve points per user +* Sort high score +* Maybe store all user information in one JSON object? diff --git a/server.py b/server.py index e34bf66..f1917b3 100644 --- a/server.py +++ b/server.py @@ -6,7 +6,6 @@ import ipaddress import random import sys import etcd -import ungleichapi import json import datetime @@ -28,6 +27,7 @@ class Challenge(object): points = 0 provides = [] requires = [] + description = None def __init__(self, etcdclient): self.client = etcdclient @@ -38,14 +38,24 @@ class Challenge(object): parser.add_argument(arg, required=True) return parser.parse_args() + def game(self): + if request.method == 'GET': + return self.describe() + if request.method == 'POST': + return self.solve() + def describe(self): return self.description def save_points(self, user): """ should be called when the challenge was solved successfully""" - path = "/ungleichgame/v1/{}/challenges/{}/points".format(user, self.__name__) - self.client.write(path, self.points) + key = "points/{}".format(user, type(self).__name__) + self.set_user_key(user, key, self.points) + + def set_user_key(self, user, key, value): + path = "/ungleichgame/v1/user/{}/{}".format(user, key) + self.client.write(path, value) def solve(self): """ Needs to be implemented per challenge """ @@ -64,11 +74,12 @@ and to setup services listening on these IPv6 addresses. Submit your network with the "network" parameter. """ def solve(self): - self.require_args("user", "network") + args = self.require_args("user", "network") + network = args['network'] + user = args['user'] try: - net = ipaddress.IPv6Network(args['network']) - network = args['network'] + net = ipaddress.IPv6Network(network) except Exception as e: return Response(status=400, response="Cannot register network {}: {}".format(network, e)) @@ -76,11 +87,10 @@ Submit your network with the "network" parameter. return Response(status=400, response="{} mask is not /64 - please use a /64 network".format(net)) # Save network - self.client.write("/ungleichgame/v1/{}/network".format(user), network) - self.save_points(args['user']) - - return json.dumps("All good, go to /level/1 to start with level 1! - {}".format(data.value)) + self.set_user_key(user, "network", network) + self.save_points(user) + return "Network {} registered, have fun with the next challenge!".format(network) class Game(object): @@ -88,8 +98,8 @@ class Game(object): self.client = etcdclient self.app = Flask(name) - self.app.add_url_rule('/', 'highscore', self.highscore) - self.app.add_url_rule('/highscore', 'highscore', self.highscore) + self.app.add_url_rule('/', 'index', self.index) + self.app.add_url_rule('/points', 'points', self.points) # etcd paths are below here self.etcbase = etcbase @@ -98,13 +108,23 @@ class Game(object): # Automate this challenges = [ RegisterNet ] + self.app.add_url_rule('/challenge', 'list_of_challenges', self.list_of_challenges) + self.app.add_url_rule('/challenge/', 'list_of_challenges', self.list_of_challenges) + + self.challenge_names = [] for challenge in challenges: c = challenge(self.client) - name = c.__name__ + name = type(c).__name__ + self.challenge_names.append(name) path = "/challenge/{}".format(name) - self.app.add_url_rule(path, name, c.describe, methods=['GET']) - self.app.add_url_rule(path, name, c.solve, methods=['POST']) + self.app.add_url_rule(path, name, c.game, methods=['GET', 'POST']) + + + def list_of_challenges(self): + return """The following challenges are available on this server: +{} +""".format("\n".join(self.challenge_names)) def read_etcd(self, path, recursive=False): @@ -117,48 +137,51 @@ class Game(object): return data - def get_highscore(self, username=None): + def get_points(self): """ Returns a dict['username'] = points """ - all_users = {} - highscore = {} + user_points = {} - print("getting high") + path = "{}/".format(self.userbase) + users = self.client.get(path) - if username: - path = "{}/{}".format(self.userbase, username) - user = self.read_etcd(path) - if user: - all_users[username] = user - else: - path = "{}/".format(self.userbase) - users = self.read_etcd(path, recursive=True) - print("reading from {}".format(path)) - if users: - for child in users.children: - print("adding user {} {} = {}".format(child, child.key, child.value)) - all_users[child.key] = child.value + if users: + print(users) + for user in users.children: + username= user.key # needs to be FIXED + user_points[username] = 0 - for k, v in all_users.items(): - # Ignore all kind of errors - just add the ones that work - try: - highscore[k] = json.loads(v)['points'] - print("f?") - except Exception as e: - print(e) + point_path = "{}/points".format(user.key) + points = self.read_etcd(point_path, recursive=True) - return highscore + for challenge in points.children: + user_points[username] += int(challenge.value) - def highscore(self): - point_list = self.get_highscore() + return user_points + + def index(self): + points = self.points() + + return """Welcome to the game server! + +Current point list is: +{} + +For more information visit + +https://code.ungleich.ch/nico/ungleich-game +""".format(points) + + def points(self): + point_list = self.get_points() res = [] if not point_list: return Response("No winners yet!") for k, v in point_list.items(): - res.append("

{} has {} points

".format(k, v)) + res.append("{} has {} points".format(k, v)) - return Response("\n".join(res)) + return "\n".join(res) # def get_ip_address():