Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python3
- """
- Goes through the quests.html file pulled from http://kancolle.wikia.com/wiki/Quests and builds
- a dependency graph based off of A23, the earliest quest that requires Shoukaku. Could be adapted
- to make a more complete quest dependency graph but not having Shoukaku has made me mad enough to
- the point to have this script directly target that dumb crane.
- """
- import bs4
- import pprint
- import re
- questIdentifier = re.compile("\w\d{1,3}")
- thatFuckingQuest = "A23"
- unlockText = "Unlock"
- requiresText = "Requires:"
- quests = {}
- class Quest():
- """
- Basic building blocks of Kancolle quests
- """
- def __init__(self, num):
- self.id = num
- self.requires = []
- self.unlocks = []
- def __str__(self):
- reqs = ",".join(self.requires)
- unlocks = ",".join(self.unlocks)
- return "\n".join(["id: " + self.id, "requires: " + reqs, "unlocks: " + unlocks, ""])
- def traverse():
- """
- Go through and build the dependency graph for the shoukaku quest
- """
- init = [quests[thatFuckingQuest].unlocks]
- layers = []
- while len(init) > 0:
- layer = init.pop(0)
- layers.append(layer)
- newLayer = []
- for quest in layer:
- newLayer.extend(quests[quest].unlocks)
- if len(newLayer) == 0:
- break
- init.append(newLayer)
- return layers
- def quests_only(x):
- """
- Filters out any nested tags and strings that are not quest strings
- """
- flattenedElements = []
- elements = x
- testString = lambda x: questIdentifier.search(x) is not None
- # Flatten out any non String elements
- while len(elements) > 0:
- ele = elements.pop()
- if not isinstance(ele, bs4.element.NavigableString):
- elements.extend(ele.contents)
- else:
- flattenedElements.append(ele)
- return filter(testString, flattenedElements)
- def populate_quests():
- """
- Goes through the quests.html file and pulls out all quests. Includes requirements and unlocks.
- """
- with open("quests.html", "r") as f:
- soup = bs4.BeautifulSoup(f, "lxml")
- rows = soup.find_all("tr")
- currentQuest = None
- for r in rows:
- if "class" in r.attrs:
- rowClass = r.attrs["class"]
- assert(len(rowClass) == 1)
- rowClass = rowClass[0]
- if "details" in rowClass:
- # Quest itself. Find the Requirements and Unlocks.
- for c in r.contents:
- if isinstance(c, bs4.element.NavigableString):
- # Ignore quest descriptions
- continue
- insertUnlocks = 0
- for sc in c.contents:
- if isinstance(sc, bs4.element.NavigableString):
- # Check for "Unlock" or "Requires" strings
- if unlockText in sc:
- insertUnlocks = 1
- elif requiresText in sc:
- insertUnlocks = -1
- if isinstance(sc, bs4.element.Tag):
- # Pull out all the identifiers for other quests
- if insertUnlocks > 0:
- currentQuest.unlocks.extend(quests_only(sc.contents))
- elif insertUnlocks < 0:
- currentQuest.requires.extend(quests_only(sc.contents))
- else:
- continue
- # Entire quest has been assembled. Stick it in the map and reset
- quests[currentQuest.id] = currentQuest
- currentQuest = None
- elif "id" in r.attrs and rowClass.startswith("quest_"):
- # ID of the quest is here. Begin quest generation
- currentQuest = Quest(r.attrs["id"])
- else:
- # No useful information. Reset just in case
- continue
- else:
- continue
- if __name__ == "__main__":
- populate_quests()
- damage = traverse()
- tabs = 0
- totalQuests = 0
- for d in damage:
- totalQuests += len(d)
- print(" "*tabs + " ".join(d))
- tabs += 1
- print("Total quests that depend on Shoukaku: ", totalQuests)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement