About

Blog

如你所见,如我所想。

Me

Microtaku -> ~(>_<~)

Yuujin

以下为各位线上/线下认识的小伙伴们的真·无序排列:

| Posted by frantic1048

制作点兔的 Telegram 贴纸集小记

Telegram 刚出贴纸功能的时候就想给做一个关于 点兔 的贴纸集了,因为考试迟迟没有动工,上周终于从动画截图中挑选了 100 多张图准备来做贴纸,扣了大概 10 多张之后在群里问了问,幸运的是 Mika 来助力,三天帮我搞定了其中的 60 张,质量绝赞!前后快一个星期的时间最后出了 149 张贴纸 !最后看到自己扣了这么多图也是感到不可思议,大概这就是爱得深沉吧 _(:з」∠)_ 随后段时间我会把原尺寸的 png 图包发到 DA 上去。同时记个创贴纸的流程~

贴纸集链接:Gochiusa, Gochiusa2
DeviantArt 链接:Gochiusa - telegram stickers set

创建贴纸集

Stickers Bot 发送 /newstickerpack,随后它会提示你发送贴纸集的名字给它。

上传贴纸

先发送 1 个或者多个符合当前贴纸内容的 emoji 过去,bot 的建议是不超过两个 emoji。

然后以文件的形式发送对应贴纸的 png 图。多张贴纸重复此步骤即可。

注意

png 图片长宽需均小于等于 512px,且长边为 512px。

使用 imagemagick 可以一键批量搞定:mogrify -resize 512x512 -format png <your pictures>

批量操作之前一定要记得先备份!我就是因为这个操作导致原尺寸的文件全被原地 resize 到 512px 了,现在得手动重做出原尺寸的大图 ˊ_>ˋ

另外,单个 stickers set 的贴纸数量限制是 100(就这么轻易地触及上限了 _(:з」∠)_)

发布贴纸

向 bot 发送 /publish,随后它会提示你发送贴纸的链接名过去,就是一个贴纸链接 https://telegram.me/addstickers/ 之后连着的内容。

之后你可以继续 newstickerpack 上传新的贴纸集。

| Posted by frantic1048

在 Umbrello 的序列图中添加参与者

这几天用 Umbrello 画作业,在画序列图(Sequence diagram)的时候发现工具栏上竟然没有添加参与者(Actor)的按钮。

我感到很是困惑,因为之前画用例图(Use Case diagram)的时候是有的,序列图也是包含参与者这种单位的,然而工具栏却看不到它的身影。先搜索一番还看到有人把这个报成 bug,难道就因为这种小事换工具?脑中浮现隔壁用 Photoshop 画 UML 的家伙的嘲讽。一番摸索后发现了另一种添加参与者的方法:

  1. Tree View 里面,右键戳里面的 Use Case View,选择 New > Actor

  2. 这时 Use Case View 下面会出现一个新的的 Actor,双击它编辑好必要的信息。

  3. 打开要添加 Actor 的的序列图,在 Tree View 里面直接把那个 Actor 托放进编辑区,成了 (。・ω・)ノ

接下来就可以愉快地继续做作业了。

| Posted by frantic1048

Arch Linux 简易打包指南

这两天给 Kreogist µ 打 Arch Linux 包,照着 wiki 跟着搞,同时在肥猫和 Wicast C 及暴君还有 jimmy66 等强力大腿及小伙伴的支持下,几番折腾终于打好了,也算是入了个门。

搞完过来发现也算简单,总体来说其实就是一个 PKGBUILD 文件的编写。就着给 µ 打的这个包写个简单指南。在写的时候实在太不知道怎么写的地方还可以直接参考一下其他软件包的 PKGBUILD 是怎么写的我才不会说呢。

编写 PKGBUILD

在最开头,复制一份原型: /usr/share/pacman/PKGBUILD.proto(同目录下也有其他特别类型的原型),之后就从这个文件开始编写啦。

先读完文件开头那段注释,然后删掉它~

Maintainer

最开头一行注释是维护者的信息,按照它提供的格式填写上有效的信息即可。

pkgname

软件包的名字。只能用 小写字母、数字和@ . _ + - 这些字符,且不允许用.或者-作开头。

另外不要和 AUR 甚至是官方仓库里面的软件包重名了(´・ω・`)

pkgver

软件包的版本,就是你打包的那个软件的版本。可以使用数字和小数点,以及其它字符。进一步的规则可参考:VCS package guidelines - ArchWiki

pkgrel

软件包发行号,一般设为 1,如果你因为某些原因给同版本号的软件进行反复打包,那么每次打包的时候 pkgrel 就应该在原基础上递增一个数字,而在打包新的版本的时候,应该重新设为 1。

epoch

强行干涉包的新旧关系,拥有更大的 epoch 值的包会被认做更新的包(此时无视版本号),可以用在如版本号风格改变等需要的时候。默认值为 0,取值为正整数。一般不会用到。

pkgdesc

软件包的描述信息,最好一句话,且不包含软件的名字。

arch

表示支持的 Arch Linux 的架构,比如 i686x86_64,如果包与平台无关的话就填 any

url

与软件包相关的链接,一般是项目首页什么的。

license

软件发布协议,如果是常见的 GPL 的话可以对照下面填写:

  • (L)GPL - (L)GPLv2 及更新版本。
  • (L)GPL2 - 仅 (L)GPL2
  • (L)GPL3 - (L)GPL3 及更新版本

depends

这是非常重要的一项,需要正确填写上软件的依赖。

对于直接发布可执行程序的话,可以通过 ldd 来看程序连接了哪些库文件,结合搜索判断出具体依赖是什么软件包。你可以用谷歌在 https://www.archlinux.org 上搜索具体库的文件名,一般都能够找到对应的软件包。

如果你已经用 makepkg 打出了 .tar.xz 的包,也可以用 Namcap 来检查依赖是否存在问题,它会提供一些有用的信息帮助修正依赖。对于他的输出含义可以直接参考 ArchWiki

多测试多测试,确保依赖真的没问题。

source

构建软件包需要的文件。可以是一个本地文件,也可以是一个远程文件。 makepkg 会在构建包的时候自动下载填写的远程文件,并且会自动解包压缩文件。

md5sums

对应的 source 里面文件的 md5 校验码。

package()

在构架包的时候执行的函数。你需要把安装软件对应的操作写在这里。函数会在一个 fakeroot 环境下执行,对应的 root 目录就是 $pkgdir,比如你有一个可执行文件名为 $pkgname 要安装到 /usr/bin 下面,对应的命令就可以类似这么写:

install -m=775 $pkgname "${pkgdir}/usr/bin"

-m 选项表示目标文件的权限,和 chmod 参数同理。

常用目录

目录 | 用途
----|--
/etc | 系统关键配置文件,如果件有多个,应该创建合适的子目录来存放
/usr/bin | 二进制文件
/usr/lib | 库
/usr/include | 头文件
/usr/lib/{pkg} | 模块,插件等
/usr/share/doc/{pkg} | 应用程序文档
/usr/share/info | GNU Info 系统文件
/usr/share/man | 手册
/usr/share/{pkg} | 程序数据
/var/lib/{pkg} | 应用持久数据
/etc/{pkg} | {pkg}的配置文件
/opt/{pkg} | 大的独立程序,例如 Java
/usr/share/applications/ | Desktop Entry (.desktop) 文件
/usr/share/icons/ | 图标,存在该目录下对应子目录位置

不该碰的目录:

  • /dev
  • /home
  • /srv
  • /media
  • /mnt
  • /proc
  • /root
  • /selinux
  • /sys
  • /tmp
  • /var/tmp

构建/调试包

在 PKGBUILD 所在目录下执行 makepkg 可以构建出对应的软件包,推荐用 namcap 检测一下构建出来的包有没有更显著的问题。

然后你可以用 pacman -U 命令安装它,看看会不会发生什么奇怪的事情,以及软件是否正常等。

当然还有可能因为 PKGBUILD 没写好,直接就报错不干了,这个时候需要顺着错误信息去修正 PKGBUILD。

发布到 AUR

在 PKGBUILD 所在目录执行 makepkg --source,会生成 .src.tar.gz 源码包,这就是需要上传到 AUR 的东西,注意不要把任何二进制文件加入源码包。

AUR (Arch User Repository) 注册(登入)帐号。进入 Submit 页面,选择好软件包对应的分类,然后添加源码包上传即可。

即使你是要更新一个包,也只需要直接在 Submit 页面上传,包的信息 AUR 会自己处理。

如果觉得每次上传太麻烦,你可以尝试一下 aurupload 来简化发布。

参考文档/维基

需要更详尽的内容以及更复杂的打包请参考以下。

| Posted by frantic1048

JS 中用字面语法设置对象属性时的“反直觉”行为

myObject.foo = 233;

服用《You Don't Know JS this and Object Prototypes》后,现在看到这句是再也不敢认为结果一定是 myObject 上有了一个名为 foo,值为 233 的属性了。

具体执行的结果还要看具体情形来决定。

如果 myObject 已经有一个名为 foo 的普通的属性了,那么执行的结果就是给 myObject 现有的 foo 属性进行了一次赋值。

然而 myObject 上面找不到 foo,那就和访问一个对象本身不存在的属性一样,JS 会一级一级地扒 myObject 的原型链最终确定 foo 的存在情况,从而来决定执行结果。

  • 如果原型链上也没有 foo,那么就直接在 myObject 上添加一个 foo 属性并赋值。

  • 原型链上找到了 foo,并且它是可写的(writable:true),那么也是直接在 myObject 上添加一个 foo 属性并赋值,从而原型链上的 foo 被遮盖了。

  • 原型链上找到了 foo,但它是只读的(writable:false),那什么都不会发生,myObject 上不会多一个 foo 属性,原型链上的那只 foo 也不会改变;如果你处在严格模式的话,JS 会顺便给你抛一个错误。

  • 原型链上找到了名为 fooSetter,这个时候始终会调用找到的那个 SettermyObject 上不会创建新属性,Setter 也不会被重新赋值。

还是来看直观的代码吧 ╮( ̄▽ ̄)╭

var Shoujo = Object.defineProperties ({}, {
  'hairColor':{ value:'black'
              , writable:true
              , enumerable:true
              , configurable:true },
  'isReachable':{ value:false
                , writable:false
                , enumerable:true
                , configurable:true },
  'makeUpCode':{ set:function (value) { console.log(value + ' Henshin !'); }
               , enumerable:true
               , configurable:true }
   });

var A = Object.create (Shoujo);

A.magicType = 'dark';
/*全新的属性,直接添加到原来的对象身上
Shoujo -> { hairColor: "black", isReachable: false, makeUpCode: undefined }
A -> { magicType: "dark" } 
*/

A.hairColor = 'silver';
/*原型链上既有的普通属性,也是直接添加到原来的对象身上
Shoujo -> { hairColor: "black", isReachable: false, makeUpCode: undefined }
A -> { magicType: "dark", hairColor: "silver" }
*/

A.isReachable = true;
/*原型链上既有的只读属性,什么都没有发生 ˊ_>ˋ
Shoujo -> { hairColor: "black", isReachable: false, makeUpCode: undefined }
A -> { magicType: "dark", hairColor: "silver" }
*/

A.makeUpCode = 'I am the bone of my...';
//"I am the bone of my... Henshin !"

/*原型链上既有的 Setter,调用 Setter
Shoujo -> { hairColor: "black", isReachable: false, makeUpCode: undefined }
A -> { magicType: "dark", hairColor: "silver" }
*/

另外,['propertyName'] 这种语法和 .propertyName 一样也遵循上面的行为。

当然,这些行为不会影响你使用 Object.defineProperty()Object.defineProperties() 来设置对象的属性。

| Posted by frantic1048

峨眉-牛背山骑行记


D1

日期:2015-2-9

路线:家-峨眉山市-双福镇-木城镇-三宝镇-洪雅县

交通:骑行

里程:59.9 km

住宿:涌泉大酒店,洪雅县

驼包各种物资就绪,满怀激情骑出家门,可能是热情给脑子冲傻了,这么多次没走错路的今天竟然走错了,原本要往城北走结果一路奔到了城东,然后又倒回来终于到了城北上了去双福的公路。进了双福镇问了下路进入了前往木城的路,这条路是第一天遇到的最烂的路了,小颠小簸过去。

到一个去往木城分岔路口的时候,我走成了另外一条错误的路,小下坡高兴蹬出去一公里多遇到一个交警,因为不放心就上去问了下木城的方向,结果得知走反了 ˊ_>ˋ,又苦逼地蹬回到岔路口去下木城。

过了三宝之后,路前面不知道多远的地方一直在放烟花,一路过去至少放了半个小时吧,休息的时候盯着看了好久。到了洪雅郊区在一家超市买了几大瓶水和一些饼干,在一家小饭馆吃了饭,老板很热心的给我指了路,然后向雅安狂奔,天越来越黑,幸好我还有个小车灯能勉强顶住,想着能走多少算多少吧,可是没想到竟然下!雨!了!(°Д°),越来越大,天又越来越黑,老爸电话过来也建议我快点找到休息的地方,这个时候还离雅安不少距离,所以就给队友说了声明天再到雅安集合,无奈之下原路返回了洪雅,路过涌泉大酒店特价 90,二话没说就进去了,前台说话的时候一直大眼睛盯着我也是醉了,说是楼层略高(6楼),让我就把车放在了前台的值班室,我就上去休息了,条件也蛮不错的,热水洗到爽 ╮( ̄▽ ̄)╭ 然后喝掉一大半瓶 1.25 L 的椰汁睡了,原本打算喝完的,可是晚饭吃了不少,喝水越喝越胀,最后还是决定早上喝了。

顺带一提我穿的衣服:抓绒骑行服一套、一个背心、一条骑行内裤、一个小裤裤。后面几天一直到牛背山街心花园我都穿这点衣服。虽然骑行服站着的时候的确分分钟会觉得冷到发抖(买的时候说好的抵抗零下十度看来是不科学的),但是开始骑之后不久,只要保持输出的话,体温就会在很合适的温度上不觉得冷,干的也蛮快的,每天骑了下来背都是干的,也没有过汗流浃背的感觉,赶脚骑行的话还是用骑行服比较合适一些,冲锋衣似乎太厚重了。

D2

路线:洪雅县-中保镇-槽鱼滩镇-竹箐镇-草坝镇-雅安市-多营镇-始阳镇-天全县

交通:骑行

里程:157.5 km ( + 97.6 km )

住宿:二郎山宾馆,天全县

为了尽早在雅安和队友汇合,早上 5 点多就爬起来,灌下剩下的椰汁,收拾好之后下楼取车,然后退房出来,刚好酒店门口旁边几米就是一家看起来不错的肥肠粉,开得也真是早,进去整了一大碗牛肉面,味道很棒呢,顺便问了下路,休息一会儿之后就出发了,离开洪雅就没路灯了,离天亮还早着呢,再次感谢我的小车灯,就靠着它慢慢爬坡,一路上看着天一点点亮起来,一个很长很长的坡上去之后是相对平缓一些的路,虽然路不是很好,但是比起之前的上坡感觉都不是事儿,果断 3-6 狂蹬,一路上真是风驰电掣的感觉,追一般摩托车都是小 case,到了槽鱼滩那边看到一个很有意思的前往汉王的路牌。

之后开始翻竹箐沟,没法儿风驰电掣了,一点点地磨上去,那地方整个山坡到处都是竹子,还是蛮好看的。差不多到达竹箐沟顶部的时候,看到了一个竹箐沟的石碑,看了一眼就骑过去了。之后的下坡还是爽爽的 (「・ω・)「

后来到了草坝,都已经见到雅安的公交了,心中很是激动,还以为已经到达了主城区,没想到一走又不知道多少公里才真正到达雅安城区(这公交线路这么长是闹哪样)。

快到主城区还有6公里时候路边出现了离主城区距离的里程牌,每公里都有一个,看着一个个牌子过去心中也是慢慢放心下来,中间一个电话和队友说好到 G318 入口集合,到了主城区之后看了眼地图,又沿着城边蹬了几公里终于到了那个位置。雨城今天没下雨,真是棒。

我到了之后一会儿队友也到了,这个时候已经中午,一起去最近的一个饭馆吃了个饭,商量今天行程。之后就上了令人激动的 G318,前往天全。出城一来就是各种坡,然后路况也越来越糟糕,大车小车非常密集,风沙灰尘也是非常浓厚,幸好有风镜君挡着让我不用爬着上坡还要同时内牛满面,根据队友体验来看,普通近视眼镜还是没法档风沙的,建议搞一个带近视镜框的风镜 ~^_^~,之后一个小弯道上遇到一个很大的泥水坑,这时候正好来一个越野车,很快的速度直冲进泥水坑,让我和坐骑都受到了巨大的溅射伤害 (。・_・。)

下午约 16 点到达天全,进城转悠了一番,决定入住二郎山宾馆,条件真是非常不错,就是热水一次还是有限的,冲澡得隔段时间去,之后就去了隔一条街的十字路口上的一家豆花饭吃晚饭,那个豆花和水煮肉都是相当不错的 (๑´ڡ`๑)。知道接下来的行程会很苦逼,所以之后又去了超市买了一些物资,士力架是必须有的啦。

晚上因为受不了白白的车上这么多泥,花了不小功夫给清理了一下还被队友吐槽了说明天分分种又全是泥。

D3

路线:天全县-青石乡-紫石乡-新沟村

交通:骑行

里程:208.1 km ( + 50.6 km )

住宿:聚缘食宿,新沟村

早上起来吃的宾馆自带的自助早餐,菜非常多,味道也蛮不错,队友对那个现做的面和煎蛋欲罢不能,我因为吃了好几个包子和番茄炒鸡蛋所以有点饱没能体验到,肚子当然是填得很饱,因为今天午饭多半就是干粮解决了。

出发才两公里,我就整个人跪了,起着大雾,然后进入了一两厘米厚的稀泥覆盖的超破碎混凝土交叉土石路面,有的路已经拆完,剩下起伏的土石路面(昨天清理的车现在又是一身泥了 ( T_T );还有的好点路的是被打满了坑,队友称之弹坑路,这简直是绝好的自行车初级控车考试路线。

到太阳终于升起,视野变得明亮没什么雾的时候,我们进入了大碎石泥土路面,颠簸程度超越前两天一大截,让你更本快步起来,上坡的时候如果输出不稳定会导致打滑然后停下来,可以选择重新起步或者推行,我这么懒的人当然是再慢都要骑过去啦 _(:з」∠)_

今天的路大都是在各种山脚下面绕过去绕过来,很多桥,各种奇奇怪怪的名字,比如“板桥沟桥”这纠结的名字,到了下午开始肚子饿了,到了一个加水的地方吃起了饼干,不得不说休息还是选择山的阳面比较好,阴面呆一小会儿就会很冷。而且路面变得更加反人类,不仅是被完全破坏的路面,还有一道道横着的深沟,配合非常多的泥沙碎石,打滑自然不说,过度的颠簸让我只能以和走路快不了多少的速度前进,而且还非常费力。

之后在阴面骑行的时候迪哥压上路中间的缝隙,正好遇到暗冰,给来了个臀部着地,前面大概一百米都有暗冰,还好发现了,暗冰路面非常光滑,而且看起来只是普通的有点潮湿的路面,或者根本看不出与普通路面有什么区别,所以到山的阴面的时候还是应该多加提防。那些暗冰路面还有不少区段是坑洼的卵石路,想要自行车起步基本没戏,几个人艰难地推车过去。

下午快到四点的时候到了新沟村,这里不少旅馆,但是都没什么生意,大概是因为川藏线一般是夏天才有人走吧,而且这又要过年了。我们直接去了一家据当地人说的最好的聚缘食宿。食宿的确都很不错,发现一路过来最好吃的还是回锅肉。

D4

路线:新沟村-二郎山隧道-甘谷地村-桐子林桥-冷碛镇

交通:骑行

里程:254.7 km ( + 46.6 km )

住宿:雨轩客栈,冷碛镇

大早上起来吃了老板娘煮的面,那调味没话说,饱饱的就上路了。

最开始的大概二十公里路还是和之前一样颠簸到手麻,之后鸳鸯岩附近开始上坡爬二郎山的时候路况有所好转,终于能见到基本完好的混凝土路面了,龙胆溪桥过去不远,我们又吃了点东西,水被喝光了,这个时候看到二郎山隧道前面有一个工棚,于是想着去要点水吃。

那边那些工人还是蛮热情的,还有交警大叔,二话没说就让我们进去接开水,这下我们的水储备又充足了。到了洞口几个人摆拍了几张照,然后发现洞里面简直冷得不行,队友都要加衣服,我想着直接一口气蹬过去就不冷了于是就直接进隧道了,里面的温度跟山阴面的风吹起来差不多,的确很冷,所以我一直狂蹬,加上有点下坡,速度越来越快,档位一直升,最后到了 3-9 我都还在用超快的踏頻蹬,里面限速 30,我想肯定早就和那些汽车一样全都超速了 ( >﹏<。),到了另外一端的时候大概过了两三分钟队友才过来。

另一端出来看到了长长的下山的公路,这下想着全是下坡真是爽,没想到还爬了两三公里长坡才真正到下坡开始的位置 (´・ω・`)

之后就是一直到冷碛镇,二十多公里的下坡真是下了个爽,这是我迄今走过的最爽的下坡了 ლ(╹◡╹ლ)

到达冷碛镇时间也是在差不多 16 点的样子,找好住宿后冲了澡去吃了个饱饭,顺便去一个咨询站问了一下上山的路线,那个人给我们说明路线还顺便画了个草图,另外还给了经常在山上的 邓军长 的电话,说山下部分的路他能指,过了邓军长旅社山上的路的话就是邓军长最清楚了,有问题就直接问他。

D5

路线:冷碛-砖厂-新路-牛背山街心花园

交通:骑行

里程:284.7 km ( + 约 30 km )

住宿:牛背山街心花园,牛背山

考虑到昨天问的路,据说行程非常长能走 10 个小时左右。我们天不亮起来,找了一家就近的小吃店各吃了一碗面,还一起吃了一笼包子。

沿着冷碛镇新街朝石棉方向走,路过了一个小隧道,照着昨天问的路,过了一个小桥就左转,这个时候路面还是平整的水泥路,后面又到了一个看起来略气派的二岔路口走左边。之后就是传说中四十五度的陡坡了,非常多的坡,路面是各种碎石,有的路段直接是一层很厚的碎石。有的坡度如果输出不稳定不够大力的话,就会直接打滑导致停下来,还要记得压住车头,要不就人就飞了,路的一侧是很高的岩壁。

骑了大概两三个小时到达了邓军长旅社,看起来还在装修外墙的样子,搭了不少架子,我们进去接了开水,之后继续上路。上去之后好几个没路牌的岔路口,依然是很陡的坡,转两个弯高度一下子就上去了好几米,过了渔进村后的第二个村前那个岔路口我们走错了,过去爬了一公里多的陡坡,感觉不对劲的时候问了一下邓军长,他直接让我们把照片彩信过去,我们的确是走错了,心中万分纠结中小心翼翼滑到了之前的路口继续向前。

路还是一直陡到必须压车头的地步,走一会儿又没水了,正好经过一个村庄,去了一户人家要开水,结果他们就顺便问我们要不要坐车上山,各种说我们不可能上去,推车两三天才能到街心花园什么的,而我从来时候就一心想要骑上去,虽然已经累得腿软了,即使很慢,我还是想骑上去。几个人谈论中我表态都是人车要一起到街心花园,而且对对方描述的我们上不去的说法感到非常怀疑,总觉得是想圈我们几个生意,后来队友两个觉得价格太坑爹,而且根据之前获取的情报来看也不可能需要两三天才能到达街心花园。道谢之后我们又一路向上了,这也算是对我们的一次考验吧。

中途有段路我们是饿得不行了,干粮也吃了不少,士力架也在之前有一次休息的时候全部吃光了,一位队友掏出了昨天买的椰丝味压缩饼干,因为小时候春游买过压缩饼干留下了可怕的印象,所以一直没再买过。可是队友的这个压缩饼干真是十分美味,不像过去的那么枯燥的味道,我对压缩饼干大大有所改观,真的不是因为饿晕了,的确味道不错。队友说买的时候还看到一个薄荷味的,味道难以想象没敢买。

到了下午四五点,我们已经爬上了相当的高度,这个时候山路没有这么陡了,而是相对平缓一些的持续上坡,绕过好几个山头仍然不见街心花园,风很大,而且周围有积雪,气温不到 10 度,我的服装显得有点单薄了,冷得不行,走着走着手都已经发麻了,望了一下对面的山路,想着大概绕过那座山之前能够到达街心花园吧,这个时候我们也只有不停向前了,我使劲蹬着,同时也是为了取暖,最后终于翻过一个小上坡,转过一个土包之后看到街心花园,整个人都不冷了 ╮( ̄▽ ̄)╭

吃晚饭的时候发现原来路上爬坡的时候一个越野车上大叫给我们加油的胖叔叔就是街心花园那个大爷的儿子,感觉蛮有意思的。街心花园这个地方有个好处就是全天有电,山顶只有每天 19 : 00 ~ 21 : 00 三个小时间发电机发电,水的话也就能满足饮用。之后商量了一下明天的行程,原本决定坐车上去,然后没看到日出的话就在上面住一晚上第二天下山坐车回去,如果看到了就玩一天,天黑之前回到街心花园之后一天下山回去。正好街心花园的大爷的孩子大都是开车的,说能够帮我们订冷碛到成都的客车票,这又一下子减少了我们的一个大问题。因为冷碛街上还是不太好坐车的,而且是三个人三个车,我们打算是骑到达泸定去买起点票,这样的话稳妥一些。

吃过晚饭之后,天已经完全黑了,除了街心花园外面有一个照明的小灯,周围望去都看不到一丁点灯光。抬头仰望星星,那大概就是 繁星满天 所要描述情景了吧(感谢文豪赵兄和文霸王叮咚的用词指导),这也是我第一次写东西能够真真切切地用到这个词。人生第一次亲眼看到了银河,心中那份激动难以忘怀,我一定要像 2013 年 8 月 14 日看英仙座流星雨那夜(看到了 14 颗流星呢 ლ(╹◡╹ლ) )一样在牛背山上躺一整夜到天亮一直盯着天空,嗯,顺便该去配眼镜了。

D6

路线:牛背山街心花园-牛背山顶

交通:坐车

里程:299.7 ( + 约 15 km )

   骑行:284.7 km

   坐车:15 km ( + 约 15 km )

5 点半起来,我穿上了预备的保暖衣和羽绒服,喝了几口水就上车了,6 点准时出发,一路上车子各种剧烈颠簸,看来自行车走这种路还是蛮有优势的,各种深坑过去毫无压力。

绕过了最后一个山头的时候,师傅停车装防滑链,我们下车来透气。这个时候天是黑的,月亮真的是非常亮呢,周围很安静,满天星星静静地在天上挂着,一闪一闪,偶尔有山风吹过,那种静谧让我就想这样躺在这里,看着天空就满足了。我和一个队友还看到了一颗流星!

最后一段路上冰雪很多,有个弯道冰层太厚,各种打滑过不去,我们都下车来,师傅花了不少功夫才冲过去,一路上迪哥吓得不停的娇呻,根本停不下来。

到了山顶之后,我们下车来,向导给我们带到达山顶最高点的路,天空勉强有点亮光了,加上月光用来照明走路不成问题。虽然能够直接看到要去的位置,但是走起来还是挺费劲的,心中的激动驱使双脚不能地跨步,那点疲倦在现在已经不算什么了,我已经到这里了!

山顶上还有稀疏的十几个人架着相机守日出,这么冷的天为了操作设备不带手套也是蛮拼的,我手拿出来一会儿就会麻掉。四周环望能够看到很多大山和东方的地平线(西方主要是各种大山),我能认出来就最大号的那座贡嘎山了。接着就是静静守候日出,远处的地平线上开始有一丝像是岩浆溢出,透着血红,一会儿出现了一层更亮的金色,后面的山全都映着一层暗红色,就连云也是铁锈般的红。

太阳出来之后竟然还有个人在这山顶放起了风筝,风很大,而且方向经常变,他们放了好几次又掉下来,就为了拍照 (´・ω・`) 期间还遇到了一个户外狂魔大叔帮我们拍高难度照片,给我们介绍了不少户外的事情。

转悠一会儿之后去客栈烤着火炉吃了碗暖暖的泡面,温饱问题就解决了,之后我们就去玩雪了,堆了一个不及膝盖的小雪包,我说觉得太小了,队友说要多大嘛,我说要人这么大,然后他们就去玩雪了,在雪上面玩拓印什么的,期间还打了雪仗,最后他们和大叔去另外一个山头逛了,我一直堆雪,他们回来了我还在堆,幸好大叔把太阳镜借给了我,要不我就得堆瞎了,今早出门前没换镜片真是失策。一直堆了好几个小时,我终于堆到了和我差不多的高度 (。◕‿◕。)

路线:牛背山顶-牛背山街心花园

交通:徒步

里程:309.7 ( + 约 10 km )

   骑行:284.7 km

   徒步:10 km ( + 约 10 km )

   坐车:15 km

住宿:牛背山街心花园,牛背山

下午下山的时候,我们下得略早了一些,因为路长怕天黑,山坡上各种走, 15 点左右看到了云开始变得粘稠,大概是云海要出现了,这个时候已经回不去了,只好继续下山,最后回到街心花园,准备第二天下山了。

街心花园的大爷给我们联系到了客车,说是要 12 点 45 得在冷碛镇上,然后得知上山还有另外一条老路,虽然长一点但是没上来的路上这么丧心病狂的陡坡。而下山也需要好几个小时,所以决定天亮就直接出发。

D7

路线:牛背山街心花园-老路-冷碛镇

交通:骑行

里程:344.7 km ( + 约 35 km )

   骑行:319.7 km ( + 约 35 km )

   徒步:10 km

   坐车:15 km

又是天不亮起床,收拾好东西之后差不多天亮我们就开始下山了,早晨加上山风吹起来还是蛮冷的,所以我只有裤子恢复到了前几天的水平,衣服就直接羽绒服加保暖衣了。路上还是有点小紧张,怕赶不上,不过还好下山速度也不算太慢,最后下到了桐子林桥头。也就是说老路是从桐子林桥过去左转上山,而新路是下冷碛新街过去遇到一个小桥左转上去的。

到镇上的时候才 11 点,我们先给师傅打了电话让他好给我们留位置,然后就直接去填肚子去,从上面下来还没吃过什么东西。

路线:冷碛镇-石棉县-汉源县-茔经县-雅安市-新津县-成都市-眉山市-峨眉山市

交通:坐车

里程:797 km ( + 约 452 km )

   骑行:319.7 km

   徒步:10 km

   坐车:467 km ( + 约 452 km )

坐上车整个人都放心了,虽然起那么早,但是一点都睡不着。车上闷闷的。冷碛出去大概 20 分钟还在路上看到一个骑自行车往石棉方向走的人 (°Д°) 一路望着大渡河前行,然后在石棉上了雅西高速,各种隧道,特别是泥巴山那十多公里的隧道,进去之后感觉就天黑了,都起了些许睡意。之后得到消息成都有 19 : 20 的末班回峨嵋的客车,我只能祈祷车能够快点到成都了。

到了成都之后,得知这辆车不去新南门车站了(开往峨嵋的车在那儿发车),我和一个住在成都南的队友在洗面桥街下车,他给我带路到了车站,真是业界良心,到的时候是 19 点几分,顺利赶上了末班车。

路线:峨眉山市-家

交通:骑行

里程:801 km ( + 4 km )

   骑行:323.7 km ( + 4 km )

   徒步:10 km

   坐车:467 km

坐车到了夹江的时候开始飘雨,而且是越来越大,当时整个人都不好了,到城北车站开始吓人的时候,师傅要送一位乘客去报国寺,正好也多载我一程,回去的路就只剩下 4 km,下车之后师傅还很热心的问我有没有雨衣。我当然有啦,脱下上衣塞进托包,套上骑行服带上风镜就开始狂奔了,感觉这种柏油路面上面的这些坡道完全是平路乃至是下坡,毫无压力地几分钟就蹬回了家 (ง •̀_•́)ง


更多照片请前往我的相册

Written with StackEdit.

| Posted by frantic1048

解决 MacOS 不能开中文版 AI

Mac 上开中文 Adobe Illustrator 会有鬼畜的错误对话框出现,进去之后几乎所有中文变成问号。刚帮某同学解决了这个问题,权当记录。方法是网上扒到的,倒是简单。

以下是记录终端中的操作方法,如果不放心就直接复制粘贴命令吧 (:з」∠)

步骤1:

打开终端,来到 AI 的目录,一般形如一下, cd 过去即可:

cd /Applications/Adobe\ Illustrator\ CS6/Adobe\ Illustrator.app/Contents/MacOS

注意这个路径是从根目录开始的。

步骤2:

把目录下的名为 Adobe Illustrator 的文件更改个名字(这里改名为 AICS6 ),用 mv 即可。

mv Adobe\ Illustrator AICS6

步骤3:

创建一个新的名为 Adobe Illustrator 文件,内容如代码所示,cat 搞定~

cat > Adobe\ Illustrator <<'EOF'
#!/bin/bash

BASEDIR=$(cd "$(dirname "$0")"; pwd)
"$BASEDIR/AICS6" -AppleLanguages '("zh-Hans")'
EOF

步骤4:

给刚刚创建的文件赋予执行权限, chmod 搞定。

chmod +x Adobe\ Illustrator

步骤5:

这个时候你就可以去启动你的 AI 啦~

| Posted by frantic1048

信仰

之前赵导说到要谈谈信仰,我这人当面说话能力太捉计,而且还容易羞涩,面谈话估计半天找不到头绪,想了想还是写下来好了。

为了不跑题事先了解了下信仰的基本解释,我现在的理解以及我所叙述的信仰都是抱有的信心和信任所在

软件

我并不是狂热的 Unix 设计哲学粉之类的人,况且我也不知道自己是否真的理解了它。我所解读出的 让程序只做好一件事小即是美 以及 可移植性很重要 这三点上我是体会到了其好处所在的,所以现在的我信任这三个观点。

从最初接触电脑到现在,上面的软件随着时间一点一点变化着,那个时候我完全是出于好奇,尝试了很多不同的软件,因为我用电脑啊,软件就是指挥电脑做事情的,我一直这样认为,每想着用电脑干什么,就会去寻找一下有没有干这些事情的软件了,然后随便玩玩。

过了一段时间,在获得了能够完成我的需求的软件的列表的时候,我会进行一个很奇怪的筛选,拿通讯软件来说,要是问 MSN 和 QQ 那个时候我会怎么选择,我会毫不犹豫地选择 QQ,为啥,更加好玩啊,一键截图呢,16MiB 的网盘,个性签名,各种好玩的东西呀,当年为了点亮一个个的图标疯狂的干了很多事情,后来又兴起了灭掉所有图标的风潮,不过那个时候我已经不在意这些东西了。

现在呢?我自认为已经不用 QQ 了,尽管还有很多好友在上面,我也就每周想起来了查收一下有没有什么要命的消息,有 QQ 的同学我会先问他们有没有什么通知,如果有正好找我的消息我会回,如果短时间内回复的话可能会根据具体情况聊一会儿,其余情况直接关掉。我已经将它逐出我的各种设备。这并不是一件很突然的事情,只是我忍了很久了,近一年前室友向我推荐 Telegram 之后,经过这么长时间的使用,我终于能够在 QQ 动态上宣告离开 QQ。

我忍耐的原因:

  • 对于客户端:

    • 我发现它做了很多恼人的事情,比如丧心病狂的系统广告,小手机一个屏幕几条消息里面几乎全部都是官方的广告消息。
    • 消息延迟,响应速度奇慢。
    • 每次升级都是一次斗智斗勇。
  • 对于 web 端:

    • 极度不方便,吃消息。离开 Windows 之后,用了 webQQ 有不短的一段时间,之后用 Pidgin + lwqq 将就了一段时间(同样是基于 webQQ),它的功能不是简单”阉割“两个字能够说清楚的。严重的消息丢失,我发个消息出去都不知道别人收到没有,也不知道人家给我发的消息是不是显示出来了,而且与客户端无法完全同步消息,导致无法知道我到底丢了多少消息,而且还因此造成过与人的误会。
    • 传说中的其接班人 Smart QQ,这东西自从出来这几年来说一直都是个残缺品,更像是什么人随便乱写的一个 DEMO 程序,使用它的感受是战略级的自虐。
  • 对于自己:我渐渐意识到我用 QQ 仅仅是为了通信而已,因为它就是一个通信工具,让我在电脑上面,接通互联网的时候能够和朋友打个招呼,为什么我会追求一些莫名其妙的东西,什么点亮图标之类云云。

我所做的”反抗“:

  • 对于客户端:转向使用 TM,随着版本推移 TM 长期不更新,又转向了国际版 QQ,一个本土软件把我逼到专门用它的国际版也是一番神奇的体验,同时可笑的是竟然在国际版上面有简体中文支持。在进入 Linux 之后使用虚拟机用过一段时间。

  • 对于 web 端:尝试反馈过一下小问题,没有人回应,弃。

  • 对于自己:寻找新的通讯工具。

最后顺理成章地,我转投了其他的通讯工具。

这是一个很曲折的过程,我用了一个通讯工具 => 我用它因为能截图 => 我不用它因为它不干活而且烦透了。当然,如果它如果现在干活我也不会选择它了。它让我迷失了自己最初的目的,或许我当初并没有意识到这个问题,我的目的仅仅是想要在电脑上不在身边的朋友打一声招呼,并不是什么点亮图标之类的什么鬼,我被它发展出越来越多跟本职不相关的东西迷惑了,丧失了最初的方向,就像丧尸一样没有目的地死命使用它,经历了丧尸的阶段之后我终于取回了神智,我想要的只是通讯而已;至于我反对自己在 QQ 空间写日志,也是因为如此,它对于书写东西来说并不方便,难以编辑,而且难以管理,这压根儿就不是用来写东西的地方嘛,所以我撤了,现在专心用 Markdown 写东西。现在QQ空间上的各种文本框已经根本不能正常键入信息了,以至于只能依靠 CP (Copy,Paste)大法来发动态,大概是他们忙着开发新的广告技术都懒得管对现代浏览器的兼容性了?

经历了这样一番弯路之后,我对迷惑我的目的东西更加警惕,并且极度厌恶。这个心理其实在很久之前就已经有了,还在各种下载站下载软件的时候,快速寻找到真实的下载链接的这个行为就是其体现。只是举出来的这个例子带给我的迷惑更大,我用了更长的时间来找到我想要的目的,因此印象也更加深刻。先前看了《乒乓》这部动画,我觉得它所传达的意思就很像我的这段经历:在最开始,我只是想要打乒乓球而已,只是因为快乐,直到陷入竞争,了解到天赋的差距,不知不觉忘记了最初的目的,渐渐走上了弯路,甚至放弃了乒乓,但是却一直找不到适合自己的东西,直到最后才想起自己最开始打球的原因,感慨万分之时,更加全心全意的投入进去。

再看计算机的世界,我所厌恶的各种软件,也正是符合了这个迷惑人的特点。它们可能在最开始是好好干活的,专注的,可是到了一定程度之后就开始发展一些奇怪的东西,最后变得乱七八糟。搜狗一个提示“搜狗输入法提示您:SD 卡用太久,清一清垃圾文件吧”,然后搜狗手机助手瞬间送上,抱怨手残之际进行卸载,“请让我留下来”、“打赏反馈下”,它就是要阻拦我,卸载程序跑完了,啊嘞,怎么整个安装目录看不出少了啥东西呢,卸载程序也不干活儿了,只好手动卸载。360 也是,一个好好的安全主导的软件不知道什么时候往系统维护上面插了一脚,但是我没觉得它在这两个方面上做的多好了,我只记得我 VB 辛苦编译出来的程序总是立刻被删除,要么就是木马,要么就是恶意程序,这判断力也是不敢恭维,这好像你带了个保镖回去,他说你全家都是坏人然后把你家人全都统统处理了,兴冲冲告诉你我帮你解决掉多少个坏人。隔壁的刚刚起步的 IObit Secruity 360 都能好好的干着活,还没见他能把我人畜无害学习过程中写出的小程序给二话不说毙掉,更别说什么 COMODO, AVG 等专门搞这些的程序了;你说 360 能给电脑加速?醒醒,电脑归根结底是机器,你要么折寿打激素(超频)要么买个新机器,否则你的电脑该多快还是多快,这一切只是它带来的迷惑罢了,如果真的想要电脑“加速”,看看当前进程列表你就知道该怎么做了,找个真心做系统维护的软件吧。这种迷惑还能上升到更加丧心病狂的高度,比如先前天猫的 ×3 事件什么的。

我感谢这些让我厌恶的东西,他们提醒了我时刻不要迷失,大到一个项目,小到一个函数,在开始的时候目的就只有那么一个,剩下的事情就是全力让它完美地实现就好了,这个过程如此艰难以至于根本没有精力去增添更多的无用目的,除非我作恶,想要迷惑别人,但这比起原来的目的来说实在是太无聊了。

桌面操作系统

在 Arch Linux + KDE 下生活了近两年,虽然不能说达到有深度的 Linux 用户的境界(写个 bash 的判断语句都还得查查手册),但是也受到了很大的影响。关于操作系统论战已久,我不会大喊 Arch Linux 是世界上最好的操作系统。我只是遇到了太多贴心的东西,让它逐渐成为了我的信仰——抱有的信心和信任所在。

更新/软件管理

无论是软件更新还是系统更新,在 Windows 下面都是一件极度痛苦的事情,单独的软件更新要手动下载安装包,然后手动重新安装一次,而且安装程序还有可能有各种迷惑性选项乃至破坏性的行为,以及安装目录的选择(我已经很久没有思考过这个问题了),而系统更新,有的推崇直接关掉吧,用第三方工具完成,也有坚持系统自己的更新功能的,每次更新之后关机开机都会耗费超过平时十倍乃至几十倍的时间,在没电的时候和情况紧急的时候,开机看到长时间的 Windows 正在配置... 又不敢做任何举动的心情真的是让人着急的不行。Arch Linux 这边,更新永远只需要一句 pacman -Syu 了事,不管是所谓的系统更新还是软件更新,所有软件都自动为你下载,为你安装,根本不需要操心安装目录这种傻到家的问题,如果遇到急事,随时都能 ^C 停下这个过程,下次执行更新的时候接着干活,开机关机也不会有什么特别的变化,一如既往地让人没时间冲好一碗麦片。

应用程序

还在用 Windows 的时候我渐渐感到对桌面的不满,为什么会有这么多图标,还有人把它当垃圾桶,让原来壁纸失去光彩,还给人了无限手残的可能。尝试了 ObjectDock,开始菜单, winkey + R。最后到了 KDE 遇到了 krunner ,让我终于能够尽情欣赏壁纸的同时超快地启动我想要使用的程序。

窗口管理器,在 Windows 的时候,我曾经感叹这个应用程序的半透明真是神来之笔,那个程序的置顶功能真是方便,要是 xxx 也能这样就方便多了。到了 KWin ,我可以尽情让合适的程序半透明、置顶/底、全屏、无边框等等,甚至还能给窗口制定规则来限制他们的表现。全局快捷键、虚拟桌面、键盘布局调整等等,这些原本想都不敢想的东西,现在已然是我的好伙伴,这在 Windows 几乎是不可能的事情。

太多了……再写就变软文了,反正我就是喜欢它,就算你说我装逼我就是喜欢它,你来装个看看呀,来说说什么地方装了?

生活

  • 拒绝冗余的形式。
  • 有想要做的事情就做,避免陷入迷惑。
  • 提升自己的某种能力,在那个能力下获得的相应的自由。
  • 真的有错误就修正,这没有什么打脸不打脸的概念。
  • ...一万字

暂时也就想到这些了,大概就行了吧(。・_・。)?

默默滚去预习(ง •̀_•́)ง

| Posted by frantic1048

解决 rhc 无法创建连接

最近 rhc 忽然连接不上了,提示这样的错误:

A secure connection could not be established to the server (SSL_connect returned=1 errno=0 state=SSLv3 read server hello A: sslv3 alert handshake failure).
You may disable secure connections to your server with the -k (or --insecure) option
'https://openshift.redhat.com/broker/rest/api'.

翻到 Redhat 上一个文章搞定了,是因为最近的 SSLv3 漏洞的原因禁用了 SSLv3,换一个非 SSLv3 的连接协议就好啦~

打开 ~/.openshift/express.conf ,在里面添加以下行即可,我这里是已经有这行只是加了注释,我将其修改成了下面的内容。

ssl_version=tlsv1

再次运行 rhc, 连接成功╮( ̄▽ ̄)╭

| Posted by frantic1048

在校园网内获取外网链接状态

由于校园网实在太神奇,在你没有登录的时候访问外网服务器也会返回 200, 然后送你一个跳转到登录页面地址的页面。
为了获取外网链接状态,干脆直接尝试获取一个来自外网的小 js 库(当然如果自己在外网有空间,随便丢一个 js 上去就可以实现)来检查是否联网。如果成功加载了 js 库的话,那在 window 下面肯定就能找到那个 js 库,以此来检查是否连网。

对于浏览器会主动缓存之前请求过的 js 库的问题,用 ? + 参数让浏览器以为是不一样的文件,每次都会真正地去请求文件。下面这个实现用的是连续三个 performance.now(),这样重复几率就小的可怜了。

关于外网库的选择,这个栗子用的是 upaiyun 上面的库,当然其他地方的也可以。

function detectOnlineStatus() {
  var magi = document.createElement('script');
  magi.setAttribute('type', 'application/javascript');
  magi.setAttribute('src','http://cdnjscn.b0.upaiyun.com/libs/hogan.js/3.0.0/hogan.min.js'+'?'+performance.now()+performance.now()+performance.now());
  window.document.body.appendChild(magi);
  var checker = setInterval(function () {
    if ((!!window.Hogan) { clearInterval(checker);window.dispachEvent(new Event("oya-online")); }
    }, 100);
  setTimeout(function () {
    clearInterval(checker);
    magi.remove();
    window.Hogan = false;
  } ,3000);  //3s to determine network status

}
| Posted by frantic1048

图片转HTML(支持动画)

也许是受到很久以前看到的这玩意儿的原因:The Shapes of CSS

现在开脑洞写了个自动转换,顺便支持了动画……嗯,纯 CSS (:з」∠)

主要步骤就是用 Python 读图片,然后把像素全转写成 CSS 的 box-shadow ,最后构建一个完整的 HTML 文件输出。

然后用浏览器打开生成的 HTML 文件,就直接看到图片了,如果输入是一个文件夹的话,就以文件夹里面的图片为帧生成一个带动画的 HTML。

之后再更新就丢这儿了: img2html

#!/usr/bin/env python3

# -*- coding: utf-8 -*-


## @package img2html

#  Usage        : img2html.py file1|dir1 [file2|dir2 ...]

#  Description  : generate html uses box-shadow to show picture

#                 or a html to show your image sequence in a folder as css animation

#  Dependencies : Python Image Library, Python 3

#  Note         : Take care of the Super-High-Energy output ( >﹏<。)

#  Date         : 2014-12-19

#  Author       : frantic1048



import sys
import os
from PIL import Image
from string import Template

class UnknownColorMode(Exception): pass

## @var tHTML template for constructing entire html document

tHTML = Template('''
<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>~ ${name} ~</title>
</head>
<body>
  <style type="text/css">${css}</style>
  <div id="image_kun"></div>
</body>
</html>''')

## @var tCSSStatic template for constructing static image's css code

tCSSStatic = Template('''
@charset "utf-8";
body{
  display:flex;
  justify-content:center;
  align-items:center;
}
#image_kun{
  height: ${height}px;
  width: ${width}px;
  position:relative;
}
#image_kun::after{
  position:absolute;
  height:1px;
  width:1px;
  background:${firstPixel};
  margin:0;
  padding:0;
  content:"\\200B";/*ZWS*/
  box-shadow:
  ${boxshadow};
}
''')

## @var tCSSAnimation template for constructing image sequence's css animation code

tCSSAnimation = Template('''
@charset "utf-8";
body{
  display:flex;
  justify-content:center;
  align-items:center;
}
#image_kun{
  height: ${height}px;
  width: ${width}px;
  position:relative;
}
#image_kun::after{
  position:absolute;
  height:1px;
  width:1px;
  background:transparent;
  margin:0;
  padding:0;
  content:"\\200B";/*ZWS*/
  animation:ayaya ${animationLength} step-end infinite alternate;
}
${animationKeyFrames}
  ''')

## @var tCSSKeyframes template entire CSS keyframes rule

tCSSKeyframes = Template('@keyframes ayaya {${keyframes}}')

## @var tCSSKeyframe template for a single CSS keyframe

tCSSKeyframe = Template('${percentage}% {${keyframeRule}}\n')

## @var tCSSKeyframeRule template for a single CSS keyframe inner rule

tCSSKeyframeRule = Template('background:${firstPixel};box-shadow:${boxshadow};')

## ensure no trailiing slash in directory name

def toRegularDirName(dirName):
    if (os.path.split(dirName)[-1] == ''):
      return os.path.split(dirName)[0]
    else:
      return dirName

## write str to a file,named as <exportFileName>.html

def toFile (str,exportFileName):
  with open (exportFileName,'w') as html:
    html.write(str)

## construct HEX Color value for a pixel

#  @param pixel a RGB mode pixel object to be converted

#  @return CSS hex format color value

def toHexColor (pixel):
  return '#{0:02x}{1:02x}{2:02x}'.format(*pixel[:])

## construct RGBA Color value for a pixel

#  @param pixel a RGBA mode pixle object to be comverted

#  @return CSS rgba format color value

def toRGBAColor (pixel):
  return 'rgba({0},{1},{2},{3})'.format(*pixel[:])

def toCSSColor (pixel, mode):
  if (mode == 'RGB'):
    return toHexColor(pixel)
  elif (mode == 'RGBA'):
    return toRGBAColor(pixel)
  else:
    raise UnknownColorMode

## construct single box-shadow param

#  @param color valid CSS color

def toBoxShadowParam (x, y, color):
  return format('%spx %spx 0 %s'%(x, y, color))

## process single image file to html

#  @param fileName input file's name

#  @param export output callback(doc, exportFileName):

#    doc : generated html string

#    exportFileName : output filename

def mipaStatic(fileName,export=''):
  with Image.open(fileName) as im:
    ## what called magic

    boxshadow = ''

    ## file name as sysname

    exportFileName = fileName+'.html'
    title = os.path.split(fileName)[-1]

    ## image size

    width, height = im.size[0], im.size[1]

    #ensure RGB(A) mode

    if (im.mode != 'RGBA' or im.mode != 'RGB'):
      im.convert('RGB')

    firstPixel = toCSSColor(im.getpixel((0,0)), im.mode)
    for y in range(0, height):
      for x in range(0, width):
        color = toCSSColor(im.getpixel((x, y)), im.mode)
        #link magic

        boxshadow += toBoxShadowParam(x, y, color)

        #add a spliter if not the end

        if (not (y == height-1 and x == width-1)):
          #keep a '\n' for text editor ˊ_>ˋ

          boxshadow += ',' + '\n'

    doc = tHTML.substitute(name = title, css = tCSSStatic.substitute(width = width, height = height, boxshadow = boxshadow, firstPixel=firstPixel))
    if (export==''):
      print(doc)
    else:
      export(doc, exportFileName)


## process a image folder

#  files in folder will processed to an animated html

#  process order is filename asend

#  @param dirName input file's name

#  @param export output callback, call with generated html as a string argument

def mipaAnimation(dirName,export=''):
  dirName = toRegularDirName(dirName)
  title = os.path.basename(dirName)
  exportFileName = title + '.html'

  files = os.listdir(dirName)
  files.sort()

  FPS = 24
  mode = ''
  width, height = 0, 0
  frameCount = 0
  keyframeRules = []
  keyframe = ''

  for f in files:
    try:
      with Image.open(os.path.join(dirName, f)) as im:

        if (export!=''):print('processing file --> ' + f)

        frameCount+=1

        #ensure RGB(A) mode

        if (im.mode != 'RGBA' or im.mode != 'RGB'):
          im.convert('RGB');

        #collect animation info

        if (width == 0) : width, height = im.size[0], im.size[1]
        if (mode == '') : mode = im.mode

        firstPixel = toCSSColor(im.getpixel((0,0)), mode)
        boxshadow = ''
        for y in range(0, height):
          for x in range(0, width):
            color = toCSSColor(im.getpixel((x, y)), mode)
            #link magic

            boxshadow += toBoxShadowParam(x, y, color)

            #add a spliter if not the end

            if (not (y == height-1 and x == width-1)):
              #keep a '\n' for text editor ˊ_>ˋ

              boxshadow += ',' + '\n'
        keyframeRules.append(tCSSKeyframeRule.substitute(firstPixel=firstPixel,boxshadow=boxshadow))
    except:
      pass

  percentUnit= 100/frameCount
  for i in range(0,frameCount):
    if (i == frameCount - 1):
      pc = '100'
    elif (i == 0):
      pc = '0'
    else:
      pc = str(percentUnit * i)
    keyframe += tCSSKeyframe.substitute(percentage = pc, keyframeRule = keyframeRules[i])

  if (export!=''):print('generating document...')
  doc = tHTML.substitute(name = title, css = tCSSAnimation.substitute(animationLength = str((1000 / FPS) * frameCount) + 'ms',
                                                                          animationKeyFrames = tCSSKeyframes.substitute(keyframes = keyframe),
                                                                          height = height,
                                                                          width = width))
  #output

  if (export==''):
    print(doc)
  else:
    print('Start exporting...')
    export(doc, exportFileName)
    print('Finished exporting !\nenjoy with your magical ' + exportFileName + ' _(:з」∠)_')


for path in sys.argv[1:]:
  if os.path.isfile(path):
    ##export to stdout

    #mipaStatic(path)


    ##export to autonamed file

    mipaStatic(path,toFile)
  elif os.path.isdir(path):
    #mipaAnimation(path)

    mipaAnimation(path,toFile)