DotaNoobs main site.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

304 lines
12 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. import simplejson as json
  2. from datetime import datetime
  3. from random import choice
  4. from flask.ext.sqlalchemy import SQLAlchemy
  5. from sqlalchemy.ext.mutable import Mutable
  6. import board
  7. from app import db, app
  8. from utils import parse_valve_heropedia, complete_hero_data, API_DATA
  9. # Model independant get_or_create
  10. def get_or_create_instance(session, model, **kwargs):
  11. instance = session.query(model).filter_by(**kwargs).first()
  12. if instance:
  13. return instance
  14. else:
  15. instance = model(**kwargs)
  16. session.add(instance)
  17. return instance
  18. # Get a little of that Mongoness back
  19. class Json(db.TypeDecorator):
  20. impl = db.Text
  21. def process_bind_param(self, value, dialect):
  22. if value is not None:
  23. value = json.dumps(value)
  24. return value
  25. def process_result_value(self, value, dialect):
  26. if value is not None:
  27. value = json.loads(value)
  28. return value
  29. # Mongoness factor - phase 2
  30. class MutableDict(Mutable, dict):
  31. @classmethod
  32. def coerce(cls, key, value):
  33. if not isinstance(value, MutableDict):
  34. if isinstance(value, dict):
  35. return MutableDict(value)
  36. return Mutable.coerce(key,value)
  37. else:
  38. return value
  39. def __delitem__(self, key):
  40. dict.__delitem__(self, key)
  41. self.changed()
  42. def __setitem__(self, key, value):
  43. dict.__setitem__(self, key, value)
  44. self.changed()
  45. def __getstate__(self):
  46. return dict(self)
  47. def __setstate__(self, state):
  48. self.update(self)
  49. class User(db.Model):
  50. id = db.Column(db.Integer, primary_key=True)
  51. steam_id = db.Column(db.String(40), unique=True)
  52. forum_id = db.Column(db.Integer)
  53. teamspeak_id = db.Column(db.String(200), unique=True)
  54. nickname = db.Column(db.String(80))
  55. avatar = db.Column(db.String(255))
  56. admin = db.Column(db.Boolean)
  57. bio_text = db.Column(db.String(4096))
  58. created = db.Column(db.DateTime)
  59. last_seen = db.Column(db.DateTime)
  60. twitch = db.Column(db.String(60))
  61. random_heroes = db.Column(MutableDict.as_mutable(Json))
  62. az_completions = db.Column(db.Integer)
  63. public = db.Column(db.Boolean)
  64. logo = db.Column(db.Boolean)
  65. points_from_events = db.Column(db.Integer)
  66. points_from_ts3 = db.Column(db.Integer)
  67. points_from_forum = db.Column(db.Integer)
  68. ts3_starttime = db.Column(db.DateTime)
  69. ts3_endtime = db.Column(db.DateTime)
  70. ts3_rewardtime = db.Column(db.DateTime)
  71. ts3_connections = db.Column(MutableDict.as_mutable(Json))
  72. last_post_reward = db.Column(db.Integer)
  73. @classmethod
  74. def get_or_create(self, steam_id):
  75. return get_or_create_instance(db.session, User, steam_id=steam_id)
  76. def __init__(self, steam_id):
  77. self.steam_id = steam_id
  78. self.random_heroes = {'current':None, 'completed':[]}
  79. self.az_completions = 0
  80. self.created = datetime.utcnow()
  81. self.last_seen = datetime.utcnow()
  82. self.bio_text = None
  83. self.points_from_events = 0
  84. self.points_from_ts3 = 0
  85. self.points_from_forum = 0
  86. self.admin = False
  87. self.public = True
  88. self.biglogo = True
  89. @property
  90. def random_hero(self):
  91. if not self.random_heroes['current']:
  92. heroes = []
  93. for (tavern_name, tavern) in parse_valve_heropedia():
  94. heroes.extend([complete_hero_data('name', entry['name']) for entry in tavern if entry['name'] not in self.random_heroes['completed']])
  95. if heroes:
  96. self.random_heroes['current'] = choice(heroes)
  97. self.random_heroes = self.random_heroes
  98. db.session.commit()
  99. return self.random_heroes['current']
  100. @random_hero.setter
  101. def random_hero(self, herodata):
  102. self.random_heroes['current'] = herodata
  103. self.random_heroes = self.random_heroes
  104. db.session.commit()
  105. @property
  106. def random_completed(self):
  107. return self.random_heroes['completed']
  108. def random_success(self):
  109. self.random_heroes['completed'].append(self.random_heroes['current']['name'])
  110. if len(API_DATA['result']['heroes']) - len(self.random_heroes['completed']) <= 0:
  111. self.az_completions = self.az_completions + 1
  112. del self.random_heroes['completed'][:]
  113. self.random_heroes['current'] = None
  114. self.random_heroes = self.random_heroes
  115. db.session.commit()
  116. return self.random_hero
  117. def random_skip(self):
  118. self.random_heroes['current'] = None
  119. self.random_heroes = self.random_heroes
  120. db.session.commit()
  121. return self.random_hero
  122. def update_connection(self, reward_threshold=30):
  123. now = datetime.utcnow()
  124. self.ts3_starttime = self.ts3_starttime or now
  125. self.ts3_endtime = now
  126. # Add general TS3 points here
  127. if self.ts3_endtime and self.ts3_rewardtime:
  128. duration = (self.ts3_endtime - self.ts3_rewardtime) / 60.0
  129. if duration > reward_threshold:
  130. self.ts3_rewardtime = datetime.utcnow()
  131. self.points_from_ts3 += 1
  132. else:
  133. self.ts3_rewardtime = datetime.utcnow()
  134. self.last_seen = datetime.utcnow()
  135. print self.ts3_starttime, self.ts3_endtime, self.ts3_rewardtime
  136. db.session.commit();
  137. def finalize_connection(self):
  138. self.ts3_connections.append({'starttime': self.ts3_starttime, 'endtime': self.ts3_endtime})
  139. self.ts3_startime = None
  140. self.ts3_endtime = None
  141. db.session.commit();
  142. def update_forum_posts(self, reward_threshold=5):
  143. if self.forum_id:
  144. posts = board.Users.select().where(board.Users.id == int(self.forum_id))[0].posts
  145. if self.last_post_reward:
  146. num_points = (posts - self.last_post_reward) / reward_threshold
  147. if num_points > 0:
  148. self.points_from_forum += num_points
  149. self.last_post_reward += num_points * reward_threshold
  150. else:
  151. # Initialize if this is the first reward
  152. self.last_post_reward = posts
  153. db.session.commit()
  154. @property
  155. def is_active(self):
  156. return self.ts3_starttime and True or False
  157. def __repr__(self):
  158. return '<User {}>'.format(self.id)
  159. class TeamspeakData(db.Model):
  160. id = db.Column(db.Integer, primary_key=True)
  161. time = db.Column(db.DateTime())
  162. clients = db.Column(Json())
  163. def __init__(self, clientlist):
  164. self.time = datetime.utcnow()
  165. self.clients = clientlist
  166. class Event(db.Model):
  167. id = db.Column(db.Integer, primary_key=True)
  168. name = db.Column(db.String(200))
  169. desc = db.Column(db.String(4096))
  170. type = db.Column(db.String(20))
  171. start_time = db.Column(db.DateTime)
  172. end_time = db.Column(db.DateTime)
  173. points = db.Column(db.Integer)
  174. reward_threshold = db.Column(db.Integer)
  175. total_subchans = db.Column(db.Integer)
  176. channels = db.Column(MutableDict.as_mutable(Json))
  177. participants = db.Column(MutableDict.as_mutable(Json))
  178. def __init__(self, id):
  179. self.channels = {'event_cid':None, 'cids':[]}
  180. @classmethod
  181. def get_or_create(self, event_id):
  182. return get_or_create_instance(db.session, Event, id=event_id)
  183. @property
  184. def cids(self):
  185. return self.channels['cids']
  186. @property
  187. def event_cid(self):
  188. return self.channels['event_cid']
  189. @property
  190. def channel_ids(self):
  191. cids = self.channels['cids']
  192. if self.channels['event_cid']:
  193. cids.append(self.channels['event_cid'])
  194. return cids
  195. def create_channels(self):
  196. import ts3
  197. server = ts3.TS3Server(app.config['TS3_HOST'], app.config['TS3_PORT'])
  198. server.login(app.config['TS3_USERNAME'], app.config['TS3_PASSWORD'])
  199. server.use(1)
  200. # Create the parent channel
  201. if not self.event_cid:
  202. # Find the LFG channel and place this one after
  203. response = server.send_command('channelfind', keys={'pattern': 'Looking for Group'})
  204. if response.is_successful:
  205. cid = response.data[0]['cid']
  206. response = server.send_command('channelcreate', keys={'channel_name':self.name.encode('utf-8'), 'channel_flag_semi_permanent':'1', 'channel_order':cid})
  207. if response.is_successful:
  208. self.channels['event_cid'] = response.data[0]['cid']
  209. # Create the subchannels
  210. if not self.cids:
  211. cids = []
  212. keys = {'channel_name':'Event Room #{}'.format(len(self.cids) + 1), 'channel_flag_semi_permanent':'1', 'cpid':self.event_cid.encode('utf-8')}
  213. response = server.send_command('channelcreate', keys=keys)
  214. if response.is_successful:
  215. parent_cid = response.data[0]['cid']
  216. cids.append(parent_cid)
  217. else:
  218. raise UserWarning("channelcreate failed")
  219. response = server.send_command('channelcreate', keys={'channel_name':'Radiant Team', 'channel_flag_semi_permanent':'1', 'cpid':parent_cid})
  220. if response.is_successful:
  221. cids.append(response.data[0]['cid'])
  222. response = server.send_command('channelcreate', keys={'channel_name':'Dire Team', 'channel_flag_semi_permanent':'1', 'cpid':parent_cid})
  223. if response.is_successful:
  224. cids.append(response.data[0]['cid'])
  225. response = server.send_command('channelcreate', keys={'channel_name':'Spectators', 'channel_flag_semi_permanent':'1', 'cpid':parent_cid})
  226. if response.is_successful:
  227. cids.append(response.data[0]['cid'])
  228. self.channels['cids'] = cids
  229. db.session.commit()
  230. def remove_channels(self):
  231. import ts3
  232. server = ts3.TS3Server(app.config['TS3_HOST'], app.config['TS3_PORT'])
  233. server.login(app.config['TS3_USERNAME'], app.config['TS3_PASSWORD'])
  234. server.use(1)
  235. response = server.send_command('channeldelete', keys={'cid':self.event_cid.encode('utf-8'), 'force':'1'})
  236. if response.is_successful:
  237. self.channels = {'event_cid': None, 'cids':[]}
  238. db.session.commit()
  239. @property
  240. def active(self):
  241. current_time = datetime.utcnow()
  242. return self.start_time < current_time and current_time < self.end_time
  243. @property
  244. def expired(self):
  245. current_time = datetime.utcnow()
  246. return self.end_time < curent_time
  247. def add_participant(self, user):
  248. entry = self.participants.setdefault(user, {'start_time': datetime.utcnow() })
  249. entry['end_time'] = datetime.utcnow()
  250. if 'points' not in entry and (entry['end_time'] - entry['start_time']) > self.reward_threshold:
  251. user.points_from_events += self.points
  252. entry['points'] = self.points
  253. db.session.commit()
  254. @property
  255. def participants(self):
  256. return tuple(self.participants)
  257. def __repr__(self):
  258. return '<Event {}>'.format(self.id)