model.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. import random
  2. import re
  3. import sqlite3 as db
  4. import sys
  5. import uuid
  6. import db_setup
  7. from game import CURRENCY_NAME
  8. from util import debug, chars
  9. connection = None
  10. cursor = None
  11. db_name = None
  12. def query_save_name():
  13. global db_name
  14. if debug:
  15. db_name = 'test.db'
  16. return
  17. while True:
  18. save_name = input('Name of the savegame: ')
  19. if re.match(r"[A-Za-z0-9.-]{0,50}", save_name):
  20. db_name = save_name + '.db'
  21. return
  22. else:
  23. print('Must match "[A-Za-z0-9.-]{0,50}"')
  24. def connect(reconnect=False):
  25. global connection
  26. global cursor
  27. global db_name
  28. if reconnect:
  29. connection.commit()
  30. connection.close()
  31. cursor = None
  32. connection = None
  33. db_name = None
  34. if connection is None or cursor is None:
  35. query_save_name()
  36. try:
  37. connection = db.connect(db_name)
  38. cursor = connection.cursor()
  39. except db.Error as e:
  40. print("Database error %s:" % e.args[0])
  41. sys.exit(1)
  42. # finally:
  43. # if con is not None:
  44. # con.close()
  45. def setup():
  46. connect()
  47. db_setup.setup(cursor)
  48. connection.commit()
  49. def login(username, password):
  50. connect()
  51. # do not allow login as bank
  52. if password == '':
  53. return None
  54. cursor.execute('''
  55. SELECT rowid
  56. FROM users
  57. WHERE username = ?
  58. AND password = ?
  59. ''', (username, password))
  60. user_id = cursor.fetchone()
  61. if user_id:
  62. return new_session(user_id)
  63. else:
  64. return None
  65. def register(username, password, game_key):
  66. connect()
  67. if username == '':
  68. return False
  69. if password == '':
  70. return False
  71. cursor.execute('''
  72. INSERT INTO users
  73. (username, password)
  74. VALUES (? , ?)
  75. ''', (username, password))
  76. own(get_user_id_by_name(username), CURRENCY_NAME)
  77. if game_key != '':
  78. if valid_key(game_key):
  79. activate_key(game_key, get_user_id_by_name(username))
  80. return True
  81. def own(user_id, ownable_name):
  82. cursor.execute('''
  83. WITH one_ownable_id AS (SELECT rowid FROM ownables WHERE name = ?),
  84. one_user_id AS (SELECT ?)
  85. INSERT INTO ownership (user_id, ownable_id)
  86. SELECT *
  87. FROM one_user_id, one_ownable_id
  88. WHERE NOT EXISTS (
  89. SELECT * FROM ownership
  90. WHERE ownership.user_id IN one_user_id
  91. AND ownership.ownable_id IN one_ownable_id
  92. )
  93. ''', (ownable_name, user_id,))
  94. def send_ownable(from_user_id, to_user_id, ownable_name, amount):
  95. connect()
  96. if amount < 0:
  97. return False
  98. if from_user_id != bank_id():
  99. cursor.execute('''
  100. UPDATE ownership
  101. SET amount = amount - ?
  102. WHERE user_id = ?
  103. AND ownable_id = (SELECT rowid FROM ownables WHERE name = ?)
  104. ''', (amount, from_user_id, ownable_name,))
  105. if not cursor.fetchone():
  106. return False
  107. cursor.execute('''
  108. UPDATE ownership
  109. SET amount = amount + ?
  110. WHERE user_id = ?
  111. AND ownable_id = (SELECT rowid FROM ownables WHERE name = ?)
  112. ''', (amount, to_user_id, ownable_name))
  113. if cursor.rowcount == 0:
  114. return False
  115. return True
  116. def valid_key(key):
  117. connect()
  118. cursor.execute('''
  119. SELECT key
  120. FROM keys
  121. WHERE used_by_user_id IS NULL
  122. AND key = ?
  123. ''', (key,))
  124. if cursor.fetchone():
  125. return True
  126. else:
  127. return False
  128. def new_session(user_id):
  129. connect()
  130. session_id = str(uuid.uuid4())
  131. cursor.execute('''
  132. INSERT INTO SESSIONS
  133. (user_id, session_id)
  134. VALUES (? , ?)
  135. ''', (user_id[0], session_id))
  136. return session_id
  137. def save_key(key):
  138. connect()
  139. cursor.execute('''
  140. INSERT INTO keys
  141. (key)
  142. VALUES (?)
  143. ''', (key,))
  144. def drop_old_sessions():
  145. connect()
  146. cursor.execute('''
  147. DELETE FROM sessions s1
  148. WHERE
  149. (SELECT COUNT(*) as newer
  150. FROM sessions s2
  151. WHERE s1.user_id = s2.user_id
  152. AND s1.rowid < s2.rowid) >= 10
  153. ''')
  154. def user_exists(username):
  155. connect()
  156. cursor.execute('''
  157. SELECT rowid
  158. FROM users
  159. WHERE username = ?
  160. ''', (username,))
  161. if cursor.fetchone():
  162. return True
  163. else:
  164. return False
  165. def unused_keys():
  166. connect()
  167. cursor.execute('''
  168. SELECT key
  169. FROM keys
  170. WHERE used_by_user_id IS NULL
  171. ''')
  172. return [str(key[0]).strip().upper() for key in cursor.fetchall()]
  173. def get_user_id_by_session_id(session_id):
  174. connect()
  175. cursor.execute('''
  176. SELECT users.rowid
  177. FROM sessions, users
  178. WHERE sessions.session_id = ?
  179. AND users.rowid = sessions.user_id
  180. ''', (session_id,))
  181. ids = cursor.fetchone()
  182. if ids is None:
  183. return False
  184. return ids[0]
  185. def get_user_id_by_name(username):
  186. connect()
  187. cursor.execute('''
  188. SELECT users.rowid
  189. FROM users
  190. WHERE username = ?
  191. ''', (username,))
  192. return cursor.fetchone()[0]
  193. def get_user_ownership(user_id):
  194. connect()
  195. cursor.execute('''
  196. SELECT ownables.name, ownership.amount
  197. FROM ownership, ownables
  198. WHERE user_id = ?
  199. AND ownership.ownable_id = ownables.rowid
  200. ''', (user_id,))
  201. return cursor.fetchall()
  202. def activate_key(key, user_id):
  203. connect()
  204. cursor.execute('''
  205. UPDATE keys
  206. SET used_by_user_id = ?
  207. WHERE used_by_user_id IS NULL
  208. AND key = ?
  209. ''', (user_id, key,))
  210. if cursor.rowcount == 0:
  211. raise AssertionError
  212. send_ownable(bank_id(), user_id, CURRENCY_NAME, 1000)
  213. def bank_id():
  214. connect()
  215. cursor.execute('''
  216. SELECT users.rowid
  217. FROM users
  218. WHERE username = 'bank'
  219. ''')
  220. return cursor.fetchone()[0]
  221. def valid_session_id(session_id):
  222. connect()
  223. cursor.execute('''
  224. SELECT rowid
  225. FROM sessions
  226. WHERE session_id = ?
  227. ''', (session_id,))
  228. if cursor.fetchone():
  229. return True
  230. else:
  231. return False
  232. def get_user_orders(user_id):
  233. connect()
  234. cursor.execute('''
  235. SELECT
  236. orders.buy,
  237. ownables.name,
  238. orders.ordered_amount - orders.executed_amount,
  239. orders."limit",
  240. orders.stop_loss,
  241. orders.ordered_amount
  242. FROM orders, ownables, ownership
  243. WHERE ownership.user_id = ?
  244. AND ownership.ownable_id = ownables.rowid
  245. AND orders.ownership_id = ownership.rowid
  246. ORDER BY orders.buy, ownables.name
  247. ''', (user_id,))
  248. return cursor.fetchall()
  249. def sell_ordered_amount(user_id, ownable_id):
  250. connect()
  251. # if ownable_id == currency_id():
  252. # return 0
  253. cursor.execute('''
  254. SELECT SUM(orders.ordered_amount - orders.executed_amount)
  255. FROM orders, ownership
  256. WHERE ownership.rowid = orders.ownership_id
  257. AND ownership.user_id = ?
  258. AND ownership.ownable_id = ?
  259. AND NOT orders.buy
  260. ''', (user_id, ownable_id))
  261. return cursor.fetchone()[0]
  262. def user_owns_at_least(amount, user_id, ownable_id):
  263. connect()
  264. cursor.execute('''
  265. SELECT rowid
  266. FROM ownership
  267. WHERE user_id = ?
  268. AND ownable_id = ?
  269. AND amount - ? >= ?
  270. ''', (user_id, ownable_id, sell_ordered_amount(user_id, ownable_id), amount))
  271. if cursor.fetchone():
  272. return True
  273. else:
  274. return False
  275. def news():
  276. connect()
  277. cursor.execute('''
  278. SELECT *
  279. FROM news
  280. ORDER BY dt
  281. LIMIT 20
  282. ''')
  283. return cursor.fetchall()
  284. def ownable_name_exists(name):
  285. connect()
  286. cursor.execute('''
  287. SELECT rowid
  288. FROM ownables
  289. WHERE name = ?
  290. ''', (name,))
  291. if cursor.fetchone():
  292. return True
  293. else:
  294. return False
  295. def new_stock(name=None):
  296. connect()
  297. while name is None:
  298. name = ''.join(random.choice(chars) for _ in range(6))
  299. if ownable_name_exists(name):
  300. name = None
  301. cursor.execute('''
  302. INSERT INTO ownables(name)
  303. VALUES (?)
  304. ''', (name,))
  305. return name
  306. def new_stocks(count=1):
  307. return [new_stock() for _ in range(count)]
  308. def ownable_id_by_name(ownable_name):
  309. connect()
  310. cursor.execute('''
  311. SELECT rowid
  312. FROM ownables
  313. WHERE name = ?
  314. ''', (ownable_name,))
  315. return cursor.fetchone()[0]
  316. def get_ownership_id(ownable_id, user_id):
  317. connect()
  318. cursor.execute('''
  319. SELECT rowid
  320. FROM ownership
  321. WHERE ownable_id = ?
  322. AND user_id = ?
  323. ''', (ownable_id, user_id,))
  324. return cursor.fetchone()[0]
  325. def currency_id():
  326. connect()
  327. cursor.execute('''
  328. SELECT rowid
  329. FROM ownables
  330. WHERE name = ?
  331. ''', (CURRENCY_NAME,))
  332. return cursor.fetchone()[0]
  333. def execute_orders():
  334. connect()
  335. while True:
  336. executed_any = False
  337. # TODO execute one orders
  338. # TODO trigger stop loss orders
  339. if not executed_any:
  340. return
  341. def place_order(buy, ownership_id, limit, stop_loss, amount):
  342. connect()
  343. cursor.execute('''
  344. INSERT INTO orders
  345. (buy, ownership_id, "limit", stop_loss, ordered_amount)
  346. VALUES (?, ?, ?, ?, ?)
  347. ''', (buy, ownership_id, limit, stop_loss, amount))
  348. execute_orders()
  349. return True