瀏覽代碼

further work on stocks

Eren Yilmaz 6 年之前
父節點
當前提交
176f612737
共有 10 個文件被更改,包括 172 次插入37 次删除
  1. 4 3
      admin_console.py
  2. 8 7
      client.py
  3. 2 3
      client_controller.py
  4. 2 2
      connection.py
  5. 38 3
      db_setup.py
  6. 1 1
      game.py
  7. 109 11
      model.py
  8. 1 1
      server.py
  9. 5 6
      server_controller.py
  10. 2 0
      util.py

+ 4 - 3
admin_console.py

@@ -1,14 +1,14 @@
 import random
 
 import model
+from util import chars
 
 
 def generate_keys(count=1):
     # source https://stackoverflow.com/questions/17049308/python-3-3-serial-key-generator-list-problems
-    seq = "ABCDFGHJIKLMNPQRSTUVWXYZ123456789"
 
     for i in range(count):
-        key = '-'.join(''.join(random.choice(seq) for _ in range(5)) for _ in range(5))
+        key = '-'.join(''.join(random.choice(chars) for _ in range(5)) for _ in range(5))
         model.save_key(key)
         print(key)
 
@@ -24,7 +24,8 @@ def cleanup():
 
 
 if __name__ == '__main__':
-    generate_keys(count=1)
+    # generate_keys(count=1)
+    print(model.new_stocks(count=3))
     # unused_keys
 
     cleanup()

+ 8 - 7
client.py

@@ -6,7 +6,7 @@ import client_controller
 from util import debug
 
 
-def fake_loading_bar(msg,delay=0.100):
+def fake_loading_bar(msg, delay=0.100):
     if len(msg) >= 32:
         raise AssertionError('Loading bar label too large')
     msg += ': '
@@ -50,14 +50,14 @@ To display an overview of available commands type \'help\'.
 ''')
 
 
-allowed_commands = ['login',
+allowed_commands = ['help',
+                    'login',
                     'register',
-                    'help',
                     'depot',
-                    'activate_key',
-                    'buy',
                     'orders',
-                    'news']
+                    'news',
+                    'activate_key',
+                    'buy']
 
 
 def one_command():
@@ -72,6 +72,7 @@ def one_command():
             print('Invalid command:', cmd[0])
         else:
             method_to_call = getattr(client_controller, cmd[0])
+            # noinspection PyBroadException
             try:
                 method_to_call(*cmd[1:])
             except TypeError:
@@ -85,4 +86,4 @@ if __name__ == '__main__':
     welcome()
 
     while True:
-        one_command()
+        one_command()

+ 2 - 3
client_controller.py

@@ -99,7 +99,7 @@ def activate_key(key=''):
     if key == '':
         print('Invalid key.')
 
-    response = client_request('activate_key', {"session_id": connection.session_id, 'key':key })
+    response = client_request('activate_key', {"session_id": connection.session_id, 'key': key})
     if 'error_message' in response:
         print('Key activation failed with message:', response['error_message'])
 
@@ -117,7 +117,6 @@ def buy(amount=None, object_name=None, limit='', stop_loss=''):
     if object_name is None:  # TODO list some available objects
         object_name = input('Name of object to buy: ')
     if amount is None:
-        print('Entering a game key may get you some money or other useful stuff.')
         amount = input('Amount: ')
     if limit != '':
         set_limit = yn_dialog('Do you want to place a limit?')
@@ -126,7 +125,7 @@ def buy(amount=None, object_name=None, limit='', stop_loss=''):
             stop_loss = yn_dialog('Is this a stop-loss limit?')
     response = client_request('order', {"buy": True,
                                         "session_id": connection.session_id,
-                                        "amount":amount,
+                                        "amount": amount,
                                         "ownable": object_name,
                                         "limit": limit,
                                         "stop_loss": stop_loss})

+ 2 - 2
connection.py

@@ -11,10 +11,10 @@ json_headers = {'Content-type': 'application/json'}
 
 def client_request(route, data):
     r = requests.post(host + '/' + route, data=json.dumps(data),
-                         headers=json_headers)
+                      headers=json_headers)
     if debug:
         print('Request returned: ' + str(r.content))
     return r.json()
 
 
-session_id = None
+session_id = None

+ 38 - 3
db_setup.py

@@ -23,8 +23,7 @@ def setup(cursor):
                 ''')
     cursor.execute('''
                 CREATE TABLE IF NOT EXISTS ownables(
-                    name VARCHAR(10) UNIQUE NOT NULL, 
-                    total_amount CURRENCY NOT NULL DEFAULT 0)
+                    name VARCHAR(10) UNIQUE NOT NULL)
                 ''')
     cursor.execute('''
                 CREATE TABLE IF NOT EXISTS ownership(
@@ -50,7 +49,7 @@ def setup(cursor):
                     "limit" CURRENCY,
                     stop_loss BOOLEAN,
                     ordered_amount CURRENCY,
-                    executed_amount CURRENCY,
+                    executed_amount CURRENCY DEFAULT 0,
                     FOREIGN KEY (ownership_id) REFERENCES ownership(rowid)
                 )
                 ''')
@@ -95,6 +94,42 @@ def setup(cursor):
                     SELECT RAISE(ROLLBACK, 'Can not own an amount less than 0.');
                 END
                 ''')
+    cursor.execute('''
+                CREATE TRIGGER IF NOT EXISTS order_limit_not_negative_after_insert
+                AFTER INSERT
+                ON orders
+                WHEN "limit" IS NOT NULL AND "limit" < 0
+                BEGIN
+                    SELECT RAISE(ROLLBACK, 'Can not set a limit less than 0.');
+                END
+                ''')
+    cursor.execute('''
+                CREATE TRIGGER IF NOT EXISTS order_limit_not_negative_after_update
+                AFTER UPDATE
+                ON orders
+                WHEN "limit" IS NOT NULL AND "limit" < 0
+                BEGIN
+                    SELECT RAISE(ROLLBACK, 'Can not set a limit less than 0.');
+                END
+                ''')
+    cursor.execute('''
+                CREATE TRIGGER IF NOT EXISTS order_amount_not_negative_after_insert
+                AFTER INSERT
+                ON orders
+                WHEN ordered_amount <= 0 OR executed_amount < 0
+                BEGIN
+                    SELECT RAISE(ROLLBACK, 'Can not order 0 or less.');
+                END
+                ''')
+    cursor.execute('''
+                CREATE TRIGGER IF NOT EXISTS order_amount_not_negative_after_update
+                AFTER UPDATE
+                ON orders
+                WHEN ordered_amount <= 0 OR executed_amount < 0
+                BEGIN
+                    SELECT RAISE(ROLLBACK, 'Can not order 0 or less.');
+                END
+                ''')
 
     if replace:  # TODO also seed new databases
         print(' - Seeding initial data...')

+ 1 - 1
game.py

@@ -1 +1 @@
-CURRENCY_NAME = 'Kollar'
+CURRENCY_NAME = 'Kollar'

+ 109 - 11
model.py

@@ -1,3 +1,4 @@
+import random
 import re
 import sqlite3 as db
 import sys
@@ -5,7 +6,7 @@ import uuid
 
 import db_setup
 from game import CURRENCY_NAME
-from util import debug
+from util import debug, chars
 
 connection = None
 cursor = None
@@ -102,15 +103,15 @@ def register(username, password, game_key):
 
 def own(user_id, ownable_name):
     cursor.execute('''
-                WITH ownableid AS (SELECT rowid FROM ownables WHERE name = ?),
-                     userid AS (SELECT ?)
+                WITH one_ownable_id AS (SELECT rowid FROM ownables WHERE name = ?),
+                     one_user_id AS (SELECT ?)
                 INSERT INTO ownership (user_id, ownable_id)
                 SELECT *
-                FROM userid, ownableid
+                FROM one_user_id, one_ownable_id
                 WHERE NOT EXISTS (
                     SELECT * FROM ownership
-                    WHERE ownership.user_id IN userid
-                    AND ownership.ownable_id IN ownableid
+                    WHERE ownership.user_id IN one_user_id
+                    AND ownership.ownable_id IN one_ownable_id
                 )
                 ''', (ownable_name, user_id,))
 
@@ -328,7 +329,7 @@ def get_user_orders(user_id):
 def sell_ordered_amount(user_id, ownable_id):
     connect()
 
-    # if ownable_id == kollar_id():
+    # if ownable_id == currency_id():
     #     return 0
 
     cursor.execute('''
@@ -347,11 +348,11 @@ def user_owns_at_least(amount, user_id, ownable_id):
     connect()
 
     cursor.execute('''
-                SELECT users.rowid
+                SELECT rowid
                 FROM ownership
-                AND ownership.user_id = ?
-                AND ownership.ownable_id = ?
-                AND ownership.amount - ? >= ?
+                WHERE user_id = ?
+                AND ownable_id = ?
+                AND amount - ? >= ?
                 ''', (user_id, ownable_id, sell_ordered_amount(user_id, ownable_id), amount))
 
     if cursor.fetchone():
@@ -371,3 +372,100 @@ def news():
         ''')
 
     return cursor.fetchall()
+
+
+def ownable_name_exists(name):
+    connect()
+
+    cursor.execute('''
+                SELECT rowid
+                FROM ownables
+                WHERE name = ?
+                ''', (name,))
+
+    if cursor.fetchone():
+        return True
+    else:
+        return False
+
+
+def new_stock(name=None):
+    connect()
+
+    while name is None:
+        name = ''.join(random.choice(chars) for _ in range(6))
+        if ownable_name_exists(name):
+            name = None
+
+    cursor.execute('''
+        INSERT INTO ownables(name)
+        VALUES (?)
+        ''', (name,))
+    return name
+
+
+def new_stocks(count=1):
+    return [new_stock() for _ in range(count)]
+
+
+def ownable_id_by_name(ownable_name):
+    connect()
+
+    cursor.execute('''
+        SELECT rowid
+        FROM ownables
+        WHERE name = ?
+        ''', (ownable_name,))
+
+    return cursor.fetchone()[0]
+
+
+def get_ownership_id(ownable_id, user_id):
+    connect()
+
+    cursor.execute('''
+        SELECT rowid
+        FROM ownership
+        WHERE ownable_id = ?
+        AND user_id = ?
+        ''', (ownable_id, user_id,))
+
+    return cursor.fetchone()[0]
+
+
+def currency_id():
+    connect()
+
+    cursor.execute('''
+        SELECT rowid
+        FROM ownables
+        WHERE name = ?
+        ''', (CURRENCY_NAME,))
+
+    return cursor.fetchone()[0]
+
+
+def execute_orders():
+    connect()
+    while True:
+        executed_any = False
+
+        # TODO execute one orders
+
+        # TODO trigger stop loss orders
+
+        if not executed_any:
+            return
+
+
+def place_order(buy, ownership_id, limit, stop_loss, amount):
+    connect()
+
+    cursor.execute('''
+                INSERT INTO orders 
+                (buy, ownership_id, "limit", stop_loss, ordered_amount)
+                VALUES (?, ?, ?, ?, ?)
+                ''', (buy, ownership_id, limit, stop_loss, amount))
+
+    execute_orders()
+    return True

+ 1 - 1
server.py

@@ -3,7 +3,7 @@ import sqlite3
 import connection
 import server_controller
 import model
-from bottle import run, request, response, route
+from bottle import run, response, route
 
 from server_controller import not_found
 from util import debug

+ 5 - 6
server_controller.py

@@ -74,6 +74,8 @@ def order():
     missing = missing_attributes(['buy', 'session_id', 'amount', 'ownable'])
     if missing:
         return bad_request(missing)
+    if not model.ownable_name_exists(request.json['ownable']):
+        return bad_request('This kind of object can not be ordered.')
     buy = request.json['buy']
     sell = not buy
     session_id = request.json['session_id']
@@ -81,8 +83,8 @@ def order():
     ownable_name = request.json['ownable']
     ownable_id = model.ownable_id_by_name(ownable_name)
     user_id = model.get_user_id_by_session_id(session_id)
-    model.own(user_id, ownable_id)
-    ownership_id = model.ownership_id(ownable_id, user_id)
+    model.own(user_id, ownable_name)
+    ownership_id = model.get_ownership_id(ownable_id, user_id)
 
     limit = None
     if 'limit' in request.json:
@@ -92,11 +94,8 @@ def order():
     if sell:
         if not model.user_owns_at_least(user_id, amount, ownership_id):
             return bad_request('You can not sell more than you own.')
-    if buy:
-        if not model.user_owns_at_least(user_id, amount, model.kollar_id()):
-            return bad_request('You do not have the money to buy that much.')
 
-    model.place_order(buy, user_id, ownable_id, limit, stop_loss, amount)
+    model.place_order(buy, ownership_id, limit, stop_loss, amount)
     return {'message': "Order placed."}
 
 

+ 2 - 0
util.py

@@ -1 +1,3 @@
 debug = True
+# noinspection SpellCheckingInspection
+chars = "ABCDFGHJIKLMNPQRSTUVWXYZ123456789"