def sharing_winners(): """ Pick winner from amongst all users who are eligible winners. This tool examines all participants in the newest sharing challenge, and prints ones that could win it. The newest challenge is picked automatically based on creation date, and everyone who has completed all todos is considered eligible to win. The winner is chosen based on the opening, closing, highest and lowest values of AEX index (Amsterdam Stock Exchange) from this week Tuesday. In order to make sure that the result is indeed deterministic, make sure that the stock has already closed for the day before calling the script: otherwise e.g. the closing price can still change. """ tool = PartyTool(HEADER) challenge_id = tool.current_sharing_weekend()["id"] challenge = Challenge(HEADER, challenge_id) click.echo(challenge.completer_str()) click.echo("") today = datetime.date.today() last_tuesday = today - datetime.timedelta(today.weekday() - 1) click.echo(challenge.winner_str(last_tuesday, "^AEX"))
def party_members(): """ Show current party members. """ tool = PartyTool(HEADER) members = tool.party_members() for member in members: print(u"{:<20}(@{})".format(member.displayname.replace("\n", " "), member.login_name))
def participants(challenge_name): """ Print list of everyone who completed CHALLENGE_NAME The given challenge name can be a substring of the whole name. If there are more than one matchin challenge, the newest one of them is returned. """ tool = PartyTool(HEADER) challenge_id = tool.newest_matching_challenge([challenge_name], [])["id"] challenge = Challenge(HEADER, challenge_id) click.echo(challenge.completer_str())
def update_partymember_data(self): """ Fetch current party member data from Habitica and update the database. If the database contains members that are not currently in the party, they are removed from the database. """ self._logger.debug("Going to update partymember data in the DB.") partytool = PartyTool(self._header) partymembers = partytool.party_members() self.add_new_members(partymembers) self._logger.debug("Added new members") self.remove_old_members(partymembers) self._logger.debug("Removed outdated members")
def __init__(self, header, challenge_id): """ Create a class for a challenge. :header: Header to use with API :challenge_id: The ID of the represented challenge """ self.id = challenge_id # pylint: disable=invalid-name self._header = header self._full_data = utils.get_dict_from_api( header, "https://habitica.com/api/v3/challenges/{}".format(challenge_id)) self._party_tool = PartyTool(header) self._participants = None self._completers = None
def party_birthdays(): """ Update party birthdays in the birthday calendar and print them. The birthdays are stored in the Google calendar whose ID is specified as BIRTHDAYS in conf/calendars.py. """ tool = PartyTool(HEADER) members = tool.party_members() for member in members: bday = member.habitica_birthday result = tool.ensure_birthday(calendars.BIRTHDAYS, member) output = u"{:<20} {}.{}.{}\t{}".format(member.login_name, bday.day, bday.month, bday.year, result[1]) click.echo(output)
def pick_winner(challenge_name, stock_timestamp, stock_name): """ Print participants and random-selected winner for a challenge. """ tool = PartyTool(HEADER) challenge_id = tool.newest_matching_challenge([challenge_name], [])["id"] challenge = Challenge(HEADER, challenge_id) click.echo(challenge.completer_str()) click.echo("") if not stock_timestamp: stock_date = datetime.date.today() else: try: stock_date = datetime.datetime.strptime(stock_timestamp, "%Y%m%d") except ValueError: click.echo("Given stock_date does not seem to be a valid " "timestamp. It must be given in ISO-8601 format as " "`YYYYMMDD`.") sys.exit(1) click.echo(challenge.winner_str(stock_date, stock_name))
class Challenge(): """ Data and operations for an existing Habitica challenge. """ def __init__(self, header, challenge_id): """ Create a class for a challenge. :header: Header to use with API :challenge_id: The ID of the represented challenge """ self.id = challenge_id # pylint: disable=invalid-name self._header = header self._full_data = utils.get_dict_from_api( header, "https://habitica.com/api/v3/challenges/{}".format(challenge_id)) self._party_tool = PartyTool(header) self._participants = None self._completers = None @property def participants(self): """ A list of all party members who have joined the challenge. """ if self._participants is None: self._participants = self._party_tool.challenge_participants( self.id) return self._participants @property def completers(self): """ A list of party members who have completed all challenge todo tasks. """ if self._completers is None: self._completers = sorted( self._party_tool.eligible_winners(self.id, self.participants)) return self._completers @property def name(self): """ The name of the challenge. """ return self._full_data["name"] @name.setter def name(self, name): """ Rename the challenge. This method only affects the local copy of the challenge: the update() method needs to be called to send the changes to Habitica. """ self._full_data["name"] = name @property def summary(self): """ The challenge summary. """ return self._full_data["summary"] @summary.setter def summary(self, summary): """ Change the summary of the challenge. This method only affects the local copy of the challenge: the update() method needs to be called to send the changes to Habitica. """ self._full_data["summary"] = summary @property def description(self): """ The challenge description. """ return self._full_data["description"] @description.setter def description(self, description): """ Change the challenge description. This method only affects the local copy of the challenge: the update() method needs to be called to send the changes to Habitica. """ self._full_data["description"] = description def update(self): """ Update the name, description and summary of the challenge. """ new_data = { "name": self.name, "description": self.description, "summary": self.summary } habrequest.put("https://habitica.com/api/v3/challenges/{}".format( self.id), data=new_data, headers=self._header) def completer_str(self): """ Return a string listing all people who completed the challenge """ if len(self.completers) == 0: return ("Nobody completed all tasks for challenge \"{}\"." "".format(self.name)) intro = ("The party members who completed all todo tasks for " "challenge \"{}\" are:\n".format(self.name)) completer_lines = ["- {}".format(member) for member in self.completers] return intro + "\n".join(completer_lines) def random_winner(self, date, stock): """ Pick a winner for the challenge, based on the values of stock on a date :date: Date object representing the date from which to use the stock data. :stock: Stock to use, e.g. "^AEX". Make sure that the stock has already closed for the day used: otherwise the result might still change. :returns: The Member who won the challenge """ randomizer = StockRandomizer(stock, date) winner_index = randomizer.pick_integer(0, len(self.completers) - 1) return self.completers[winner_index] def winner_str(self, date, stock): """ Pick a winner as `winner` does, but return a string. The returned string states the date, stock and seed used to pick the winner, together with the name of the winner. :date: Date object representing the date from which to use the stock data. :stock: Stock to use, e.g. "^AEX". Make sure that the stock has already closed for the day used: otherwise the result might still change. :returns: A string describing the process. """ randomizer = StockRandomizer(stock, date) winner = self.random_winner(date, stock) return ("Using stock data for {} from {} (seed {}).\n\n" "{} wins the challenge!".format(date, stock, randomizer.seed, winner)) def award_winner(self, winner): """ Award the given user as the winner for the challenge. :winner: UID of the winner """ response = habrequest.post( "https://habitica.com/api/v3/challenges/{}/selectWinner/{}" "".format(self.id, winner), headers=self._header) response.raise_for_status() def clone(self): """ Create a clone of this challenge and return its ID. """ resp = habrequest.post( "https://habitica.com/api/v3/challenges/{}/clone" "".format(self.id), headers=self._header) resp.raise_for_status() return resp.json()["data"]["id"] def add_task(self, taskdata): """ Add a new task to this challenge. :taskdata: A dict representing the new task, see https://habitica.com/apidoc/#api-Task-CreateChallengeTasks for keys and their values """ resp = habrequest.post( "https://habitica.com/api/v3/tasks/challenge/{}".format(self.id), data=taskdata, headers=self._header) resp.raise_for_status()