Jeu de belote en ligne.

db.py 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. from flask_login import UserMixin
  2. from werkzeug.security import generate_password_hash, check_password_hash
  3. from flask_sqlalchemy import SQLAlchemy
  4. from sqlalchemy.orm import relationship
  5. import random
  6. from belote_jeu import cards, N_PLAYERS, colors, winner, N_TURN
  7. db = SQLAlchemy()
  8. levels_users = {'Inactive':0, 'Simple user':1, 'Can create games':2, 'Can manage games':8, 'Can manage simple users': 9, 'Admin':10}
  9. #######################################################################
  10. # User class #
  11. #######################################################################
  12. class User(UserMixin, db.Model):
  13. """Model for user accounts."""
  14. __tablename__ = 'users'
  15. login = db.Column(db.String(100),
  16. primary_key=True)
  17. name = db.Column(db.String(100),
  18. nullable=False,
  19. unique=False)
  20. password = db.Column(db.String(100),
  21. primary_key=False,
  22. unique=False,
  23. nullable=False)
  24. level = db.Column(db.Integer, default=1)
  25. last_login = db.Column(db.DateTime)
  26. def set_password(self, password):
  27. """Create hashed password."""
  28. self.password = generate_password_hash(password, method='sha256')
  29. def check_password(self, password):
  30. """Check hashed password."""
  31. return check_password_hash(self.password, password)
  32. def get_id(self):
  33. return self.login
  34. def __repr__(self):
  35. return '<User {}>'.format(self.login)
  36. #######################################################################
  37. # Game class #
  38. #######################################################################
  39. class Game(db.Model):
  40. __tablename__ = 'games'
  41. id = db.Column(db.Integer,
  42. primary_key=True)
  43. name = db.Column(db.String(200))
  44. players = relationship("Player")
  45. turn = db.Column(db.Integer, default=-8)
  46. atout = db.Column(db.String(1))
  47. preneur = db.Column(db.String(100))
  48. admin = db.Column(db.String(100), db.ForeignKey('users.login'))
  49. cards_to_distribute = db.Column(db.String(200))
  50. first_player = db.Column(db.Integer)
  51. start = db.Column(db.Boolean, default=False)
  52. last_played = db.Column(db.String(20))
  53. played = db.Column(db.String(20))
  54. fixplayers = db.Column(db.Boolean, default=False)
  55. points_0 = db.Column(db.Integer, default=0)
  56. points_1 = db.Column(db.Integer, default=0)
  57. cumul_0 = db.Column(db.Integer, default=0)
  58. cumul_1 = db.Column(db.Integer, default=0)
  59. partie = db.Column(db.Integer, default=1)
  60. distributeur = db.Column(db.Integer, default=0)
  61. def start_game(self, ordered_players):
  62. # Ordering players
  63. if self.fixplayers and not self.start:
  64. i=0
  65. if ordered_players is not None:
  66. for op in ordered_players:
  67. player = Player.query.filter_by(game=self.id, user=op).first()
  68. if player is not None:
  69. player.nr = i
  70. i+=1
  71. for p in self.players:
  72. if p.nr is None or p.nr<0:
  73. p.nr = i
  74. i+=1
  75. db.session.commit()
  76. self.start = True
  77. self.first_player = 0
  78. self.distribute()
  79. db.session.commit()
  80. return True
  81. return False
  82. def fix_players(self):
  83. if self.can_start():
  84. self.fixplayers = True
  85. db.session.commit()
  86. def distribute(self):
  87. ___cartes = random.sample(cards, k=len(cards))
  88. for i in range(len(self.players)):
  89. self.players[i].cards = ','.join(___cartes[5*i:5*(i+1)])
  90. self.played = ___cartes[5*(i+1)]
  91. self.cards_to_distribute = ','.join(___cartes[5*(i+1)+1:])
  92. def authorized(self, user):
  93. for p in self.players:
  94. if user.login == p.user:
  95. return True
  96. return False
  97. def isadmin(self, user):
  98. return user.login == self.admin
  99. def serialize_state_anonymous(self):
  100. r = {}
  101. r['players'] = self.get_ordered_players()
  102. r['playersinfo'] = {}
  103. for p in self.players:
  104. r['playersinfo'][p.user] = User.query.get(p.user).name
  105. r['atout'] = self.atout
  106. r['preneur'] = self.preneur
  107. r['last_played'] = self.last_played.split(',') if self.last_played is not None else []
  108. r['played'] = self.played.split(',') if self.played is not None else []
  109. r['turn'] = self.turn
  110. r['first_player'] = self.first_player
  111. r['points'] = [self.points_0, self.points_1]
  112. r['cumul'] = [self.cumul_0, self.cumul_1]
  113. r['partie'] = self.partie
  114. r['admin'] = self.admin
  115. r['distributeur'] = self.distributeur
  116. return r
  117. def serialize_state(self, user):
  118. r = self.serialize_state_anonymous()
  119. r['nr'] = self.get_nr(user)
  120. cards = self.get_player(user).cards
  121. r['cards'] = cards.split(',') if cards is not None else []
  122. return r
  123. def get_ordered_players(self):
  124. r = {}
  125. for p in self.players:
  126. r[p.nr] = p.user
  127. r2 = []
  128. for i in range(N_PLAYERS):
  129. r2.append(r[i] if i in r else None)
  130. return r2
  131. def get_nr(self, user):
  132. p = self.get_player(user)
  133. if p is not None :
  134. return p.nr
  135. else:
  136. return -1
  137. def get_player(self, user):
  138. if not isinstance(user, str):
  139. user = user.login
  140. return Player.query.filter_by(game=self.id, user=user).first()
  141. def can_join(self, user):
  142. if self.authorized(user):
  143. return True
  144. if not self.fixplayers and len(self.players) < N_PLAYERS:
  145. return True
  146. return False
  147. def can_start(self):
  148. if len(self.players)==N_PLAYERS:
  149. return True
  150. return False
  151. def join(self, user):
  152. if not self.fixplayers and not self.authorized(user):
  153. p = Player(game=self.id, user=user.login)
  154. db.session.add(p)
  155. db.session.commit()
  156. def leave(self, user):
  157. if not self.fixplayers:
  158. for p in self.players:
  159. if isinstance(user, str) and user != self.admin or hasattr(user, 'login') and user.login != self.admin:
  160. if isinstance(user, str) and user == p.user or hasattr(user, 'login') and user.login == p.user:
  161. db.session.delete(p)
  162. db.session.commit()
  163. return True
  164. return False
  165. def get_players(self):
  166. r = []
  167. for p in self.players:
  168. user = User.query.get(p.user)
  169. r.append({'username':user.login, 'name':user.name})
  170. return r
  171. def tour_choix(self, atout, user):
  172. if (self.turn + self.first_player) % N_PLAYERS == self.get_nr(user):
  173. self.turn += 1
  174. if atout is not None and atout in colors:
  175. self.atout = atout
  176. self.preneur = user.login
  177. self.turn = 0
  178. self.distribute_restant()
  179. db.session.commit()
  180. return True
  181. return False
  182. def distribute_restant(self):
  183. todistribute = self.cards_to_distribute.split(',')
  184. for pn in self.get_ordered_players():
  185. p = self.get_player(pn)
  186. if pn == self.preneur:
  187. p.cards += ',' + ','.join(todistribute[:2])
  188. p.cards += ',' + self.played
  189. todistribute = todistribute[2:]
  190. else:
  191. p.cards += ',' + ','.join(todistribute[:3])
  192. todistribute = todistribute[3:]
  193. self.cards_to_distribute = ''
  194. self.played = None
  195. def tour_jeu(self, carte, user):
  196. if (self.turn + self.first_player) % N_PLAYERS == self.get_nr(user):
  197. winnr = -1
  198. self.turn += 1
  199. if self.played is None or self.played == '':
  200. self.played = carte
  201. else:
  202. self.played += ',' + carte
  203. if self.turn % N_PLAYERS == 0 :
  204. winnr, points = winner(self.played, self.atout)
  205. if (self.first_player + winnr)%2 == 0:
  206. self.points_0 += points
  207. else:
  208. self.points_1 += points
  209. self.last_played = self.played
  210. if len(self.cards_to_distribute)>1:
  211. self.cards_to_distribute += ','
  212. self.cards_to_distribute += self.played
  213. self.played = None
  214. self.first_player = (self.first_player + winnr)%4
  215. if self.turn == N_TURN*N_PLAYERS: # Dix de der, chute, belote et capote !
  216. # Dix de der
  217. if self.first_player%2 == 0:
  218. self.points_0 += 10
  219. else:
  220. self.points_1 += 10
  221. # Belote possible
  222. winnr = self.distributeur
  223. belote =-1
  224. belote_0 = 0
  225. belote_1 = 0
  226. ccc = self.cards_to_distribute.split(',')
  227. for i in range(N_TURN):
  228. cccc = ccc[i*N_PLAYERS:(i+1)*N_PLAYERS]
  229. if 'R'+self.atout in cccc:
  230. if belote>=0:
  231. if (cccc.index('R'+self.atout) + winnr)%4 == belote %4:
  232. if belote %2 ==0:
  233. self.points_0 += 20
  234. belote_0 = 20
  235. else:
  236. self.points_1 += 20
  237. belote_1 = 20
  238. else:
  239. belote = winnr + cccc.index('R'+self.atout)
  240. if 'D'+self.atout in cccc:
  241. if belote>=0:
  242. if (cccc.index('D'+self.atout) + winnr)%4 == belote %4:
  243. if belote %2 ==0:
  244. self.points_0 += 20
  245. belote_0 = 20
  246. else:
  247. self.points_1 += 20
  248. belote_1 = 20
  249. else:
  250. belote = winnr + cccc.index('D'+self.atout)
  251. win, xxx = winner(cccc, self.atout)
  252. winnr = win+winnr
  253. # Capote
  254. if self.points_0 >= 162 or self.points_1 >= 162:
  255. winequipe = 0 if self.points_0 >= 162 else 1
  256. # Capote possible.
  257. winnr = self.distributeur
  258. ccc = self.cards_to_distribute.split(',')
  259. for i in range(N_TURN):
  260. win, xxx = winner(ccc[i*N_PLAYERS:(i+1)*N_PLAYERS], self.atout)
  261. winnr = win+winnr
  262. if winnr % 2 != winequipe:
  263. break
  264. else:
  265. if winequipe == 0:
  266. self.points_0 += 90
  267. else:
  268. self.points_1 += 90
  269. # Chute
  270. if self.get_player(self.preneur).nr %2 ==0 and self.points_0 < self.points_1:
  271. self.points_0 = belote_0
  272. self.points_1 = 162 + belote_1
  273. if self.get_player(self.preneur).nr %2 ==1 and self.points_1 < self.points_0:
  274. self.points_0 = 162 + belote_0
  275. self.points_1 = belote_1
  276. # Retirer la carte du jeu !
  277. p = self.get_player(user)
  278. ccc = p.cards
  279. ccc = ccc.split(',')
  280. ccc.remove(carte)
  281. p.cards = ','.join(ccc)
  282. db.session.commit()
  283. return True, winnr
  284. return False, -1
  285. def restart_jeu(self):
  286. if (self.turn==0 and (self.atout=='' or self.atout is None)) or self.turn==N_TURN*N_PLAYERS:
  287. if self.turn>0:
  288. self.partie +=1
  289. self.turn = -8
  290. self.atout = None
  291. self.preneur = None
  292. self.last_played = None
  293. self.played = None
  294. self.cumul_0 += self.points_0
  295. self.cumul_1 += self.points_1
  296. self.points_0 = 0
  297. self.points_1 = 0
  298. if self.distributeur <3:
  299. self.distributeur += 1
  300. else:
  301. self.distributeur = 0
  302. self.first_player = self.distributeur
  303. self.distribute()
  304. db.session.commit()
  305. return True
  306. return False
  307. #######################################################################
  308. # Player class #
  309. #######################################################################
  310. class Player(db.Model):
  311. __tablename__ = 'players'
  312. id = db.Column(db.Integer,
  313. primary_key=True)
  314. game = db.Column(db.Integer, db.ForeignKey('games.id'))
  315. user = db.Column(db.String(100), db.ForeignKey('users.login'))
  316. cards = db.Column(db.String(40))
  317. nr = db.Column(db.Integer, default=-1)