Skip to content

Instantly share code, notes, and snippets.

@maddievision
Last active December 10, 2015 09:19
Show Gist options
  • Save maddievision/4413695 to your computer and use it in GitHub Desktop.
Save maddievision/4413695 to your computer and use it in GitHub Desktop.
Wanikani messy Python
WK_API_KEY = 'dick' #API key which will be used for general stuff
import requests, datetime, time, pytz, romkan
WK_CACHE_TIME = 10 * 60
WK_MAX_LEVEL = 25
WK_ALL_LEVELS = [x+1 for x in xrange(WK_MAX_LEVEL)]
WK_API_URL = 'http://www.wanikani.com/api/user/%s/%s/%s'
WK_UTC = pytz.utc
wk_display_type = {u'radical': "Radical", u'kanji': "Kanji", u'vocabulary': "Vocabulary"}
wk_cache = {}
class WK(object):
def __init__(self):
self.user = WKUser(WK_API_KEY)
def radicals(self,levels=[]):
return [x for x in self.user.radicals(WK_ALL_LEVELS,include_all=True) if len(levels) == 0 or x.level() in levels]
def kanji(self,levels=[]):
return [x for x in self.user.kanji(WK_ALL_LEVELS,include_all=True) if len(levels) == 0 or x.level() in levels]
def vocabulary(self,levels=[]):
return [x for x in self.user.vocabulary(WK_ALL_LEVELS,include_all=True) if len(levels) == 0 or x.level() in levels]
def all(self):
return self.radicals() + self.kanji() + self.vocabulary()
def display_matches(self,query,levels=[],types=[],reading=True,reading_type="a",meaning=True,character=True):
return ', '.join([x.display() for x in self.matches(query,levels,types,reading,reading_type,meaning,character)])
def matches(self,query,levels=[],types=[],reading=True,reading_type="a",meaning=True,character=True):
return [x for x in self.all() if x.matches(query,levels,types,reading,reading_type,meaning,character)]
def __repr__(self):
return '<WK object>'
class WKUser(object):
def __init__(self,user_api_key):
self.user_api_key = user_api_key
def username(self):
return self.__r_user_information()["username"]
def gravatar(self):
return self.__r_user_information()["gravatar"]
def level(self):
return int(self.__r_user_information()["level"])
def title(self):
return self.__r_user_information()["title"]
def about(self):
return self.__r_user_information()["about"]
def website(self):
return self.__r_user_information()["website"]
def twitter(self):
return self.__r_user_information()["twitter"]
def topics_count(self):
return int(self.__r_user_information()["topics_count"])
def posts_count(self):
return int(self.__r_user_information()["posts_count"])
def creation_date(self):
return wk_datetime(self.__r_user_information()["creation_date"])
def lessons_available(self):
return int(self.__r_study_queue()["lessons_available"])
def reviews_available(self):
return int(self.__r_study_queue()["reviews_available"])
def next_review_date(self):
return wk_datetime(self.__r_study_queue()["next_review_date"])
def reviews_available_next_hour(self):
return int(self.__r_study_queue()["reviews_available_next_hour"])
def reviews_available_next_day(self):
return int(self.__r_study_queue()["reviews_available_next_day"])
def radicals_progress(self):
return int(self.__r_level_progression()["radicals_progress"])
def radicals_total(self):
return int(self.__r_level_progression()["radicals_total"])
def radicals_percentage(self):
return float(self.radicals_progress()) / float(self.radicals_total())
def kanji_progress(self):
return int(self.__r_level_progression()["kanji_progress"])
def kanji_total(self):
return int(self.__r_level_progression()["kanji_total"])
def kanji_percentage(self):
return float(self.kanji_progress()) / float(self.kanji_total())
def srs_by_level(self):
return self.__r_srs_distribution()
def srs_by_type(self):
inp = self.__r_srs_distribution()
out = {}
for sl in inp.keys():
for st in inp[sl].keys():
if st not in out:
out[st] = {}
out[st][sl] = inp[sl][st]
return out
def recent_unlocks(self,limit=10):
inp = self.__r_recent_unlocks(100)
return [WKUnlock(a) for a in inp][0:limit]
def critical_items(self,max=0.75):
inp = self.__r_critical_items(100)
return [WKCritical(a) for a in inp if (float(a["percentage"])/100.0) <= max]
def radicals(self,levels=[],include_all=False):
inp = self.__r_radicals(WK_ALL_LEVELS)
return [WKListing("radical",a) for a in inp if ((a["stats"] or include_all) and (len(levels) == 0 or int(a["level"]) in levels))]
def kanji(self,levels=[],include_all=False):
inp = self.__r_kanji(WK_ALL_LEVELS)
return [WKListing("kanji",a) for a in inp if ((a["stats"] or include_all) and (len(levels) == 0 or int(a["level"]) in levels))]
def vocabulary(self,levels=[],include_all=False):
inp = self.__r_vocabulary(WK_ALL_LEVELS)
return [WKListing("vocabulary",a) for a in inp if ((a["stats"] or include_all) and (len(levels) == 0 or int(a["level"]) in levels))]
def __request(self,resource,argument=""):
return wk_request(self.user_api_key,resource,argument)
def __r_user_information(self):
return self.__request("user-information")["user_information"]
def __r_study_queue(self):
return self.__request("study-queue")["requested_information"]
def __r_level_progression(self):
return self.__request("level-progression")["requested_information"]
def __r_srs_distribution(self):
return self.__request("srs-distribution")["requested_information"]
def __r_recent_unlocks(self,limit=10):
return self.__request("recent-unlocks",str(limit))["requested_information"]
def __r_critical_items(self,max=75):
return self.__request("critical-items",str(max))["requested_information"]
def __r_radicals(self,level_list=[]):
return self.__request("radicals",','.join([str(i) for i in level_list]))["requested_information"]
def __r_kanji(self,level_list=[]):
return self.__request("kanji",','.join([str(i) for i in level_list]))["requested_information"]
def __r_vocabulary(self,level_list=[]):
return self.__request("vocabulary",','.join([str(i) for i in level_list]))["requested_information"]
def __repr__(self):
return "<WKUser: %s (L%d)>" % (self.username(),self.level())
class WKItem(object):
def __init__(self,object_data):
self.object_data = object_data
def ascii_display(self):
if self.item_type() == 'radical':
return 'R%d %s' % (self.level(),self.meaning())
else:
return '%s%d %s [%s]' % (self.display_type()[0],self.level(),self.meaning(),self.romaji())
def display(self):
if self.item_type() == 'radical':
if self.character():
return 'R%d %s (%s)' % (self.level(),self.character(),self.meaning())
else:
return 'R%d %s' % (self.level(),self.meaning())
else:
return '%s%d %s (%s) [%s]' % (self.display_type()[0],self.level(),self.character(),self.meaning(),self.reading())
def display_type(self): return wk_display_type[self.item_type()]
def item_type(self): return self.object_data["type"]
def character(self): return self.object_data["character"]
def kana(self): return self.object_data["kana"]
def kanas(self): return wk_comma_split(self.kana())
def kana_romaji(self): return wk_romaji(self.kana())
def kana_romajis(self): return wk_comma_split(self.kana_romaji())
def image(self): return self.object_data["image"]
def meaning(self): return self.object_data["meaning"]
def meanings(self): return wk_comma_split(self.meaning())
def onyomi(self): return self.object_data["onyomi"] if "onyomi" in self.object_data else None
def onyomis(self): return wk_comma_split(self.onyomi()) if self.onyomi() else []
def onyomi_romaji(self): return wk_romaji(self.onyomi()) if self.onyomi() else ""
def onyomi_romajis(self): return wk_comma_split(self.onyomi_romaji()) if self.onyomi() else []
def kunyomi(self): return self.object_data["kunyomi"] if "kunyomi" in self.object_data else None
def kunyomis(self): return wk_comma_split(self.kunyomi()) if self.kunyomi() else []
def kunyomi_romaji(self): return wk_romaji(self.kunyomi()) if self.kunyomi() else ""
def kunyomi_romajis(self): return wk_comma_split(self.kunyomi_romaji()) if self.kunyomi() else []
def important_reading(self): return self.object_data["important_reading"]
def romaji(self):
return wk_romaji(self.reading()) if self.reading() else ""
def romajis(self): return wk_comma_split(self.romaji()) if self.reading() else []
def reading(self):
if (self.item_type() == u'kanji'):
return self.object_data[self.important_reading()]
elif self.item_type() == u'vocabulary':
return self.kana()
else:
return None
def readings(self): return wk_comma_split(self.reading()) if self.reading() else []
def all_readings(self):
if (self.item_type() == u'kanji'):
return self.onyomis() + self.kunyomis()
elif (self.item_type() == u'radical'):
return []
else:
return self.kanas()
def all_romajis(self):
if (self.item_type() == u'kanji'):
return self.onyomi_romajis() + self.kunyomi_romajis()
elif (self.item_type() == u'radical'):
return []
else:
return self.kana_romajis()
def matches(self,query,levels=[],types=[],reading=True,reading_type="a",meaning=True,character=True):
if len(levels) > 0 and self.level() not in levels: return False
if len(types) > 0 and self.display_type()[0].lower() not in [x.lower()[0] for x in types]: return False
query = query.strip().lower()
if meaning and query in [x.lower() for x in self.meanings()]: return True
if reading and reading_type.lower()[0] == "a" and query in [x.lower() for x in self.all_romajis()]: return True
if reading and reading_type.lower()[0] == "a" and query in self.all_readings(): return True
if reading and reading_type.lower()[0] == "i" and query in [x.lower() for x in self.readings()]: return True
if reading and reading_type.lower()[0] == "i" and query in self.romajis(): return True
if reading and reading_type.lower()[0] == "k" and query in [x.lower() for x in self.kunyomis()]: return True
if reading and reading_type.lower()[0] == "k" and query in [x.lower() for x in self.kunyomi_romajis()]: return True
if reading and reading_type.lower()[0] == "o" and query in [x.lower() for x in self.onyomis()]: return True
if reading and reading_type.lower()[0] == "o" and query in [x.lower() for x in self.onyomi_romajis()]: return True
if character and query == self.character(): return True
return False
def level(self): return int(self.object_data["level"])
def __repr__(self):
return '<%s: %s>' % (self.__class__.__name__,self.ascii_display())
class WKUnlock(WKItem):
def unlocked_date(self): return wk_datetime(self.object_data["unlocked_date"])
class WKCritical(WKItem):
def percentage(self): return float(wk_datetime(self.object_data["percentage"]))/100.0
class WKListing(WKItem):
def __init__(self,item_type,object_data):
self.object_data = object_data
self.object_data["type"] = item_type
def srs_type(self): return self.__stats()["srs"]
def unlocked_date(self): return wk_datetime(self.__stats()["unlocked_date"])
def available_date(self): return wk_datetime(self.__stats()["available_date"])
def burned(self): return self.__stats()["burned"]
def burned_date(self): return wk_datetime(self.__stats()["burned_date"])
def meaning_correct(self): return int(self.__stats()["meaning_correct"])
def meaning_incorrect(self): return int(self.__stats()["meaning_incorrect"])
def meaning_max_streak(self): return int(self.__stats()["meaning_max_streak"])
def meaning_current_streak(self): return int(self.__stats()["meaning_current_streak"])
def reading_correct(self): return int(self.__stats()["reading_correct"])
def reading_incorrect(self): return int(self.__stats()["reading_incorrect"])
def reading_max_streak(self): return int(self.__stats()["reading_max_streak"])
def reading_current_streak(self): return int(self.__stats()["reading_current_streak"])
def __stats(self): return self.object_data["stats"]
def wk_timestamp():
return time.mktime(datetime.datetime.now().timetuple())
def wk_datetime(timestamp):
return datetime.datetime.fromtimestamp(int(timestamp),WK_UTC)
def wk_url(user_api_key,resource,argument=""):
return WK_API_URL % (user_api_key,resource,argument)
def wk_request(user_api_key,resource,argument=""):
url = wk_url(user_api_key,resource,argument)
resp = {}
if url not in wk_cache or wk_timestamp() > (wk_cache[url]['time'] + WK_CACHE_TIME):
resp = requests.get(url=url).json
wk_cache[url] = {
'time': wk_timestamp(),
'response': resp
}
else:
resp = wk_cache[url]['response']
return resp
def wk_romaji(kanastring):
return romkan.to_roma(kanastring)
def wk_comma_split(commastring):
return [a.strip() for a in commastring.split(',')]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment