// ==UserScript==
// @name Ky.is WaniKani JS Replacement
// @namespace rfindley
// @description Replaces Javascript on ky.is/wanikani to support WaniKani updates.
// @include http://ky.is/wanikani/*
// @version 1.0.3
// @author Robin Findley
// @copyright 2015+, Robin Findley
// @license MIT; http://opensource.org/licenses/MIT
// @run-at document-start
// @grant none
// ==/UserScript==
/*
//=========================================================================================================
The following code block fetches the number of kanji in each level on WaniKani.
Paste the code in the javascript console while on the WaniKani Dashboard.
It should output something like this:
new_KANJI_LEVEL_SIZES = [18,38,33,38,42,40,33,32,35,35,38,37,37,32,33,35,33,29,34,32,32,31,31,31,33,33,32,34,33,31,36,33,32,34,32,33,32,32,34,32,30,33,35,34,35,37,36,37,33,35,35,35,35,35,35,35,35,35,35,32];
//--[ begin ]---------------------------------
var level_hrefs=[];
$('.nav .levels li a').each(function(i,e){level_hrefs.push($(e).attr('href'));});
var num_levels = level_hrefs.length;
var num_kanji = [];
$(level_hrefs).each(function(i,href){
num_kanji[i] = 0;
$.get(href,function(data){
num_kanji[i] = $(data).find('.single-character-grid li[id^="kanji"]').length;
});
});
console.log('new_KANJI_LEVEL_SIZES = ['+num_kanji+'];');
//--[ end ]---------------------------------
//=========================================================================================================
*/
new_KANJI_LEVEL_SIZES = [18,38,33,38,42,40,33,32,35,35,38,37,37,32,33,35,33,29,34,32,32,31,31,31,33,33,32,34,33,31,36,33,32,34,32,33,32,32,34,32,30,33,35,34,35,37,36,37,33,35,35,35,35,35,35,35,35,35,35,32];
var new_stats = [
['Grade 1', 8],
['Grade 2', 18],
['JLPT4', 27],
['', 40],
['', 50],
['complete!', 60]
];
var number_of_standard_deviations = 2.0;
function DayDateAt(sec){
sec = Math.ceil(sec / (15*60)) * (15*60);
var t = new Date(sec*1000)
var wday = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'][t.getDay()];
var hh = ((t.getHours()+23) % 12)+1;
var mm = t.getMinutes(); if (mm<10) mm = "0"+mm;
var ampm = (t.getHours()<12 ?'am':'pm')
return '('+wday+' '+hh+':'+mm+ampm+')';
}
function daysHours(t) {
return '['+(Math.floor(Math.round(t/3600)/24))+' days, '+(Math.round(t/3600)%24)+' hours]';
}
function new_statsCallback(data, status) {
if (!callbackCheck(data))
return;
var radicals_data = data.requested_information;
if (!radicals_data) {
alert('Unable to load your WaniKani API data');
return;
}
var user_data = data.user_information;
currentLevel = user_data.level;
$('#stats-data').removeClass('hidden');
var currentTime = Math.round(new Date().getTime() / 1000);
var levelStats = new Array(currentLevel);
for (var idx in radicals_data) {
var rd = radicals_data[idx];
var stats = rd.user_specific;
if (stats) {
var lvlIdx = rd.level - 1;
var cbt = levelStats[lvlIdx];
var timing = stats.unlocked_date;
if (!cbt || timing < cbt)
levelStats[lvlIdx] = timing;
}
}
if (!levelStats[currentLevel-1])
levelStats[currentLevel-1] = currentTime;
var currentLevelTime;
levelStats[currentLevel] = currentTime;
lastLevelUp = levelStats[currentLevel - 1];
currentLevelTime = currentTime - levelStats[currentLevel - 1];
var timePerLevel = new Array(currentLevel - 1);
var levelTimes = new Array(currentLevel);
var longestLevelTime = 0, fastestLevelTime = Number.MAX_VALUE;
for (var i=0; i<currentLevel; ++i) {
var diff = levelStats[i+1] - levelStats[i];
levelTimes[i] = diff;
if (diff > longestLevelTime)
longestLevelTime = diff;
if (i < currentLevel - 1) {
timePerLevel[i] = diff;
if (diff < fastestLevelTime)
fastestLevelTime = diff;
}
}
longestLevelTime /= T2DAYS;
fastestLevelTime /= T2DAYS;
var maxDays = Math.ceil(longestLevelTime / 3.0) * 3;
var dayInterval = maxDays / 3;
$('form#stats-form').hide();
$('#st-user').html(username + ' <span lang="ja" class="note">' + numberToKanji(currentLevel) + '</span>');
var start_date = new Date(user_data.creation_date * 1000);
var nowTime = new Date().getTime();
var dayDiff = Math.round(((nowTime / 1000) - user_data.creation_date) / 3600 / 24);
$('#st-date').html('Worshiping the Crabigator since ' + start_date.getDate() + ' ' + MONTH_NAMES[start_date.getMonth()] + ' ' + start_date.getFullYear() + ' <em>(' + dayDiff + ' days)</em>');
/* Average time */
var avgTime = 0;
var reject = [];
var stda = [];
var median, medianDev;
if (currentLevel > 1) {
var sortedTimePerLevel = timePerLevel.slice(0);
var sortedDevPerLevel = [];
sortedTimePerLevel.sort(numericalSort);
median = sortedTimePerLevel[Math.floor((currentLevel-1)/2)];
for (var i = 0; i < currentLevel - 1; ++i)
sortedDevPerLevel.push(Math.abs(timePerLevel[i]-median));
sortedDevPerLevel.sort(numericalSort);
medianDev = sortedDevPerLevel[Math.floor((currentLevel-1)*(currentLevel<8?0.5:0.75))];
var min = median-(medianDev*number_of_standard_deviations);
var max = median+(medianDev*number_of_standard_deviations);
var sum=0, cnt=0;
for (var i = 0; i < currentLevel - 1; ++i) {
if (Math.abs(timePerLevel[i]-median) <= (medianDev*number_of_standard_deviations)) {
sum += timePerLevel[i];
cnt++;
} else {
reject.push(i+1);
}
}
avgTime = sum / cnt;
}
if (avgTime < 8 * T2DAYS)
avgTime = 8 * T2DAYS;
averageLevelTime = avgTime;
console.log('Using Median '+daysHours(median)+' +/- '+daysHours(medianDev*number_of_standard_deviations)+'.');
console.log('Averaging levels between '+daysHours(min)+' and '+daysHours(max)+'.');
console.log('Rejecting levels ['+reject.join()+']');
window.currentLevel = currentLevel;
window.averageLevelTime = averageLevelTime;
window.currLevelDiff = currLevelDiff;
window.lastLevelUp = lastLevelUp; currLevelDiff = levelTimes[levelTimes.length - 1];
var curr_level_fraction = currLevelDiff < avgTime ? currentLevel + currLevelDiff / avgTime : currentLevel + 1;
var dates = [];
var labels = [];
var completion = [];
for (var i=0; i<new_stats.length; i++)
{
dates.push(new Date(nowTime + avgTime * (new_stats[i][1] - curr_level_fraction) * 1000));
labels.push('<span class="note">'+new_stats[i][0]+'</span> Level '+('0'+new_stats[i][1]).slice(-2)+':');
completion.push('<span>'+dateFormat(dates[i])+'</span>');
}
labels = labels.join('<br />');
completion = completion.join('<br />');
avgTime /= T2DAYS;
$('#stat-average').html(dayDate(avgTime));
$('#stat-leveltime').html(dayDate(currentLevelTime / T2DAYS));
$('#info-container .info-box:nth-child(2) .info-left').html(labels).css('vertical-align','top');
$('#stat-completion').html(completion).parent().css('vertical-align','top');
var canvas = document.getElementById('levelgraph');
if (canvas.getContext) {
var barW = 96 - (currentLevel * 5);
if (barW < 30)
barW = 30;
canvas.width = currentLevel * (barW + BS) - BS + 40;
canvas.height = GH;
var ctx = canvas.getContext('2d');
ctx.textBaseline = 'top';
ctx.font = '12px sans-serif';
for (var i = 0; i < 4; ++i) {
ctx.fillText(maxDays - i * dayInterval, 2, i * BA / 3);
}
ctx.textAlign = 'center';
ctx.font = '14px sans-serif';
for (var i=0; i<currentLevel; ++i) {
var levelDays = levelTimes[i] / T2DAYS;
var color = i == currentLevel-1 ? 'pink' : levelDays - fastestLevelTime < 0.1 ? 'baby' : longestLevelTime - levelDays < 0.1 ? 'black' : levelDays < avgTime ? 'blue' : 'purp';
drawBar(ctx, i, levelDays, color, barW, levelDays / maxDays * BA);
}
}
/* Levelup */
getApiData(stats_key, 'kanji/' + currentLevel, 'levelupCallback');
}
function new_levelupCallback(data, status) {
if (!callbackCheck(data))
return;
var kanji_data = data.requested_information;
kanji_data.sort(function(a, b) {
var aStats = a.user_specific;
if (!aStats)
return 1;
var bStats = b.user_specific;
if (!bStats)
return -1;
if (aStats.srs !== "apprentice")
return -1;
if (bStats.srs !== "apprentice")
return 1;
var aMax = Math.min(aStats.meaning_current_streak, aStats.reading_current_streak);
var bMax = Math.min(bStats.meaning_current_streak, bStats.reading_current_streak);
if (aMax < bMax)
return 1;
if (aMax > bMax)
return -1;
return aStats.available_date - bStats.available_date;
});
var idx90 = Math.ceil(kanji_data.length * 0.9);
var kanji90 = kanji_data[idx90 - 1];
var statsDict = kanji90.user_specific;
var nextLevelUp;
var cTime = Math.round(new Date().getTime() / 1000);
if (!statsDict) {
var half_level = 4.0 * T2DAYS;
nextLevelUp = lastLevelUp + (averageLevelTime < 8 * T2DAYS ? half_level * 2.0 : averageLevelTime) - cTime;
if (nextLevelUp < half_level)
nextLevelUp = half_level;
} else {
var streak = Math.min(statsDict.meaning_current_streak, statsDict.reading_current_streak);
nextLevelUp = statsDict.available_date - cTime;
if (streak < 3) {
nextLevelUp += 3.0 * T2DAYS;
if (streak < 2) {
nextLevelUp += 1.0 * T2DAYS;
if (streak == 0)
nextLevelUp += 0.17 * T2DAYS;
}
}
}
$('#stat-levelup').html(dayDate(nextLevelUp / T2DAYS));
$('#stat-levelupat').html(DayDateAt(nextLevelUp+cTime));
}
//============================================================================
// Calculate WaniKani coverage charts
function new_data_tables() {
var wk_kanji = '上下大八入工山口九一人力川七十三二女,又玉本子丸正犬夕出目了火五四才手天刀王左中月々田右六小土立石丁日千木水白文円,矢市牛切方戸太父少友毛半心内生久台母午北今古兄元外分公引止用万広冬,竹車央写仕耳早気平花足世打百氷虫字男主名不号他去皿先赤休申見貝皮代礼糸町村年,角青体色来社図毎羽林行金草里作多肉会交近池雨米当走同言自売形空音学光考回谷声西何麦弟,全後血両明京化国死亡画地東食直前有知活長曲首次夜姉点安室科海羊店南星州茶思歩向妹,辺付札鳥黒船以必末氏失魚組家欠未紙通民由理校雪強夏高教時弱週風記黄,答反君局買雲楽数決絵住電森助馬間場医朝番所究道役研身者合支話投対,受事美予始服度発定談表客重持負相要新部和県返乗屋送苦泳仮物具実使待勝界,進酒業算運漢鳴集配飲終顔落農速頭聞院調鉄語葉習軽線最開親読転路病横歌起,功成岸競争便老命指初味追神良意労好昔低育令拾注利位級仲放秒別特共努伝戦波洋働,悪息章登寒深倍勉消祭野階庭港暑湯島童員商都動第期植根悲短球泉流陽歯族旅温着,皆謝整橋選想器暗疑感情料様養緑熱億殺宿福鏡然詩練賞問館映願士課標銀駅像題輪,能芸術雰骨束周協例折基性妥卒固望私材参完松約残求季技格頑囲的念希,紀軍秋信岩仏建猫変晴築勇泣司区英丈夫飯計法晩昼毒昨帰式列浅単坂春寺,浴箱係治危冒留弁証遠園門府幸阪急笑荷政保品守辞真喜関険典専冗存面取曜書,是結底因識干敗渉果官署察堂幻非愛薬覚常鼻無原栄恋塩席側兵説細梅虚警,告達焼借弓脳胸喫等枚忘訓種報句許可祈僧禁静座煙汽験試類洗禅,得加冊履忙閥布比歴続減昆困易絡笛容団史徒宙混善順宇詞改乱節連舌暴財若,裕尻確械犯害議難災嫌夢震在飛産罪穴被個機妨倒経率圧防臭余尾論厚妻,責条済委省制批断任素敵設評検岡増査判審件際企挙認資義権派務税解総,援態誕状賀各費姿勢示寝営坊罰策案提置域応宮吸過領脱統値価副観藤,呼崎施城護鬼割職秀俳停宅裁律導革贅乳収演現備則規準張優沢師幹看,庁額腕境燃担祝届違差象展層視環製述武型狭管載質量販供肩株触輸腰,慣居逮票属捕候輩況響効抜鮮満与掛隠模含訟限肥豊替景巻捜構影絞訴補渡,接再独獣菓討故較創造往励激占障我徴授鉛郵針従豚復河貯印振刺突怪汗筆,怒昇迷招腹睡端極郎康健誘貸惑痛退途給就靴眠暇段胃症濃締迫訪織悩屈,攻撃浜綺益児憲冷処微修博程絶凍巨稚幼並麗奇衆潔清録逆移精隊庫妙券傘婦,略積添寄宴板壊督僚杯娘診乾欧恐猛江韓雄航監宗請怖索臣催街詰緊閣促烈,更魅背騒飾預詳版旗浮越照漏系覧婚懐撮枕遊快貧延押乏盗購適翌渇符,帯廊離径融均除貨孫墓幾尋編陸探豪鑑泥巣普棒粉既救似富散華嘆偵驚掃菜脈徳倉,酸賛祖銭込衛机汚飼複染卵永績眼液採党志興恩序雑桜密秘厳捨訳欲暖迎傷,灰装著裏閉垂漠異皇拡暮忠肺誌操筋否盛宣賃敬尊熟砂簡蒸蔵糖納宝諸窓,豆枝揮刻爪承幕紅歓降劇奴聖推臓損磁誤源芋純薦丼腐沿射縮隷粋吐貴縦勤拝,熊噌彫杉銅舎酔炎彼紹介湖講寿測互油己払鍋獄為恥遅汁醤滞剣破亀厄酢,諾盟将舞債伎鹿換牙旧般津療継遺維奈核廃献沖摘及依縄踏伸姓甘貿頼超幅,患狙陣塁弾葬抗崩遣掲爆恵漁香湾跳抱旬聴臨兆契刑募償抵戻昭闘執跡削,伴齢宜賂賄房慮託却需致避描刊逃扱奥併傾緩奏娠妊贈択還繰抑懸称緒盤,控充渋岐埋鈴埼棋譲雇免群枠銃仙邦御慎躍謙阜片項斐隆圏勧拒稲奪鋼甲壁祉,敏吹唱衝戒兼薄堀剤雅孝頻駆俊誉茂殿殖隣繁巡柱携褒排駐顧犠獲鋭敷透,棄至拠蜂儀炭衣潜偽畑蛍拳郷蜜仁遜侵鉱伺徹瀬墟酎措誠虎艦撤樹包,析弧到軸綱挑焦掘紛範括床握枢揚潟芝肝喪網克泊双柄哲斎袋揺滑堅暫糾荒,襲沼朗摩懲慰懇筒滅距籍露炉柔趣擦琴垣即威滋牧泰岳旨刷珍封斉沈撲裂潮貢誰,刃砲笠竜縁忍釣吉粒髪丘俺僕斗寸桃梨姫娯謎侍叱棚叫匹辛芽嵐涙雷缶塔朱翼,頃菌鐘舟嫁暦曇也塾呪湿稼疲翔賭霊溝矛狩脚澄塊狂嬢裸磨陰肌魂眺硬卓凶滝井,墨瞬泡穏孔椅菊涼綿魔寮鳩鈍鍛碁癖穂吾鍵盆庄猿棟誇瞳寧俵幽架黙斬帝租錬阻歳零,幣箸瞭崖炊粧墜欺滴塀霧扇扉恨帽憎佐挿伊詐如唇掌婆哀虹爽憩尺砕粘畳胴巾芯柳,遂蓄脇殴咲鉢賢彩隙培踊闇斜尽霜穫麻騎辱灯畜溶蚊帳塗貼輝憶悔耐盾蛇班餓飢迅脅,概拘煮覆駒悟謀鶴拓衰奨淡礎陛浸劣勘隔桑尼珠抽壇陶妃刈紫唯剛征誓俗潤,偶巧鰐把駄洞伯唐諮廷蟹晶堰漂淀堤后疫翻鬱涯銘仰漫彰簿亭訂壮軌奮峰墳搬邪,肯浦挟沸瓶召貞亮襟隅郡燥釈脂偉軒蓮慈塚玄肪耕媛邸喚苗隻膚軟郊頂濯渦聡枯,祥呂偏茨陥鎖賠恒綾没擁遭噴殊倫陳隼乃輔猟唆惰怠覇須牲秩孤芳貫糧颯慢膨遇,諭随胡搭錦鯉胞浄帥諒蒙曙惨稿啓披繊徐葵騰据莉緯瓜虐戴艇丹緋准舗壌駿剰寛,庶且顕杏栞欄冠酷叙逸紋阿愚尚拐悠勲疎謡哺栽践呈傲疾茜酬呆鎌粛茎痴荘鯨卸,栓累伏虜循凝粗瑛旦奉遼郭抹佳惜憂悼癒栃龍弥髄傍愉赴昌憾朴脊該之鎮尿賓那,匠拍縛飽柴蝶弦凛庸錯轄悦窮嘉弊遥洪紳呉穀摂寂宰陵凡尉靖恭縫舶搾猶窒碑智,款鼓盲醸凹弔凸烏敢堕衡伐酵閲遮腸瑠乙楓膜紺蒼漬哉峡賊旋俸喝羅萌槽坪遍胎,陪扶迭鶏瑞暁剖凌藩譜璃淑傑殻錠媒忌濁椎赦戯享嘱肖憤漣朽奔帆菅酌慨絹窃硫,亜屯岬鋳拙詠慶酪篤侮堪禍雌睦胆擬漆閑憧卑姻曹吟礁峠沙蔑汰紡遷叔甚浪梓崇,煩蛮廉劾某矯囚痢逝狐漸升婿匿謹藍桟殉坑罷妄藻泌唄畔倹拷醜渓湧寡慕'.split(',');
var joyo_kanji = '一右雨円王音下火花貝学気九休玉金空月犬見五口校左三山子四糸字耳七車手十出女小上森人水正生青夕石赤千川先早草足村大男竹中虫町天田土二日入年白八百文木本名目立力林六,引羽雲園遠何科夏家歌画回会海絵外角楽活間丸岩顔汽記帰弓牛魚京強教近兄形計元言原戸古午後語工公広交光考行高黄合谷国黒今才細作算止市矢姉思紙寺自時室社弱首秋週春書少場色食心新親図数西声星晴切雪船線前組走多太体台地池知茶昼長鳥朝直通弟店点電刀冬当東答頭同道読内南肉馬売買麦半番父風分聞米歩母方北毎妹万明鳴毛門夜野友用曜来里理話,悪安暗医委意育員院飲運泳駅央横屋温化荷界開階寒感漢館岸起期客究急級宮球去橋業曲局銀区苦具君係軽血決研県庫湖向幸港号根祭皿仕死使始指歯詩次事持式実写者主守取酒受州拾終習集住重宿所暑助昭消商章勝乗植申身神真深進世整昔全相送想息速族他打対待代第題炭短談着注柱丁帳調追定庭笛鉄転都度投豆島湯登等動童農波配倍箱畑発反坂板皮悲美鼻筆氷表秒病品負部服福物平返勉放味命面問役薬由油有遊予羊洋葉陽様落流旅両緑礼列練路和,愛案以衣位囲胃印英栄塩億加果貨課芽改械害街各覚完官管関観願希季紀喜旗器機議求泣救給挙漁共協鏡競極訓軍郡径型景芸欠結建健験固功好候航康告差菜最材昨札刷殺察参産散残士氏史司試児治辞失借種周祝順初松笑唱焼象照賞臣信成省清静席積折節説浅戦選然争倉巣束側続卒孫帯隊達単置仲貯兆腸低底停的典伝徒努灯堂働特得毒熱念敗梅博飯飛費必票標不夫付府副粉兵別辺変便包法望牧末満未脈民無約勇要養浴利陸良料量輪類令冷例歴連老労録,圧移因永営衛易益液演応往桜恩可仮価河過賀快解格確額刊幹慣眼基寄規技義逆久旧居許境均禁句群経潔件券険検限現減故個護効厚耕鉱構興講混査再災妻採際在財罪雑酸賛支志枝師資飼示似識質舎謝授修述術準序招承証条状常情織職制性政勢精製税責績接設舌絶銭祖素総造像増則測属率損退貸態団断築張提程適敵統銅導徳独任燃能破犯判版比肥非備俵評貧布婦富武復複仏編弁保墓報豊防貿暴務夢迷綿輸余預容略留領,異遺域宇映延沿我灰拡革閣割株干巻看簡危机揮貴疑吸供胸郷勤筋系敬警劇激穴絹権憲源厳己呼誤后孝皇紅降鋼刻穀骨困砂座済裁策冊蚕至私姿視詞誌磁射捨尺若樹収宗就衆従縦縮熟純処署諸除将傷障城蒸針仁垂推寸盛聖誠宣専泉洗染善奏窓創装層操蔵臓存尊宅担探誕段暖値宙忠著庁頂潮賃痛展討党糖届難乳認納脳派拝背肺俳班晩否批秘腹奮並陛閉片補暮宝訪亡忘棒枚幕密盟模訳郵優幼欲翌乱卵覧裏律臨朗論,亜哀挨曖握扱宛嵐依威為畏尉萎偉椅彙違維慰緯壱逸茨芋咽姻淫陰隠韻唄鬱畝浦詠影鋭疫悦越謁閲炎怨宴媛援煙猿鉛縁艶汚凹押旺欧殴翁奥岡憶臆虞乙俺卸穏佳苛架華菓渦嫁暇禍靴寡箇稼蚊牙瓦雅餓介戒怪拐悔皆塊楷潰壊懐諧劾崖涯慨蓋該概骸垣柿核殻郭較隔獲嚇穫岳顎掛潟括喝渇葛滑褐轄且釜鎌刈甘汗缶肝冠陥乾勘患貫喚堪換敢棺款閑勧寛歓監緩憾還環韓艦鑑含玩頑企伎岐忌奇祈軌既飢鬼亀幾棋棄毀畿輝騎宜偽欺儀戯擬犠菊吉喫詰却脚虐及丘朽臼糾嗅窮巨拒拠虚距御凶叫狂享況峡挟狭恐恭脅矯響驚仰暁凝巾斤菌琴僅緊錦謹襟吟駆惧愚偶遇隅串屈掘窟熊繰勲薫刑茎契恵啓掲渓蛍傾携継詣慶憬稽憩鶏迎鯨隙撃桁傑肩倹兼剣拳軒圏堅嫌献遣賢謙鍵繭顕懸幻玄弦舷股虎孤弧枯雇誇鼓錮顧互呉娯悟碁勾孔巧甲江坑抗攻更拘肯侯恒洪荒郊香貢控梗喉慌硬絞項溝綱酵稿衡購乞拷剛傲豪克酷獄駒込頃昆恨婚痕紺魂墾懇佐沙唆詐鎖挫采砕宰栽彩斎債催塞歳載埼剤崎削柵索酢搾錯咲刹拶撮擦桟惨傘斬暫旨伺刺祉肢施恣脂紫嗣雌摯賜諮侍滋慈餌璽鹿軸叱疾執湿嫉漆芝赦斜煮遮邪蛇酌釈爵寂朱狩殊珠腫趣寿呪需儒囚舟秀臭袖羞愁酬醜蹴襲汁充柔渋銃獣叔淑粛塾俊瞬旬巡盾准殉循潤遵庶緒如叙徐升召匠床抄肖尚昇沼宵症祥称渉紹訟掌晶焦硝粧詔奨詳彰憧衝償礁鐘丈冗浄剰畳縄壌嬢錠譲醸拭殖飾触嘱辱尻伸芯辛侵津唇娠振浸紳診寝慎審震薪刃尽迅甚陣尋腎須吹炊帥粋衰酔遂睡穂随髄枢崇据杉裾瀬是井姓征斉牲凄逝婿誓請醒斥析脊隻惜戚跡籍拙窃摂仙占扇栓旋煎羨腺詮践箋潜遷薦繊鮮禅漸膳繕狙阻租措粗疎訴塑遡礎双壮荘捜挿桑掃曹曽爽喪痩葬僧遭槽踪燥霜騒藻憎贈即促捉俗賊遜汰妥唾堕惰駄耐怠胎泰堆袋逮替滞戴滝択沢卓拓託濯諾濁但脱奪棚誰丹旦胆淡嘆端綻鍛弾壇恥致遅痴稚緻畜逐蓄秩窒嫡沖抽衷酎鋳駐弔挑彫眺釣貼超跳徴嘲澄聴懲勅捗沈珍朕陳鎮椎墜塚漬坪爪鶴呈廷抵邸亭貞帝訂逓偵堤艇締諦泥摘滴溺迭哲徹撤添填殿斗吐妬途渡塗賭奴怒到逃倒凍唐桃透悼盗陶塔搭棟痘筒稲踏謄藤闘騰洞胴瞳峠匿督篤栃凸突屯豚頓貪鈍曇丼那奈梨謎鍋軟尼弐匂虹尿妊忍寧捻粘悩濃把覇婆罵杯排廃輩培陪媒賠伯拍泊迫剥舶薄漠縛爆箸肌鉢髪伐抜罰閥氾帆汎伴阪畔般販斑搬煩頒範繁藩蛮盤妃彼披卑疲被扉碑罷避尾眉微膝肘匹泌姫漂苗描猫浜賓頻敏瓶扶怖阜附訃赴浮符普腐敷膚賦譜侮舞封伏幅覆払沸紛雰噴墳憤丙併柄塀幣弊蔽餅壁璧癖蔑偏遍哺捕舗募慕簿芳邦奉抱泡胞俸倣峰砲崩蜂飽褒縫乏忙坊妨房肪某冒剖紡傍帽貌膨謀頬朴睦僕墨撲没勃堀奔翻凡盆麻摩磨魔昧埋膜枕又抹慢漫魅岬蜜妙眠矛霧娘冥銘滅免麺茂妄盲耗猛網黙紋冶弥厄躍闇喩愉諭癒唯幽悠湧猶裕雄誘憂融与誉妖庸揚揺溶腰瘍踊窯擁謡抑沃翼拉裸羅雷頼絡酪辣濫藍欄吏痢履璃離慄柳竜粒隆硫侶虜慮了涼猟陵僚寮療瞭糧厘倫隣瑠涙累塁励戻鈴零霊隷齢麗暦劣烈裂恋廉錬呂炉賂露弄郎浪廊楼漏籠麓賄脇惑枠湾腕'.split(',');
var jlpt_kanji = '日一国人年大十二本中長出三時行見月後前生五間上東四今金九入学高円子外八六下来気小七山話女北午百書先名川千水半男西電校語土木聞食車何南万毎白天母火右読友左休父雨,会同事自社発者地業方新場員立開手力問代明動京目通言理体田主題意不作用度強公持野以思家世多正安院心界教文元重近考画海売知道集別物使品計死特私始朝運終台広住真有口少町料工建空急止送切転研足究楽起着店病質待試族銀早映親験英医仕去味写字答夜音注帰古歌買悪図週室歩風紙黒花春赤青館屋色走秋夏習駅洋旅服夕借曜飲肉貸堂鳥飯勉冬昼茶弟牛魚兄犬妹姉漢,政議民連対部合市内相定回選米実関決全表戦経最現調化当約首法性要制治務成期取都和機平加受続進数記初指権支産点報済活原共得解交資予向際勝面告反判認参利組信在件側任引求所次昨論官増係感情投示変打直両式確果容必演歳争談能位置流格疑過局放常状球職与供役構割費付由説難優夫収断石違消神番規術備宅害配警育席訪乗残想声念助労例然限追商葉伝働形景落好退頭負渡失差末守若種美命福望非観察段横深申様財港識呼達良候程満敗値突光路科積他処太客否師登易速存飛殺号単座破除完降責捕危給苦迎園具辞因馬愛富彼未舞亡冷適婦寄込顔類余王返妻背熱宿薬険頼覚船途許抜便留罪努精散静婚喜浮絶幸押倒等老曲払庭徒勤遅居雑招困欠更刻賛抱犯恐息遠戻願絵越欲痛笑互束似列探逃遊迷夢君閉緒折草暮酒悲晴掛到寝暗盗吸陽御歯忘雪吹娘誤洗慣礼窓昔貧怒祖泳杯疲皆鳴腹煙眠怖耳頂箱晩寒髪忙才靴恥偶偉猫幾,党協総区領県設改府査委軍団各島革村勢減再税営比防補境導副算輸述線農州武象域額欧担準賞辺造被技低復移個門課脳極含蔵量型況針専谷史階管兵接細効丸湾録省旧橋岸周材戸央券編捜竹超並療採森競介根販歴将幅般貿講林装諸劇河航鉄児禁印逆換久短油暴輪占植清倍均億圧芸署伸停爆陸玉波帯延羽固則乱普測豊厚齢囲卒略承順岩練軽了庁城患層版令角絡損募裏仏績築貨混昇池血温季星永著誌庫刊像香坂底布寺宇巨震希触依籍汚枚複郵仲栄札板骨傾届巻燃跡包駐弱紹雇替預焼簡章臓律贈照薄群秒奥詰双刺純翌快片敬悩泉皮漁荒貯硬埋柱祭袋筆訓浴童宝封胸砂塩賢腕兆床毛緑尊祝柔殿濃液衣肩零幼荷泊黄甘臣浅掃雲掘捨軟沈凍乳恋紅郊腰炭踊冊勇械菜珍卵湖喫干虫刷湯溶鉱涙匹孫鋭枝塗軒毒叫拝氷乾棒祈拾粉糸綿汗銅湿瓶咲召缶隻脂蒸肌耕鈍泥隅灯辛磨麦姓筒鼻粒詞胃畳膚机濯塔灰沸菓帽枯涼舟貝符憎皿肯燥畜挟曇滴伺,氏統保第結派案策基価提挙応企検藤沢裁証援施井護展態鮮視条幹独宮率衛張監環審義訴株姿閣衆評影松撃佐核整融製票渉響推請器士討攻崎督授催及憲離激摘系批郎健盟従修隊織拡故振弁就異献厳維浜遺塁邦素遣抗模雄益緊標宣昭廃伊江僚吉盛皇臨踏壊債興源儀創障継筋闘葬避司康善逮迫惑崩紀聴脱級博締救執房撤削密措志載陣我為抑幕染奈傷択秀徴弾償功拠秘拒刑塚致繰尾描鈴盤項喪伴養懸街契掲躍棄邸縮還属慮枠恵露沖緩節需射購揮充貢鹿却端賃獲郡併徹貴衝焦奪災浦析譲称納樹挑誘紛至宗促慎控智握宙俊銭渋銃操携診託撮誕侵括謝駆透津壁稲仮裂敏是排裕堅訳芝綱典賀扱顧弘看訟戒祉誉歓奏勧騒閥甲縄郷揺免既薦隣華範隠徳哲杉釈己妥威豪熊滞微隆症暫忠倉彦肝喚沿妙唱阿索誠襲懇俳柄驚麻李浩剤瀬趣陥斎貫仙慰序旬兼聖旨即柳舎偽較覇詳抵脅茂犠旗距雅飾網竜詩繁翼潟敵魅嫌斉敷擁圏酸滅罰礎腐脚潮梅尽僕桜滑孤炎賠句鋼頑鎖彩摩励縦輝蓄軸巡稼瞬砲噴誇祥牲秩帝宏唆阻泰賄撲堀菊絞縁唯膨矢耐塾漏慶猛芳懲剣彰棋丁恒揚冒之倫陳憶潜梨仁克岳概拘墓黙須偏雰遇諮狭卓亀糧簿炉牧殊殖艦輩穴奇慢鶴謀暖昌拍朗寛覆胞泣隔浄没暇肺貞靖鑑飼陰銘随烈尋稿丹啓也丘棟壌漫玄粘悟舗妊熟旭恩騰往豆遂狂岐陛緯培衰艇屈径淡抽披廷錦准暑磯奨浸剰胆繊駒虚霊帳悔諭惨虐翻墜沼据肥徐糖搭盾脈滝軌俵妨擦鯨荘諾雷漂懐勘栽拐駄添冠斜鏡聡浪亜覧詐壇勲魔酬紫曙紋卸奮欄逸涯拓眼獄尚彫穏顕巧矛垣欺釣萩粛栗愚嘉遭架鬼庶稚滋幻煮姫誓把践呈疎仰剛疾征砕謡嫁謙后嘆菌鎌巣頻琴班棚潔酷宰廊寂辰霞伏碁俗漠邪晶墨鎮洞履劣那殴娠奉憂朴亭淳怪鳩酔惜穫佳潤悼乏該赴桑桂髄虎盆晋穂壮堤飢傍疫累痴搬晃癒桐寸郭尿凶吐宴鷹賓虜陶鐘憾猪紘磁弥昆粗訂芽庄傘敦騎寧循忍怠如寮祐鵬鉛珠凝苗獣哀跳匠垂蛇澄縫僧眺亘呉凡憩媛溝恭刈睡錯伯笹穀陵霧魂弊妃舶餓窮掌麗綾臭悦刃縛暦宜盲粋辱毅轄猿弦稔窒炊洪摂飽冗桃狩朱渦紳枢碑鍛刀鼓裸猶塊旋弓幣膜扇腸槽慈楊伐駿漬糾亮墳坪紺娯椿舌羅峡俸厘峰圭醸蓮弔乙汁尼遍衡薫猟羊款閲偵喝敢胎酵憤豚遮扉硫赦窃泡瑞又慨紡恨肪扶戯伍忌濁奔斗蘭迅肖鉢朽殻享秦茅藩沙輔媒鶏禅嘱胴迭挿嵐椎絹陪剖譜郁悠淑帆暁傑楠笛玲奴錠拳翔遷拙侍尺峠篤肇渇叔雌亨堪叙酢吟逓嶺甚喬崇漆岬癖愉寅礁乃洲屯樺槙姻巌擬塀唇睦閑胡幽峻曹詠卑侮鋳抹尉槻隷禍蝶酪茎帥逝汽琢匿襟蛍蕉寡琉痢庸朋坑藍賊搾畔遼唄孔橘漱呂拷嬢苑巽杜渓翁廉謹瞳湧欣窯褒醜升殉煩巴禎劾堕租稜桟倭婿慕斐罷矯某囚魁虹鴻泌於赳漸蚊葵厄藻禄孟嫡尭嚇巳凸暢韻霜硝勅芹杏棺儒鳳馨慧愁楼彬匡眉欽薪褐賜嵯綜繕栓翠鮎榛凹艶惣蔦錬隼渚衷逐斥稀芙詔皐雛惟佑耀黛渥憧宵妄惇脩甫酌蚕嬉蒼暉頒只肢檀凱彗謄梓丑嗣叶汐絢朔伽畝抄爽黎惰蛮冴萌旺壱偲瑠允侯蒔鯉弧遥舜瑛附彪卯但綺芋茜凌皓洸毬婆緋鯛怜邑倣碧啄穣酉悌倹柚繭亦詢采紗賦眸玖弐錘諄倖痘笙侃裟洵爾耗昴銑莞伶碩宥滉晏伎朕迪綸且竣晨吏燦麿頌箇楓琳梧哉澪匁晟衿凪梢丙颯茄勺恕蕗瑚遵瞭燎虞柊侑謁斤嵩捺蓉茉袈燿誼冶栞墾勁菖旦椋叡紬胤凜亥爵脹麟莉汰瑶瑳耶椰絃丞璃奎塑昂柾熙菫諒鞠崚濫捷'.split(',');
var freq_kanji = '一七万三上下不与世両中主乗九予争事二五井交京人今仕付代以件任企会伝位低住佐体何作使例供価係保信個側備働優元先党入全八公六共内円再写出分切初判別利制前副割力加助労動務勝勢化北区医十千午半協南原去参反収取受口可台各合同名向含告味呼命和品員商問営四回団国土在地型域基報場境増声売変外多夜大夫失女好始委姿子字学宅守安官定実宮害家容察審対導小少局展山岡島川州工差市席常平年幹広店府度建式引張強当形影役待後得復心必応念思急性情想意感態成戦所手打技投担持指挙提援撃支改放政教数整文料断新方施族日早明映昨時景書最月有望朝期木末本村条来東松果査校株核格案検業極楽構様権横機次欧止正武歳死残段毎比氏民気水求決沢治況法注活派流海消深済渉減渡港準演点無然物特状独率現球理環生産用田由申男町画界番疑病発白百的監目直相県真着知石研確示社神票福私移税種究空立第答策算米約終組経結統続総線置美義考者聞職育能脳自若英落葉蔵藤融衆行術衛表被裁補製西要見規視親観解言計記訪設訴証評試話認語説課調談論識警議護象負財費資賞質起足身車軍転輸農辺近述追退送通造連進運過道達違選部都配重野量金銀長門開間関閣防限院際集難電非面革韓音領頭題額食首験高鮮,並丸久乱了互亡介仏他令仲伊休伴伸似余併依便促修倍倒候借値停健催債傷傾像僚儀億償充光児兵具冷処刊刑列券刻則削創劇功努効募勤包卒単博占印危却厚厳及友古史右号司吉君否周善喜喪器因困囲図固園圧坂均城執埼塁塚壊士夏夕夢天太央奈契奪妻婚婦存季宇完宗客宣室宿寄密富寺専射将就尾居届屋属層岩岸崎崩左巨巻布希師帯帰幅幕幸庁底座庫庭康廃延弁弱弾彼律徒従徴徹志恐息恵患悪惑愛慎慮憲懸我戸戻房払批承抑抗折抜択抱押拒招拠拡挑振捕捜授採探接控推措掲描換揮損摘撤攻故救敗散旅旧昇易星春昭普暮暴曜曲更替服未札材束板析林枚枠染栄根棄森植標模樹橋欠欲歌歩歴殺母永汚江池沖河油波洋浜浦浮混清温測湾満源激火災為焦焼熱燃爆父版犯狙献獲玉王留略異痛療登皇益盛盟盤省督短破禁秀秋科秘称程積突章端競竹笑等筋管節築簡籍精系紀納紙級紛素細紹絡給絵絶継維緊緒締編緩練縮績織繰罪署羽習老聴肉背脱臓臨至致興舞航般船良色花芸苦草著葬薬血街衝装裏複覚角触討許誌誘読請諸講譲谷豊貢貨販責貴買貸貿賃賛購赤走超越跡路踏躍軽載輪辞込迎返迫迷逃逆途速逮週遅遊遠遣適遺避還邦邸郎郡郵針鈴鉄録閉闘阪降陣除陸険隊階障雄雇雑離雨需震露青静響項順預頼顔願類風飛飲養館香馬駅駐骨鹿黒齢,丁丈丘丹之也乳乾亀仁仙仮侵俊俳俵倉倫偏偽僕兄兆克免典兼冊冒冬准凍到刷刺剣剤剰励勇勉勘勧匹卓即卵双句叫吸吹哲唆唯唱啓喚喫噴圏埋培堀堂堅塗塩塾墓墜壁壌奇奏奥奨妊妙妥妨妹姉威娘嫌孜孝孤孫宏宙宝寒寛寝寿封尊尋尽屈岐岳巡己帝帳幌干幼床序廷弘弟彦彩彰往径徐御微徳忘忙忠快怒怖恋恒恩悔悟悩悲惨慢慣慰慶憶懇懐懲戒才扱披抵抽拍拐拘拝括拾捨据掃排掘掛揚握揺搭携摩撮撲擁操擦敏敬敵敷斉斎旗既旨旬旭昌昔是昼晩晴智暇暑暖暗暫曽朗杉李杯枝柄柔柱柳栃栽桜梅梨械梶棋棒棟概歓歯殊殖殿毒毛氷沈没沼沿泉泊泣泰泳洗津浄浅浩浴浸涙液淡渋渕湖湯溶滅滑滝滞漁漂漏漢漫潜潟潮濃瀬炉炎炭烈煕煙照熊熟片牛牧牲犠犬狂狭猛玄珍甘甲畑疲症皆皮盗盧盾看眠瞬矢砂砲硬磯礎礼祈祉祖祝祥祭秒秩稲稼稿穴窓竜童笠筆箱範簿粉粘糖糧糸紅純索絞綱網綿緑緯縁縄縦繁繊罰群翌翻翼耐耳聖肝肥肩肺胆胞胸脅脈脚腐腕腰腹膨臣舎舗艇艦芝芳茂茨茶荒荘荷菊菜華菱蓄薄薦虐虚虫衣衰袋裂裕襲覆覇訓託訟訳診詩詰詳誇誉誕誠誤諭諮諾謀謝豆豪貞貧貫貯賀賄賠賢贈趣距踊軌軒軟軸較輝輩透遂遇郊郷酒酸釈里鉱銃銘銭鋭鋼錦鎖鑑閥阻阿陛陥陰陳陽隆随隔隠隣雅雪雰雲零雷霊靖頂須頑顧飯飼飾駄駆駒騒騰驚髪魅魚鯨鳥鳴鶴麻黄黙,乃乏乙亘亜亨享亭亮仰伍伏伐伯佳侍俗俣俸俺倶偉偵偶傍傑傘僧其冗冠冨凝凡凶函刀刃刈剖剛劉劣勲匠卸厘又叔叙召后吐吟吾呆呈呉咲哀哨唇唐喝喬嘆嘉嘱圭坊坪垂垣堤堪堰堺塀塊塔墨墳壇壮奉奔奮奴如妃妖姓姜姫姻娠娯媒媛嫁宜宰宴寂寅寧寮寸尚尺尻尼尿履屯岬峠峡峰峻崇崔嵐嶋嶌嶺巌巣巧帆帽幡幣幻幽幾庄庶廊弊弓弔弥弦彫征循忌忍怠怪恥恨恭悠悦悼惜愉愚慈慌慨憂憎憤憩憾戯扇扉扶把拓拙拳挟挫挿捉掌搬摂擬敢敦斗斜旋昆晃晋晶暁暦曇曙曹朱朴机朽枢枯架柏柴柿栗桂桃桐桑棚椎椿楊楠榎槙槽樋樺樽欄欺款殴殻毅汁汗沙沸泡泥洞洪洲浪涯涼淀淑淳淵添渇渦湘湿溝滋漆漠漬潔潤澄濁濯灘灯灰炊煮燥狩猟猪猫猶猿獄獅獣玲珠班琴琵琶瑞瓦瓶甚畜畠畳畿疎疫疾痕痴癒癖皿盆盲眺眼睡睦矛砕硫碁碑磁磐磨礁祐禅秦稔稚穀穂穏穫窃窒窪窮笛符笹筑筒篠篤粋粒粕粗粛粧糾紋紘紡紫累紳紺絹綾縛縫缶羅羊翔耕聡聯肇肌肖肪肯胃胎胡胴脂脇腎腸膚膜臭舌舟舶芥芦芽苗茅荻菅菌菓萩葛蒲蒸蓮薩薫藩蘇蘭虎虜蛇衡袖裸覧訂詐詞詠該誓誰諏謙謡譜豚貝賓賭赦赴趙跳践輔轄辛辰辱辻迅迭逓逸遍遭遮遷那邪郁郭鄭酔酢酬酵酷醸釜釣釧鈍鉛鉢銅錠錯鍋鍛鎌鎮鏡鐘閑閲闇阜陪陵陶隅隻雀雌霞霧靴頻顕飢飽餓駿騎髄鬼魂魔鳩鴨鵬鶏鷲鷹麗麦麹鼓鼻龍,丑串丼乞仇伺伽佃但佑侠侮侯倣倭倹偕偲僑儒儲允兜冤冥冴凄凌凧凱凸凹剃剥劾勅匂匡匿升卑卯卿厄厦厨叢叩只叱叶吊呂呑呪咸哺唄啄喉喋喘喧嗅嗜嗣嘘噂噛噺嚇囃囚坐坑埴堆堕塙壕壬壱壷夷奄妄姑姚娼婆婿嫉嫡嬉嬢孔孟宋宍宕宵寓寡尉尖尭尹屏峙峨峯嵯嶽已巳巴巷巽帖帥庵庸廉廟廣弛弧彗彪彬彭徘怜怨恣悌惇惚惟惣惧惰愁慕慧憧或戴抄抒抹拭拷挨挺捧揃搜搾摯撚撫播斐斑斥斬於旛旺暉暢曼朋朔杏杖杜杞杭杵枕某柚栓桝桟桧桶梁梓梯棺椅椙楕楢楼榊榛槌槍槻樟樫橘橿檀檄檜櫛欣欽此歪殉毬汎汐汪汽泌洒洛洸浙淘渓渚渥湊湛湧溜溢溥滴漕漱漸澤濡瀋瀕炒烏焉煎煥煩燈燕爪爽牌牙牝牟牡牢犀狐狛狸狼猷玩珂琉琢瑛瑠瓜甕甦甫畏畔畝痢瘤癌皐皓眉眞瞑瞳矩矯砦硝硯碓碧礒祇禄禍禎租稀稜稽穣窯竪竿笏笘箏箕箸篆篇篭簑簗粟粥糞絆絢綜綴綺緋緻縞繕繭罵罷翁翠翫耀股肢胚脊脩腫膝膠膳臼舘舛舜舩舵艶芋芙芭芯芹苅苑苫茎茗茜荏菩萌萬萱葦葵蒋蒔蒙蒼蓋蓼蔑蔡蔦蔭蕃蕉蕨薔薪薮藁藍藏藝藻虹蚊蚕蛋蛍蛭蛮蜂蜜蜷蝶蟹衷袁袴裾褐褒襄襟訃詔詫諌諜諦謄謎謳謹讃貰貼賊賜贅贋赳蹄蹴轍轟迦逐逗逝逢遥遼邑鄒酉酌酪醍醜醤釘鉾銕銚鋳錫錬鍵鍼鍾闊附隈隷隼雁雛雫霜鞍韮韻頃頒頚頬餅餌饗馨魁魏魯鮎鮫鮭鯉鯛鱒鱗鳳鴈鴎鴻鵜鵠鷺麓麺黎黛'.split(',');
function newArray(dimensions, init_val) {
if (typeof dimensions === 'number') dimensions = [dimensions];
if (!dimensions.hasOwnProperty(length)) return undefined;
var dim = dimensions[0];
var arr = new Array(dim);
if (dimensions.length === 1)
for (var i=0; i<dim; i++)
arr[i] = init_val;
else
for (var i=0; i<dim; i++)
arr[i] = newArray(dimensions.slice(1), init_val);
return arr;
}
var khash = {};
function hash_kanji(klist, level_name) {
for (var lvl = 0; lvl < klist.length; lvl++)
for (var i=0; i < klist[lvl].length; i++) {
var kanji = klist[lvl][i];
var kobj = khash[kanji] || {};
kobj[level_name] = lvl;
khash[kanji] = kobj;
}
}
hash_kanji(wk_kanji, 'wk');
hash_kanji(joyo_kanji, 'joyo');
hash_kanji(jlpt_kanji, 'jlpt');
hash_kanji(freq_kanji, 'freq');
function create_page(selector, em1, em2, col_labels, row_kanji, row_name, col_kanji, col_name) {
var rmax = row_kanji.length;
var cmax = col_kanji.length;
// Initialize empty arrays.
var kchart = newArray([rmax, cmax], '');
var cchart = newArray([rmax, cmax], 0);
var pchart = newArray([rmax, cmax+2], 0);
var unlisted = newArray([rmax], '');
var missing = newArray([cmax], '');
var ctot = newArray([cmax+1], 0);
// Populate arrays.
for (var kanji in khash) {
if (khash.hasOwnProperty(kanji)) {
var kobj = khash[kanji];
if (kobj[row_name] !== undefined && kobj[col_name] === undefined)
unlisted[kobj[row_name]] += kanji;
if (kobj[row_name] === undefined && kobj[col_name] !== undefined)
missing[kobj[col_name]] += kanji;
if (kobj[row_name] !== undefined && kobj[col_name] !== undefined) {
kchart[kobj[row_name]][kobj[col_name]] += kanji;
cchart[kobj[row_name]][kobj[col_name]]++;
}
}
}
// Calculate column totals.
var rsum = 0;
for (var col = 0; col < cmax; col++) {
ctot[col] = col_kanji[col].length;
rsum += ctot[col];
}
ctot[col] = rsum;
// Calculate chart.
var max_found = newArray([cmax+1], false);
var csum = newArray([cmax+1], 0);
for (var row = 0; row < rmax; row++) {
rsum = 0;
for (var col = 0; col <= cmax; col++) {
if (col < cmax)
rsum += cchart[row][col];
else
cchart[row][col] = rsum;
csum[col] += cchart[row][col];
cchart[row][col] = csum[col];
pchart[row][col] = (max_found[col] ? '-' : (csum[col] / ctot[col] * 100).toFixed(2)+'%');
if (csum[col] === ctot[col]) max_found[col] = true;
}
}
var mtot = 0;
for (var col = 0; col < cmax; col++)
mtot += missing[col].length;
// Create chart header
var str = '<em>'+em1+'</em><br><br><table><tbody><tr><th>Level</th>';
for (var col = 0; col <= cmax; col++)
str += '<th>'+(col===cmax?"Total":col_labels[col])+'<span class="note"> /'+ctot[col]+'</span></th>';
str += '<th>Unlisted</th></tr>';
for (var row = 0; row < rmax; row++) {
str += '<tr><th>'+(row+1)+'</th>';
for (var col = 0; col < cmax; col++)
str += '<td title="'+kchart[row][col]+'">'+pchart[row][col]+'</td>';
str += '<td>'+pchart[row][col]+'</td><td lang="ja">'+unlisted[row].split('').join(' ')+'</td></tr>';
}
str += '</tbody></table>';
str += '<p><em>'+mtot+' of '+ctot[cmax]+' '+em2+' kanji not yet covered by WaniKani.</em></p>';
str += '<table><tbody>';
for (var col = 0; col < cmax; col++)
if (missing[col].length > 0)
str += '<tr><th>'+col_labels[col]+'<span class="note"> '+missing[col].length+'/'+ctot[col]+'</span></th><td lang="ja">'+missing[col].split('').join(' ')+'</td>';
str += '</tbody></table>';
$(selector).html(str);
}
create_page(
'#data-joyo',
'Kanji learned by the end of each school grade. "G9" denotes the end of middle school. (<a href="https://en.wikipedia.org/wiki/List_of_j%C5%8Dy%C5%8D_kanji" target="_">source</a>)',
'Jōyō',
['G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G9'],
wk_kanji, 'wk',
joyo_kanji, 'joyo'
);
create_page(
'#data-jlpt',
'Kanji required for each JLPT exam level. (<a href="http://tangorin.com/common_kanji" target="_">source</a>)',
'JLPT',
['N5', 'N4', 'N3', 'N2', 'N1'],
wk_kanji, 'wk',
jlpt_kanji, 'jlpt'
);
create_page(
'#data-freq',
'2500 most frequently used kanji in Japanese newspapers, grouped in blocks of 500. (<a href="http://tangorin.com/common_kanji" target="_">source</a>)',
'most frequent',
['F1', 'F2', 'F3', 'F4', 'F5'],
wk_kanji, 'wk',
freq_kanji, 'freq'
);
}
function new_main()
{
KANJI_LEVEL_SIZES = new_KANJI_LEVEL_SIZES;
window.statsCallback = new_statsCallback;
window.levelupCallback = new_levelupCallback;
var labels = $('#info-container .info-left:nth(0)');
labels.html(labels.html().replace('Level Up In:','Level Up In:<br>'));
var stats = $('#stat-levelup');
stats.after('<br><span id="stat-levelupat">Loading...');
new_data_tables();
}
var old_log = console.log;
console.log = function(text) {
if (text == 'Requesting stats information') {
console.log = old_log;
delete old_log
console.log(text);
new_main();
} else {
if (old_log)
old_log.apply(old_log,arguments);
else
console.log.apply(old_log,arguments);
}
}