Code Monkey home page Code Monkey logo

xinglie.github.io's Introduction

Concact me 👋

  • 微信ID:qq84685009

GitHub Status Github Languages

xinglie.github.io's People

Contributors

xinglie avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

xinglie.github.io's Issues

javascript IE浏览器中String的match方法与其它浏览器的不同

上代码来说明问题

var str='ababab',reg=/a/g;

var result=str.match(reg);//此时result为保存3个a的数组

此时result在其它浏览器中都是Array类型,在IE浏览器中也是Array类型

通过Object.prototype.toString.call(result)的结果也是[Object Array]

但是 如果你用for in语句来循环result的时候 会发现第一个元素是str的值,然后才是依次3个a

完了还有最后匹配的索引等东西。并非纯数组,很是搞人,如果要转成纯数组,可以使用Array.prototype.slice.call(result)

提升拖动排序的效率

拖动排序在前端是最常见的功能之一,那么如何做到效率最优呢?

从拖动上,我们一般是为要拖动的元素绑定onmousedown事件,在onmousedown中进行判断是否需要拖动,如果可以拖动,则给document绑定onmousemove和onmouseup事件,在onmousemove中进行位置更改,onmouseup中释放拖动

通常我们拖动时,需要实时获取鼠标指向的DOM节点,在onmousemove中根据event.srcElement或event.target获取,这样才能更改拖动中的各种效率,比如树节点的拖动,来显示是插入到2个节点中间,还是追加到某个节点下,在onmousemove中需要注意的时,拖动的东西不能挡着鼠标,要不然通过event.target或srcElement获取到的始终是挡着鼠标的节点,因此我们可以把拖动提示的节点跟随在鼠标的旁边,而不是挡在鼠标下面

对于鼠标拖动到浏览器外边浏览器还能响应onmousemove事件,我们通常需要判断节点有没有setCapture方法,如果有则调用一下setCapture,这样对于像IE6这样的浏览器鼠标在浏览器外面也是可以响应的,但是这样又引入一个新问题,从firefox 4开始,firefox也提供了setCapture方法,一但这个方法被调用,在onmousemove事件中,取event.target始终是设置setCapture的这个节点,不再是鼠标指向的节点,不管有没有节点挡着鼠标,所以到这个地方又需要判断浏览器,我是不喜欢浏览器判断然后写不同的代码的,尽量使用各浏览器间通用的方法

找到一个各浏览器间还算统一的方法document.elementFromPoint方法,不过这个方法在safari 4.0 ,opera 10.10实现都是不正确的,不过随后的版本修正了这个问题,但是这个方法还是有细微的浏览器差别,用起来也不是让人省心,而且在iOS5跟之前的iOS4也是不一致的,关于iOS的这里有篇文章可供参考:http://www.icab.de/blog/2011/10/17/elementfrompoint-under-ios-5/

目前可通过如果元素有setCapture方法就使用elementFromPoint方法,否则使用onmousemove中的event.target或event.srcElement

对于获取到鼠标指向的元素后,可缓存下来,鼠标再次移动时,先判断鼠标是否仍处于缓存的元素内,如果处于缓存的元素内,无需获取鼠标下的节点,反之再次获取鼠标下的节点,尽可能的提升查询效率。

使用script载入外部js脚本的相关教训

网上的例子一大堆,这里只说明出问题的地方
假设你要写一个这样的类
1:顺序加载外部的js文件,即我给出System.js System.Debug.js两个js文件应按给定的顺序加载
2:可以加载js代码字符串,我给出 var s="var a=12,c=23";这样的字符串,通过设置script对象的text属性从而实现字符串的解析,在上下文中出现变量 a 及 c;

针对1

   /*代码片断*/
    var st=document.createElement('script');
    st.src=loadScriptQueue[0];//我把需要加载的js文件放入一个队列里,依次加载。
   st.type='text/javascript';
   st.onreadystatechage=st.onload=st.onerror=function(){//响应不同浏览器的加载完成
        loadNext();//加载下一个
    }
    /*监听加载完成的方法一定要在appendChild之前,否则在safari chrome浏览器里有问题*/
   document.body.appendCild(st);//当然这里也可用head;

针对2

      /*这个简单*/
       var st=document.createElement('script');
     st.type='text/javascript';
       st.text=scriptBlockString;//代码断字符串
       document.body.appendCild(st);//当然这里也可用head;
       loadNext();//加载下一个

如果 把这两断代码放在一起完成的时候,如果没看准就有可能出问题。我出的问题就是顺序加载外部js文件时候把监听方法放在了appendChild之后,导致页面来回切换的时候有时候不能正常加载。

猜想可能是因为缓存的原因,appendChild之后script已经完成了事件响应,此时再去监听就晚了。

关于自定义autocomplete的一些实现细节

使用autocomplete帮助用户快速完成几乎成了一种标准,用到最多的就是搜索框,用户输入后智能匹配一些结果供用户选择,不单方便用户搜索,也更能提升服务器性能,因为对于同样的搜索关键字,缓存中有直接读就可以了。

在实现的过程中,第一个要注意的就是关闭浏览器自身提供的autocomplete功能,以免影响我们提供的自动完成,对于IE来讲,设置input的autocomplete为off即可,而对于非IE的,如果输入框不在form表单内,那么默认是不出自动完成的下拉框的,如果在表单内,设置input的autocomplete属性为off也不行,要设置表单的autocomplete为off才行,这样才能完成禁用浏览器自身的自动完成功能。

第二个要注意的是减少不必要的请求,只有输入框的内容有变化的时候才进行请求,能引起输入框内容变化的有键盘输入,向输入框内粘贴内容等。对于键盘操作来讲,我们最好使用延时技术,比如检测keyup事件,在keyup后500ms用户没有再输入新内容时,我们再请求,在keydown时我们就清除掉这个延时,对于输入快的用户,我们可以大大减少请求的次数。对于粘贴来讲,目前除Opera外,都支持onpaste,可以在这个事件里进行监听。如果您非要在Opera下也实现,可以用一个定时器,来循环检测输入框内是否有变化。当然,可以在输入框获得焦点时,才启动这个定时器,在失去焦点时,停止这个定时器,尽最大可能减少资源的使用。

对于减少请求来讲,我们还可以缓存历史记录,比如用户输入了abc三个字符,假设输入a时对输入框内的a进行了一次请求,输入b时对输入框内的ab进行了一次请求,输入c时对输入框内的abc进行了一次请求。客户端可以声明一个对象,然后以这3次请求的关键字为key建立一个key/value值对,value就是请求返回的结果。那么如果用户在输入了c后发现输入错了,把c删除后,输入框内只有ab,因为我们已经对ab进行了缓存,直接去对象中取ab对应的value就可以了,不必再发送请求到服务器。

当然对于这种自动完成的功能,返回的数据量最好有所限制,而对于客户端缓存的,也最好限制一下,比如最多保存20个历史记录等。

那架牵牛花

农民

七、八月份的豫东平原上,火辣辣的太阳照射在那一望无际、密不透风绿色的棉花地上。

汗流浃背的我背着打农药的喷雾器,穿梭在这半人多深的棉花丛里,边走边用力压着左侧的手杆,混合着农药的井水就从我右手细细的铁管里,经喷雾喷头后,化作阵阵水雾落在棉花枝叶上。

棉花,是我们那的主要经济作物,在我的印象里,贵的时候一斤能卖3块多,便宜的时候也有13毛多。通常在3-4月份,小麦没过脚脖的时候,就要在地里先挖约30公分深,宽1-2米,长约几米的苗床。把挖出的土堆在苗床里的一边,形成一个低矮的小土堆。用一个顶部带圆筒的叫“制钵机”的工具,稍用力的插到土堆里,经过手和脚并用,把进到圆筒里的土挤压推出,铁制的制钵机通常会发出“哒”的一声金属撞击的声音,就这样一个个顶部带着凹窝的“营养体”就慢慢散落一地,再徒手把这些个营养钵整整齐齐的摆放在苗床里。这个季节农田里到处都可见三三两两弯身忙碌的农民,每家的田有多有少,前后要持续个把月吧。

我喜欢这个时候的田野,即使中午也不会多热,纵横交错的乡村小路把绿油油的麦田划成一块块,绿地毯似的。等到快傍晚,在西斜的太阳下,我多数会跨过家后面那条干涸的小河,到对面河堤上随意的走着。看风儿吹皱十几公分高的麦苗,听一些不知名的鸟叫。漫无目的远眺着,农村的生活即朴实又快乐。

打好营养钵,把它们在苗床摆放整齐后,我们会用一层白色的塑料膜盖住整个苗床,防止这些营养钵被太阳直晒干裂。阴干几天后就要开始培育棉花苗了,通常在家里把棉仔泡上一夜,增加发芽率。隔天早上把泡好的棉仔稍微空干水,运到农田里。揭开苗床上的塑料膜,从远处的机井里挑水过来,根据营养钵晾干的程度,用水瓢均匀的洒水在这些排在一起的营养钵上,湿润这些以土做的小圆柱。

我不太喜欢种棉仔。等泼在营养钵上面的水,在顶部凹槽里逐渐消失的时候,我就要弯腰蹲在苗床边,把昨晚泡了一夜的棉仔或5,6个或7,8一起,丢到这些营养钵的凹槽里,还要轻轻的按一下,以便发芽后更好的扎根在营养钵里。这个过程枯燥又累,我蹲在苗床边机械的重复着同样的动作很多很多次,很多时候脚都是麻的。要把一块地都种上棉花,就得用很多个营养钵孕育棉花苗,我得用很长时间才能把棉仔丢在一小片的营养钵里。站直身子活动活动,吸一下轻风带来麦苗的青气,躬身换到苗床的其它地方继续。

当苗床比较宽,在边上无法把棉仔丢到中间的营养钵时,就要用木板架到苗床上,然后人再上去把中间的营养钵丢上棉仔。通常会让小孩子或体重轻的人上去,防止木板被压的过弯,破坏了下面的营养钵,不过每年都有听说谁谁家的木板压断了破坏了一片营养钵,或谁谁家脚蹲麻了,从木板上滑下去踩坏了一片。我有没有掉下去过?或许有吧。

整个苗床都丢完棉仔后,会盖上薄薄的一层土,再用竹条弯成半圆形插在苗床两边,最后盖上塑料膜,一个很小型的塑料大棚的样式,接下来就等这些棉仔发芽出土。

在放学后或星期天,我会骑着大家里的二八大杠,奔走在家里的几块田地方间,去看那个小小的塑料“大棚”里,棉仔有没有发芽。“大棚”其实只到膝盖,我需要轻轻的拍打塑料膜,让沾在内壁的上的小水珠在振动的作用下,形成大水珠流下去。透过大水珠滚过的地方,我就能清楚的看到棉仔有没有发芽出土。

棉仔发芽后我会更忙些。4月份的平原白天和晚上的温差还是有点大的,我得把哪块地里的苗床发芽了记清楚,白天要去给它们“放风”。白天温度上来,塑料膜盖着的苗床里面温度会更高,如果不及时掀开塑料膜,会把这些发芽的棉苗“烧”死。晚上还要记得把掀开的塑料膜盖回去,防止温度低冻死,需要很小心的伺弄好。我有一次就是给它们“放风”不及时,导致棉苗“烧”死了一片,被骂了很久。这些季节型的作物,过了那个时间点再种就不行了,不是容易死就是长不大,一定要很留心。

棉花是我印象中最累的作物,全程都需要付出很大的精力和体力,这可能也是棉花价格贵的一个原因吧。在地里挖好一个个坑,把发芽后的棉苗同营养钵一起从苗床里取出,再一个个像插秧似的种到挖好的坑里。一天劳累下来,腰都要断了。

在那个夏天,我高中毕业,家里的棉花也早已过了膝盖,我背上打农药的喷雾器,带上拴着长长尼龙绳,用来从机井里取水用的桶,就这样告别学生时代,成为了一个农民。

七月份开始,酷暑就来了,地里的棉花也有半人深。

每天5点多天刚刚亮时,我就会收拾好打农药的器具,向田地出发。夏天也是病虫害高发的时节,早晚天气凉快些,害虫也比较活跃,这时候打农药是效果最好的时候。

一路上会碰到些邻居,“坤飞,今年高考考的咋样?”,我似回答似不回答的长“嗯”一声,不知道该怎么说。夏天夜短,5点就起来干农活,带着些疲惫和倦意,也许也带着回避吧,不想说话,也不想以后会怎样,就这样放空自己默默的干着农活。

当太阳很高,炙烤着皮肤,汗不停流的时候,我才会往家走。以往过暑假最不喜欢的就是下地干活,又热又累,但在这个夏天,我以后就是一个地地道道的农民了,累也不能说,苦也不能说。

中午的时光是最快活的时候,屋后的那个小河会因为下过几场暴雨而蓄满水。电视里的广告越来越多,也没有好看的连续剧,我会带上凉席,拿着《小侠黄九龄》,在屋后河边的树下,或坐或躺,阳光透过树叶间隙洒在书上和我的身上。我喜欢看的武侠小说,再也没有心思读进去。有时候会昏昏的睡过去,直到母亲来喊醒我回家吃中饭。

另外一个清闲的时光是下雨的时候,农药肯定不能打,因为会被雨水冲掉没有任何效果,湿漉漉的棉花和田地也让人没办法去干其它农活。人们或打牌,或闲聊,我则在雨停后去小河边望着河水发呆,从学生到农民,心里还一时接受不了。

那天雨后的下午,在湿湿的土地里,我发现了它,碧绿的小身子蜿蜒的长着,很小。农村这种野花,野草很多,没有人会在意,也没有人会在乎,那天它却牢牢的抓住了我的眼球。雨后的田地土很松软,我很容易的就把它挖了出来带回了家。老家的院子有一小片菜地,每年会种些黄瓜豆角之类,我随手就把它种在了菜地旁边。

夏天的雨水很多,不下雨的时候得抓紧时间干地里的农活,辛苦自不必说。在另外一个雨天,我才注意到被我带回来的那个植物已经在地上爬了长长一段,我明白它要像豆角一样,得搭一个架子让它往上爬。在当时我并没认出它是什么,很是好奇,抽空我给它胡乱搭了个架子,我倒想看看这到底是个什么植物?

高考

我大抵是和班主任有仇的

高中在县城读,住校,为了节省车费,大约1-2月回家一次,这对于初中就开始住校的我并不是什么难事,无非是换了个地方,变了下环境。新的高中需要慢慢熟悉,老师也不像中学那样在学习上很严格的管你,环境确实会影响人,向上走很难,向下滑坡很容易。

高一的班主任是教化学的。初中我的化学还是相当棒的,到高一的时候,各科都不好,化学更差,我还记得上半学期期中考试成绩出来后,在一个晚自习时间,班主任点了5名同学到教室外面,其中就有我。

“知道为什么叫你们几个么?”班主任发话了,我们看向班主任,说不知道。“倒数后5名!”。嗯?什么?我真的不敢相信,时至今日这个场景我依然记得很清楚,初中三年我是在镇上的实验班(尖子班)过来的,怎么到高中短短几个月考了倒数后5名呢?感觉随便考考都不会这样吧?因为河南生源实在太多,像我们高一每个班普遍都在100人以上。我们5个人,除我之外的其他3个男生倒数我不意外,因为很少见他们进班学习,但我不是这样啊,我竟然在泱泱100多人的大班里,考了倒数。

“还有你,一个女生,成绩居然比这几个不学习的男生还差”噗,我乐了,我也不知道当时我是怎么了。“考倒数第二光荣是不是?你还笑?”我天?倒数第二?我还不如那些不进教室学习的?

班主任训了多久我不知道,时至今日我仍然记得那个叫陈锐的女生,家是在校门口卖饭的,人家成绩差无所谓,而我呢?高一的成绩一直没有起色,好在后来不是倒数了,化学,再也没学懂过。

高二的班主任是教历史的,我上学第一次逃课,是在初中逃的历史,所以历史成绩一直就没好过。教历史的班主任是一个胖胖的女人,教学很有一套,脾气也厉害。我不敢马虎,但是之前的历史都没认真学习,基础太差,一时之间很难有提升,每次考试我都想法设法的去提高历史成绩,不然被班主任骂会很痛苦。

每次考试各年级都会不同时间的放假,比如1-2号高二考试,高一高三放假。然后把高二的学生分到不同的教室里去。有一次考历史,我借了5本历史书揣身上带进考场,进去后身上留一本,课桌里两本,放在不同的位置上,剩余的两本放在了旁边的课桌里。考试开始后,先把会的做一做,然后就把身上的历史书偷拿出来抄,因为不会的太多,我就把书放在课桌上,盖在卷子下。课桌上还是很明显的,很快就被监考老师发现收去了。我不担心,我从课桌里摸出来另外一本继续,一会的功夫又被监考老师发现收去了。“不能再抄了!”监考老师冲我说,“嗯嗯”我应答着,接下来的一段时间我稍微老实些。我揣测监考老师应该认为我没有书可抄,不太会关注我这边,悄悄地摸出第三本历史书继续。

“嘿,你还有?!”我知道又被发现了,只好主动的交出历史书,这时候班内其他考试的同学也都望了过来。“你出来,站到这边来”,我只好起身,离开了座位。监考老师坐在我的座位上,把周边仔细找了一下,又搜出一本。“嚯,你可以啊,带这么多书来抄”,嗡,其他考试的同学都笑了起来。“还有没有?”“没了”“如果被我发现你还有,你还抄的话,就报教务处通报批评!”这招对我是有效的,不能因为考试抄书被弄个全校通报批评,这太没面子了。想着接下来监考老师可能会重点注意我,抄是抄不成,书也就没什么用了,我就主动把老师没找到的最后一本书给翻出来交给了他。哈……,其他考生哄堂大笑,监考老师直勾勾的看着我,我有点心慌,不会通报批评吧?“老师,我交卷”想着反正也抄了不少,其他的编也没意思,闪人吧,趁监考老师没做最后的决定之前,交了试卷,匆匆离开了考场。

高二结束的时候文理分科,学文,历史不好,学理,化学不好,着实让我左右为难。犹犹豫豫了很久之后,选定了文科。

高三在紧张的氛围里开始了,开学的时间都早了很多,8月份都开学了。我还是没有紧张起来,坐在文科教室里,看同学把从高一开始,需要复习的书一摞摞的书搬到自己的座位上,我不以为意。“我们要复习这么多书么?”我问和我一个班级的好友刘朝华,“不是的”他说“这些还一半不到,还有一多半没搬过来呢。”看着他面前的书我心里开始打鼓,就这些书我觉得我都背不下来,何况还有一大部分?

好在我们是首届文理分科,不满意的同学可以到教务处重新选择,这确实是一个好的政策。那段时间里,不断有人从理科班转到文科班,从文科班转到理科班。我举棋不定,中午吃过饭的时候碰到了另一个好友,他是理科,手里拿着需要复习的书“这只是一部分吧?”我问道,“不是,这就是全部了,你看,高一的,高二的”,我看了看,确实少,原来理科只需要复习这么少的书?那天下午我果断的去教务处转到了理科班。

虽然能转,但教务处老师说只能转一次。转了理科后,我也不再想其它的了。

理科班的气氛是比文科班的要安静一些,不管是成绩好的,还是成绩差的,娱乐区的后3排,也只有悉悉索索的声音了,坐在这低声聊天的后3排中,开始了我的高三生活。

第一次摸底考试时,我意外的考了第17名,在100多人的班级中还是很不容易的。按成绩挑座位,班主任站在门口,按成绩念名字,被念到同学到教室中任意坐还空着的座位。念到我后,我就挑了倒数第二排南边的位置上,坐下后班主任走了过来“你想坐在这?”“对”“不往前坐坐?”“不用吧,这里可以”我知道班主任的心思,后3排是都是不愿学习的学生,老师平时也是不管的。从初中开始到高二,我都喜欢坐在后排,太枯燥的学习我不喜欢,能自由的出入教室,没事听听歌曲,“娱乐区”才是我喜欢待的地方。

高三的“娱乐区”也不见得都是学习成绩不好的,那些差生在高一,高二的时候通常都退学了,愿意参加高考的还都是想再奋斗一下的。那次挑座位后3排其他人员基本上还是原来的这些人,我的同桌是卞永刚,他要参加高考,也知道自己考不上大学,所以并不怎么学习。好在他不学习的时候,也不来打扰我。

那段时间我们2个用那种小录音机听了很多磁带,一副耳机一人一个。为小录音机提供电源的,是小型的便携充电器,我们一人买了几个。能充电的地方,只有教室前面黑板旁的一个插座。我们就用这个插座轮流给这些充电器充电,除老师上课要用插座外,其他同学想用插座充电时,都会跑过来问我们有没有充好,这也是后3排同学的“威信”,其他同学不敢随意乱动后3排同学的东西。

第二次排座位的时候,天气快要热起来了,我去了倒数第二排的北面。认识了一直到今天的挚友李春光。

李春光家在县城,不住校,有时候中午也可以回家吃饭。那段时间他总是带很多剥好的花生给我们吃,我发现他带给我们吃的花生要比平时见的饱满,也大很多,味道也相当好,我问他:“你家种的花生是啥品种的?为什么每个都这么好?”“不是种的”他说,“这是家里卖的花生种”。农村像大豆、玉米这些为了来年种,会挑品相好的留下来做为种子,自己平时如果吃,都是差一些的。万一家里没种子,就只能去市场上买。所以种子都是很爱惜的保存,拿来吃是肯定不会的。后来我才知道他家原来在县城有门面,专门销售农业种子,像大豆、玉米、花生之类的。那段时间我们吃了不少花生种,家里有条件的就是不一样,着实让我羡慕。

我们县城有一个图书馆,只需要很少的钱就可以办到借书证,这让我们这种穷学生也有机会可以借到书。当然对于我们来说,虽然钱少,但是大部分都不愿意花这个钱去借书的。如果谁借来了书,在规定还书的时间内,大家都是轮流着看,我们称为“利益最大化”。春光有一个发小王发启,对新生事物很感兴趣,我们那个时候电脑刚刚联网,也有了网吧,系统普遍是winow 98window 2000,那些装window xp的就是最先进的。

王发启办了一个借书证,他喜欢计算机方面的,经常借相关的书来看。我初认识春光的时候,是不认识王发启的。那天发启借了一本书,看完还没到还书时间,就趁下课间隙拿来给春光看(发启和我们不在一个班)。发启借的自然是关于计算机的,春光看不懂就扔给了我。

我接触电脑是在初三的时候,用过QQ,打过仙剑,当然,水平很菜,不会打字,也不太会用鼠标。在初中的时候碰巧班上的同学带了一本计算机入门的书,借来看,我很痴迷。从那本书上“学会”了五笔输入法:只知道字根,完全没在电脑上练过。初中部分的事情有空再来写写吧。

高中的时候有了计算机课,但只讲word之类的软件如何使用,我在这个时间终于能把我学的五笔理论知识实践了,在打字上入了门。那时候计算机相关的介绍非常少,偶尔能见到一些像电脑报之类的,大多数也是看不懂的。

在那个开始变得闷热的午后,接过春光扔来的书,准备从无聊的学习中换换脑子。或许命中注定吧,那是一本介绍HTML标签的书,厚厚一本,前面介绍什么是网页,让我明白了去网吧点开那个e图标看到的内容是怎么回事。接下来的内容就是一个个像pbtable标签是怎么使用,如何改变字的大小,如何改变颜色,如何居中。我看的如痴如醉,终于能有一本关于计算机的书能看得懂了,虽然今天看来没什么技术含量,但在那时候没有别人教,通过书深入浅出的教会了我如何写一个网页。

那个下午,上了英语课,上了数学课,讲了什么我全不知道。我不但认真看那本介绍HTML的书,还做了笔记,把我感兴趣的标签一个个记录下来。到晚上发启来要书时,我还没看完,我只好央求他晚一点还,也就是这时候算是和发启正式认识了。我们各自聊了很多自己会的计算机知识,有种相见恨晚的感觉。他居然懂如何在网络上通过免费空间建自己的网页,这很是让我崇拜。最后同意我慢慢看,他可以晚几天再去还书,着实让我感激。

在后来的日子里,我总是约着发启去网吧,慢慢建着自己的主页。春光因为对这些东西不感兴趣,只偶尔跟我们一起去玩一玩,聊聊QQ,游戏都不怎么打的。

那时候总盼望着快些高考,快些结束这沉闷的高三。高考从原来的7月份调到6月份,让我高兴,少煎熬一个月。功夫都在平时,对我来说,多一个月也并不能多考几分。

高考那天每年都要下雨,那年也不例外,雨后的天气确实让人倍感舒适。然而最后的理综卷却没有让我高兴起来,我偏科,300总分的理综6张卷子12面,那么不幸运的是超过6面都是我不会的化学。早早的交了卷子,这些不会的化学,看多久都是不会的,不如交了吧。

走出考场,失落的心情马上好了起来,解放了!考完我并没有着急回家,因为高一、高二要到7月份才放假,他们正常上课,高考完的我们还可以在学校住上几天,慢慢收拾自己的东西,我准备趁这几天玩一玩。几个要好的同学也没打算回家那么早,我们终于想睡就睡,想玩就玩。游戏厅,网吧,上学的时候就来过无数次,但这几天我们像告别一样,一个个玩过去,还互相说着以后可能再也不会到这些地方玩了。

估了分后,心情就很不好,总分750,我估分只有350分,在考生众多的河南省,这个分数想上大学,根本不可能。面对这个结果,也只能告诉自己坦然些吧。

知道自己可能上不了大学,志愿还是要填一填的。我英语很好,也很感兴趣。如果走英语专业,就得文科,这也是我最初文理分科的时候选文科的原因。在教务处填写的志愿,总共有3个志愿可写。这时候我才发现理科也有英语相关的专业,只是擦边。想着反正是考不上,就胡乱选了2个学校和它们对应的带有英语的专业,第3个志愿没写交给了教务处的老师。那个老师接过来看了下说:“把第3个志愿也写写吧”。我是没打算填的,想想万一有机会呢?就接过来,选了个本省的学校,因为省内的分数线相对低些。不能还写有关英语的专业吧?自己计算机也感兴趣,换成计算机专业吧,就这样填满3个志愿,离开了太康二高。

复读

那个暑假,结束了十几年的学习,我知道录取通知书我是等不来了,回家种地吧。

风,很少有。一排排无垠的棉花像防风林一样,不知道把风挡哪里去了。太阳透过地表把水抓出来,摇曳着向上提,远处的树木和村庄也仿佛微微晃动起来,感觉轻轻一吸,都能把水蒸汽吸到肺里。热,到处都热,偶尔有风吹过,也是热的。盛夏中的棉花不只是打农药,还要打花杈,掐花头,上化肥。走在被棉花挤的不宽的田埂间,把棉花一株株拉近、翻看有没有害虫,要不要打花杈,汗水很快就会打湿体恤。我很容易出汗,劳作一段时间后,走出棉花地,像洗了澡似的,体恤脱下来,能哗哗拧下很多汗水。

分数出来了,比预想要高,390多。按录取分数线,重点、一本、二本陆陆续续的录取通知书下来了,自然不会有我的,志愿我都没写本科。我也早已做好了打算,不去复读,上学对我来说,太痛苦了,何况高三复读?心态慢慢转变,我也做好了当一辈子农民的准备。

8月份高三开学,很多考的不理想的也都回去复读,来年再战。父母自然知道我考的不好,就一次次让我回去复读,我都是无声的走开,即不能顺从,也不能反抗。

田间劳动是辛苦的,每天晚上睡觉的时候,骨头都像散了架似的疼,只能咬牙硬抗着。虽然做好了不复读的打算,有时太累的时候,也会想想如果坐在教室里学习,就能够远离这些累人的农活。

农活和劝说,我动摇了,2个多月的超负荷打理棉花,我确实累惨了。在8月底的时候,我带上简单的被褥,拿上书本去了太康一高复读

教学质量在我们县城最好的就是太康一高,很多优秀的教师也都被招到了这里。为了来年都有好的成绩,都想法设法的进一高。到一高校园后就遇到问题了,升到高三的学生加回来复读的学生实在太多,光理科有都有十几个班,每个班都被挤的满满当当的,每个班都有110-120人之多。我想回来复读,连坐的位置都没有,别人8月初开学都来了,我是月底,早没了位置。

我打听到,每个老师为了升学率,会优待那些高考成绩不错回来复读的同学,我觉得这是一个办法。那段时间虽然是在一高的校园里,也经常见到以前二高的学生,大家的想法都是一致的,就是复读的时候一定要找个更好的学校。

运气很好,碰到了王春光(我同学叫春光的非常多)。我知道他成绩不错,难道他也回来复读么?

“春光,你也回来复读啊?”

“不,500多分,我考上本科了,和石培培再来学校玩一下”。

王春光和石培培高考成绩都还不错,要去不同的大学,就约着来学校玩玩。我跟王春光说

“你成绩这么好,帮我去拿一个复读的名额吧?现在复读教室都没坐的地方”

“怎么拿?”

“你只需要去x班找班主任xxx,告诉他你要回来复读,以你的成绩,班主任肯定会想办法在教室里腾一个位置出来的”

“你自己不是也可以直接找班主任说的”

“不行,我这成绩,你觉得他会让我去他的班复读么?”

“行啊,反正没事,我去试试”

我就在外面的树荫下等着,远远的看他走进老师的办公室。不一会那个班主任带春光到教室,很快又返回办公室,再然后春光出来向我这边走来,我赶紧迎了上去。

“咋样?”我问道。

“搞定,教室里腾了一个位置出来”

哈,没想到这个问题就这样被我解决了,我向王春光表示了感谢,现在有位置了,先坐进教室再说。

隔天晚自习,班主任进班检查学习情况,很快就发现我这个新面孔。班主任走到我身边,问:“你是?”,我愣了一下,意识到虽然解决了座位问题,可这个问题我该怎么回答?“我是王春光”我硬着头皮回答。“王春光?我怎么记得王春光不长这样?”我没说话,班主任也不傻,我继续撒谎也没意义。

班主任站了一会转身走向讲台,“一个月后摸底考试,复读生必须参加,不参加的复读生我会直接赶走。”他顿了顿接着说“以高考成绩为参考线,凡这次摸底考试没有超过自己高考成绩的,差1分交100块钱才能在我这个班里复读。”

真是张良计,过墙梯,玩不过这些老师的。走一步讲一步吧。

复读的气氛更沉重,百十号人拥挤在闷热的教室里,只有几个破旧的吊扇呼啦啦的响着,2天后我就坐不住了,还不如干农活呢。午饭后少部分人还在奋笔疾书,多数趴在课桌上睡觉休息。书我是看不进去了,题也不想做,在教室里感觉浪费时间,去网吧玩玩。

走出教室,向一高大门走去。远远地看见一个同学,推着自行车,前面车框里放着些书,后面带着褥子床单,不用说,又来一个复读的。

“坤飞,弄啥去?”

“上网去,原来是文雅啊”

这个也是我二高的好友:刘文雅。我对他说:“教室里位置非常紧张,这些天不断的有人来复读,不过也有复读几天走了,你看看还有没有哪个班级有空位”我把了解到的信息告诉了文雅,少让他兜圈子。

到了网吧,没心思聊天,更不想玩游戏,查了查录取情况,我天!我竟然被录取了,什么情况?!

大专的录取是在本科之后,8月中旬才有部分大专开始发录取通知书。我把录取信息反复看了几遍,确定录取了,是第3志愿那个计算机专业的学校,这个学校生源不够,录取分数向下降了十几分,我就被录取了。

心情一下子好了很多,因为实在不想复读,虽然这个省内大专学校一般般,不过总算对高考有一个交待:要么去上,要么回家种地,我底气一下子足了起来。什么摸底考试,什么差1分交100块钱,想到不用再参加那么多考试就一阵阵的高光。

在网吧随便玩玩后就盘算什么时间回家,不想在这复读的地方待了。刚回一高进了大门口,又碰见了文雅。

“文雅你怎么还带着东西呢?”

“甭提了,每个教室都是满的,根本没位置,我只能去二高看看,希望能找到还有位置的班级”

“别去了,我不打算继续复读了,你去坐我那个位置吧”

“真嘞?你咋不读了?”

“竟然有个大专录取了,不管好不好,要么去上,要么回家,复读我是不干了。”

就这样我把那个位置给了文雅,回家等录取通知书去了。十几年后,在郑州刘文雅开的烟酒店里,他问我还是否记得让位置给他的事情,说实话我对这个事情已经相当模糊了,感觉像是有这么一回事。文雅就把整个过程诉说了一遍,我问他你怎么会记得这么清?他说“正因为你走了我才有机会坐进那个教室,复读考大学,如果你不走,我去了二高,谁知道以后的路是怎样的?”

到家后,夏季农忙,还是像以往那么累,不过这次有盼头了,父母也同意我去上这个大专,等通知书下来即可。

被我捡回来的那个植物,因为忙,也没怎么管过,我依稀记得在准备去大专前,它已经爬满了整个架子,也开了很多小花。我无心打理,也无暇欣赏,在那个9月,我揣着凑齐的学费,带着满身的尘土和疲惫,坐上大巴车去了另外一个城市。

军训完后的十一,我回了趟老家,到家后发现那个植物连同我胡乱搭的架子不见了踪影。也许在父母眼里,它不像豆角可以吃,也不像棉花可以卖钱,像草一样的东西留它干什么呢?

青绿的棉花叶子开始泛黄,结了棉桃,棉桃裂开是白白的棉花,十一里我依旧要一块地一块地的去摘棉花,忙碌几天后返回学校。

至今不知道那个植物叫什么名字,甚至农村叫的土名也不知道,那就那样悄然的出现,又蓦然的离去。

生命是坚强的,随便在哪里,只要有机会,都会努力的生根发芽。生命亦是脆弱的,变幻的环境,莫测的未来,随时能摧毁它。似水的岁月也一次次把我冲向未知的远方,我就这样随波漂着,荡着,努力的寻找下一个可以停靠的地点。

a星算法 js版本

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>A星寻路算法</title>
<style type="text/css">
html,body{font-size:12px;line-height:22px;}
</style>
</head>
<body>
<div id="astart"></div>
</body>
</html>
<script type="text/tpl" id="tpl">
<table>
<#for(var i=0;i<cx.map.length;i++){#>
<tr>
<#for(var j=0;j<cx.map[i].length;j++){#>
<td style="width:20px;height:20px;background-color:<#=cx.map[i][j]?'grey':'green'#>" id="cell_<#=i#>_<#=j#>"></td>
<#}#>
</tr>
<#}#>
</table>
</script>
<script type="text/javascript" src="Items/js/K1.source.js">
var Map = {
    map: [],
    init: function() {
        for (var i = 0; i < 30; i++) {
            this.map[i] = [];
            for (var j = 0; j < 30; j++) {
                this.map[i][j] = Math.random() < .2 ? 1 : 0;
            }
        }
        K.TP.using('tpl').toFill('astart', {
            map: this.map
        });
    }
};
var AStar = {
    Point: K.clazz({ //点
        x: -1,
        y: -1,
        ctor: function(x, y) {
            /// <summary>构造方法</summary>
            /// <param name="x" type="Integer">x坐标</param>
            /// <param name="y" type="Integer">y坐标</param>
            this.x = x;
            this.y = y;
        },
        genKey: function() {
            /// <summary>根据坐标点生成一个key</summary>
            /// <returns type="String" />
            return [this.x, this.y].join('_');
        }
    }),
    Node: K.clazz({ //节点
        parent: null,
        G: 0,
        F: 0,
        H: 0,
        x: -1,
        y: -1,
        ctor: function(f, g, h, x, y, parent) {
            /// <summary>构造方法</summary>
            /// <param name="f" type="Integer">F值</param>
            /// <param name="g" type="Integer">G值</param>
            /// <param name="h" type="Integer">H值</param>
            /// <param name="x" type="Integer">在地图中x坐标</param>
            /// <param name="y" type="Integer">在地图中y坐标</param>
            /// <param name="parent" type="AStar.Node">父节点</param>
            var me = this;
            me.F = f;
            me.G = g;
            me.H = h;
            me.x = x;
            me.y = y;
            me.parent = parent;
        },
        getPoint: function() {
            /// <summary>获取当前节点的地图坐标点</summary>
            /// <returns type="AStar.Point" />
            return new AStar.Point(this.x, this.y);
        }
    }),
    setMap: function(map) {
        /// <summary>设置地图</summary>
        /// <param name="map" type="Array">一个二维数组表示的地图,0表示可通过,其它值表示不可通过</param>
        this.$map = map;
        this.$openList = [];
        this.$closeList = {};
    },
    checkNode: function(node, p1, p2) {
        /// <summary>检测节点</summary>
        /// <param name="node" type="AStar.Node">当前节点</param>
        /// <param name="p1" type="AStar.Point">检测点</param>
        /// <param name="p2" type="AStar.Point">目标点</param>
        var me = this,
            openList = me.$openList,
            closeList = me.$closeList,
            key = p1.genKey();
        var tempNode = closeList[key];
        if (!tempNode) {
            tempNode = new me.Node(0, 0, 0, p1.x, p1.y, node);
            openList.push(tempNode);
            closeList[key] = tempNode;
            tempNode.G = node.G + me.getG(node.getPoint(), p1);
            tempNode.H = node.H + me.getH(p1, p2);
            tempNode.F = tempNode.G + tempNode.H;
        } else {
            var tg = node.G + me.getG(node.getPoint(), p1);
            if (tempNode.G > tg) {
                tempNode.G = tg;
                tempNode.F = tempNode.G + tempNode.H;
                tempNode.parent = node;
            }
        }
    },
    setNowPoint: function(node, point) {
        /// <summary>设置当前节点</summary>
        /// <param name="node" type="AStar.Node">当前节点</param>
        /// <param name="point" type="AStar.Point">目标点</param>
        var me = this,
            map = me.$map,
            x = node.x,
            y = node.y,
            g = node.G;
        var top = x - 1,
            left = y - 1,
            right = y + 1,
            bottom = x + 1;
        var maxMapHeight = map.length,
            maxMapWidth = map[0].length;
        if (top >= 0 && left >= 0 && !map[top][left] && !map[top][y] && !map[x][left]) me.checkNode(node, new me.Point(top, left), point); //1
        if (top >= 0 && !map[top][y]) this.checkNode(node, new me.Point(top, y), point); //2
        if (top >= 0 && right < maxMapWidth && !map[top][right] && !map[top][y] && !map[x][right]) me.checkNode(node, new me.Point(top, right), point); //3
        if (left >= 0 && !map[x][left]) this.checkNode(node, new me.Point(x, left), point);
        if (right < maxMapWidth && !map[x][right]) this.checkNode(node, new me.Point(x, right), point);
        if (bottom < maxMapHeight && left >= 0 && !map[bottom][left] && !map[x][left] && !map[bottom][y]) me.checkNode(node, new me.Point(bottom, left), point); //7
        if (bottom < maxMapHeight && !map[bottom][y]) me.checkNode(node, new me.Point(bottom, y), point); //8
        if (bottom < maxMapHeight && right < maxMapWidth && !map[bottom][right] && !map[bottom][y] && !map[x][right]) me.checkNode(node, new me.Point(bottom, right), point); //9
    },
    getH: function(p1, p2) {
        /// <summary>获取两个点之间的H值</summary>
        /// <param name="p1" type="AStar.Point">起始座标点</param>
        /// <param name="p2" type="AStar.Point">结束座标点</param>
        /// <returns type="Integer" />
        var xDis = Math.abs(p1.x - p2.x),
            yDis = Math.abs(p1.y - p2.y);
        if (xDis > yDis) return 14 * yDis + 10 * (xDis - yDis);
        return 14 * xDis + 10 * (yDis - xDis);
    },
    getG: function(p1, p2) {
        /// <summary>获取两个点之间的G值</summary>
        /// <param name="p1" type="AStar.Point">起始座标点</param>
        /// <param name="p2" type="AStar.Point">结束座标点</param>
        /// <returns type="Integer" />
        if (Math.abs(p1.x - p2.x) == 1 && Math.abs(p1.y - p2.y) == 1)
            return 14;
        return 10;
    },
    getPath: function(start, end) {
        /// <summary>获取寻找到的路径</summary>
        /// <param name="start" type="AStar.Point">起始座标点</param>
        /// <param name="end" type="AStar.Point">结束座标点</param>
        /// <returns type="Array" />
        var path = [],
            me = this,
            map = me.$map,
            openList = me.$openList;
        if (!map || map[start.x][start.y] || map[end.x][end.y]) {
            K.log('no path');
            return path;
        } else {
            var tempH = me.getH(start, end);
            openList[0] = new me.Node(tempH, 0, tempH, start.x, start.y, null);
            var tempLen = 0,
                nowNode = null;
            while (0 < (tempLen = openList.length)) {
                var maxNode, minIdx, minF = 1E9,
                    idx = 0;
                for (idx = 0; idx < tempLen; idx++) { //在开放列表中搜索F值最小的
                    maxNode = openList[idx];
                    if (minF > maxNode.F) {
                        minF = maxNode.F;
                        minIdx = idx;
                    }
                }
                nowNode = openList[minIdx]; //当前搜索到的较合适的节点
                K.arrDelAt(openList, minIdx); //移除当前搜索到的节点
                if (nowNode.x == end.x && nowNode.y == end.y) { //如果是结束节点 则递归查找路径
                    path.push(nowNode.getPoint());
                    while (nowNode.parent) {
                        path.push(nowNode.parent.getPoint()); //存储坐标
                        nowNode = nowNode.parent;
                    }
                    break;
                }
                me.setNowPoint(nowNode, end);
            }
        }
        return path.reverse();
    }
};
Map.init();
AStar.setMap(Map.map);
var date = new Date().getTime();
path = AStar.getPath(new AStar.Point(0, 0), new AStar.Point(29, 29));
K.log(new Date().getTime() - date);
K.list(path, function(v) {
    K.nodeStyle('cell_' + v.x + '_' + v.y, {
        backgroundColor: 'red'
    });
});
</script>

js克隆一个对象,支持循环引用的克隆

(function(){
  var toString=Object.prototype.toString,gObj={},cloneHelper=function(cache,item){
   /// <summary>helper for Utils.clone</summary>
   if ('object' == typeof item || Utils.isFunction(item)) {
    for (var i = cache.length - 2; i>=0; i -= 2) {
     if (cache[i] == item)
      return cache[i + 1]
    }
    cache.push(item, item = Utils.clone(item, cache))
   }
   return item 
  };
  window.Utils={
   isFunction:function(it){
    /// <summary>判断参数是否为Function</summary>
    /// <param name="it" type="Object">待判断的参数</param>
    /// <returns type="Boolean" />
    return toString.call(it)=='[object Function]';
   },
   clone:function(obj,cache){
    /// <summary>克隆一个对象</summary>
    /// <param name="o" type="Object">要克隆的目标对象</param>
    /// <returns type="Object" />
    cache || (cache = []);
    var clone,temp;
    if (!obj || (!Utils.isFunction(obj) && typeof obj != 'object')) return o;
    else if (obj.cloneNode) return o.cloneNode(true);//克隆DOM节点,绑定事件的有问题,暂不处理
    else if (Utils.isFunction(obj)) clone = new Function('return ' + obj)(); //克隆function eval在当前作用域,Funtion在全局
    else clone = (temp = obj.constructor, clone = new temp(obj.valueOf()), obj == clone) ? new temp() : clone; //克隆其它对象,通过识别复制后的对象与原对象是否相同来决定传不传参数,像数组是不能传参数的
    cache.push(obj,clone);
    for (temp in obj) if (gObj.hasOwnProperty.call(obj,temp)) clone[temp] = cloneHelper(cache,obj[temp]);//使用gObj.hasOwnProperty 防止对象obj重写了hasOwnProperty方法
    return clone
   }
 }());

支持节点克隆,对象克隆,同时也支持循环引用的对象克隆。

比如:

   var souceObj={

      childObj={

     }

   };

  sourceObj.childObj.child=sourceObj;

这样一个循环引用的对象也可以正常克隆

cloneObj=Utils.clone(sourceObj);克隆后,同样保持与原来相同的引用关系

对于
var obj={};
var a={};

a.b=obj;
a.c=obj;

var d=Utils.clone(a);

在clone之前
a.b.f='123';
那么a.c也就有了一个f 为 '123';

但对于 clone之后的d 也有这功能

然而,每段代码或解决方案都有它的适用范围,以上代码也无法保证在所有浏览器中对任意对象克隆均能正常工作,您应当看懂理解代码,学以至用,而不是简单的把代码复制过去,等出了问题的时候说:我靠,这他妈写的什么代码啊,一点都不稳定。

以上代码在opera某些版本下克隆正则有问题,已满足大部分需求

已知格式化日期的字符串和格式化后的日期,还原日期

需求:

1 已知格式化日期字符串format 为 "YYYY-MM-DD" 或 "DD/MM/YYYY"等常见的格式化字符串

2 已知和这个格式化字符串对应的格式化后的日期date为"2011-11-12" 或 "12/11/2011"

求 年 月 日

解:

   var getDateFromFormat=function(date,format){
         result={year:0,month:0,day:0};//当然这里可以默认1970-1-1日
         if(date){
              format.replace(/y+|Y+|M+|d+|D+/g,function(m,a,b,c){//这里只做了年月日  加时分秒也是可以的
                       date.substring(a).replace(/\d+/,function(d){c=parseInt(d,10)});
                       if(/y+/i.test(m)&&!result.year)result.year=c;
                       if(/M+/.test(m)&&!result.month)result.month=c;
                       if(/d+/i.test(m)&&!result.day)result.day=c;
               });
          }
         return result;
    };

测试

    getDateFromFormat("2011-11-12","YYYY-MM-DD");

    getDateFromFormat("2011-04-12","YYYY-MM-DD");

    getDateFromFormat("12/11/2011","DD/MM/YYYY");

    getDateFromFormat("2011-4-1","YYYY-M-D");

    getDateFromFormat("2011-12-20","YYYY-M-D");

    getDateFromFormat("12月20日(2011年)","M月D日(YYYY年)");

在前端如何保护共享对象

什么是共享对象

被多次使用到的同一个对象即为共享对象

比如我们用标准的es模块来写一个导出单位转换的模块

//converter module
export default {
    cmToIn(){
        //convert logic
    }
}

当我们在其它模块中使用该模块时,converter即是共享对象,内存中只有一份,不管它被import了多少次。

同理,上面展示的是通用方法的对象集合,在前端项目里,我们也会把一些所谓写死的数据集中封装在某个模块里,方便后期的修改,比如我们实现一个constant常量模块,我们把一些项目中使用的,后期可能会修改的数据放进去

//constant
export default {
    dateFormatter:'YYYY-MM-DD',
    reports:{
        productId:'123',
        productName:'456'
    }
}

这里仅示意一下

为什么要保护共享对象

防止共享的对象被意外修改导致线上故障

原则上这些通用的模块,我们不会,也不会有意的在我们业务代码中去修改里面的数据,尤其像常量这样的模块,如果要修改的话,我们肯定修改常量这个模块。

但是,凡事总有意外,比如说我们有这样一个场景:根据后端返回的用信息,以及前端写死的一些常量,来判断某个用户能不能展示某个报表,我们期望的代码可能是这样的

import Constant from './constant';//引入我们前面定义的constant模块
//...其它略
export default View.extend({
    render(){
        //...其它逻辑略
        if(Constant.reports.productId==user.reportProductId){
            //....
        }
    }
});

注意上述代码中的if语句,如果错写成:if(Constant.reports.productId=user.reportProductId),两个等号的比较写成了一个等号的赋值。

如果自测的时候,用户接口里user.reportProductId返回的正好也是123,那么先赋值,再做if判断,成立,做为开发者会错误的以为这里的逻辑没问题。当然,正常情况下也要测试下用户接口里user.reportProductId返回不是123的情况,这时候或许就能发现问题。

如果上述问题没有测试出来,阴差阳错的上线之后,这个问题对于大型单页应用是致命的,如果某个用户的reportProductId456,访问了写错的页面后,因为被意外的修改了constant中的reports.productId,会导致后续其它模块在读取时不再是最初的123而出问题

如何保护共享对象

const

const关键字声明的仅防止变量被重新赋值,无法防止对象修改

Object.freeze

可以防止被修改,但是如果对象嵌套时,被嵌套的对象依然可以被修改,需要开发者对要freeze的对象递归遍历进行freeze。最重要的一点是,当我修改一个freeze对象时,虽然修改不成功,但也没有任务失败的提示,在前述场景中,我们还是希望开发者在修改一个不允许的被修改的对象时能及时给出相应的提示。

Proxy

es6新增的代理操作对象的方法

Proxy相关的文章非常多,这里就不再详细说,我们借助Proxy来实现一个Safeguard方法来保护我们的共享对象

const Safeguard = o => {
    let build = o => {
        let entity = new Proxy(o, {
            set() {
                throw new Error('readonly');
            },
            get(target, property) {
                let out = target[property];
                if (target.hasOwnProperty(property) &&
                    (Array.isArray(out) ||
                        Object.prototype.toString.call(out) == '[object Object]')) {
                    return build(out);
                }
                return out;
            }
        });
        return entity;
    };
    return build(o);
}

这里简化了代码,你可以根据自己的需要去调整相应的实现逻辑

使用

const user=Safeguard({
    name:'行列',
    address:{
        city:'hz'
    }
});

这个user对象只能读,不能写,当开发者尝试写入新数据时,会抛出错误提示开发者

使用场景

地址栏解析对象

在单页应用中,我们需要把地址栏中的字符串地址解析成对象,方便我们使用。

比如/path/name?a=b&c=d,我们可能解析成这样的对象

{
    path:'/path/name',
    params:{
        a:'b',
        c:'d'
    }
}

如果你统计过你的单页应用,会发现固定的用户总是只访问某些页面,我们可以在用户访问某个页面时,临时的把地址栏中的这个地址字符串解析一遍,也可以把解析结果存起来,当用户再访问这个页面时,不需要解析,把存起来的结果拿出来使用即可

关于这一块我曾经写过Magix.Cache,详细的来说明该如何智能的缓存哪些需要的信息

对于缓存后的地址栏信息对象,它就是一个共享对象,要确保它不能被开发者写入新的值,就可以使用前面我们定义的Safeguard方法来进行保护

缓存的接口数据

在单页应用开发中,有些数据需要后端提供,但是后端提供的这些数据可能在很长一段时间内都不会被修改,比如省市数据,前端没必要在每次需要使用这种数据时都请求一次,所以前端可以把该接口的数据缓存下来,来节省请求

对于这样的数据对象,也需要保护,简言之,只要是共用的对象,均需要防止它被意外的修改

关于上线

前面我们聊到的Safeguard方法,在我看来是没必要发布到线上的,只要开发阶段存在即可。只要保证在开发中没有对共享对象的写入操作,那么发布到线上时肯定也没有写入操作,这时候这个保护Safeguard方法就是多余的。

如何在开发时保护,而发布到线上时去掉呢?

我们可以使用uglify这个代码压缩工具的global_defs配置。比如在开发阶段这样定义

if (typeof DEBUG == 'undefined') window.DEBUG = true;
//...

const user={
    name:'行列',
    address:{
        city:'hz'
    }
}

if(DEBUG){
    user=Safeguard(user);
}

然后在压缩时:

uglify({
    compress: {
        global_defs: {
            DEBUG: false
        }
    },
    output: {
        ascii_only: true
    }
});

那么这样压缩出来的代码就不包含DEBUG相关的语句了

当然,Safeguard跟随上线也没有什么大问题,最后这个“关于上线”这块只是想做更深入的探讨,如果Safeguard要上到线上,注意Proxy的兼容即可

那些年的magix

  magix3缘起

 我原本以为以magix1.2版本的稳定性可以支撑好些年,不曾想人在江湖,身不由己:出了一个magixbrix共用事件模块的magix2.0版本。magix2.0是在magix1.2的基础上,把事件模块换成brix提供的事件模块而已。在实际项目开发中,brix提供的事件模块并不能有效的解决dom变化事件需要解绑或绑定的问题。这是因为brix的事件模块是扫描dom节点找到有哪些事件,这样当dom变化时,都要重新扫描,而dom是否变化是在magixview中由开发者做的,这就导致需要在view中把所有与dom变化的地方都要关注起来,从而可以在dom变化的时候通知到brix的事件模块。如果存在大量的dom变化,事件这块的每次扫描整个dom,性能并不怎么好。

 分久必合,通过magix2.0brix整合重复的部分,使我意识到仅仅做事件这块是不够的,模块的加载和实例化也是重复的,viewbrix组件间的关系也是分不清楚的,那时候我被问的最多的一些问题:在项目中我应该把这个封装成brix组件么?brix组件里不能包含业务代码么?包含业务代码在我自己的项目里也是没问题啊?在brix组件里我怎么能够使用magix管理的接口?

 magix2.0的一些事情没有做好,我们回过头来重新审视,总结经验:这些合并应该更彻底一些。

 magix3.0,合并magix与brix,使view与组件归一化,统一模板引擎。brix抱歉了,有些必须割舍,包括brix这个概念。原来的brix组件变成magixview,现在这些组件对应的view在这里:magix-galllery

  模板引擎

 许多问题皆源于它,时至今日仍然还在围着模板引擎转,使用合理的模板引擎,生成最优的目标代码,以达到高效的界面更新

 合并后第一个挑战就是选择一个合适的模板引擎,统一我们之前在项目中用到的mustache,crox,xtemplate,vue等各式各样的模板。

 underscore.template,最后一版brix用的模板引擎,也没有什么学习成本,magix3就选择了它做为模板引擎。现在来看这个模板引擎的选择并不怎么好,但在当时要整合brix,要升级组件库,许多方案只能先使用旧方案,减少新方案带来的坑和其它问题。统一,在当时显得更重要。就这样我们选择了underscore.template模板写法。

  局部刷新之字符串拆分

 如果view数据有变化,我们可以用最新的数据和模板生成最新的HTML,然后通过view根节点的innerHTML属性更新界面。当然目前也可以通过dom diff最细粒度的更新。不过那时候的需求是:找一种可以介于把整个view粗犷的刷掉和最细粒度更新之间的方案。那就是以dom节点与数据进行绑定的局部刷新,感谢波哥在这块的探索与实现,magix3的首次使用的局部刷新就是该方案

 当时的局部刷新方案的弊端是:需要在待刷新节点上写上对应的数据key,如果对应key的数据有变化时,则只刷新该节点下的innerHTML,开发过直通车的同学应该有体会。有时候忘记写key了,导致数据变化界面没刷新,如果多写了,则会有不必要的刷新。

 带着不完善的方案,magix3的使命完成:使用原有的经验,统一割裂的开发方式,减少概念上的认知。

  离线处理

 处理不好性能的程序猿都是耍流氓。大概2015年底和波哥聊优化的事情,发现很多运行在线上的处理完全可以线下做,这样上线后可以减少计算,提升运行效率。同时因为是线下提前处理好的,可以通过查看结果来发现一些原来线上不能复现的问题。加上magix的本身也需要把html合并到js中,这时候magix-combine就出来了。

 最初magix-combine只是合并文件,并做一些简单替换。

 第一个主要的离线处理是前面提到的局部刷新之字符串拆分,为了方便开发人员,不在节点上标记数据变化的key,由程序自动识别完成。magix-combine做这一个功能时,从一个文件到拆分成十几个文件,从简单的正则到复杂的parser方案,前后持续时间最长,难度系数也最大,详细的技术方案可以查看这里 局部刷新与模板 。终于凭一己之力把它做了出来,也正是得益于该方案的实现,后续很多离线处理都在该功能的基础上顺利完成。

 第二个主要的离线处理是样式的scoped化,这里有记录在实施scoped之前遇到的问题 关于style的scope。 样式scoped方案线上处理的版本居多,但我们的要求是线下完成。参考过vue给节点增加data-v-hash的方式,私以为样式选择器从原来的标签或类选择器经过scoped后加上了属性选择,浏览器在处理样式匹配上性能会下降。参考过css-modules的做法,需要通过对象+旧选择器来使用变化后的选择器名称,很难和magix这种jshtml分离的开发方式结合起来,使用起来也不方便。同时要照顾开发人员,不能因为要使用scoped功能就要做很大的变化。

 “无感使用”是我在做样式scoped时候的感受。我该如何引入新的功能而不用改变现有的开发方式?我该如何平滑稳定的把有问题的方案引导到新的方案上来?虽说不破不立,但同事的感受更重要,我不能太唐突的推进。我要实施新功能,我也要照顾现有的开发流程,如何在二者间平衡,很难。最终在不改变当前开发方式的情况下,实现了想要的功能,新的方案得以顺利实施。难,吾往矣!

 其实,一直在跟随着社区的发展,只是像前面所说的,有些功能的实现是无感知的,许多开发者在使用的时候或许并不知道我们早已默默应用了该技术。不过也正是由于我们自己的工具,可以把社区中一些优秀的方案在我们的项目中做的更彻底,能工具化的为什么要开发者参与呢?

 第三个主要的离线处理是代码检查,之前我们的开发框架和组件可以快速的搭建出页面,但是如何保证产出的代码质量,如何让开发人员自己快速检查代码,如何避免别人踩过的坑,如何让别人的经验成为自己的经验,是我想解决,并且一定要解决的,尽管很难,If not me , who?

 目前代码检测涵盖样式检查(书写要求、使用情况等),js代码循环检查(n层循环嵌套),js接口服务数据检查,模板命令语法检查,模板图片src属性检查,模板不建议使用的标签检查,模板危险属性检查,模板a或area标签检查,模板iframe标签检查,模板mx事件写法检查,模板mx-view检查,模板重复属性检查,模板命令语句中function及for of语句检查,模板标签配对检查等

 把常见问题写到代码检测里面去!把别人的经验写到代码检测里面去!把需要掌握的知识点写到代码检测里面去!授鱼不如授渔

 所以2016-2017年我的精力都放在magix-combine上,尽管有些事情远远超出离线处理这个愿景。

  我回来了

 老实说,在我做magix-combine这段时间里,magix除必要的支持外并没有怎么跟进,不过我终于忙完magix-combine回来了。

 他们说underscore.template语法写多了比较乱,好的,支持类mustach的模板语法。他们说局部刷新使用字符串模板拆分的方式仍然刷新的范围太大了,而且社区里都是细粒度的刷新,好的,https://github.com/thx/magix/blob/master/src/tmpl/dom.js。真实dom与真实domdiff,真实dom与虚拟domdiff,虚拟dom与虚拟domdiff,满足你的一切好奇心。

 我说历史的原因,我们的dom转换是在线上完成的,这显然应该在线下做,jsx的是不错的首选,好的,使用jsx去写magix,感谢竹隐的支持。我说根据同事间的调查,并不是每个人都乐意使用jsx,而且刚熟悉的类mustache写法要丢弃么,好的,支持类quickapp形式的模板。我说这些加载器requirejs,seajs,webpack都是过客,浏览器原生的import才是主场,好的,https://github.com/thx/magix/tree/master/src/module

 你有问题我有解决方案,最美好的事情不过如此吧?

  局部刷新之dom diff

 magix3提供了比较多的diff,目前线上用的是真实dom之间的diff,这是要照顾一下开发人员还有部分组件,时间久了都会有一些技术债。真实dom diff可以操作dom,而使用虚拟dom是无论如何都不能操作真实dom的,所以目前我们想直接用虚拟dom还需要一段时间的过度

  当下

 啰嗦了一大堆,有些伤感,回头看了下有用的并不多

 magix最新版本3.8.10,magix-combine的最新版本是3.11.0。模板引擎不要再使用unerscore.template,请换用类mustache的模板,当然,不换也没问题,兼容的。局部刷新使用拆分字符串的方案应该不会再使用(旧项目有bug会继续修复),pc端目前使用真实dom diff,移动端没历史包袱可以使用虚拟dom diff,长远看都会切到虚拟dom上,当然,如果浏览器本身提供了增量更新,我们就不用这么费劲了。magix3版本里面的方案切换应该没有什么成本。

 magix-combine看下 https://github.com/thx/magix-combine/blob/master/CHANGELOG.md 吧,想做一下magix-combine的分享,太多也太专了,讲的无聊,听的枯燥。今天看了下magix-combine,好像不是那么容易看懂。

 实验中的功能:离线转虚拟dom,这个由magix-combine支持。dom diff按时间片更新,这个是看reactTime Slicing后做的。

 我会继续做magixmagix-combine,有些功能因为个人工作上的安排晚了些,但不会缺席。

 github.com上的magix-gallery暂无精力维护,我们后台项目开发中使用的组件请使用虞佳维护的zs_gallery,组件使用等相关的问题可以直接联系虞佳

 解决开发、调试、打包、发布工具的magix-cli工具由崇志维护,magix3统一了技术方案,magix-cli则统一了开发方式。这个工具在这里:http://gitlab.alibaba-inc.com/thx/magix-cli

 2016年底有感于崇志、浩添去北京支援一淘商家后台项目,虽说当时我们的开发效率很高,我觉得还可以再突飞猛进,所以做了面向开发人员的可视化页面搭建:生成可供编译的代码而非线上页面。2017年集团可视化页面搭建遍地开花,而我们的则由宫卫默默无闻的开发,除了支持业务外,到目前仍然在持续完善中。这个工具在这里:http://gitlab.alibaba-inc.com/thx/magix-desiger ,附一个搭建gif图:https://img.alicdn.com/tfs/TB19JeNrL9TBuNjy0FcXXbeiFXa-1700-880.gif 现在开发一个页面只需要几分钟。重要的是以后普通页面会由运营搭建,彻底解放前端。

 移动端的cell由竹隐在负责维护,我们移动端基本上都是由cell支持的,开发移动端页面的同学应该不陌生吧。

 还有很多想法,没有落地,一个人的时间和精力是有限的。

  后记

 以古作镜,可知兴替。技术的发展是飞速的,没有哪一套技术实现可以久远,相对不变的,唯思路尔。想在技术上长足的同学,不要留于使用的表面,走进喜欢的框架里,读懂作者的悲喜。犹记得木头曾聊过微软的htc技术,时至今日,微软自己的浏览器都不支持了吧,但是这种解决问题的思路,不还在react,vue上持续发光么,iframe标签不也在淡化,由新的方案替代么。

 没有什么是不能被淘汰的,要抓住本质。去理解他人的思路,方可一反三,去读懂他人的实现,方可知深坑,去按自己的想法实施,方可胜于蓝。

道格拉斯-普克 抽稀算法 附javascript实现

道格拉斯-普克抽稀算法,是用来对大量冗余的图形数据点进行压缩以提取必要的数据点。该算法实现抽稀的过程是:先将一条曲线首尾点虚连一条直线,求其余各点到该直线的距离,取其最大者与规定的临界值相比较,若小于临界值,则将直线两端间各点全部舍去,否则将离该直线距离最大的点保留,并将原线条分成两部分,对每部分线条再实施该抽稀过程,直到结束。抽稀结果点数随选取限差临界值的增大而减少,应用时应根据精度来选取限差临界值,以获得最好的效果。


以下转载自:垂距法与道格拉斯-普克法删除冗余顶点效率的比较

道格拉斯- 普克法可描述为:将一条曲线首末顶点虚连一条直线 ,求出其余各顶点到该直线的距离 ,选其最大者与规定的限差相比较 ,若小于等于限差 ,则将直线两端间各点全部删去;若大于限差 ,则离该直线距离最大的顶点保留 ,并以此为界 ,把曲线分为两部分 ,对这两部分重复使用上述方法 ,直至最终无法作进一步的压缩为止 (见图 3)。
img

道格拉斯 2 普克法有一个十分突出的优点 ,即它是一个整体算法 ,在一般情况下可保留较大弯曲形态上的特征点。经道格拉斯-普克法压缩后得到的图形如图 4所示。由于该算法可准确删除小弯曲上的定点 ,故能从体上有效地保持线要素的形态特征。正是因为道格拉斯-普克法具有这样突出的优点 ,所以已经在线要素地自动制图中得到了较广泛的应用。但道格拉斯- 普克法较垂距法复杂 ,且通常编程实现时需要采用递归方 ,有一定的难度。
img

转载end

以下是javascript版本的实现

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
   <title>DouglasPeucker</title>    
</head>
<body>
   <div id="processBefore" style="background-color:#ccc;height:100px;position:relative;"></div>
        <div id="processAfter" style="background-color:#ccc;height:100px;margin-top:10px;position:relative;"></div>
</body>
<script type="text/javascript" src="Items/js/K1.source.js">
var points = [{
    x: 10,
    y: 10
}, {
    x: 20,
    y: 30
}, {
    x: 30,
    y: 12
}, {
    x: 35,
    y: 5
}, {
    x: 40,
    y: 22
}, {
    x: 50,
    y: 12
}, {
    x: 80,
    y: 40
}];
var Helper = {
    renderPointsTo: function(points, anchor) {
        var d;
        for (var i = 0, p, a = K(anchor); i < points.length; i++) {
            p = points[i];
            if (a) {
                a.appendChild(K('div', {}, {
                    position: 'absolute',
                    left: p.x + 'px',
                    top: p.y + 'px',
                    width: '5px',
                    height: '5px',
                    backgroundColor: 'green',
                    fontSize: '1px'
                }));
            }

        }
    }
};
Helper.renderPointsTo(points, 'processBefore');
var DouglasPeucker = {
    getProcessPoints: function(points, tolerance) {
        /// <summary>获取处理后的点</summary>
        /// <param name="points" type="Array">包含点的数组</param>
        /// <param name="tolerance" type="Float">取样临界值</param>
        /// <returns type="Array" />
        if (!K.isArr(points) || !points.length) { //当points不是数组或没有值时,直接返回一个空数组
            return [];
        }
        if (points.length < 3) return points; //小于3个点时不抽稀,因为1个或2个点无法进行抽稀
        var firstPoint = 0,
            lastPoint = points.length - 1; //取开始点与结束点的下标
        var pointIndexsToKeep = []; //保存需要点下标的数组
        pointIndexsToKeep.push(firstPoint);
        pointIndexsToKeep.push(lastPoint); //开始与结束不进行处理,直接保留
        while (points[firstPoint] == points[lastPoint]) { //处理闭合情况,闭合时,强制断开
            lastPoint--;
        }
        this.reduce(points, firstPoint, lastPoint, tolerance, pointIndexsToKeep); //抽稀
        var resultPoints = []; //返回的点数组
        pointIndexsToKeep.sort(function(a, b) { //排序,这个可排可不排
            return a - b;
        });
        for (var i = 0; i < pointIndexsToKeep.length; i++) {
            resultPoints.push(points[pointIndexsToKeep[i]]);
        }
        return resultPoints;
    },
    reduce: function(points, firstPoint, lastPoint, tolerance, pointIndexsToKeep) {
        /// <summary>抽稀处理</summary>
        /// <param name="points" type="Array">待抽稀的数组</param>
        /// <param name="firstPoint" type="Integer">起点</param>
        /// <param name="lastPoint" type="Integer">终点</param>
        /// <param name="tolerance" type="Float">取样临界值</param>
        /// <param name="pointIndexsToKeep" type="Array">保留点下标的数组</param>
        var maxDis = 0,
            idxFarthest = 0; //定义最大长度及最远点的下标
        for (var i = firstPoint, dis; i < lastPoint; i++) {
            dis = this.perpendicularDistance(points[firstPoint], points[lastPoint], points[i]); //获取当前点到起点与
            if (dis > maxDis) { //保存最远距离
                maxDis = dis;
                idxFarthest = i;
            }
        }
        if (maxDis > tolerance && idxFarthest != 0) { //如果最远距离大于临界值
            pointIndexsToKeep.push(idxFarthest);
            this.reduce(points, firstPoint, idxFarthest, tolerance, pointIndexsToKeep);
            this.reduce(points, idxFarthest, lastPoint, tolerance, pointIndexsToKeep);
        }
    },
    perpendicularDistance: function(beginPoint, endPoint, comparePoint) {
        /// <summary>计算给出的comparePoint到beginPoint与endPoint组成的直线的垂直距离</summary>
        /// <param name="beginPoint" type="Object">起始点</param>
        /// <param name="endPoint" type="Object">结束点</param>
        /// <param name="comparePoint" type="Object">比较点</param>
        /// <returns type="Float" />
        //Area = |(1/2)(x1y2 + x2y3 + x3y1 - x2y1 - x3y2 - x1y3)|   *Area of triangle
        //Base = v((x1-x2)2+(y1-y2)2)                               *Base of Triangle*
        //Area = .5*Base*H                                          *Solve for height
        //Height = Area/.5/Base
        var area = Math.abs(0.5 * (beginPoint.x * endPoint.y + endPoint.x * comparePoint.y + comparePoint.x * beginPoint.y -
            endPoint.x * beginPoint.y - comparePoint.x * endPoint.y - beginPoint.x * comparePoint.y));
        var bottom = Math.sqrt(Math.pow(beginPoint.x - endPoint.x, 2) + Math.pow(beginPoint.y - endPoint.y, 2));
        var height = area / bottom * 2;
        return height;
    }
};
Helper.renderPointsTo(DouglasPeucker.getProcessPoints(points, 14), 'processAfter');
</script>
</html>

js版数字转中文 支持到12位

/*
    工具包
*/
var Utils={
    /*
        单位
    */
    units:'个十百千万@#%亿^&~',
    /*
        字符
    */
    chars:'零一二三四五六七八九',
    /*
        数字转中文
        @number {Integer} 形如123的数字
        @return {String} 返回转换成的形如 一百二十三 的字符串             
    */
    numberToChinese:function(number){
        var a=(number+'').split(''),s=[],t=this;
        if(a.length>12){
            throw new Error('too big');
        }else{
            for(var i=0,j=a.length-1;i<=j;i++){
                if(j==1||j==5||j==9){//两位数 处理特殊的 1*
                    if(i==0){
                        if(a[i]!='1')s.push(t.chars.charAt(a[i]));
                    }else{
                        s.push(t.chars.charAt(a[i]));
                    }
                }else{
                    s.push(t.chars.charAt(a[i]));
                }
                if(i!=j){
                    s.push(t.units.charAt(j-i));
                }
            }
        }
        //return s;
        return s.join('').replace(/零([十百千万亿@#%^&~])/g,function(m,d,b){//优先处理 零百 零千 等
            b=t.units.indexOf(d);
            if(b!=-1){
                if(d=='亿')return d;
                if(d=='万')return d;
                if(a[j-b]=='0')return '零'
            }
            return '';
        }).replace(/零+/g,'零').replace(/零([万亿])/g,function(m,b){// 零百 零千处理后 可能出现 零零相连的 再处理结尾为零的
            return b;
        }).replace(/亿[万千百]/g,'亿').replace(/[零]$/,'').replace(/[@#%^&~]/g,function(m){
            return {'@':'十','#':'百','%':'千','^':'十','&':'百','~':'千'}[m];
        }).replace(/([亿万])([一-九])/g,function(m,d,b,c){
            c=t.units.indexOf(d);
            if(c!=-1){
                if(a[j-c]=='0')return d+'零'+b
            }
            return m;
        });
    }
};

以下是测试代码:

for(var i=1,num;i<100;i++){
num=Math.floor(Math.random()*900000000000);
document.getElementById('test_editor').value+=num+':'+Utils.numberToChinese(num)+'\n';
}

var nums=[1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,10000000000,100000000000,2,20,200,2000,20000,200000,2000000,20000000,200000000,2000000000,20000000000,200000000000];

for(var p in nums){
document.getElementById('test_editor').value+=nums[p]+':'+Utils.numberToChinese(nums[p])+'\n';
}

显示结果:

546922213826:五千四百六十九亿二千二百二十一万三千八百二十六
225517757101:二千二百五十五亿一千七百七十五万七千一百零一
304989819591:三千零四十九亿八千九百八十一万九千五百九十一
650530768615:六千五百零五亿三千零七十六万八千六百一十五
474366279962:四千七百四十三亿六千六百二十七万九千九百六十二
402193930448:四千零二十一亿九千三百九十三万零四百四十八
330811323772:三千三百零八亿一千一百三十二万三千七百七十二
613724178372:六千一百三十七亿二千四百一十七万八千三百七十二
362437458377:三千六百二十四亿三千七百四十五万八千三百七十七
280791491687:二千八百零七亿九千一百四十九万一千六百八十七
712572891931:七千一百二十五亿七千二百八十九万一千九百三十一
622361249622:六千二百二十三亿六千一百二十四万九千六百二十二
785000698935:七千八百五十亿零六十九万八千九百三十五
121039034440:一千二百一十亿三千九百零三万四千四百四十
145761350789:一千四百五十七亿六千一百三十五万零七百八十九
801418871325:八千零一十四亿一千八百八十七万一千三百二十五
275617014335:二千七百五十六亿一千七百零一万四千三百三十五
669283556190:六千六百九十二亿八千三百五十五万六千一百九十
215284914400:二千一百五十二亿八千四百九十一万四千四百
577156188141:五千七百七十一亿五千六百一十八万八千一百四十一
308390670957:三千零八十三亿九千零六十七万零九百五十七
260173492764:二千六百零一亿七千三百四十九万二千七百六十四
174321944673:一千七百四十三亿二千一百九十四万四千六百七十三
53377468036:五百三十三亿七千七百四十六万八千零三十六
532141896964:五千三百二十一亿四千一百八十九万六千九百六十四
30444497053:三百零四亿四千四百四十九万七千零五十三
577626148261:五千七百七十六亿二千六百一十四万八千二百六十一
513050154801:五千一百三十亿五千零一十五万四千八百零一
376303814890:三千七百六十三亿零三百八十一万四千八百九十
478271079791:四千七百八十二亿七千一百零七万九千七百九十一
846915088935:八千四百六十九亿一千五百零八万八千九百三十五
622734865742:六千二百二十七亿三千四百八十六万五千七百四十二
250556318001:二千五百零五亿五千六百三十一万八千零一
731040531375:七千三百一十亿四千零五十三万一千三百七十五
382395857739:三千八百二十三亿九千五百八十五万七千七百三十九
291990932264:二千九百一十九亿九千零九十三万二千二百六十四
254447153708:二千五百四十四亿四千七百一十五万三千七百零八
329426108502:三千二百九十四亿二千六百一十万八千五百零二
611531587954:六千一百一十五亿三千一百五十八万七千九百五十四
280253311170:二千八百零二亿五千三百三十一万一千一百七十
498114289002:四千九百八十一亿一千四百二十八万九千零二
696280529166:六千九百六十二亿八千零五十二万九千一百六十六
483829251342:四千八百三十八亿二千九百二十五万一千三百四十二
849633660184:八千四百九十六亿三千三百六十六万零一百八十四
410711754414:四千一百零七亿一千一百七十五万四千四百一十四
735140278725:七千三百五十一亿四千零二十七万八千七百二十五
178728843350:一千七百八十七亿二千八百八十四万三千三百五十
333680152899:三千三百三十六亿八千零一十五万二千八百九十九
879254318396:八千七百九十二亿五千四百三十一万八千三百九十六
695026128590:六千九百五十亿二千六百一十二万八千五百九十
692600909123:六千九百二十六亿零九十万九千一百二十三
529338064356:五千二百九十三亿三千八百零六万四千三百五十六
317334694337:三千一百七十三亿三千四百六十九万四千三百三十七
345744346837:三千四百五十七亿四千四百三十四万六千八百三十七
510409315863:五千一百零四亿零九百三十一万五千八百六十三
722184947710:七千二百二十一亿八千四百九十四万七千七百一十
510530514221:五千一百零五亿三千零五十一万四千二百二十一
631038174222:六千三百一十亿三千八百一十七万四千二百二十二
647772659973:六千四百七十七亿七千二百六十五万九千九百七十三
423471230012:四千二百三十四亿七千一百二十三万零一十二
423306171256:四千二百三十三亿零六百一十七万一千二百五十六
505707781786:五千零五十七亿零七百七十八万一千七百八十六
869957584874:八千六百九十九亿五千七百五十八万四千八百七十四
231579106734:二千三百一十五亿七千九百一十万六千七百三十四
80828059163:八百零八亿二千八百零五万九千一百六十三
17212792377:一百七十二亿一千二百七十九万二千三百七十七
55764319017:五百五十七亿六千四百三十一万九千零一十七
430219790713:四千三百零二亿一千九百七十九万零七百一十三
158350342570:一千五百八十三亿五千零三十四万二千五百七十
362289374504:三千六百二十二亿八千九百三十七万四千五百零四
776314108843:七千七百六十三亿一千四百一十万八千八百四十三
301021029178:三千零一十亿二千一百零二万九千一百七十八
120691162021:一千二百零六亿九千一百一十六万二千零二十一
34760018592:三百四十七亿六千零一万八千五百九十二
1425175442:十四亿二千五百一十七万五千四百四十二
359113932447:三千五百九十一亿一千三百九十三万二千四百四十七
254807677421:二千五百四十八亿零七百六十七万七千四百二十一
781982213661:七千八百一十九亿八千二百二十一万三千六百六十一
29563927374:二百九十五亿六千三百九十二万七千三百七十四
316910050269:三千一百六十九亿一千零五万零二百六十九
729591861238:七千二百九十五亿九千一百八十六万一千二百三十八
304278177347:三千零四十二亿七千八百一十七万七千三百四十七
61284312240:六百一十二亿八千四百三十一万二千二百四十
843466943569:八千四百三十四亿六千六百九十四万三千五百六十九
798746930895:七千九百八十七亿四千六百九十三万零八百九十五
864205827192:八千六百四十二亿零五百八十二万七千一百九十二
200618428295:二千零六亿一千八百四十二万八千二百九十五
414672171302:四千一百四十六亿七千二百一十七万一千三百零二
134967442641:一千三百四十九亿六千七百四十四万二千六百四十一
820677190609:八千二百零六亿七千七百一十九万零六百零九
574058298657:五千七百四十亿五千八百二十九万八千六百五十七
842932998524:八千四百二十九亿三千二百九十九万八千五百二十四
146635147823:一千四百六十六亿三千五百一十四万七千八百二十三
766698761744:七千六百六十六亿九千八百七十六万一千七百四十四
402568199182:四千零二十五亿六千八百一十九万九千一百八十二
134140797843:一千三百四十一亿四千零七十九万七千八百四十三
481854840341:四千八百一十八亿五千四百八十四万零三百四十一
828903740348:八千二百八十九亿零三百七十四万零三百四十八
748493874133:七千四百八十四亿九千三百八十七万四千一百三十三
1:一
10:十
100:一百
1000:一千
10000:一万
100000:十万
1000000:一百万
10000000:一千万
100000000:一亿
1000000000:十亿
10000000000:一百亿
100000000000:一千亿
2:二
20:二十
200:二百
2000:二千
20000:二万
200000:二十万
2000000:二百万
20000000:二千万
200000000:二亿
2000000000:二十亿
20000000000:二百亿
200000000000:二千亿

解题思路:

先把数字简单的转成汉字加上单位 如100则转成 一百零十零
然后再处理生成的字符串 对于以零后跟单位的 则要考虑 亿和万 如果是亿和万保留单位去掉零 否则去掉单位
然后再处理多个零连在一起的情况
亿的情况又特殊些
大于万的单位比较特殊 需特殊照顾

水平有限 代码乱 大家凑合着看

前端做模糊搜索

我们先看一下效果图:
image

这是搜索关键字cfg时,会自动匹配到config方法

同样,我们再看另一个例子

image
通过关键字bi会匹配到好几个结果

这个和一些编辑器的搜索功能很像,比如sublime text,不需要知道关键字的完整拼写,只需要知道其中的几个字母即可。

那么这个功能在前端我们如何去实现呢?

不考虑性能的话,我们可以用正则简单实现如下:

把关键字拆分,加入(.?),如cfg最终为 (.?)(c)(.?)(f)(.?)(g)(.*?),然后拿这个正则去测试要搜索的列表,把符合要求的选项给拿出来即可

考虑到要高亮结果,我们还要生成对应的替换表达式,最后的函数如下

var escapeRegExp = /[\-#$\^*()+\[\]{}|\\,.?\s]/g;
var KeyReg = (key) => {
    var src = ['(.*?)('];
    var ks = key.split('');
    if (ks.length) {
        while (ks.length) {
            src.push(ks.shift().replace(escapeRegExp, '\\$&'), ')(.*?)(');
        }
        src.pop();
    }
    src.push(')(.*?)');
    src = src.join('');
    var reg = new RegExp(src, 'i');
    var replacer = [];
    var start = key.length;
    var begin = 1;
    while (start > 0) {
        start--;
        replacer.push('$', begin, '($', begin + 1, ')');
        begin += 2;
    }
    replacer.push('$', begin);

    info = {
        regexp: reg,
        replacement: replacer.join('')
    };
    return info;
};

调用KeyReg把关键字传入,拿返回值的regexp去检测搜索的列表,把符合的保存下来即可。

到目前为止我们只实现了搜索功能,按更优的体验来讲,在搜索结果中,要优先把相连匹配的放在首位,如bi关键字,要把bind结果放到beginUpdate前面。第二个截图是有优化的地方的。

要完成这个功能,我们使用KeyReg返回值中的replacement,用它进行检测,把结果中长度最长的放前面即可,这块代码以后有时间再补充

2018.5.31
今天重构了下,增加了结果排序,完整的代码及使用示例如下

let Searcher = (() => {
    let escapeRegExp = /[\-#$\^*()+\[\]{}|\\,.?\s]/g;
    let escapeReg = reg => reg.replace(escapeRegExp, '\\$&');
    //groupLeft 与 groupRight是对结果进一步处理所使用的分割符,可以修改
    let groupLeft = '(',
        groupRight = ')';
    let groupReg = new RegExp(escapeReg(groupRight + groupLeft), 'g');
    let groupExtractReg = new RegExp('(' + escapeReg(groupLeft) + '[\\s\\S]+?' + escapeReg(groupRight) + ')', 'g');
    //从str中找到最大的匹配长度
    let findMax = (str, keyword) => {
        let max = 0;
        keyword = groupLeft + keyword + groupRight;
        str.replace(groupExtractReg, m => {
            //keyword完整的出现在str中,则优秀级最高,排前面
            if (keyword == m) {
                max = Number.MAX_SAFE_INTEGER;
            } else if (m.length > max) {//找最大长度
                max = m.length;
            }
        });
        return max;
    };
    let keyReg = key => {
        let src = ['(.*?)('];
        let ks = key.split('');
        if (ks.length) {
            while (ks.length) {
                src.push(escapeReg(ks.shift()), ')(.*?)(');
            }
            src.pop();
        }
        src.push(')(.*?)');
        src = src.join('');
        let reg = new RegExp(src, 'i');
        let replacer = [];
        let start = key.length;
        let begin = 1;
        while (start > 0) {
            start--;
            replacer.push('$', begin, groupLeft + '$', begin + 1, groupRight);
            begin += 2;
        }
        replacer.push('$', begin);

        info = {
            regexp: reg,
            replacement: replacer.join('')
        };
        return info;
    };

    return {
        search(list, keyword) {
            //生成搜索正则
            let kr = keyReg(userInput);
            let result = [];
            for (let e of list) {
                //如果匹配
                if (kr.regexp.test(e)) {
                    //把结果放入result数组中
                    result.push(e.replace(kr.regexp, kr.replacement)
                        .replace(groupReg, ''));
                }
            }
            //对搜索结果进行排序
            //1. 匹配关键字大小写一致的优先级最高,比如搜索up, 结果中的[user-page,beginUpdate,update,endUpdate],update要排在最前面,因为大小写匹配
            //2. 匹配关键字长的排在前面
            result = result.sort((a, b) => findMax(b, keyword) - findMax(a, keyword));
            return result;
        }
    };
})();

//假设list是待搜索的列表
let list = ['config', 'user-page', 'bind', 'render', 'beginUpdate', 'update', 'endUpdate'];
//假设userInput是用户输入的关键字
let userInput = 'up';

//获取搜索的结果
console.log(Searcher.search(list, userInput));
// ["(up)date", "begin(Up)date", "end(Up)date", "(u)ser-(p)age"]

对搜索结果中的内容做进一步处理渲染出来即可,比如把 ( 替换成 <span style="color:red">) 替换成</span>显示到页面上就完成了高亮显示

识别滚动条上的mousedown mouseup事件

网页内容区域自动滚动,滚动条会随着内容的增加自动往下滚动。

当用户鼠标在滚动条上按下的时候,我们可以假设他(她)正在浏览聊天内容,那么这个时候好的用户体验就不能让滚动条再自动滚动了。

为了实现这个功能,可能大家首先会想到的就是mouse down 和 mouse up事件了。

嗯,我们可以利用它,我们还要识别滚动条的宽度及最左侧的位置,于是我们有了这样的一个方法:

var getScrollbar=function(){
    var e=document.documentElement,
        ow=e.offsetWidth,
        cw=e.clientWidth;

    return {//需要识别滚动条是在左面还是右面,目前没做处理,简单示例
        left:cw,
        width:ow-cw
    }
}

getScrollbar获取滚动条左侧位置,及滚动条的宽度,接下来我们要注册onmousedown事件,我们注册在document上

var isOnScrollbar;
document.onmousedown=function(e){
    e=e||window.event;
    var bar=getScrollbar();
    if(e.clientX>bar.left){

        isOnScrollbar=true;
        document.title='mousedown on scroll bar';
    }
}

我们发现这段代码可以在IE FF下正常运行,接下来注册mouseup

document.onmouseup=function(e){
    if(isOnScrollbar){
        document.title='mousedup';
    }else{
        document.title='mousedup on body';
    }
    isOnScrollbar=false;
}

发现除IE外其它浏览器都可以正常工作,IE不行,尝试跟踪mousemove事件:

document.onmousemove=function(){
    window.status=new Date().getTime();
}

发现鼠标在滚动条上按下后移动,mousemove是不触发的,而其它浏览器是正常触发,猜测IE在拖动滚动条开始时

setCapture了,导致其它事件不能正常运行,不过发现鼠标在mouseup后,mousemove会触发一次,我们可以利用这个

来hack IE下的问题

if(document.attachEvent){
    document.onmousemove=function(){
        if(isOnScrollbar){
            isOnScrollbar=false;
            document.title='mousedup';
        }
    }
}

最终的测试如下:

<!doctype>
<html>
<head>
    <title>aa</title>
    <style type="text/css">
        body
        {
            height: 2000px;
        }
    </style>
</head>
<body>
</body>
</html>

<script type="text/javascript">
var getScrollbar=function(){
    var e=document.documentElement,
        ow=e.offsetWidth,
        cw=e.clientWidth;
    return {
        left:cw,
        width:ow-cw
    }
}
var isOnScrollbar;
document.onmousedown=function(e){
    e=e||window.event;
    var bar=getScrollbar();
    if(e.clientX>bar.left){
        isOnScrollbar=true;
        document.title='mousedown on scroll bar';
    }
}
if(document.attachEvent){
    document.onmousemove=function(){
        if(isOnScrollbar){
            isOnScrollbar=false;
            document.title='mousedup';
        }
    }
}
document.onmouseup=function(e){
    if(isOnScrollbar){
        document.title='mousedup';
    }else{
        document.title='mousedup on body';
    }
    isOnScrollbar=false;
    alert('up');
}
</script>

本例只是抛砖引玉,只提供一个简单的思路,没有严格的测试,也许在其它浏览器下有问题,欢迎留言交流

HTML在线编辑器,可调整大小对象在firefox一个不满意处

通常一个网页编辑器使用iframe做为载体,开启document的designMode为on就可以了

如果你的内容中有图片之类的,通常在您点击一下它之后,会出现可以调整大小的手柄,然而在firefox下,你在调整完图片大小之后会发现,原来图片周围的8个调整手柄不见了, 即使您在图片上再次单击也是没效果的,必须把鼠标在编辑区内别的地方点一下再去点图片才行。

ie没这问题

另外用webkit内核的更悲惧些,根本不出调整手柄,因此 chrome safari mathon3都会受影响,opera尚未测试,希望表现好一些。

对于控制它们可调整大小或不可调整大小,ie下可以监听body的onresizestart方法,通过event的srcElement取得当前对象,通过event.returnVlaue=false来阻止调整大小

其它浏览器可以使用execCommand('enableObjectResizing', false, false)临时关闭调整功能,在需要的时候再打开

让eval()全局作用域执行的方法深入研究

eval(str) 用来传入一个字符串动态执行一段脚本,这个方法非常有用。当直接用eval()时,作用域为当前作用域,有时候我们需要让它在全局作用域范围内执行,比如 ajax返回的脚本字符串,然而浏览器对eval的差异可能使事情刚开始并不是那么顺利,本文通过在7种浏览器(IE, Firefox, Chrome, Safari, Opera)环境中测试,并提出三种解决方案,使这个问题比较完美的解决。

看这一段javascript代码:

function xx(){ 
var x= 1 ; 
window .eval( 'var x=3;' ); 
document .writeln(x); 
}

xx();

在你自己测试和看我接下来的分析之前,先想想,你认为输出结果会是什么呢?是1还是3?

根据本文的标题,可知肯定是在不同浏览器下有不同表现的。

以下是我的实测数据:

function xx(){ 
var x= 1 ; 
window .eval ( 'var x=3;' ); 
document .writeln (x); 
} 
xx(); 

浏览器 IE IE Firefox Chrome Chrome Safari Opera 版本 7.0 8.0 3.0.8 1.0 4.0 4.0.2 9.62 运行结果 3 3 1 3 1 1 1
可见各浏览器及版本对window.eval()的作用域处理是有差异的。

IE中,window.eval()和eval()一样只在当前作用域生效。

Firefox,Safari,Opera中,直接调用eval()为当前作用域,window.eval()调用为全局作用域。

尤其值得注意的是,Google Chrome 的不同版本之间对于eval的处理也有差异。

如果需要在全局作用域eval()的效果,且通用于所有浏览器,那就得好好变通一下了。

方法之一:
使用IE专有的window .execScript 。

如果你碰到这个问题不知所措,并上网搜索,这个方法大概是最先也几乎唯一能搜索到的方法。

window .execScript (sExpression , sLanguage )。

比如上面那一段代码中eval一句如果换成window .execScript( 'var x=3;' ); IE中的运行结果就是1了。

非IE内核的浏览器并不支持window .execScript 。

IE之所以有这个window .execScript ,还和IE能够执行其他语言的脚本有关,通过给不同的sLanguage 参数,IE这个方法除能够执行javascript之外,还可以执行vbscript或是其他任何安装过相应解释引擎的脚本如perl,python等。

当需要在局部环境中执行的时候,我们就直接用eval()。

当需要在全局环境中执行的时候,我们可以封装一个通用的函数,就像下面这样:

//在全局环境中执行

function evalGlobal(strScript){
    if( window .execScript) window .execScript( strScript );

else window . eval ( strScript ); 
}

就是将IE和非IE区别开来对待。

看起来,问题似乎圆满解决了。但是显然是有问题的,比如上表中的Chrome 1.0也和IE的eval()规则一致,况且还不知道其他浏览器其他版本是否有差异呢,因此,这种方法并不很可靠。

但是如果你有一点完美主义者的倾向,那么事情还不能到此为止,肯定是有更好更简洁的方法的嘛。

不知道阅读此文的你是否有想到呢?

是否和我的想法一致呢?

方法之二:
新建一个<script>元素装载脚本。

这种方法常用来解决innerHTML中的脚本不能运行的问题。但用来解决eval()的作用域问题,恐怕就比较罕见了。

//在全局环境中执行

function evalGlobal(strScript){

        var a = document .createElement ("script" );
        a.type= "text/javascript" ;
        a.text= strScript ;
        document .getElementsByTagName ("head" )[0 ].appendChild (a) ;
}

虽然这个方法有点变态,需要新增一个<script>元素,但优点是各种浏览器及版本通用,比方法一要好一些了。。

但是如果你有再多一点完美主义者的倾向,那么事情还不能到此为止,毕竟添加了一个HTML元素嘛,影响了页面原本的DOM结构。

那么是不是有更好更简洁的方法的呢?答案是肯定的。经过我的研究,找到了同时具备简洁和可靠的方法三。

不知道阅读此文的你是否有想到呢?

是否和我的想法一致呢?

方法之三:
还是eval。回归原生态。

我们别忘了javascript里面有一个改变上下文环境的关键字,强大的with .

原来事情可以更简单更有效!

//在全局环境中执行

function evalGlobal(strScript){

        with ( window )eval (strScript) ;
}

看看,都这么简单了,我们完全可以不用封装为函数了,直接在代码中用。

文章最开始的代码我们就可以这样来了:

function xx(){ 
eval ( 'var x=1;' ); //局部变量 
with ( window ){ eval ( 'var x=3;' );} //全局变量 
    //也可以用封装的 evalGlobal( 'var x=3' ); 
document .writeln (x); //1 局部变量 
document .writeln ( window .x); //3 全局变量 
} 
xx();

特别:
有时候,我们eval()要求既不是在全局执行,也不是在当前作用域执行,而是在父对象或子对象中执行,这时,用 with ( objContext )eval (strScript) 就更加是不可替代的选择了。

总结:
让eval()全局作用域执行的方法主要有:

(1)window .execScript + window . eval 级别:弱。 缺点:不简洁,不可靠,不通用。

(2)document . createElement ("script" ) 级别:凑合。缺点:不简洁,不干净。优点:可靠,通用。

(3)with ( objContext )eval (strScript) 级别:最佳。优点:简洁,干净,可靠,通用。

事情到这里,才可以去休息一下了。

LZW压缩算法js版本

网上搜到的原版

// LZW-compress a string
function lzw_encode(s) {
    vardict = {};
    vardata = (s + "").split("");
    varout = [];
    varcurrChar;
    varphrase = data[0];
    varcode = 256;
    for (vari = 1; i < data.length; i++) {
        currChar = data[i];
        if (dict[phrase + currChar] != null) {//这块有问题
            phrase += currChar;
        } else {
            out.push(phrase.length > 1 ? dict[phrase] : phrase.charCodeAt(0));
            dict[phrase + currChar] = code;
            code++;
            phrase = currChar;
        }
    }
    out.push(phrase.length > 1 ? dict[phrase] : phrase.charCodeAt(0));
    for (vari = 0; i < out.length; i++) {
        out[i] = String.fromCharCode(out[i]);
    }
    returnout.join("");
}
// Decompress an LZW-encoded string
function lzw_decode(s) {
    vardict = {};
    vardata = (s + "").split("");
    varcurrChar = data[0];
    varoldPhrase = currChar;
    varout = [currChar];
    varcode = 256;
    varphrase;
    for (vari = 1; i < data.length; i++) {
        varcurrCode = data[i].charCodeAt(0);
        if (currCode < 256) {
            phrase = data[i];
        } else {
            phrase = dict[currCode] ? dict[currCode] : (oldPhrase + currChar);
        }
        out.push(phrase);
        currChar = phrase.charAt(0);
        dict[code] = oldPhrase + currChar;
        code++;
        oldPhrase = phrase;
    }
    returnout.join("");
}

很不幸的是,在压缩的时候,注释部分是有瑕疵的,比如你压缩这个字符串在ff浏览器下:

watchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatchwatch

因为标准浏览器下对象都有一个watch方法,所以会出问题,因此我改写了这个过程:

xcode = function(s, f) {
    if (!s) return '';
    var dict = {},
        out = [],
        prefix = s.charAt(0),
        curChar = prefix,
        oldPrefix = curChar,
        idx = 256,
        i, c, d,
        g = function() {
            out.push(prefix.length > 1 ? String.fromCharCode(dict[prefix]) : prefix);
        };
    if (f) {
        out.push(prefix);
    }
    for (i = 1, c, d; i < s.length; i++) {
        c = s.charAt(i);
        if (f) {
            d = s.charCodeAt(i);
            prefix = d < 256 ? c : dict[d] || (prefix + curChar);
            out.push(prefix);
            curChar = prefix.charAt(0);
            dict[idx++] = oldPrefix + curChar;
            oldPrefix = prefix;
        } else {
            if (dict.hasOwnProperty(prefix + c)) {
                prefix += c;
            } else {
                g();
                dict[prefix + c] = idx++;
                prefix = c;
            }
        }
    }
    if (!f) g();
    return out.join('');
}



//压缩时:xcode('watchwatch....');

//解压时:xcode('compressed string',true);//第二个参数传true表示解压,反之为压缩

大段文本的多个关键字高亮

前几天看到有人提在网页中实时高亮关键字,大约6万多个字中高亮600个关键字,用户可以随时修改并及时高亮,也就是onkeyup时做高亮,说用正则在IE下效率不理想

想了下自已给了一个实现方案:
比如这段文本是:"这是一大段文本,一大段文本哦"
关键字是:["这是","大段文本","哦"]
首先找出最长的关键字,并把这些关键字弄成map,如:

var keys = ['这是', '这里是', '文本', '一'];

var prepareKeys = function() {
    if (!prepareKeys.$map) {
        var map = {};
        var maxLength = 0;
        for (var i = 0; i < keys.length; i++) {
            map[keys[i]] = 1;
            maxLength = Math.max(keys[i].length, maxLength);
        }
        prepareKeys.$map = {
            map: map,
            cache: {},
            length: maxLength
        }
    }
    return prepareKeys.$map;
}

接下来在大段文本中,从开始位置截取按最长关键字的长度截取一段

则截取后的字符串是:"这是一大",那么剩下的字符串为: "段文本,一大段文本哦"

接下来比较 "这是一大" 是否为关键字,如果是关键字,则着色并继续按上述规则截取剩余的字符串

如果"这是一大"不是关键字,则从后面截掉一个字,并把这个字追加到剩余的字符串开始位置

则"这是一大"变成"这是一" 剩余字符串为:"大段文本,一大段文本哦"

然后再比较"这是一"是否为关键字,直到为空

然后再从剩余的字符串中按上述规则继续截取

最终代码如下

var input = '这是一大段文本,这是一大段文本';
var keys = ['这是', '这里是', '文本', '一'];

var prepareKeys = function() {
    if (!prepareKeys.$map) {
        var map = {};
        var maxLength = 0;
        for (var i = 0; i < keys.length; i++) {
            map[keys[i]] = 1;
            maxLength = Math.max(keys[i].length, maxLength);
        }
        prepareKeys.$map = {
            map: map,
            cache: {},
            length: maxLength
        }
    }
    return prepareKeys.$map;
}

var colorKeyword = function(str) {
    var info = prepareKeys();
    var output = [];
    while (str) {
        var sub = str.substring(0, info.length);
        var oSub = sub;
        if (info.cache[sub]) {
            console.log('cache:', sub);
            output.push(str.charAt(0));
            str = str.substring(1);
        } else {
            str = str.substring(info.length);
            while (!info.map[sub] && sub) {
                str = sub.charAt(sub.length - 1) + str;
                sub = sub.slice(0, -1);
            }
            if (sub) {
                output.push('<', sub, '>');
            } else {
                info.cache[oSub] = 1;
                output.push(str.charAt(0));
                str = str.substring(1);
            }
        }
    }
    return output.join('');
}
colorKeyword(input);

用优盘做系统

引导磁盘应具有的条件
1 是主要分区
2 处于激活状态
3 拥有启动文件

一:激活u盘

准备优盘一个 USBoot软件。

打开USBoot软件,会出相应的提示,把u盘上的数据先备份,清空u盘。

然后在软件列出的列表中选中u盘盘符

然后在下面的“点此选择工作模式”选择“引导处理”

点右上角的“开始”,改变u盘的结构,使u盘具备做引导磁盘的条件

然后把需要装机的系统也放在u盘上

说明:u盘最好先使用FAT格式格式化一下

二:向u盘装引导使用

使用ghost32.exe把bootu.gho文件装到u盘上,这样u盘就拥有一个小型的界面操作系统,可以在该系统内方便的为硬盘安装系统

在向u盘写入bootu.gho时应选择disk from image

三:使用u盘装系统

设置bios从u盘启动。选择第一项进入。

使用win pm对要装系统的磁盘进行

在主磁盘上点右键 创建 如果已经分过区的可以点“删除”

先分区 再设置为要装系统的盘符为活动的

清除MBR等操作后把u盘上的系统装到磁盘上

极致的性能

加载性能

基础设施文件应保持小巧,magix做为展示页view加载器,压缩后6kb、gzip后3kb。做为后台管理SPA框架,压缩后12kb,gzip后6kb

通用组件只提供核心功能,最多支持到觉功能,其它个性功能在各个项目中进行定制

当需要使用社区类库或组件时,除基础类库外,我建议只把用到的功能拿过来,比如underscore,只用了数组操作?把数组操作拿过来。有空多读读源码,尝试把这些优秀的类库再做一些拆分,你会发现你常用的功能也不过就那几个,其它很多功能根本用不到。

运算性能

循环

通读过妈妈下面很多项目的代码,循环这块的问题大家应该很少注意下,这里举例说明

_.each(campaignModelData.mediaType, function(item) {
  _.each(mediaTypeList, function(_item) {
    if (_item.id == item) {
      _item.checked = true
    }
  })
})

_.each(campaignModelData.terminalType, function(item) {
  _.each(terminalTypeList, function(_item) {
    if (_item.id == item) {
      _item.checked = true
    }
  })
})

_.each(campaignModelData.shopId, function(item) {
  _.each(shopIds, function(_item) {
    if (_item.id == item) {
      _item.checked = true
    }
  })
})

且不论_.each vs for的性能,看这3对嵌套的each,我们只分析第1对的each,后面2个同理

第1对就是如果mediaTypeList数组元素在mediaType元素中,则标识checkedtrue

假设medaiTypeList的长度为10,medaiType长度也为10
则第1对each跑完需要100次

如果我们对代码改造一下成:

var map={};
_.each(campaignModelData.mediaType, function(item) {
    map[item]=1;
});
_.each(mediaTypeList, function(_item) {
    if (map[_item.id] == 1) {
      _item.checked = true
    }
})

减少嵌套,则这时候

假设medaiTypeList的长度为10,medaiType长度也为10
则each跑完需要20次

我们可以明显减少CPU的计算。

再比如

//获得不热门的定向数据,并提示
_.each(data.list, function(item) {
    var videos = item.unSellVideoTheme
    var videoArr = []
    var videoStr = ''
    var length = 0
    _.each(videos, function(video) {
        if (video.unSellVideoTags.length) {
            length++
            _.each(video.unSellVideoTags, function(tag) {
                _.each(tag, function(name, id) {
                    videoArr.push(name)
                })
            })
        }

    })
})

我们可以看到是4个each嵌套,同样,如果每个数组有10个元素,则跑完这些循环需要10000次

再如钻展的这个页面http://gitlab.alibaba-inc.com/mm/zuanshi/blob/master/app/views/crab/premium_batch_cpc.js#L65

_.each(result, function(algoItem) {
    _.each(data.campaignTransList, function(item) {
        _.each(item.targetList, function(targetItem) {
            if (targetItem.id == algoItem.id) {
                targetItem.suggestPrice = algoItem.bidPrice
            }
        })
    })
})

像这样的代码在很多项目中都有,而事实上项目中数组的数据要大于我举例中的10个,所以真实循环中可能几千、几万、几十万次都是有可能的。

有些循环是可以通过前面类似打平,不去嵌套的方式实现,而有些是很难这样做的,这时候可能需要我们变换或重新设计数据结构,从而减少数据循环查找的可能。

像东风项目中菜单项的处理

case 2 :
    menus = [
       ms.source._cs([
           ms.media_2._cs([
               ms.media,
               ms.adzone
           ])
       ])
    ];
    break;

与其根据权限动态的拼凑出菜单,不如在设计菜单时这样设计

var ms = {
    "promotion" : { name : "推广管理" , url : "/activity/index",children:['activity'],permission:'1'},
    "activity" : {name:"活动管理" , url : "/activity/index", icon: "&#xe632;"}
]

当然这块我只是大概看了下,也许并不能完全满足需求。我们可以通过设计合理的数据结构,减少一些循环的处理。

这块的初步打算是,做一个提交前的检查工具,对于这种多层循环嵌套的,提交前给出提醒,尽量减少嵌套

html结构方案

左侧菜单

css选择器

类似这样的css选择器 .form-div .line-detail .line-resolution .dropdown-toggle 在我们项目中还是比较常见的,我们这之所以嵌套这么多就是把样式限定在特定的范围内,但这样做也给浏览器解析带来一定的压力。

样式问题我们可以通过 css模块 类似这样的方案来解决,让工具帮我们处理。

样式可以出一个选择器检查工具,避免嵌套过深的选择器

离线计算

把线上一些固定计算转移到线下来做。

  1. 模板字符串转换成函数
  2. 子模板分析
  3. 模板字符串分析
  4. css类名转换

其它-转换思路

如果我们做一个拖动排序或拖动到的功能,像邮件可以从收件箱拖到垃圾箱,常见的方案都是计算目标节点的位置与大小,然后再比较鼠标的位置。这是一个非常通用的,也很少有bug的方案,其它的也有监听目标节点mouseenter事件的,但是或多或少都有一些问题。监听drag事件,要看浏览器的支持情况

对于这个场景,其实有一个更高效的document.elementFromPoint方法,在拖动时检测鼠标下的节点是非常方便的。无论节点多少都不会引起性能问题,并不随节点的增多导致查找时的性能下降

同样,magix在设计DOM事件监听时,1个view有click,还是1000个view有click,查找性能是一样的,即使这些view是嵌套存在的。magix并不会把这些事件处理函数放到一个数组中去处理,因为这样会随着事件处理函数的增加而导致调用时性能下降。magix针对自身的特点,在事件这块重新设计:全局一个统一处理函数,不管事件类型,也不管有多少个view有什么样的事件,同类型的事件在全局只会向body上绑定一次,然后由全局处理函数统一处理。magix中的事件代理

入职印象深刻的另一件是 水鱼 对搜索关键字的查询优化,关键字一万多个一次发送到前端,然后前端根据用户的输入过滤出匹配的项。按正常思路我们在用户输入后对整个关键字列表进行查询,然后把匹配的显示出来。每次输入都要查询一万次,在用户连续输入的情况下就无法及时的给出反馈。

当时 水鱼 给出的实现的方案是,拿到关键字列表后,做一个字典树,当用户输入变化时,沿着字典树向下查找,每次并不会遍历一万多次,即使用户在快速连续输入的情况下也能及时响应。

现在的硬件很好,速度很快,向上面我提的这些点不去改进项目也跑的很好。而有一些点我们直接去测试时,几乎没什么差别,比如循环100次和循环10万次,也就1ms的差别。那么我们是否应该去优化?

性能的问题是一个习惯的问题,我们平时如果看到了更优的解法,认可这种解法,就应该改变自己原有的习惯,然后把应用这种更优解法变成你的习惯。

不管当前硬件多强大,一台计算机的能力总是有限的,而你也无法预知你正在开发的应用将来会变得多庞大,也不会知道什么时间会出现性能瓶颈。性能的事情也是点滴的事情,你的页面不会因为多了1万次循环变得卡顿,也不会因为你减少了1万次循环变得异常流畅。一旦你的页面出现了卡顿,想再回头优化到流畅通常是很难的。

先做功能,回头再优化性能是不对的,性能的事情要在写代码前就已经解决的。

让原本很快、很流畅的应用变得更快更流畅不好么?

浏览器会内置类react框架

DOM操作

Prototype.js到风靡全球的jQuery.js,都是在解决浏览器间DOM操作的差异化问题,同时也提供了简洁友好的API,但是随着标准的不断的推进,现在浏览器间的差异化可以说已经没有了,像Github就宣布了弃用jQuery.js,直接使用浏览器提供的DOM操作更新界面。

尽管浏览器提供的DOM操作API有时候看上去比较啰嗦,但是只要所有浏览器实现一致,前端就不需再使用一层封装来间接操作DOM,只需要学习标准化的API即可

网络请求

IEActiveXObjectXMLHttpRequest Level1再到XMLHttpRequest Level2,然后fetch出现一统网络请求。

在我们平常的开发中,可以直接使用fetch进行请求,无需再引入其它的网络请求库。不过目前fetch提供的API不够丰富,可能在使用时还要简单封装

模块化

从最早的对象模块命名空间,到amd,cmd等模块化工具require.js,sea.js等,再到es module,目前chrome中已经可以直接使用,并且动态的import也已经支持,从此可以告别那些第三方的模块加载器,学习并使用标准的es module即可

功能点

比如以往我们要实现平滑滚动,我们要用setTimeoutsetInterval先实现一下基础的动画引擎,然后再实现一下相应的tween缓动算法,然后再应用到我们的滚动上。现在浏览器已经支持通过css给要滚动的节点添加scroll-behavior: smooth,然后再操作相应的scrollTopscrollLeft即可实现相应的平滑滚动,省去了原来大量的代码或引用第三方类库的事情

再比如某个节点滚动到或即将滚动到可视区域做一些事情(像瀑布流等),以往像平滑滚动一样,我们要监听滚动事件,我们要计算节点的位置信息等一大堆事情要做,现在有IntersectionObserver,我们完成类似的功能只需要几行代码即可

对于图片多的网站,前端经常使用的图片懒加载,现在也有了原生支持,给图片加上<img loading="lazy"/>即可,不但省去了大量的javascript,也提升了易用性

web components

通过前面的一些基础点,我们可以看到浏览器越来越多的把一些常用功能内置进去,可以预见未来也会更多的把常用功能内置进去。

内置的功能不但方便开发人员,同时在内存管理上,性能上,资源使用上都要远远优于javascript的实现

长远看,现在前端开发的模式:界面管理+数据管理=应用。界面管理也很有可能被内置到浏览器里,简单理解就是把页面组件化的功能内置进去,比如内置一个react。开发人员只需要管理好自己的业务数据即可。

目前这个内置的界面管理浏览器提供的是web components,但是它在使用起来仍然不够方便,不过随着时间的发展,也许一年半载之后浏览器发力web compoents,把它打造的更顺手易用也说不定。

浏览器的未来

从前面的一些例子我们可以看到,浏览器也在不断的吸收好的开发思路和方式,同时开放更基础,更易用的API给到开发人员,这是一个互相辅助的过程。

一但某些库或框架成为事实上的标准,那为什么不推进它把它写进标准,然后让浏览器实现呢?比如jQuery.js就是成功的案例,比如图片懒加载也是很好的说明,也许浏览器会很快内置lodash呢?

如果浏览器没能发展好web components,如果react发展成熟稳定,浏览器或许就直接内置了,让我们只关注业务即可。

关于使用JS获取Html标签的内容时应注意的事项

原来我有一个获取任意元素内容的方法如下:

function getValue(id){
        id=typeof(id)=='string'?document.getElementById(id):id;
        return id.value||id.innerHTML;
}

我这样使用id.value || id.innerHTML获取元素的内容,只是想用最少的代码来完成。这段代码在大部分时候都是正常的,但今天我在获取Html标签li内容的时候即始终返回-1。见下面的代码:

<ul id="LiOwner">
    <li id="Test1">adfadsf</li>
</ul>

在使用getValue('LiOwner')的时候结果是正确的。
但使用getvalue('Test1')结果是-1(在firefox下有该情况,IE良好,其它浏览器未试)

郁闷了~!。到w3cshool上看了一下(这个链接:http://www.w3school.com.cn/tags/tag_li.asp)

对li的解释如下:

在 HTML 4.01 中,li 元素的 "type" 和 "value" 属性是不被赞成使用的。

换句话说li在firefox下默认有type属性。

使用

var o=document.getElementById('Test1');
for(var v in o)document.write(v+':'+o[v]);

看了一下。firefox下果然有type属性。

汉字转拼音,支持20870个汉字,包含完整的多音字

(function() {
    window.Utils = {};
    var C = Utils;
    var group = /[\da-r]{3}/g,
        base = 19968,
        middle = (40896 - base) / 2;
    var EMPTY = '';
    var COMA = ',';
    var chars = (function() {
        var a = [];
        for (var i = 33; i < 127; i++) {
            if (i != 34 && i != 92 && i != 45) {
                a.push(String.fromCharCode(i));
            }
        }
        return a.join(EMPTY);
    }());
    var SDB = {
        "a": {
            "yi": "!]#R$!$q(3(p)[*2*g+6+d.C.q0[0w1L2<717l8B8E9?:8;V;[;e;{<)<+<S<]=9>.>4??@~A`BbC:CGC^CiDMDjDkF!H/H;JaL?M.M2MoNCN|OgO|P$P)PBPyQ~R%R.S.T;T<TBTqT|UQUXU}V[WCXgYCYDY_YdYuZ9Zs];]j]p]q^.^@^S^w^x_,_T`H`J`ga)a8aQb9budJddgoh9hqi2itj&jEjRj]jzk>k^l$l<mLmdnDoEoMoQoop3p5pWp`qSr.u'uLv]wIxXy_y~{z}`~r-$=-$X-$Y-%!-%0-%j-&^-&s-'t-(<-)2-*n-+6-+f-/M-/N-0.-2|-3u-4b-4c-4m-5E-5N-5Z-5l-6&-6+-7*-70-73-8F-8R-8g-:*-:5",
            "ding": "!2%%&_&x'u=:=h@NC`H?LQNkQ3Xo^Gn?osrUsNvAwKxKy9-!T-$6-$v-%O-&b-(+-9%-9(",
            "zheng": "!S#(#D/]031$456+=L?OIzYM[']I^g_.eUl}m~qJsHulwuxU-!?-,d-3D",
            "kao": "<dLWr5x7-!J-,7-/Y-/s-2'",
            "qiao": "#+$4&.&1'7'Y'z($(),B,{0c7y8<:H<8<YE{F0GdKYMCZP]Y_8_zd.d/d{e5fGfHfUmKmrmvp#t>t?uJv$vMyE|R}a-!}-#&-#8-#L-#b-$Q-%?-+q-,6-,8",
            "yu": "#V$l%S&9&I('(7(=)))m*#*$*B+2+F+v,0,b,i.W0.1F232L2a3(384>6P8n;';i;y<1>(>)>]@iB<B?BDBEC'C*CoCpELE^HIHJHTIpJIJ`KXL&L1LxMbMqNXNqPdPsQ<RFT?U(URV7WnX:Z?ZT[6[H]!]~_7_J_``Za#eXg;h#hVhuiyj!j#k9kDkMl#lClUlmmUnFoAp(pzqnrSsSt0vJwszp{_|N}!}$}I}t~(~,~.~w-$D-$]-%^-&j-';-'k-(3-(H-(v-*1-*Z-+#-+d-+{-.1-.2-.<-.K-.[-.e-/d-0=-0P-1:-1m-39-3`-3b-3e-41-5e-5}-6/-6;-6p-7:-7Z-:(-:2-:F",
            "qi": "!8%&%>&X&m&s'2'X'd'f(9(c(i(j)@)l+'+M.).+1y1{2=3K4c6&6'6)606<6B6`9`9{:a<g>`?`AgCLCuD%D2F2GyH&H1I;K~LkLuM&MYO0O3O9P8PbPcQqR5S2SCU0U~V%XYY&Z}[G^P`7cUc}dEeNgOj$j)l?m:n4p,sOuRv.y'{/|i}1~P-$B-%Y-)|-)}-*K-+G-+H-,[email protected]/|-0y-2D-2c-4W-4`-4h-7a-7p-9c-9i",
            "shang": ")Y6V9cJvR8UqXJXa])asbQc,s,uSvz-#+-.;",
            "xia": "#Y#w&,&;'''I)1.u/j7=:[<'B[ByCtL'NmNyQOR([0`(cLh[iRkVt/t_u4uezFzM|W|{~d-&)-*4-.}-0a-5;-8S",
            "han": "#,.m/h:l<P>MFrGXJqNrOUPCPqPrQ|]@`+`2h1lBlZnXp*r;rWrkz9{4{B}x-#c-#y-$;-$l-$y-%Q-%n-(i-(x-)i-/!-3*-5B-9V",
            "wan": "#=$0&o.]0F4@5X5b6*628u9p<K?e?h@IChFqG!G7H2HHJzL=O5Q'RQ`;a:b<bGeHh&h)rMr^s'slu!-$E-%V",
            "mo": "!`#$#&#y$%%P'e(T*N3v5$517`8R=6?XA5E6FZF~JLM;MgP+RTRcU6]'](_j`s`x`y`za+qkuDyR|G-!e-'g-($-(U-*R-+k-,(-.U-.k-.{-8/-80-8K-8L",
            "zhang": "#~(#.:2o3N>k@,JhR`b$b`knmtujz'z0}<-#+-'I-*Q-16-7m",
            "san": "3T3q3w3x7~uJuwzA-'n-([-,s",
            "ji": "#r%''l'y)3)d)o*Z+'+9+G+M+T+Z+^+g+x._.c/R090d1S1W2;43484J4R5C5w6)6C6`7f7s878H8t8w9J9X9Z9{;8;<;B;C=(=2>6?YA$B+CHD0D8DbE:EQF2I*I|JEJnKKL)L:LkLzMdN'N5N:NiQ6QyRrUWVcVnWPWQWtX6XEXYXuY(ZAZ|[/]O]e^F^J^U^~`)b#b0c*ckc}dee!e$e9e>eyf+fXfrg)hFhriMjZlrqmr)sRt%uov3vevw|@};}N}g~!~+~F~{-!&-!u-#N-$%-&a-'u-(,-*x-+]-,W-.?-.V-._-.d-.g-/+-0$-0H-1%-1/-10-1^-1o-2/-2@-3'-4)-4o-5>-5H-5U-6,-6J-7/-7P-9e-9g-9h-9i-9j-:l",
            "bu": "0$192,FKJgT=UYZ^e+hhjmm8mFoGpGp}sjw]w{-'7-'E-/m-3#-4.-6=",
            "fou": "4I:L:O:Q~1-3:",
            "mian": "!G!d#4$U$W$]3Y5X6A6_6o9g9w@qB/CkG!H_Q;-!L-!M-!P-/_-7y-7z-8'-8,-8q-8r",
            "gai": "):5=5LD,ErI!J1Z'_/`TaYaac!lnpcw[|O}1",
            "chou": "!+#n$N+0/y0}2:4e5/6#9jB*B.GNLfUmZ+^3^5_4e%e4fWkan]nbo.o6oU}u~$~*-.X-/>",
            "zhuan": "%H'S'V.K0k1B1H1r2?7Z<r@RA7IDRsVk[J]Tb3b<c8gThai'mp-%+-%u-'p-(]-14",
            "qie": "%>+7+f,8.#.|0K0p2O>#DNE1P.ccd]eMlpt8y>-0&",
            "ju": "!Z$L$w%R*W,c,l/e1~3&3J8#:t=#=`=k@FBGC0DlD}FeGAIaIkJbMrN[OVP`RDTlU|W>Y`[$^Z`Ua*ccc{dWd]dae#e@eFeff8fSg*g<guh~l'lXmIoOq(rps%vXw_x|y;zb|m}o-#/-#:-&4-&Q-)<-)?-)d-*z-+0-/.-/:-3[-48-4S-4k-5.-9H-9K-9x-:@",
            "pi": "#M%D'C(5(6)L*F*K+;.n1C4M8}:y;/;2;A<,<{>a@'@2@KA%C|DQO+O]O^PvR!REScU'UfZw]m`l`na'i[l_m;p<pYpyqCqyr*s1s;trx4{8|*|=|p}F-!!-#,-)@-,H-.p-/#-/3-2#-3>-4F-6'-63-91",
            "shi": "!E!Q!e#?$p%$&+'$([(](q*^.&/5/n0[1w204z<gBNBQG)I:ISIUJ3NlN{Q>QQR9VYW2W@W^X2XNYxY{ZI[:[<[v]X^l^{^}_p`DaDbmgqi8ixjdk!kNkpl(lkntoMo^ocoeofp5ppq%q&q*q4qbr=t9x/-&^-&_-&}-'<-'@-(*-(8-)!-)H-+,-/<-0?-0d-0o-0p-2:-2O-3+-38-57-6M-9C-9E",
            "qiu": "*6*7+a0r3k4D5]6j>7CaCeF`HEJXMhNgNjONP;QMQ_RfSWUUX?XUXqXrajc$d'jpjskXl][email protected]:r?-#5-#6-$8-/'-/k-0W-0X-1,-2Z-4v-7&-9U-:Y-:Z-:]",
            "bing": "!n)F*4+/,>.75@DsOcZ7l`puqar||>-!:-!q-#,-#G-''-'C-(D-/O",
            "ye": "$>$E(0,a6g=;@?HfSb[]_]lUlfn(oip=rmtDtTtevTx?-!O-!R-$5-%N-'F-'e-(T-*o-4Y-61",
            "cong": "$'&Y1>8==g=l=p=vDIE=I2JUK0LsRZZk]$a}a~sKtBuKu_-*)-*V-+Y",
            "dong": "&&.r0b5D?7?C@JD|G;I#KwQ([&jV~^-)T-/=-0)-4g-5/-6T-9,",
            "si": "'?(b)^)g)p*+.</#40415O6i8l9~;.<|<}>+>0KxL+NLP7PiQnReS&W_`tp1pvp{qTqnr8r`tIuzyB-&6-&R-&^-&c-&s-&{-(:-)L-)q-*8-+.-0.-5j-6`-9N-:o",
            "cheng": "#0$,$P&W*O*[*w+A+{,O,v/l5[7#:`?}FQOoS(UKZV_#cHcJk#m$nhrxtkuxv@vWx=xB|2-!A-$h-'w-)o-*>-+B-/u",
            "diu": "r2xL-&&",
            "liang": "3A3D3{6K@0CRF{Q%Up[,_Oe1h!h2hCiBiHojss-!=-)h-.J-.O",
            "you": "(r)O*I7o8W;L;f=5=M>VDKFoFsFwG/KaOOOSPSQLY8ZN_;`qh%hMjWjnk6kPlYmEn3n>ncodp~r3x&x<-),-.y-/1-1p-1z-7N-8P-9D",
            "yan": "##%F%L&%&F&T&v(Z,j/u1?2$5t7V;!;h?<@@AsCVCYCZD3FmGpH.JlN_PVQAT$UxV9WUX/XkXmXnY?Z3[U^1^C^E_e_~`B`C`RbDbPc;g/g7kIm#mNmsn5nHnsnyoPoVo`x+z7zkzmzn{A{`{e|}}2}b-%'-%,-%B-%v-'0-(#-)~-*$-*F-*j-*s-+C-.4-.H-.Y-0V-3$-3*-3B-3n-5#-5G-5u-7K-7r-8T-8W-8_-8`-8a-8d-8j-9L-9Q-9w-:1-:N",
            "sang": "'EVNts-%2-%{",
            "gun": "#<&#'U6F6z9dJ>JpTFTwUu]4h<iF-/2-/g-2<",
            "jiu": "+E,*42464]8mB:BCBHBMH7cQnGz){Z-#}-#~-,l-./-01-3!-5w-6I-79-7c-:$",
            "ge": "&!/30*4?8r>:?B@}AbB3BwECHxJ1NwOrP'U9UPXM[X[hhLhmq`tetlu.xSyUzTzU{W}4-!S-!s-#F-#`-#j-%f-(A-*%-+t-.3-/K-/U-1u-3T-3z-6g",
            "ya": "#B%C&{'I*{,a.g=UDEKqO;T1WEWGY.^[g=i!j4lUp=s=v7x;}f-3C-3c-4U-6O-6V-9o-:;",
            "pan": "!&!>!?!H!o'L'x2A76=F>R?$AIH<IrRoT{WBY[d[e{f0rvtpw=zx-#E-$J-4D",
            "zhong": "#%(n*8+>+m/V2T4{6b99>j@`BnEkK*O:OBP^R2RKSzTKTNTO[@e^f>ohparHtQv5wbyF-3_-9@",
            "jie": "#S%@&{(.*d+=.G0e4J5,599D;k=(@/CfD,G#G`J[LzOFP&P:PTQ=SKSQSqT/TITPTlU4U7UPVQXOXSX}Z%ZWZh]/^K^~_5ckdve=j^qGtNtXz,|1}.-!m-!u-$U-%c-&v-+i-.l-/@-2&-4{-5$",
            "feng": "!@%N'40m5v7R:3C$FdHnN.PFSaWI[R^c`?b.c5k'n+n;r[u5uXxs-!$-!4-&%-&J-&L-(w-3(-3,-3F-8)",
            "guan": "!'$b$j$k(W)B,Y/f0E6:9&:]:gBVFqIEWSW{X+X.a?bifMh?kmsUu>w7zOzS{,{2}{-'K-(N-0q-1N-1j-2e-2z-6D-7A",
            "kuang": "!Y!z$Y%1%r%w(G+}/O/z5'538V8vZ<ZG^y_=aNbpgHgRgXg`j+lHlhn/qUrevy-4>-8>",
            "chuan": ",40jA7BYB`BhBxEvale[hIkJp%wQ-5+",
            "chan": "&6'W)K)q1N6D7$8*8A8[8_:6;xCODJIHKQQ2RGR_R{S1UeW!W`X3ZMZy]B^+^7_N_bfbi|n2n6o@rTr]uWw3xYz%ze{7{g-#Q-%D-%~-(%-(S-+Z",
            "lin": "$B&['t0:393O5{8!<WA?B%GsKEMOaWb{fEf]fgfxhlh}iVk{lgn$utzg|9}C~[-*a-1G-2t-7_-7n",
            "zhuo": "#'&Q)a+l,%,V,]102E2`8?:J;&=NE.HtJ:L|SJSsZx[+]6_Fd!nArfvLvOy|-4J-5d-:x",
            "zhu": "!a$6$h%^%v'f)!)/*h,@.4.S.T.[.w/P/o0]0n141=1a4n4q5.9+:s;W<EBrD/DVDpE_EmFYHtJQKZMMO`O{QTS>S]SrU;V<YLYoZ;[S_$_B`[aCbhdVdjfRggjMjrk1ljq6q{r}vbwExIx`|x-&r-(~-)=-)]-+2-/H-0E-11-3s-6(-7T-7V-8x",
            "ba": "%#.a3#:y;2;N<z>sD5E4GTO$WNYk`LdDdNgjozp?wr~~-!a-&.-.D-.`-/&-/0-1t-1v-1}-9=",
            "dan": "!K%$%5)r,S0N1h4V8A=A=B=H=~>q@9ATAVH*JDOkPUTLV?VoXGX~ZK_'a|bBc3f{mHn&nKn~~t-$I-'G-'s-)*-)a-,C-3Z-8H-8b-8i",
            "wei": "#o$M%}&0'#'D'M6/6p6r7+8y9f;6>n@gC+D!DOE+FCGBH)I&I(I4INJ]K$KJL7LdMDN0PwQ$QDQHR?T3T6V`WkX$Z)[#[^^*^4_I_^e;fefig@hbj>k<k[m}nvs~t4uGzz{G}&}'}7}Y~n-!#-#Z-#a-#i-#q-#v-#z-$T-&7-'J-'X-'z-+a-+b-+c-.P-/,-/F-/P-0N-0O-2(-2W-2p",
            "jing": "#C*?*u,2.8.9.A.E.P.R042v3F3Q5(5q6!9@=_>g?:?k@<E;EtExFiG8HlS/Z`]ge(jTjwrhuYyi|+-!=-!@-!C-!D-!F-$N-$m-%b-*m-03-2M-4:-4a-4d-7e-7o-9I",
            "li": "!!!0#A#E%7%_%m%q'|(K(L(Q(^)u)y*%*H,&.$.J.{/c1.1:2Z3$303G3b4)5}7T8Q8g:7;4@*C%DPDbEEF%FDFWF[GUI[I`JFKIM1MKN4OWOnP#PNPlQaR[S*S:STSVS_ULU_VWXhYY]&^,`9`}cPdbf`hzh{i5jDk+l7l;m6n=oBoNogokqAqururzs3tludvuxjyU}V}W}X~&~8-!+-!5-*}-+A-,^-.3-/p-/v-07-1W-1b-1k-26-29-2x-2~-3Q-4X-5I-6F-6l-7f-7k-8A-8Z",
            "pie": "$2DmW]u~",
            "fu": "%8%[(u(v)U)j*k*o+:.'/$///_0$0=1j3C3d4a4j4u5B5k5p6q7B8L939<:0:o:}<&>N?#@!@D@E@nA3C!CWC}D*DFE'E,E]EpFFF|GKHKHjJXKsNSODOGOXOwPIPMQEQIQWTETsTvU.V(V6ViW+WKWMXpYS[C^H`Va4a{b4bXc(c7cRd=dZegh*hPhRiAiLlIm(m*mmnQowo|pFq<q@t#t5{s{t|?-#]-#x-$`-&(-&.-(n-)F-+/-,P-.5-/)-/8-/X-0^-1|-2[-2}-3%-34-3N-4H-4}-7x-7{-8#-8*-8o-8p",
            "nai": "<p<q?L@=CcH4R'VHj[o}sk-9'",
            "wu": "$A%*&l)+,D,o0a2tAMB]D#D<EPFSKvMVPLQzS#Z>ZYZZ]U_6_9d9fYj6j~lWm)mep)rQrbrctvwkxc{y|U}6~?~C~`~m-!Z-*'-+R-/j-0j-3i-4/-4@-5,-5f-6j-6s-7)-9G-9W-9X",
            "tuo": "%U%V&z0L2J4v?{@$F_H6MUTbT~Y'Yc^QdHdQnVq+r`x1{{|;|<-&d-(.-(z-({-)1-)J-)K-*:-*e-*p-+$-+3-.b-/%-/[-0b-3O-4,-6_-8}-9$-9?",
            "zhe": "#'%+%E'P2f2|<f=VHtJ~NoP4PKR9RRRSU%VXW<Yq]*]:^%^0_ucKe`h(h0hei@iUj:j{kurAtMy!-({-/f-5W-75",
            "ma": "#X%3'8(e)h;0GsK?N}R+RTRUkku/z2-(u-)N-+!-+9-,r-0n-5P-8.-80",
            "me": "-8/-80",
            "yao": "!T$R'T(g,3,:,=,F,I,J,e,f/C0^4<7o8Q8s<a>_@eB>CADvFAI0I>J:L]M:M~TgWHWfY/Ya[|[}^6_ngmi6k`kll*l9r!tdwhxRzv}!-!j-%=-&9-&T-'(-'=-*&-0u-1I-2f-3;-3]-5F-5Y-7+-9T-:%",
            "zhi": "!7!t$s%=(J(i(k(s(y)2)I)Z*2*>*A*T*^*c+(+)+J+Y,G/k4Q4b5T5W5s6~7^7|9(98;(<0=E=Q=b=}>L>|?+?QA<AJB1B2B5B6CzD$D?E8GeM7N/O3P1P]R@RhTQTTTxTyU{W.WgXCX[XcY9ZB^l`@`A`haAb!b=bbbwdAdYdueTeWf,f_fag6glg}i1i:jDlqm6neoyqrr=r_vsxAy3|)|Z}R}[}j-)!-))-)Q-*?-*L-*Y-+O-0:-31-3S-3m-5+-5^-6a-8m-8y",
            "zha": "!l%Q0>4^4g=0D{OPOZX]Yb[(]G]W^ng=o;t*xHzI{N~J-&t-/9-/a-1{-22-9]-9`",
            "hu": "(1(~.j0Z1M3!3^545r757G?0AMCtCxD<E$GxI+K%K;NGNHNPNWQ^R)T2X`Xd]<]x^^``gVi3mqo)snt+tK}Z}q~B-$4-$k-'O-,j-.s-0<-0c-1`-2v-32-4?-4x-5)-52-5?-65-6n-7!-7?",
            "fa": "#k%O/'/N:q;*;3EeKkLvo1oKstzV{V-,F-,J",
            "le": "%f.U1_>5C_{u-$*-'1-(A-1!-1d-2i",
            "yue": "$S%!(a){0^0|242S2_373H4<8sAlM{O,O.ZaZc_>cid2dCdFfZgApDqBw2whw}zczd{[-,V-6:-6B-8Y-:^-:m",
            "lao": "&)'n,71s3<5>9M<b<c=&=3F'HYP3Rvg.g4hin`oDr(v/x8xa-%8-,9-/W",
            "yin": "&#&j'a)Q*a,^/B2{5G6{7V?3DJEGEcF=FHIRK4K8MuO2RLRzU=Y$Y*Y2Zu[M^9cXczh'monipNp]qer/xFx^z{{||/|l|w|~}0}@}Q~W~f~p-!b-!r-$&-$2-&m-&q-(6-)^-+:-/I-5h-9p-:!-:?-:E",
            "ping": "%b&'.H0W1Q:T=f>~CXE%F$H(JWMaOQP%Yg^jgrh>mAqa-$^-(w-/(-1w",
            "pang": "!o'A1+=/>R?$?=A/B|QmWsd@jf~6~|-0k-2g-:K-:M",
            "guai": "0,;%",
            "sheng": "!D!^...t7*7q859e=[=x?*E(KM]^aMb1q2t2|#|Y|u-4_-9B",
            "hao": "*:.,25<x=ZEMJ$L3L5LWLtNYO<SG[0]z`Y`ym,mhu#y]-%>-%|-0i",
            "mie": "!`(D1G1dJxL>SNS~W]vt-1e-3M",
            "nie": "1&294(4,=G=|B)B0E!GDMlSX^=e)e?eAezforAs$sJu*vfw9wByVyY{&|c}(-%L-%x-:#",
            "xi": "!>#6$3$d%/&(&g'J's(!)P)n*l+7,,,n313z434i5j6H7?7W81878g979U;V;n<2<5<6>c>d@>A6BABBB}FUG]HeI9IbIwJ+JVKzL2NdPjQoQqRYRqSiT!U)UzW9WFWiWlX7XfXjXlZH[K[m]5]F_@`.`/`W`_a(cCcGcfcwesf)fulGlplwm&m4m_n:oIokp2p7pbqLqMqvsYu+ufv&w6wSxJy,z[{5{b}9}?}P}U~#~2~q-!%-&?-'2-'`-'r-(1-(C-*C-*O-*{-.)-/x-0_-1+-1J-2X-2q-46-6*-8I-9O",
            "xiang": "!;)*+50U5Q6Y8b9u:U;E;J<4APC{HGHvL<N~RbS4T.VgVsZ(_0`PdqmGmYmZmfqiq|v(w4z&zXzt|H-$3-$9-%R-&g-'+-'{-(&-(?-(b-*w-+_-/C-/~-1<-1L-1g-23-7g",
            "shu": "*V*x.0.D2B4#4K5%5^6s9/;,@[BPF(GuIBIeK7LUL`MLNePDShT*UHW'W0`=bOc+e%e0gIhOiOjQmSqIs_u[|I}!~Y-/A-1Z-1a-4G-4p-8@-98-99-:e",
            "dou": "$#,[,}1E@#FEKCOI_E`5jym%mMnMpCrIwpzH{.{~|]-'9-(F-.%-.&-.*-.,-..",
            "nang": "Sd-(&-()-(^-9b",
            "jia": "+L/23l=!?)?u@jF+FuI.P5P>TaU4UI`]a$a]bxdRjGl{m/q#qOrXu,x$x>y`-$a-$e-%c-%d-)B-+5-3J-3q-4(-7i",
            "mao": "!M#i$i*:/66e:u<eDDE/E2E3HVJOQ9QNRXT}WY`|a&aSbrgPmkn!nJq>qcsVx,y%-,B-,O-4|",
            "mai": "?W?XF>K^LgS{aKaxj(l+~g~h-!'-5{-7t-7u",
            "luan": ";D?dAzA{L=NDW~o{r7w@-4'-6G-6h-:y",
            "ru": "/M7F8G:1>AEgIYJ6KlLhQJSHU:VGW,inlEm`oSr+x_-%E-&!-1]-3)-3K-3x",
            "xue": "$?,(A=C@E@IGLKStTnXd[p_[coe,hdibig~/-!_-#M-18-2k-6%-6^",
            "sha": "%4&G052u4O8F8~<<<CFaG`H+K<U]t}xPzazi~S-,[-.h-/q-/r-2=",
            "na": "*0.u.x4E9#>WIYIuTJU!Zt`m`pgNlNlypHu7wcyZ~0-!d-.x",
            "qian": "'K.(/~0A0t1'2*2D2R2p6+7[8J8q:G;h>b@vA~CnD(EIElF:I%IjK>KLNNO&O8P}VR[*[u]u_q`!`&gSh;i~kjk~p9pEpOq;q?r6sPtYukvqwPwgwtwvx+{x-#U-$z-*+-*/-*=-+U-,y-,z-0x-37-4M-6z-8G-8M",
            "suo": "#*1Z1^4Z797U:?;cFaFbJ7P{VJcuk)tatju3u9xi-/b",
            "gan": "!3%)*1*t.Y/x1*1}3%4s91>GCmE#T>Y^bJbTcAcTcti}nE-+e-.Q-1T-2w-3*-:i",
            "gui": "!q#o$.$C%x%})0)s,E/?1K1T?NERJ;N%P/R*RpU<V{WVX0XPZ!_*aHbod<dng>gEi#lilxuyvlzY{P|M~#-#K-*;-.7-.:-.=-/S-1F-1U-2%-2r-34-:Y-:]",
            "jue": "$Z$l$o%6,%525S8#9NA^D=KiKtNnO6RwRxU!WWWbX%X5X>XBXZXiY4Zj]N^f_}a0c[chd<fCfDfwpKv)v:wCyo-)0-,$-2r-3<-3=-5g",
            "liao": "$:,A,m,x1g7n8%:@:C=OA#ADJcM(RnRv`1b8f$fJizl&mnopv,wNypz.-&@-&G-,)-5t-77",
            "er": "3><m<p=8=T?HEyLoS|U8Z6aBaGbjd3gshtjJl2q_x9|L}M-'/-(=-)Y-,Q-,R-/D-2)-3j-6b",
            "chu": "$e%s(/)M.%.)114y9=<~=%A_DCG=IdIoMMNOPQS'XRXe[/`E`Oa,cmf=fTfcmaq3rnxlzW|`}p}|-59-8O-9|-:)-:9",
            "kui": "#f#o$C'D,Z,p0v1m22=m=o=s={?NAFI6IJKnLyN1N;NbQY[edpf*fvk;mXt;tJ{0}7-$A-$d-%6-'a-'o-(P-(`-*6-+P-.B",
            "yun": "!F'N*;/`/|0y4T6z7!7<7C8z9|<y=?@_D@FLG7IAIVIyK_K|L#L0MIM`QcV@a3b)b@bYc=j1kQm!m7mVmgnRo0o8pVrO|'|d}5~7~i-#?-#g-#n-#{-$(-$/-'N-(p-)'-:'-:0",
            "sui": "!q#G#J%G&f)$)t+R+h+p5m7>7h7x8D9V:4AQCyFOFPNxV}Zm]c_QazkFkHl.uqv!vF}*}/}G}H}w-#$-#r-+|-,/",
            "gen": "CQEHdc",
            "xie": "';(f*&3c4k5+595I5h6g6v7&8>8T92:B:M<3>l?T?V?ZA&LRLTM0Q7QKS+S@SBStTRV*V^W4XKXOXS[B[y^<_Z_mflfnl,lU-!i-!v-#1-#D-#h-$#-%c-/S-2%-9Z-9q-9t-9~-:b",
            "zhai": "%X)3,92q<?a@b]q=-9c-9d-9i",
            "tou": "4G6sMyjqrItA-$b-&r-+h-8;",
            "wang": "!664:h:i:j:k:mFvGmO>P*Q,Znh5iGj+jM-.N",
            "kang": "%<+U2v3tg1lJpgugwmz={L-17",
            "da": "!W.u/(/S84;H=<EsF*LHS0VCYldzi{j0j7j;k?kZt]tqvZ-!g-!|-#R-:S-:U",
            "jiao": "$y$}'~+k,A,K.`/I1o5;8?8]9O:J?E?j@hA9AKB(CaEZE[KTM5NZP!RkR|WWWbX%X5X>Xs]Q]fa`d0dhe3gvh_hfi;i?lvnkoHo]p#q]v*xW-'%-(B-*h-+;-/Q-1>-20-3|-5k-5s-78-:a",
            "hai": "5L?Aj9l/lnnro<-'!-'~-)Z-)b-+>-+p",
            "heng": "?J?mMZT9vc-3o-4$-6e",
            "peng": "%c&'&S'+'Z+,.V1+1@5@8P>~AACgE%FdJRMkRiRjU3eSgbh:s9v{zL-$+-$0-):-*A-,X-,b-,q-4K-6y",
            "mu": "!1#N%]+V7`7n:@?.C5DeF~G%O=e/qKqPx!~3~G-#9",
            "ting": "/s5l<t=j=z>%>&?qC)FnI7PWQ8ZJ[El=rUxKz`~K-!~-$g-%e-9F",
            "qin": "$j$k*'*Q.d5c=>>MD1DAGZG^GkMRO8Q}RJS7TVWJWrZQc]pXpkriwix{}c-!]-$~-)f-+E-/c-33-4L",
            "qing": "&/&Z'i046+60:ZDaHzQ#Wr[%]%_Agph+i7m<s4vi-!;-!<-!B-$7-%P-/}-2B-8X",
            "bo": "%h&^'x(B(U*L+l081c2%2,3~4m:S>;>t?fA!BuC,DrGWH=I'J{L4MmO^U+U,U6VrW5ZL[d]Rd8d_eKf@m3pxq5qFrVtow0wxw|x(yT-'4-'^-(E-(V-(d-(g-).-)[-*^-+)-+~-,$-/0-1=-1}-42-6k",
            "lian": "'K+D2+2P2V6w7b8k94;s<T=Y=n=q=t=u@+AZAcG(G,HLJTKDLELOMsMtQtS=U`UaVUW#We]0f2j?k(n0oPsZsyt`u@vKxfy}-,n-0U-0}-27",
            "duo": "&U5|:!BtU0Uncrdfdid~eYg!g#g5plvUx5|E|J}*}3}S-&~-(;-(z-)1-,i-4]",
            "men": "#{$*+XGRNEsuwVz1z6{>{M-#!",
            "ren": "(o*,*e+#4A4U5)5y8x9$>?@AD)E}FGGDTUU2Y!ZC^I^Vg&gFi&p/p;pRqp-!W-![-#[-#w-&i-'#-(2-.^-3{",
            "shen": "!U![$8$r$u%j)#)9,12e2g3T3U3q3w4l96:p:~>i>m?t@BFkHwH}JGK!LCPGPHUNX)Y1YHZ*[2^)_%_L_S_VfylPqRrj-$W-)W-.m-/z-0@-0|-1)-2N-4A-8b",
            "ze": "#R#}$n(+*p/,0J1I=0BsKAS?Vz[(].a@b7b]c:jO-&t-6.-9s-:,",
            "jin": "!#$j$k%M)8)G.U.m/J4W4`6L70:/B6F&F;GcGkJYM!TWW%WzX<X@]9_sb&bIc#j2j<k8olomp>sTwGy2-!^-'m-(Y-)$-7D-88-::",
            "pu": "$5*k+j0$8LBTBUFXGGGaH~IsIt[D]]_|bEfInprtupv=xbyqyu|[-/m",
            "reng": "(_DGiu|z",
            "zong": "&Y'h+?3P3]4$5z6E6Q6n6x7(7M7X7e7t9%9n<J@MI=J=QU`eePeRf1t!v_-)z-*5-+K-,`-,f-.8-09-0G",
            "lun": "&n'k*|6:9&='@4D:GLPk[1^`eBhAi)s.|k-04",
            "cang": "15B$BpC<DUI~M#R3b/w8-50-6P",
            "zi": "!i!j%()R*/*X*b+E/)2l354F4d6I6W8O9s<u>z?!?MB'CwE5E7ENE`F4GHHuJbL;NsXHYOYP[I_caFa[bzb~cZcpd(h3hQiJmbp&pmsGtRtuy=yO-$s-$t-,I-/{-0r-2P-4e-9)-9f-9i-9u-:D",
            "zai": "#^7HGHb+g|i9n^",
            "ta": "(d)i2~VAZr]wdBe7etfFfOfpkdkiq+sBt]tex1{'{5{;{={R{o-!s-#*-#B-/?-0t-2d",
            "xian": "!:!O#5$<&#(F(h)X*3+D/D0V2k3B4%4|5A5c5t6,6]7J7r8Z8c8q90:%;];d;h?&@oAnA~B;BvDSDwFzG,LOM'M*MpOKO_O}PJT+T0V_W:WRX,ZXZo[O]d`>awbKb^cYdgd}f;fhgBhHnfo'oPqvr#r$rFrqs<sps{uww'xJxMy4zBzC{H|K|a|e|s|v}J~v-#T-$!-$$-%.-%H-'D-(M-(o-/T-1l-21-55-5x-5y-6$-6q-7G-7h-8$-9P",
            "cha": "'0*049B=C9CjD}EYEdTAYyY}_1enr't7t[vryDz!-!U-'Z-(O",
            "hong": "&*&8.*.>0o334=4P4f5i8o8{;z<!<==CDyF?HoHpL*LXNtXtXy^L`'`*`,gUhNhwi+p[q[rGrYt:z?zXzrzt{I~U~e-!n-.(-.a-3v-6i-8<-8?",
            "tong": "!r$@%o&>*]+m.?/Q/i345D5N5`9PA@EjJPO1T,Z,cFj|ndq:qYqjxC-')-/L-2*",
            "dai": "0,1n4x7%9AC?OMQ]TdW=Yd^xa7aLbqdff'gCgLg[i%jIk4p0~z-!0-)E-/>-3I-8N-8e",
            "ling": "%d)D*M++.5/+4p6@9];K;U<.=KBqD[GiJJJmL%M|OiT(TcUjYVdLgZh/n8oWpts0x)zN|q~;~O~]~a~c-!2-$L-%`-)C-/$-05-2C-3L-6Y-7E-7q-9z-9{-:A-:T",
            "chao": "!k,h,r2u6?9b;5<wXDY=]?cdh`mlpSwa-7w-8v-9#",
            "chang": ">J@mA+DTGMH!UlUqZfs&sWy+z'z(z0zh{1{a-#d-.0-02-1X-2H-2T-92-:d",
            "sa": "8g?^HDK{LYY@fnpQuwwS}A-!c-!s-&,-&P-)&",
            "fan": "%0(M/1/40i2A2d6R7i8$;o<[AIBcBfE0KNLPM>N!SOVqXva=bcf<gEg_hThkj5p'v#v?wT-&=-&Z-&n-&o-(5-1E-5r",
            "miao": "!J#m*=.10s6e6u7n9z:@D`M$l3-4s-6u",
            "yang": "!R#!(C)Y*R4t;E;J;P?5OxQ/YX[T_0gahGqDswt,wX{}|.|y~:~}-!p-&8-&M-&k-',-)G-0]-3a-3t-62-6X",
            "ang": ">Xo:-+g",
            "wo": "#l&A,R,_6}>I@OAlB!G*HQLgP[Qbe:-(p-:4-:I-:L",
            "jian": "!%#9#`$<$D$I&N&b','r'}(&(<(X+D.p/9/g0#0/0Q181k262I3_5U6Z788(899v:9<F>$>S@fB4BoCICSCTETE~G<GrHiI{K5K]L!LVLwN=RGSEU5UcVjVlWAWRW}X#X,YT[.[F[c],][]}^!_Y_v`K`Racaybkc|d?dKdye8ecephvp/p;qXrMrZs(tFtHu!ubv4vDvNvovpw.w1w5xwy:zCzD{J}d-!V-#;-#>-#O-#X-'A-'S-(7-(k-,h-0Y-0`-0h-1(-28-2h-37-40-4R-5@-71-7F-7I-7J-7W",
            "fen": "#|%A*9./2x3=3r4S9';M;q;~ARD4IxKmO?O@TGY,`^`ff|hjnOpUvY}K~5-'W-'}-(c-(r-.w-1M-2Q-35-85-8n-9.-9:",
            "bin": "%A8I::A)AiNc`X`cahailKvjya~l-$p-%G-%k-,'-,1-,E-,_-,p-.!",
            "di": "!u#/%W')'.'{)<)_*U.v/*1=2c4+6c:);X<?=b>;@WDXD_FMG9G_ICJMJrJwJ|M6Q+QVR<TtX*X8XIYW[:[A^q_f`dcee_f/gYjKjtjukLkekwldp0qNuIyj|5}#-!X-#=-$H-(y-+n-,>-0>-69",
            "fang": "!I!n(l4Y9*>TBjD;O!Y;^ed@lLp@siwn|,-,?-.v-1s-3E-51",
            "pei": ">Q?(JBSwUrUsauc2hyiPnBn{s5y7|%|f~M-)#",
            "diao": "$#&a,C,k.B1]5FJML|NhOaXxZ8Zv_M`ro~p_r!r:s*s[vawUxExR}v~D-.c-//-0%-2L-2{-3&-4O-9>",
            "dun": "!<!A%J'3(%Pxd;eZf?fKfVjikGkvpLw`-$G-%X-*c",
            "wen": "+C+`+z4B4C5X7!7<839)9|=d>^?gD'G!O'O(R/RO`ahShWiNu6zlzqzw{<{D{Q{c~4-#?-#{-%(-'f-)(-)4-.r-0g-0z-2V-36-3G-9<",
            "xin": "!=(F?zBID7FkLZSyVtY3Y<gBiWlOo[pIrNv1w,xtyn{w-%/-(q-(t-)$",
            "ai": "$F$|%l%~&e'M(:5=CbKGL6MN[K]k]{b2g(r9tWv^yK}1}8~s-!.-!3-'U-(m-1[-3l",
            "xiu": "**3h5g7u8,9T;Y?i?yB*B7DuQ{ToV0V1`ur%rBtSu=u^uvxp-&K-'l-(X-,@-,U-/Z-13-3}-6d-9^",
            "xu": "!$!*!4!Z#j$l%;)W+@+H3[5K5e5x6T6X6s7)8X9[9_=X=e?4D/IeJ)JXJfKrLxM/NQNTNUO[P$Q:UDX|YBYJYs[8[Z]C^^_3_ia^lUmwnLo*qovn~E-$<-$>-%T-%U-*[-,w-.G-.W-1_",
            "tang": "$f'@)f0{3V3j3o;l=)@zA4J4LJQSR$RAcMc~eef&g+m]o=tiu)uTv'wDx[yWyd{1}:-#I-']-'h-5:-96",
            "huo": "!V$S$^(*)>)S*Y*_*`+|,W10=$=4AuCJG.IhMTSI[g`0a<bacnlTpesrvhwoy6yyz5}y~R-!,-#S-*0",
            "hui": "#J#[$G)N*i+s1;5R8.869I9}<9<:<L<^CxEbF1K2KeL8L9MFN,NuO7OtOuPZR*RyT_V:Z$Z2Z_[L]S]n^#^X_!_<`FaXbyh4iEjUk*qouqvI{6{j}3}S-!Q-$c-%C-%l-'R-/V-1#-81",
            "kuai": "/w3}?]AWIJIql|n*-)0-1P-2.",
            "cui": "'g,w2z3L4[697>:4<%<@[email protected]{THVmd#uQ}Y-$|",
            "che": "$;%I&?&@=JFjP@g<h~jA-$M",
            "chen": "#t&M&t'`*[+A+{5{>FA}EKFRFcK:LmRBTDW6Y7Zz[Q[o^;_V`$arb;c`cad>dKeagKimjHmDo@pAt(|C|o~H-5T-7]-9l-9m-:=",
            "xun": "!x$Q*p,^4;8MAjEnF:KLKSL[LaMcRzS%XwY#Y)Yt^R^T_+j%jajlkclsmzoTv`-%A-(}-)U-+%-1?-1H-24-5A",
            "chi": "!]!y$).X.y/A0+02133,5W<#<$<D<H<|=@>>?2?D@SE9E|GeO%OHORR;U/U0UkVMYFZ9Zq[t`8aRcBc^d+dfeGj@jBkKkfkrkyl7q7q^qusx~9-&l-(4-(|-+&-.R-3Y-4!-4r-4w-4y-5]-6Z-8(-8C-9k-9v-:<",
            "xuan": "!m!x#d$['5)k0R5?7J7d7w9K<G<_HMHNJ8K#L/MQMfPEQ?S<T)U$[;[W]_^&_abRgDi$jkl!q,ratLu?x0yl-#'-&2-)U-)k-0f",
            "nu": "%a/.?;-)>-+4",
            "bai": "+&.;3;3M51L^W3b:b_-#k",
            "gu": "!/$J'B)A*~+P.z010?0u3g75:r:v;Q>K@(AfE)G>GhJ,LSOdOjSeXFYR^h`%a]bxgdgehYi,iXk,nYprpws]wwy.}h-%@-%W-'Y-(Q-+`-/;-0'-2I-3^-5?-6S-7%-9*-9+",
            "ni": "!h#P*G2m73=i>$>}@pABA{DqLpOLP.Q!XXZt`~d`h.jhmCpnx3}L~X-(e-0,-2J-7`-:+",
            "ban": "*E2s5!9;>PBgBkQ*QvVKd[iciipPqEwfzx|$-!h-$F-%Z-.n-35",
            "zhou": "!+#U$x&y062.2@2C3+384:777o8p9:<B>B>o?#B^F@GoI$LfY][a]y^r_4_Manc0gkg{h,i0i<k7m>nCqg~Q-);-)`-)t-*r-+[-0(-3~-6f",
            "qu": "$L'o(}.2.F/@2U3?4o5#<1<U<~>u?/AxDlG:HhKbM}O[OfOpQdRDRlSkSpT'T:U&WxX!X&X=YeYjZj^tcjcld%d*fqf}g2gWw<zfzu{i|4-)3-)5-*W-+'-,S-.~-1'-1;-3W-4l-6E-6[-7}-7~-8&-8+-8U-8u-9A-:/-:H",
            "ci": "'=(A)%353a5579ESEUG6L;OsQpS3Yp^saqc.c_dSiYiZiaij}m-&y-'*-+l-,%-/+-3V-5C-5D-7'-:6",
            "beng": "(l5@657k9iGnO*dtf3jYk2uiygz>-#)",
            "ga": "g=onsfwH-.A",
            "dian": "&p'v,j1iIiKRPXdXeVewq!x%|8~@-!E-%3-%4-%z-*g-8Q-:8",
            "tian": "!:#;'1'H,j4w6D>v@:BRBXGvWmX9atnTr#rFsXx%xM{%{n-!>-!G-'$-3f-5J-5S-8:",
            "bi": "#L#M'!(w)L*@*C+;.n.o/E/Y0(0)1/1<2r2y4M4m6>7Q8@8};7<,=a>a>r@lA[BlC|E*F.FJG~H:J<JdKHLLPPR!TiUfVhW$W)X^Yh^v`<a!aEaUbMblc/d|e~fPfQi[kBl)l^mjmym{q1truFvQx2z8z9z:zP{B{C|V-#,-#G-#p-&u-'j-(f-)I-*X-+x-,N-.T-/*-0Z-2S-45-4}-5b-5n-8~-9S",
            "zhao": "#'$K.e00:V;#;?>*>1>2GdYf^ucScxorp<q.t6wL-)8-/G-3&",
            "shao": "#+*y/r4r6%9>C&CqD^FyHSK}Tjh$la-#&-$)-,Z-/`",
            "zuo": "(|*S+!+n/,/p4*7{?'D{F^H`HaJ?Th[(nWp||7-&t",
            "ti": "!g#e')'?)Z)|*v/8285f6|9Y9y:{DXF!KgLIUzV&V'[qd)d2eJemexf~g8jxk=kLo&rDt)xy-%$-%r-*2-+m-,0-,L-,]-,a-/^-0B-2U-4;-4w-4y-5L-5M-5i-6r",
            "zhan": "$H&b.33*6=9oGQLMN2N`NaOeWyYQZ/]h]l^B`#cghUhgiSl0n|zK~V-%~-&*-&N-&e-'|-*b-*l-.Z-1S-2y-37-60-7=-8i-:h",
            "he": "&c()*(0z2i3@4?8r<N<ODdFIGFGzJ1R(SMTmV2WOYGYIYw[z^i`x`yaTbtcIloovq0vgzRzU{){X{m}Z-!7-!8-!9-#7-$P-%f-'&-(@-.|-1u-5$-52-58-6?-7#-72-7v-9n-:>-:`",
            "she": "'y(`BJBKBLJuNpOgP(S5Y>^dagakc'cDg~{!{^-#h-)u-7l",
            "die": "!g!t&w5M9G<k<l>pB5C6D~PmQ`R@V,V]YU[7_WcbdOdXdreigojNz+-#1-0S-2R-3d",
            "gou": "/01%2)3g6t:&<h<i<jD>DhO[U#VBWwX;YNY~_(`ob5bgk_pMqHwl}k-#A-#m",
            "kou": "!P!Z#r$$,P.2/W1OD+K=KFp$-5K",
            "ning": "$P=R>!DpLevm-,~-64",
            "yong": "%p&>A]DcIPP=Yre2e]l@mJmio9rHuVyh}n}~-%*-%s-'x-/y-0w-15-2A-2o-5`",
            "wa": "%K,),?,E,`=N@r@xOyTuW1lc-#W-#^-#t-8w",
            "ka": "?8U@qV",
            "bao": ",<.~6h?,DgGYHcK`L4MJN^OJTeUdV4V5Vf`ib*d8q/w%x.zs~>-!6-&x-&|-(9-)/-+j-,M-/7-1~-3/-3A-6Q-9r-:B",
            "huai": "=7N3N8VDVSeE-:f",
            "ming": "!C!w#zEDJ'R,WuZ0m^n_q}xT-3.-6L",
            "hen": "Y|-!y",
            "quan": "$b%u/K0B5<6$7:9mEqI3NAP|SlXLZ#_)dkeIgzi=o5qxv%xO{#-#_-%M-&$-)V-*3-,e-0L-2^-9}",
            "tiao": "!~(t),,J,g/!3/4.5F=S?PCdD^H0J@JMJNPnWdZ8Zv_McqdwjCr!rdtyxR-#%-,G-/o-1&-2;-9y-:C",
            "xing": "!D#Z&$0Y0g6J@YApBFEuF7FhHrP9T#XVX_[_lMluo+pBqZqwrhwZx6|D|S-'V-(/-)p-+D-/5-0D",
            "kan": "!N$=$g%?'^.QG&T%h8ho{4{q-%)-.+-:R-:X",
            "lai": "#8#F/X0%2/2MG'H%MSW7Zqaob,c&c4k.mBsgxd-$q-$w-)y-0*-4B-4f-8%",
            "kua": "50?>B~Z=d9dlq~-+s",
            "gong": "'91*44474=8o;z>[OBXQXba6bZfzg$gtrG-!z-,T-:L-:Q-:W-:u",
            "mi": "!s#p$A(w)')w*C1d2b2}3p407c;>;F?bClH{J#K'K/L}N#N6PaU*WZW[WcX1Z.[j[l_g_rjXo4oXoYo_r,z/-!K-66-7X-7Y-7j-82-9&",
            "an": "!(!.;)?I@XEzGlHWHgJSUxZS[N_d`k`{r1s:x]zy}+~=-!w-!x-$1-(l-/E-4I-4u-6v-8c",
            "lu": "!)#Q$_%|&L&d'])E)J*}+[+o071X1v2!2#2G2H3I6S8^9q:f?9A,AtBmBzCFCMCND.G@JcJeJtKcM[N<NINVR>SYXh[~aVb|d$dseCf#gxh^h|i/i>iTk5nwpis2sascu8uMumvGw&w+yr|A|t~x-%J-%_-)+-)r-*N-,3-.q-.t-00-1i-1r-1y-3w-4E-4P-6!-6>-6U-7;-7C-7M-7b-8l",
            "mou": "!|7n:@Oq[[_Ue6t=-#9-3y-8!",
            "cun": ".N2nA>lS",
            "lv": "$()(*r+~0`5Z5~6S7_7j9q:*@wA(A8A;HkM,NKV=VZm'rJw#xDz_{T-*u-+*-5a",
            "zhen": "!X!b!c!}%Y'%)5)T)b+I.A0X264N4w5Y7D7L9,:2=I?%B9H5I5IWJ&LnTpUSWaYKZb^pa2afbWc%g^hZi4iqkOnNoxq$r~s`tOu$u%wJyS|0|_~L-)D-,o-1f-3@-6R-8d",
            "ce": "/%/U/^/t0G1W36F/H3HPJA",
            "chai": ")&>HCjEJNzS9T[Xz`jp4wY",
            "nong": ")v*j+q8C?cAXL,V~]iioipoL-,{-9a",
            "hou": "#c$t0q3Z<M<UEVHq`MjgltmWq|t@-'T-+r-/B-0C-1O-2!-2,-9Y",
            "jiong": ",M4~5uB#B&MeMjVIjFjjqi-$}-%h-)6-)X",
            "tui": "+y=N@tJ^MAM^P?PYQkVL^.eof7jb}D-$n-$o-$r-%m-)l-+u-.L",
            "nan": "@^G$HOQe[PcEk]}_~'",
            "xiao": "#+&4&:+i,N.l/q0!0O0c1(1b1u5a9R<;>@AGFyHCKyL2LtNBNMP<RPR^S!S[Y5YzZUZl[ke*jom9r@xh~I-&3-*`-+8-+q-,!-,+-.I-3X-3p-5Q-6W",
            "bian": "%`&}+8,;/=0S2A2W3W6k6y:$:+B/C4DLHUL{QBV+WTW}[5^/aJbfi^idieifihikiliviwkSl4l5oatPzO-##-#<-0I-0J-2`-3R-5&",
            "pian": "0l6y:$<I?K@5WX[9_haIaZdtejsq-)O-)v-*(-**-+?-+N-+w-.z-5&",
            "cu": "1P3)7S?xK)XAZDcjcvd%d*eOehf%fAfBo$-%<-7O-7R-7T-7s-8t",
            "e": "#3%:%B%Z%y'<(9@bDRF}HXKfO#PBQ)WpY+ZF[?]L^2^___`NgMgii(j8kRkUl%mRpJpjrrt&w*xoyCzn{f|!|3|:-$?-$R-$S-%%-%&-%t-%w-'6-'L-(G-)n-.f-0[-0v-1h-2Y-4&-4<-4=-4z-6o-7$-9[-:3",
            "guang": "%w?@B#B&EWgwj}r0-89",
            "ku": "%,&5*D,@,T5:9E>{DoU1UbVTdPllnm-+o-/R-:p",
            "jun": "&].=/`0<0CFlGCI1O/PeTXWhaeg?m1p^qfr&t'wj|Q}^}l-$j-'8-(J-)m-+F-/]-2?-43-44-47-7U-7^-7d-:Y-:]",
            "zu": "(x*J+10H4}95GqHbIkYm^kd6eLtdu2u;yk|6-!f",
            "hun": "!F#O#W#]F6I8JyXT[=_2hczo{d-'>-(L-.C-9J",
            "su": "';+1+3+],X1U3.324X7K7U:?>,>/@{DWFwJsM+M]MiXWYE[r^o_lcyf(k$khksnZrR-':-*_-+L-/i-1@-5p-6~",
            "pai": "0'1z1|IOhBjLtV",
            "biao": "'c,!1D@3A,A1AoJoM=T@UoVa[3]#b?seuZw$ycz#-&&-&+-&5-&D-&E-&F-&H-&O-&W-&X-*~-+@-+W-,;-2j-7Q",
            "fei": "%[//1!6M9a<A>O>e>r>z>{@GDFGjH$KhP_PuRuUtZp_GaObsvEyP|g~T-!/-!H-!I-&Y-&[-&]-'H-(j-*!-*,-0+-2F-9;",
            "bei": "&i&r)`0'3f>wA[DfJ9M8PAU'V;ZLZwa1bVgch@iDlbm5mQqWrPv[wd|=-!l-#,-#C-+k-4N-6x",
            "dao": ")=)H)x+B+K005F8h<B<`B_C7GwR7T4T7Umeqg9iwkYoq|b}=}O-.]-1n",
            "tan": "'/6D8A:_:eBOBSGtM@TkW(WJZ~]Z]a_R_xa.a>bdm?n~o,oJqQsMx#y8-$x",
            "chui": "&U0D@8GPsFtny0|n-$u-:_",
            "kong": "%.&V,/0@;gg,sA-#(-4[",
            "juan": "!{#2#H5J5V7Z9S:|;=?w@7AaG[K3SfUM^&mTrZras6u0vHy5yXzt}^}l-#'-&k-'.-6m-:w",
            "luo": "%T&!&='n/>0M2]5>8f9M:n;@@)@UAwF8H9HYJ5N9OrRHS6UvW~X'Z1dbf`g'kAl:uEw>y/yf}s-$f-('-)_-*P-*k-+=-+X-/K-4#-6)",
            "song": "&P.@===yGOY0Z]^b_?jcu1-$@-%[-'[-)e-,c",
            "leng": "#>&h++L@eD",
            "ben": "/&<(DxRuaUblk/sIy&",
            "cai": "#T677P8aGSK+U>a5b[dxeQob",
            "ying": "!R$v&C&|(P)c+_2K2^6U7/8`9^:>:X:Y:c=?A:ASDzEAF7F9G0G1H@HAHBHZJKLqMwOmQ0QPQiR0S8SgVPWv[i]M]|adbHc@g:j/m2twv8vky?~_-##-$.-$i-%g-%o-%p-1V-3g-4q-5*-53-5o-5~-67-6C-74-7>",
            "ruan": "&u(>6^<o@QgQhDi*|(",
            "chun": "#_0_4L8|>U?sA7C~G3G}HRITJZQgSUb(hKn}o/sL|T-0#-0Q-4i-4~-6{",
            "ruo": "0P1#DnI}mP-0e-0{-5<",
            "dang": "!,#s%2'((2/[1f2&CDF3GbKuN(S)UCW&]b^A_kd&kEvWxB{9~A-8[",
            "huang": "'w+e0f1q7O>=C1F#H|Q@RtSuYv[V[f_Xd,kWt3txu}yI},-$,-'P-*.-0T-1A-2]-5q-86-87",
            "duan": "${'&.I1`2X6a:#<r@kI/V/fdt.tGyG",
            "ou": "*$=*@VA*KPM)MG]3^Yu:-3H-5[-6N",
            "zan": ")},'1A1t1x3`W?^'^?apbCc<d4d5e}n1n7n<smuaubv2v<-((-4C",
            "za": "%k4^4gAvA|Vpj*q8}r}}~)-$'-.u",
            "lou": "$(0x1V=+=1C>IMK(QfRI]1a*g3kxu]yN|F~x-#J-+}-,*-5a",
            "sou": "#v2BC;IQJ(L_M?Qum[o3t~uAyH-&:-&<-&S-'c-(R-*<",
            "yuan": "!9!f)V.i0F6f7':.;m>CD3DYE?I?I_InLGLdO5PRPzQFQXQrT&TYUiUuV3VF[xa3bYh]iQj=k@kgl8lRnPphs'u(|^-%1-)9-*G-.o-30-3U-4V-5%-54-6K-6]-6}-8s-9!-90-95",
            "rong": "+Q+S5E7@9C;^>FEFEfF5J/QhQwQxSDVEghthyb-)R",
            "jiang": "(43u3|5P8:9L:F<>=.A2EaH^ILK.LAQjRM[w]=^W`6ngo>oF|H-#P-%5-12-2_",
            "bang": "&<'A+%5_749B@uC8IcO!O*OvPt[s_olQlVt^y^-#3-,#",
            "shan": "#:'m)K)q+W.s7g7}:D;p;r?pALATBaD&DtR}S,TCWjY%[b]r^ObFc?cVd^gGlAn#p!qtvBwRz4z5z;{@|P|X-'q-*J-+V-/l-1C-1D-2s-2y",
            "que": "&5&E&g'6'7(1(N:P:RI]O6c}z}{*{l{p}a-4Q-6t",
            "nuo": "+<+u3e3y4&<oU/U0[Y_DelkCt<y#}_~'",
            "can": "+W1A3ELBO4Q.SjSn]2uJ-&`-'3-*T-+M-8^-8f",
            "lei": "$X'F'b(,(H(I)7)~2j4h5H7Y8S8Y8j:=:d;t<s>5JiKWL.M4N*N+N7N@SPZ:^(^zhxnoqls?vPvvw:yz~<-!*-$O-$_-%7-%}-1Y-6<-9R",
            "zao": ",y,~1R3sC#LlMPOC]`d1f4fNk%ktoCwA",
            "cao": "3m>9C=C[EwJ_R:VbV|n)uc-*D-94",
            "ao": "!T'Y<Q<V<Z=wC]DBK&R=T]Vy]7]8g]kom9uBuMuNz*}>}I-*S-+S-0~-2b-5X-8{",
            "cou": "@ThJiK",
            "chuang": "'_,H,L,q{+{E",
            "piao": "$+).1D7a:;<RF|LiRCo?{3-%9-&A-&B-&V-*U-+W-.S-1.",
            "man": "#{$*$c5X7]:<JkJzN)P2R6R]SoVw]>_tmuuCuUye-#!-%;-%y-'i-(Z-,t-,u-1*-2m",
            "zun": "8':^U5]Pk|qqv+-1B-2u-4n-5|",
            "deng": "$7'q.M/H1pCCW|`:f9l>mxv6yx}E",
            "tie": "=VH8OhaPbndXq'qzv>vRx'-&z-'Q-*i",
            "seng": "-,v",
            "zhuang": "3:3nF)F]UBUZ",
            "min": "!B%9&`.}/<1l6O6d:,:wDiSSb'pqs7tEzEzZ{K{S-1$-2n-3P-8q-8r",
            "sai": "2'@cb6c9-%#-0_-2X",
            "tai": "0+27>h>yB8BeD]GeLjdIl[nSpfw^-&/-)E-+7-/6-2$",
            "lan": "17212Q4/8K8i9x;+I<JCL~N$N&VVVxW*W;WDWoX(X4]K^:_{fknxw/wFytz~{h-#Y-%K",
            "meng": "$/$T$`(?C.CKFgH'IZKONvPgQZRaSFn'n,rKsby<~?~k-!(-!)-%F-(!-,O-/t-08-68-7@-8q-8r-8z",
            "qiong": "#@#x,+,.,d,|/:/FB{EBM%MBP,P0cWdolFqs",
            "lie": "5}=]?oEOOzU?csf^j`-&0-,x-.#-/J-1c-3r",
            "teng": "2>2F7I@sAHM9N?R1Z@[`l1~u-)S-*B-*v-0s-97",
            "long": "!p$a%n&=(R(S,u.!.6/;1*162N=P>'?6E<MxS^S`W8`4bSffu`w)|B}%}T~y-!1-*t-6@-:J-:O-:P-:V",
            "rang": ")z+t,$8bMn]s^8^Nfm-.$",
            "xiong": "?F?GCrY:YiZ4^a^mb'}e",
            "chong": "*86b;:;|B@CBEhNfQRS$T5V)f!ohqhxZ||",
            "dui": "&k'O(m5nLb]H]vhsj_v0v9ys{v|j})-$[-3h",
            "rui": "#h.h6N8+D6E(KUKVKpMWMXO)P~r<rwuqxx",
            "ke": "#u%T&5&~'B'Q(*(;*<+.,U,r6[9t<7C3DdHFLFOTQ5S}TmZi_Hd:gni.o2psqds/wyxQy)zM-$Z-${-%i-%q-){-+I-+y",
            "tu": "*)*.*x,6/a@dFNG+GVHsIfcbe&j,jvnjp6porIs!s}wO-(h-)j-4*-49-4T-5!-5O-5z-9M",
            "nei": "?~@;lNsE-'5-(I-/e-0!",
            "liu": "&B&d'>'[,A6;9l;1;;</IgJ*MERWUTe|kbs#tctzuHu{xuy[ym~%~j-&>-&@-&C-&U-'b-(W-)M-)c-*@-*d-+T-.9-0m-5=-5_-7.-76-7[",
            "shou": "6.9h@yC2uA-(_-:s",
            "ran": "7v>ZDZIFOEOYTST`Tz-,A-,K",
            "gang": "%.&q/{639!:N:W:x>Ep+s)ttwe",
            "gua": "506}:z;%>xU<V#Z5[>^|cnedr#rFxM-&'-&1-*9-3k-6c",
            "zui": "#G)C+15&8d;$KjRdXHi]nInqo!s$s8",
            "qia": "%{'I?1HyU4dUnU-!{-+z",
            "mei": "!L!_#)#a({)]+X0h3p;I;T?S?r@PE&FfI@QGTZdMg0mOnlrKtUtZyMyQ~N-#^-.>-.F-5(-7(-8V-8h",
            "zhun": "+$,56(>UT8YAZ{_Pj.",
            "du": "#K#b*f.T.^1,>DCsFBR&SZSmUyWqZd^$^D_E`3b%bNc)mMo(sDs|v}yL{!{^-!Y-#V-#s-#u-*E-,,-8]-8k",
            "kai": "II`7gysvtbt{vCxGxvy@z<{({U-&;",
            "hua": "%;&K'B3S8/BWD9D:GgIKK[MzR#XKZ&Ze[4[>]A]o_&`0p(p)rbsdunxN-*]-+<-5m-8=",
            "bie": "FTNFObRmVuf6-19-2l-8|-:[",
            "pao": "%e(@(O,!?|H>M=TeTfV>dDdTgfq/x.-!N-!o-7Q-7S-7|",
            "geng": "56575d6m7,9Q;j;u<v=DFVGfavc1m0-%b-+v-/h-25-4j-6|",
            "shua": "<nZR",
            "cuo": "#1$z'G79?nFpFtImJ2J}NR[(erk0kzn7o7rEs^t[xqy$-7H-7L",
            "la": "%_'R<*@>AbArG?HYM3PfQ4Q[SRi_i`l6v|z$-#0-,k-0F",
            "pou": "0$UO",
            "tuan": "1H4'V8a%u<-5V-6#",
            "zuan": "1B2Y808N8U8e:Kb3fjftq)vxw?w~",
            "keng": "%t&3&RZOr>t1uOxg|&",
            "gao": "#R#g)4)6)e*m+N+O/v0~3i7E:5;O;TA'B,GILrMHZ[_:m+ryu#xny]-#o-'_-,4-,5-5R-5v-93",
            "lang": "&7*n/dC(F{IXJ.JHPOQlZEg%lzl~m.rLu&xzz^{]-)h",
            "weng": "#q:b;}=rJ0L(Qstg-56-7,-9_",
            "tao": ")?58617A7N9W9kG|PoUhX{Yn[{^MdwhXjPjenzs+|r-!k-!t-#@-#l-#|-&w-'d-'y-)P-)x-9/",
            "nao": "%z&q'*?a@&@ZAkP6R~YZ]Ju|x@zJ{O-.'",
            "zang": ";S?_AmAyB$I,K@M#abambLbUb}rC-)A-++-,.",
            "suan": "(z.b/m0;1BI^nn",
            "nian": "':*5*P1Y3*C/K6evf5f[h=iCiS-/4-0;-1x-2K-4%-8B",
            "shuai": "7>:4RNTH",
            "mang": "!5!6&<&D.ZCvEXEiG4G5M_OvRaSAlDp.rsx:-)g",
            "rou": "*!2w3X>3?l@aHdQC]tekhEt$-#2-#f-*7-0R-4t",
            "cen": "+W.m1A",
            "shuang": "(V7;CPuh}z~b-*M-*y-+^-5c-6A-7B",
            "po": "%g%i/70I3'7i<,IlK,jLn%n[o1oKotq9uswMwz|=-$K-%a-)7-,N-.E",
            "a": "@@s@x}|:",
            "tun": "AYAeC~OlVL`G`IgJ~Z-&h-(0-.j-1q-8J",
            "hang": ".k/T5*9HBiDHOAT#UAa9j3lJ-$C-%]-.i",
            "shun": "!x$&$1$9BZKo-$:-%S-,g",
            "ne": "!vY6^]",
            "chuo": "'j0^6?8&9bd!e'e<h6iIirisk:narfu;w!-'B-:&-:G",
            "wai": ".O-%:",
            "guo": "$Y1K3R68=W=c@[email protected]]Q&Q1RVUwV!h7j'kTm=pZszvVxm-'?-(K-(a",
            "qiang": "%.157p82;G;R;Z;a;g;w@HCEJjKBLDMvPhVd[ndGeuf.tkuPurx~yAyw-50",
            "pen": "<XHm",
            "pin": "$V%A(8+w=^LcMaSLa;be-%I-%k-&#-(s-*q",
            "ha": "4_NyP'QOqdxQ",
            "o": "/}",
            "huan": "#.#x4!565b6l8;:(:I;b><EoH#H,I_M<^>`Q`b`va/hpj9k3l/lsn9tCvSyJy{{:{r}i}{-*|-,|-/n-0A-0K-2>-3?-4+-7<",
            "ken": "&#>8>Y>fUFV$`S`wsh-:?-:E",
            "chuai": "A0ACeb",
            "pa": "/b<zBdDrI)Trd7wr",
            "se": "+b+r,#3688CULD]Ehnr4tauuxVz[{5~2-&I",
            "re": "Dn",
            "sun": ".f/L0T1rF<J%L$LNt|}]-&f-&p-5A",
            "hei": "-8D-8E",
            "de": "OMsoy(",
            "kuo": "*Y*_/GH[H]O~r#rFxMz|{k~o-#.-#H-#e-$V-,V-,}",
            "ceng": ".Lf:-*f",
            "ca": "(E(Ykq",
            "zeng": "$~'p.L5z7H7z9n:E;9]DbAc>m|roxk-.6-1K",
            "nin": "?[",
            "kun": "#7&H);*s+*5oGEPpUEUJUgV.`wo%sCy*z]zj{Y-)w-,<-,=-,D-0/-2G-4^-5'-6w",
            "qun": "0<;_;`UVU^e.k&-7U",
            "ri": "TMp/p;pd-)%-+(",
            "lve": "+4rgrlxr",
            "zhui": "&U((.h66729r:'@C@|[!b>c6j_o#s>sQvdy1})}Y-)s-+J-4Z",
            "sao": "$O7m8<:A:HAdR4-&<-*#-*I-+Q-,:-0l-1R-2a",
            "en": "J!",
            "zou": "0&6GG=[)_CcNcOlem@mcn.|h-*H-+1-/w-06-2E-83-:.-:7-:n",
            "nv": "2h=TSvSxp8wW",
            "nuan": "-'M",
            "shuo": "$m&+'$0cIvZaZc_>qttmv~x*",
            "niu": "4H9.FxpTwq-!`",
            "rao": "+i8)9FF,KdVvk}}B-'v-(>",
            "niang": "nuoRoZ",
            "shui": "#I)7*q*z@1U[ZaZcZg_>_KzG",
            "nve": "&ONJ",
            "niao": "@%E>K1T^UGVO-2{-6H",
            "kuan": ",s,tAqw(-,&-,2",
            "cuan": ",',Q,s,t,z1)1[fLfsrZw;yv",
            "te": "?vRgr{xe",
            "zen": "]V_y",
            "zei": "S;a_bv-0M-1Q-2+",
            "zhua": "2(AU-,Y",
            "shuan": "5<@]z3{?",
            "zhuai": "#1dmi'",
            "nou": ";v=,tfv;",
            "shai": "/Z121J1e2[[K",
            "sen": "Ve",
            "run": "$1AOz@zQ{F",
            "ei": "ZH_@",
            "gei": "5C9J",
            "miu": "7n:@]+_w",
            "neng": "?LR'",
            "fiao": "WL",
            "shei": "Zg",
            "zhei": "j:",
            "nun": "-84"
        },
        "m": {
            "yi": "-:~-:<-:;-:4-:3-:#-:!-9~-9T-92-8u-8R-8N-8I-8+-8(-7O-7M-74-6l-6c-6L-5z-5)-40-2U-2Q-2>-11-0o-/_-..-,o-,B-,3-+q-+[-+<-)X-(o-(5-'w-'k-'=-'#-&6-$'-!?~=}E}1|x{Zz|zzxix6x.x%wKw,v%uPs_rurorEr8r)pppdpXojoioVnxn<mLm=l1j{jvjkj/j(i^i]i6h6gYg0g)g&g%fbf2f1f0f/etepd~dpd;c~c`c@bhbbbTaE_T_>_,^g]|]{]`]/[!Z=Y5XVVTTgT_T7T1SxSsR~RyR;QwQ0Q!PDP6NbN^N,MZMSLXLIL6L$J9I}IUIIHMG?EaEHE4D!CwCFBkBTBEB9B5@2?Y?K?I>K>H>'=a=R;m:~:48c8!7,5g4q3&2}2Y1j1f1`1M1/1'0t.O.K,_,,*x*f(c'G&.&&%b%Y%G%$$b$6$/#x#T!9",
            "ding": "-:}-8q-)?-%!vipfkGiydzY2Ik6u+B&^&[%_",
            "zheng": "-:}-9O-7L-0#{1{,yjuvsRm*lNlIi;eheZe8e4e3d/`x_v]3[+ZSY8Y2XlVFTYT#Q1C@A!4W3w07.),]%*#C",
            "kao": "-:|n{k][#TbL>>R3p/,",
            "qiao": "-:|-:(-6A-5v-4=-3(-2[-.@-,2-$H-$5-!q-!=y/y$xkx4rSm+m!k]k%j:iSi(hqbvaT_wVuV6V$T%KgGaF^FKFGEpDSBCBBB;8<2b1C1>.}#e",
            "yu": "-:|-:p-9^-9P-9J-9H-80-7t-75-6'-5g-5b-5H-4U-3F-2l-20-1F-+K-)O-)+-(J-%a-$p-$K-$9-!7}]}W}5{7zizNzEvyvwv9v3tytjtetcsqsos@rsq|pyp+p%oQn6m%l8kyklk8jfgvguf%eGdWbtb(aLaKa:`1_1^:]e]d]KZOZ!YmXiTDS`SUS7RpQyNvLAKsJKJJJ;IAH|HmHVDVD:D*D#D!CrC[CDC,B*@K=Q<><<<1;h;_:v9G908=7M7I7A535#2{2R1b1:1(0;/q.(.&,1+G+9+7)n)h)F))(+&*%!$M$D$=#V!A!0",
            "qi": "-:{-:r-9{-9E-9;-99-82-8$-5f-5(-3D-2{-1:-0G-.j-(Y-(A-(.-'v-'C-&%-%m-%I-%F-%E-%:-$D-#N-!Z-!B}$zvyHwbw;w1u~t[tFn;n3n$m~l^kkiBg/dpdTcKb<aBa&`3`2`'_b_)^K]OYRY@X?W1TgT1SkSjS1RxQ4PbO@N]MyMCL]LZKhKOJ~JcJ]J[J>J4GyGJE<E,CyCkCjC<AEABA6@a@7@$?+>W<Y<N;5;49h9*6f4x3D,m+N+8)a)](`'4&V&1%K!C",
            "shang": "-:z-:t-7k-3C-%S{p{*y:oAo@c8aA`@]}Q^G.BxBZ@P:h9>8l1T",
            "xia": "-:y-:s-9u-6I-5e-3w-+T-*+-(v-'m-%n-!!}({Mwtwpm/logkeB_3YST)P~M<Jm4X3z2i.L.,,}*C)1%V%J$8",
            "han": "-:x-8S-7J-3>-1A-/j-/i-*P-*J-(^-&C-&9-$k}[{Xtrrbp,n8lJl%dqbm_c_L]cZ(VLV%T]R_R^QRQQPOK9IJCH@l@^@?=k=Z=?<l8k7X6'[email protected],t**&{!p",
            "wan": "-:w-:E-5=-/S-.f-+)-+&-&1{0z*x=wlwkv6tJt3ptpen%iGf_f?d[b.b,]1Z9Y|YmY=QOQDQ@Q,NVNNK1J%G9B2@h<m:X7}7<5:3]+&)t)Z%z!n!7",
            "mo": "-:w-:5-0z-.(-#S-!l~j~b}!yQy#v!r_rMr$qno}o?iji_hR_(^d[cVzVkVjUHTyR$O4M[FrFMC$C#B~?~?o?e8m640`.8,%#m!x",
            "zhang": "-:v-8k-8]-8L-3=-1byErnkDimiIh}hsfnfmfXey`Q]hYEPRNeFt<y<p8Z8Y,$(V$`#}#u",
            "san": "-:u-8d-7q-5p-3c-*Q-)m-)l-)k-)j-)ix:iHg#T5AeAdAZ7s/%",
            "ji": "-:r-:O-:<-9p-99-8x-8w-8'-8$-6t-4W-41-2w-1:-12-10-0*-/l-/^-/W-/#-.d-.^-.0-,9-*z-*`-*U-)d-)P-)0-)#-'6-&c-%s-%d-$V-#x-!{~z|~|f|.zxz?z(z'xlw;v^vJuZuLs$qAp=p;oJnfnEn(l$l#kRjsj0iBhYh!gEf=f<eseMdxdaczbAb*a!_K_)^k^F^C]@ZRYCXHW1V`VBV$UtU^TgT1RnRmRlP]P[PCOAO@O$N9N5K,JNI*HrHhGoGTFfF3ExEXEPE8E'D[BdB:@O@B>y>]=x<`;t;(9.9(857&6{6d5m3D/;.j+?(>(!&8%{%t%4$X$,#H#>#'!w",
            "bu": "-:q-7F-,M-*w-*t-(d-'K-&D{B{?{6zPtOm#izh'gfd,bi[rY}Y{YfQHM,C>C;C:'=",
            "fou": "-:q-(cvCBj4H",
            "mian": "-:o-42-1d-0w-,S-,H-$`tktQsZqpq#aDNWJ^E=D~@p?|;k;,7G/o",
            "gai": "-:n-9w-6e-+u-+t|'uYm@dy^AW%T`QYNaHZGNGM:M8|'{&6!,",
            "chou": "-:m-:l-8m-5_-4=-2A-(m~{t/r!iKhld$b3aS_%[_Y%W~N?N=LJJkI|E?B_0h/O.s.p&3&!%l#v!m",
            "zhuan": "-:k-7o-3G-3+-2y-.I-)n-%+~EzRyPreq<oXoRc0V28t5%)5(f'.",
            "qie": "-:j-7Q-/`-+P-*@-#uw1u{iCcpbkaia8`fZoOZL]I~>;<`,E%g#(",
            "ju": "-:j-:?-9m-7n-62-5`-5S-4x-4j-2l-19-0%-.Z-.:-,.-+n-)H-'d-$|{/ztx_uct_tNt$o{nvnqnOnMmqmil`jYj9j7g+e%d<d3d(an`}_E^j];[I[C[;Z^Z@YdY$XMUdUVR3M^M9KxJyI{IzIrHSHDF:EcDPDCC8AqAi?b?L?(>:<g<I;[:o7)4L3o3<30/4/..P.A*e)m%5",
            "pi": "-:i-8@-7|-7P-2Z-.R-.9-+>-(h-(c-%5-!.-!,~|~X}2|L{2xhvCs<rwnumblFk7hWcibx_U]G[q[eXcUgS+OXN3N2HPB&B%<@8>7*6e4n2x.Q.G,n)Q'(%k%h%@$p#R!U",
            "shi": "-:h-:g-9q-9l-9N-9M-8t-8_-7R-6k-6]-1X-0m-,^-,:-+_-+6-++-*>-);-()-'{-',-%.-#t-#7-!W-!>{>z|y{x<wQvqunu<r4pbpap[pVpMp*oun~ninhm;m7l0l/kQi{iuiQg!f}f|eCdodTc_c[aU^*[.ZyXYS6RXRUQ{QzQhMWLxLrLlL5HiH[H,ELBiAJ>n=}:{:s:W:5:'9v7C7?6n4=4%28.3.+.#,0)$&3$}",
            "qiu": "-:f-:^-8m-6#-)u-)9-&+~*|FyTsQl4j2j1cFc&]rWkO%KIHeF8BpAn@s@b?J=o;^:l:k:j2D/T.k+D*'([!P!(",
            "bing": "-:e-:W-8h-8b-6u-5B-4T-3Y-1;-0a-0[{mp1ngnZhbhah&cm[vY,W5R0QpN/MQLQLLJnJbGXE:@~4E)r%,",
            "ye": "-:d-9z-9.-9&-4e-2_-0U-)7-(u-'%-$W-#,-!]{:zIxqxdwgoVm$jxjw[hZzZ!YyY;X:X6UhUcUUUSURQUPxP@P?P,OmOkMYMXIQHsHpCXBh>i<o8q7w753l3M2N1H0M0,0)).(T'b$V!a",
            "cong": "-:c-8f-+r-)K}w}ptPq6eUeTeReJdZcnbUbIa3`^`.PTMxJ`HyG2FgF[D?<G9!8v8L8D8#5V3+1n0H)X(e(a",
            "dong": "-:b-6R-4n-3,-0`-0P-0>-,u-,G-,/-'I|/{)y&u^tXr*mSm>lKl?eNc3_H^LZhX<QrNILfJGA8A+>L<j:n4#18.0",
            "si": "-:a-9B-7T-7R-7N-6H-5f-5X-4,-3y-2+-1[-03-*#-)x-)5-'F-#m-!u-!M~)ugtdsJqDoaj.gUd%cHa2VMSDNOMeL{J~I/H!C'@X?O?8?*>^>J=,7[6?1</R",
            "cheng": "-:`-:%-:$-68-4_-2z-0K-0C-(@{H{A{,zYz#ywu*pSlth%eZb^al`(_v^t^U]A[zZFYPXDWQW,VRVQVFQJQ)N}MnLtJPJ@IyF=F<F9EeETA!?0>e=_=G<8:?7f7d6/05/f*6*2)c%x!'",
            "diu": "-:_-:[",
            "liang": "-:]-:Y-9)-5x-5[-5>-5%-1G-0B-&J-%y-%7-$Ly2bWY7Q*KJIwG%<e:_",
            "you": "-:Z-9#-7w-7=-7'-6X-4;-2*-0t-*p-)f-)c-):-'~-&u-&>~n}bvRuAq=pZo8o6m1lyh[hZh(d]d$c|cqbY`,^xXkTaS4OVM;LAKGK=H{GFD}DJ@8@(?V?>=g;C:b976B/j/i/O.b.D,?,>+Z+Q&g&d%O%!",
            "yan": "-:X-9d-5]-4]-4O-3;-1u-1Z-1Y-.a-.[-+:-*O-*F-*/-*$-){-)z-'%-&=-&2-%'-$N-$G-!L~~~a~Q~5{GzAydy7xLx@wMw>vPv>uFu@titfrgr?r9qwqfqWpKmhlEl'kuktk0jUjKjJjIjGg<g*f'f&c$a7_5^~^8]w]?Y3Y'XhXPT3R8QZQ.P`P/O}OrJsJ<IFIEI5FeF'E^E.D`D3C_BhBG@,?P>M<V<&;K;D:i:H9R8y8S5O5I56544k4j3u3X3J3B3?3!2~2U1t1E140Q/U,w,g,d*Q*()V'$!3",
            "sang": "-:V-$J-#}WgK{KzGV",
            "gun": "-:Ub6JY9W93",
            "jiu": "-:T-:8-:7-9|-9v-5A-2p-.H-+|-+e-+]-+A-*(-'U-$wvdo(gogdgc`IZ2XkXBXAW9TGRhO#NTM+LsKwFxD;BW@v@Q5$/b+:%X",
            "ge": "-:S-9Q-8R-7!-6|-59-.O-+l-)(-)$-(e-(D-'4-&Y-&?-#s-#`-#J}6yhfLaO^^^R^=]_ZkX*WHULTML4GsE!CW9l9`/T.f,C+k%Y!,",
            "ya": "-:R-9>-9<-9:-7m-5K-0W-.$-*H-*G-*A-*?-(s-(H-&n-&'-%;}L}@}9{j{5zbxTuBu3t%q2n,lVlUhKh?[`[ZZZY:XLN'KlIsIFA0A,<r9,8//g.^,[,E+/)}'b%h%J$x$K",
            "pan": "-:Q-0S-/B-)R|Ys3i1[O[AW]U=MMGu?t>}>k:c9s84684l0$/w&C&/&,!*",
            "zhong": "-:P-8A-83-7x-4Z-0j-/C-$Tz8ysx$vMvHs^o)i)eqe0dddYS`MKC2@=?G4w2k.T$F!>",
            "jie": "-:N-8i-8<-5$-4~-4W-4!-3j-2]-/@-/?-/)-,r-,a-*j-*i-(e-&c-%d-%H-$m-$8-#q~zzKz7vevOuit>sasVsCs(qSpIoJnpnln*m|lCkvkbjrjqjgjbhihIeEbr^S^;]_[,YZY+X{XwX?W_UmUOUJS9RINXNJL0KxKoI~I1HqHgHfH8EOB,>j>;:z9b882?/'.6+0)H)8&K&J%g%]%M%##D!~",
            "feng": "-:M-8:-5L-4N-2Y-0]-0&-0!-/{-/y-%p{Rz9z5w}w9v7odoYl}l|l5W4MkKPI.E[?m?h=S;Y;#:R8e5Z4i3V3*2g1h/1,O)u%C$B",
            "guan": "-:L-58-1=-0l-*vphb@b?af`LXqW*SRJ+G*D(B2>w<v<W8G5Q0E)W(4'e$_$0#Y",
            "kuang": "-:L-22-0V-,b-+V-+N-*v-&o}&xNwFm_dJcW^z^y]>RWQkP#L)?N>=0X.X.U",
            "chuan": "-:K-7o-3G-2t-.K-$]}Tz3jFjDPMIRIDCbA?@i,H+<)7",
            "chan": "-:J-91-2y-2R-1~-1/-/:-.k-.J-.*-*~-%$-$F-!n~P~@xBszr>q3l>kJkCkBjXh{hpgWdu^r^lXsX+W;VqVhU#S9RYJsJXDEB#=v:^967o7n71655d5B2V1I,#&v&u",
            "lin": "-:I-9U-2g-0e-00-0/-)v-(l-%PxDlbk,gIgHc=bob)_=_6[MVGS?Q+PGN!FIEmED<U7j7H5h3819+u)S(I'+%o$Z#M#K",
            "zhuo": "-:H-4t-.`-.<-+#-)X-%U-%T-!G}+y@v,tYeu[BZ,Y~V3UxU[StSHSESBSAS>Q>L#JuJfJ3J,IoGcDh@j=|=h<b<J7%6S5[4}4N3_3#1>.h)e)N",
            "zhu": "-:G-:B-9]-7d-7G-7?-6Z-.&-,t-,n-#T-!z~4|=xpx3qVq!ploNnWnIl*i>[[[WT&StS;OqO1O0O.N>M#LzLFGWFmF,DhDbD^D0BH?&>Q;b7t7Z6s5x5>4V4A3y2^2@1+0x0?,K*K%B$J",
            "ba": "-:F-8l-7`-1E-)^-)@-(b-&M-&I|_{[x>wCv0mumIj,fq]o]I]6]#[GZ)O+M'D,5?4R0+.m+@%N#/#!",
            "dan": "-:D-8~-7{-7H-2r-2J-/V-,,-+G-*~-*{-'f-&2-%C-%B-$v-$F-!m-!b~[vTsjiofTfOfEb$aga>_q_P]4[VXuV@V?UjRiM/BeBSA*@)>r<?7.1I.@+#'O''%f%:$H#`#N!F",
            "wei": "-:C-8{-7p-7e-7A-4s-4V-4Q-3~-2x-2$-*h-*b-*O-)O-'q-%q-%k-$s-$S-$@~.}o}m}S}7y1xJueu7u$snsUsHoqoQnxn_m9m2lHl7kskZk=jljTiniEi9gme=e:avaPaM`?_JYnYUXbX1VEV1S^PuO5L*JqIOINHkD@?g>c>C=n=$;S;N;0:N:08?837i6R6G5|4]4>4$2]2O2F1]0u02/$.r,[,P,I*~)h);'f&H%!$N#X#U",
            "jing": "-:A-9C-9+-9'-5r-5%-3A-2O-1N-0K-0C-/9-.~-,y-,k-,[|i|g|cyIvQt:t8t+pojAh|fdfZeeeWb/___NUoT+S&S%Q:Q3PIP0KZJpEvBsBn@I@H>m>%=><87]6#,r,'(^(B(<%($u",
            "li": "-:@-6_-5u-5k-5Z-3s-2&-1z-08-/Q-/=-.o-.G-.'-.%-,l-,&-*L-*I-*:-*.-*!-)|-)Z-)X-(z-(2-&U-&0-%g-$C~g~`~A~>|`yrxEu+tat#rjqYq,nAmkm5m.lzjag@b]bXbRbB`l^&]q]gWYU@U3TsTlSpP_P>P%O&NmN^MqMSLnLcLYLUK!JoJdJMG1ECDuDjD_D8D.C/C+?k?[?Z=Y=U=/:/8z7@6C6$5H0a0U/>/=/#.z,~,u*V*$)z(t(_'x'u'l'W%R%F$l#P#A!Y",
            "pie": "-:>rVV]V[PHAD8>",
            "fu": "-:=-9c-8[-8#-7z-73-5y-5m-5j-5U-46-3v-0d-/|-/J-.R-+h-(=-(6-'[-'S-&E-!s|<|!{]wvwWvVvRuru'tDt,sbr5qJq/pmp3oWmgmFi~ifi7hzh;fwfkeje?c{ct^w]l]J]&]%[Y[QZ+YfV7S}SLS)ORN+M]MGM)M'L1KWJ2IYIPHKA:>~>Y=W<w9c7T4S3d3/0.+2*t*!()&m&b&N&G&@#h!)",
            "nai": "-::-6v-4iw:vhv)qxq(g6WVV{M$AC;<%`",
            "wu": "-:9-:1-9D-97-8>-8%-6;-5|-4k-2k-2:-1q-.T-,|-,C-+y-+/-*V-(U-(T-(J-(?-(+-&)-%K-#v}4|^zLykxvvxv4u%tjthsurTownkn9n+lmkzk_j6hFgQfudbd`d@c'b[bZbKat_]^[]e]d]]Z4WGTTS7RoROQENvNtNoM&K#FLCVC=B3@[@Z@S?{>T>*=V;^:,874(3C322*1w/V/A+3*4*3(|(P')$h",
            "tuo": "-:6-8X-77-6h-6.-'a-'G-%[-%$|Sz;v8sNrRmck'gzet]i]`[H[F[EZMYuV1NgN^MTM8ITI+GbFBF0AvA_@d?`?_?^<k.K",
            "zhe": "-:6-9[-*K-&L-%9-$o-#T~h{Er^bp`6]H]'W_ViQGQFNgM=JWFwC%=m<E",
            "ma": "-:5-9Q-3o-(r-&!-$%-#4-#3vUs1rWqNhR[cVzNQH2:2/&.c,4+5(x$[$Z",
            "me": "-:5~t~j~UhR6I",
            "yao": "-:5-:,-8;-6D-5@-4?-3_-2q-+m-)&-'7-$b-$2{}zBwUvGu_svs=pro3o,n/m,l,k#j~h^e;e.cqcRa%[oX2WrW@VdV$PkP'NGN#LuI;HBH9G5C!BA:B9J444&1|0f0(.E,;+r*D(~(l%S$%!t",
            "zhi": "-:2-9Y-6f-5^-5C-4|-4d-44-3y-2,-/}-/0-.U-.+-,v-*e-*>-)C-(W-'v-'8|||{|T|:z~z{yFy@x$v%uNtsrGp&m7l0j+iridiahyh5h3ggf5eYeKe4e3dmdUcU`6`*_$^{^E]Y]F]E[u[HZtZpZ]Y{XvWpWVW2V{VvVtUKUJU>TjSMRwRgQ`Q/NOMyMcM2LqLhL6K~K7JjIuI]I*H+GHF_D|DnCAC6BiAJ@t@O@N?v?T?3>V>3<L<!9e9S9B8}8@7~6>4`1_/9,x,^(R'w'[&3%c%;%7${$z$k$E",
            "zha": "-:0-48-.N-.=-*C-(w-'X-'?-&K-$j-$O-$Aw/pNd6]s[m[XZdX4WIW#O2M7M1M0LvLlI?H4Fv;X:67u5#4@2N/p&d%.!M!H",
            "hu": "-:/-:'-9j-9F-5E-0Z-+U-+L-'h-'W-%n-%Z-$_-$4-$1-#>-#2~k}v|;x1x0x,uGt4sEr]r[oxm[iphxfxfgdFd*d)cGa{^V^6^4^3^/^.^,^']y]9[xWWW$SXRFR<OjN(L8I%I$GEGCCR@9@&?f?7=t<.<+;$9E99986Y5s483S2;1a.J,S)b)+']'['I",
            "fa": "-:.-8!-6y-3Z-0R-)]|A{vy)uwm4fKL@FO?X?:=z5R*[)L%8#.#+",
            "le": "-:,-9R-8r-,J-)2-#1d}]qH`G5@z??/b+A",
            "yue": "-:,-1g-1e-1`-/P-&j-&@-%A-!DvAqrn1m^jec,bubS^]]g]8Y_U@OpOoOWN8LcH`G5FTDj?'5e0J+*",
            "lao": "-:,-6~-3!-,j-,i-,>-'$-&N-%z-#p-!}uSr`ljk/cY_f_eYtVZO:L=G5F!=O='8%7a3{/^./*<$f#c",
            "yin": "-:+-7}-6^-0t-0;-*c-(j-(V-%o-$d-!T-!+~l~+~$}`}$|&{w{YzXz:w_u=t0t&p:n}lnlLl<jdg^g>fya@`i`B_u_t_0SMO[L:KKEkE@E1DKCwC_BYBGA5>l>d>U<5;~:}:i9}9V6^6]4).],|,j*I(U$7#k#_#:",
            "ping": "-:*-5i-0]-/z-/s-'u|Qz1u/ngnZmTi[iJi4heh&`0_zMfEU?6>6=A<D3)*v'F';&_",
            "pang": "-:)-*B-#ww}r|o2h9h*ere<S2@<?y9p4i",
            "guai": "-:&-)_wVcuc>[KMbLw",
            "sheng": "-:%-:$-4H-.X-.Q-,?-+0-(9}=x{x7u*k}_VS[RGQJQIOeMuIyG~E{BzBF?%;k;@:q7G2u/M.N*h)i&y&s&`!'",
            "hao": "-:!-65-3k-2)-)6-'j-&_-#k-!t-!Y-!#~xxRvacOblRDR'QBPePaPWP7J!A~Ao=]<Q9j9U7S6c5N5@,/,)+}!y!q!h!f!c!_",
            "mie": "-9}-),-':-&Hq7hk^uWeDr9m64504!",
            "nie": "-9}-%*-#e-!O~m~D~5~2}#q'q&mFkTjujLivZ&YVY5X[WCVsT|T<MVG@DW=@:Z%+",
            "xi": "-9y-6&-5l-3i-3#-1B-0,-+?-+*-*n-*R-(P-'x-'>-'6-&/-%]-$X-$:-!p-![~T~8y?xWwnw'tgs;rCr@nsncn`nRnHkgk9jpj`jZiqiOeceOe9djd_dEcscgcZcKc/bqbeb8ay`r`p_s_r^V^6^4^3]_]O]HW%R:QKQ9Q6PEOzNON)MdLZKSIdIGG{GUFkFRE|EjCzCuCmCMCJA4@e>X>S=f<[;i:+9h9)8p8/8,7N3e3R3K343&2Y2+2)2%1q1P1O1N0}0P/E/?/*.{.t.#+p*r)|(#'h$1!k",
            "xiang": "-9x-9,-9(-6}-3*-1}-,4-,$-*0-(x-&r-%L~Ww~uXk5j)h7gqe'abQXP5LWH^F1DH;!8:*E'g'T",
            "shu": "-9s-61-5g-55-54-1|-1F-)Y-'3yNyGu[tGq4oNoCnWnIg}gxdWchcgcIbt^X].Z.Z#Y>WBU9T'S|PvPtP*OhO1O0O.N[NBMtL`JtFuFYEpBuBKAaA`?c<O8[8H7m7Z6m5q3Q1k)f(i('%h%e%d#O",
            "dou": "-9r-61-1T-1P-(~-(N-&&-%|])S]SPN&J}EwAm=d;n6<.$$v",
            "nang": "-9o-1s~d~;~1_QWwU{TkOwD+<n5b5;",
            "jia": "-9n-8<-7Q-6w-4X-3X-2]-,}-)S-&?-&4-#F|}{MwIwDsrs,pvpImei,e[eBd^cA^J^G]L[d[Z[,ZWZ8UhSYSVM`M_K/ILHNH:G^ENAz?H>&=L/3,E,B*n*d&f%0$8",
            "mao": "-9k-1,-1(-0|-0z-*dzLwksLmOkzi?a=_?^(S/QvPrN4M@I'B!AcAW?9;F/Y/#,J)E#$",
            "mai": "-9i-7I-,{-,*-*}-#${Kx5",
            "luan": "-9h-9Y-9V-*^}C}Bvmu0qXq:q$m)jOZ[TvOuL2D69K5J59#4#3",
            "ru": "-9f-6K-2C-1K-(N-#{-!$vkv[s7qyq)jciX]kZgUTP+NzL(E0@W>7;Q9u6b+^",
            "xue": "-9e-.x-(Q-!9|Bxbq>q+mmmMjzf=ckT/SlKvFc?!>u9j7>5y1&.B%L%<",
            "sha": "-9b-4c-3?-2H-/,-.t-*+-%t-%^-%H-%4-$R-$0iCgkZEZDW<N{NrK`H?FlCaC3BDAl?w6{2P,v$g",
            "na": "-9a-1*-*|-(R-(8-&T-#_v=tx]0[LZxZgYWWL",
            "qian": "-9`-9Z-9W-8T-8B-7l-7(-5q-4w-4^-3g-31-2<-/r-/[-.u-+4-)}-&4-#u}/}.zaySy4xZvgt7seqtq`q5n'n!k{kVdObgbLaN`f`<]Z]N[J[1ZCYLY=Y!X7WSVgVbVUU,U+U)O_NwJ_IbH3GiGPF%E7DzD'C~CeCZC7@]@M>$<%81806O5S4B2Z/J/B/2+%!l",
            "suo": "-9_-9=-3]-&8-%x-$&-#j-#gu&s(as^$ZEZDW:PjKaJz:E9y+|)w)v)!(]",
            "gan": "-9Z-8S-7J-5&-0=-/u-'c|Ro'o%o#o!hfh_dqa5U~T]T6R_NuMDKLH6FNEd@??;<:8f7_7/55+;*w'#%?!T",
            "gui": "-9X-6q-3{-/(-/&-.7-.5-+Q-+J-+I-+F-*%}3{zv2u;s?rhrIp|k$jpj`iLhLh,gmf;cMVxVVTiThRCQ2O%M9L.KeIeI`GTGAG<G;FWEQE)DXDQC*@v;;:H4t,Q*A(r(D'q#X#0!|",
            "jue": "-9S-50-3f-0X-/R-.?-+@-*,-)X-(Q-!a-!R-!9~I{PxbvAqRqQnLnJlPl@k$j}fmf>_k_Z^b]7Z`Y~Y9V^V;TnSgKTF7F6D[CvAG@:?!5P2|1d1>0S0G000/+z+M+)+'*](n(G%L$3",
            "liao": "-9R-2|-!rrLovomo<o5o4nKkLk+k*g]gG`/_^W9VaV9S{SZPLO~FxFA8Q8%4f1;0V0R+q(H%[#g",
            "er": "-9L-6v-6T-1r-1a-1_-/1-'B-%hoHoGoFmAg$f~NiLCLBK6FaAt>[>90%*F",
            "chu": "-9K-5N-3d-3R-2K-2!-0$-/m-/Y-/I-,t-*)-!o{$x!s>n5hjgXcj`g_SWxW$VoTNS=NEIjI&HoHQF|E}EsESE#DsDdCzCG?@9r9q6x4N/+*+(,&;",
            "kui": "-9I-3{-/4-+I-+F-$U-$;-!xwow4s/rBo*mQjVjHb]a.a,_y^BXgQdPyI2I0E&BV:S7x2l.q!/",
            "yun": "-9G-7r-3q-1p-+}-+x-(0-&^-$^}xwEvsvEqOb}aca4a)`c]2[yRNQTP}MwHWF@BmBaA&A%@0=3=!:!7W2h2:202(2$1b.Y+(&P",
            "sui": "-9A-5#-&F-#U{3wytvr1nwn4kpRqEWC1C0Ab=H9[7+6z5}2C1g0~(/'p",
            "gen": "-9@-9?-&pX=X'L7",
            "xie": "-9=-9!-7[-4J-4A-4/-39-1{-0s-0c-,w-,+-+'-+!-*k-*Z-)7-$(-!C~e{ry_wrw8w1u)sOq]opnenVnNm$jrgJeFcT`z`p_BZ~ZWZ8X9WnWMV*UiUFT}SWRePXMZLIK@JwI,HOH?H/FlC]?K>p>A;P9h7B695{5!4Q4P3b3E2,0w0s0O,C+k+e)8",
            "zhai": "-9;-6B-4f-4*-3E-*K-*C-&c~zw{p{os[u[2YxW/UwU>SiSfH#EL#t",
            "tou": "-98-4'-4&{$wNv'sqs@aK]*T0SQ",
            "wang": "-97-8v-87-1JvYo7o1o0o/eoeiefe[dldJa}]>RTQ(OEODO=N1JD@J6;+E",
            "kang": "-96-8)-+X}|rmkKg|dG`8]f](G=8_4d.a",
            "da": "-95-.N-+f-'f-'R-&m-#~-!J{hxrw[v*d'ag_q]nWZVJ@f?}:<4Y0p&@&4$#",
            "jiao": "-94-6n-6D-2q-2j-2I-.B-.6-,6-)B-(<-$H-#M-#K-#?-#(-!^-!=~IuUu1r=r6qcm+m(k1k%k!e.e+cJbl_~_i_KZjZTZ5X&W9VlVCV(ToTJT?T,SwSuSgSSQbPgP2LOIpG!>!:l:k9Y8w8<7b5[5C443,2b1>1*.9+l*X(5#e!v!^!V",
            "hai": "-93-'V-'0-$#-#h~ey]vOq;pL[!A3=N3[,C",
            "heng": "-90-&B-%QuJcXcLbaVKL/FiF&<|42*B",
            "peng": "-90-5,-3J-.F-+o-!~zgyqyYfUe|cyc+`%[tZ?Z6YkXpWvW4OTKCJLIlIWGGFn?6<R<D8e8]7Y3Z1h$a!u",
            "mu": "-9/-8H-/~-,=|Ey9usuSu%m<i&i!`[`Z[TPVPUO7O'I(FrFqB1AwApAX@#4h/a/_/X/L.S&U&Q&E&:&9&(",
            "ting": "-9*-68-60-4C-*M-*7-(]}>t}sxk~hVhJh)gBg?g;dzZ<K]KHH~H(@u=6;]6u453`3^*.&^&[",
            "qin": "-9%-64-1^-,8-(g-(f-&#-#f-!Q|w{Fshs.p.p(o~oyogkmkVk2k)hOgbdO`C_G_F]N]5YlX,X$V/UlS@R=J|E`Cg@3:$7'6(*J)R)M#l",
            "qing": "-9%-4b-3<-2(-0A-.b-,O-*S-%1}V{1wfp7hQgwgeb4`9YLUpUoQ5PsJ'G/EME/DcBnBFA7A.A(<';w;B916X&x",
            "bo": "-9$-8Q-7`-73-6,-2v-2f-.e-.]-,Y-*y-*w-&M-%#-!h~oxbq*k3ibeu`s^|[3ZJWyV=V5UgUfMFM'KYHKEVEUDFBj?E?,=e;};W:L2//l.?,9*q'`'^#2#1!Y!8",
            "lian": "-8}-34-.;-+E-+D-#V-!XzUwAvusMrKr/iegjd&cS`F_{^fW.T=SrJhI#GiGSE7DfCHBlBP=%;6:C8j8A777$6p5p5l4<2f1y0z)x)3(X",
            "duo": "-8|-8X-02-/2-/$-.c-.V-'`-&y-&e-$O~}~S{|{{z}z]xzxywiwhwHvtvlsNo+lOh1ae_oZrZqYJTET>T8T.O)O(NfN^MrMTMSM&KuIRAh?`?^&D$i",
            "men": "-8{-8G-53d8bcbCaz_9_&]VYgS^PZIh@>3=1,+((W",
            "ren": "-8z-8y-8s-8U-8F-88-/d-/cx;vSu`n:n2d|dwdv]XO,NiLPLMK6J7/]",
            "shen": "-8t-7V-6i-6/-5d-1Q-)l-)k-)j-)i-(V-'i-&}z^u|u>ttsys.qmp_pHorn7lui(fp`t`b]b]4WPTFR4P9P3M:J7J(IHHRA9@+=D<0</;f;e9?671?*g&~&w&q&e$G#{",
            "ze": "-8p-6B-4*-/M-.{-'X-%d-%2-%.-#9rcl:iAi#hU[~[2Z$UwRKR7G)C.@q?n?A>n:(9U7C5[!e",
            "jin": "-8o-8j-8d-7}-6<-35-2^-2=-01-,y-,k-,[-*X-*'-%o-!F~y{Fzkz6y<xPvFt7rfr9q~p(nyj'j!gbb+`CWfSOQaQ_N7HEG8CTB[>E=q=M:I9$6~6g3h2M0i*Y)y)K(z(d(@(*",
            "pu": "-8n-3$-+k-!S}^}O}<{BzPy(]p[rY{V0UvTeTdQ;PiPPP&O*M,FZE_AS=`:17k6T614r3a+v(C$m",
            "reng": "-8g]m",
            "zong": "-8f-5:-4y-43-3KzFpikxkrkNeJcdaraVY^XXX(W&Q|O>MxJQIKG28L8D8#3+1n1c0{,b,R%E#w",
            "fo": "-8e-8;-73|IJl",
            "lun": "-8c-7i-6S-4u}l}Y{.t*lSlRb9[{YMJa?j<6:3",
            "cang": "-8a-89-7h-5;-3e-07-+OkeD<?i9n6J,**{(p",
            "zi": "-8`-4m-17-.h-)%-(W-'t-'r-';-%@-#r-#cupuoudu9qTqNqMqHq1q.l;k[c;NnLKK8InH=Ez?s>W<];o:Y9g9_8a7;/G+J(!&Y&7",
            "zai": "-8`-3V-2G-1!-&v}8pOl.]j]>L3>f;>:.4|4{3~&Y&7",
            "ta": "-8^-6E-3^-#~-!&~Kz$yyy6vep}lc[HZXW`V&HCG}EqA[?}<c:<9w8^7(6w/`.3+d+V",
            "xian": "-8Z-8Y-7b-7,-30-2m-2d-2b-1i-0O-)o-'c-'E-'*-&O-&2-%6-#u-#:{`{!ycxXv`v&uKu>u.t`tZs~r~rOrNr9q`pUo;o:nBmylxlhjthhgCfhf+dI_a_X_R_'ZPYQXsWnWiVhVXVSU6U'QlQNPKNFMhGiFFEtDRC~ArA@>S=E=7:]:C7Q6*574*0l.=,s,G+f+c+U+O*|*s*T*,'3$c#b#Z",
            "cha": "-8X-6Q-4D-/,-.t-)e-$A-$$~s{yvbu?o|m}kqj3]a]OZ7Z.XZX5WJW1NsM0LvK?I?GjEB@k,<%s",
            "hong": "-8W-)w-).-(X-(K-(;-&{-%}-$)~i{kvXu6pqpjn=j[fvfBa*``XeVNQ[@E?y?<>@=b=S;J;B:R8J7U5(3|31+>+4'T",
            "tong": "-8V-7/-6R-4Z-2h-,/-(}-&|-#Z}o|/mNm>m3h:f(c%`P`)Z1Q]P<O<K|KUG+F+AV=P7l4C4#18.~.0+s%%$s",
            "dai": "-8P-6G-3W-)g-(B-(4|3{(w[m`ikiViMiFg[edd!_/^1PAMJJCC)ByB+5c,2*y)?'!",
            "ling": "-8O-7X-0?-/D-)G-(#}h|>wwuqtKqdmdmVlQjhekY<R)OQMRJeJ5DND)?/<77=5'4O0v0=.I*z){'H!z",
            "chao": "-8M-8D-.B-.6-,6-(S-!yjQj?j>ffd9]<VlQiOBGFG!C{9+7z4g303#22/v",
            "chang": "-8L-8J-7j-5D-5+-5!-3|-2~-26-1b-*P-)~-%i-#8~v}%z=yZtWrdo=iDgReLd>bDaxT:RBQtPcIiAT<T<P2t,`+6)^)4(h'B&z&R%w",
            "sa": "-8K-+2W<VPU:Dw?'>X7s5L",
            "fan": "-8E-0)-0(-0'-,1-+R-)a-!hy%v_tDr;r:iwhwdi_h]l[ARvRtNpMLKXJrJAG,FD@w@g?4955t5_3n2E15.l.[(A&O&/&,!.",
            "miao": "-8D-,m-)v-$?vDscrPh>gtgSX^NP<#;A+K",
            "yang": "-8C-7<-6{-3[-15-,f-,@-*g-'Z|J{xwTukswmrl6l3e`d4cEaA`m^}]T[lXRU<T*RVR2PmNRMHL9I7HvG`FpB|A=A2A'>z>`8N6A4y4D4.2B+6*O)4%Q$|$@#F",
            "ang": "-8C-*gn.RLQoN0!5",
            "wo": "-8?-4s-4L-*l-(/-'&-%q-$atCtBsfi8^TZYYbYSXKV#SRN8I>@1=#<m<h;V;U7!6`3.,N'|",
            "jian": "-8=-6J-5W-5P-4g-4:-3g-2s-2i-2L-14-0L-0<-.q-._-.W-.P-.4-.3-./-.,~6~'|bzmzaz2xovfuRuQp4oDiHhcg8fNfHeDaq^Z^Q^<^9[8Z>YqXmXjX7WmV!UGU'R{PpO_MoM(LEK3JgIfIJICI)HEG]FhFCEKE2DLC&BMBLA]>a>$<z;l;a;&;%:Q8T7P6H625k5f5a2a1l1Q/u/Q/2,g+%*W)<)6!2",
            "fen": "-86-3}-2n-/a-(`|v|q|]xuw7vpv;n&ithog,dDa0_gR>OYOSN.K&J*J)F)A>@66}5i4v391=16+{+.",
            "bin": "-86-3S-2EpAe}W?UNShJnImGXE:B^BO@r9I6q6Q6M6,+.(j((",
            "di": "-85-7@-5a-4F-3:-*D-'}-&t-&$-%R-%&-#O-!(}0|h|d|@{Q{L{8zMyFy;x|w?tqsmrimUkIjoi`hBg:fofjeld#`7]g[g[=YFX]XGW2TLT!R[NfN(MrM3KAK:JCHiG7AI=g<};T9f9=3F/K.V+=*5'1%c##",
            "fang": "-84-4}-+^|r{Qzcv5er^%TZS:S(RER6N/@<<M/Z'P",
            "pei": "-81-7$-5o-'lzyvZvCuCtOs_k7iid7[eU5S5S,M'LyJUAj?u=F<@.`*=)d",
            "diao": "-8/-0@-/f-/G-)1-)!w$njfzfYe~]gYHI|@m)U#p!?",
            "dun": "-8.-(a-!2}}|sy!x~x}hNdPb2_mVYV.T2HnF>@'8*4c1@/!+m",
            "wen": "-8,-/X-(M-(C-(&-%Jy`vNf)dfde]:X.WRSmQsKNHWH)C$B`@>;z;R:*4s+1*8(}(&$;$.",
            "xin": "-8*-7f-5d-5G-!3-!0~%v<r,qFgTe$e#dHawa>SCR9N@N%D$C^4a3$",
            "ai": "-8&-2W-09-)h-'!-&q-&5-%Y-$'-#]-#E-!;{SzIyfxUtgtUrxr'kaa9_7_,ZNYaT&T$QqP^P.CxClB.:%9t6U3.03(k(;#]!s!j!]",
            "xiu": "-7~-5c-5V-''-$/~|p@mfmPh2N~G09~9F8I4+*P*#(N",
            "xu": "-7~-7Y-6Y-6!-49-0x-,F-,E-*Y-)T-)+-'p-$e-$Q-#7-!o-!W}7{Wy,x+v&uxspsArFhHeXckcKc:b(`g^YY4XMTKT@RbRZR!QcP{O^OOLGI9GfC|CtCiCOCKBw@5@4>?=t<>;+;):P9r998W8B433W2H0m+t*N*?&;%T",
            "tang": "-7y-5+-4M-3l-3U-1v-.2-&.-${-#.|XzpyukdilaA^cW^V~OsJFH%F{F<@P<T:h:G8n5D3i23100A(u",
            "huo": "-7v-6r-5T-.Y-.1-(p-'W-'D-$e-!%~V~Fw^vouWf.f,b'^OZ/Y4UPU4RkO|E9@%>/:f8U6y6Y6+525127+_#@",
            "hui": "-7u-7#-2u-1{-+H-+.-'/-&j-$[-#=-!f-!U-!D~p~,~&}u}Fz]xztEsgr7q]onn?n>i*gmg7g5f6f4f3e,e*cDcCc<c(bfau`H_x^sZ|ZQX>VEQSQCP|PQO]KeIOI3GRF4EiEZEQDqBVB>B=B7@n?D>h>g=y;+:S9X897x796y6:5,5)3t3q3k2h0y0q+h*9)G(=(2$~$)",
            "kuai": "-7u-6@-2M-/p-&f-!8}:|ez&y'jEgMdXUkRrO]Cq=y79.*+g(2",
            "cui": "-7s-5?-3N-04-%I-%>y8lYlWkhdSbE`TV|IxH*GHAg<48P6a331g)p(b%I$L!d",
            "che": "-7n-5`-4I-,%-'y-&*|?vln|nGene/]QY.XcVsV>V<7`3r3b3E0C",
            "chen": "-7h-4_-3e-2'-#|~ZyWyAw]pGoBdRa>[aY]THS~QAP$L[K_K'J(HUG3D]@+@*2n05)l%P$?$$",
            "xun": "-7g-6O-4.-,Q-,A-,)-,(-+5-'3-!k-!P~u|y{=yixYxAw#uHqKq9o`oOmEj@j&j#g=ebe>c]`uXUTfRcP(NqL_KbF`BvB@Au@Y>5=r=l8+7y6V583O2h1{1D130j0Y0Q.5+b*H(L&T",
            "chi": "-7c-7M-6b-6P-5E-3@-,W-,K-+_-*]-)<-)3-))-(:-&W-$z-$I-#l-!g-!=|@|)yLw/vBs6n|fsf$eweve6cBc9`X`7_|_2]`[f[!ZvZ/W+TxTCSNNcMPM3G1ChC6C4BX@T?Y;:8g4~4;3U1K.O'A$Y$U$E$2#G",
            "xuan": "-7b-2N-/.-)o-)'-'(-$Y-$Mz)wsv&sWrqr.p]f[cobMaQaI_I^nX_SyS'RAR,QeQ$Q#PNK@HxHwEf?#;I8d4M3x2e+L*s*)*&)B(Z'~%/#E#<",
            "nu": "-7a-3r-,svjq?ilfed1Wo",
            "bai": "-7`-6z-(1-&:hJ[?[>ZwYeX}WAUfUCTAMFLN,n'D#*#)",
            "gu": "-7_-3T-2e-0F-)I-'s-'N-&<-&;-%G-#y-#@}gzfx#uhrUq@o&lXl=j5j4d*`~]_]9TSNaM.K<JIHFGzF$D{B<@K?R?=<X6P6./P/@$Q!L!G",
            "ni": "-7^-7]-7.-4v-2>-27-+8-(%|Nzsznv/v)t<rkqkq0nznbnEcvb5`{_,]0[i[<Y5UQS$QuQ7PSMPJ&E6@y?)<=9x6o.F,l%b",
            "ban": "-7Z-.!-+,|z|Yutn0d2]R]M[OW]W[T[ScSbRJOSN;MM:c/x*>'Y'R$*#[",
            "zhou": "-7W-6M-2X-0{-'|-'z-'Q-'5-%X-$i-!G~{v.t/pgjCiceIY%QnQLQ<I|>8<S494'*S'9%W!R!I",
            "qu": "-7U-7E-7+-/H-,q-+S-+=-+7-)t-)s-)W-'e|Vt^nnm{m]k?e%`&^0[^SzSIOnOOD=D4CzAL>)<3;[5U3G2o0D(K(8#9",
            "ci": "-7T-7B-6m-47-17-/+-/'-'t-'r-%@|*q}j3h<`hN|MILHD&C??56Z*p*k'E'6%=!{",
            "beng": "-7S-#w-#+{R{#zgyXw!lBkYX0>v)d)[',&k&j$a",
            "ga": "-7Q-'M-#A-#/-!4wIwDoEo>o.RaOM+C",
            "dian": "-7K-7:-3m-18-**~M|P{lyBxfw6v~t6t!kXj]jNjMh@ao^!YOTrTWT9I_GqG_FPF5B?<a9k764?*u)s&c&`%1$W$$#L#=#6",
            "tian": "-7K-56-1>-(7-%`ylybwYvit=nodgc2b:Y#WPQ?LSB{?U<A<$;2)g(q(.&}&|&h&`&L&F$W",
            "bi": "-7D-78-73-5F-45-+c-(h-']-&k-%?-#Y|jzVxgwLvnv:u}twt1r3qonrlFi|huhthPgLg'fRfQfJeme!crciaJaF[YT;SqS+OXO!MUM!K;I<HPB)B(B'B$A|Af?x?C:u9Z9D7q6e2`1p.%+y+x*`(:&W&V&G&5%^%H$T$S#'!o",
            "zhao": "-7C-1k-)A-%X-%T-!y|#v+j*]B[@S!Q}P8OBM{J,E*?S6S4T2G0r0:09.7(m!F",
            "shao": "-7C-,p-+~-*a-)A-&Vu,oIf^Z'R|NhM?K(7v3m2s17*m",
            "zuo": "-7>-72-66-4E-'L-&,-#!|lmtmsj;h0d6YTV4R%M7M&)e",
            "ti": "-7;-5N-5'-4R-/!-.n-*;-%H-$y-$3~w~rw?smsPnmnYnVl2foeCe6bnbjb#b!aU^)ZHY*X]XGU>OaONL$JxJCCQB]=0;T8O*5)A'r",
            "zhan": "-7:-4>-2y-*s-!IrQnamRl>l)kCkBk.j|d+b0^M^?^5W|SJSGS0RsMjLiL<KmJ?HLFCDEAyAQAO?Q:|)q!F!4!$",
            "he": "-79-,_-)$-(v-(/-'o-'Y-'W-'&-&R-%<-$Y-$W-$1-#d-!c-!!|,xVuyp6mJb&[jTROiOZMNL8I@CsA^?]<i;M7R3P2m2'2&0k0e.8,C#^!W!<!:!6!1!,",
            "she": "-76-*E-*9w/v|oVfP`_`;^h]'ZyZbYjX:WEWCT|EEDACJ?@=<<f;s9Q5Y,W&*&)&$",
            "die": "-74-)M-'>-&t-%H-$j{szSmDl/kIi3c}cPa`^IZbX:QwP!M2HsGUBcAK?I0*/}/n'_&#%q%j%i",
            "gou": "-71-3p-0y-+z-)H-'p-%W|C{uwdwcuTs0mnfM[CX%VcN6M^Gm?q:925.C*o%2",
            "kou": "-71-0f-.C-,g-)J-)DpCp8fId3]^[|VpTV9@",
            "ning": "-70-6>-4a-29-0.-'H-!)r%q!p2p)p'p!ot[4UMM5F/E5?17J6k.<+a&i",
            "yong": "-7*-5t-3M-,U-,T-'T-$t-$+-!:{Oz!yCxcrlkUg{gAe{ceb{bzapaC`w`n`:[6XTU}M4LaGQ@}>x=9:p947:5T/{/i&p&l%)#S#8",
            "wa": "-7)-/n-,e-(/-'P-'&-&x-%h-%A-#y-#nu5tbt3sGnCije[ZaWUTq>.:;8h'V'D'>&A",
            "ka": "-7&-*r-'O-'M-'4-$u{g",
            "bao": "-7%-5h-21-/>-.e-.]-,!-+{-+s~ozPzOz@sBqBpcpMp$ohoee&d:[w[kPPP1P&M]614J2<0_.u.h*G",
            "huai": "-7#-',|mx^xIe_dC_:^oGhDX<25z",
            "ming": "-6x-0g-06-(|-'guEs&`aXxR@PhOFH<>0:7,8",
            "hen": "-6s-&p-!3eac6[0.:$y",
            "quan": "-6p-1H-/.-.#-,5-,#-%%}X}Q{4w5u:t;q[m?jRf`c0b_b%['Y`WKNxJ:I[H_GLFjD>?F>F:a5841/I/H/7.o.n.m.O)2&I%'",
            "tiao": "-6o-%Xr#pWmjmWh4cRZfSQRdQjOLO'NYK.Fo",
            "xing": "-6j-5.-1<-/U-&g|0{auft{t5qljAh`f*cxb>aZUYR/P4Nl>Z<u9d2d.N,L)@![",
            "kan": "-6g-4G-0r-/r-/]-,D|n{!zGyDlkl)k{b7^D]ELRG]E2CeCc",
            "lai": "-6d-5Y-5<-%_u!t2lil_h$eSeHU2NUJiJ0DT=&<)6r5v5r,i)k%R#P#J#?",
            "kua": "-6a-'.{iwJuGcGZiQcI:",
            "gong": "-6`-6N-1D-1?-,~-+g-+d-)w-%}-$)yepTpQj<j8i2g4f{c1a*``[)[(T^N`L?@V7U1u*R",
            "mi": "-6[-0v-0n-0b-'9-#'yzqZpmpDp9m6i:i.hrfifafAcb^dVnU_TyTON2HIG$E6E+@L?{?Z?C>G<9;H9<8o6o6l5n5G1z0B,a+T'h",
            "an": "-6W-5J-4<-2D-*P-*J-')-%e-$x{b{&z_sYpwn@n8mXm:hXg~ZnXNQ.PnL'L&A1>M.g*w$V",
            "lu": "-6V-33-1C-.H-,N-,<-*q-*o-!N~q~_};|G|5yVyUxMtVmChGgZgFf9f8^7XzW)V)UzUAU/O{MpLeJ#G&FyEuDvDaARAM>s<K<;;p9:9'8.7L6@6)4p1m0T+W+H)Y(Q()'m&n!%",
            "mou": "-6U-,c-)x-($-&azLcVTTMEKs/a",
            "cun": "-6J-/Z-(~x'qLocdn[%Nj7^!O",
            "lv": "-6F-63-4#-38-23-,'-*x-(t-(F-&G|+nTnSnPl(e^`A`5ZcZ*YwS.K*HTDsDoAYA)9M6D3A0]+I",
            "zhen": "-6C-67-4)},ygybuMs*p5ndiUiRi<fc[nZlZGXWWOSTR*OJN$MhLVKjK_IHHuHLHAG_FVBb=~:y:$8$72,+*_*^({(q'8&Z&<%9",
            "ce": "-6B-4*-1%-1#-*=-*2wZgrc!aY_jZ}TQLl={;O&8",
            "chai": "-6?-2@-$h~?j3[UL}.i$'",
            "nong": "-6=-2S-0p-&b-!Eg.ZmZAElDG=s7#0o#W",
            "hou": "-6:-5*-*8-({-(L-(K-'p-$l|%zQi=e]>b._,A$C",
            "jiong": "-69-3'-1.-1$-0}}z|K{;]~]}?M=J7e4t4I3c2T2S1W1.",
            "tui": "-6.-6(-3&y'tmo$ftfodrY(F>24",
            "nan": "-6+-*|-$r~'~#v=tzstrb^e[sXfPqN*M6H}:d29&a&?",
            "xiao": "-6*-5v-5R-3a-.x-,d-'j-'1-&l-&P-$}-$1-#D-#?-#&-!|-!v~c~J~CuUtHqGpPpJoKlGh/fFcJ_iX;V:TPT/SoSnQVQ'P;MiMaLOK+DOCYCLBAB4>B===8<Z8E6!5+5*4,3L2&1L,o+r+o$t$o!i!b",
            "bian": "-6)-+9-*u-)UwzmKg1eAdVaX^#]=XSR#@A@@4Z26/o,@+`+,':%8",
            "pian": "-6)-4P}ysI^#I=Ht/y/0,@+`(j((",
            "cu": "-6%-+$-!csFegd(_YEsB},X$I#z!H",
            "e": "-6$-4K-2k-+j-*T-*N-(_-(E-(*-'A-')-&X-!j-!A}s{nzhzIzCv$uzuBtotUtTtSn]n)mGm'm&l+gnc'bOata?^+]DWsWdWNUbTMM}DZCEC(>M=5;9*7)`$V$O!r",
            "guang": "-5~-2}-1h-'@{~uIhXhTgOZsVKL+>28)5/4b4_4^3s.d+Y*U",
            "ku": "-5}-/3-&Q-$6~R}PzrhDh+gN]dZiZ5OPMgL!I%3N.>$9",
            "jun": "-5{-2T-0q-(n-(G|u{NuHollq_;Z3U5TzQPKMJH@F=l6V3G1B*1&'!Q!K!J",
            "zu": "-5w-5?-+1-+$-&S-%rlYlAd(S#M1Ix0'*e",
            "hun": "-5s-4o}_t9t'o9dMaz`oYDR?Q~JYJRBf=u<d<(;=:t:`9{3O36*9)G",
            "su": "-5n-3x-2c-$*~9}/{3y}y|wjs#p@a(a'_lVnKKJ2H;G(F~F8DYBo?2>>=4:&9z828&+F*L(F&r",
            "lia": "-5[-5>",
            "pai": "-5Q-&sg9eP[NY?JU?p>+;j;8/t.w,q",
            "biao": "-5O-36-2/yJtIryi%f!VfNhLjFzEG<.9C66511o0c,k#|",
            "fei": "-5M-.m-+M-*4-(i-%8w%vZt@t?nXh8gpgPbH]xSdQxQ%P:OPNLLxJVH5FOF)Di?W<C;x6K.`.H,p%3$]#a",
            "bei": "-5I-57-4B-4%-3b-37-,Y-+a-+%-(1-&:w|qIh#bdbGajaR`$X3RMNLNKLyK^K5JUJSIq3:/S/).R,y*/)T!@",
            "dao": "-52-/g-/e-/6-)E-#K-!5xSo_oLmvlvk;k:jiiKhld{b=YoYcWqUZO'JkIaGZEIE?AA3;0g'd!+!&",
            "tan": "-51-3^-3/-2R-)4-%$-#P-#I-!n-!m|o|a|U{'xxxsxaxKtAfTfOfEdtcfb$_p_W_OY/W=UDTuR5PJP=HYF5EnCUAk:w9H7|7{7.5E4K1G(3$}$^#~#7",
            "chui": "-5/-(O}T|9{Va|Y[WcKtJ6ItGl4o",
            "kong": "-4{{+qPlfcNb;Y)Iv<n",
            "juan": "-4z-,h-,P-,0-*[-((}X}Q{Iw<w5uVtut;jpj`j%iYf`byb%`4Z%Y`OGL%K@J:I[=2<^3M.!+j'C",
            "luo": "-4r-1y-.|-'4-%(~<~/o^mHZ*YbW(U@U3U/T{TlOvI^D9>q>O>N;y8^6F3{/(,T+P*M#y#5!Y",
            "song": "-4q-3I-0D-)'u8pulDk^kOgydYdAb`a3a$`D_MZ#XXW0N<N:MmM>K%J`HyEF<B9!6v",
            "leng": "-4p-0T-%uzdz,lQa1J5I!",
            "ben": "-4l-$E|q|pwSwPw.w(YXV8O3LQKXI4?B;|8]4v/8&=",
            "cai": "-4h-4,-%N{%tLp?f#]t]qY0NkJZA},Y",
            "ying": "-4`-3.-%1-$>-#*-!K~Oz%x#s{sXs9s%quqqq_q%kcj[jWhCgDexdha/_AVwV_U0U&R]R.Q:PwO?MHKpK]J{HvHdFbDMDI=_;E:U:K9d9O8K8F6j6i6N6=6&5~5o5j5M5A2w2r2_1x1)0b*:)*(y(S'i'5'%#j#;!B!;",
            "ruan": "-4[zJxQsiVWOUE0):'}",
            "chun": "-4Y-&7sda^RPR(PlOONDIBGrFQE(=T<,:[9N8u/6)C",
            "ruo": "-4S-)[sskPf]Z:YUI8;y3'0^",
            "dang": "-4M-2P-1V-/k-!1}*{fx]swpkl6kdf:aAZUUsTpKiEYD5@|8:7E5D*;(J(6'?%}",
            "huang": "-4@-1L-/w-$PzDz.xtw&s[pEl9jBi0e@clcQa_a#`dXTQgQfPBOEHbH7D{@9:x9i8)4:2c2.1J0X+w)((E#i!}!g!Z",
            "duan": "-4+-.Uz+s`SFS<IMBIB62j)0",
            "ou": "-4(-+=-+7-(q-(K-(3-#;yTd?`EDpC}CSBJB8?l8s1Y'M'0",
            "zan": "-4$-2.-1x-1o-'2-$c-!e~:p>[$XOVUU8U*TwR1Q&PYKrEy6E5K't'k'c",
            "za": "-4$-+Z-'b-'X-'2-$c-!c~B~:~5i}]s[$NyKr?r?a",
            "lou": "-4#-38-.}-$7-#ByMu4tRo{n[kjkEg_`5X)W'HaG#:O9&8~1i'2$5#o#n",
            "sou": "-3z-0J-)Q-)N-#z-#R-#QgsghZ#YvWlW>W0V:U`UBJ/DgCn:#,5#s",
            "yuan": "-3u-1n-1)-0h-.z-*3-*1-)y-(0-&^-$Y-!<}{}t}Z}R}N}M}D{t{_yawlv6v(sSs:s)qhpep<f[cwbyb,`qXoX8NNJ=HxH>H0ErDk@/<m<*;{;v;r;g:e:F:D5]04,M,6)/",
            "rong": "-3t-3`-0u|ts8s'qzp~pFlwkokcjj^WX#WwOyLmHGH.H&GQAsAU9|6%3T1v0b.2)#",
            "jiang": "-3p-2a-,7-+Y-+Wz/xew~w+vvvru]oToSkMfrfWfVfSfCVyVeKdGDEoDeBQ@U>P>#;L9A8M.|,&&B%y%n%m",
            "bang": "-3n{^ypiNi5h~hme|Z?YrWvS2KEJTJSH@=j/m++",
            "shan": "-3h-3)-2R-/F-/<-.a-.E-*~-$q-$F-#H}'{Gy+y*ulubr2nDj|i(f+]zZ;Y3XuXsWaVhV?UySvQ8NrL|LlIVFSEhCI@`7|7p7O5F4B2Z211~.4*b%U%1",
            "que": "-3f-*_-*W{Pyty$lgbNa+`KX!T8T.JBH$@j4e0|)O#q!N",
            "nuo": "-3Q-1w-$ftxa6_#_!ZLXnWoWbWLK0HJF2Am",
            "can": "-3P-2F-)l-)k-)j-)i-$D-#H~:r(q3amah`W`V`U_[XsVqVhO_BtBg;/784z1!0L(9",
            "lei": "-3O-24-1t-,J-)q-#1|(z0xOx?rrU|U;G'E]DyDxD/?$>I=+<F5X'z%u$)#Q",
            "zao": "-3L-/h-&(-%w-$5-!@`JRfMsLkK>JO7F5&2>1#(](7#&#%",
            "cao": "-3L-#GnGk@`v`k`^_DVAUqOgOfG:8x",
            "ao": "-3H-/n-*&-#X-#W|H|4xnxkv}vyvwsDs2rZmxmakAjnga`O_@]I]![DVuUeTBM*K=?>9;7M741m1^0Z,!+~(Y",
            "cou": "-3D-0:Hl;1",
            "chuang": "-3B-/b-/K-/5-.s-.i-.L-$T-!dhvhMd=`|W7O<F+0#/r/k%D$+",
            "piao": "-36-.D-,;-#Crteze7`]RuO*Br9/.v'Z!X",
            "man": "-32{KyKujtlrpn^i'bc`M`=VrOdG9Fs:V9P928b7<701V,(",
            "zun": "-3%-!ix}oPk&[%YzVILEFU5k",
            "deng": "-2z-/t-!VxwrHk(_v^@E$7d6/5.1A(O#,",
            "tie": "-2s-'yigd+",
            "seng": "-2o",
            "zhuang": "-2hx9x8x2w)vWv@tphvhShE^a^`^_VDKcKBG6:`8X3H.e.Z",
            "min": "-2`-0Q-/E-,X-(&|1uumYl]dfded8bJaWaG`S_`[]YhTUTIT(RSRRPzAH>|;z;+:t8(+1*c)o)j)=$R!D",
            "sai": "-2V-#b-#)-!/yod%a2XaAxAb",
            "tai": "-2B-0_-)=}e|Mw[wXwOvzqvqCdodQdB`e[pU]SpR]MeE>@f@D@C>{:=4G4F1$*f",
            "lan": "-2?-1@-)}-%P-!'~3|hx`xXt(qgqaqUmwkwhgb)_8_'^p[5X/UXU(TmSaS_PpLbHXDDD2D1=^9L8i7K6W5`5W5=5<46121%0n0d0I0@0>($'j",
            "meng": "-2;-0k-,Lwaw`qEo2hnh*_._+^qXtUaP)O9K$F;EAANAF:A6h,Z+]'/&X#B!#",
            "qiong": "-28-*fr.pza]`!K}F(3(3%2L1}*))J(G's'f",
            "lie": "-25-0N-/O-,z-,w-,`-'<-&G{D{CuDjaj=djZeZ_YiUEL;JMA{>_=p403f2A1$0a0[.x,h,V+k+[",
            "teng": "-2%i+9]8r1e%6%&",
            "long": "-2#-'J-&]~^|7|6xHxGo2n=k6j_j^g.e([9U.QmOxO8LgKDGYDU>t:g9T9%5w0N*Z'n#f",
            "rang": "-1}-,$~Nx[xC^mU$5b0K+S'X",
            "xiong": "-1m-1j-/q-+v-+p-&zwsdLc?Sy@;>42w2r2#2!",
            "chong": "-1l-0Y-#L{*p`oflelde0dc`+_dX<W8?z=K=98X0F*@%&",
            "dui": "-1g-1e-1`-%L|$zlymobo]oMcc_n_m_*TET>T2NB6[6G5|5u$P",
            "rui": "-1g-1e-1`-)LxFas]0M~KVF.@G)'&t",
            "ke": "-1f-/*-.w-,]-,R-+;-)>-'o-'0-$!|Dzqx4u#p^oUmomIkvknjqc4bra<a;XJWsT4M%J1G|F}CcBCBBA/;u;G:>6U4U0!/N//*j%>$O",
            "tu": "-1c-1]-0H-/o-(y-&3-%?}n}c}J}I}A}?zezZyvxipvnUlskikFh.gVeVc}bsZ.YYX@W2K?EL@R=C=::r7u(i$r$>",
            "nei": "-1I-1*-&TtvA<A;=H",
            "liu": "-1C-/N-.8~fy^s5qik`gl^vW9S4S*R}L~LpKnKQH'FHF#>(=w::8Q7V631r1[*a)~)%(v(?&S&>&%%r$(#d",
            "shou": "-13-)`-)V-%l-!o{ox)x&pxo[]v]uYITcTN<t.1+n+X$e$&",
            "ran": "-1+-1&-(!-##umsKMBF'2y1Z1F*i",
            "gang": "-1'-0^-/L-.gzjz4mzmplT^a^`^_]fYKWDNZJEGe;L2z2v/W/:.a%Z",
            "gua": "-0~-/8-.r-.S-.A-*m-)F-(/-'s-'&-%0|Ooz[/ZuY6LSK[C`2='a",
            "zui": "-0i-*6-'d-#U-!w-!*k<jmQ=O`OGLDG[F]EgEbD@6a(%",
            "qia": "-0M-+;-*r-'6})m0iZc.a<[j[7YAXJUhBq>,",
            "mei": "-0I~j|vz>yRv#sks]sTs4r<p/l&k|e)[bZBU%S3R&M|LoKFHzHjGgDrBfB0B/?~?o?d=I;?;7;32Q2J11,=+$*0)D$w",
            "zhun": "-0E-05-%L}5zwpnnFdPRQ<,:@",
            "du": "-0+-.`-+B-)p-#0z<vKv1uTqjh1SsQ4PvN_IcDlBRBNB+=(;n;Z6</s/h/5.y..+i)I'y!E",
            "kai": "-/x-/v-/%-.M-,I-#J{ey~w0n3kag2dEc#aB`y`r`GXCPfHfCxCu6U4m3}",
            "hua": "-/T-.>-+b-+(-(_-(.-&h-#%{@wGuWs}s|rJrDlaWTV}V+NAMvKfIgGKFX9a7c,7&]&+%~",
            "bie": "-/A-/;fGe2`#M'M!$!#I",
            "pao": "-/>-+i-'^~o|2w=hA]$[P?.4J4H3d06.M'^%A!S",
            "geng": "-/7-&A{TzHlrh=ZIOlK4IX=X2p&M",
            "shua": "-//-%j",
            "cuo": "-.y-.p-*5wukWkSh!ZKY&WuV4(o$j$'",
            "kei": "-.woU",
            "la": "-.v-%3-$n~L|8[RXFXEWnUEU2R`MOI6DT:T0['o$A",
            "pou": "-.l-'_-&[{]twtO]+]&Z+YGJS/<",
            "tuan": "-.I~!}~}K}HyPy&f7`>[}XIVmGLE;;.:m8t2[,F%v%p",
            "zuan": "-.)XOTt",
            "keng": "-,x-([|t|kvIZCXlVgBF/C",
            "gao": "-,Z-(I-(>wRlpWjNHGxGwGdG>E~E3Dm,)!y!t",
            "lang": "-,V-&J-$~{Jy[r{llgiSeOIOHO;KRHHG4Cp=[3Y,z*%(s",
            "weng": "-,@-#oyxv{kfU!Pd9o'N'&",
            "tao": "-+m-)E-'+-%DwPwMw*r}i/fl`j[oYBWXL,JkGtE?><=)<t<H9^6_(w",
            "nao": "-+`-'n{cz[wqt.rzq8l{jyjSd0b~bPad_QZVW9VOKkFJ<J,D+Z+Q),",
            "zang": "-+Oynw)g(/~",
            "suan": "-+C,{$n",
            "nian": "-+3-&i-%b{9uOhdg3dNbTa~[SYVVHV,U7HL=;<0:C2q",
            "shuai": "-*xixiWW3+I&o",
            "mang": "-*<-)*-&Zx(u(o2h*dkb|OENdNSAF@c=i8`/[/D.$$q",
            "rou": "-)uslpsXdMAHc;d2K)>'v",
            "cen": "-)l-)k-)j-)i{Un#kH@?=1",
            "shuang": "-)byOqeq^`NDB>t8R5w5^0&",
            "po": "-)8-&M-#6~]|ZvztMoZmlmZg9W]TXR+O*E%?E>q>o>D;*:J8;6F3v,9*l!`",
            "a": "-(s-'o-%O-$0",
            "tun": "-(k-(7-%L-!`}}|snFhNdP_mRQPFOC@x=335",
            "hang": "-([{dwSvIj)dGS8NML/@.",
            "shun": "-(ZHnF?",
            "ne": "-(R-(8-(%-&T]0%a",
            "chuo": "-(Q-&@-%=~Hu!t~t.ssqVa|^2Z}UuCC<q<J",
            "wai": "-(/-'&-$gwml7C95z",
            "guo": "-(/-'&-%)-$e-#<~.}r}k}f}d}a}U{<zTy>lMi@i$fDf@b1`Y_4XyW6TMMzJ$I:GOD{=#<W;U9#7!,c$<",
            "qiang": "-(,-%f-%M-$.-#[y=y3xmrXr0k>gKfVfSfC^P^N^>[zWQW!VySKMlIvGkFdEJ:)8{4[1s/|/z,f,.*{(p%m",
            "pen": "-('-$E-$=-!6CN;'6}'Q!=",
            "pin": "-&~~Yuatnrvq{[AZ{H]@_/c+!)r",
            "ha": "-&wvz",
            "yo": "-&`-%c-$B",
            "o": "-&X-$a-!H-!%",
            "n": "-&)-#a",
            "huan": "-%v-$Z-$Y~G}D{[email protected][pYp0okm8l!h]bVaH_I^iYpXQUnU1KyK2GBD%CPCB>1=c<~;c8V7D734/3>2I.[.;,3+R*})9(1'b$d$:",
            "ken": "-%V{qxjc*_CX~*I",
            "chuai": "-%=XIW}Ch",
            "pa": "-%/vLisihd.]oX|NC@r8608)P#!",
            "se": "-%,-$,yogK_<Z}VnUrLTGJC5C3>W<x;q7h7g6|6t60)p)&(0#r",
            "re": "-$fa[YU;y3g1X",
            "sun": "-$DqKq9]EYsW{WzW;H1Gv.',:",
            "hei": "-#h-!l7r",
            "dia": "-#^",
            "de": "-#5}0hBeQe5e1c)bFakR[JW<_##",
            "dei": "-#5eQ",
            "kuo": "-!`g`]W[:[/ZsUI8U6L",
            "ceng": "-!_ntnQk4OcObF*",
            "ca": "~s~B[UUWU:",
            "zeng": "~7y5y._}OcObF*1R(M'*",
            "nin": "~(c^bQ[*",
            "kun": "}q|Wzoz`x/x*t'l[lZbwZ0RHQMJv=B8C371U,e)_(g",
            "qun": "}jwxpRl~iPCT",
            "ri": "}iRjA=",
            "lve": "}Go^Y1&2&0",
            "zhui": "|[y0w#t]aaXIIt?s'<%|",
            "sao": "zus+`k_D]UYNXrWtK(AP:8$4",
            "en": "wBmBc5WF20",
            "zou": "w3s>Y%X`W~J/J.Hl",
            "nv": "vkc7OM@!",
            "nuan": "vcPo;`:m2X2W",
            "shuo": "v]a'WhT'S|OKGnCn>>470W+p",
            "niu": "v?q=dKd0]S]![DN?@8@!4u/e/d.W",
            "rao": "u2rA]PU?KkFJ",
            "niang": "t|r&qb",
            "shui": "t]iTZMYuA$A#@{=.=*",
            "nve": "t)%S$%",
            "nen": "sirarYc^",
            "niao": "s!r+qsnwFq9x",
            "kuan": "pBp#ooK)CoCfCd",
            "cuan": "jPV'U*T~TwDtD7BU@o6E5K1S0<",
            "te": "dsdr`R/F/9",
            "zen": "d5VU",
            "zei": "^H",
            "den": "][]C",
            "zhua": "],ZYV#ER0:09",
            "shuan": "[&L^GL<s",
            "zhuai": "Zz",
            "nou": "WoGpE0+^",
            "shai": "W<TsQWOt",
            "sen": "J8ISGI",
            "run": "FE<{8'",
            "ei": "Cl",
            "chua": "Ci"
        }
    };
    var DB = {
        sToC: {},
        cToS: {}
    };
    var sToC = DB.sToC,
        cToS = DB.cToS,
        group = /-?.{2}/g,
        rg = /^-/,
        fromX = function(str) {
            var result = 0,
                temp = 1;
            for (var idx = str.length - 1; idx > -1; idx--) {
                result += temp * (chars.indexOf(str.charAt(idx)));
                temp *= 91;
            }
            return result;
        },
        fn = function(a, f) {
            var p, gs, i, ch, num;
            for (p in a) {
                if (a.hasOwnProperty(p)) {
                    gs = a[p].match(group);
                    for (i = 0; i < gs.length; i++) {
                        ch = gs[i].replace(rg, '#');
                        num = fromX(ch);
                        ch = String.fromCharCode(base + middle + (f ? -num : num));
                        if (sToC.hasOwnProperty(p)) {
                            sToC[p] += ch;
                        } else {
                            sToC[p] = ch;
                        }
                        if (cToS.hasOwnProperty(ch)) {
                            cToS[ch] += COMA + p;
                        } else {
                            cToS[ch] = p;
                        }
                    }
                }
            }
        };
    fn(SDB.m, 1);
    fn(SDB.a);
    SDB = null;
    /** 
        目前缺少多音字的处理 
    */
    C.CSpell = {
        getSpell: function(chars, polyphone, spliter) {
            var cToS = DB.cToS;
            var res = [],
                pp = typeof(polyphone) == 'function'; //判断polyphone是否是函数 
            chars = String(chars).split(EMPTY);
            for (var i = 0, ch, ss; i < chars.length; i++) {
                ch = chars[i];
                if (cToS.hasOwnProperty(ch)) {
                    ss = cToS[ch];
                    if (~ss.indexOf(COMA)) {
                        ss = ss.split(COMA);
                        ss = pp ? polyphone(ch, ss) : '[' + ss + ']';
                        res.push(ss);
                    } else {
                        res.push(ss);
                    }
                } else {
                    res.push(ch);
                }
            }
            return res.join(spliter || COMA);
        },
        getChars: function(spell) {
            var sToC = DB.sToC;
            if (sToC.hasOwnProperty(spell)) {
                return sToC[spell].split(EMPTY);
            }
            return [];
        }
    }
})();

使用示例:

Utils.CSpell.getSpell('阿里巴巴欢迎您');//[e,a],li,ba,ba,huan,ying,nin

因为“阿”是多音字,因此结果是 [e,a],li...这样子的,当您需要遇到多音字自已处理时,可以这样:

Utils.CSpell.getSpell('阿里巴巴欢迎您',function(charactor,spell){
console.log(charactor,spell);
return spell[1];
});

结果:"a,li,ba,ba,huan,ying,nin"

结果默认是逗号分割的,您也可以这样:

Utils.CSpell.getSpell('阿里巴巴欢迎您',function(charactor,spell){
console.log(charactor,spell);
return spell[1];
},'-');//使用连接符

结果:"a-li-ba-ba-huan-ying-nin"

Utils.CSpell.getChars('li');//根据拼音获取汉字,只能是单个拼音不支持如 nihao 这样的多个拼音

判断两个线段相交,附javascript实现

游戏当中需要用到,向我同学请教之后得到的结果
img
javascript实现:

var isLineSegmentCross=function(p1,p2,q1,q2){
    var d1=((p2.x-p1.x)*(q1.y-p1.y)-(p2.y-p1.y)*(q1.x-p1.x))*((p2.x-p1.x)*(q2.y-p1.y)-(p2.y-p1.y)*(q2.x-p1.x));
    var d2=((q2.x-q1.x)*(p1.y-q1.y)-(q2.y-q1.y)*(p1.x-q1.x))*((q2.x-q1.x)*(p2.y-q1.y)-(q2.y-q1.y)*(p2.x-q1.x));
    return d1<=0&&d2<=0;
}

调用:

var p1={x:100,y:68};

var p2={x:50,y:128};

var p3={x:39,y:-10};

var p4={x:122,y:10};

alert(isLineSegmentCross(p1,p2,p3,p4));

教育部推荐中小学生最全必读书目

一年级学生必读书目

1、《**古代寓言故事》邶笪钟编写 北京人民文学出版社
2、《中外神话传说》田新利选编 北京人民文学出版社
3、《十万个为什么》卢嘉锡主编 少年儿童出版社
4、《与鸟儿一起飞翔》郑作新著 湖南少儿出版社
5、《海底两万里》(法)儒勒.凡尔纳 北京教育出版社
6、《汉字的故事》梅子涵著 上海科普出版社
7、《安徒生童话选集》(丹麦)安徒生著,叶君健译 译林出版社

二年级学生必读书目

8、《克雷洛夫寓言全集》(俄)克雷洛夫著,裴家勤译 译林出版社
9、《拉.封丹寓言》(法)拉.封丹著,倪海曙译 上海译文出版社
10、《格林童话全集》(德)雅各布.格林威廉.格林著 译林出版社
11、《科学王国里的故事》王会等主编 河北少年儿童出版社
12、《神奇的符号》苏步清著 湖南少儿出版社
13、《诗词中的科学》唐鲁峰等 江苏人民出版社
14、《**古代科幻故事集》杨鹏、刘道远 **少年儿童出版社
15、《阿凡提的故事》赵世杰编译 **少年儿童出版社
16、《三毛流浪记》张乐平 少年儿童出版社
17、《宝葫芦的秘密》张天翼 农村读物出版社
18、《今年你七岁》刘健屏 **少年儿童出版社
19、《荒漠奇踪》严阵 **少年儿童出版社

三年级学生必读书目

20、《伊索寓言》(希腊)伊索 **妇女出版社
21、《宫泽贤治童话》(日)宫泽贤治著 周龙梅 少年儿童出版社
22、《列那狐的故事》(法)玛。阿希。季诺著 北京教育出版社
23、《天方夜谭》郅涛浩等译 译林出版社
24、《130个科学游戏》(德)汉斯。普雷斯著,吴衡康编译 **少儿出版社
25、《东周列国志故事》郭平、陈咏超改编 江苏少年儿童出版社
26、《成语故事365》帆女阿雪等 国际文化出版公司
27、《一百个**孩子的梦》董宏猷 21世纪出版社
28、《我们的母亲叫**》苏叔阳 **少年儿童出版社
29、《小兵张嘎》徐光耀 **少年儿童出版社
30、《三寄小读者》冰心 少年儿童出版社
31、《皮皮鲁传》郑渊洁 学苑出版社
32、《肚皮上的塞子》周锐春风 文艺出版社
33、《乌丢丢的奇遇》金波 江苏少年儿童出版社

34、《我要做个好孩子》黄蓓佳 江苏少年儿童出版社
35、《灵性的王国》张香桐著 湖南少儿出版社
36、《爱的教育》(意)亚米契斯著,马默译 浙江少年儿童出版社

四年级学生必读书目

37、《稻草人》和其他童话叶圣陶 **少年儿童出版社
38、《**当代儿童诗歌选》张继楼,彭斯远 四川少年儿童出版社
39、《外国儿童诗选》文成英,李融编选 四川少年儿童出版社
40、《科学家故事100个》叶永烈 少年儿童出版社
41、《中外探险故事精选》伊明选编 **少年儿童出版社
42、《无尽的追问》王淦昌著 湖南少儿出版社
43、《昆虫记》(法)法布尔著,言小山译 人教社大百科全书
44、《我的野生动物朋友》(法)蒂皮。德格雷,黄天源译 云南教育出版社
45、《中外战争的故事》张鸿海等 **少年儿童出版社
46、《做人与做事》卢勤 接力出版社
47、《30天环游**》郑平等 **少年儿童出版社
48、《草房子》曹文轩 江苏少年儿童出版社
49、《第三军团》张之路 **少年儿童出版社
50、《巫师的沉船》班马 21世纪出版社
51、《糊涂大头鬼》管家琪 浙江少儿出版社
52、《木偶奇遇记》(意)卡洛。科洛迪著,杨建民译 上海科技教育版社
53、《格列佛游记》(英)乔纳森。斯威夫特著,杨吴成译 人教、译林版
54、《福尔摩斯探案全集》(英)柯南道尔,丁锦华译,远流公司
55、《顽皮捣蛋鬼》(德)威廉。布什 湖北少儿出版社
56、《七彩的分光》王大珩著 湖南少儿出版社
57、《悠长的岁月》贾兰坡著 湖南少儿出版社
58、《写给小读者》晓玲玎当 **青少年出版社 五年级学生必读书目
59、《圣经神话故事》陈静选编 **少年儿童出版社
60、《严文井童话选》严文井 四川少年儿童出版社
61、《普希金童话》(俄)普希金著,亢甫,正成译 浙江少年儿童出版社
62、《王尔德童话》(英)王尔德著,唐讪辉译 **连环画出版社
63、《中外动物故事选》伊明选编 **少儿出版社
64、《中外经典科普故事》伍钚编 **少年儿童出版社
65、《中外网络故事》伍钚编 **少年儿童出版社
66、《科学改变人类生活的100个瞬间》路甬祥主编 浙江少儿出版社
67、《水陆两栖人》(苏)阿历山大。别利亚耶夫,善诚译科学普及出版社
68、《中外艺术家的故事》江钥含编 **少年儿童出版社
69、《国际知识问答》 **少年儿童出版社编**少年儿童出版社
70、《上下五千年》林汉达曹余章著 上海少年儿童出版社
71、《马燕日记:一个感动世界的现代童话》(法)韩石 华夏出版社
72、《中华经典诵读本》徐含之选编 苏州大学出版社
73、《漂亮老师和坏小子》杨红樱 作家出版社
74、《幻城》郭敬明 春风文艺出版社
75、《鲁滨逊飘流记》(英)笛福著,王泉根译 北京少年儿童出版社
76、《魔法师的帽子》(芬)杨松著,任溶溶译 纺织工业出版社
77、《金银岛》(英)史蒂文生著,单蓓蕾译 北京出版社
78、《吹牛大王奇游记》(德)埃。拉斯伯刘浩译 少年儿童出版社
79、《淘气包艾米尔》(瑞典)阿。林格伦著,高锋红译 **少儿出版社
80、《童年》(俄)高尔基著,上海译文出版社
81、《做一个快乐的少年人》邓碧霞译 三联书店

六年级学生必读书目

82、《科学的发现》郭正谊等 **少年儿童出版社
83、《高士其科普童话》高士其 人民文学出版社
84、《元素的故事》(苏)依。尼查叶夫,滕砥平译 湖南教育出版社
85、《**民间故事》宣仁选编 **友谊出版公司
86、《诺贝尔奖金获得者与儿童对话》 三联书店
87、《世界五千年》段万翰、顾汉松、陈必祥编著 少年儿童出版社
88、《三字经、百家姓、千家诗》来新夏主编 南开大学出版社
89、《丛林传奇》(英)吉卜林著,徐朴译 少年儿童出版社
90、《爱丽丝漫游奇境记》(英)刘易斯。卡洛尔著陈伯吹译 上海科技教育出版社
91、《骑鹅旅行记》(瑞典)塞。拉格洛夫著,王泉根译 北京少年儿童出版社
92、《汤姆。索亚历险记》(美)马克。吐温著,钟雷主编 哈尔滨出版社
93、《捣蛋鬼的日记》(意)万巴著,思闵译 **社会出版社
94、《小王子》(法)圣埃克苏佩里著,马振聘译,人民文学出版社
95、《哈里。波特与魔法石》(英)joko罗琳 人民文学出版社
96、《生命的密码》谈家桢著 湖南少儿出版社
97、《假如给我三天光明》海伦。凯勒著李汉昭 译华文出版社
98、《父与子》(德)埃。奥。卜劳恩,洪佩奇编 译林出版社
99、《大作家史努比》(美)蒙特。舒尔兹 中信出版社
100、《再见了,可鲁》(日)秋元良平等 南海出版社

初高**读部分:(10种)

①《西游记》(明)吴承恩著;
②《水浒传》(明)施耐庵、罗贯中著;
③《三国演义》(明)罗贯中著;
④《红楼梦》(清)曹雪芹、高鄂著;
⑤《唐诗三百首》(清)衡塘退士选编;
⑥《宋词选》胡云翼选注;
⑦《阿Q正传》鲁迅著;
⑧《古代散文选》人民教育出版社编;
⑨《科学的历程》吴国盛著;
⑩《数理化通俗演义》梁衡著

初一年级学生必读书目:

①《红岩》罗广斌、扬益言著;
②《安徒生童话全集》(丹麦)安徒生著,叶君健译;
③《童年》(俄)高尔基著,刘辽逸译;
④《格兰特船长的儿女》(法国)凡尔纳著,范希衡译;
⑤《爱的教育》(意大利)亚米契斯著,田雅青译。

##初中二年级学生必读书目
①《青春之歌》杨沫著;
②《骆驼祥子》老舍著;
③《钢铁是这样炼成的》(前苏联)奥斯特洛夫斯基著,梅益译;
④《福尔摩斯探案集》(英国)柯南道尔著,丁钟华等译;
⑤《居里夫人传》(法国)埃里·居里著,友明彻译。

初中三年级学生必读书目:

①《家》巴金著;
②《牛虻》(爱尔兰)伏尼契著,李俍民译;
③《高老头》(法国)巴尔扎克著,傅雷译;
④《莎士比亚戏剧故事》(英国)兰姆姐弟改写,萧乾译;
⑤《**科学院院士自述(青少年版)》上海教育出版社编。

高中一年级学生必读书目:

①《矛盾论》、《实践论》***著;
②《围城》钱钟书著;
③《希腊的神话和传说》(德国)斯威布著,楚图南译;
④《谈美》朱光潜著;
⑤《科学发现纵横谈》王锌坤著

高中二年级学生必读书目:

①《子夜》茅盾著;
②《悲惨世界》(法国)雨果著,李丹、方于译;
③《简爱》(英国)夏洛蒂·勃朗特著,祝庆英译;
④《圣经故事》刘小江编写;
⑤《傅雷家书》傅敏编写。

高中三年级学生必读书目:

①《共产党宣言》(德国)马克思、恩格斯著,****马克思、恩格斯、列宁、斯大林 著作编译局译;
②《从鸦片战争到五四运动》胡绳著;
③《老人与海》(美国)海明威著,海观译;
④《培根随笔选》(英国)培根著,何新译;
⑤《只有一个地球:对一个小小行星的关怀和维护》(美国)巴巴·沃得、雷内·杜勃斯主编

 

正则表达式(?!patten)与(?=patten)妙用

假设我们要匹配一个以 数字 字母 下划线组成的字符串,并且该字符串长度要大于等于6,只能以字母开头的字符串

我们可以使用?=来验证长度

该正则为:/^(?=.{6,}$)[a-zA-Z]+\w+$/

我们对上面的要求再加一个,就是不能以下划线"_"结尾

我们使用?!来限制

该正则为:/^(?=.{6,}$)(?!.*_$)[a-zA-Z]+\w+$/

项目中的需求是验证一个字符串,由汉字 字母 数字 下划线和连接线"-"组成

要求:

1:下划线"_"不能与连接线"-"挨着

2:连接线不能出现在首或尾

示例:

可以匹配

  a-b-c_
 1-2-cc
 1-A-b
 _我
 我们-你们
 q-我
 1-2-他们
 90-abc-90后

不能匹配

-a
-我
_q-c-
我-
a-1-_2
我-_上海
q_-我
我-你-

最终的正则为:

/^(?!.(?:-|-)+.$)(?!.-$)(?!-.$)(?:[\w\u4e00-\u9fa5-]+)$/

判断矩形相交以及求出相交的区域

问题:给定两个矩形A和B,矩形A的左上角坐标为(Xa1,Ya1),右下角坐标为(Xa2,Ya2),矩形B的左上角坐标为(Xb1,Yb1),右下角 坐标为(Xb2,Yb2)。
(1)设计一个算法,确定两个矩形是否相交(即有重叠区域)
(2)如果两个矩形相交,设计一个算法,求出相交的区域矩形

(1) 对于这个问题,一般的思路就是判断一个矩形的四个顶点是否在另一个矩形的区域内。这个思路最简单,但是效率不高,并且存在错误,错误在哪里,下面分析一 下。
pic

如上图,把矩形的相交(区域重叠)分成三种(可能也有其他划分),对于第三种情况,如图中的(3),两个矩形相交,但并不存在一个矩形的顶点在另一个矩形 内部。所以那种思路存在一个错误,对于这种情况的相交则检查不出。

仔细观察上图,想到另一种思路,那就是判断两个矩形的中心坐标的水平和垂直距离,只要这两个值满足某种条件就可以相交。
矩形A的宽 Wa = Xa2-Xa1 高 Ha = Ya2-Ya1
矩形B的宽 Wb = Xb2-Xb1 高 Hb = Yb2-Yb1
矩形A的中心坐标 (Xa3,Ya3) = ( (Xa2+Xa1)/2 ,(Ya2+Ya1)/2 )
矩形B的中心坐标 (Xb3,Yb3) = ( (Xb2+Xb1)/2 ,(Yb2+Yb1)/2 )
所以只要同时满足下面两个式子,就可以说明两个矩形相交。
1) | Xb3-Xa3 | <= Wa/2 + Wb/2
2) | Yb3-Ya3 | <= Ha/2 + Hb/2
即:
| Xb2+Xb1-Xa2-Xa1 | <= Xa2-Xa1 + Xb2-Xb1
| Yb2+Yb1-Ya2-Ya1 | <=Y a2-Ya1 + Yb2-Yb1
附上js实现

intersect = function(rect1, rect2) {
    var half1Width = rect1.width / 2,
        half1Height = rect1.height / 2,
        half2Width = rect2.width / 2,
        half2Height = rect2.height / 2,
        cen1 = {
            x: rect1.x + half1Width,
            y: rect1.y + half1Height
        },
        cen2 = {
            x: rect2.x + half2Width,
            y: rect2.y + half2Height
        };

    return Math.abs(cen2.x - cen1.x) <= half1Width + half2Width &&
        Math.abs(cen2.y - cen1.y) <= half1Height + half2Height;
};

(2) 对于这个问题,假设两个矩形相交,设相交之后的矩形为C,且矩形C的左上角坐标为(Xc1,Yc1),右下角坐标为(Xc2,Yc2),经过观察上图,很 显然可以得到:
Xc1 = max(Xa1,Xb1)
Yc1 = max(Ya1,Yb1)
Xc2 = min(Xa2,Xb2)
Yc2 = min(Ya2,Yb2)
这样就求出了矩形的相交区域。
另外,注意到在不假设矩形相交的前提下,定义(Xc1,Yc1),(Xc2,Yc2),且Xc1,Yc1,Xc2,Yc2的值由上面四个式子得出。这样, 可以依据Xc1,Yc1,Xc2,Yc2的值来判断矩形相交。
Xc1,Yc1,Xc2,Yc2只要同时满足下面两个式子,就可以说明两个矩形相交。
3) Xc1 <= Xc2
4) Yc1 <= Yc2
即:
max(Xa1,Xb1) <= min(Xa2,Xb2)
max(Ya1,Yb1) <= min(Ya2,Yb2)

使用div模拟table

本项目仅供参考,需要浏览器css支持display:flex,position:sticky等特性

为什么模拟table

从功能上来讲,行列的数据更适合使用table,所以当您的需求中没有固定表头,固定列时,请直接使用table,模拟table更多的是解决固定表头,固定列等事情。

table有哪些问题

body不能滚动

当数据量多时,我们期望表头或表尾固定,只滚动中间区域,但是<tbody>不能做为滚动容器。如果我们强制改变<tbody>display使它可以滚动,然后<thead>中的列和<tbody>中的列就对不齐了。

然后我们可能就要上javascript然后各种同步列的宽度了,然后你会发现解决1个问题会引入3个问题,到最后列可能还会有些许的偏差并没有对齐。

这个网上的案例有一些,感兴趣的话可以搜搜看

sticky

我们知道css3position新增了sticky,如果浏览器支持,直接在<thead>上使用position:sticky就完成了表头固定,多好?

chrome曾经支持过<thead>上设置position:sticky,但是后来不知为何又去掉了,然后目前没有浏览器支持<thead>上设置position:sticky,这都什么鬼?具体可以看下caniusehttps://caniuse.com/#search=sticky

table做固定表头,固定列功能

网上常见的做法是使用4个表格来完成相应的功能,以ant.design为代表,可以看下它的效果和实现:https://ant.design/components/table-cn/

这种做法实现起来麻烦,计算的量也不少,在表头固定、首列固定、尾列固定、表尾固定这些需求同时存在的情况下,列对齐需要计算,然后同步。行高需要计算,然后同步,据说ant.design是以中间行为最大高度,然后去同步首列中的行和尾列的行。

做到最后依然可能对不齐,我在ant.design中的表格组件上经常能见到对不齐的bug

做完各种计算后,如果要实现鼠标移上行变色,你会发现css中的hover伪类没法使用,因为表格是分离的,这时候就又需要绑定javascript事件进行模拟实现,这个简直了...

div模拟表格

该方法仍然需要计算,但计算量少了很多,只需要列宽计算

因为行没有被拆分,所以行高不需要计算对齐,同时可以使用css中的hover伪类实现鼠标移入变色

demo地址 https://xinglie.github.io/magix-table/index.html
项目地址 https://github.com/xinglie/magix-table

行高

由单元格内容自动撑开,最好不要在单元格上写高度,可以在单元格内再套一个div之类的来处理高度。因为整行的单元格并没有分离,所以行高不需要计算,同时可以使用csshover伪类来处理鼠标移上的背景色。

列宽

列宽需要javascript计算,其实也谈不上计算,因为计算宽度的过程可以省去,比如你给每一列都写好了宽度,或使用百分比则不需要计算。

列宽的处理上更重要的是把表格head中的列宽同步给body中的列,列宽没办法自动处理,这一步还是需要javascript来进行同步。

同时考虑到类似table实际运用,宽度可能是百分比,可能是定值,也可能混用,也可能省略等,以方便为目的,对head中的列宽进行计算后再同步给body中的列

单元格合并

列合并不是问题,因为所有的单元格都在一行上,无非是计算的时候,把合并列的单元格的宽度自成它合并几列的宽度即可

行合并是个大问题,目前并未找到合适的方案,示例中的head中的行合并其实是视觉上的效果,并不是真正意义上的合并。也仅head中的单元格做了视觉上的合并,body中的并没有做,因为该“行合并”方案本质上有很大缺陷,就没再深入去处理。

后续

未来可能使用css中的display:grid来模拟表格,这个方案在合并单元格上有着天然的优势,也许可以用它做出更好的表格

当然,还是希望position:sticky能尽早的用在table上,目前虽然像chrome支持在th上使用position:sticky,但是也仅是th上,而且还有bug,期望浏览器赶快完善起来吧。

需要注意图片onerror事件所带来的其它问题

Stack overflow at line: 0

一般来说,这是Javascript出现循环调用时报的错。由于页面上的代码比较多,无法一下子判断出是哪里的问题,我只好一段一段地删。然而,即使我把所有的<script>标签都删了,这个错误仍然存在。我又怀疑这是嵌入的外部文件导致的问题,于是又把所有的<iframe>标签给删了,但问题依旧。

难道HTML也会导致循环调用吗?其实我算漏了一个地方,就是HTML元素的事件,可以通过标签的“onEventName”属性指定,比如“onclick”、“onmouseover”等。这下终于让我找到了线索:页面上的一张图片设置了“onerror”事件。代码大概如下:

<img src="a.jpg" onerror="this.src='b.jpg'" />

onerror事件用得比较少,但它本身并不会造成什么问题。然而,这里的“a.jpg”和“b.jpg”都是不可访问的。访问“a.jpg”的时候出错触发了onerror事件,把图片的地址设为“b.jpg”,问题就在于“b.jpg”也不可访问,又触发了onerror事件,再次设为 “b.jpg”,这自然也是不可访问,继续触发onerror事件,如此往复。

可以使用以下方式解决

<img src="a.jpg" onerror="this.onerror=null;this.src='b.jpg'" />

新版汉字转拼音 50kb

思路见上篇,唯一不同是区间拆分成了3区间 #26

(function(){
    var db={"yi":"$$$h$i$p$q%)%*%+%V%y&=&`&d&i'1'4'j'l(0(T(^(t)M*H+I/2/6/I0^1%2>3v4<4i4x5A5V5v7h8X9=9W9d:<:U;J=g?^@gAfAzB:C_DDDFFfGCGKGSH5HSIbJ>L>M/M5M_MlMzOBONOYPOPPPcQHR/S$S5THUbUgUrVXV_W1W2WXX`YCYmYsYvYwZBZrZsZtZu[7[;]4]B]w^;^Y^y_X___la+c*cBcScvdhdie/e`fsg`hoiTkemamin;nAnVn[oWo]pEpfqWqerJrXt;t?tpuIuPvRvbvuw1y)yCykyw,$v&6'x(;(O)h)p*K+.+D+S+`+d/u0T0c0e1j1m282[2j4^5S6H8&8h9e;9<6>2>8>[?R?V?]?o@8@?@OC+C1CzDVEoF*H=I`K)K2KSK[KnL;LZM1M8MKMoO<P7Q4QaRYV8VuWhXEXzYPZ'[l]D_=_X`5a*fDg(g]g`haiak1k6k?kUkakcl5l>lwmsmyo6q%qernsMsZsqt%thu/u0vKxfxr,%L'9(/(3(p)K*/*v+6+;+@+X.:/F/J/R0Y1n1o1u2N2Y363=3b4G566a7D7E7`7e7v8A9$:Q;);1;2;K;^;q<?<@<Q<y=t=v>=>]>k?/?s@YB=BVEwFHG)GHH5HDHcHpHzIBIcJ+JPJhL(LAM'N1N9N=NZO$O&OJORPMQ/T>TcUzVnX/Y<Y[[f^Y_sbSbobpc@cMd2e+eBfJfogliYj'jXmUmVn=qDrDs8s9sCsxt*t8tItatfuluqutw9wEwYy*y6","ding":"$%&A8*<eHtOLU9Vk]8hryU,9yEHJPJRKVObRkTUToUslxmPpLssxv,'K)s.P6i;eLyN_QVRVU_VpWwXl`]bLc7cme1f_wuwx","zheng":"$%%['m1rD3D7E^InLJSGT)T0WS[C[P[s[w[x^.aVb`e[fjgIhlhri?ksmnnNqV,*Q/&<O=7A7CRD%L5N)P.P`Q$^7^j_cc3e8m5oF,$_7N97:`</<RCOKSL[PDRPU+WDX*`Gk^qi","kao":"$&QETyfrmfvm,1c=>BHlE,'QQ6Wc`Rk1mbn$pE","qiao":"$&%$)()Q+<.W/*3d4y=F=Y?*?`FCFMFdGEMPSFSOTyUZVMW;WfWz_J`sb_kDl.l?nLwK,%j&t'1'5'i)7+U+V+^8N>S?y@'BTM_PcQrSzT&U5UWUxV(V/Zd[G_Dg7gViqkol;vGvXx>,&L(D8X:p<]=IAvAwBnC/DHDIDVL'LOLSNlSMSNTaUBUkXx]E^Za0a6aGa[aqbhc]jdk0k2","yu":"$&$4%M%Z%a%c'+'E(/)C)a)f*(*y.:.q/W0H5g7q8?9&<%<t=C=U?fANASAvD+DWDrE$HdHfINITJrK*K1K3L*L.L]M1N/O9P1P7PhR5SLTAT]TjUHUwY%Y&['[d]Z_L`Ba$a%a8bHcOdMe(e)eCgMgzh7iBn.nonyoBofpdt%vjw?xnxoy'z(,$G$V$m)4)P)`)g)h)u*6*M*e+n/[2k40424=4c4l5[7<7S8M9D9H9P;m<%>:>c?Z@+@>A3AYCSCUDRECEQESG)G1GRGoHtK.L=LoLxM(MmO4OEQ8RTSCT0T@V+V<VBW6WyX7X8XUYLYaZ;ZQ[.[5])^e`/`xa<aPaub/c<e]h3jWkCkSkhmnmonLpgrHrKrPrQs;s>t+t.unv(y)y*y6,$T%5%K&K&v')'r(c(r)a)y+z.4.Y/k1r2c373x5a648G8]9E9W:9;?<[<o=/>1>VCRECF3FfG/H:H@HAI^IiIrJOJoK*KCL3M)N+NqOmPhQTR[S?UhWBZT[J]A]r]t^C^n_(_._/_xbZbsd$e9egfAffg$gShriFiljVjnl2l3l=lLl]lfmlnLn`oPp.q^r/r1r4r]tBtZtituuTv$vFy(y3yG","qi":"$'$2%0%f%p%r')'8)b*I.<.b0T1N3:8n919D9X:6;Z;p<><A<B<M=J>G?B?ZB1DJF(GtHEHOIfK:KOR0R8RFRISqTkWLYn]B]^^n`/a0aKbFbGbQbtcVd<e?hQhdilk*manAndneoHo^qSr+sUt@u)uavNvPwJwcx;xVx]x^y$y0,%Q&)(G(V)n*%*&*U.Z.^.j/F/p0+1+1^3j3u5@5A6q7X:3</=jClE<ERG8G<H@IsJWK&KjO2OhRlS.TOTdTjU0UVUbUdV>VhVnVoWLWxYBYh[R[T`b`da+bBcae3e4e6e<eHeNeli*iGj4lHnOoVqls`t3t@tLvZxSx^xhyy,&q'e'o(&(Z*?*B*H+N+x+y/9/Y0^0o2j3c3g6S7&909V;n=cAAAiB8CHEWHBHGJkKmLnNuRWTiUKXZZp][^)_QbXcwhahbi7j:j;kglAlNn/o3pbq)s.s6s>vLv[x]xc","shang":"$($0'N.=<4CID9F8PxPy_*a1b9dgq(,&G*v+>/V5j7E7t?hWfeci/,%b/]3U6D6Z:@?P@6@nR5TjVBa;l<","xia":"$)$1%6(w)c+_5^788Q9b;o?zB+ClGbGfSCS`Y2[icMhPnHqfuhxL,<N=4>LC0COC[FNGhK_KkM/Q;QXSyT2U$UGW=]H^DfPj/k_rhs0t2,&w)u**.m/M9?=TA8FkGiJ$S>SnTJU$Z)Z2]J]n_edNhum'npsnwF","han":"$*&_'o.B0M23246i6o8j;=;G<yAOCaJyMBP0R3T/TS]A_Sbsc4e*gtkml>mkowoxq5q6r?wyyv,*I/;/I/h2Q2b3&3W7u99:q=e=n?bA=BkCeFgJ3NZPd]@^Bj?l2n=wEx3,%])z*e+Y.2.3/D:V=W=^F@JnK1M=NsQ<QXQlYsZu[.^rarb3bQc+c:cod6gFgUhMm)qOsuxP","wan":"$+$_*52I3>6366;OD4E@G<GjGkIQKKKcO>OMREWGZEZe]V`=`>e^gdh&h7hgq8qCqGqZtFtNx*y>,&<+g/?3V5y8j9U;f=QEdFzG>K;N]O>PtQnTf]0_&c>d^dge7e>h:i<l+o[o_pGt$wDwRwgxiy(,%f'7*D.E/v=g>m?v@*CBF6F9QNQ_R0RtT9b[ct","mo":"$+$o0q4$>B?1@:@BB3EvFNIeMEMVN(N=P<PzVzW0XCcWcyf3k?kNkOlxmNp[sbuH,&`'/*m*n*p000?0I7s:e@dCDD^MVNRP:P[P^QZQdS@UcVYXbbmd(d6fsgmltoOq:uWw.wQ,%8(<(h+B/y022p:>:?=9>I>N>O>P>_PeTZY0]:`mf=fWg3i>j^jxlVllm%vwvxw>w?","zhang":"$.&G&U&f.C0+F+M6U<VwWEWnWxZ6Z7ZK[2b&e%h_r<t8,&^3J3S8081D_HIL]MFMNQ`V'[ca_bEnZp),%S0/?_@DJ=LQU)YbYj^6a;eui=oLvX","san":"$/&N'H)W+s6h7S7T7U7V7WG?WFYyn=,.;.<.E8tBObKbhbnbog<,TaU8Z$fDg9km","ji":"$2$T$h%;%r&:&;'5'8(L*w+H.f0T0]0_1k212?2E2y3@3F3t4r6?6Y6d7]7p8;8G:C:s;j;y=8=s>w@(B4BLC/DHE*EBECFcHEI(I=J4JBLxNjOuOwPoQZR$RBTTTUU.UjVWWLX<XsYWZgZh[8[^]:]Q^?`(`@aOc5cVcrdAdDeNgJhaick*kYkwl?lLlcmanAohoiojr2r3rKsTsUsqtdthx0xk,$<$Q$[%[%v&l'I'a()(3(K([)/+5+_/W/e1<1X2D3d4V5L7U7Z8U9k9s:5;3=jB:BhEKHbI&JvK:KAL*LdM:N$N0NFNSQSRmUjUwW?WpX$XnYBYSYbYhYoYuYxZ*Z=]2]6^+^p_E`<`@a)c1c6cHcPdHe%e6eOelfyg1gQgch9h<hlhzi%iGjhjljrjslglpn$oPq(r8s[tJtRu%u[usvZyi,$a%1%Y&>&y'4'e't(e)0)=)B)q.S/A0A3<4N4Y5C5D5g606?6S6o7(8I9/9>:f;$;d;h;s<F=U?^?j@lAVAiBWBrBtC3C8CsD+DYDsE2FUG*GdHxKHPgQ)RZS5U0UPV+V?]3^5^H^a^y_+_G`%`/a&a^b<e0fKf`idjOkQl@lWl`lelhm4n4nWo<oEoFotp0pLp^qLrUsEsqt$t3tgu/upv<x_xaxbxcxdym","bu":"$3's4^6B6E8d:.;<CwCzD.DpKFSNVjXnY7^0_Weyh%h'h>q?uw,*S*V*WIj^[_w`rvt,%R1p3>8fC$FwI5KkKyN3O:OpRrW*WJeceqmuqHrYtw","fou":"$38eID,+/<_cGiuixiz,_2q_","mian":"$5+G0)0t4W4c=/K)KDLBN;O2a.tEx[,(F(b/7024`5H9JA[OwP>PkR>R@REbPd^eMekf$i3iCpor;t'wRy@,.X`T`U`Xmgvevfvpvuwdwe","gai":"$6%4([5=5>C5J5S2]9dFk7mhq.t<,$i&%&&6/7dI*JxOHWFdBdQtGv>ya,$r80<S>)?7?>@dKDOUW)]B^)","chou":"$7$8&E)i+</F8Z@'KgN*WCX(^8`8`tcZf7i'j4t^t`vaxNyD,(D+:@[B$B_BbK$K6KIMMN^O[QOR7YJ^S__a(ccd4e0i6r7r:x','`3Q84;P;R<XBuC.DXJ0MAMFMoMwNA^o_$_*lYmF","zhuan":"$9'J.9.T.d3Z7R<[@_DnEwM?NoPaPg_4l2,7l;zGdH:IyS8UQUT[t_L`)`1`Za/fnlSpPq<,$'0B4V9Y:k?m?v@yE]FpG>LMcId=fFg:oJ","qie":"$:'h2=5b6y=vHOIiWK^I_U`_a:aig.s;vNyB,1z3dD>KNNES.YQZ)ZY[L]O_+_Qa?mitiuR,+DANBOCGKFSGXqn6","ju":"$:$e%>'K)9)h)t*V*e.q0U1p3I3j5&5D7x9k<hD5DLFpJ*K7KGKqP>QJQOQqQsRVR_SoV.VNVPYq]0]v^(^4`YaQc;cseSfLfRfZg?g]h@i(i^l]ljpMuFukw:x@yEyFyN,$p%('B'v):)G*Y./.70L0b102$3]3z4o5c9h<Z=?=r>'BABGC*C;F+G*L)P5R5R`SBXk[/[8^?`gasbAg>jGlbmHmSpDrSsCu1uBw8wq,$E$O%M(s)d*f+v/i2I3a517a94;x>*>^ANAgBJBOBSBsC:C@C`D9DTE3EDF&G8JSK/L%N;OxQqR.UvW.XRXnZF]`^ia>aIdXdvgvgyhHifixm6mBr)rds(sAsaxBxExryA","pi":"$;&r'='i/+3Q3k5t8`8e<R?o?p@&@KAyBfD2FgIDLaM+QKRfT3UIX>^P_Hc)eGezf1iHlYoMs=tjtk,$s+r+s4.8L9g:4<9>=C)C5CkGGJ'KJKMKuLLMqNuQ/S4UAV:V;WXXYX_YU]A`*cKhBjLj_jbjqkdl]nPp$p0pIq)t:tl,*;*l*m.7/G/j192b3J9(;.>B>D>ZGrK5KnO/OLOlP=PsQ*R9RCT*W`Zy[s]0]c^@`)a<gzkBlqm*m;pAqcrrtbtmx)","shi":"$<$=%:%?%]%^&>&S'g(U(d061'4M4q5S6%617$809H9S:L<Y=w>_?E?_D$DDELG=H/HlIvJRMpOPOQOVO[OeP2PDQBQWQXS7S;TITJU/ViVoW=YzZ%Z&[h]C]^^Z^^`rd]fhfyiQoCp&p)pbpcpuuLv3v9v?vv,$Z$h%A(7+0.U1G2?5V5_5z6G6T6c9N9R:)<j=*?&CICPCXDSGtK$L?OuP*P?PvRXRjSxTxVaVbVvXq[O]e^H_=```ucxlHrZr^wYyx,$8$:$t)t*..[.o/^4E4z535P6*6H7y8%8Q9I9K:0:o<4<C<E=?=p>w@QEyGNH9I*IGIsJ?JTKAMXN9NINNNPNQO&OcOuOvOzP.P[Q>SHWZe+e.eLehelf^fkg]h+iumDnNnso'o(pWpmqPq]sju2x=x?","qiu":"$>$F&E)G7K82;T@yBlEsLKTEVUVV^s_=drjGspwi,$_'D+'.2/4/E0d2M4m5f5g5h>qAvBgEFFjHDNzOLXIXJZ$_SbbcBdbevn%stsxw3y%,%D(i)o)r*^+Q.k/%051.3:696O6k6l?G@fApI8I;J&K3LzMoNaO+Q@aDaEbNm0msngnhoCpxsLuhxOyZy[y^","bing":"$?$L&J&P(K*0*z.%0S151:CLP*QYQfX4X5Xo^Leuhwk&pPpmtnuRvYv_xKxW,%r(I/'<bG%L3PHWRXGYIZ`[`dEu8,*r8?K6OhPZR&]1`B`ya<aVeSeofwmW","ye":"$@%1&&&/*j/'1@848R:S=7>i?@D(DwF^FkGoPcSMUeUff.fxgzh)hiiqiulXl^lklmlnq2qlrNrOrbs's)uJuKyo,$P$S*9+11L3T7o8p9]=B=a>g?t@vAAADGkHKIELfNjR%R.V5[+eslyp=yG,189l=*K*K<LcNTO0QnSSSdStUrWk`W`ZbKclerf;g2iZs0tk","cong":"$A&L5@7uA4A;KENu[U[V[X[a]W^K_k_wa?aqbKr:u*xY,$J&C&k&v)K4%7a7j8>8F8g;I>+?NA$G@H;H?QfTP`%gWmOmTmXm_tdu_yp,%A%x'm0(8s:;?Z?[RSSQTbTuhkiBjL","dong":"$B(n*a.S161E1W464d5%:0C.D:FKJ1K=MyRtS4T.T:[]_1c8d;g5iopktSvExr,.h.t1i3Y5d=.@/CLSs]E_CdIo.o:pHuAwkyb,&j.F96Ht__h9mEn9s=sbu9x%","si":"$C%i'e'g'k(x)b)o+L+]/[031c7@7H86:3>'?&?O@zJ&K2LRNgPXVYYG^7^qa@klo5tMu?v0x;,$8%K*j/N0_0v1.1W1k3:96:Y@)AxU=VgWjWsX%X?[e]Sc.c/dTeuh1iJj^l^l_mqmu,&k'$)T+M.(/6040R5Q>JNyOiOnPNPhQ9QaSXU;XudZdwe+e2eBeJfmh1hUhyivn=tGuDxHyp","cheng":"$D%'%()3*p.c1J1R92CqCxD7DgEGEPJdO_SZXp[P_c`[bPb`cid2eMeqgVhSigjak0kgkhksq=q^suu6v7xixyyG,'?'@'C't(//&1'1P2^2u466=9*9.:jA9AeF[F`G6K=OMPgQkR9TNXcXoY5Y[Z@Zq[B^Fdaf7j3otvz,+'0T308_<HA4A6IHKWMLQySzU9U^UuWiWn[z`Ic'fMhSi(j5n&","diu":"$E$H,,Q3WxdK","liang":"$G$J&*)O)l*4*L0G1S;6;d<P=BF@_ihmq]whyI,&O3_5sb8b;breWp.sfwN,.C3T9<<tC)F2FAFRGXG_NUS$`EhLlKlP","you":"$I&2'B(%(<(h+>/]0w6I7Z7^819P:a;B@6AII5JMNnOWQ*Q.SASUX:X;Xm]U^8^=^H_gbLcei@mgoEs?uivjwkwu,$H&/(c)@/o0'0W0p2U525p7L:VAaAbB$BpC8DDDEE0E9JGJJKfL=VwW[X]g+grk%k@lsm6nFtfwBwFwJw_,&S*_*c+j.j798V<`>GF5F]HuI6IZIuK0KxLmLxMGNOOqQ4WRWhgglzm9p1p;v:wCx>","yan":"$K%G)k*r+(.E/o04053C3H5x6j6s757?7E7F:S;C;N<`=@=G?P@$@C@R@oCrE(EdF;G+G9H3HBI7IIJHJNK+K0M=MeMkN4NENSOgR`T4TQTaTbUPV2V<V=V>V@YaYr[%[&_?a;cKc_dOdmeOhqi%iCiZn?pHq+qYr/r`rnryxFy&yzz$,$2&m'T($(U)))W*3+1+Q/z0^1h3m4G5(515i64717g87;P;V;j;l<<<==9=U=d=l=o>6>7>`?H?w@3@rAuCbCrCuF@FiGBJ+OBPZS6S<SrT=TKTmV`[6^O`&`jdyfjjRkBo3p>qxsjsmsntMw@xJxe,%W)g+m._1W3]3z5H6'6e6g6h7@8;9e;N;a;c=4=M=n=o>'@'@5A%E7E?InKVL*LPLoM+MWM^N<NBNKWWYqZOZQZR[+[K[P]p^*^[cEcJc`d>e[fVhchfi2iUi_j6l5lIlZnfqIqOqgr=sVsztRv7v^wGwJwQwRwSwVw]xFxKxqy2yO","sang":"$M=D=njKw7w8,%tUC,4:T+cOdC","gun":"$N`5x`,7*7PPsSpUSeRf1i0,%(%[1y2T3Y:JFKG]m:mopY","jiu":"$O$l$m%/%5*1.m3[565M5U5q7;9y<mHyQ;Y.Y9Y:b0gki@iiijjyn)onsrtHuxv8w;,&Y)O+A/1/U<$AiEPK]Y`ZLc0c4cZh2rFrOrTrYxn,A=M*Yd[[email protected]$","ge":"$P%Y&`(A(D*93T5F8B8F8c9.:E;%;A=x>6>KAuE`ZW`xd(d5dJe0g2j)jjltmzvw,%W(a*:6m6yAvBlD@DuK[OHSo]c^bc=h7n(o9q$qgr?s.ueyY,$r*(+*+>2s356G9h9wF[G%PYStT$TDX(Y3Z9Z:[C^.`[a$aUaoayd.fthgjgl4mSm^p6qyrIuK","ya":"$Q%m%o%q'L*%1>4(6q6r6x6z8T9(:h;X<LA_AkArCOD/D_FzJLJ[KpNyR>SxSyXJXVf6f;gBhji_tuwFyMyz,.p.s3Q7V8[AdBtD&D>E[FqIEKMKkLDLqPyS3TrUGY9[+]:m>t`,&d*J1d585:7/;yEEG9HQK*O0REUTWg^`qhr2s*u4u;xiy<","pan":"$R1B2Z7nBXLjW^fFfTjUm.uV,%U0:181J5o6f8V:a<;AIASJkK(K*OJOVOnOoOxPIUJUva1fIm/nBnqqNxs,$V0>2X557]BNCuD1QwT(VbZ]aTbarp","zhong":"$S&q'('A*t1*2Y=:E3ETGTI:I?L?Q:We[:]$]N]XnouX,*`/j0g<0>JC&LvO7P]VsXKYXZ2^1aDcyenhZnYp^rzv7,%s*I*Q+t/V/p1P2'2*2+9OCWD?NSOSQISaURW1Xyr.x:","jie":"$U&I&v*M*P*w+V+l/)2]2^2s494J6O6P8c:s;y<?<w=V=z@(DuE4HxI8J$KWL<LFLYLtNWOiPoQPQTR@RKT6T`TtUkUlUvV$X+XL[f_Nd4dLe0fihIhxi0i4iljSlSlqlvo@p7tDtRw$w:wCyB,$6$R$]$^%6(4+l1K1z5W6w8R>vBMCFEZGPGaJcJdKNKXKhL<N(NLQ5S0TrV3XwYW[p_FcHd2d>hfkElgp+sytGwSx:,%G't*U+=+P+k.Z0w1&1G1b2%2.2I2n2q354=6I6M6w8.8`8p:E;i<F<YAVBiC7I$PAS^ShYg[y^&`ua&bld)eEj[lmmHpDsQsW","feng":"$V&x*$+)/.191o1s1w1y;mCgE2E6GXHGIPPUP`SQSRTDk'u9wb,$9(&0A0F2i4q5Q6(8$;E<>=W>.>N?TBDD4FyKrLzOpS>U2_Ne$ffi[s8w7yO,)6+]175<9b<)=k?h@vILLfLuQ]TKToXI`+`<dJdodqgTqMqQqkvr","guan":"$W*:0Q1(6COJ`)`*`bb+i:k2o%y8,&J)b+g1>3M3l8C;NA'GAHlIBL^M7MjOWRJRRRSV]WN[$^@_%eFhHj0j:rcwD,$(5F5n6$6&>r@MDNFNJ<R^TTV[Z4Z8ZnZs^uewg*o)oep)q+qBu'v+","kuang":"$W/U1?4I5[5d6C:gB/G)H:Ri]h^bcccdePp'prrkw*,0`1x@kByC%P4PTRBRvSbSgVLZB^(^Td+d8gqh;,8D8O<A<b?*@TEPEZEaEhHIJtK>LiPOQfVArjw1","chuan":"$X'J.9.i3X=2AVE8VAVCrAynz%,*0.a/>D;ENGbZU_Kq<rfrlrts/vB,?ICUFXIoNnVvs_","chan":"$Y%z.d/5/f0`2c393Y3y6;<c=H?/@S@dG7KxMfNxT;U6U=U>V/WpX$YE]=ckcqi8j(jwkHkQmGo@p%xFxa,)E+u2F5t7M8x8y9a:d;<;^>_?sD`J8J9T+UUWWX&`7ePf8gEg[gvgyi_kRscte,$+&D.O/l0.0J0]3I4k5R6+8U9*:X;I;T<s=1DcH=LlLpN*QUQ^TnVWX0Y`ZIZx[RaacbdFfXg1jM","lin":"$Z%U.v111f1g7J8[<7G5SmUSYSYT_%_Q`AcCcJfHkro:q[rGtz,'3'l(?3n9&9I;[email protected]$KFLbMvMxR)TRUr^qb0bFe)g=l9qDr2xM,&8(P?5@`DFD^DhDyG$G7GmJJK=L_U5ZK]*^=_]iLo^q<vJvY","zhuo":"$[*Z3D3h697h<2<3?UB(F2IZK<[6fSgph$l1lHlenZo1o4o7o8o;qIw2xDxSy1y7yQ,%h(x/=2@2T3b3y9l:E;D<(<X=O>5@'BjG4GJP_THWmZ1ZGZx['_na5aOgYisjVm7uOyU,%$'v0v1I9)9;:L<kAkM$QgUjUmYYrvtAyy","zhu":"$]$b%N'U'r'z(f4&474=>A>x@pBuF_GFNTO3OFPkQiQwTNWPf:f>nKnZo>rzsesfsht_v)v1ve,%s&e'O(x)')+)Z+P121d4i8s97:$;&;b<P<f=5>W>u@;@KA/D8FFKsLrP;QtRPSMSfUdW/W;Y$Zb[]]%]&]/]J^)^I_>_O_r`$`Iclcod3hMjFk2l%s'tItqu5v)v9w+yU,%=&M(N*o+5.r0j131H2u4&7M7p8C9c<I<g>2>v@LBIB]DSEoHkI:IUK@P0PuR'V(VjWuX6]keAg[gwhAizmPnToGrBtcv@vBwk","ba":"$^&F'Y0I7c8)8f;3;7BSC^G;H=IWRRS'VZZ3dueEeXekfNgssjv%,)^;a<TABBeEJKgN?NKRi]4apjLjbk'l[nctOuUx/,*45A7l=xB7BAErNfO2WA`(`idRlElam/m8p5p7p>x7","dan":"$`&4'>'q.k/=2F5'5k6;6>9i;N<D<E<n=H?0?;@HI3L3VuZOZTZ_`F`aa4bec0eZf?i6kykzlVomuu,+4+E.u0&1C4/9d?sC<EgIWJ(KOL$LtMdMuO/P$RjRzX'Zu_0`PcTg[m(m)m1mgnap7qYq[xb,%0*z+l2(4)4Z6A6x8S<L?Y@%@tE%L$LaM0Mc_ub`esfIgehEk=r(w;wTw[","wei":"$a&7'I'T'x*[*x+&+W.e/c6Q6W6j7q9^;l;r<q=;=N@vA<A>AWAtFAG/J(JWJjL/LGLTPHPhQHQbS9S@T1TBTcU$UCUqV3VvWIWUY0[n[q`Q`w`zb:c6h6hNiIizktl3nqqosaw)xHyqyr,$X)J0G1R1r2N3B4w5%5E6.6L8K8W9':F:Q:y<J<i=+>X>f>o?`@NA<BPB`D&D3D:EiG1G^IAJfL=LnMkMnQPR6SmT%TwUBUKe;f%f'f?h>i2jfn^pes?t=tjuMvlwrxayeygyr,$3%H%m&='1'^(E)8.8.B.b.f/d1f1i4K5^5t82939m;H;Q<n=+C5DfDjEHFqH[IaJ)LZMZS1SCT^Z_[3]v]w^1^S_o`*ajapaxb)b0b4bkd[evf/fPjSjTjUlQm5mNmXn^n_pFpuq8","jing":"$c%h&(&.)U*L.?/80@1J1R2d3$424@4OBIBKBOF'I6K[K^KjOCVFWoZ@ZI[F[S`<bwc2lQnFoRoSqMqTrEr_wWxI,'c+$+)/^/_1H2:3'4695:uCgD[HBH^HdL7LGPzXRY3ZS[a[b[j[n[y]$^kafb=bHd.dve/hbmGnVo1obp:u]v@vDw<whyM,0Z8h;&BxHrI?QiTpYF[t`E`H`K`L`Nbec.d(iXnBpkrfs7s:vPvZxC","li":"$d(b)R)])m+c/a/j1^2K2`353]4%4'4?5/6m6p7(767A7D7f7h8M9@;);P;v=K@=@D@c@fBREUG4JcK5KrM:NQO'R(R]S=SDSTV%Y]_d_h_n`'acdadse&jXm)m8mTm[n_r0rPrisot0t?u3uPv=vHvQvUx:xJxUxl,&D(@(k(v)*)R)]*c*f0C0R0S2c2g386M7f9Q:U:t;W@c@nB7B8BQBWCZCdF;FmFtH*HAI/I2I;IOKcKoLPMsN+NqORO`PxQ%S%SNS]SaUzVPVQVVVcX*X0X9X[ZH[M[s]N^=_l_xaJaqb%b>bXc&e+fhglh*i`jdp's9tku%ugvNvmw)w/x0,$@$D%2&<(2(L)<*g+&+:+e.+/'0)0V0f1)1+15313C4C6b7Z:=;J=e>SA<BTDaG4G5GKHbIPJcJgKiLwN.N:NRNVP;PoQvR$R;T$TzV=X@Y3^P^Q^R_&_9`4`=iij4kWl4mxn'nFonoxp*pSpVq@qFqvs/t%u)uPvQvVw4wM","pie":"$fMMk]k^rF,.[8LQpu2,5OU?","fu":"$g%H&V'9'?(1)N)Z)^)r+C+`121v2R3Q5J959<9s:$;;?(BvC:C]G`H'I1I5IrJgKQKiL;MoNaO%OEP(PbRaS*VfW'WWWqXZZ+Z9[A[l^>^EcfdxeDeheif<fDgqh>l+nQo+oOsCtquGu]uzv%vzwZy2ygyp,$x.f171[2e3L6v9=<S=J>(A@EXEsFoHvJAJLJ`JgJnM[OKS&SKVzW$WbWvY'Y+YT[P]T]_^9^[^t`Rb:bZc_chcsdGdpduf&fUgghTh^iXjBjPk^n>npovpBpCplq8s6skt;tEtauIuNv'v<vowOx$y+yK,%D&f)[*S*V*h+1+`+d.c.g.u1x2P2S2h3j3w4T4t5>5@6j7T9R;f>+>g?X?n@=@j@xA>B0BMCaF:F`FbGWGcJuK[K^LJM6NcNhO9P6P:S3SD[_[`]2alb2bvdMdRgKh)iwkJl6m2m@manmp=pyqEqJqXqsrtsSvdvgvlvswbwc","nai":"$j(J*fHFHuI^N3O+Ygj[k>v(,.]59KUlQlRoCp;svxk,/L44HyNiRsww","wu":"$k$s%g%t&t'7)0)K*d.r/M/s3O4/4h596.6c8r8s9&939F;V<<=uAwBTDtE]FXHeISJiK*K.L&MOPBQUR2R?SbT[TwVQXOYKZ/]P]R]r_<_e_f_u`Sbyd*e(e)e2gijkmsoBogp1qBt%t't.v&x9,'0*;*T+f/K/L/S031a252f4m6O8S='=k>%?5?EAtB4EWF^F_GyHOJ&LTR(RpTcW8Zf[;_BadqRrit>tVurw%,&i(W+c/B0O8F8b8c:l<Z<^B*DZHSIFK.K]LBNrQRQcQdT0W:X9[e]H^0_@_D_a_n`chijEmrnyr8rZrls`tCuNuWukxAxQxR","tuo":"$n&Y(+(X)=9n:2<*<cB_E0IOLNMQReUXXx[7e$e/fMfOfPgOh/l3t6t?uOulyl,$;%i':'L.(.A/C0N0O0P3XC1SESFTq_.a:ctoroxw2xm,(V2?2[7'7d;oB;BDM;P$QaW][g].]/e3fagWgXgkh/h0i$iPi[imj$lcm.mdnqqtrXuCwpwtx9","zhe":"$n%O6n;4<N<u>A@<CtMF_PbCeFegjSkPq@qAt6ugxb,&Z*l2O4'P_RqS5UNaUallGm?yU,%j)w+J+b/^/w/x2`4D5/7r:A:P;C;M=DA7CYF8F?FtGVGlHWICJDQBS]XUgXmnt5uv","ma":"$o%Y+g8U;^=i>b>cI2LlMLN]XCf3k?tK,%<6JBNBoDOEUH&LaLbQ:RxU6VjWtj`xM,&2*0/P/y/zJ:TEYlgRh3ikj*klo&t.vvvx","me":"$o@0@:@NXC,:O,vwvx","yao":"$o$w&w)%*2+:+w.l5E8D:B=+=]C<E'H)I@J0L%L`O@Q1Q7R<SETLU]U_X8[p]&^H^gaLf%iyj@jrkUl?qyrgtUtyv6,$*%*%5&@*o+W6:79<s=)?@@^AEC7DHDnFMGwH4KbMANVP/R;URVlZTZ[Z_ZhZkZl[1[2]s_?c:g+glh8lBnNpcrJsTu;vjynz%,%$'V(;)(2D5;5X707b:6:7;S==EuGLJ/J;JVJePySsW7X'ZZ]r`rcZd^dyeTeihho/o`q.q`r*syt7umxNy%","zhi":"$r%Q(Z)j*/*R*k+E+]/Z1u2m3N3x456T7$8&8p9X:AB6B7B^BxDBDEF*F2GTIbJ@JxM]P6S;TIV[VrW)W.WrXaXcY6Zo[Q[`[w[x]E]]^dbCbNc[cbdBe5eHeIevfMg'g+g@h'i5jBj[k)k>kCkElulvm+m^o*o_ooq&qXtMu)uAurv:vCvuw4x$xOyKyd,$<%B&+&s(d(r*P*[+0.U/3/W/X080Y1$1_2+3w4K6t707A7c8J8i:Z<G?^B<CaD$HMI0IKK$KRKzL'LALBLQLwOgPNR[S+VOVnVpVxW'W>WUWgXEXQXTXhXqXvYCYDYeYtZi^EcOc`dYd]dxf5fqg:hJhYjXkgm.m:mJmfn<nlnxoHqAqOr=r>rArBt8t?tYuYx?,(8)7*B+G+s/e072/222U2V3`4v5Y6=6U6]7:8J<4=l=m>>>t?]?w@F@[B4BLBhCNCQD.D`DbE>EtF0GGGPHbKGKiMINePlQ>Q`V;WmXf[r]M^L^U^dg]gdh6i)i8iEjBnIqUqxr<s_t;uEw`wl","zha":"$t+A3U3g6v8P9v::;5<z=?=MHQOd^%dqf'f=g9iwjik9sdumusutv5v?,$&%:&[4r6F8r<%<g>gAZJJL2O&O+PFSA^uc[celnu@,*`*j6V7c98:^:n<6EEN%S:WtZ.[:_KeCmAmip<pOxVxY","hu":"$u%%%A%e*+1;5]5f9g9w;o<+=0=Z=^>W>d@9A5BwGHGIGLJGKbLWMGMHPARlVtWsZ*Z=]l^2^3^r`Ld1dQdSdTdXdYdZd`dkeUesjZk8nvp:pDs*ttvs,$A$B&0&2*?/n0)0H0w2H4@4B5P7>7J7K:?;+<o=Z>z?[C2D0G7GmIJIKI^V6W.]=_<`6aobTd9dwfHfZo%qRt2t6tVuFxRyj,%n&.)O)P)X)`/$/N1e6Y6^:R;9<$>6E_GILNMkRvS;SZ^T^k_CbJc*f$kdltnKnrovq>qVrksNs]sesrtouRudv)","fa":"$v':(G.$1C7dBqCCFHImS>ZXvk,'+0U0t2B;MF6GLL&N@NBQLS?]W^'jDjZjcv1,&^'pMrN7S%Z;[Bk@kD","le":"$w%X&@4a89>e]5ds,$d&@/+0oAiEISU]'`Gmzsr,[abAe]fto9ozq1","yue":"$w0&0(0/2L:l;@<F?XIFN9R:RjUx_7_K_md)e&eVhEm)s$s%s>tevH,$d&@'&(v11;;@yE`R<RhVfX2_?_^`yaCaNb.b?c:h8qq,)%*<*=8i8k<cATAzB6B9D[EIO7P<VVW7WLZGZH[GkPttu%wLy_yn","lao":"$w(B.^4A4B4m:T;2;c>$>uJ;MDSeUQ^`bpbqh0k_s[vn,&@'Y2m3?8e91=3AmCMFULVMaSvUlZX`[b3dCholClDlelqvPy;,+I0EE6E<FxMDN0Q(ULWdX7cUk3m`","yin":"$x'<(c0w1Z6V8^8q;n=)?H?q@8@xA(AKB1C6CBC`DhE1GwJQKfKoOxQCSaT+T=UyY?Y_Z)a2afb7babbcPo*s:vqwg,'n(C(R)?)p*3+?+Q.k1I1Q1`494L5T5i6[7+:;:<=&BuC]CoFHHJM0MXMeN4SpTaU_W^Xt[(]rakdLf2fjo(teuiv/vfvq,$7&%&)(v*A/q0I2w7$7*739&9];VADAfF7LLMMOAOOP_Q0WrX4Z`[h[w]_]j]q^(^:^K_X_g_q`j`zb=bHe<e@fihBj+mQtExjxyy@yF","ping":"$y)_191x2(9YBaE:J`QYQfRsW3WDWZX1XobIb[u>,(.0x2(3$4(>/EqIaIlJOSQSt[q_9`:j&mNnnsluGvMx`,%C(b*a+<7h<2EzFMKtPZbtgTm1p8","pang":"$z6w=tGXM&Q2X]Xk[9[ooG,/k056i<>PIU?_jlmnBnqo4q4s3,/55fB3I._7`&nzq/yLyN","guai":"%&7bH(^D_$fJuBv4,^djU,","sheng":"%'%(+13K3R4l6+99AnFSGBJdTXc(nsp9q=q>s1u/yG,%L'^*t+R134`555a9J>@B&C.F(G0J5J;JNOMOtP8[V]Gf>g/gOi1mDmanwuJ,&@:t?)?kP*SA[l]L]hs5x<","hao":"%*)6+k/^859e:w>)?'?C?y@*G%I%^j_Tp<pXqEr(r.r7rWyA,+w.12`3r6o7.9>:6;Q;`DTDYDcNQNYNcNeNhNlXM[U`zlYmCuo,$f'+'/'Q'n)b*K0s9?;;>0>OK`LET:Y:c[dDnx","mie":"%.8>:?;8NtX)chjM,(n6l:e;p=/P:VI`0`L,%d'80z1T5OV<p$qr","nie":"%.<]>1?M@7@`@[email protected]/S*U*UhV;VngvhMhoiOjokFmKn6uM,&5)33%5wL4_ea'c%c)m0mer6r<uDwt,(m1/;ZByC9C;CtDpQBR+RRTAV.V^VgY4Y7Zh]U]xcjd@xz","xi":"%2)D)[+m.]0L1i5s626K6g8w9V:;:C;Q<)=6=T?+?A@O@lF3FwGhHXK/LbMaMdQMQ^QaQnQxToUGUmV&V+VsW?[H[[[r]H]S]m^F^R^_^n_5_O_[`3`Na]a_bcbdd1dQdSdTe0e?eFk7pFq<qNqQrIrqtMtsu@vPw_y]yy,%O%u&g'(']'o)m)r)z*D*G.l/B1]1b2V3h4b6P6q7Y7p8[8^9C=I=[=c=z>2>[?4?6?:?K?l?m?n@F@sB0B6BJBVB^CXDpEuFrI%I?M6N`OnPmQqRLRtSuT^UHUqV&W]WzY(YQZN[:b&bqc1cgdoeTfRfkgKgQh*hXhwk1kHkiklkmnRnSp<q;rMrNs4w'x7yFyw,$F$[$m%B&m'*)l.)/7/90'0@1?1U2d3_5*595[5_616`6d6f8P9Z:%:K:]<e=Y=Z>.>5>[A/A3AQAcCmD)DvJsKFKMKYKgL<LtN5NVNzO(OTPFPGPpRbTBU%UDVZVxWvX`Z@Zv[M^3^9^J^O^z_3_r`.dde^f6fHfdfvi/i;igl)n)nnoBoapvq9rbtew<xI","xiang":"%3&'&+(C.U/g4w51748O:d<;@LGWJ6UKV^X_Y*].`fq/rYvS,$f'K)B5R8PFLI@IROkW7YO_7dVefh%iAj'jujzkkqUt9y'yW,'6*1010`1a4R4_81<T>%BdKzL7L8LCPcPvUFVXYaZ=ZX];bIbOcpe6eWfQfYfrg?icjQmKn1oRocp&pPvR","shu":"%8):)a*=*>/h0H7g:FEyF)J3KNNwPkPvQiQwXuXz]Z^Q^R^p_Ld/eagogyhfjpm2nJnRqnqprds.sesfshtAtZu0vKxE,&]&x'i*y+M.?.@0K3t8/8B8z97:*;/=]?QG3H7HxKMKPKQMtXjY6[X[ma2bwcId)dcf(hPj]pYr]vQxO,$%$I&('O'Y(M)m+Z1>1^3+4p4x=i@4@mBuC(EQF_GfHoL1PCRgTr]<]r_ZmIoqowrssFw3x2x3yf","dou":"%9):0:0>8I8y;Y;aeenro'tvx<,'b.32X4]:]CWLFQb[&[I`.owvn,&6*X<j=aIAKXL)M2O6QJW?Z+Zo[j]Oeefyl%l&l*l.l/","nang":"%</q@@@i@sc/j;lEm]rt,)_3U;>;e,1:fYf]g;x[","jia":"%=&v'h(I*v.&/)4.7m;A;L>OB5ClH7H<L)LpO<OiRcWb[O[i]T^xd=d@eBf2f;figEgelXnunxuDuEx.yt,$u%4%m(5.$0f292pBBD>DAEyF.JHL0M/Yg]bbclanvolphvTwHyl,+K+T2>2n3.>3>W?:@]BEHeKQKbOsPIQYTCWPWjY=bwc$d)d*h%j&qor@rTvT","mao":"%@0b0f0o0q6UDtGkLPRxT[WOa5cAd_oJpgqrtiud,$?+v.=.H0u5/AqBQD9GSNIP&QJRQXM]feqjHlFt_uPuSuTy8,%;.V.l0&2Z5L>R>Y?1@VEXLHL]M/P8P]R_WXXXk<kIsR","mai":"%B'p405)6<>qCnGD,oNoOvg,&P'a1Q?'?UHFJW_h_i`0tXv`va","luan":"%C%Q%T6[AhAiHpJ_NRNqO1SHV8gAmQrvvy,)T78;U;gN:N;jtoZr(r),'7)L5qNgQ8VerSu*uLyz","ru":"%E(u/D0C8y=p?xHrI*LfN2O*UzW6dyg6llrcsxw+,(S/O2'4y6d:7E+^&fYgbiYn1v3,$>$w&_'b.h0t2t434uH/JqL=N?Q+X5ccdGosqNqprG","xue":"%F3*8v?dBpFmNmO(RZRzUcZg^NnCncw<,&o161@6o9S;%@@C:KiKyR&ZJqBsSub,$*'E1J2K6^:(=)AZC%FsGxH&_0`ga]oNq3t`uB","sha":"%I*l.A/?2p3078;i<(<?<S=<=_WKY2gWgXjvswt)wR,%/&f*1*_+T.4079s>eCcLURyT>^laecMgahCkskzw4x:xc,&/3AT7X%ZEZM_TkUlimymzpZ","na":"%J0d6=8u9:;*>7IJJse_fIfzg6hLjf,XC]H]KcChEnG,$>$Y2&2]9%>C>FEVJzKOO;TMW2Y8_1`lly","qian":"%K%P%S&^&p'M(;)V*W*q+o.O/K2)2A3/6'7C;L=vB%B&D`EtF>FtHvK_L8N7NKNvRCRHTZU(]c_Y_t`yaib=e4e@fKfegYhWhgi*itj_kRkWkdm>m?mAs7t$xZy_,%;%b%z'V(L(f)c)i*+*7*Z/J/Y2;4H8Y8Z:I;L<e>ZB)B3BCEeN_UI[Q^X^x_U_f`pa4aBa`e8fogeh6ipkBnQptr.t*tCukv8vcyd,$N&1&?)V*6*G.>4>9::/;6=@=N=RE[FJH?J9JMO*O8OBP5P9Q7RXSiU*V9VuW6WCWEWW[daec;hmhpi'jHkskto2q[ryu_w:w@","suo":"%L%n+y;H;e=h>*>/JhLt`TdcgWgXjxqzwQx?,676`DdFwFxGvHCPb`C`FcXfLfiihk=w4w5,$x.<46AaINSpSyTITOX?mj","gan":"%P&_'o*K1X2&9lB`Q<Q>Q@QAX0X7]Aa=lBmkn<owt&u`wf,%8'.'u/h0s447z939c;kEOEpJ.KvNvOcRoXDY2]+^R_i`farcqhRn7t)uE,1q7_@/@9A+A@A`H>M(jWlRokq?qOyj","gui":"%R(O+Z2t2v3m3o5a5h5i5l7>AxC?IUJSL^M<MZO6U[UmV&WBXIXiY0Zi^lkAkcm_m`p=qUspukw&wMy[ya,%v&4&9&:&z(2(Y)2)9*g/15:64<3D2FPH.H[I6MkN>NNPKQPQlR*ShSmW<X(Zg]o`4`=oEut,%%).+E/O0?2v4g5I6(6J8)<O?$@SB/BaEFEMG:K?KNU:V4Z>[<]@^zaZi%l8l;l>m[o]olpCq:qXyZy^","jue":"%W*B+p1=2J3e5r777h8v?<?J?d@ZCiFmIFNXNYQtQvT'T9U[U`Z7Zfbkc$d$eWg=h$hkk[l'mYnhw^,'E'F)/)q.X/m16;O>9?X@'@pA%A>A?DfE=EaEcF5H2HXKiM4RCRTRWS$ZGd7dXg>hpqctW,&[&g)v*E0F0G2]5J5T5u6/686<6T6c758r:e<.=L>cAGASB/DDDEDxO>UGUWVhYLgjjtq:qaqbtD","liao":"%X.a?)MWPCPLQ&Q/Q0QuU4UTUUY@YUbJbxjykXl)nSntrBrm,&Y';898e<A@*@m@qDoHWKYM]QxZc[9[D`Og*g@iiilm8q'qI,%N((0=0E=]?rD$DKH;JRLKN[UJVsYMYhdedljytQux","er":"%_(J(l/r0.002l:7;uPqPrPsS1YxZ$t4vhvix%,&q.*1Y2%AHFKb5lNlQlvm=o?vE,'i1R2r8>>u>z@NB$F$G.HhJ^PXWe]?^GeZfph>kKkLmLpGr9uF","chu":"%`)y+r../</e1q202C2S477:?.D?GVL_R6X*YD^Oahc+j:k8kJmyo<tWyV,$@$T$r&U'['f(0(`(m)%)m*J0n6g6h9v<XBIFfHsJsRMScV4WY[N[R_ocwh_l`ldqdt^wm,$H$S(N)W+h0S6L6_9>=q>$>`AXD>DUDdL>P+QoXBZ<]R^j^vslwBxvy)y:","kui":"%b+Z2i5i5l=9=S>zGgHLLnMbQ9RvV1V?_daDaEb]dEiDpyqk,$5$7(]+B6'8o>IBaOFQGQPR*UB[%[<_W`U`wmUmWm[mdoEqKyt,$/&a's)9)C)j.w9tBcD*DwI`L6SJSYZq^1bWbzcSf7fEg.g=hwjClC","yun":"%d'G+e/t555:9B:x=1A3H;HjIBN[_C`ea>aHale]erp2q3qgu+,$l'<+*+8.y.z/w343D6Y9:>M?$?0?7?;?ZBxEbJ^OvULXN^:^V_ZcRf1f6fOfVh?iHlZm&p]tZvuwgz(,$;$^&Q&o&s'((J(a/)4*>f?d?z@>A'HNIvKUKjL4LDM7MqMyOIQP[p]V^/_8_jaNavb&b5b?bEezgMgby'y1","sui":"%j*N;:>@D1G]JuMsQIR7Tfoe,(**a*b.>2t7&9f9t:x>r?U@EHqI7PKQ'Q*S7T]W1X)YmZ+Z5drfQg$g6g_hxi]qVt7vxvy,*)4i8u:y<v?WIkImJYU2U@Ud]z^'^A^B^qa4b*jok'","gen":"%k%l:finj.vt,seuj,BU","xie":"%n&3'^+/+8+J.G/i0x13445(656:6N6_84=f?Y@?CGEiGdHHHOJeLMNNPIQ[QjQrSMUkYR[e^eaTa_c>ftgEgeirjDjel9lWlzmJnwoqr6uIvbwrxB,$:$t%/%?&f*50c1E1t4z6q9O:`:z<&<U<V=L=i?3@L@P@tD@DuE$GaU9VkX:bYcid1d>dNdmesf+f:gXgohSikivkjn[oKoMoQq*,'L'N(1.T.i0W0l0n1J203l4I5%6E6I6M9Q:3;Y=(=<DmDoJXK*`qa'a@aSawb:d)m[pCxTxkxnxxyc","zhai":"%p)'*i+N.;6n6v:s@(GZO7PFevfdh*k.lIm+nfni,%J(7MOSHW?ZZaakv,>s@AP7x]x^xc","tou":"%s+Q+RD?H2I`L*L]a%ednBo&,cEf(,(zI9QJSPbxeAjZw.","wang":"%t&<'$0DI.Q+Q3Q4Q5[<[B[E[O]F]h`JePp*q_sPsQsXtlxu,/]:^EEOfe@j;j<j=j>j@wIxG,*M+A.J8vFDG^HIHklO","kang":"%u'35YA/M7U5Xv]kbAe'ef,&88*<CBqS*Ypafbk,E9JvOYU&W<Yw[8oM","da":"%v3U5L9i:%:i=m?RCQF]GzI]^5`abedvjWko,/A016@<M@SJnJzMCP2]H]X^.gNjxlzv?vS,'B0[4/7mBmH<HMHTHXIdJ(SlT)Ux`oa/abyTyV","jiao":"%w(R)%.l.s/>3b3n4u8'96=F>H>J>V>m???`@ZJ9J^MgMnNHSFSIUOUZU^]&](^o_TbWbmc5g3gHghj/jykMkvl;mXn&n3nEnWnYnho$q$r&r]v[yP,&R2=5f5g7(7i8N90;D;]<s>*>S@'@<CCDtF9HkM_NTNmNtRbRfV%Z0ZcZm]3]y`Wd@gYgwhqiso<oapfq>qPr5stv%v&,&G(6)c+90:0K5J5T5u6/686m:h;%?=AxBZC+F'FnFuGQGUKLMON4NHNlPVUHX.eQfuiSj.mYoTpMrKtHtPuyyb","hai":"%x9x:I=k>.@?EkI8NpOffs,.m2n=RD@dQo8,HVJZKDMVN&eNfTh?hFj1jc","heng":"&$;><6JD^a^m_`knw%,&i'U3G<uFOoAod,([1lV)r>rPuI","peng":"&$*E.63^5C>tDYEVEnZN[/^@_8bSewg^ggh9i;j<k'sAwoxmyTyi,&.&d0x3q4(8$8.98=S?TL[NUSRStTJU(UXYG](_j`'dEgknnqFszuGw7,%>(l08092mCMEjFIRAVCZ1bBbFgti+kRk[kkrwu^","mu":"&%&j1t4nBmF9IqJ;JiS6WhWlasatfAr8r9s_sn,$>&`&a+h.'.0.G0.<?AjAlArB'C'JXJ]JiJtJuK0OaQ0SLYqfsg*iinzsHu(wQwU,*LC'PEPJWN_4_HaH","ting":"&))3);+66l7+8kAmJnKzTWX?XKXlYZY^Yb]8gawUwj,$E%E/2314n9y<r=N=PFdJPJR^MdqlUmRmcmkmlohs=wAyu,+n.U8R9TJiQVWwZD_La1c&d+x@","qin":"&0)7014s8a8b;]>0?KB;CsL5LoP/P4P;P@PRTiU(UNUVXFY;]cb6c9c:e@eYh8j'j1l5lTo9pCx=,'y*)/t6W9j:pFGGFGKMWRRRSX;Xe]7dhm%n=tKt[x5x8xE,(S*G/E/o0c245=5e8YAHOKO^QjW8XQ^]`ec?hJj8mkqWrx","qing":"&0*m.D/_1T3B4[6f<VATD3GpP$XDY$Y8`7b@hWlPlQqRqqy<,&F(6(T)&+)+R.i.r.w4F4S537R:@J6T$TQUg^ke8e<j.u$y[,.A5e95:<<fExF;GMKoR<V1`C`D`JbMcnn0p`wK","bo":"&1&a'Y(1)>.g.w3?3G4Q6@6B;3<d?5@5FmO)UMW+[6a[cafcgRj9l%l/lYlZu^v%wX,$x(+(.)D+/0i1*2W4M4s60?1A_C=DJEvIGIIN<N=NqO=SWTTUvVGVZX`Z1^o`K`k`rbuckj%n)ndo]q&s*s@u7x2xtyf,%g'.(n*m2f2g2p4^5&8T9s:iB)BQCEDAKfOkP/P@QWT'VTWGWKWTY2e`f4fxg4gAgDghh@iIirjqjtm8oSp>r^uO","lian":"&5.L3i5m5n>??DDkH?HhLOMXMuW(Y3^6^fb3bZcwk/n5n]xQ,$C%b%w(L(z*I+++H3A5?697v8I9Z9m:';0;4<k>O?C@IFvGfHGUIY_`[email protected]]m^p(q`qhwXw]y.,%@&7'?'I(t(u/<0i3D3E4A4l5W:FD3H]IMLjN<RcS*SoTVUiX<YZkhneo7pT","duo":"&6&Y1d2k2x3A3M9o:]:q=?@%@PC=C>DCDdFTFUGmGnH8HiHqLNQ8T(Xe`cbgg)g*hYn+n4n:nDslsmt7t?u2uOuPv&w=yn,.80N0PJjLSTLe*iKs),2j3RA^BXB[BqCSE)E*E=O_UsWa]8]=]z^+^MeMfngWgkkcs3","men":"&7&k*?]z_^`&`McGcYe8h=nqr4yX,/i=q@:EbHHQ]QiYsx+,)MS&W$YkYp[([9a2","ren":"&8&9&?&]&l&z292:G>I4J/R1R9]6];]<e6sit4vZv^x%y+,AnVtX@XxY>c?cSd/e'h=hFn/p?tDvIvpwt,232l6y8K;g;tE/ENG=NwO.OEPj```dakb1e8eOfel_rJ","shen":"&>'c(W)<)d0=7T7U7V7W8q9f:XDcIhJPJwKyLoN>OSOjPGR4SYWfZ4aZame+eZjbn*pLrUr[ujy+y;yx,$q.g0$2x4>4?4e4f7D:b@&F)J0J7J=JILuMHP0P6QvRZR^SYW0WEZRaTaVbKbLbhbncjhWjCjQnXn]okp@w>yXy_,%3%k'=+^+_335y727I839A;G<J<q<x=$DzK%PLQkbnh<lnn+nOo6o@plrmwT","ze":"&B)'+N2O3'9v;y<U<Y>]MAT?WMWkX@emfdgxlIp5pI,&K*d/[email protected];DNfQ4Q_RVV1Y.]]_*`2lns(,&40k4f98:D>s?q@AA$HmeCthxmy.","jin":"&C&H&N'<)/.K/(/J1e424@4O6a7<;n?V@)CsDUE5F6G'IAK_M>MkN+P4QGV`VeY;`?b6jLo(q%q'tf,%'&=*=+=1p2K2o637_9p:2=F>h@ZF8FuGMH$H<H`HuOSRRRSS=WDWS]']@]zcUc^eXfCiWrBvOvdx=xE,%E'y254n5m666::O=B?a@.@eHOHYI]NWNXO1R]VlXe`ffCg7g_v0w)y;","pu":"&D.[5G?IAMA[AoCwDpFIdteyh'l4lJmcmdqLr$r>rhskuw,&w'z.L2]6K9%:D:h<5=MDjH]LOQsY'Z/^[ggrarbw*wwx;y`,$W$X9S:s=K@(DJMTQuU1UZX8YNYR]Nmu","reng":"&Kdw,Vdtb,H6]m","zong":"&L*8*U+F.5DzOIT^TdU2[a^U`U`qhFiRj+k6pasWu*xhyu,&C8>8F8g>+?N?Y@HCwD1KpMLTPUfYYbGbSbxe(eQe^ezf/f<faflfxg2hGi:l*pKz$,%'.s>;CJCLD2S2V%h_hvj>kYk`l9nHnV","fo":"&M&w(1BixM,,","lun":"&O'P(m*YA?AQD6KkT$T%`2ephVxX,0D486ITeUiY:eFhHlfp2tTx%,.*9@<&C<FPG@R6]^nC","cang":"&Q&y'Q*7+q1_5cTq,)N0E6k:NDXElH0_sr1s%sOtp,$c'z/W?iV]scu5","zi":"&R*b0W3<8E8p9Z9]:><G=y>3ItIuJ)JUNVN]N^NcNzO&T>Tz_'t/v`wzyR,%1'_0;1^3g4[5x6r6z8(9VB.E@I&JTJwPCPDRnW_XBXlXuY`]Ya[b*cDcbeUedgji?lVnjnooDr4t5uVuXupv*v]wxyV,%M'5*$6B7P7Q9X=2>y?9@_@cAFA[AqFBFaGaL?NoO`ROSbT/XpY+c4c5kCn.o*pns;wyx`xcxoyE","zai":"&R.(/@0l:`AsOcTKdzePvx,1O576N<)<*=0JTJwQ?f[wx,?fF/GOMB","ta":"&T)$+x=m?v@XEFENF<HxO5SlfMgDjRl=,%)%M'h.D013a6@6b8+9i9wAkCIE%E4ViWuan,4+8z;8B5C1CnDGDPDqJ3J8P$RJSlStW]ZiZv[%['[>[Za$a:aQmGo.q*","xian":"&W&X'W(7.P.p.y/$0$1F7Q9l:4:N;1;N<Q=v>[CYDAEeFvI&IaJCJPJaK6K;KtM$MTMUMkNKO]Q'Q(R'RNSVSgUiX.YYZ<Zx]ibuc&c.cXgLhRi8jDjIkQkakfm5mCpqq9rCtVu<,%b'6'e)8)i...`1b2w305u699@:n;i=%@WC?CfD<DzE&E5E;EkEtF=FeItLYMbMiOjP(PlQzSpVKVmWeXFY_]t_8aZb9byczdFdhdye9eif^g0guh&h6hQiNk7k>kBnspmqsr.rGs+tnu<wMw],'I('(*(q*Z*n+7+a1_1c4J5+5E6%8a8w9_:z=j?T@0@BAEBYBpD<DiEJFWMJMiN<PpPzQ$QGQrRDRxS.U8VLWvWyXgZ%Z&[4]>]S]W]f]i^D_wadb9b;cKcfepg)gLm]p+pNshtUtVt_uUv3vSvmxJ","cha":"&Y(o+52p307[=M=j@1C@I$JOP=RJTeVTe.e?gfgoiPivjhk*t(utv5ws,$&%a(A/<DGKBU.XCc7rIsLt&uBv$v0,1t7z8'<UChQ'SFSkV:XwY]`^f1g+","hong":"&Z7I8=8o9%97:Z;`=e@;CNI/JXOAOHR.V*Z.ZbaGaoiFkkq*,/b050r1u2Z2i5)536(8@9<;w=2>&ELEVIRSwT/[S[g_Pb(c;cNcddnh4h@kTkYktm*u>vhyPyQ,&z'R*%6n6s;j=S=V=XE^F^G1GBONPUQHQZSIYyZ=ZVZX[5_V_f`vl(lbrEuMw/w2","tong":"&[(5(n*t.u5%8J:Y>;A<C.RyS4S?X[[$_>b'bOglq)rRsYw6w],&I'P.I2l9$<d=.@/BSCLDmL:LIPLR'S_T5XpZ2[h^*^Cb)dIdSdehrqEv6,%<*@1`85A2IDMHP4PSPdWoeUmTpH","dai":"&b(y.'7Y909>C(D;GzRhVyW8WAWHYA[G^:cQdVrMuYxv,*h*u+m;=DQEnGYJ/^d`Vcvf9hcsR,*].z2A507e<@>j?(@UBXD'EKETEdG<HgIXNx`$`8h(mFqnwAwW","ling":"&c'a1V2X7y9NACBtG_IsKJNGRdRqT&Uu[@hhpVsDuQxTy/,)<)a1(479T;x<W@MA1C3EmFsI_NPSSWPXaYF[^][cneLi'k$k0kem4s&tvxC,%6%X&u)&*x1[2@3N7WB?EcF>LrNCOgR8WUZ3]d_<_P_^_b_d`:bcd&h&m+nDpaqqu>v1v]xtxuyByU","chao":"&e&n3b3n4u8t>yV6VHVIZ>]yeRkMptsS,&/&R)l7W8m<@>'>5?.ATPE[4[>aeeKi.jelX,6>7>:UAOFoLIOFW0vcwiws","chang":"&f&h'O*.*F*O+Y._/Q0+6i7B;t>^@.B0E.EmK>M@Q%WJYJ[_]t`%`On8p>pir*yW,.K3o3s>ACyETG;GeH8IeJ4J[K>n:pkq1tox&xY,3P3U8nR/R`X_YbYcYjZLZr[Lasl1nAoopfprx*ye","sa":"&g6)jvkim1,(i111]8t;Sh*oTy$,&n'S7ADoODU8Vx^;`ka$dQduga","fan":"&m1l1m1n4z5`7`?5FLI'KQMiMjVmWt]IbndxfTo`obt+uWwYxGxx,&H'8/0/@0z7N;*;A=@>p@2BfBvH_J_K(K*OGRuVR]a]d_Ja1aSe_g%g?kIl=qNrorruQ,&A'J(?))1$4]6p>p@GD=EMEgFdFzHRNpUAU]Vydbe(e=e>fho[tO","miao":"&n4>7J=OICL:MSXWY'YIiMtL,4J54E?OzQNXP[Y_Teqf*g*iFiitz,($J_sIuY","yang":"&o(&(E+z0Y4E4k6R9tBhCAH*IyL$RUTCTF[K^'^ta1abc`e:f(iXm/nGp(pNqwtJu[vr,$0$M%k&b*r.c.n.x1;1U8<:W<.<c<y>sETFBGeKdL@M%N&P+PYVHWfXfcrjujzk)o*,+2.L7Y9d<TEiFVP>S(S<W&[i[v]l_;`'`xd]dre:eXh*nlr0rCtlu=","ang":"&o6RR=p4pntm,O@nH,N$jY","wo":"&s*[++6M9C:R;l=.KRKSL7WVd3gChBhPi`l@o%te,$'/v3C3V3[4t4u9o:9>)D5I)QMT8Zt[)f4n9pMqqr/wZy3,'a+r/(C4gMy5yJyM","jian":"&u(v)p)w*h+?+o.j.t/;0Z1I1Y333E3L3S3p3q3u3w@nA%BPDSD`E9F`HwJ<J=P'PuWFX3YeZUZ[[g`Vd+d6dKdNf^g_h3i>iAitjElAlymCoZqts7u5v$vfx(xRyZyvz&,$=%'%n&j'9(8(Q)>*k+K+L.C1T2;3I4_4j5N5O6)869A:P:g;5;:;?>T?P?kAUAyBCCrEeF:G]GcOCOUPpQAQzR+R2TETXU)UpV$V*VAV^Y_]C]i^A^Z^f_3_v`Sa$a9bUdZegfKgCgSiBibl&mjnCpdr@s$s]sgshuvvJwlxLyJ,$`&&&O&r'P'q)E/l0q2o3G4U4W545E5p5s6%7U9=9U9r:C:r;>;@='=E=w>'?@?V@OAhB2B>BlC2C]CjG0NwO.PRQNQ[R1SUSWT9TxUQUbUlV7V8VRVUVYXMXmZ&Z'[6^^`_aJaMa_ahemf(fjgHkbninonwo?pUq0q[r[s'ssurv2v5v6vC","fen":"'%+X.o2<8hB<BABUFYHIHmILRDVpX%Yp]naBbopBs<sBtox6y9y:,'R.b/q9q;7<1=u@(@1DeE]Q^S1XL[Wahb4bicQhIk&kKkXqWtN,$]&`*N*O1z7.>4><E&FyM4OHUw^E_6f.fSg@gOlxodpoqYw&wax&x4","bin":"'%.+/BOq[.jslrngxKyS,%r(I+;+I/57::&:G:K:lE]H6HwS1gdicq/qn,)k>/>9?E?FJwV2Y>_mc1ced3jwk)k?kXkjky","di":"'&'y)g+3.F6u9Q:b;[<5<a>F?tB$BJBNBrChCmD*DsF*F7FRHAJzL0M;RrU7UnW/XSYcZ5Z:[?^9bBe&f/fXh^iNidk)n$nOozt7ttu2uqwqwxxv,$Z&>.V2U3F4v6s7F=hB(C$EMF]IvKRNJPOPfSGU&U*UyWHWkXi]I]Z`$aRc(eoiRk3kvmJn)pUtstyvvwix9,$&%9%^%c%h(7.I.t/a2Q5z626C7X9I9P<9=5>:APCXD0EbHiI<I=IqJ4JFK:NxPHT`YG]&]s`aaLb_gVjak8nMts","fang":"''*Q5TB@ChD^IR[9dbmmo?oPp;pJtn,/k3vApIVOyPHVqcWhLnDrvtU,*27<<+B3JxO3RqW=[uk9lwp4qjsd","pei":"'*(?)X9cDGI+IDJKKFL>UIW$^$f1m6oDoLv%v2xd,.6092v4.BrFTG5nAnu,%.1M3V3W?R@sG3GgM%M`R=Xj[n]X_Ng^","diao":"'.1U272U8:8HH[QVZ(ZJ[+e&h[yD,/:GCMSO6QbTWZe[7[k`EdK,%9'v)p*p6r8@9'<r>HNjOQPyQ;R3RdV'VzWqX'^p_Eldm7n5pjqCqKs$x8","dun":"'/8g?kA.B?FOFPFQXG]b`9bik`l6n@,$U'>0(8`<D@%BRDsOlOqS:U1V),.9B.CTD@DLDWI1IlJEO?W/b^cviN","wen":"'02D8z9/9K<=EhI9Zz]L]MeTj&j`nbpjwd,$l%D*m+9/i4P4x6Q<4EYFYGxHyM*M9Y^YzZ?c@cAd^f6fOgMhKiHmLnMo^tBwR,*7*8/S/t>7FcFgGeTLZPZUZ[[&[0[=[N_5aNb5cFf<gcgnlsnvo4ptqZqlx6","xin":"'2'S)d*)?j?mA'IKMwNeYH]1]2]j`Pa4o6pGt]tw,)f*4<F>4OmVKoqrUtQw>,'T1O4`747=EJGnK$NGO<QOUNVQXJYK[ccLgNgQg_","ai":"'6/01]7X:V:e;K<.=g>9>P?bCfDwEbFyK/K@M*N%Tua9cIcSgNhCnKnMplr1ra,)o*$+k6V6e:C>)A;H5HeMgNWNaNnR/ReS[SnT[UKV?dBsu,&:'0(O9Z;*;<?lE1Q:SgV$Y'^)^2_t`6`;f*gJorr;","xiu":"';)e)q:Q=`@&OrRbRwXdst,&E6Z7=8A=$FAFnHQX>b_dlg3gGhvk4o`opr7rCu:,/C2L3q3r>KQ%QCScTSTtU7XFdpfBg6k:kOmcoIrLuHxW","xu":"';'`(g)H+@0s4e4f6`7l8?9_=(==>_?.?EAtCbFEGMIaIlL+L[M^XM[R^N^n_(`Bahd.hpi^n%n2otp$p^pzqis8sFvd,$.%e)k)s*'*B*F*w/r/s1v2H405I5K6*6g7J838H<t=V>m@VDlFCFRJsKaOTOZOdP5QKRTS)WdYZYcbRdPdje&eaeef(f=gsi&i)mAmMo)tI,$I$k%D%Q&e'r(0)Y)])^*k+;.W3'6v7C7K7t9G9j:Y<$<W=8?;K*LTM1MlPiV6_FbRbTcrcsiGkqlHlXou","tang":"'@*F+*+j.)/n3r;R<i>hBYDPERTrVxa1czjTk;rxxs,%H&V'@/V3o5j657r;[=E?+@7A+H)RNU>Wr_]bMbabfkFlhpxq9,$u'D.q/I/fA9AjC_D&E4L:N'SxT@TkUEViX2Y5YAZr^4aXf3f>smx0","huo":"'C(N)s3J3s8W9w:5=(?w@M@^GxHnJ7ZvZw`Cd8gnhplpm7okro,(J0*215l859u:?:m;n;o?'E*N.P1R<RFV0WJW`XmXrXsZAZy_nlclrqzs^w^,$L(U0u9v=[>o@EAYK)OWRzV0W>XiYVYo^s_S`5achq","hui":"'D(@.h/i5j6/:J:l=3>X?7?G?X@4@wA&A6AeDdFTKPL6MmNNPKR*R+WdY0YfYhZnZpZq]'])^u^v_&_;_Z`Rb1b^cjfvgKimktq4qDqhr=s9wMyq,$4%x'H'p('(2(o+B+Z+[+b/90j1M1N2C5I6'7)8Q8o9X9u:_;s;v=:===C>M@J@RDxFXGQHcHnL>M=Q*Q=R0WZY%Z8_ydWgHgPhkiIkpkql.l?t6v.vY,%z&W'2'3(G)5*&*F+.+/+q/O0H2<4$8+8:8g9[:j;/;A;v<G<a=r?6@^FCG[HsIOPiU2UgZw[U^+^M`Ybycad4f'm_o:vy","kuai":"'D))/:2+:p?eAqBMEDFJVBYO]YlUods9,)v2C9XCQDyHn^QbtoSq],$/$UKRLegjogpK","cui":"'F*3.21b<><IF:SuSwTn]_`$azk=yH,%C&+.94:8::8>$?UG'H>KlLpNgUe[CajbCcYeEfQi]k]kwoIoLp*qJqSqmxU,2$4XAlTh^Sc=","che":"'K)h+0509U;UBsHqQDQy[=]%e=hviHkFl$l&,92=<=L=iA)QyS9T6T7m3w=,+VEDG8H_bd","chen":"'Q*p+q/`=o@IEpF1GyOkPw]`a4f5hGn(nPqFrjvOwSx5y;,$n&B).0$0%>GA9G+KeM&MBQUTDTkU^XoY[Z@e)n6r+umw$w6,&+'g/g1w5'789+9a:';X=$=P?O?uAKALB1B>CZESH.HfKwN*O4S8]6]b_It2vHxfxgy>","xun":"'R(q+K4Y4j5*5+6&:F?2?L@/B9D%E_FuG8H]JFN`NrPYPjS+VGVaVdY`[I[m^]aYiUmbosrft*vLwP,&r*x+X.)/M2)2J2P8_8n:B;h=_>M?A?x@4@Y@j@rCGE'FIHSJYPRR:Y.[(c9ghqov:vc,&?&F'U'Z(d0I0Q6q6z7)7u;p;r<PHCI'I4J2KILWN@V&c_gZh:inoUo_pQst","chi":"'V'l(_(p*+.@4S4`5S6]8/888A98;'<j=E>(?6?`BrC3F$HQIELgQDZ1[([4[5[u^w_)avbBbYcNe/f0fsg%gnk1mOn/o)t:uSuq,&D*(*[*^+@/R0T5;7y<'<l=X?qC+IfLcLgLwM5N%P7PSQh]*]L]q^c^i_qayd]kZk[l$l(l^m'n.o'o;pQuZvHx?,*5*W*b/`2i2j3O497G8A8y:.=d?0A.AIAtBXCAH^H`IpJ5JAJHJcP1PWPoS)_:e;fggYiolSr'rNsHsMsOt:u?vqw6xexpy=","xuan":"'W/92o7Q8C:P=5=AEAGcIaLEM3MvOUZH^J_s`va'c7coiLnUoQp?pSpxqcqdr@wr,$K$L's155*8%<Y=6>PE>EtFhFkGVHEI'L1N'N2PGPRQERDU3Ww_4dDf^fwg5hml'l@y/y0,$y%l''(R(g+[.]0h1]2_9J9g:u;D=0@7ELG;I3JNP%QbS[TUW[YIa7dVh:hOnu","nu":"'X+d48HsNlVxZ?^*jC,SP]^o2,gxj%","bai":"'Y(F9A;FXKfVfWg$h?i.jqlZm&n1u^v],CkIcNCNDYA[db2bDd6,'W5$?t@Caz","gu":"'Z.*.x1O7w9[:);D;E<@=r>UADDZGUJ%MNNkQ=SvT<VRVS^2aPe0eUmtt<uvwvxp,%&%P'W(e+]/[0[0q3k:H:kAzB5LkO'O.O_R3U@WMY<Yk]M^h^v_Vb^fHjEjIk*n;p%qkuKwnxB,$n'M*s*y1;6@7S<0=Q?:@]ElEmFiGCGoIQM>OeOjReWFXa^bc^cuf0g/jRmCn7pgr+sru8ugwzx$","ni":"'['](6*X/I/P5z9LBdDMDRIXI^KYM9N@O$QFQ_R$^C`6aScSe_f+fYholooTphqPr;uSy=,(M/.1/416a:(C6CmKSPBQ2XZa]fFmQmjnmpnqGr)u6,'j*[+D.@6R9%>TBRF=I0KvOaW_^F_YgBn<phvKy+","ban":"'_4*60B8BXIpR;^)e<eAfFjUjVmlnlnmp6sBtbuV,5oARFSIMITM<MhXXacd&h]n@rsrw,.H/>47BNGyH(OCP?W5Z][m`pb]cxloqY","zhou":"'b(s//0p9R9T:&:D</=$?U@'IYKgOKVDW*[bi'poq;qKyD,2&3p<n=(F>InK^NxO*O[Q7RaTp^m`sa0a3axb/c8fJg+h5h[kyn2n_nprjvixIyc,'`7^9p;:<:<X<[email protected]<GFGRI[KqM&Pa_RguhDhXi^jNn8rMuJ","qu":"'d't(82T4:5_5u6$7L7M7i9jB[K8QRRLRkUA]0bRdWf8nTo0s&sF,)M)V)m.S264;4o;J=g>FA(HTHhN5R5UmW+[Z[o]paEb6cmd'khl7l`neo$r&u1wjyI,&T)'*k*u+(/*/i0;1A1F1Z1m2a5k5r5v677f7k8r<<AUAWAnAsDrE'E:E`VaZJZY[T]%gmgoiCipkMm(o>oQr%sBu(u@vivjvovtwHwhx;y0yI","ci":"'e'w(S+B0W2q2u9Z9]<GC2N.VTXYagsvuZvc,)d*R0y:>EwF%IbIqKxNOU;VFW2b*bWd:fLuuuwwf,'5++/80_7q<;?N@oAJBFGpGqGwH)^geHeVj_jum4r$svswuiy7","beng":"'f=t>jCgD@DYEoH^T7U%j$,1?G5G=IzJCJDL[VqdEeAg'i5xH,*:BgD4HwIVU(YDYxa9","ga":"'h:*>T>g?iH7H<PtQ$Q6ousH,EG,EENYRnVmlB","dian":"'n((+i0V79@VBbCMF0FiHJH_K`KsU&V)V9V:XU`XdehTmUmpn9yb,%Y%l'*'G+Y3c6n9[<hErG$JKJNL/LeMBMwN1N8TgUt[6`Q,$M&E+oBKCPCqOrWQ])_A`McPcQdBiRwDy9","tian":"'n*<0P9;<&E[EfH%HtKXQQ]K_2`1i)jbqHvW,*s0X4+4I5CG2H/HrJ1J2JFJNJbJhLeOjPrU/UF[6cuePnfp8r_rexP,5`63?QM9PzQGRaWQWyZg[Y`F`OePr5t&t1w+","bi":"'u(*(1**+D5O8`9r:k<H><BHDjFhH4HoIMIgJtKeMqN<QNT3VhWvWwXEYPYuZQZRZY[>]3^G^Pa&a*f<n7n^oMs=ssuNv*ww,$)$s+o+p+q+t+y.:060k5]7'7?8v:4>U?LCVDgDhF2HfJVJWJgJyKWKmLhLiNFN[Q.Q/TvW%WXXSXVYU]A]B]u^4^`^a_m_zabaicKckeJfegZhBjgkdmInPnbpjqarxt:uLvVvsxXxq,%&%O&;'F+g/G2F3J4S4m4r6W7i<>=h>U>x?3@2@P@pBoCxDQDRGrIgJUK4LGLVLXP)T*T]UoW^YrYsYtZ5[.[/]Ia<aVb([email protected]?tKwqxM","zhao":"'v/y8(</<3>yC9I[V]eLfUoVp`rVsSu'y7,(X0Z:E<R>n@QA4A5CEH3O/P_R4]8^gj(jSjompmvmwx>,7g<=A?AdN^O/P&SEVqgrmOqK","shao":"'v4;546X8(;(JbPpZFguoYt5uex4,8q=A>B@0EzPcY7^Lcpe2h`s:t/txwLy5,&p2GF4K7a6b@kTmh","zuo":"($(2)5+4:+;S>sBFRSRTVLXf^%hOl0pZumv&,G4W*XgY=Z3]]^Jc'g9ntu@w1yAyB,%)2E98M<Oo](eC","ti":"(')y*J+%2z367'<?<k=[@+@2HAL0LLQSQgQjTGZ5[h[u_R_V`G`H`rd^gThyiNidm+s5sGw1xAxv,*@+<374v8;F]GWI5PAQFU&U=WgX3Y4]ha&dkf3i$iEjNtsvK,&Y'C3_3h3i:)ArAzCDCgCrE(E@I@IbIqMhQES9XOcBd:hsj`k(kFkVkZmfnQpsrgsMsOt(t)tFuV","zhan":"((+;.d6F?SMRQ`RuT;TOU=U>URUa^1`;d:dHdRj6o/o2oIocu:vBvowExz,$w'9)E.%.N.P0]5UG&O/OAOPR1TX[[aweIi;x*,'G):)h)i*t5l7R87;';+;`=OARFeFvGjJ[MaZ0_WdFdOdse4fRiMiWl[ojqAq[tjv'w[yi","he":"()4L8F8Q9C9`9u9w:R;.<K=5=7=^>2?:?zC0FxIkP%S&`Df*mus+s;uUvs,$%)t.B0Q3Z5&9?=^>H?8?9@X@_CDD@MfNsO9O;O?ODOHTYV/X<_[aXb7c=h7l0l1u'vrwvxT,$r/M0y2J3s5B7H7J7x:4<1>N>O?2@XA5KENbP(V/Z7Z:Zk[D[X^T`?`@`AaFbgd.eRfsm&p6sWsesktyueusvbxhy?ya","she":"(.6t7)HQHaPcZSapb>cuegfyg;h:iqjmjomK,(>)I*G0n3)3^4W72;FD*K.K/K4UwVerVrWrX,%a)x*v+?0a7?<*?D?H@iA0F1Zd[IawhYvW","die":"(07s:;:b<?<zCFDmS.TJU7W[^<^i`hd>g;iqpfrlur,$P%u+6.T0eACAMA]IHK5KDKKKLPAPNTndRhilLlMn`rAsIuC,../&/e3n4H7V9F=%AMBBBKBeCcEwHlYfa@ncppr3","gou":"(3+f0r587x9_<0BoCDGrGsJ:LmRYZVfRj0kVtguF,%^0=6C?)C9ExL.]`_d`ob^f)iOlIlJlKtXu+,*k2^4.5j657O8(<M>[email protected]@PBW;^eaPb%","kou":"(3103a4D7v8%OoOzZZ^(e1eokImq,7CP)P5QSQcZr[Z^2`8tF,&0&9Nmt'","ning":"(4)+*n/N1h:1?sN'O3P)P3P5P:PEfblsuo,'M(N1&9G:.C@E(JER9m;mhu5,'_V5kxtn","yong":"(9)S.34U4V9z<p=c?cCjEHF/FlM8U)XwY[[0^T_E_F`Wa/aWaab?f`iVlCupvJ,%y/(1=3.5b7O9W;KAOAbJ>JBL6MpN6S`T5qbu&,$5+S7sC*CVJlL&LFMzQITmYE^h^xcHd;fNn*o1oKp_q7t=","wa":"(:2/4F9C:':R:^;u<F=r>&JYK4KcLUR&Vz[Og<j]mV,226A7xIPIcIiJmS;ZKZaZg[*m7pppv,+32R4yK9agamb.wj","ka":"(=6G:(:*:E<oCR,o/,2zPP","bao":"(>)`/V2_3?3G53575?@5DpDqE)LZNiOOOeP8PQPT]/]xetf)r>r^rhuG,:h<]>y@eB]BjFJZ^]Qetnyu*x4yD,&R'.(K)f*Y2B3H3u3v4Q>??eB)P'VJWYZW_?`>eGeKflgij]kGm?p?qSqfu6xlyC","huai":"(@:LBEFqG0[L]ocFcn,%c)24<;$lu,);)@404?C?yg","ming":"(H1/1`8K9hJILvani3p@r%sO,%2206EDKOsPQQ[uf,$i/Q5h88L;MCPwX)qRu1","hen":"(M:f?j[J_.ff,CBLC,8&a*","quan":"(P0F2o4)4v52<bARAYD0HKJTKZNOS3V5ZD_4_b`EfnhDjgszy(ye,$e&'&h)L0h1o5q;h<vB*B+B>BcBdBeC+GgJeL8RJSe^$^ydAe1fMi9v=yq,)I.=1B6F8*<NB^CCF+GSMvPrUCX$ZeanckdIh;htk_n[q$xw","tiao":"(Q</N)OZR^RpXb^gg7o&orpssIsntCx/,&cPXVyW9Zl[3]Rb$c*dKm<oGswtxxg,%*%9%:./5V8@9'<rA]BjHaPyQeT3X'a5kAmwo=pXxsyD","xing":"(V*D0R2G:oC+CXJ'JpKaN?VFX6Zy^A`+`mlgpQrZt1,1Z3N6u>QC.D7GXNoOtQ<Sq_;_HeVpWqurRvAv`w;yS,+O1V6P6X9nJyKKMmO5PTPqQiW(Wb]7]Ff+fbhTj7m=nS","kan":"(Y+20y2)[email protected]`4dCeIvX,%n(Q*+*/P'R$ROS/U[[zwV,1XFGG'Zu[]cGl+ySyY","lai":"(])n*6<'JlKdSfSpXq[W[cm9tGxPy4,)63@4D:%;(;.CpG.KcMsMyN/PoQ&^3^]`ta=wWx],(T5(8y?L?g@h@uIRKuRoX:c2c8h^n:rns<vn","kua":"(`:KCPH6JG^rg4pz,$+d5o5s5,8EB*B_Pxjf","gong":"(a(r0J0O4+5K5N7I;`=eEcO^OaVKVOW]YiZ'_3aGaoflfmmjt=vl,/P9<?GF?U7_ic2c5c;h4kTnK,*Q6K6[>i@?E$E+F%QHa+kNyMyRyXyv","mi":"(e0u1&14:@>nEMNPOEOnOyS<WTWaWyZ;ZCZc^WcykKlbmNmxtk,$z&P(M(W/Z030S0k1n455+7G7q:(:+;2;X?BA*CxE6I?PMQQR(W%W4X.XV`LaQambgc.fvjnjvoXt(y],$e%p%w'w)*)>+w2e5M5N5U6)869y:$=6=AHvMuNDNENJQ.Yi`StpvDvEvUvzwv","an":"(i*&+=/C6i6o:O;x<lCWD=DbLCO;R)R3RoS8X=Xtg/i]qYqvw.w/,.o1hBkEpLfOXO^jYo@pVvFxFy9yH,%?3]8[9^=3>A>QQ2RBX3Z^^$_>a(a)bGgImMrusKuZwU","lu":"(j.M0K3[4]4o6H6J?N@3@EApBkC&EqErG*K?S/XNYBYVZkZldPi1k3l:lFm(m<rpu4vFy@,&N&X'd(j)(.M.R1B3x434Z7I7[8]9E:X:o<7?O@oE3EBG?HNHvI:J@OOOYQ3RGSlTCTZUZWQWVY;YvZ4^n`A`_`h`ia7a8b@e`gxi=j9o0q2qyrys1sYsasbtHwp,%N%P%`&U(])D)Q)_/c106b:8?4@aAmBfC=CzF)FmG6GEGTGkIYM[O[R:RiRkTNTdU.UeVKVPYO]4]g_ychd%gfhVi:k+lrlun?p(p3p:rFrqs%t]txu:v%v/v9vMw_","mou":"(k4H7H9M:uDt^cmsu_w?,AjPVg*ii,+)9k<zC0SLaHrHvk","cun":"(v2B8IGQN_PV]Dfpt3,94O$[wa^qC,K(","lv":"(z)8+U.H/T5.6A8S9*;9C1QlQmQpTP[Mb8bDg:grh+oKx2,$o(m(q.F.v76:T=m@gEAQgW5Y0ZC_Ad`e.e`frg&i=iSpuq.q=q@yL,(.)S4'4FKZQKVHWpZC[@iaist>","zhen":")&)4+OB'EaEfJALrP&Q]W9W<WRZAf&g1gUiSjcnzpUsKtxu<vTwHwSyx,$N$w%+%l'$+72>5X6W8f9`DWF3F4GzH/IoJSJrL%P3P<P=PWSITyWAWaWnYd[j_:a$cLcud_fWf`hNiZm2nrrExlys,$<$h'h2M385S7L8j<8>e?C@<@gEfFjGJH2ItM3NdOtR(RhS_T;T<VoY1[x]Q_Mh'kip%qeu7wV","ce":")'+N0i0k7%72H$Y)_A`nblfumvv?,2A5$Jv]U^0^8^N_'`@b+vWxjy2,%+","chai":")*/G=%@eVTf@v.,BiM?W3n8t&ul,*+0e296t>@O%W'","nong":")./41$:t?WYog0g[,'m)C2I9n@TMlX+Y&Z6g^oYq^,'%4j;(H0H1N8kuxZ","hou":")1*G7*8L9$9%9_<xC7DoWQ[N,1SBsDBLyQDR]_RbQl/l7uxyR,=yI/KJL5PvSOf)jemJnRofp@pJxS","jiong":")2.X0a0j0nA1BgD'dfdg,0a2r9+<3<^=K>a>b?e@9Zod%dzr0r3,(f(k45HdI2Pcc>d0gph=","tui":")=)B.YFJK'Q?Z0Z5]@i$,'>?*Z>m7pr,%I(B(_+U+p/348;KCiD8I(^>c/c0c3d5hPjhlM","nan":")?6=<rA%A)IJJqL'MBcxexiEqstrun,$F5n?%JMJop[wTy1,/+9`A1J*^X_'","xiao":")@)Q)u+u3*4G9e:H:j;0<g=^>Q>V>o>v?%@A@Y@aJ9KMNdObOhPnT2XgZ^^obmipl(mwnCn`naq1q`rSu;uCv[x1,);*8*E+W+e1s3(3/3i8E:v;t;u<z=b?9?pCjDnDqLHLMNbNiPcT)T1Z.Zp]?^K^Y_1_D_g`J`^dfhtkrn0qLwLxz,&l'*'n)J)U+R/u0+0N12768$8^8t9zBzI7KlQAX>_JdWiKj)jdjrk$lJr&r?t/u<","bian":")A5y6D7kG[S%Yl[j][`oddeQiWp],/f/g<L?(A[DCE)E^ImL&SOTtYRZ]]m_5a1aGbNewf0iMiTr;sGtgy7,'u.`3m5G5p9D;L?&@JGtGzH$H%H'H*H+H7H8IxJ`JaNLS`Z4a3aKnXnYq&qwsY","pian":")A+'A2LSdd,$($OAQBEDCE)H6Hw_Mf0iMl)oBp3,5K9H=7?%?8BgCdRyh4hZhjhlj2jAjjm$sY","cu":")E68?:LV[D^4c%,'f*qD)LsMIO+`9avfgoo,%r6;8LAUAbAnAsCICbD%DBDCMfcYv;v>v@v_wg","e":")F+..r5H6e6k8i9+9G:8:O;&?3?[A8CKDXDwE&IcIjJLK%K@KAKBQdRAS)SJSKTMY/_<_q`Sa3d[eJj?jNjdl_mzu%,)0*L*i1h325<FZG9LfLmNXPjS(S2SJSiU:V>p`tmwPy:,&X*3+X.G5c7+8N9N:c;O<%=.=zEUEqG?HUIwIzJQL0O=O]QsS6VOXEXvZR[Q[k]$]+bUbibjcCcDd<d?ebexfzhRlgnko0p'pwrRrhrisPuSufxUy4","guang":")I.`0%:9C;JEX=XAYMg(knw(,2.8a;q<E<H<I=;BnE1F<Sgo7r0r3uy,F(IEQ1w*","ku":")J2j;/=X@QAZDNXQXjYNe)g4ghsEu=w3,$A=`C>M.RrT*XWZbZvd?hgnku4,2k3F4@BCKBMQjbmZyq","jun":")L/30z8Y9)B=CkJFPMS^cEgjm6mMq7wexq,/a2P:B=g?zFaK1NyO(O)TS[f^:^s^zw?wsyo,*>.$265Z?BEGKdOPP`Q&S7W9]D^W^fc)edg&hQj9mep]r_r`rcvAvIvOyZy^","zu":")P*36*68;+;kSuT8^4oUusyH,AFF+W&X^YK_(d$hVxKyC,$O7n<3B'CFSsTHTQYH]'`n","hun":")T*`ALK]KnQ)]e`Ma`h`pAp_x`xg,+32G3`4E585^5r6^=_=xFXGQOvQ1Q9Q>v_yv,%e6N9L<VFrZS[Oejg(lDxD","su":")Y+^.z=d@kB%D1EJEKGlLyOraIaJbjkKwgy2,%3&L&S'D)1+(1%1w336U6_8X8dEDFEHYJ<U9YKYMYwZz`>azb'cVf_fiihmrmtpytrwJ,%_(+(^(j6Q7F:*<7=;AeD(IIJ7JBM?QSefiJj?mqoVtMuc","lia":")l*4,,","pai":")v:cYd[ZfGhexd,0>244a5=AVBZCh^_`c`e,$4FQHjSf","biao":")x.J/XF&KLM)Wi[*kSt5vA,&W(<4@7@:c;o?M@aCnMGUaZD`+p1q2q6qt,%Z(>1s3S4L9B::?yRmTqVIY@Y^dKdPdYdidjdkdmdte%e&ijj3jJk5q2v=","fei":")z375e708_<OHZI+KUKVQhX^Y+YL_xdlnkpeqbrTsEtPv3xc,%9'+'R(w0V4)4R:MBrC4CiL+L`McSK]__aeYi+kxn?nTnbnjnkpEtaxDx[,&Z+u.60D3X8x<l?+@WUcY.]Y_U`7`P`Qe'e)e*etgGhdhnn;pdx5","bei":"*'*;+7+S+t.I4Q5Q679A;FGYNbXr_]_y`^`ubTixp3tPtQv2wTx&xdxfyO,=tAwBKC(C`FcGDO5T`TiWl^_b]ngqau),$z(9+W2b4%8T9(>d@;EkFOGZK8KhL/PQQQUyW3]0`ta<aRj^rzu]","dao":"*@26282g8$>J?hG$PZPmRQSXUEUFUtWCX(]7`.h5hAjAlfsnxNy`,%p(:(D._=s@]ICOIONWIWTX/Y]Yf^gdKh+kylArksJxQ,/[1g1j3QCkEAH8J'N]]T^7^Il^p/","tan":"*A+x.Q/587<c>E>L?/?0BCBQB]D<FVF[FnG.KTZOZTZ_]>^S`Fbfc'c1hujum%mRpKrDrQ,$j'G'k*<.55Z7;8k8l9d;Z<[?uHmL?L_MEN7U+ePg[j2j8r[r`xN,(A2H4q5=91:q:w<w=G>a>q@HKrMcMnN6PKRUWOXkc9","chui":"*C8xAVByCc`KhHjOw>y.yL,%_<8TL_$p6x),RNT&Xc]ac6y`","kong":"*SD8NZSi^k`0hzyJ,3URsTMZP^wkA,E5RIa8s2","juan":"*T4C4Z5$6^9IARAYCpHDHKJ8JvKZUmV&VbW5ZD_G`EbEgwhDsNw0wry(ye,353f=aCYDvIdPUPiQ(dOd[fnhujOjmonp5qfx6,&$1<32;DL2Q[QbR>TFUfXhY6ZX^W^fa7e:eYuQyx","luo":"*]/k3&:E<_@h@uP[S(grhBk4m)m8m<mLm[ruyc,)Q1D1f1g4Q8+:R=3BLD/E:FDMJN9NqSDSoT4Ul]n_/aLdCh)hojAjpp&pSr%vaxpy;,$v)A+*/m0b3Z5q5w89BTDaE0IfJfT[VcXbYC^mc%fZhCi<iVj0jKmSrOtd","song":"*^.71Q8CJVO=T5TxU1Xy]X]q_aa?aMb5c3gyiRk+tatcu7ufx7xY,$J(=4*7a9xTG[im$mbx(,718e<(<dI)TGbVcyf2hIk]","leng":"*_1A;hD]E>T&aAy/,$DPuT_YF,':C>","ben":"*c=IBABBH+H0HRHWhKl*scvYwY,$30l4N8.<1B=Jq]Vk`u=,0D?3@PISRQXY","cai":"*g+L<9D>KIOs[)dpdshtt2x_,+xD(Q6eCfdh$x.,%t2x>h@@BkCKNM","ying":"*o.R<V=P>k?Q@TEEGUKwLDLdLwN6N:NLO0TsV*V0XRYX[3]JaCc?kBkZm;mDoypRqMqmsVu[wBwUx>,$M$`&p)=)A2^506%616u748?8D:/:0:J:[:r:w;1;6;R;_>>>C>V?D@=@bFWGnH%HLI>IrJ*MYN3O3O:P+R_T:TsVUWoYya;aMebfBgzi(igj*j+j6m&q?qXu?ucv`vbw`waxwxxxyy<,%7'k(x+%.M.n/1/T0d1=4<5i9x:d;=?A@+A*EBHLKeT1UUV3Xr_`a3bDc(d/d7d8omr6sGs^sftLt[tqu&uuv(","ruan":"*sDvG&L4kbs@,(SG_I(TlVCejlPpO,EYFSGA[q","chun":"*u;IL9`jp0pWqxsFtXz',%X')(Z2h4A5v757kB?GUQ@_@cJhAnEojq<t<wcxWy4,$9%F//1*?cFZMbMpRT]Gn3nas?sTu`","ruo":"+$7eL(U0ZGgchN,$/4Q>1@f_2_bu3,$bL.nto5so","dang":"+*/70822?lB)CSFrL$OGTCTrZja1gGlMmWwI,(()U/)8P9L;[FVHUHjIhK8O]QTRwU%V7^6`N`lsWv[x<,&h)10U3&4o:x;_=:AoIjUuWnZz_BwN","huang":"+90B2$=>E%E=FZHYLAOmT@VEW_[k^M^h`iaNakiVpvpwrLsP,$b%7(e/n5Y6p8a<m>R?2?r@kDiGpHZMZNMNdNpUuZ(_G`Yfcn+sDvLy^,.^0C1K7w9f9u=&AuJ%SBT2U>Y%^%bCf%hondoWpztNw'w(","duan":"+M3NE?L=o3o=ys,+O+c>KGiRdTz[r`HaHemiLlSpiym,3pDeS=SVXz","ou":"+P5u6$8V9%9?>ZEs]sb4,(p)j*>+N+a0B7m?cIYIwX8lipTq0,&C()(H:I;wTPqmt9u3","zan":"+T/Y/l/u:G=*?8@jOtfqi[kdm3m@mPpOqar5w@,'`:S;TI3I<IDX4ZI`(`]`abV,52;E;]?M@&A&B%B&CwLkLqLvRuTwTxUOUYf[ro","za":"+T5W9m9v:G=*?:@b@j@oVgdqfqsyw@,0<0MSZc[cer$r*,4[HHP2^l^w_)b>lv","lou":"+U.H3%=W>SEzJZKCP>QeTlU;Y>bDj*k5,$c&Q6+7]7b?SIuM2MTMUQg_Y`?ljlosQ,$2%q/./n:G>^E;JGTsY*]9_yaYjpjzt>","sou":"+[1K7o7r=q>C>DY(Y5gyh.jFjtk+l(lam'y5,(y)y6XDNMPQWa2sN,$6$j'X(@/=L9MtT8TWY$d_dadxf9g0i&","yuan":"+a/v0e1.3(71737G9B:x=5?aA0A7APAXA]A^AgCECZEgGjIQI_LILcLsNCOMOvZH^B_G`>a^i<istNy%,$K%0%>'g(u/x3V4C4O4T4X4d5m6668;CA:D6DMGjOiP@Wc]<_&erf;iVkGn3tMttuaz&,$C$R'A'^*D+i.;.d.v/:1Y273M3Y3t42:2>f@>FlGhHZIeJ6JdK'M5OZR0T?]PcNgsi3lpqTqzs+sXsgu0uAubwfwrx(x/","rong":"+b+v0vB>LeLuN1O4OlSWTgTsUsd0j2j;rrv>,%%%@%G%y.+.J6]:s=Y?F@bCJGuYlYndJfShek8n6uhv2v^,$p/0/?/@0p41EpSwY?h7","jiang":"+f/%4t5X5ZE<FjGWHTHgHkJ2PePfU3Z2ZLZMZPZak@kTwN,&1'j)$+G/Q1e2<5'7B8=BUD]JlK<KGKHV9blbsdUgThniokullq7v+y?,$1%v';/2/r:1:S;u=bMKN(N2];a`cRoHq%","bang":"+hC[EWW@WYWmX'[/g^h2j<oGwmxexf,%.2RA^E_T3U?Y@ddfGhdpssK,$G*2*:+0.5:+=>K&K+SmY;aBjs","shan":"+n.V/52V2a3C3_6;<s=H>MB.CrFFFGIxJ+MrR%UaWfZxdjgbhqi6i8jQkQkzlGnXqOt)v/v?yj,'''q*H/G8k8w9B;Y<e>Z?/?>CHF0K`L/PqUkWWX&Yr]Ffzg;imkJkLogqQqYrmtAu9,0L0X1v5]7%9q;3;m@)A)ABBPEOJmL^NkPnU`VwYnYoYu[*]C]KfGi6jImtoYoZq;qA","que":"+p6Z6bCiESFMSh_raFb.j3n:nDxw,%I/=<B@GGIMRO%T*T<T^U4U5V6VSiyj$,$A*EAiZbZl[W[[^Zs&uX","nuo":".//m='Jsa<c]c^gPi=jCjPjfx+,$y'J.3YVZ:b[bpbzlP,2i2j9i<iCfIhSKXV^X_'","can":".0/A7T7U7V7W=J>M@jN$Nx`Z``awaxaybzi8kHkQs7,*z+25F9Y<+@D@wHgYr`(b<,'<*C.K1@1D:HTae/e_i@j@wPwX","lei":".1/S/p4a7O>eC4E;G(G:M2lDm0,&M(%(g(h)[141l3;4&;GI+K@M=MrRAUDU`V2VMVNWCX5aYcfdMfmgngth/ifj7kNlTmz,%T&J'&(5)3)4)?)H1%8B;F<BG2MSPfRGUnV>V_YW_=`3bfbucTdEoptvxL","zao":".425;W;f=Y?]b/opu1v@wtxj,9K;y>w@CHCHiNGNH[E[J`;bjs7,'f(Q*R:vAyD5DOIJJCN/Vf","cao":".4>NQyU@aXadaqc<kxlOs/s0,&;7hbdn'sPsovC,%J/_4M4hLdTyi0x.","ao":".82/7=>=>>BjC'FaFdH`HdHfLXLkMIRORgU?UoY<b(c@eEelfQkDl[n0uywu,0p7H9D9^?O?_@iDaDbHFP/UWl3l8l<m`spt],%o/b2:4e:M:NEeJ>KlTXTdTeYe^8^Ci?jFo8q(t6wn","cou":".<1[,$W5DpR,FYGb","chuang":".>2;2Q2h313;3W=:?9WuXH]uaRk$sY,'PAJAXA`KqM;U]ZjZn[=,Zm[1","piao":".J3`4p>RM0[1[taroask,+%7TB[ILNrQjW:`+ftidl4wO,'c/hN)ZtcVdfdge$iAjJlToD","man":".NCnF%IzK(M4QcWg_^b*b<kGs2,&<&_6$737Q8'9U9b?fDZQ]QiRKd^fpie,%V%f)2+H/Z0*1E4c:T=CLRTYTlYBa2cXdAf?g8knkooAq5","zun":".Z?4FQPiUYfph(kpvf,'%;5gBj1,2o:gJKPkUIoXq=sDtY","deng":".c2'?FFWM[UWb`dG,(_9.:j;r@$HPNAQuUo[v]x`XsV,5o=fD:JjLUUSYU^?","tie":".j9UW&^1,m?xo,*w?.@RBKOwPtU[UpWSeIf&iT","seng":".n,,kp","zhuang":".uG@GAGGHVI0IGK$WuXBXPd%d&d'kuwOwp,&?5r82=fBmBwb1bevRw0,3%3?","min":"/&1D2W4R9KC*IoRnSr]L]M]z_v`pa)b$bvf9h<mrn'nIp+p.qj,.W194P5I5^8bEYF/G(G/G[LjO1OrS'TV]P]l`Te[epiUjJu.,1(?bOdR?STZ(Z?[7[?o;q6quwdwe","sai":"/1>4>l?nEX^7a@iJ,.&.>`mpa,?p@zcAnnpv","tai":"/E178.AFBeGzH&H1HcN5Nh]C]a]pajf$ldn_oyu?,(E/A/c/d1:6?<`<a@BF*^ca%nWnirDrqtwx?,'dB<K2M8OXW+dSh(j(m>pB","lan":"/H0N7C<7?u@qBJFoFvKmNDNJNURPT_X/`AcHcXcmfaj%lhmBmZnnnpqtvI,$k)F)X)Y2_777w9F:A;@;H;c;d<q@5@A@U@`@zA.A0I$I=_u`vaAc+gfh.iDj[yz,%/'x)+)/4B4d4s5.575b5x6.:b;W=JDlM]VSVkYQZc[Saici","meng":"/L1)4_GuGvNfQ2X&XkcRcTcli7l`res]x8,'A(B.Q.Y6;:1D'E.IxJUN*OQQmR=RHVDsAs_w:x_,$?&B*'.&.x000rLbLgQLRjXo_@_l`1`2cdfUkIn%nGtrv*wdwewm","qiong":"/O6SMvO8`kbVw5,'S>0>3>i??FhGNHXI4IAPwQYZMZO[0[H]j]vs2ud,(%(C+C+FACBbJrPm","lie":"/R1G2M41444K:=;9CuCvJJV%VJ]Hg8g>h;m$vpxl,+z1V2L<w=H>t@B@c@hBYCqD+DuE/e+mEofuq,+42yA_D_I&dTkrkzmRoyrA","teng":"/bWc,7%7n?WL(L9a.a6f]pqqM,(:)G/U8H9oJ]_vh8i.ibo+x1","long":"/d:/:y@FC$C%G1G2Q2R.UJV'V(Yo]+f]m=pprss^vDwn,%q)51A5k7/7^;'@uF7I9M^PJRIS^T4VWVX[A[K[_]k_i_ta>m9mmo+u^,(y14165)=`@8DgTvVN]5]u^N_z`9i`tzyKyPyQyW","rang":"/g51@UFsG6cpmF,;>@xE7INX1Z9ZFh%,(o;4;U;lDnl$","xiong":"/w/z2*5<5B:[Gc]f^znU,/l2*>>>C?<?=o=o>t0,7;7j8<<'<5?b^_","chong":"/x1<>ID9ORPSSjSk]$]ObMbriojz,042q3.82A&FQL9XKenjjkVrLsUv4,)n.p0P1h3kCyNSPbX1]o","dui":"0&0(0/<;C8DTEZPWP]Pl^VbhbicUn+n4n@tZ,:=:Q:y;)LlTbUMVrds,'[:_;7G+I%UMUVYP[b]]]ybrr7","rui":"0&0(0/7tG3`Te_u$w[,'N/`GqJ:QI];eZgFtPuJ,&H&I&c(X(Y*9.?Q=QxU2XN","ke":"0'2r3+4N4X5w8+9`:I=lBnDOGEJkOTPdRXS'T`ThUl_0_Na6a7iaj?n>v'y3,%N&T*/+U+V.q4U5.6>:C<QAKB%BFF&KwLmQVSDT*TuU@UOV0V@XOYHZw[>ehi@knsFu'y&,'@*d.R1S2J8q<mB+EvGDMsOfP^R7WHX&X]Z2bqc<d1d9h`j<jl","tu":"0*021M2.8N;M<HA=AHAaAbAjAlD[DfEQFfO<QkS[TmU:XhYF[T^<_MgohJikk)ws,(7/T2y3+5`8rH7LJM'X=XAY6ZW^;pbvww[x1yT,$JAMBvHJI>MNO'ObQJR)S0VtgEhNrVres)sUt+tWxG","nei":"0E0d;*Ju,.d.e2toup9,JzRMeag%mmn2","liu":"0K2N3l@>EjLhNBTvY1cgjyoEoNoXv+v;wDwa,%F'4'X272E6B899;:f?J?aF1FpGsH(HaJZJpK3KCM>M`T9TZU<UYZceGi8jajkkf,$K$l(F0%39CvJ1R*SrT4T_U<XKY9YJ_%_kdcdedhdzf8g5h2hGi*iOjGl:o%spt<uouwvG","shou":"0[7a7j;q?.CJGOGRO:P^dndohZmemy,3OCKDrE2LWM@e:i4pwsE,TWg<yt","ran":"0c0h9O>rIwLQub,'T><?b?vF'g4nJtu,$)*T*i212=2Wk;kE","gang":"0g182P3=DVE7RMRWSzd%d&d'e'hXjntBxt,%f5'>;>?AsB;BqKZRsTh^Ue?hDiwj)jKn5,NtR2T.W4","gua":"0m2e323P3c6L7z9C9[:R<WBcP?fgg&hnvWwV,*2>xIFd5f4jMjUnh,2v3e8=9M<DAYC^PzQGWydLdUhzr:uG","zui":"1+7.9k>@?$?rUDUpqJs6sNvg,%o&u'r'w)J:8HzQ'WOYKd*h'jT,&]036BGsM.MUMdR+R@","qia":"1H5w6G:CB*SBW4_6a6f*f_hcialX,+&23SkUGo&yZ,2nBHM:a.jm","mei":"1L@:B<[email protected]]*f4gZmEoFpYu&v<wl,$I$Y%d(n+3+i+j000?0J2s565>5B>d>k@6DFEfFbGTLEP%P9PaQBW)WiYs_Ibgjyk/oJoipNuHw9z',.e28B@E8L+MPQLSeSjY)Y/_Oaml?lGs[ujwIwZ","zhun":"1P1a<;AvDIODQz]bp/,4A6<Y?ZVe5nE,1k7B9.<uHK","du":"1j3D5p7P>fE/I<IVJ:NAXen[qSqnt>y^,(t+F+J+m3>4]4p:][email protected]+QCXy]&]1_kn4t1vk,/K111C3^5d8l;B;b<j=_?`@3@kL)MjRLS/VEY(Zd[I`bafb+b/i1k%wOw^","kai":"1z2%2w3V4b>KCTEIHPR8TuYk]m_@a0aUa]b2ihr',$^)o)r:C<:=1,$.=cF*S'SqT5UaWsXLXsYvZj[Ad`","hua":"2H3f5P648i9D:n>pCyH9J7KuKvMYM`Snj^k<l8t[u.wLyY,&(&y6x9/DLJQK+K7S)TBU@bJgIrdtStTxA,$0&N)$/H6E8/8m9C9M:W;0<K=[NqNrQcRlU/WziHj/tJw0","bie":"2[2bZ][ybUv%v*,MDMzw&,)N*q0<4aD7oOq4woy]","pao":"2_5I9q@5C)HCXTejfE,1)<]<_=JA8C/IIKtNwSTVEVTZDosxu,(>2B2C4(B7BGEnP'WY`V`wv=v?vh","geng":"2f;?CeDxS]XXgSs(x'yh,2d>EJad;d<dieyf@hskDkOlWm+w(x@,?S@rKcd(jimppRs@ua","shua":"2n;s,lO,8Z","cuo":"3)347/GaU'U+XsgQi&j=l0,H1LRM?PhRcUEfLoewCwG,$Q$s%i)Z98ClITJILqMxQFRfSkXGXWv4v8","kei":"3+Pd,,","la":"3.<T<v@WBzfCieifjDm$m9ovuT,$1)66&@hI8M$SNUPkbp<qgqwwoy;,(4.%.Q.y1'GuGvJbVDY_a?kenU","pou":"389p:zC]JtKFecehgqh]xf,B9^[,34","tuan":"3ZA*A+A`AcEwFKZmb;enibkL,&'(H5G5e7l>YD=K?KE`1c$,3y>XTRt4t^","zuan":"3zi[mS,`)aIgJgigph(it,?mDkDuOyV@VdWM","keng":"438lB>BGI>gYi?kR,+RB2SdT(TI,8WQ?S@TfX=[o","gao":"4P9'94H.S_jHtT,%R%S%g&7'Z(P(sDYNQNVQ4QHW@WBWqY)YiYj^P_`b`fXi^k(k/q+r9wy,'l(I8d<_K_QzT:XDY:b'f5k.k/t0tSx+","lang":"4T;6<fCoElM'ScY4njsLsMsZw`,%$&A)w2a=TC_FlH+T.Y*^>s<wN,$=$o%4+f/48ME.KPKTKaQMT=XPZB[HhL","weng":"4k>%EOHbTpmHr),6jIXJ)QRj5kWmZ,$q&x/;SvsiunxX","tao":"5E8$:M<CH0H3HUM%W`Z8aef%hbjYw'xN,%V(D1y3=3O4$7$::H'WKd=e=fTfbhyi7xV,.03L6u7o:5;kBjFhHnI+M_R4]e`sa%aOb$b6eFf:fOh5h]x'","nao":"5R9aCVDeGeKhM(NsSSUdV4^+_B_p`dc/gFjykjwG,'23yD?E0E9GlSjThU'oWozpXqp,+L0M7[:aU=WlZ/[;l'","zang":"5cEYHVYt,ALk.oUqrr'r1yk,&3'z???J@1@:@bQDh$itk&","suan":"5o,C^LNW(]5^G^r`),$BMR","nian":"6(:m<$D)J?X2Yj]d_l`IfBhMkql7m4,$w3*4>69>DU8XHXd`BawsB,&'CpD6D]FLGYGjm<nJp9pirQw5","shuai":"6AVlW7k(,EAJ?fQi],/s2$","mang":"7&8@;$GPJfQ2Xk]G_DsPt9tI,.Y/D2S8)AoB1CWLKOeOfT3T;].t4uzv5wdwe,(`+0000mJpNvQtWfhK","rou":"7KL1O?iGuc,$a4g>jGZI1X6agbOmxocp_yE,.a;5CeFTS4aAauhxnbsJ","cen":"7T7U7V7WCdRGU8,/h36Yr]@`(,","shuang":"7_ExNFNMb),)H1A88;';BAGV[fNsd,U'^t_ci9iejPt@u$v.","po":"83;3>`@GBWHcKHP_R[RmYdjUmopTsk,(^0i1D1F1q5J628O:R=8DJF$NkSVSX]g_)atg%kd,$P%uHjL`M@MrN7N`P3U4VrWI]0bbd'gqkHlF","a":"8T9`<8=_,p>,RHXS]+","tun":"8]9;<;?=A.B?QzXG]bbip/rHsR,//34=yq_qjt<,+$48=s=uER_[e7fclkp2w=","hang":"8lCUH+I>V^]koAtOw%,/y]>^/d0hjrutc,*P1V3$>lHPJvbYczlj","shun":"8m,$U'=PRQeQoQwrg,&bbPcqka","ne":"8u9:9L;*e_,KTPP,77;z","chuo":"8v;@<J@[JlJmKhL(NT`KdUfulK,*N3R3yUh_?eKgAi.,AkBwC6FEG`H3H4I_MEQgTQVGeny&yH","wai":"9C:R=&GiTB,*X;$[x,cW","guo":"9C:R<^=(>Y@vA9A@AEAGAJAUD&DlF4T*WNWjZ`Zd`:aucLi2k%mzu(y?,$+&$(e3C3l4u7`9oCvM)RB`4bIeDm@mKp4pJq3wz,&*)e.D.N0$3[3dFFHEIyKpOMS+UtXCekg'g>","qiang":"9E;w<:=a>:F5F?FbMKMtUBYQZMZPZad7d9dIeqjak:[email protected],%`&n(96R7e<K?IANAPCsDUElH0KHRs_sg.gLjwk+k5k;kAkQpFsX,%U&5'>(w.'4O:&B:CoD/SzTgU3XTXtYTsc","pen":"9J=I=Q?g,*C5M9qIUO8l:yN,","pin":":[email protected]&M.N0fTfw,$g/HAhEhG%R?S1V=Z<mF,'](b0x>n@Icgd3dHgPi]","ha":":_Hc,c],**+>.mP^X&","yo":":v;z=L,,","o":";&=.?T?w,^W,","n":";V>5,,","huan":";g=4=5@]AgCZDiH@HNMvNOOXP+PNS:TVX9_ja(c7cth4iYlRm:w9x),&3)e*A*O2/2Y3E4h849M9_<x=p>lBvCADPE8EjG`HoIELXM+PeQYbvd;dgexgUiQirk<n*v;xZxd,$C(=;[>&>8>L>bG(HVIWJZKILsSRUqY&YX[$[^^c^uihkvmvnPnZp[qdrWv&","ken":"<1CHFe_9c=i+,FHSpn&nInU,3)3f>(>MRpy@yF","chuai":"<Jibj5,*(q5qH,C[","pa":"<XI;VqW%^/dui/tY,/58TA6GHNK^<l[rpu7yh,2OB(WA","se":"<Z=bEXYQcDfukKlNvV,&)*]*_1^3K4Y9(9)9r9z:iG'GrHpMQZ%Z7ZEb+gRsi,'>:[G&Q5SpU6X+Z@Zv_3dn","re":"='`lhN,4Q=G?du3,","sun":"=JN`NreIh1j7j8jw,%=%TCTDI]9^%_6`Zve,$g&t'HT6^Ve5e?st","hei":">.?1,8u,w7w8","dia":">8,,","de":">aB$XS[Y[v[z_:_z`]ozxb,3eNJ,*]RwX[","dei":">a[Y,,","kuo":"?=Y=e7f[fgg(lw,85:LXmXr]wy=y>,+8PzQGWyZa[V_pa=aWatbmkPkw","ceng":"?>QLQoULs3s4,'Q[u,D;iQ","ca":"@1@bf@lim1,VJV_,J@","zeng":"@mF=FDbXs3s4,'Q?jHRJ%RgUn[ue(f[g8i:inji,:Z@$A(LYQpXAl7ob","nin":"A$^[_ofk,oR,","kun":"A:BZDQDaGJGNKnSsSt_Igmp8q:xC,2z8G=w?gCtG:H9PnT?WGY1YEdtwu,.13(3/3K3o>MMgRKX^ZAZN[Eh[k6k7k>n>pes4sZu[","qun":"AAG^O`SPW>,*=^sk9k:,3;3BC&IKvA","ri":"ABol,.c,2)NwO.OVg`iq","lve":"AdP[hs,K%K'YN,QhQmXH","zhui":"BVFBH]K9`gibyL,0;IkK9TLV.];eBfEi>iPpApz,92?x@wI%MeRFRYV*Xd]y^ShWj=s1","sao":"DKLqadc<e9hUi9j>x4,.O6DM3R8g)gVijiqqi,/Xdahei5jDk4o$oiq'","en":"H>S0_/jl,?0,$d","zou":"HML_i'iKj4y5y6,$W^^eSwm,99<hA:A;K;KsL@Lh]Zi4iyn(nEpcw$y/y8yo","nv":"Hr_+sH,0/aWm=,1L1NO)W%","nuan":"Hzqu,4k5e>]>^,ey","shuo":"I)aJjJnJnRsJ,%])y1w<p@lDpRUSxTx_D,$Z8i8k<cPnT%VFWV","niu":"IHNn]g^+e;elfQt^,/o0/<2AfAgBzcFhOwK,OGW@`h","rao":"J]Mce>m*wG,'2Z.gDhhvU,&V4bJL^<fLfq","niang":"JoN&NI,,MYN>NF","shui":"K9W:gOh/,/$/%/*393<Q)WCY/Y8p/,3@8i8k8o<c<pZ*","nve":"Kl,KbMATF,)R","nen":"L4MCMJ^[,,","niao":"LzMxN8QI,&a6aoyu`,%y2;3*4;qCu+","kuan":"OpP9PJx3,)x***.[?[@qv,VMjvk*","cuan":"V7l<m@mImP,(l)S+C/8:S;T?iA2ZIZs[?[@[F_h`D,DMDtQ[V`YS","te":"]?]@b%,B/B<om,06R%X;","zen":"^&kd,,:m=H","zei":"d?,,0g?<@Zn]ohpI","den":"e3eK,,","zhua":"ebgCl@,(1A4A5`nqZ,kS","shuan":"fovM,&'3PdApZ,Ym[)","zhuai":"fx,Ph,B`G>","nou":"jC,%Z(SE+kPlk,SuUX","shai":"jvmTq0rw,^5_p`3`MaK,9Z","sen":"y*ym,&*,4P","run":",'73H8cQoqT,YzZ6[2","ei":",*$,8P<e","chua":",*',","gei":",dHhl,","miu":",g*ii,:B=F","neng":",oC,/L","fiao":",,5?","shei":",,8o","zhei":",,HW","nun":",,w%"};
    var chars=(function(){
            var a=[];
            for(var i=36;i<123;i++){
               if(i==44||i==34||i==92||i==45)continue;
                a.push(String.fromCharCode(i));
            }
            return a.join('');
        }());
    var from84=function(c){
            var result=0,
                temp=1;
            for(var idx=c.length-1;idx>-1;idx--){
                result+=temp*(chars.indexOf(c.charAt(idx)));
                temp*=chars.length;
            }
            return result;
        };
    var s2c={};
    var c2s={};

    for(var p in db){
        var one=db[p];
        var ranges=one.split(',');
        for(var i=0;i<ranges.length;i++){
            var range=ranges[i];
            for(var j=0;j<range.length;j+=2){
                var ch=range.substring(j,j+2);
                var c=String.fromCharCode(from84(ch)+19968+(i*6976));
                if(s2c[p]){
                    s2c[p]+=c;
                }else{
                    s2c[p]=c;
                }
                if(c2s[c]){
                    c2s[c]+=','+p;
                }else{
                    c2s[c]=p;
                }
            }
        }
    }
    db=null;
    console.log(s2c,c2s);
    var exports={
        getSpell:function(chars,polyphone,spliter){
            var res=[],pp=typeof(polyphone)=='function';//判断polyphone是否是函数
            chars=String(chars).split('');
            for(var i=0,ch,ss;i<chars.length;i++){
                ch=chars[i];
                if(c2s.hasOwnProperty(ch)){
                    ss=c2s[ch];
                    console.log(ss);
                    if(~ss.indexOf(',')){
                        ss=ss.split(',');
                        ss=pp?polyphone(ch,ss):'['+ss+']';
                        res.push(ss);
                    }else{
                        res.push(ss);
                    }
                }else{
                    res.push(ch);
                }
            }
            return res.join(spliter||',');
        },
        getChars:function(spell){
            if(s2c.hasOwnProperty(spell)){
                return s2c[spell].split('');
            }
            return [];
        }
    };
    window.Utils=exports;
}());

js触发a标签的onclick方法

想当然地以为 A 标签和按钮一样是有 onclick() 事件的,结果发现没有,后来从网上搜了一些资料之后,成功解决了这个题目^_^ 。解决办法是针对 IE 和 FF编写不同的逻辑,部分代码如下:

var comment = document.getElementsByTagName('a')[0];
if (document.all) { // For IE
    comment.click();
} else if (document.createEvent) { //FOR DOM2
    var ev = document.createEvent('MouseEvents');
    ev.initEvent('click', false, true);
    comment.dispatchEvent(ev);
}

车票

“集合,向右看~齐!向前~看!向左~转!跑步走!”

“一二一,一二一……”

在军训的命令声里,我开始了大学生涯。

求学在另外一个城市,一个产煤的山区。不像老家一马平川的土地平原,这里到处可见大大小小的石头。山不高,由许多石头低矮的堆在那里。在这些山中间,偶尔有一些柏油马路蜿蜒穿过。印象中山上很荒凉,没有植被,也没有树木,只有荆棘那样带刺的植物胡乱的长着。新校区在郊外,把绵延的很多个山头圈起来一大块。新校园很大,估计这种地方地皮很便宜。

山脚下是男女生宿舍和食堂,顺阶梯向山上爬去,到山顶是教学楼,每次爬上去都累的呼哧带喘,如果哪天起的晚,着急往教室赶的时候,真的会要了老命。还好,从山脚到山头不算高,站在教学楼一楼前,能看清宿舍六楼的顶部。校园内这种山头好几个,每幢教学楼都座落在山头上。我还记得许多课程的安排,上午前2节后和后2节课不在同一个教学楼,我们就会沿着教学楼后的机动车道下山,因为不是阶梯感觉会轻松些,然后再慢慢走到另一幢教学楼所在的山上,这个过程通常会花去我们半个小时的时间。

在这个学校除吃饭外没有其它花费,300块一月的生活费足矣。这是一个还未完全建设好的校区,我们大一的宿舍楼也是刚刚建好没晾干就交付使用了。军训的时候不断的有工程车从我们身边驶过,去建设图书馆、体育场等。园区内除了超市,澡堂这些必须的基础设施外,其它的娱乐设施一概是没有的。所以除了生活花点钱外,其他根本没有花钱的场景。

出了校园就是一小片狭长的田地,被连续的山拥着。田边有一条不宽但却是唯一能出入校区的水泥路,平时没有什么车,没有公交,也没有的士,因为校区所在的地方太荒僻了,这些车都是不来的。校园内有通往市区的大巴车,但是我从来没搞清楚它的发车规律,大学几年中也没坐过几次。像这些出行设施,没有人去管理,也没人能管理,有就不错,所以乱一些倒也无所谓了。

因为出行的不便,滋生了很多黑车。校园外有一个村庄,据说以前村里有很多土匪,这在平原地区是很难想象的。村里的人买来那种面包车,在门口招揽生意。这种黑车很不安全,在上学期间听过很多次某某被这种车司机抢钱了,欺负了等。辅导员也告诉我们尽量不要去坐,对于这种校外的地痞流氓,学校没精力也管不住,只能让我们少接触。

校门口也有村民开的餐馆、旅馆、台球室、网吧之类的,我不怎么玩台球,那段时间去的最多的也就网吧了。

体育馆和操场都在建设中,军训并没有场地,参与军训的人又多,我们只能见缝插针的自己找地方。宿舍楼下,学校大门口等空地方,都留下我们走正步、站军姿的身影。教官也是,哪里能晒到太阳带我们去哪里,整个九月下来,黑的自己都不敢照镜子。

白天齐步、跑步、军姿、正步,晚上大家围成一圈,拉歌,讲故事,让同学上去表演节目,累并快乐着。进入大学后,我就告诉自己,已经进入了半个社会,要处好关系,广交朋友,勇敢的表现表达自己。

半个多月后慢慢和教官熟络起来,大家也没了开始军训的认真劲。很多人在队伍中和新认识的同学小声的说着什么,队伍也走的歪歪扭扭。那天教官破天荒的把我们集合在了教学楼的影子里。

“我知道大家训练了这么久,很辛苦也很累,但我希望大家能够认真对待,练就练好!”他拿目光逐个扫视着我们,我不知道发生了什么事情,不由得紧张起来。“如果你觉得累,可以不参加,我不勉强你们。军训对你们来说一辈子可能只有一次,我希望都能认真对待!”教官转身走向一边,再一个标准的有力的右转面向我们“不想军训的可以出来站到我这边!”。

静悄悄地,我知道教官生气了。这样的情景,如果是初中或高中生,铁定没有人敢站出去,大学,真是打破这些束缚的地方。沉默片刻后还真有人站了出去,“你不想练了?”“嗯”“很好,还有没有?!”又有几个人站了出去,最后我也站了出去。教官看看我们没有说话,转身对其他同学说:“好,我们继续,听命令,向右~转,齐步~走!”。“你们几个可以自由的活动,接下来的日子不用参与训练”教官对我们说。

不用参与军训不意味着很轻松,作为像班主任一样的辅导员,权力很大,而且不带课,没事的时候就会到我们军训的地方,或我们的宿舍里,看我们训练作息的情况。不训练也不能在宿舍待着睡觉,只能出去上网了,聊聊QQ打打游戏。

人确实很奇怪,群体时,都想标新立异,而离开后则开始想融入。不参与训练的我们几个很快就有人抗不住,回去继续训练,而我呢,还没想好要不要回。那天晚饭后,休息,不是每天晚上都会有活动,一个老乡找到了我。

“坤飞,明天去军训吧”,说话的这个是我的老乡,出门在外,大家都会认几个老乡互相有个照应。出省的,只要是同一个省的,都是老乡。学校招的大部分都是省内的学生,我们则是按地区来,自然同一个地区是老乡。这个即是同学又是老乡的很懂得拉拢人,一心要在军训结束,正式上课时整个班长当当,所以军训的时候非常积极,平时辅导员或老师有什么事情都是立马站出来承担解决。他告诉我军训结束的时候,有一个走方阵表演,因为我们几个人不训练,方阵缺少2个人,希望我能回去继续训练。

“回去训练吧?你要是觉得在队伍中太辛苦,我跟教官说说,让你去当领队,只需要练练正步就好”

“能当上领队?只用走正步?”我很疑惑,虽是一个地区的老乡,毕竟也没认识几天。

“能,肯定能,放心,我来搞定”,看在老乡的份上,加上我本来也有点想回来继续训练,就答应第二天过去。

后来果然当了领队,而且只需要练正步。这件事情使我意识到还是要和周边的人处好,走人情关系,确实会让你省不少事。不过这也是我不太看得起的,在心底里还是觉得凡事要凭真本事。

最后的方阵表演并不理想,领队2个,我和另外一个女生,我们走的太快了,和后面的方阵在步调上没有保持一致,中间的距离越拉越大。最后的评比自然也不理想,不过这些对于我来讲已经不重要了,因为不用再苦巴巴的训练。

在大学中,最不待见我的就是饭卡。

为了方便在学校买饭购物,学校有自己的卡片,像银行卡那样,花20元购买一张,充钱后可以消费使用。

我的第一张卡片军训没结束就丢了,那个时候电子支付没有,很多地方也不怎么收现金,所以只好重新又办了一张。第二张没用几天也不见了,正郁闷呢,老大给我想了个办法。

我们宿舍一共有8人,按年龄排了下,除老大外,其余年龄都相近。我们其他人之间都像老三、老五都是不喊的,只有老大我们一直这样叫他。

“你和我用一张饭卡吧,轮流充钱就行”。

补办一张要出20元的卡钱,对于常丢卡的我来说,丢了就办,太费钱。如果没有积极的办理新卡,捡到是可以消费的,这种卡不记名也没密码,补办的晚了,里面的钱可能就被别人使用了,更亏。两人甚至多人使用一张卡,确实可以省去一笔卡钱,我觉得这个方法不错。

在以后的日子里,在吃饭上我就和老大紧紧的绑在了一起,共用一张卡。我们两个依旧也没能看牢卡,几年下来也丢了无数张。丢的最快的一次是吃饭前发现卡不见了,补一张吃饭,卡放在餐桌上,饭后两个人起身走了。他以为我拿了,我以为他拿了,等我们再返回食堂找寻时,餐桌上的卡已经不见了,火速再去补一张,免得里面的钱被别人刷用了。

在饮食上,我最不待见的是芹菜。

其实我并不挑食,初中开始住校,伙食也非常差,土豆都不削皮,我照样能吃。在老家时,有芹菜也吃芹菜,从没感觉到难吃。反而到大学后,我发现同样是芹菜,学校里的和老家的味道差远了,不是一般的难吃。

可能是山区,物产不丰富,品类也少。新校区只有一个食堂,上下两层。以面食为主,包子馒头却是没有的,入学后甚是吃不惯。主食是大饼,非常厚的饼子,很是磁实,吃起来还有股淡淡的中药味。菜呢?炒肉放芹菜,西红柿炒蛋放芹菜,西葫芦炒芹菜,凡带点绿色的放的都是芹菜,而我又不怎么爱吃肉。放芹菜也就算了,整个菜口味也不合口,一大半全是芹菜,就这样越来越觉得芹菜难吃。

建设中的学校围墙有部分没有拉起来,那段时间可以看到周边的村民为了抄近道从学校食堂前经过,很多次看他们带着芹菜悠闲而过,我大概也想到了:这地方丫的离平原差远了,能在山区大量盛产的估计只有芹菜了。

那天早上走进食堂,买了东西一口也吃不下,全扔掉了,我以为自己生病了。中午稍感觉好些,进了食堂二楼,还没买饭呢,就感觉胃里阵阵难受,晚上亦如此,想着是感冒了?消化不好?喝点水早早休息。第二天有饥饿感,但是到了食堂依然吃不下饭,继续休息。到第三天感觉事情没这么简单,吃不下饭这还了得?就去了校医务室。

“医生你好,我三天没吃饭了,没进食堂前还觉得饿,进了食堂啥都吃不下”。

“哦,没事,你回去多锻炼身体,弄点红糖水喝喝”。

我本以为是消化不良,会给开点药什么的,结果啥也没有,只让我喝点红糖水。就这样呗,去超市买红糖回去冲水喝。想起医生让锻炼身体,难道是平时锻炼量不够?几天没吃饭,也不清楚自己这是什么病症,就想出去走走。因为围墙没有全部立起来,出校园很容易,随便找个口子出去后,沿着荒山漫无目的的走着。山上没有路,好在也没什么植物,光秃秃的,避开大石块,散漫的走在碎石上。

后几天都是靠那袋红糖吊着。

课还是要正常上的,我不舒服,好些天吃不下饭,老大尽可能的找以前没吃过的饭菜,如果我能吃的下,就吃一点是一点。那天早上老大买回一个葱花薄饼,是那种厚厚的带中药味的1/5厚吧。我竟然吃了很大一块,我心说终于能吃得下东西了,心里的石头稍微落下来一些。可惜中午、晚饭依然没有吃下任何饭食,我想继续买那个薄饼,奈何那个饼只有早上才供应。

后来我才发现,那种厚饼子是机器做的,一次能做好些,任何时候去买都能买到,而这个薄饼,是人工做的,每到饭点那个婆婆才支好平底锅,慢悠悠的开始摊饼。出饼慢,虽然吃的人不多,每次早上也是排了长长的队,大部分起床晚,还要上课,很多时候能看到等不及的人从队伍中离开去找别的早餐吃。这个薄饼是我唯一能吃得下去不反胃的,从那天起直到毕业,早饭再没换过别的地方,就算上课迟到,我也要买,人是铁饭是钢,那种几天不吃饭的经历我再也不想重复。

饼好吃,每次都会有很多吃排队买,婆婆自然也把价格提高了不少。饼薄,少了自然吃不饱,其他同学排队买了后通常会再去别的窗口买些其它的吃的。对于我来讲,它是我的全部,价格贵无所谓,吃不饱就多买。每次到我的时候,无论还有多少我统统买完,如果不够还会继续等下一张出炉。好几次都听到排在我后面的同学说,“哇,又出来一张,这次就轮到我了”,然而当我全部买走时,估计他们在心里肯定把我骂了很多遍吧。

至今,我再没吃到过那样式的薄饼,尤其是那个味道。

薄饼解决了早餐,午餐和晚饭怎么办呢?那天晚饭时,我和老大转悠到了二楼,偶然间发现东北角新开了一家山西牛肉水饺,那尝尝吧。3块钱一大碗,吃完之后我觉得剩下这几年能活下去了,太合乎我的胃口了。

我不挑食,老大更不挑食,但那个食堂却教会了我挑剔食物。好在关上门的时候,给我留了一扇窗,早餐薄饼,午饭、饭晚牛肉饺子,整个大学就是这样过来的,中间再也没换过别的。

每当我们到了二楼饺子窗口的时候,我们和卖饭的大哥眼神都不用递,只需要往旁边的餐椅上一坐,饺子好后大哥会敲击两下窗口前的台面,我就知道我们的饺子好了。偶尔排队的也会问:“他俩好像没排队吧?为啥把饺子先给了他们?”“他俩早来很长时间,刚才有事去别的地方了”卖饺子的大哥总有很多理由打发队伍当中的询问。

离开后,在北京的那段时间,中午和同事们外出吃饭,很多时候也是吃饺子。北京那边的饺子也很好吃,但是带汤的只有大学时那个牛肉水饺好吃。

有些味道,带不走,却也忘不了。

山区爱刮风,一年刮两次,一次半年。

产煤的地方户外更是不能久待,许多时候遇到风大的天气,从教学楼回到宿舍,洗把脸,水都是黑的。

入学的同学大部分和我类似,成绩不算理想,只能来这个学校。我从初中接触QQ,高中开过计算机课程,在大学里,我发现大部分人没使用过电脑,更不知道QQ是何物,女生更是如此。上计算机专业的竟然之前从没摸过计算机?

那段时间里,我帮班内的很多人申请了QQ号,带他们玩了很多游戏,一发不可收拾。女生觉得网络聊天这么好玩?男生觉得传奇,反恐精英这么吸引人?大家约着白天去,晚上去,时间不够就包夜。刚开始我还很自豪,时间长了我觉得很没劲,这些初中高中都玩了很多次的,大学还继续玩有什么意思呢?

就在同学们都在网络聊天上入门时,我选择了去学习。上课认真听,下课积极练习,没课的时候就去图书馆,本来作为业余爱好的计算机知识,如今成了专业,既然这样,那我不如把背后的知识掌握牢固。没想到一旦学进去,写出来一些简单的软件之后,举一反三,会让我懂得越来越多。大二的时候,有一门课程是女院长带我们,因为是院长的原因,她很忙,上机操作时,她偶尔会不来,每当这个时候,都是我带同学们上课,并解决他们软件编程中的问题。

大学最惬意的时光,应该是周五晚饭左右,一周的学习结束,即将迎来自由的周末休息。

我和老大通常会喝上2杯。上初中就偶尔喝喝啤酒,高中时学习压力大,那时候零钱更多的是花在网吧、游戏厅里。到了大学,网吧、游戏厅已经吸引不了我,这部分钱会换成啤酒、白酒,来消磨一下时光。

我以为我的酒量不错,没想到老大的酒量更好。我们从最初的一斤开始,到后来的两斤、三斤,慢慢喝,开心聊。谈各自的过往,想以后的未来。等到路灯亮起,沿着小路,听风沙沙的响着不知是树叶还是纸屑,慢慢的回到宿舍,躺在床上美美的睡上一觉,吃饱喝醉呼呼大睡。

那个周末,风依旧很大,灰蒙蒙的天破例变得湛蓝起来,莫非是元旦这些煤矿也放假了?冷,在老家过冬时,羽绒服从来没穿过,山区不行,套上还能感觉到风像刀子。太阳一杆高的时候,照在身上暖暖的,让你心情也舒服起来。我和宿舍老三站在阳台上望着远处发呆:一座高高的山被勾勒在蓝天白云下,半腰上的庙,也能清晰的看到轮廓。

“要不我们去那个庙里玩玩?”我向老三提议到。

学校在荒郊外,周边没有可玩的,有庙的这座山,平时也能看到。要看清上面的庙,只能像这样的好天气,也听说有同学去玩过。这个元旦放假三天,不想学习也不想去网吧,突然想出去走走。

“要不我们走着去?”老三说,“这太阳晒着肯定舒服,比比体力,看谁先撑不住去坐车”。

嘿,体育考试我可是替过考的,跟我比体力。我们俩个就这样出发了,为了早些到达,采取了直线行动,遇小山就爬,碰到小溪就踩石头过去,搞得灰头土脸的。风像刀子,第一次在大学体会到,看山跑死马,那天我们是体会到了。看着近,走起来就是无法达到,直到过了午饭,我们才到山脚下,上到半山腰非常的失望:不捐钱不让进。扭头就回,路上有卖茶叶蛋的,买了几个来吃,山区中的茶叶蛋怪好吃的。

正因为学校的环境这样,玩的地方挺少,所以让我有大部分的时间来学习。

我想也许正是在初中高中太贪玩,也玩够了,到了大学反而自律去学习,这也给我以后走上社会快速站稳有了一个良好的基础。我的同学们,初中不敢玩,高中管得严没得玩,到了大学所有的压抑一下子释放,毕业时,很多人还写不出来一个hello word,这个教育过程值得反思。

大二开学后,周末照例去图书馆看书,路过女生宿舍时,看到一个我们班的女孩拖着行李箱。开学有来早来晚的,我没在意,打声招呼后就沿阶梯向山头教学楼爬去。

许多天后我才得知,那个女孩是转学去武汉,因为一年下来,实在学不会计算机,就去上自考。那天我以为她拖着行李是开学刚来,没想到是带行李去武汉,想来真应该去送一下的,从那后对这个女孩开始留意。

班级内的同学都互相加了QQ,也留有电子邮箱,后来有机会上网的时候,有意没意的和那个女生聊天,要么写电子邮件聊一下近况等,有时候想能和她谈一谈恋爱也是挺好的。

通过短信表白,她没说同意,也没说不同意,我觉得这个事情要成,就得做些什么出来。班级的其他女生告诉我她的生日是十月初四,虽然不在一个城市,我准备想办法给她过一个生日。

离生日还有一个多月还始准备,快到生日那天,终于折了一千多只千纸鹤。那个周三,向同宿舍的借了500块钱,和老大买了两张去武汉的站票,晚上十一点多的火车,一夜站到汉口。没有座位,火车上也是满座的,两个人站在过道里,困的时候就站在那睡,熬到了目的地。因为夜里没休息好,整个白天都没精神。先找了武汉那边的高中同学,下午去超市买了一个大熊布娃娃,晚上买了一大束火红的玫瑰花。

第二天早早地来到她的学校,早上七点多钟,左手抱着半人高的娃娃,右手拿着鲜花,站在校门口。早上是快要上课的时间,陆陆续续的学生从宿舍出来去到教学楼。校门口停着一辆大巴车,看样子是教师乘坐去另一个校区的,不断的有人侧目看过来,包括大巴车上的老师。我告诉她生日快乐,让她来校门口。她过来才知道原来我跑了这么远来给她过生日,很开心,我陪她上了两节课,其他课则请假和我一起去公园玩了。

在武汉待了几天,回校后在公用电话那里打了许久的电话,终于同意在一起,挂了电话,我走时借的500花的只剩8毛了。

毕业前的最后一个学期,可以不在学校上课,课程相对也少很多,有些同学趁这个时间出去找工作实习。我去了武汉,因为女朋友在那里。

她帮我租了个房子,单间180。安顿下来后开始找工作,没想到相当难找。网上投出去的简历,没有一个电话能打过来让我去面试,只好自己沿着大街小巷看哪有贴招聘信息的。

前后花了近一个月,联系过找家教的,去过面包店,都不合适,学了几年计算机,还是想找和电脑或网络相关的事情。时间越久心里越焦急,钱也越用越少,那天漫无目的在电脑城逛着。

四楼拐角,一个卖空光盘的贴着招聘启事,需要一个帮他们搬光盘的体力劳动者。外面下着雨,又累又饿,想休息也顺便看能不能找到个事情做做,就走了进去。和老板谈了谈,愿意要我,心里的一块石头落了地。做的事情则是别人把货物运来时,要负责把这些东西从一楼搬到四楼,平时要在店里卖卖光盘,我想先有份事情慢慢做着吧。谈完老板坐那打游戏,我就坐一边休息。

没多久老板娘来了,老板随意说了下,说找了一个搬东西的,还是个大学生。不一会来了几个人买装系统用的光盘,因为这个店里都是空的用于刻录的光盘,我就告诉他们这里没有,可以去一楼看看。买光盘的人走后,老板娘就发话了:“还大学生呢,生意都不会做,你可以告诉他们光盘有,要去仓库拿,然后去别的店里拿了转卖给他们不就好了?”之前从没接触过,也没想到有天会卖东西,这里面的套路我是不懂的。后续老板娘又含沙射影的说了一些其他的,我只能默不作声。有点郁闷,心里也有点不舒服,感觉太刻薄了。

虽然我需要工作赚钱,什么样的事情都愿意做,不过在这样的氛围里,我宁愿饿肚子也不要这样的工作。坐了一会,去了趟洗手间,出来时准备一走了之,不过想想雨伞还在店里,南方的天气经常下雨,没有伞是不行的,也没有多余的钱再买一把,只好重新返回了店里。还是想趁早走,就跟老板娘说找了好些天工作,今天太累,想早些回去休息。不出意外的又被老板娘说了一顿,什么这点苦都吃不了,什么想赚钱哪有这么容易的事。我听不下去,拿起伞走了,再见!

出了电脑城,想想真是郁闷,什么也没干被别人说了好些难听话。沿着街道准备回租房子的地方,偶然间看到一个雕刻店贴着招聘人的A4纸,需要电脑操作员,进去碰碰运气。

这是一个专门制作印章的店,在电脑上操作类似photoshop的软件,生成相应的指令再控制车床把印章制作出来。这些事情对我来讲是很容易的,店老板看我学得很快,就同意我第二天来店里正式上班。

印章分为塑料章和钢印,塑料是用激光把表面相应的地方烧毁,形成字样。这个过程中燃烧的气味比较难闻,我就是从这个事情开始做起,因为塑料材料比较便宜,即使刻坏了,还可以把整个表面烧平重刻。

找到了工作,心里踏实了下来,就是钱很少。700一月,除了房租、电话费,不到500一月的生活费,在武汉捉襟见肘。在学校吃饭都是那种北方的大碗,武汉是很小的纸碗。那段时间的中午,常常买几块钱煎的小包子,再配一小纸碗炒米饭,虽然吃不饱,也不敢多吃,因为早晚饭也是要花钱的。为了省钱,早晚饭自己做,买点青菜,煮点挂面,许多时候为了省从租房到雕刻店里1元公交车费,都是走着上下班的,闷热的武汉天气,常常让我湿透体恤。

雕刻做了一个月多,大学同学们不断催我回去,因为毕业设计还没有做。

大学期间我很少玩,在编程上面比较懂,其他同学则是大部分都不明白的。面对需要编程的毕业设计,他们都来找我,在短信里,QQ上,不断的给我留言,让我帮他们做。我只好同意了,毕业班里能写出程序的没几个人,不过因为雕刻的工作,我也没多少时间,就打算回学校了再做。我帮他们写程序,他们帮我写毕业论文。

一个多月后,和老板说了下要回去做毕业设计,拿着第一次赚到的1000多工资,回了学校。

回校后他们很兴奋,终于把我盼回来了,那段时间我要不停的写代码,帮这个,帮那个。忙活了一段时间,自己的毕业设计也还没动工,最后实在没时间,只好用C#草草地做了一个。做完后班内另外一组和我同样的毕业设计题目,他们的代码也没有写,也不会写,关系也不错。他们来找我,我于心不忍,就把这个C#版本的给了他们。

没了代码,怎么答辩?而且时间还这么短?复制粘贴肯定不行,同一个题目自然也是同一个辅导老师,肯定一眼就知道是一样的。我最后选择了和C#语言看上去差异比较大的VB重新把代码写了一遍,虽然逻辑一致,但是看上去差别非常大,交了上去。

过了答辩,顺利毕业。卖书,卖电脑,等着离校的日子。

分别,悄无声息地准时到来,刚来时的军训仿若昨天,可转眼就要各奔东西。一个个送别寝室的伙伴,有武汉那个雕刻的工作兜底,我并不急于走。帮他们收拾东西,背下楼,再送到校门口,失落的心情越来越沉重。送走最后一个伙伴,已是傍晚,没有心情吃晚饭,空空的宿舍里,只有我的床铺还孤零零的留有铺盖。站在阳台上,路灯依次亮起,通向山头教学楼的阶梯,隐现在淡黄的灯光里,远处的教学楼可能暮霭的原因,模糊在视线里。

此一别,山高路远,再不相见!

返回武汉后,雕刻的工作继续,不过因为不合我的专业,在雕刻期间投了无数简历,均无回复。雕刻只做了6-7个月,尽管走的时候仍然没有找到软件开发的工作,终究我还是走了。走后2个月�因为没有工作,一直待在出租房里,充电学习,年底钱也花的差不多了,回家过年时,身上剩的钱刚和去武汉时一样。

过了年后终于找到了软件相关的工作,这一干就是3年,期间女友毕业,找工作,这又是另外的故事了。武汉的这几年,走过无数次江滩。北京3年,怀孕期间晚饭后一起植物园散步。后辗转杭州买房落户,终于不再漂泊。

那一张平顶山站到汉口的火车票,第一次带我走出河南省,也带我走进你的心里。

在这个结婚纪念日,我想对那个羞涩的女孩说:老婆,我爱你。

Nuclear看法

项目地址:https://github.com/AlloyTeam/Nuclear

代码中可借签地方

内联事件

所有实例都有id,所有实例都挂到Nuclear.instances下面。直接写onclick之类的,然后渲染时在处理函数前加上所属的实例对象。

我在2011年之前也曾经这样做过,只是当时处理函数前加所属对象需要手动添加。

这样做的好处:充分利用浏览器的事件绑定,同时因为内联事件,可直观的看到节点上绑定了哪些事件,及对应的处理函数,比用选择器动态绑定要好很多。

缺点:浏览器间的差异开发者要清楚,同时要有对应的替代方案,比如onmouseenter之类的,通常这些事件类库或框架会帮我们搞定浏览器间的差异,如果像Nuclear这样的处理方式就得自己去解决。

样式scoped

通过style的scoped属性,及在不支持时打补丁的方式,让样式只在当前范围内生效。

这样的做法我觉得有这样的问题:当页面上存在多个相同区块时,style会重复解析,因为要在当前范围内生效,每个相同的区块内都有相同的style。这个其实是不必要的,更好的方案应该是 css modules

命名空间同样也会在区块嵌套的时候有问题,详情见这里

observe

确实非常小巧,可以使用。只要不去兼容ie8

set-dom

项目地址:https://github.com/DylanPiercey/set-dom
采用节点到节点的比较试,类似这种思路的还有一个这样的库:https://github.com/kof/diff-renderer

这种做法在只单独的通过string更新节点时很有帮助,但对于像magix view这样的节点,当view渲染后会对初始的节点做较大改动,这个只能在set-dom库内部做改造才有可能去适应我们的项目。而且不是很确定能改造成功,这个有空可以尝试一下

汉字转拼音压缩思路

理想状态下是使用Stirng.prototype.localCompare了,但是由于这玩意并不是所有浏览器实现都一样,例如chrome早期的就不是按拼音排序,所以这个方案先放一边

那网上最常见的就是码表了,比如{"a":"吖阿啊..."},这种形式的最可靠稳定,但唯一不足的是码表太大,汉字的范围最常用的在 \u4e00-\u9fa5 这个区间里,其它区间的暂不考虑。这个区间有20928个汉字(后来经我简单资料查找,发现这个区间里有些汉字并没有对应的拼音,也有些汉字无法正常显示,所以被我精简到了20870个汉字了,当然网上也有只把常用的几千个汉字做为码表的)。

现在的问题就来了,如果把这2w多个汉字做为码表存在js文件里无异是非常大的,我们需要想办法压缩,而在压缩前我们还有些问题需要解决:

如果存放js代码的文件用utf-8来保存,那如果这个js被放在了gbk编码的页面上,并且script标签未指定charset utf-8,那么这个js中的汉字是会乱码的,所以需要编码,常用的是unicode成{"a":"\u5416\u963f\u554a..."},这样就不会有问题了。

如果用unicode编码,则2w多个汉字大概需要12w个字符表示(一个汉字6个字符)。如何用字符最少的来表示这些汉字成了压缩的关键

我们知道每个汉字都可以用charCodeAt取到相应的数字编码,也可以用String.fromCharCode进行还原,例如:"我".charCodeAt(0);//20105;我们也可以用String.fromCharCode(20105)还原成"我"字,OK,到这一步,最小汉字是19968;最大是40896。如果把所有汉字用数字表示,则只需要10w个字符即可,1个汉字对应5个数字(当然,直接把这5位数字转16进制,则只需要4个就可以,2w多个汉字大约8w个字符,仍然很多)。

到这一步后,我给自已一个目标:能否用2个字符表示一个汉字?如果可以,那么大概只需要4w多字符就可以表示完,这个压缩比对10w个字符还是相当可喜的。

既然再压缩,那就把刚才的 汉字的数字 20105再进行压缩,这时候我采取的是进制转换,比如把它转成64进制等尽可能大的进制。如果转64进制,则2位64进制只能表示4096个汉字,这个太少了。我需要自已写一个大的进制转换,我把ascii码表重新拿出来,128个字符,除了不显示的,我挑中了从33到126之间的这些字符(除34,45,92三个外,因为我需要把程序发布到网上,别人可以复制粘贴之类的,所以需要可视字符),一共91个。那么91进制2位数可表示91*91=8281个,仍然不够。

回头再看汉字的区间,19968-40896 如果每个汉字都减去19968,则区间变成0-20928,如果把这个区间一分为2:0-10464 10465-20928,第二个区间每个汉字减去10465 则变成0-10463,至此2个区间各有1w个汉字,离我们的91进制2位表示的8281比较接近了。

假设我们用3个91进制的字符,则可以表示753571,表示2w个汉字绰绰有余,但这时候需要6w多个字符。如果我们使用91进制的2个字符,每个区间共有2000多个无法被表示,如果剩余的这2000多个用3个字符表示,我们会发现这2000多个的高位一样(xyz),都是'x';那么这时候大概需要4w加上2个6000,大概5w2k个字符即可表示完成。

当然,我们要对3位的高位给一个特殊的字符,这样我们再还原的时候就很方便还原了,这不是难事,忽略不讲

至此,我们就完成了压缩,最后的js大约共58kb

代码见:#25

中缀转后缀

如何将中缀表达式转换为后缀表达式

  1. 遍历中缀表达式
  2. 如果当前中缀元素为操作数,则直接将此操作数“输出”到后缀表达式尾端
  3. 如果当前中缀元素为*/(,直接push入操作符栈
  4. 如果当前中缀元素为),则依次pop出栈顶操作符,“输出”到后缀表达式尾端,直至pop得到的是一个(才停止,并丢弃该(
  5. 如果当前中缀元素为+-,则依次pop出栈顶操作符、“输出”到后缀表达式尾端,直至栈底(栈空)或pop得到了一个(,若pop得到一个(,将'('重新push入栈。达到这两个条件之一后,将此操作符(+-)入栈。
  6. 如果当前中缀元素为=,则依次pop出栈顶操作符、“输出”到后缀表达式尾端,直至栈底(栈空)。

现在让我们假设一个中缀表达式a+b*(c-(d+e))=,然后追踪一下它转换为后缀表达式的过程:

 首先遍历遇到a,因为是操作数,所以直接输出至后缀表达式,接着遇到+,因为栈空所以将其入栈
  
image

  接着我们遇到了b,同上,输出至后缀表达式,接着我们遇到*,因为是*/(中的一种,所以直接入栈
image

  再接着,我们遇到了(,同上,直接入栈,然后是操作数c,直接输出至后缀表达式
image

  下一步我们遇到了-,于是我们pop出栈顶元素,发现是(,所以我们将(重新push入栈,然后将-入栈。

  接着我们又遇到了(,根据规则3,直接入栈。然后是操作数d,根据规则2,我们将其输出到后缀表达式

  
image

  现在我们到了+处,因为pop出栈顶元素为(,所以将(重新push,然后将+也push入栈。

  再接着我们遇到了操作数e,直接输出到后缀表达式
image

  接下来我们遇到了一个),按照规则4,我们依次pop出栈顶操作符并输出到后缀表达式,直至pop得到的是((丢弃)。于是我们将栈顶的+输出到了后缀表达式,并丢弃了+下面那个(

  
image

  接着我们又遇到了一个),再次依照规则4,我们将-输出到了后缀表达式并丢弃了-下面那个(

  
image

  最后,我们遇到了=,于是我们依次pop出栈内元素并输出至后缀表达式,直至栈底。

  
image

  至此,我们完成了对a+b*(c-(d+e))=的转换,所得后缀表达式为abcde+-*+

后缀计算

  1. 遇到数字入栈
  2. 遇到操作符出栈顶2个元素(栈顶是右操作数),并计算后把结果重新入栈
  3. 最终栈里的一个结果即是最终结果

abc*+
我们遇到a、b、c,依次入栈
image
遇到*,pop出c作为右操作数,pop出b作为左操作数,进行bc运算后将结果入栈
image
遇到+,pop出b
c的结果(假设为d)作为右操作数,pop出a作为左操作数,进行a+d运算,然后将结果入栈
image

Magix中的微前端实践

微前端

微前端主要是借鉴后端微服务的概念。简单地说,就是将一个巨无霸(Monolith)的前端工程拆分成一个一个的小工程。别小看这些小工程,它们也是“麻雀虽小,五脏俱全”,完全具备独立的开发、运行能力。整个系统就将由这些小工程协同合作,实现所有页面的展示与交互。

规则

一、充分使用浏览器原生方案

  1. 如果有dom操作,请直接使用浏览器原生的api,不要引用jQuery,也不要自己去写简版的jQuery lite之类的,没必要。
lastNode.classList.add('@game.css:succ');
  1. 加载器使用浏览器提供的import即可。
import Frontend from 'https://xinglie.github.io/frontend/build/fe.js';
let FE_ID = Magix.guid('_fe_');
Frontend.config(FE_ID, {
    logo: 0,
    hash: 0,
    scrollId: FE_ID
});
Frontend.boot();
  1. 每个项目需要的第三方类库在自己项目中加载,项目与项目之间不共享这些模块。如果共享这些模块,就需要考虑如何共享,如何升级。从单一项目出发来讲,这样的方式并不利于开发和维护,越内聚越少与外界有关联越好。所以即使某些模块重复加载也未尝不可。
  2. 项目中,不再使用reset.css这样的样式文件,项目中的样式选择器一定要拒绝标签选择器。reset.css放在入口文件中统一提供
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <link type="image/x-icon" href="./icon.png" rel="shortcut icon">
        <title>Loading</title>
        <style>body,ul{padding:0;margin:0}ul{list-style-type:none}body{font:14px/1.5 'helvetica neue',arial,'hiragino sans gb',stheiti,'wenquanyi micro hei',sans-serif}@keyframes load{0%{width:0}100%{width:98%}}.outer{background:#e6e6e6;position:fixed;left:50%;top:50%;width:300px;margin:-20px 0 0 -150px;height:2px;}.inner{width:0%;background:#4d7fff;height:100%;animation:load 3s forwards;margin-bottom:-2px;}</style>
    </head>
    <body>
        <div id="fe"><div class="outer"><div class="inner"></div></div></div>
        <script type="module">import a from './src/fe.js';a.config('fe',{logo:1,hash:1});a.boot()</script>
    </body>
</html>

实践

主项目文件

https://xinglie.github.io/

被加载的第三方

https://xinglie.github.io/frontend/

javscript 非递归实现组合算法

内容可能与题目不太对应,不过已经包含组合算法了。

需求:

a=1 b=2 c=4 d=8 e=16

给个7可以算出这个数字包含abc三个变量
给个3可以算出这个数字包含ab两个变量
随便给个他们这些个变量中其中几个的和就可以判断这个数字包含那几个变量的算法

这个是需求,下面是实现:

var hash = {};
    var vars = [1, 2, 4, 8, 16];
    var comb = function (arr, len) {
        if (len == 0) return arr;
        var num = len || 1, i = 0, j, count, temp = [];
        for (; num < arr.length; num++) {
            for (; i < arr.length; i++) {
                for (j = i + 1; j < arr.length; j++) {
                    count = num - 1 + j;
                    if (count < arr.length) {//这是关键,取出对应长度的内容,再加上循环到的值。arr.slice(0)表示复制了一次数组
                        temp.push(arr.slice(0).slice(i, num + i) + ',' + arr[count]);
                    }
                }
            }
        }
        return temp;
    };
    var initHash = function () {
        for (var i = 0, res; i < vars.length; i++) {
            res = comb(vars, i);
            for (var j = 0, temp, sum; j < res.length; j++) {
                temp = (res[j] + '').split(',');
                sum = 0;
                for (var p in temp) {
                    sum += parseInt(temp[p], 10);
                }
                hash[sum] = temp;
            }
        }
    };
    var getVars = function (num) {
        if (hash[num]) {
            alert(num + '由' + hash[num] + '组成');
        } else {
            alert('没找到匹配的');
        }
    }
    initHash();

    getVars(17);
    getVars(7);
    getVars(9);
    getVars(55);

前端的离线处理

这里的离线处理指线下把一些事件提前做好,不在应用运行时再去做

其实前端的离线处理在一些工具中可以看到,比如说css中的背景图,某些css工具在打包处理的时候,如果图片的文件大小比较小,工具会读取文件内容转成base64直接放到css文件内,减少http请求。

类似的还有使用字符串模板的情况下,提前把字符串模板变成js中的函数,避免运行时再去生成相应的函数

接下来聊聊其他的离线处理

模板的离线处理

自定义标签

现在很多前端框架支持自定义标签的书写方式,比如基于vue的element。我们以它的inputnumber为例来看一下: http://element.eleme.io/#/en-US/component/input-number

<el-input-number v-model="num1" @change="handleChange" :min="1" :max="10"></el-input-number>

一个自定义的el-input-number标签,最终生成的html是

<div class="el-input-number">
    <div class="el-input">
        <input type="text" autocomplete="off" class="el-input__inner">
    </div>
    <span class="el-input-number__decrease el-icon-minus is-disabled"></span>
    <span class="el-input-number__increase el-icon-plus"></span>
</div>

vue会把自定义标签替换成最终实现的html内容,这个过程是运行时做的。其实这个过程是可以通过工具线下处理好的,不必在程序运行时再做。

字符串模板

字符串模板在很多前端页面中可见,模板引擎也很多,以underscore中的template方法为例:https://github.com/jashkenas/underscore/blob/master/underscore.js#L1579,它里面在生成函数时,如果没有variable参数,则会加一个with语句,通常我们是避免掉with的

那么有没有什么办法是不用传variable,也不使用with语句呢?这个也是可以线下处理好的。
比如模板如下

<%for(var i=0;i<list.length;i++){%>
    <%=list[i].text%>
<%}%>

通过工具我们是很容易转换成下面的内容的

<%for(var i=0;i<obj.list.length;i++){%>
    <%=obj.list[i].text%>
<%}%>

这个就需要借助acorn类似的工具来处理了,不过肯定是可以做到的。

有的同学说这样做是错的,因为with语句不在运行时,根本不知道它里面的变量从哪里取值。是的,不过我们完全可以通过约定模板中用到的变量都应该在使用时,显式传递

比如window上有一个getUser()方法
在去掉with前

var tmpl='<%=getUser()%>';
_.template(tmpl,{});

这时可以正常工作

通过离线工具的处理,去掉with后,模板变成了

var tmpl='<%=obj.getUser()%>';
_.template(tmp,{});

这时候就不行了,不过我们可以约定模板中使用到的都应该在调用时显式传递,从而避免一些潜在的问题出现。

当然,这个模板字符串离线处理最好的结果是直接就是一个函数放在那里了。

css图片的处理

在我们的项目中,考虑如下文件结构

|____index.html
|____index.css
|____index.js

我们通常是把html和css打包时,打包到js文件中的,因为js文件可以很方便的模块化,把html,css依附在js文件上。这样js按需加载时,html和css也按需加载了,而且不需要为它们特殊处理。

假设它们最终打包出来index.js如下

var Magix=require('magix');
var indexHTML='<div class="mp-et5-content">...</div>';
Magix.applyStyle('mp-ec5','.mp-et5-content{color:red}');

更多信息可参考 https://github.com/thx/magix-combine/issues/15这个打包工具。

样式变成一个字符串放在js文件中。

我们看一个事情:在css中使用背景图时,为了达到最佳实践,我们希望在支持webp后缀的使用webp,在高清屏下使用2倍图等 。如果我们用纯css实现,要写很多media query,产生很多css代码。

其实这个事情我们没办法离线处理,但我们可以这样做:书写css仍然是写最基础的背景图,不去考虑webp,2倍图等事情,也不需要写media query之类的。在打包时,把图片这块调用js函数在运行时动态处理

如前面文件结构中的,假设index.css中使用了一个背景图

.title{background-image:url(//cdn/a.png)}

我们打包到js中时,完全可以变成

var Magix=require('magix');
var ataptImg=function(img){
  //处理webp 2倍图等
  return img
}
Magix.applyStyle('mp-ec5','.mp-et5-title{background-image:url('+adaptImg('//cdn/a.png')+'}');

这样可以很方便的处理掉这些事情。像阿里cdn,七牛云存储等,都有相应的规则生成相应的webp或压缩图片等功能,所以我们adaptImg方法很容易实现

同时因为我们使用的是最基础的css功能,所以不存在浏览器不兼容的问题,像css背景图中image-set用来处理2倍图的方案,在firefox中是不被支持的。

模板中的图片

如css中的图片处理一样,我们同样可以用工具离线处理。通过识别模板中的img标签,再对src属性做处理即可,这样开发时只去关注基础功能的实现,其它的适配都应该交由工具去实现,最大化的解放自己。

我是如何做固定头部(thead)的

在前端开发中经常遇到需要页面滚动时,固定某个区域显示,常见表格的需求,因为表格有很多列,如果列名不固定在顶部显示,滚动到底部时,可能就不知道某些列对应的是什么了

那我们就聊一下如何在滚动时固定(thead),让它始终显示在列表的上方

css的方案

如何让tbody滚动

如果我们用css来实现,网上常见的一种方案是给tobdy一个固定高度,然后让它滚动,这样就实现了滚动列表时,thead不动。

有同学说tbody没办法滚动,所以网上也有用div来拼表格的,这样就容易滚动了。其实tbody也可以滚动的,比如tbody{display:block} 这样列的宽度就需要用css来控制了,总之是可以达到的。

这个方案的缺点在于,页面上有很多滚动条,tbody的,页面的。虽然该方案易实施,但在视觉设计师那里通常是不能忍受的。

使用sticky属性

现在css里有一个position:sticky属性,正好可以实现该需求,我们只需要给thead加上position:sticky即可。关于sticky的浏览器支持可以看这里 http://caniuse.com/#search=sticky

这里有一个坑的地方,给thead的position指定sticky,chrome、safari都可以支持,唯独firefox是不行的,也就是写上后没有任何效果
那么对于不支持sticky的,我们只能再想解决方案了

js的方案

这里的js方案还是用css来实施的,只是这个过程中加入了js控制

别人的方案

  1. 上下2个table
    js加载后,把当前表格分成上下2个table,上table只显示thead,下table只显示tbody。

这个略显麻烦

  1. 再克隆一个thead出来

这个对于原有thead上已经绑定了事件,对于克隆后的也要做处理,也很麻烦。

我希望就用一个thead,尽可能的减少辅助节点,把这个事情搞定

fixed+absolute模拟sticky

我们尝试给thead加上position:fixed,再指定top:0,然后这个thead就脱离的文档流,固定在页面顶部显示了,还好,所有支持fixed的浏览器都表现一致,就连firefox也生效了。

这时候带来的另外问题就是thead脱离文档流后,thead里面的列的宽度就失效了,也就是thead中的列名称和tbody里面的列宽度不一致。

这时候想到的方案就是通过计算tbody中的列宽度,然后同步给thead中的列,这样就能对上了。
但是表格的thead并不是上来就是fixed效果的,而是随着滚动条的滚动,当它处于页面顶部时才进行fixed效果。即thead的position会在static与fixed之间进行切换。

这样子看上去问题就解决了,但是在某些情况下,static与fixed进行切换时,前后的列宽度并不一样,比如static时,某一列是40px的宽度,但是fixed后,通过计算tbody对应列的宽度,它变成38了,虽然切换前后thead中的列与tbody中的列宽度仍然是一致的,但是在切换过程中这种宽度的变化导致表格会有一些让人不舒服的变化,对于我是不能忍的。

既然thead在文档流中和不在文档流中,tbody表现并不一致,那我们干脆直接让thead脱离文档流好了,该如何脱离呢,给它position:absolute,绝对定位,然后不给left top值,这样它还在原来的位置,就是不占高度了,这时候我们仍然计算tbody中的每一列的宽度,给到thead中的列。然后在absolute与fixed之间进行切换时,也不会有任何宽度变化了。

但是,使用absolute或fixed后,原本thead所占的高度就没有了,因为脱离了文档流。这时候整个效果还是不对的,我们要想个办法,找个节点占着原来thead的高度,这样才完美。

我最终找了caption标签,然后把thead的高度给到caption。这样就可以了

树状结构如何在数据库中存储

昨天有人在QQ小组问起,无限分层的树状结构,数据量比较大,在一万条以上,如何设计数据库的结构。其实这是个老生常谈的问题,一般的做法是有一个pid字段,为了提高效率,还会有个FullPath字段。(一些人还设置一个层级字段,但我不知道这个字段有何作用),FullPath字段可以用id-id-id….这种方式拼字符串存储,这样可以方便地用 like 语句进行查询某个节点及其子节点。

曾经看到过另外一种存储方式,利用了一般树结构可以转换二叉树的这一做法,用二叉树进行存储,在数据量大的情况下,存储读效率比上述的常见方案更优些,所以特写此文简单介绍一番。

下图说明了这种方案

图片丢失~~~

如图所示,在每个节点上,有left ,right两个字段,我们看到,图上从根节点顺着子节点开始画一条线,每深入一层left加一,到底后,right=left+1,然后顺着节点回溯,right逐级加一,一直回到根节点。

如果要查询某个节点及其子节点,比如 fruit 节点 ,条件为 where left between 2 and 11

要查某个节点的full path ,比如 banana,条件为 where left<8 and right >9

如果要插入某个节点,比如red yellow直接插入一个节点,则update left =left+2 where left>=7 ,update right=right+2 where right>7,然后 新节点的left rigt分别是 7,8。 删除节点类似。

这种方式,因为id都是int型数据,加上索引后,读的效率较高。而fullPath字段的方案查询时候用的是字符串操作like,效率较低。

在内存中,如果要还原树状结构,即在每个节点上增加pid属性和children属性,则稍微麻烦些,可以如下操作:

1 按left between x and y order by left 取数据

2 顺序遍历数据,如果left=上一个Left+1,则是上一个节点的子节点,设置两个对象的父子关系,如果发生跳号,则是上一个节点的兄弟节点。

document.elementFromPoint

先说一下这个方法的参数

elemntFromPoint(x,y);//传入坐标值,返回当前页面上包含该坐标点的顶层元素

注意2点,坐标值和顶层元素

先说坐标,因为不同的人理解是不一样的,也就造就了这个方法在不同的浏览器中表现是不一样的,所以在传入坐标时就分 整体页面坐标 和 可视区域坐标,我们看上篇文章中的图来理解下:
pic
中间的方块是可视区域,红点相对可视区域的左上角我们称之为 clientX和clientY,相对于页面起始处的左上角称之为 pageX和pageY

有的浏览器在调用elementFromPoint时要求传入clientX和clientY而有的要求pageX和pageY,具体的详见:http://www.quirksmode.org/webkit.html 看 elementFromPoint部分,上面也提到如果在标准中进行规则统一,也会规定使用可视区域的坐标

显然我们如果要用这个方法时,就要注意兼容了,而对于同一种浏览器,因为版本的不同,导致同样的这个方法可能要求传入的坐标也不同,比如chrome浏览器,那么,我们该如何去兼容呢?

The w3c specification says:

The elementFromPoint(x, y) method, when invoked, must return the element at coordinates x,y in the viewport. The element to be returned is determined through hit testing. If either argument is negative, x is greater than the viewport width excluding the size of a rendered scroll bar (if any), or y is greater than the viewport height excluding the size of a rendered scroll bar (if any), the method must return null. If there is no element at the given position the method must return the root element, if any, or null otherwise.

调用elementFromPoint时,必须传入可视区域内的坐标,如果你传入的坐标不在可视区域内,即使在这个坐标处有元素,也将返回null;我们可以根据这个特性来写兼容代码:

使用jq实现的代码如下,我们可以很方便的改写成自已的

(function($) {
    var check = false,
        isRelative = true;
    $.elementFromPoint = function(x, y) {
        if (!document.elementFromPoint) return null;
        if (!check) {
            var sl;
            if ((sl = $(document).scrollTop()) > 0) {
                isRelative = (document.elementFromPoint(0, sl + $(window).height() - 1) == null);
            } else if ((sl = $(document).scrollLeft()) > 0) {
                isRelative = (document.elementFromPoint(sl + $(window).width() - 1, 0) == null);
            }
            check = (sl > 0);
        }
        if (!isRelative) {
            x += $(document).scrollLeft();
            y += $(document).scrollTop();
        }
        return document.elementFromPoint(x, y);
    }
})(jQuery);

原理就是上面说的,如果页面有滚动,则尝试获取页面坐标最边缘处的元素,如果能获取到,说明是使用页面坐标,因为在有滚动的情况下,获取可视边缘处的坐标,页面坐标会大于可视区域的坐标,所以如果是用可视区域坐标,肯定返回null

嗯,一切看起来都还不错,IE6 7就不行了,仔细看了下这个方法,这个方法最早应该是IE特有的,最后被其它浏览器实现,在IE下,一直使用的是可视区域的坐标,但是在IE6 7的情况下,当你传大于可视区域的坐标时,也是可以获取到值的,也就造成了上面兼容代码无法在IE6 7下正常工作,所以上面的代码并没有考虑IE6 7的情况,需要你添加一些判断。

除了坐标问题外,该方法只能返回顶层元素,也就是在有2个元素重叠的情况下,只能返回最上层的元素。

之前我也有写过高效拖动的文章,比如拖动排序分类,常见的是鼠标在拖动的时候,不停的计算鼠标是在哪个分类上面,然后做出变换的效果,如果列表元素比较少的情况下还是可以的,如果大于1000个,而这些分类的高度不定,通过这个循环判断的方法显示就会觉得很卡

我在之前的文章中提到可以在mousemove时,不让任何元素挡着鼠标(通常我们可能会在拖动时,让被拖动的元素随鼠标一起移动,这时候元素可能挡在鼠标的下方),可通过事件的event.target获取鼠标指向的元素,这样列表中有多少个元素都不会影响到效果

回头说一下setCapture方法,该方法是IE下让元素捕获到事件,比如鼠标移到浏览器外边也可以响应得到,然而这个方法在firefox在4版本时被引进firefox中,引入后如果拖动时你调用了setCapture,就算鼠标下面没有东西挡着,event.target也始终是鼠标按下时的target,IE中则不是,调用setCapture后,mousemove时依然可以获取到,当然IE下可能要用event.srcElement获取

所以,保险起见,我们要调用setCapture,而调用后,firefox4以后又不能及时获取到鼠标下的元素,抛开这些,在ios设备上,touchmouse时,同样也是获取不到手指指向的元素,所以只好回头折腾这个elementFromPoint了。

在折腾这些的时候,还发现诸如getBoundingClientRect在ios设备上也是有问题的,这个方法正常返回相对可视区域的坐标,而在ios上,实现的却是相对页面的坐标,实在让人郁闷

回头再看一下兼容,之前做浏览器间的兼容,更多的是这个浏览器有这个方法,那个浏览器有那个方法,方法的不同而已,现在的兼容则是同样的方法,最终的结果不同,比如setCapture还有getBoundingClientRect等,可能还有其它一些有问题的方法,这种兼容起来更麻烦,远不如没有方法来的干脆些。

网页关键字高亮显示

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style type="text/css">
<!--
.adKeyword {
color: #FF0000;
}
-->
</style>
</head>
<body>
<p>  一个和尚挑水吃、两个和尚抬水吃、三个和尚没水吃。总寺的方丈大人得知情况后,就派来了一名主持和一名书记,共同负责解决这一问题。主持上任后,发现问题的关键是管理不到位,于是就招聘一些和尚成立了寺庙管理部来制定分工流程。为了更好地借鉴国外的先进经验,寺庙选派唐僧等领导干部出国学习取经;此外,他们还专门花钱请了天主教、基督教的神父传授MBA。神父呆了不久留下几个东东就走了,一个叫BPR,一个叫 ERP。</p>
<p> </p>
<p>  书记也没闲着,他认为问题的关键在于人才没有充分利用、寺庙文化没有建设好,于是就成立了人力资源部和寺庙工会等等,并认认真真地走起了竞聘上岗和定岗定编的过场。</p>
<p> </p>
<p>  几天后成效出来了,三个和尚开始拼命地挑水了,可问题是怎么挑也不够喝。不仅如此,小和尚都忙着挑水、寺庙里没人念经了,日子一长,来烧香的客人越来越少,香火钱也变得拮据起来。为了解决收入问题,寺庙管理部、人力资源部等连续召开了几天的会,最后决定,成立专门的挑水部负责后勤和专门的烧香部负责市场前台。同时,为了更好地开展工作,寺庙提拔了十几名和尚分别担任副主持、主持助理,并在每个部门任命了部门小主持、副小主持、小主持助理。</p>
<p> </p>
<p>  老问题终于得到缓解了,可新的问题跟着又来了。前台负责念经的和尚总抱怨口渴水不够喝,后台挑水的和尚也抱怨人手不足、水的需求量太大而且没个准儿,不好伺候。</p>
<p> </p>
<p>  为了更好地解决这一矛盾,经开会研究决定,成立一个新的部门:喝水响应部,专门负责协调前后台矛盾。为了便于沟通、协调,每个部门都设立了对口的联系和尚。   协调虽然有了,但效果却不理想,仔细一研究,原来是由于水的需求量不准、水井数量不足等原因造成的。于是各部门又召开了几次会,决定加强前台念经和尚对饮用水的预测和念经和尚对挑水和尚满意度测评等,让前后台签署协定、相互打分,健全考核机制。为了便于打分考核,寺院特意购买了几个计算机系统,包括挑水统计系统、烧香统计系统、普通香客捐款分析系统、大香客捐款分析系统、挨上必死系统(简称IBS系统)、马上就死系统(简称MS系统)等,同时成立香火钱管理部、香火钱出账部、打井策略研究部、打井建设部、打井维护部等等。由于各个系统出来的数总不准确、都不一致,于是又成立了技术开发中心,负责各个系统的维护、二次开发。由于部门太多、办公场地不足,寺院专门成立了综合部来解决这一问题,最后决定把寺院整个变成办公区,香客烧香只许在山门外烧。 </p>
<p> </p>
<p>  部门多、当官的多档和开会自然就多,为了减少文山会海,综合办牵头召开了N次关于减少开会的会,并下达了“关于减少档的档”。同时,为了精简机构、提高效率,寺院还成立了精简机构办公室、机构改革研究部等部门。 </p>
<p> </p>
<p>  一切似乎都合情合理,但香火钱和喝水的问题还是迟迟不能解决。问题在哪呢?有的和尚提出来每月应该开一次分析会,于是经营分析部就应运而生了。分析需要很多数据和报表,可系统总是做不到,于是每个部门都指派了一些和尚手工统计、填写报表、给系统打工。</p>
<p> </p>
<p>  寺院空前地热闹起来,有的和尚在拼命挑水、有的和尚在拼命念经、有的和尚在拼命协调、有的和尚在拼命分析……忙来忙去,水还是不够喝、香火钱还是不够用。什么原因呢?这个和尚说流程不顺、那个和尚说任务分解不合理,这个和尚说部门界面不清、那个和尚说考核力度不够。只有三个人最清楚问题之关键所在,那三个人就是最早的那三个和尚。说来说去,就是***闲人太多了!他们说:“整天瞎分析个屁!什么***流程问题、职责问题、接口问题、考核问题,明明就是机构臃肿问题!早知今日,还不如当初咱们仨自觉自律一点算了!如今倒好,招来了这么一大帮傻B,一个个不干正经事还***人五人六的,跟屎盆子一样甩都甩不掉!”</p>
<p> </p>
<p>  又过了一年,寺院黄了,和尚们也都死了。人们在水井边发现了几具尸体,是累死的;在寺院里发现了几千具尸体,是渴死的。</p>
</body>
</html>
<script language="JavaScript" type="text/javascript"><!--
var keys = [
["和尚",""],
["系统",""],
["念经",""],
["工会",""]
]
var bookmark;
if(document.createRange){
var range = document.createRange();
}else{
var range = document.body.createTextRange();
bookmark = range.getBookmark();
}
var key;
for(var i = 0;key = keys[i];i++){
if(range.findText){
range.collapse(true);
range.moveToBookmark(bookmark);
while(range.findText(key[0])){
range.pasteHTML(range.text.fontcolor(key[2]));
}
}else{
var s,n;
s = window.getSelection();
s.collapse(document.body,0);
while(window.find(key[0])){
var n = document.createElement("SPAN");
n.style.color=key[2];
s.getRangeAt(0).surroundContents(n);
}
}
}
//--></script>

基于Web音频API的流式音频数据实时分析

Web音频API是一个高级的JavaScript API,用于处理和合成Web应用程序中的音频。API的目标是实现游戏中的动态声音效果、音乐制作应用程序中的声音处理以及音乐可视化器中的实时分析等功能。

音乐可视化器创建和渲染与音乐属性(频率、响度等)变化同步的动画。大多数媒体播放器(如Windows Media PlayeriTunes)都具有音乐可视化功能

image

在浏览器中创建这种可视化只有通过预先处理音频并单独存储信息来实现,以便在播放期间由可视化器访问。

API目前是一个工作草案,因此可以随时更改。Chrome部分支持(我们使用webkit前缀),我们可以开始尝试、研究它的特性。在本文中,我们将开始研究API的实时分析功能。

音频路由图

API基于音频路由图的概念。最简单的是,音频路由图:由直接连接到声音目标(如计算机扬声器)的单个声源(如MP3文件中的音频数据)组成。

image

通常,路由可以包含连接在一个或多个音源之间并最终连接到目的地(您能听到的)的任意数量的“节点”。音频数据被传入每个节点,以某种方式操作并输出到下一个连接。

使用API主要是为了创建不同类型的节点(一些用于控制音频的各种属性,一些用于添加效果等),以及定义节点应如何连接在一起。正如您所能想象的,与上面显示的简单连接相比,这可以允许更复杂和强大的路由

AudioContext

AudioContext对象是用于创建声源、创建音频操作节点以及定义它们之间的连接的主要抽象。

let context = new webkitAudioContext();

那么,让我们看看如何使用它来创建我们前面展示的简单的从源到目标路由。

首先,我们需要声源。创建音源的一种方法是使用XMLHttpRequestMP3文件中的音频加载到内存中。在下面的代码中,我们使用了AudioContextcreateBufferSource来创建源节点。然后我们使用上下文的createBuffer函数将来自请求的arrayBuffer响应转换为audioBuffer,并使用该函数设置源的buffer属性

let request = new XMLHttpRequest();
request.open("GET", urlToMp3File, true);
request.responseType = "arraybuffer";

request.onload = function() {
    let source = context.createBufferSource();
    source.buffer = context.createBuffer(request.response, false);
}

request.send();

我们不需要创建目标节点。AudioContext有一个destination属性,它表示音频硬件的最终目的地。我们只是通过将源对象连接到AudioContext的目的地来创建路由。

source.connect(context.destination);

流式音源

上面描述的缓冲区方法对于短的音频剪辑是很好的,但是对于较长的声音,我们不希望等待将完整的数据加载到内存中!然而,在音频路由图中,很容易将流式音频输入作为声源。为此,我们使用一个<audio>html元素

<audio id="player" src="urlToMp3"></audio>

<audio>元素表示音频流。AudioContext有一个函数createMediaElementSource,它创建一个声音源节点,该节点将重新路由元素的音频播放并通过路由图传输它

let audioElement = document.getElementById("player");
let source = context.createMediaElementSource(audioElement);
source.connect(context.destination);

您可能需要注意的一个“问题”是,源及其连接可能需要在音频元素准备好播放后创建

audioElement.addEventListener("canplay", function() {
    let source = context.createMediaElementSource(audioElement);
    source.connect(context.destination);
});

分析节点

所以,现在我们的流输入进入路由图,直接进入音频硬件。但是,为了让我们的音乐可视化,我们如何进行实时分析呢?嗯,我说过路线很简单

image

API提供了一个节点,它为我们提供了全部功能——AnalyserNode。我们所需要做的就是创建一个分析节点,并将其连接到源和目标之间的路由图中。在路由图中使用AnalyserNode时,音频数据是通过未经处理的方式从输入传递到输出的,但是我们可以使用node对象实时访问频域和时域分析数据。

如您所料,可以使用AudioContext对象上的createAnalyster函数创建AnalyserNode

let analyser = context.createAnalyser();

为了创建路由图,我们只需在流音频源和目标之间插入分析器。

audioElement.addEventListener("canplay", function() {
    let source = context.createMediaElementSource(audioElement);
    //链接音频源到分析器
    source.connect(analyser);
 //再把分析器链接到目标节点
    analyser.connect(context.destination);
});

默认情况下,分析仪将为我们提供1024个数据点的频率数据。我们可以通过设置fftSize属性来更改此设置。fftSize必须设置为2n次幂,频率分析中的数据点数量始终为fftSize/2。分析器的frequencyBinCount属性将告诉我们在频率数据中要得到的数据点的数量。

console.log(analyser.fftSize); // 2048 by default
console.log(analyser.frequencyBinCount); // will give us 1024 data points

analyser.fftSize = 64;
console.log(analyser.frequencyBinCount); // fftSize/2 = 32 data points

因此,如果我们使用frequencyBinCount元素保留一个字节数组,我们可以随时用频率数据填充它,方法是将它传递给分析器的getByteFrequencyData函数

let frequencyData = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(frequencyData);

创建动画

使用此实时数据创建和呈现动画的最佳方法是在requestAnimationFrame回调中刷新频率数据,然后使用新数据更新动画。requestAnimationFrame只是为动画帧安排在下一个适当的时间再次调用函数。它允许浏览器将动画更新与屏幕的重新绘制同步(并可能根据CPU负载进行其他优化,无论页面当前是在后台还是前台选项卡中,等等)。

function update() {
    // 等待下一次绘制
    requestAnimationFrame(update);

    //获取新数据
    analyser.getByteFrequencyData(frequencyData);

    // 更新界面
    bars.each(function (index, bar) {
        bar.style.height = frequencyData[index] + 'px';
    });
};

// 开始绘制
update();

这里,我们只是使用频率数据来设置一些彩色“条”的高度。当然,仅仅在条形图中显示频率数据是最简单的音乐视觉化,但是如果有更多的想象力和创造力,应该可以使用这种方法来创建一些更有趣的音乐视觉化

如何隐藏页面滚动条并防止页面内容左右移动

用户体验要求越来越高,像网页的alert或confirm都拿层来模拟了,以提升用户体验

但是在模拟的时候,我们一般会拿一个半透明的div放在后面,以防止用户点击到弹框后面的内容

但是我们却无法遮盖着滚动条,用户依然可以拖滚动条。

好了,需求出来了,要么那个半透明的div盖着滚动条,要么隐藏它

在不修改当前结构的情况下

显然盖着办到太难了,那到只想隐藏的办法吧。

在有文档声明的情况下,大部分浏览器的滚动条都是在html元素上的,而webkit在body上

隐藏比较好办,找到拥有滚动条的元素,把它的overflow设置为hidden

然而问题又来了,国内的网页绝大部分都是居中的,滚动条隐藏后内容会向右移动,在显示滚动条的时候,内容又会左移,造成内容一晃一晃的,很不舒服,这个问题也得解决

经过尝试,在隐藏拥有滚动条元素的滚动条时,把它的内容向左或向右用padding占一个滚动条宽度的位置即可

最后的代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" dir="rtl">
<head>
    <title>hide scrollbar</title>
    <style type="text/css">
    html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {
margin: 0;
padding: 0;
font-size: 100%;
vertical-align: baseline;
border: 0;
outline: 0;
background: transparent;
}

ol, ul {
list-style: none;
}

blockquote, q {
quotes: none;
}

:focus {
outline: 0;
}

table {
border-collapse: collapse;
border-spacing: 0;
}
    #main{width:900px;margin-left:auto;margin-right:auto;background-color:#ccc;}
    </style>
</head>
<body>
<div id="main"><input type="button" onclick="Scrollbar.hide();" value="hide" /><input type="button" onclick="Scrollbar.show();" value="show" />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br /></div>
</body>
<script type="text/javascript">
    var Scrollbar = {
        get: function (id) {
            return document.getElementById(id) || id;
        },
        getRoot: function () {
            return document.compatMode == "CSS1Compat"&&!/webkit/i.test(window.navigator.userAgent) ? document.documentElement : document.body;
        },
        getStyle: function (node, key) {
            node = this.get(node);
            if (node) {
                if (node.style[key]) return node.style[key];
                if (node.currentStyle) return node.currentStyle[key];
                if (window.getComputedStyle) return window.getComputedStyle(node, null)[key];
            }
            return null;
        },
        hasScrollbar: function () {
            var root = this.getRoot();
            if (window.innerWidth) {
                return window.innerWidth - root.offsetWidth;
            } else {
                return root.offsetWidth - root.clientWidth;
            }
        },
        hide: function () {
            var hs = this.hasScrollbar(), root;
            if (hs) {
                this.$hide = true;
                root = this.getRoot();
                this.$bakData = {
                    overflow: this.getStyle(root, 'overflow'),
                    overflowX: this.getStyle(root, 'overflowX'),
                    overflowY: this.getStyle(root, 'overflowY'),
                    paddingLeft: this.getStyle(root, 'paddingLeft'),
                    paddingRight: this.getStyle(root, 'paddingRight')
                }
                root.style.overflow = 'hidden';
                root.style.overflowX = 'hidden';
                root.style.overflowY = 'hidden'
                if (root.dir == 'rtl') {
                    root.style.paddingLeft = (parseInt(this.$bakData.paddingLeft, 10) + hs) + 'px';
                } else {
                    root.style.paddingRight = (parseInt(this.$bakData.paddingRight, 10) + hs) + 'px';
                }
            }
        },
        show: function () {
            if (this.$hide) {
                delete this.$hide;
                var root = this.getRoot();
                root.style.overflow = this.$bakData.overflow;
                root.style.overflowX = this.$bakData.overflowX;
                root.style.overflowY = this.$bakData.overflowY;
                if (root.dir == 'rtl') {
                    root.style.paddingLeft = this.$bakData.paddingLeft;
                } else {
                    root.style.paddingRight = this.$bakData.paddingRight;
                }
                delete this.$bakData;
            }
        }
    }

</script>
</html>

样式表是复制的reset.css 使页面表现在所有浏览器中一致

不管滚动条在页面的右边或是左边都可以达到要求

关键找准哪个元素拥有滚动条

关于onpopstate

Magix第1个版本做了hash与pushState之间的切换兼容
关于url解析可以看这篇

当时在做history.pushState时(2012年),发现对于onpopstate对于不同的浏览器是不一样的。

$(window).on("popstate", function() {
    alert('popstate');
});

上述代码在chrome中页面加载完成时竟然会弹出 popstate
现在仍然能够搜出很多在stackoverflow问这个问题的人,如
http://stackoverflow.com/questions/4688164/window-bind-popstate
http://stackoverflow.com/questions/6421769/popstate-on-pages-load-in-chrome/

当时阅读了pjax,使用了类似如下的解决方案

var initialURL = location.href,popped
$(window).bind('popstate', function(event) {
  var initialPop = !popped && location.href == initialURL
  popped = true
  if ( initialPop ) return

当然,现在并没有这样的问题了

存储信息

JSL = {
    LC: (function() {
        var store = null,
            engine = null;
        var searchOrder = ['localStorage', 'userData', 'globalStorage'];
        var engines = {
            localStorage: {
                test: function() {
                    return window.localStorage ? true : false;
                },
                init: function() {
                    store = localStorage;
                },
                get: function(key) {
                    return store.getItem(key);
                },
                set: function(key, value) {
                    return store.setItem(key, value);
                },
                del: function(key) {
                    return store.removeItem(key);
                }
            },
            globalStorage: {
                test: function() {
                    return window.globalStorage ? true : false;
                },
                init: function() {
                    store = globalStorage[document.domain];
                },
                get: function(key) {
                    return store.getItem(key).value;
                },
                set: function(key, value) {
                    return store.setItem(key, value);
                },
                del: function(key) {
                    return store.removeItem(key);
                }
            },
            userData: {
                test: function() {
                    return window.ActiveXObject ? true : false;
                },
                init: function() {
                    store = document.documentElement;
                    store.addBehavior('#default#userdata');
                },
                get: function(key) {
                    store.load(key);
                    return store.getAttribute(key);
                },
                set: function(key, value) {
                    store.load(key);
                    store.setAttribute(key, value);
                    return store.save(key);
                },
                del: function(key) {
                    store.load(key);
                    store.expires = new Date(315532799000).toUTCString();
                    return store.save(key);
                }
            }
        };
        for (var i = 0, l = searchOrder.length, engine; i < l; i++) {
            engine = engines[searchOrder[i]];
            if (engine.test()) {
                try {
                    engine.init();
                    break;
                } catch (ex) {
                    engine = null;
                }
            }
        }
        if (engine) {
            delete engine.test;
            delete engine.init;
        }
        return engine;
    })()
};

获取光标位置

从stackoverflow上看到的,记录一下 https://stackoverflow.com/questions/1589721/how-can-i-position-an-element-next-to-user-text-selection/1589912#1589912

var markSelection = (function() {
    var markerTextChar = "\ufeff";
    var markerTextCharEntity = "&#xfeff;";

    var markerEl, markerId = "sel_" + new Date().getTime() + "_" + Math.random().toString().substr(2);

    var selectionEl;

    return function() {
        var sel, range;

        if (document.selection && document.selection.createRange) {
            // Clone the TextRange and collapse
            range = document.selection.createRange().duplicate();
            range.collapse(false);

            // Create the marker element containing a single invisible character by creating literal HTML and insert it
            range.pasteHTML('<span id="' + markerId + '" style="position: relative;">' + markerTextCharEntity + '</span>');
            markerEl = document.getElementById(markerId);
        } else if (window.getSelection) {
            sel = window.getSelection();

            if (sel.getRangeAt) {
                range = sel.getRangeAt(0).cloneRange();
            } else {
                // Older WebKit doesn't have getRangeAt
                range = document.createRange();
                range.setStart(sel.anchorNode, sel.anchorOffset);
                range.setEnd(sel.focusNode, sel.focusOffset);

                // Handle the case when the selection was selected backwards (from the end to the start in the
                // document)
                if (range.collapsed !== sel.isCollapsed) {
                    range.setStart(sel.focusNode, sel.focusOffset);
                    range.setEnd(sel.anchorNode, sel.anchorOffset);
                }
            }

            range.collapse(false);

            // Create the marker element containing a single invisible character using DOM methods and insert it
            markerEl = document.createElement("span");
            markerEl.id = markerId;
            markerEl.appendChild( document.createTextNode(markerTextChar) );
            range.insertNode(markerEl);
        }

        if (markerEl) {
            // Lazily create element to be placed next to the selection
            if (!selectionEl) {
                selectionEl = document.createElement("div");
                selectionEl.style.border = "solid darkblue 1px";
                selectionEl.style.backgroundColor = "lightgoldenrodyellow";
                selectionEl.innerHTML = "&lt;- selection";
                selectionEl.style.position = "absolute";

                document.body.appendChild(selectionEl);
            }

            // Find markerEl position http://www.quirksmode.org/js/findpos.html
        var obj = markerEl;
        var left = 0, top = 0;
        do {
            left += obj.offsetLeft;
            top += obj.offsetTop;
        } while (obj = obj.offsetParent);

            // Move the button into place.
            // Substitute your jQuery stuff in here
            selectionEl.style.left = left + "px";
            selectionEl.style.top = top + "px";

            markerEl.parentNode.removeChild(markerEl);
        }
    };
})();

动态载入脚本,又一个教训,Opera真讲究

Opera 10.50版本

var s = document.createElement('script');
s.type = 'text/javascript';
s.src = 'abc.js';
s.onreadystate = s.onload = s.onerror = function() {
    alert('load');
}
document.body.appendChild(s);

这样的代码,如果存在abc.js文件则会弹出load 否则将不会弹出,操蛋

要改成下面的代码

var s = document.createElement('script');
s.type = 'text/javascript';
s.src = 'abc.js';
s.onreadystate = s.onload = s.onerror = function() {
    alert('load');
}
if (s.readyState && s.readyState == 'loaded') s.onerror(); //手动触发一下
document.body.appendChild(s);

把三次贝塞尔曲线放进外接矩形中

给出任意的4个点绘制一个三次贝塞尔曲线,把这个曲线放进外接的一个矩形内

三次贝塞尔曲线网上有很多种实现,我们找到这样的一个方法

let threeBezier = (t, p1, cp1, cp2, p2) => {
        let { x: x1, y: y1 } = p1;
        let { x: x2, y: y2 } = p2;
        let { x: cx1, y: cy1 } = cp1;
        let { x: cx2, y: cy2 } = cp2;
        let x =
            x1 * (1 - t) * (1 - t) * (1 - t) +
            3 * cx1 * t * (1 - t) * (1 - t) +
            3 * cx2 * t * t * (1 - t) +
            x2 * t * t * t;
        let y =
            y1 * (1 - t) * (1 - t) * (1 - t) +
            3 * cy1 * t * (1 - t) * (1 - t) +
            3 * cy2 * t * t * (1 - t) +
            y2 * t * t * t;
        return { x, y };
    }

给出任意的一个进度t(0<=t<=1)和4个点的坐标,我们可以计算出当前贝塞尔曲线上的一个点。

根据上述代码,我们可以推导出一个t的一元三次方程。

image

根据求根公式,我们只需要计算出在0-1区间内,对应的x和y最大值和最小值即可。

推导出计算区间的函数如下

let getRanges = (p1, cp1, cp2, p2) => {
        let part = -2 * (3 * p1 - 6 * cp1 + 3 * cp2);
        let power = Math.pow(3 * p1 - 6 * cp1 + 3 * cp2, 2);
        let delta = 4 * power - 36 * (p2 - p1 + 3 * cp1 - 3 * cp2) * (cp1 - p1);
        let down = 6 * (p2 - p1 + 3 * cp1 - 3 * cp2);
        if (delta > 0) {
            let sqrt = Math.sqrt(delta);
            let t1 = (part + sqrt) / down;
            let t2 = (part - sqrt) / down;
            if (t1 >= 0 && t2 >= 0 && t1 <= 1 && t2 <= 1) {
                return [t1, t2, 0, 1];
            } else if (t1 >= 0 && t1 <= 1) {
                return [t1, 0, 1];
            } else if (t2 >= 0 && t2 <= 1) {
                return [t2, 0, 1];
            } else {
                return [0, 1];
            }
        } else if (delta <= 0) {
            return [0, 1];
        }
    };

这样给出4个点,我们就能算出它x或y的最大值和最小值

然后根据最大x,y和最小x,y画出矩形即可,完成的代码如下

<!DOCTYPE html>
<html>

<head>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <title>Page Title</title>
    <meta name='viewport' content='width=device-width, initial-scale=1'>
</head>

<body>
    <div style="position:relative;width:500px;height:300px;background:#ccc;margin:50px;">
        <svg id="bezier" style="width:100%;height:100%;overflow:visible">
        </svg>
        <div style="position:absolute;border:solid 1px red;pointer-events: none;" id="rect"></div>
    </div>
</body>
<script>
    //p1 cp1 cp2 p2
    let bezierPoints = [
        { x: 100, y: 50 },
        { x: 150, y: 100 },
        { x: 260, y: 100 },
        { x: 200, y: 200 }
    ];
    let threeBezier = (t, p1, cp1, cp2, p2) => {
        let { x: x1, y: y1 } = p1;
        let { x: x2, y: y2 } = p2;
        let { x: cx1, y: cy1 } = cp1;
        let { x: cx2, y: cy2 } = cp2;
        let x =
            x1 * (1 - t) * (1 - t) * (1 - t) +
            3 * cx1 * t * (1 - t) * (1 - t) +
            3 * cx2 * t * t * (1 - t) +
            x2 * t * t * t;
        let y =
            y1 * (1 - t) * (1 - t) * (1 - t) +
            3 * cy1 * t * (1 - t) * (1 - t) +
            3 * cy2 * t * t * (1 - t) +
            y2 * t * t * t;
        return { x, y };
    }
    let getRanges = (p1, cp1, cp2, p2) => {
        let part = -2 * (3 * p1 - 6 * cp1 + 3 * cp2);
        let power = Math.pow(3 * p1 - 6 * cp1 + 3 * cp2, 2);
        let delta = 4 * power - 36 * (p2 - p1 + 3 * cp1 - 3 * cp2) * (cp1 - p1);
        let down = 6 * (p2 - p1 + 3 * cp1 - 3 * cp2);
        if (delta > 0) {
            let sqrt = Math.sqrt(delta);
            let t1 = (part + sqrt) / down;
            let t2 = (part - sqrt) / down;
            if (t1 >= 0 && t2 >= 0 && t1 <= 1 && t2 <= 1) {
                return [t1, t2, 0, 1];
            } else if (t1 >= 0 && t1 <= 1) {
                return [t1, 0, 1];
            } else if (t2 >= 0 && t2 <= 1) {
                return [t2, 0, 1];
            } else {
                return [0, 1];
            }
        } else if (delta <= 0) {
            return [0, 1];
        }
    };
    let updateOutlineRect = () => {
        let xRanges = getRanges(bezierPoints[0].x,
            bezierPoints[1].x,
            bezierPoints[2].x,
            bezierPoints[3].x);
        let yRanges = getRanges(bezierPoints[0].y,
            bezierPoints[1].y,
            bezierPoints[2].y,
            bezierPoints[3].y);
        let xValues = [];
        for (let xt of xRanges) {
            xValues.push(threeBezier(xt, bezierPoints[0], bezierPoints[1], bezierPoints[2], bezierPoints[3]).x);
        }

        let yValues = [];
        for (let yt of yRanges) {
            yValues.push(threeBezier(yt, bezierPoints[0], bezierPoints[1], bezierPoints[2], bezierPoints[3]).y);
        }

        let minX = Math.min(...xValues);
        let maxX = Math.max(...xValues);
        let minY = Math.min(...yValues);
        let maxY = Math.max(...yValues);

        rect.style.left = minX + 'px';
        rect.style.top = minY + 'px';
        rect.style.width = (maxX - minX) + 'px';
        rect.style.height = (maxY - minY) + 'px';
    };
    let updateBezier = () => {
        bezier.innerHTML = `<path style="fill:none;stroke:#000;stroke-width:1;" d="M${bezierPoints[0].x},${bezierPoints[0].y} C${bezierPoints[1].x} ${bezierPoints[1].y} ${bezierPoints[2].x} ${bezierPoints[2].y} ${bezierPoints[3].x},${bezierPoints[3].y}"/>
        <path d="M${bezierPoints[0].x},${bezierPoints[0].y} L${bezierPoints[1].x} ${bezierPoints[1].y} M${bezierPoints[2].x} ${bezierPoints[2].y} L${bezierPoints[3].x},${bezierPoints[3].y}" style="fill:none;stroke:#FA742B;stroke-width:1" />
        <circle onmousedown="resize(event,'start')" r="4" cx="${bezierPoints[0].x}" cy="${bezierPoints[0].y}" style="fill: #fff;stroke: #FA742B;" />
        <circle onmousedown="ctrl(event,'start')" r="4" cx="${bezierPoints[1].x}" cy="${bezierPoints[1].y}" style="fill: #fff;stroke: #FA742B;" />
        <circle onmousedown="ctrl(event)" r="4" cx="${bezierPoints[2].x}" cy="${bezierPoints[2].y}" style="fill: #fff;stroke: #FA742B;" />
        <circle onmousedown="resize(event)" r="4" cx="${bezierPoints[3].x}" cy="${bezierPoints[3].y}" style="fill: #fff;stroke: #FA742B;" />`;
    };
    let ctrl = (event, key) => {
        let index = key == 'start' ? 1 : 2;
        let startX = bezierPoints[index].x;
        let startY = bezierPoints[index].y;
        document.onmousemove = e => {
            let offsetX = e.pageX - event.pageX;
            let offsetY = e.pageY - event.pageY;
            bezierPoints[index].x = startX + offsetX;
            bezierPoints[index].y = startY + offsetY;
            updateBezier();
            updateOutlineRect();
        };
        document.onmouseup = e => {
            document.onmouseup = document.onmousemove = null;
        };
    };
    let resize = (event, key) => {
        let index = key == 'start' ? 0 : 3;
        let startX = bezierPoints[index].x;
        let startY = bezierPoints[index].y;
        document.onmousemove = e => {
            let offsetX = e.pageX - event.pageX;
            let offsetY = e.pageY - event.pageY;
            bezierPoints[index].x = startX + offsetX;
            bezierPoints[index].y = startY + offsetY;
            updateBezier();
            updateOutlineRect();
        };
        document.onmouseup = e => {
            document.onmouseup = document.onmousemove = null;
        };
    };
    updateBezier();
    updateOutlineRect();
</script>

</html>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.