class Policy(db.Model): _id = db.Column(db.String(64), primary_key=True) __formula = db.Column(db.String(128)) max_level = db.Column(db.Integer) def __init__(self, policy_id, formula, max_level): self._id = policy_id self.max_level = max_level self.set_formula(formula) def set_formula(self, formula): ''' Sets formula, after checking the format, if wrong format InvalidFormulaException is raised ''' self.__check_formula_or_raise(formula) self.__formula = formula def __check_formula_or_raise(self, formula): errors = validate.formula(formula) if errors: raise InvalidFormulaException(json.dumps({"errors": errors})) def get_level(self, user_points): ''' Get the level info for the puntuation passed ''' level = self.__get_level(user_points, 0, 1) level['policy'] = self._id return level def __get_level(self, user_points, total_points, level): if level < self.max_level: total_points += self.__calculate_points(level) if user_points >= total_points: return self.__get_level(user_points, total_points, level + 1) return self.__serialize_points(level, total_points - user_points) def get_levels(self): ''' Get all the levels of this policy ''' return {'policy': self._id, 'formula': self.__formula, 'max_level':self.max_level, "levels": self.__get_levels([], 0, 1)} def __get_levels(self, points_list, total_points, level): if level <= self.max_level: points_to_next = self.__calculate_points(level) points_list.append(self.__serialize_points(level, total_points)) total_points += points_to_next return self.__get_levels(points_list, total_points, level + 1) return points_list def __calculate_points(self, level): ''' Calculates the points necessary to reach the passed level from the previous level ''' value = eval(self.__formula) return _round_in_hundreds(value) def __serialize_points(self, level, points): if self.max_level == level: return {"level": level} return {"level": level, "points_to_next": points}
class User(db.Model): ''' User class ''' _id = db.Column(db.String(64), primary_key=True) observations = db.relationship('Observation', secondary=user_observations, lazy='joined', backref=db.backref('user', lazy='joined')) def __init__(self, user_info): self._id = user_info['_id'] def __str__(self): return str(self._id) def __eq__(self, user): return user == self._id def serialize(self, only_id=True): ''' Serializes the object, has two modes:\n only_id = True => serializes only the id\n only_id = False => serializes id + observations''' if only_id: return {"_id": self._id} return { "_id": self._id, 'observations': [ observation.serialize(only_id=True) for observation in self.observations ] } def get_id(self): ''' Returns user id ''' return self._id
class Votes(db.Model): observation_id = db.Column(db.String(64), db.ForeignKey('observation._id'), primary_key=True) upvotes = db.Column(db.Integer) downvotes = db.Column(db.Integer) ''' Votes class ''' def __init__(self, json): self.upvotes = json['upvotes'] self.downvotes = json['downvotes'] def __str__(self): positive = Fore.GREEN + '+' + str(self.upvotes) + Fore.RESET negative = Fore.RED + '-' + str(self.downvotes) + Fore.RESET return f'{positive}\t{negative}' def add_vote(self, vote_type): ''' Adds a new vote, returns the number of votes ''' if vote_type: self.upvotes = self.upvotes + 1 else: self.downvotes = self.downvotes + 1 return self.number_of_votes() def number_of_votes(self): ''' Returns the number of votes ''' return self.upvotes + self.downvotes def serialize(self): ''' Serializes object ''' return {"upvotes": self.upvotes, "downvotes": self.downvotes}
class Image(db.Model): ''' Image class ''' _id = db.Column(db.String(64), primary_key=True) observations = db.relationship('Observation', backref=db.backref('image', lazy='joined')) x_size = db.Column(db.Integer) y_size = db.Column(db.Integer) probability = db.Column(db.Integer) fwhm = db.Column(db.Integer) def __init__(self, image_info): self.observations = [] self._id = image_info['_id'] self.x_size = image_info['x_size'] self.y_size = image_info['y_size'] self.probability = image_info['probability'] self.fwhm = image_info['fwhm'] def __eq__(self, image): return image == self._id
class Puntuation(db.Model): ''' Puntuation class implementation ''' observation_id = db.Column(db.String(64), db.ForeignKey('observation._id'), primary_key=True) positive = db.Column(db.Integer) negative = db.Column(db.Integer) ''' Puntuation class ''' def __init__(self, votes): self.positive = votes.upvotes self.negative = votes.downvotes def __str__(self): positive = Fore.GREEN + '+' + str(self.positive) + Fore.RESET negative = Fore.RED + '-' + str(self.negative) + Fore.RESET return f'{positive}\t{negative}\t{self.calculate_certainty()*100}%' def serialize(self): ''' Serializes object ''' return { "positive": self.positive, "negative": self.negative, "certainty": self.calculate_certainty() } def add_vote(self, vote_type, karma_level): ''' Adds a new vote, returns the certainty ''' if vote_type: self.positive = self.positive + karma_level else: self.negative = self.negative + karma_level return self.calculate_certainty() def calculate_certainty(self): ''' Calculates the certainty ''' try: return (self.positive - self.negative) / (self.positive + self.negative) except ZeroDivisionError: return 0
class Position(db.Model): ''' Observation Position implementation ''' observation_id = db.Column(db.String(64), db.ForeignKey('observation._id'), primary_key=True) x_position = db.Column(db.Integer) y_position = db.Column(db.Integer) ''' Position Class ''' def __init__(self, positon_data=None, x_position=0, y_position=0): # if positon_data: self.x_position = positon_data['x'] self.y_position = positon_data['y'] # else: # self.x_position = x_position # self.y_position = y_position def __str__(self): # pragma: no cover return f'x:{self.x_position}\ty:{self.y_position}' def serialize(self): # pragma: no cover ''' Serializes object ''' return {"x": self.x_position, "y": self.y_position}
class Observation(ObservationAbstract, db.Model): ''' Implementation of the Observation ''' _id = db.Column(db.String(64), primary_key=True) state = db.Column(db.Enum(State)) image_id = db.Column(db.String(64), db.ForeignKey('image._id')) votes = db.relationship('Votes', uselist=False, lazy='joined') position = db.relationship('Position', uselist=False, lazy='joined') puntuation = db.relationship('Puntuation', uselist=False, lazy='joined') users_who_voted = db.relationship('User', secondary=user_observations, lazy='joined') brightness = db.Column(db.Integer) def __init__(self, observation_info): self._id = observation_info['_id'] self.image_id = observation_info['image']['_id'] self.brightness = observation_info['brightness'] self.votes = Votes(observation_info['votes']) self.position = Position(observation_info['position']) self.puntuation = Puntuation(self.votes) self.difficulty = -1 self.certainty = 0 self.state = State.PENDING def __str__(self): parse = DATA_TAG + f' Observation (id={self._id})\n' parse = parse + to_string_list('votes', self.votes) parse = parse + to_string_list('puntuation', self.puntuation) parse = parse + to_string_list('position', self.position) parse = parse + to_string_list('state', self.state) return parse def __eq__(self, observation): return observation == self._id def __repr__(self): # pragma: no cover return f'<{Observation.__name__}, {self._id}, {self.puntuation.calculate_certainty()}>' def serialize(self, only_id=False, difficulty=False, id_position=False): # pragma: no cover ''' Serializes the object, has two modes:\n only_id = True => serializes only the id\n only_id = False => serializes all the object''' if only_id: return {"_id": self._id} if id_position: return { "observation_id": self._id, "image_id": self.image_id, "state": self.state.value, "position": self.position.serialize() } if difficulty: return {"_id": self._id, "difficulty": self.difficulty} return { "_id": self._id, "image_id": self.image_id, "votes": self.votes.serialize(), "puntuation": self.puntuation.serialize(), "position": self.position.serialize(), "state": self.state.value, "users_who_voted": [user.get_id() for user in self.users_who_voted] } def add_vote(self, vote_info, user): vote_type = vote_info['vote_type'] karma_level = vote_info['karma_level'] number_of_votes = self.votes.add_vote(vote_type) certainty = self.puntuation.add_vote(vote_type, karma_level) self.users_who_voted.append(user) return number_of_votes, certainty def change_state(self, change_to): ''' Changes the state of the observation based on the approved parameter\n approved=True => approved \n approved=False => denyed ''' if self.state != change_to: self.state = change_to colored_state = f'{Fore.CYAN}\'{self.state.value}\'{Fore.RESET}' info(f'OBSER', f'{self._id} state changed to {colored_state}') def get_notified(self): ''' Returns if this observation has ''' return State.APPROVED == self.state or State.DENYED == self.state def repeated_vote(self, user): ''' Detects if the user passed has already voted this observation ''' for user_who_voted in self.users_who_voted: if user == user_who_voted: return True def get_certainty(self): ''' Calculates the certainty of this image ''' if self.get_certainty: return self.get_certainty return self.puntuation.get_certainty() def user_has_voted(self, current_user): ''' Detects if the user passed has already voted ''' for user in self.users_who_voted: if user == current_user: return True