from flask_login import UserMixin from werkzeug.security import generate_password_hash, check_password_hash from flask_sqlalchemy import SQLAlchemy from sqlalchemy.orm import relationship import random from belote_jeu import cards, N_PLAYERS, colors, winner, N_TURN db = SQLAlchemy() levels_users = {'Inactive':0, 'Simple user':1, 'Can create games':2, 'Can manage games':8, 'Can manage simple users': 9, 'Admin':10} ####################################################################### # User class # ####################################################################### class User(UserMixin, db.Model): """Model for user accounts.""" __tablename__ = 'users' login = db.Column(db.String(100), primary_key=True) name = db.Column(db.String(100), nullable=False, unique=False) password = db.Column(db.String(100), primary_key=False, unique=False, nullable=False) level = db.Column(db.Integer, default=1) last_login = db.Column(db.DateTime) def set_password(self, password): """Create hashed password.""" self.password = generate_password_hash(password, method='sha256') def check_password(self, password): """Check hashed password.""" return check_password_hash(self.password, password) def get_id(self): return self.login def __repr__(self): return ''.format(self.login) ####################################################################### # Game class # ####################################################################### class Game(db.Model): __tablename__ = 'games' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(200)) players = relationship("Player") turn = db.Column(db.Integer, default=-8) atout = db.Column(db.String(1)) preneur = db.Column(db.String(100)) admin = db.Column(db.String(100), db.ForeignKey('users.login')) cards_to_distribute = db.Column(db.String(200)) first_player = db.Column(db.Integer) start = db.Column(db.Boolean, default=False) last_played = db.Column(db.String(20)) played = db.Column(db.String(20)) fixplayers = db.Column(db.Boolean, default=False) points_0 = db.Column(db.Integer, default=0) points_1 = db.Column(db.Integer, default=0) cumul_0 = db.Column(db.Integer, default=0) cumul_1 = db.Column(db.Integer, default=0) partie = db.Column(db.Integer, default=1) distributeur = db.Column(db.Integer, default=0) def start_game(self, ordered_players): # Ordering players if self.fixplayers and not self.start: i=0 if ordered_players is not None: for op in ordered_players: player = Player.query.filter_by(game=self.id, user=op).first() if player is not None: player.nr = i i+=1 for p in self.players: if p.nr is None or p.nr<0: p.nr = i i+=1 db.session.commit() self.start = True self.first_player = 0 self.distribute() db.session.commit() return True return False def fix_players(self): if self.can_start(): self.fixplayers = True db.session.commit() def distribute(self): ___cartes = random.sample(cards, k=len(cards)) for i in range(len(self.players)): self.players[i].cards = ','.join(___cartes[5*i:5*(i+1)]) self.played = ___cartes[5*(i+1)] self.cards_to_distribute = ','.join(___cartes[5*(i+1)+1:]) def authorized(self, user): for p in self.players: if user.login == p.user: return True return False def isadmin(self, user): return user.login == self.admin def serialize_state_anonymous(self): r = {} r['players'] = self.get_ordered_players() r['playersinfo'] = {} for p in self.players: r['playersinfo'][p.user] = User.query.get(p.user).name r['atout'] = self.atout r['preneur'] = self.preneur r['last_played'] = self.last_played.split(',') if self.last_played is not None else [] r['played'] = self.played.split(',') if self.played is not None else [] r['turn'] = self.turn r['first_player'] = self.first_player r['points'] = [self.points_0, self.points_1] r['cumul'] = [self.cumul_0, self.cumul_1] r['partie'] = self.partie r['admin'] = self.admin return r def serialize_state(self, user): r = self.serialize_state_anonymous() r['nr'] = self.get_nr(user) cards = self.get_player(user).cards r['cards'] = cards.split(',') if cards is not None else [] return r def get_ordered_players(self): r = {} for p in self.players: r[p.nr] = p.user r2 = [] for i in range(N_PLAYERS): r2.append(r[i] if i in r else None) return r2 def get_nr(self, user): p = self.get_player(user) if p is not None : return p.nr else: return -1 def get_player(self, user): if not isinstance(user, str): user = user.login return Player.query.filter_by(game=self.id, user=user).first() def can_join(self, user): if self.authorized(user): return True if not self.fixplayers and len(self.players) < N_PLAYERS: return True return False def can_start(self): if len(self.players)==N_PLAYERS: return True return False def join(self, user): if not self.fixplayers and not self.authorized(user): p = Player(game=self.id, user=user.login) db.session.add(p) db.session.commit() def leave(self, user): if not self.fixplayers: for p in self.players: if isinstance(user, str) and user != self.admin or hasattr(user, 'login') and user.login != self.admin: if isinstance(user, str) and user == p.user or hasattr(user, 'login') and user.login == p.user: db.session.delete(p) db.session.commit() return True return False def get_players(self): r = [] for p in self.players: user = User.query.get(p.user) r.append({'username':user.login, 'name':user.name}) return r def tour_choix(self, atout, user): if (self.turn + self.first_player) % N_PLAYERS == self.get_nr(user): self.turn += 1 if atout is not None and atout in colors: self.atout = atout self.preneur = user.login self.turn = 0 self.distribute_restant() db.session.commit() return True return False def distribute_restant(self): todistribute = self.cards_to_distribute.split(',') for pn in self.get_ordered_players(): p = self.get_player(pn) if pn == self.preneur: p.cards += ',' + ','.join(todistribute[:2]) p.cards += ',' + self.played todistribute = todistribute[2:] else: p.cards += ',' + ','.join(todistribute[:3]) todistribute = todistribute[3:] self.cards_to_distribute = '' self.played = None def tour_jeu(self, carte, user): if (self.turn + self.first_player) % N_PLAYERS == self.get_nr(user): winnr = -1 self.turn += 1 if self.played is None or self.played == '': self.played = carte else: self.played += ',' + carte if self.turn % N_PLAYERS == 0 : winnr, points = winner(self.played, self.atout) if (self.first_player + winnr)%2 == 0: self.points_0 += points else: self.points_1 += points self.last_played = self.played if len(self.cards_to_distribute)>1: self.cards_to_distribute += ',' self.cards_to_distribute += self.played self.played = None self.first_player = (self.first_player + winnr)%4 if self.turn == N_TURN*N_PLAYERS: # Dix de der, chute, belote et capote ! # Dix de der if self.first_player%2 == 0: self.points_0 += 10 else: self.points_1 += 10 # Belote possible winnr = self.distributeur belote =-1 belote_0 = 0 belote_1 = 0 ccc = self.cards_to_distribute.split(',') for i in range(N_TURN): cccc = ccc[i*N_PLAYERS:(i+1)*N_PLAYERS] if 'R'+self.atout in cccc: if belote>=0: if (cccc.index('R'+self.atout) + winnr)%4 == belote %4: if belote %2 ==0: self.points_0 += 20 belote_0 = 20 else: self.points_1 += 20 belote_1 = 20 else: belote = winnr + cccc.index('R'+self.atout) if 'D'+self.atout in cccc: if belote>=0: if (cccc.index('D'+self.atout) + winnr)%4 == belote %4: if belote %2 ==0: self.points_0 += 20 else: self.points_1 += 20 else: belote = winnr + cccc.index('D'+self.atout) win, xxx = winner(cccc, self.atout) winnr = win+winnr # Capote if self.points_0 >= 162 or self.points_1 >= 162: winequipe = 0 if self.points_0 >= 162 else 1 # Capote possible. winnr = self.distributeur ccc = self.cards_to_distribute.split(',') for i in range(N_TURN): win, xxx = winner(ccc[i*N_PLAYERS:(i+1)*N_PLAYERS], self.atout) winnr = win+winnr if winnr % 2 != winequipe: break else: if winequipe == 0: self.points_0 += 90 else: self.points_1 += 90 # Chute if self.get_player(self.preneur).nr %2 ==0 and self.points_0 < self.points_1: self.points_0 = belote_0 self.points_1 = 162 + belote_1 if self.get_player(self.preneur).nr %2 ==1 and self.points_1 < self.points_0: self.points_0 = 162 + belote_0 self.points_1 = belote_1 # Retirer la carte du jeu ! p = self.get_player(user) ccc = p.cards ccc = ccc.split(',') ccc.remove(carte) p.cards = ','.join(ccc) db.session.commit() return True, winnr return False, -1 def restart_jeu(self): if (self.turn==0 and (self.atout=='' or self.atout is None)) or self.turn==N_TURN*N_PLAYERS: if self.turn>0: self.partie +=1 self.turn = -8 self.atout = None self.preneur = None self.last_played = None self.played = None self.cumul_0 += self.points_0 self.cumul_1 += self.points_1 self.points_0 = 0 self.points_1 = 0 if self.distributeur <3: self.distributeur += 1 else: self.distributeur = 0 self.first_player = self.distributeur self.distribute() db.session.commit() return True return False ####################################################################### # Player class # ####################################################################### class Player(db.Model): __tablename__ = 'players' id = db.Column(db.Integer, primary_key=True) game = db.Column(db.Integer, db.ForeignKey('games.id')) user = db.Column(db.String(100), db.ForeignKey('users.login')) cards = db.Column(db.String(40)) nr = db.Column(db.Integer, default=-1)