def count_change( requester: nsapi.NSRequester, nations: t.Collection[str], start: datetime.date, end: datetime.date, ) -> t.Tuple[t.Mapping[str, int], t.Iterable[str]]: """For each nation provided, retrieves the number of issues they have answered between the two dates. The returned mapping contains .clean_format version of nation names. """ starting = {} ending = {} invalid = [] # Get the starting number of issues for nation in requester.dumpManager().nations(date=start): # Check if either normal or clean name was provided if nation.name in nations or nsapi.clean_format( nation.name) in nations: starting[nsapi.clean_format(nation.name)] = nation.issuesAnswered # Get the ending number of issues for nation in requester.dumpManager().nations(date=end): # Check if either normal or clean name was provided if nation.name in nations or nsapi.clean_format( nation.name) in nations: ending[nsapi.clean_format(nation.name)] = nation.issuesAnswered # Check/make sure both starting/ending have all the nations # (e.g. differences may occur when a nation ceased to exist, was founded, etc) # If a nation didnt exist on the start date, it started with 0 answered. # If a nation didnt exist on the end date, it must have CTE # there is not really an easy way of finding the ending number of issues answered, # so we cant really calculate. for nationName in nations: if nationName not in starting: starting[nationName] = 0 if nationName not in ending: starting.pop(nationName) # track the invalid nations invalid.append(nationName) # Calculate the difference between end and start for each nation in # starting, which should have identical keys to ending so it doesnt matter # which one we iterate through # Standardize nation name formatting delta = { nsapi.clean_format(nationName): ending[nationName] - starting[nationName] for nationName in starting } return delta, invalid
def low_endorsements(requester: nsapi.NSRequester, region: str, count: int = 20) -> Collection[str]: """ Finds nations with low endorsements. Searches the nation dump for WA nations in the specified region with less endorsements than the given count. """ filtered = [] # Squash casing on region lower_region = region.lower() # Search for matching nations for nation in requester.dumpManager().nations(): if ( # Compare regions, case insensitive nation.region.lower() == lower_region # Check that in WA and nation.WAStatus.startswith("WA") # Check that endorsements are under the specified level and len(nation.endorsements) <= count): # Save to return at end of search filtered.append(nation.name) return filtered
def founder_endings( requester: nsapi.NSRequester, since: t.Optional[int] = None, before: t.Optional[int] = None, referenceDate: datetime.date = None, ) -> t.Iterable[Ending]: """Returns the founder endings in the given timestamp frame. `before` defaults to now, and `since` defaults to 24 hours ago. Uses the given referenceDate to retrive a region dump to cross-reference with endings with region founders (defaults to most recent dump). """ endings = retrieve_endings(requester, since, before) # convert endings to nation: region map endingRegions = { nsapi.clean_format(ending.nation): ending.region for ending in endings } # cross reference with region dump founderEndings = ( Ending( nation=nsapi.clean_format(region.founder), region=endingRegions[nsapi.clean_format(region.founder)], ) for region in requester.dumpManager().regions(date=referenceDate) if nsapi.clean_format(region.founder) in endingRegions.keys()) return founderEndings
def unendorsed_nations( requester: nsapi.NSRequester, endorser: str ) -> Tuple[str, Iterable[str]]: """Finds all WA members of the nation's region who have not been endorsed Returns a tuple containing the region, and a iterable of unendorsed nations """ # Collect region region = requester.nation(endorser).shard("region") # Load downloaded nation file # Pack into conversion generator to simplify transformations nationDump = requester.dumpManager().nations() # Pull all nations in the region that are WA members # Use generator because we dont need to generate a list that is never used logging.info("Collecting %s WA Members", region) waMembers = [ nation for nation in nationDump if nation.region == region and nation.WAStatus.startswith("WA") ] # Pull nations who are not endorsed logging.info("Collecting WA members who have not been endorsed") nonendorsed = [ # Save name string, converting to lowercase, underscore format clean_format(nation.name) for nation in waMembers # Check if unendorsed by checking endorsements if endorser not in nation.endorsements ] return (region, nonendorsed)
def factbook_searcher( requester: nsapi.NSRequester, *keywords: str, populationMinimum: int = 0) -> Sequence[nsapi.RegionStandard]: """Returns Region's which have at least one of the given keywords in their WFE (.factbook)""" return [ region # Maps from XML to RegionStandard, should be single pass since its a generator wrapping for region in requester.dumpManager().regions() # Probably not the most efficient (probably O(n^2)) if any( keyword in region.factbook for keyword in keywords) and region.numnations > populationMinimum ]
def named_cards( requester: nsapi.NSRequester, cards: Iterable[nsapi.CardIdentifier], ) -> Mapping[int, str]: """Maps each CardIdentifier to the nation name, using the card dumps. Returns a mapping from id to name """ cardMap = {card.id: "" for card in cards} for standard in itertools.chain( requester.dumpManager().cards(season="1"), requester.dumpManager().cards(season="2"), ): if standard.id in cardMap: cardMap[standard.id] = standard.name return cardMap
def find_rarities(requester: nsapi.NSRequester, rarity: str) -> None: """Searches both card dumps for cards of the specified rarity and saves the id/season to a file of the same name""" # Goes through each dump, grabbing any CardStandard that has the right rarity # store season with it, since the CardStandard does not have season cards = [] for card in requester.dumpManager().cards(season="1"): if card.rarity == rarity: cards.append((card, "1")) for card in requester.dumpManager().cards(season="2"): if card.rarity == rarity: cards.append((card, "2")) # Dump everything as strings so its easier to use with open(resolve_path(rarity), "w") as file: json.dump( [{ "cardid": str(card.id), "season": season, "name": card.name } for card, season in cards], file, )
def get_nations_by_region( requester: nsapi.NSRequester, regions: t.Iterable[str] ) -> t.Mapping[str, t.Iterable[str]]: """Returns an mapping from region to all residents of that region. """ regionSet = set(nsapi.clean_format(string) for string in regions) output: t.Dict[str, t.List[str]] = {} for region in requester.dumpManager().regions(): if nsapi.clean_format(region.name) in regionSet: output[nsapi.clean_format(region.name)] = [ nsapi.clean_format(name) for name in region.nations ] return output
def collect(requester: nsapi.NSRequester, region: str) -> t.Mapping[str, t.Iterable[str]]: """Compiles the endorsees of every WA nation in the region.""" # Cross-reference region nations and WA members region_nations = set(requester.region(region).nations()) wa_nations = set(requester.wa().shard("members").split(",")) members = region_nations & wa_nations # A dict mapping each WA member of this region to the nations they endorse endorsees: t.Dict[str, t.List[str]] = {member: [] for member in members} # Parse nation dump for nation in requester.dumpManager().nations(): # Search for nations that are WA in this region if nation in members: for endorser in nation.endorsements: endorsees[endorser].append(nation.name) return endorsees