def vote(member_identifier, bill_identifier): """Predicts how the specified member will vote on the given bill. Arguments: member_identifier: A value that identifies the member such as full_name or database id. Make sure the value uniquely identifies the member in the database. bill_identifier: A value that identifies the bill such as bill_number or database id. Make sure the value uniquely identifies the bill in the database. Returns: A decision object containing the results of the decision on the vote """ member = PymongoDB.get_db().find_one(db_constants.MEMBERS, queries.member_query(member_identifier)) bill = PymongoDB.get_db().find_one(db_constants.BILLS, queries.bill_query(bill_identifier)) if not member: logger.LOGGER.error("Member not found in DB: %s" % member_identifier) return None if not bill: logger.LOGGER.error("Bill not found in DB: %s" % bill_identifier) return None return _vote_helper(member, bill)
def setUp(self): self.DB = PymongoDB.get_db() self.decision = Decision() self.member = Member() self.bill = Bill() self.strategy = BestForTheCountryStrategy(self.decision, self.member, self.bill) self.stance = Stance() self.stance.issue = "Some Issue" self.stance.side = outcomes.FOR self.stance1 = Stance() self.stance1.issue = "Some Other Issue" self.stance1.side = outcomes.AGN self.group_result = ResultData() self.group_result.outcome = outcomes.AGN self.group_result.data = [self.stance] self.credo_result = ResultData() self.credo_result.outcome = outcomes.AGN self.credo_result.data = [self.stance] self.decision.MI_group = self.group_result self.decision.MI_credo = self.credo_result self.stance_country = Stance() self.stance_country.issue = "Very important" self.stance_country.source = self.strategy._COUNTRY self.stance_country.side = outcomes.FOR self.decision.for_stances = [self.stance] self.decision.agn_stances = [self.stance1]
def setUp(self): self.DB = PymongoDB.get_db() load_data.load_data() self.member = self.DB.find_one(db_constants.MEMBERS, {"full_name" : "vote_test"}) self.MEMBER = "vote_test" self.BILL1 = "VOTE_BILL1" self.BILL2 = "VOTE_BILL2" self.BILL3 = "VOTE_BILL3" self.GROUP1 = "VOTE_GROUP1" self.GROUP2 = "VOTE_GROUP2" self.strategy1_name = "AlwaysSucceed" self.strategy2_name = "AlwaysFail" self.strategy3_name = "AlwaysFail2" self.strategy4_name = "Inactive" self.bill1 = self.DB.find_one(db_constants.BILLS, queries.bill_query(self.BILL1)) self.bill2 = self.DB.find_one(db_constants.BILLS, queries.bill_query(self.BILL2)) self.bill3 = self.DB.find_one(db_constants.BILLS, queries.bill_query(self.BILL3)) self.group1 = self.DB.find_one(db_constants.GROUPS, queries.bill_query(self.GROUP1)) self.group2 = self.DB.find_one(db_constants.GROUPS, queries.bill_query(self.GROUP2)) AlwaysFailStrategy.call_count = 0 self.DB.DB.drop_collection(db_constants.DECISIONS)
def setUp(self): self.DB = PymongoDB.get_db() self.decision = Decision() self.member = Member() self.bill = Bill() self.strategy = NotConstitutionalStrategy(self.decision, self.member, self.bill) self.stance = Stance() self.stance.issue = "Some Issue" self.stance.side = outcomes.FOR self.stance1 = Stance() self.stance1.issue = "Some Other Issue" self.stance1.side = outcomes.AGN self.group_result = ResultData() self.group_result.outcome = outcomes.AGN self.group_result.data = [self.stance] self.credo_result = ResultData() self.credo_result.outcome = outcomes.AGN self.credo_result.data = [self.stance] self.decision.MI_group = self.group_result self.decision.MI_credo = self.credo_result self.stance_con = Stance() self.stance_con.issue = self.strategy._CONSTITUTION self.stance_con.side = outcomes.FOR self.decision.for_stances = [self.stance] self.decision.agn_stances = [self.stance_con]
def _extract_single_voting_stance(vote): """Helper to extract_voting_stances. Extracts a stance the member holds based on voting for a particular bill. It checks the bill and returns the stances that can be inferred from voting for or against it. Arguments: vote: a vote from member.voting_record Return A list containing all stances to be inferred from the vote. """ logger.LOGGER.info("Extracting stances from vote: %s" % vote) # Check if the name used in vote is the name of the bill, bill number, or # a synonym bill_identifier = vote.data query = queries.bill_query(bill_identifier) bill = PymongoDB.get_db().find_one(db_constants.BILLS, query) if bill is None: logger.LOGGER.error("Bill not found: %s" % bill_identifier) return [] if vote.outcome == outcomes.FOR: return bill.stances_for elif vote.outcome == outcomes.AGN: return bill.stances_agn else: msg = "Bad Bill outcome. Expected FOR or AGN. Received %s" % vote.outcome logger.LOGGER.error(msg) return []
def load_data(): """ Loads the database stored as json objects in files. The files are stored under database/.... The old data in the database is erased. """ config_db = config.CONFIG[config_constants.DATABASE] DATABASE_PATH = "%s/../../../database/%s" % (os.path.dirname(__file__), config_db) DB = PymongoDB.get_db() print "Loading %s database data" % config_db print "Target Directory: %s" % DATABASE_PATH print "Running..." for collection_name in db_constants.DB_COLLECTIONS: DB.DB.drop_collection(collection_name) result = [] file_name = "%s/%s.txt" % (DATABASE_PATH, collection_name) with open(file_name) as data_file: json_object = "" for data in data_file.read().splitlines(): json_object += data if data == "}": result.append(json_util.loads(json_object)) json_object = "" for hash_data in result: DB.insert_one(collection_name, hash_data) print collection_name + " loaded." print "Finished"
def _infer_single_relation_stances(relation): """A helper method for extract_relations_stances(). It queries the database for an individual group a member has relations with and extracts stances from it. Arguments: relation: the relationship to examine (identifies a group) Returns: A list of all stances extracted from the relation """ results = [] # Check if the relation group is identified by name or id or synonym. query = queries.group_query(relation.group) group = PymongoDB.get_db().find_one(db_constants.GROUPS, query) if group is None: logger.LOGGER.error("Group not found: %s" % relation.group) return results logger.LOGGER.info("Inferring stances from group: %s" % group.name) for stance in group.stances: stance.relation = relation results.append(stance) return results
def _update_regular_stances(decision): """ Updates the various stances within decision. In particular, this function calculates norms, determines the stances groups have on the issue, and determines split groups, credos, voting records, etc. Arguments: decision: The decision object to update """ logger.LOGGER.info("Updating regular stances...") fors = decision.for_stances agns = decision.agn_stances bill = PymongoDB.get_db().find_one(db_constants.BILLS, queries.bill_query(decision.bill)) logger.LOGGER.info("Updating norms...") decision.for_norms = stance_analyze.collect_normative_stances(fors) decision.agn_norms = stance_analyze.collect_normative_stances(agns) if bill is None: logger.LOGGER.error("Decision bill not found.") else: logger.LOGGER.info("Updating bill norms...") decision.for_bill_norms = stance_analyze.collect_normative_stances(bill.stances_for) decision.agn_bill_norms = stance_analyze.collect_normative_stances(bill.stances_agn) logger.LOGGER.info("Updating group stances...") decision.groups_for = util.collect_group_stances(fors) decision.groups_agn = util.collect_group_stances(agns) # Equality is defined by seeing if a stance has the same source as another. # This is needed to detect split groups. However, the stances are not # equal to each other in the normal sense. Hence, the intersection is done # twice to get all unique stances. eq_fun = lambda stance1, stance2: stance1.source == stance2.source for_intersect = util.intersection(decision.groups_for, decision.groups_agn, eq_fun) agn_intersect = util.intersection(decision.groups_agn, decision.groups_for, eq_fun) decision.split_group = for_intersect + agn_intersect if decision.split_group: logger.LOGGER.info("Split group detected.") for_bills = util.collect_bill_stances(fors) agn_bills = util.collect_bill_stances(agns) if for_bills and agn_bills: logger.LOGGER.info("Split record detected.") decision.split_record = for_bills + agn_bills for_credo = util.collect_credo_stances(fors) agn_credo = util.collect_credo_stances(agns) if for_credo and agn_credo: logger.LOGGER.info("Split credo detected.") decision.split_credo = for_credo + agn_credo logger.LOGGER.info("Regular stances update complete.")
def _save(decision): """Saves the decision to the DB. Arguments: decision: the decision to save """ logger.LOGGER.info("Saving the decision to the database...") result = PymongoDB.get_db().insert_one(db_constants.DECISIONS, decision) if result: logger.LOGGER.info("Decision saved.") else: logger.LOGGER.error("ERROR decision not saved.")
def _run(self): """Implements the logic of Not Constitutional.""" constitution = PymongoDB.get_db().find_one(db_constants.ISSUES, queries.issue_query(self._CONSTITUTION)) if not constitution: logger.LOGGER.warning("Constitution issue not found in DB.") return result = self._consensus() filter_fun = lambda stance : queries.is_issue_identified(stance.issue, constitution) self._non_constitutional_stances = filter(filter_fun, self._decision.agn_stances) if result == outcomes.AGN and self._non_constitutional_stances: return self._set_decision(outcomes.AGN)
def _get_members(member_identifier=None): """Retrieves the members for vote_all. If member_identifier is specified, the specific member is looked up in the DB. If the name is not specified or the member was not found, a cursor for a Pymongo find request is returned. Arguments: member_identifier: the identifier of the member to retrieve. Returns: Either an array with the member specified in member_identifier or an iterator for all members who will vote. """ member = None if member_identifier: member = PymongoDB.get_db().find_one(db_constants.MEMBERS, queries.member_query(member_identifier)) if member: return [member] else: if member_identifier: logger.LOGGER.error("Bill not found: %s" % member_identifier) return PymongoDB.get_db().find(db_constants.MEMBERS)
def _get_bills(bill_identifier=None): """Retrieves the bills for vote_all. If the bill_identifier is specified, it returns a list of the specified bill. If not, it returns an iterator over all the bills in the database. Arguments: bill_identifier: an identifier for the bill to retrieve. Returns: Either an array with the bill specified by bill_identifier or an iterator for all bills that will be voted upon. """ bill = None if bill_identifier: bill = PymongoDB.get_db().find_one(db_constants.BILLS, queries.bill_query(bill_identifier)) if bill: return [bill] else: if bill_identifier: logger.LOGGER.error("Bill not found: %s" % bill_identifier) return PymongoDB.get_db().find(db_constants.BILLS)
def normative_stance(stance): """Checks if a given stance is the normative stance on the issue (i.e. the way most people in the country feel about the issue). Argument: stance: the stance to check Returns: True if the stance is normative, False otherwise. """ stance_issue = PymongoDB.get_db().find_one(db_constants.ISSUES, queries.issue_query(stance.issue)) if not stance_issue: logger.LOGGER.error("Issue not found: " + str(stance.issue)) if stance_issue and stance_issue.norm: return stance.match(stance_issue.norm) return False
def _retrieve_strategy_list(): """ Queries the database and finds all StrategyEntry's that are active. It returns them in an array sorted by their rank. This list specifies the strategies that should be applied to the decision and their order. Returns: An array of StrategyEntry's in the database that are active sorted by rank. """ strategy_entries = [] for strategy_entry in PymongoDB.get_db().find(db_constants.STRATEGIES): if strategy_entry.active: strategy_entries.append(strategy_entry) sort_key_fun = lambda strat_entry: strat_entry.rank strategy_entries.sort(key=sort_key_fun) return strategy_entries
def _run(self): """Implements the logic of Best for the Country.""" result = self._consensus() country = PymongoDB.get_db().find_one(db_constants.GROUPS, queries.group_query(self._COUNTRY)) if not country: logger.LOGGER.warning("Country group not found in DB.") return filter_fun = lambda stance: queries.is_group_identified(stance.source, country) country_for = filter(filter_fun, self._decision.groups_for) country_agn = filter(filter_fun, self._decision.groups_agn) if result == outcomes.FOR and country_for and not country_agn: self._country_stances = country_for self._set_decision(result) elif result == outcomes.AGN and country_agn and not country_for: self._country_stances = country_agn self._set_decision(result)
def dump_data(): """Dumps the current data from the database into json files.""" config_db = config.CONFIG[config_constants.DATABASE] DATABASE_PATH = "%s/../../../database/%s" % (os.path.dirname(__file__), config_db) DB = PymongoDB.get_db() print "Dumping %s database data" % config_db print "Target Directory: %s" % DATABASE_PATH print "Running..." for collection_name in db_constants.DB_COLLECTIONS: file_name = "%s/%s.txt" % (DATABASE_PATH, collection_name) with open(file_name, 'w') as dump_file: for data in DB.DB[collection_name].find({}): dump_result = json_util.dumps(data, indent=4, sort_keys=True) dump_file.write(dump_result + '\n') print collection_name + " dumped." print "Finished."
def setUp(self): self.DB = PymongoDB.get_db() load_data.load_data() self.member = self.DB.find_one(db_constants.MEMBERS, {"full_name" : "member_analyze_test"}) self.BILL1 = "BILL1" self.BILL2 = "BILL2" self.BILL3 = "BILL3" self.GROUP1 = "GROUP1" self.GROUP2 = "GROUP2" self.bill1 = self.DB.find_one(db_constants.BILLS, queries.bill_query(self.BILL1)) self.bill2 = self.DB.find_one(db_constants.BILLS, queries.bill_query(self.BILL2)) self.bill3 = self.DB.find_one(db_constants.BILLS, queries.bill_query(self.BILL3)) self.group1 = self.DB.find_one(db_constants.GROUPS, queries.bill_query(self.GROUP1)) self.group2 = self.DB.find_one(db_constants.GROUPS, queries.bill_query(self.GROUP2))
def setUp(self): self.DB = PymongoDB.get_db() load_data.load_data()