<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>mvj3</title>
    <link>https://ruby-china.org/mvj3</link>
    <description>逻辑是用来事后证明直觉的。</description>
    <language>en-us</language>
    <item>
      <title>《使用 Luiti 来构建数据仓库》系列文章－ 使用 DAG 来解耦 数据处理中的复杂逻辑</title>
      <description>&lt;p&gt;前言 - 《使用 Luiti 来构建数据仓库》是关于大数据处理的实战经验总结的系列文章，面向的读者范围是对数据处理有一年以上经验的人。众所周知，Hadoop 和 新兴的 Spark 是当前最流行的分布式计算和存储平台，但是均和保守死板的 Java 编程语言所绑定。R 和 SQL 因为专业领域和表达能力的有限性而导致始终不能一统江湖。而 Python 作为一个通用的脚本语言也拥有一个完全可以与 Java 匹敌的生态环境，在 Web 开发，机器学习，文本挖掘，爬虫等方面均有众多优秀的框架和类库。并且 Python 可以作为工业胶水把前述几个技术方案融合成一个相互补充的解决方案。本系列文章的侧重点在于从 Python 的函数式特征出发，来逐步讲解一个有约定而不失灵活性的离线数据仓库处理框架是怎么来的，和可以做什么。欢迎关注 &lt;a href="http://luiti.github.io" rel="nofollow" target="_blank"&gt;http://luiti.github.io&lt;/a&gt; 。 &lt;/p&gt;
&lt;h2 id="谁在遭遇大数据？"&gt;谁在遭遇大数据？&lt;/h2&gt;
&lt;p&gt;在一般互联网公司中，负责数据分析或 BI 报表等职责的人里最多的是 数据分析师。TA 们擅长的专业技能是用 SQL 去做各种复杂的数据统计分析，并会稍微掌握 一门脚本语言 (通常是 Python ) 来做些 ETL 和 SQL 整合的工作。TA 们的劣势在于没有较强的软件工程背景，加上工作内容很大一部分都是一次性的，会导致 TA 们很少去注重代码的 通用性 和 可维护性。于是便越来越停留 在各种重复性工作上，生产数据的效率跟不上公司业务的快速发展。 &lt;/p&gt;

&lt;p&gt;另外还有一类人是没太多工作经验的数据仓库工程师，TA 们需要一套三两天就可以上手 的软件框架，来快速和稳定地生产数据，以提供报表数据给公司里的其他后端技术部门来使用。 &lt;/p&gt;

&lt;p&gt;更多请访问 &lt;a href="http://luiti.github.io/chinese/Processing-data-in-a-DAG-way.html" rel="nofollow" target="_blank"&gt;http://luiti.github.io/chinese/Processing-data-in-a-DAG-way.html&lt;/a&gt;&lt;/p&gt;</description>
      <author>mvj3</author>
      <pubDate>Thu, 27 Aug 2015 19:28:13 +0800</pubDate>
      <link>https://ruby-china.org/topics/27101</link>
      <guid>https://ruby-china.org/topics/27101</guid>
    </item>
    <item>
      <title># 抵制浪费时间的编码面试 # 用一个开源的方式来说明</title>
      <description>&lt;p&gt;项目地址：&lt;a href="https://github.com/mvj3/oracle_interview_calculation" rel="nofollow" target="_blank"&gt;https://github.com/mvj3/oracle_interview_calculation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;简单来说，我想通过这个作品来向社区呼吁，雇主应该少让弱势应聘者浪费时间去做这些无聊的面试题，因为每个人的时间都很宝贵。&lt;/p&gt;
&lt;h2 id="问"&gt;问&lt;/h2&gt;
&lt;p&gt;为什么我要无偿做 Oracle 的这个编码面试？&lt;/p&gt;
&lt;h2 id="答"&gt;答&lt;/h2&gt;
&lt;p&gt;首先感谢 Oracle 给正在找工作的 Ruby 程序员提供了机会，但是我看到了我认为的不尊重应聘者的一条招聘说明 --- 做一个编码测试。以下是我对这一做法的反对声明：&lt;/p&gt;

&lt;p&gt;从这个招聘描述 (见下方我从招聘贴里拷贝过来的，我去掉了邮箱地址) 的薪资待遇中一条"高于行业的薪资水平，15-25K"说明看来，TA 们要招的应该是一个中高级的 Ruby 工程师。&lt;/p&gt;

&lt;p&gt;我相信，对于一个中高级的 Ruby 工程师来说，应该有一个善于活用开源软件库的能力，所以怎么说至少得有个 Github 账户等一些可以显露技术能力的互联网上的公开证明吧，
如果对方已经有一些开源作品 (当然没开源的也可以了)，做这个"投递简历前请确保你能给出如下问题的一个优雅的解决方案"恰恰是对应聘者的一个 &lt;strong&gt;不尊重&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;我建议是可以让应聘者发一个 TA 得意的编码作品，从这个作品里，应聘者应该可以确保雇主得到如下信息：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;作品是应聘者主导参与的，这个是人品问题。&lt;/li&gt;
&lt;li&gt;作品应该可以让雇主基本判断出综合技能是符合职位要求的。&lt;/li&gt;
&lt;li&gt;代码文档解释性&lt;/li&gt;
&lt;li&gt;代码结构设计&lt;/li&gt;
&lt;li&gt;代码迭代 (重构) 的能力&lt;/li&gt;
&lt;li&gt;编程基本素质，包括但不限于 命名，测试，等。&lt;/li&gt;
&lt;li&gt;其他我上面没提到的&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;如果非要应聘者做编码面试的话，那么请考虑这个编码是对应聘者是有损失的，TA 不需要靠这个测试来证明或提升自己 (真正优秀的工程师都会善于在日常工作中发现和解决问题，TA 会发现自己在哪些方面应该去提高)，所以建议付给用心完成任务的工程师 TA 当前待遇标准下的时薪。&lt;/p&gt;

&lt;p&gt;请尊重相对弱势的应聘者，因为每个人的时间都很宝贵。&lt;/p&gt;
&lt;h2 id="[北京] 甲骨文社交云平台团队招聘 Ruby 软件开发工程师"&gt;[北京] 甲骨文社交云平台团队招聘 Ruby 软件开发工程师&lt;/h2&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;问： 神马？？？我有没有看错？ Oracle也开始用Ruby了，那Java兄肿么办？
答： 是的！这世界变化快，哦也没有办法 :-1 谁让那些创业公司都用ruby呢？甲骨文云社交平台是通过收购美国本土成功的创业公司（如Vitrue, Involver, Collective Intellect, BlueKai）来组建的，所以抹油办法了，只好用Ruby喽！！（不过话说Ruby还挺好用的说。。。）

问： 甲骨文。。。大公司。。。很沉闷死板了喽？
答： 错！说实在话，俺们现在很纠结的啦，500强的名头，创业公司的文化（但不是加班文化哦）。俺们团队平均年龄相当低，俺30出头，已经是“老当益壮”， “老奸巨猾”，“发挥余热”了。。。。（另，由于团队太活跃，已然被其他组投诉好多次了。。。）

问： 产品干嘛的？
答： 官方的那些销售语言俺就不说了。简单来讲： Oracle的社交云平台（SRM，社交关系管理）目的要整合地球（注意，是地球）上主流的社交关系网络，来实现商业公司与消费者社交关系通道的统一配置与管理。Oracle社交关系管理（SRM）平台是业内第一个统一的集成平台，它为客户提供了从内容创建，协作化管理，消息响应到语义分析的整体解决方案。目前SRM已在全球和众多知名社交网站及应用展开战略合作，包括Facebook, Twitter, Google+, Instagram, Weibo等等，未来Oracle会继续加大对亚洲区市场的扩展和投入。此外，利用Oracle强大的背书，SRM正在和多个Oracle CRM系统开展对接，无疑SRM将成为众多企业参与下一代互联网竞争所必不可少的决定性工具。
产品官网看这里：http://www.oracle.com/cn/solutions/social/overview/index.html

问： 那你们的优势捏？
答： 俺们不逗比，不画饼。那些该有的（比如神马弹性工作制啊，优越办公环境啊，双休啊，无限量零食啊，聚餐啊）必须有！ 还有神马美女帅哥啊，那也不是事，关键是俺们的美女帅哥都是神马耶鲁啊，MIT啊，宾大啊，清华啊，北大的。。。还有还有，俺们有安全感，俺们不加班（真的不加那种）。。。

问： 你们会不会跟“啊倒闭”那家公司一样，搞几年中国team就over了呢？
答： 不好意思，俺们老大中国人。。。

好了，言归正传！

基本要求
1. 三年以上互联网应用开发经验，优秀毕业生亦可（但目前不接受实习）
2. 熟练掌握Ruby语言，熟悉Rails，有ROR项目开发经验
3. 熟悉基本的Linux命令，熟练操作Linux，有Linux下开发经验
4. 熟悉流行数据库（SQL Server/MySQL/Oracle）
5. 有一定算法基础，良好的面向对象思维
6. 优秀的学习能力，优秀的沟通能力，勇于承担责任，易于合作并帮助团队成功

加分项
1. 熟悉HTML/CSS或熟练掌握Javascript
2. 熟悉Shell脚本编写
3. 熟悉流行前端框架，如：Backbone, AngularJS
4. 熟悉TDD/BDD，熟悉RSpec，Jasmine等测试框架
5. 有数据库设计或优化经验
6. 熟悉社交网络集成开发
7. 良好的英语读写听说能力

薪资待遇
1. 高于行业的薪资水平，15-25K
2. 年终奖金
3. 弹性工作制
4. 优厚福利，如：公司级及团队TB活动，无限量供应的零食，TEDTalk分享会，加班餐，网费报销
5. 硅谷出差机会

工作地点
海淀区西二旗中关村软件园

我们的优势
1. 保持快速增长的崭新团队
2. 打造引领行业并帮助世界最顶尖公司走向成功的社交产品
3. 与世界领先的Rails技术团队零距离沟通
4. 轻松高效的团队氛围
5. 工作与生活的平衡

又有新的HC放出来，欢迎投递简历。
*******补充要求********
投递简历前请确保你能给出如下问题的一个优雅的解决方案：
http://www.codewars.com/kata/525f3eda17c7cd9f9e000b39
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# encoding: UTF-8&lt;/span&gt;

&lt;span class="c1"&gt;# Run tests&lt;/span&gt;
&lt;span class="c1"&gt;# ruby oracle_interview_calculation.rb&lt;/span&gt;

&lt;span class="no"&gt;REQUIREMENTS&lt;/span&gt;&lt;span class="o"&gt;=&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;REQUIREMENTS&lt;/span&gt;&lt;span class="sh"&gt;
References:
[1] https://ruby-china.org/topics/25179 [北京] 甲骨文社交云平台团队招聘 Ruby 软件开发工程师 － 继续招聘
[2] http://www.codewars.com/kata/calculating-with-functions/ruby

Description:

This time we want to write calculations using functions and get the results. Let's have a look at some examples:

seven(times(five())); // must return 35
four(plus(nine())); // must return 13
eight(minus(three())); // must return 5
six(dividedBy(two())); // must return 3
Requirements:

There must be a function for each number from 0 ("zero") to 9 ("nine")
There must be a function for each of the following mathematical operations: plus, minus, times, dividedBy (divided_by in Ruby)
Each calculation consist of exactly one operation and two numbers
The most outer function represents the left operand, the most inner function represents the right operand
&lt;/span&gt;&lt;span class="no"&gt;REQUIREMENTS&lt;/span&gt;



&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Calculation&lt;/span&gt;
    &lt;span class="c1"&gt;# We use `method_missing` and `define_method` to define number and operator methods lazily, and with cached.&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NumberValue&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="n"&gt;to_ary&lt;/span&gt;  &lt;span class="n"&gt;number&lt;/span&gt;
        &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="nb"&gt;inspect&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OperationValue&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:operation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="n"&gt;to_ary&lt;/span&gt;  &lt;span class="n"&gt;operation&lt;/span&gt;
        &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="nb"&gt;inspect&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MiddleRightExpression&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:operation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;


    &lt;span class="no"&gt;Numbers&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"zero one two three four five six seven eight nine"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:to_sym&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;NumMap&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_index&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_sym&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;NumberValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;

    &lt;span class="no"&gt;OperationsMap&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="ss"&gt;plus:        &lt;/span&gt;&lt;span class="no"&gt;OperationValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                      &lt;span class="ss"&gt;minus:       &lt;/span&gt;&lt;span class="no"&gt;OperationValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                      &lt;span class="ss"&gt;times:       &lt;/span&gt;&lt;span class="no"&gt;OperationValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                      &lt;span class="ss"&gt;divided_by:  &lt;/span&gt;&lt;span class="no"&gt;OperationValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:/&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                     &lt;span class="p"&gt;}&lt;/span&gt;


    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;method_missing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;#0. Check name is valid&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="no"&gt;NumMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="no"&gt;OperationsMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;"Can't find `&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;` method in current scope."&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;

        &lt;span class="c1"&gt;#1. Define a number method lazily&lt;/span&gt;
        &lt;span class="n"&gt;expression_num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;NumMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;expression_num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_a?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;NumberValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="no"&gt;Kernel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:define_method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_a?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MiddleRightExpression&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;expression_num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;__send__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="k"&gt;else&lt;/span&gt;
                        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;"`&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;` should be a MiddleRightExpression"&lt;/span&gt;
                    &lt;span class="k"&gt;end&lt;/span&gt;
                &lt;span class="k"&gt;else&lt;/span&gt;
                  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;expression_num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;
                &lt;span class="k"&gt;end&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;

        &lt;span class="c1"&gt;#2. Define a operation method lazily&lt;/span&gt;
        &lt;span class="n"&gt;expression_opr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;OperationsMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;expression_opr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_a?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;OperationValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="no"&gt;Kernel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:define_method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
              &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;MiddleRightExpression&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression_opr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;__send__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"test/unit"&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestCalculation&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Test&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Unit&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TestCase&lt;/span&gt;
    &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Calculation&lt;/span&gt;

    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Welcome to do some calculations!"&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Avaiable numbers   are: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Calculation&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Avaiable operators are: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Calculation&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;OperationsMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Usage:"&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"    seven(times(five())) # =&amp;gt; 35"&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Note:"&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"This DSL is limited, can't support operator precedence, it's done by single nested parentheses."&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="no"&gt;REQUIREMENTS&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_simple&lt;/span&gt;
        &lt;span class="c1"&gt;#1. some test cases from requirement&lt;/span&gt;
        &lt;span class="n"&gt;assert_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;five&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="n"&gt;assert_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seven&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;five&lt;/span&gt;&lt;span class="p"&gt;())))&lt;/span&gt;
        &lt;span class="n"&gt;assert_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;four&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nine&lt;/span&gt;&lt;span class="p"&gt;())))&lt;/span&gt;
        &lt;span class="n"&gt;assert_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;eight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;three&lt;/span&gt;&lt;span class="p"&gt;())))&lt;/span&gt;
        &lt;span class="n"&gt;assert_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;six&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;divided_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;two&lt;/span&gt;&lt;span class="p"&gt;())))&lt;/span&gt;

        &lt;span class="c1"&gt;#2. more complex test cases&lt;/span&gt;
        &lt;span class="n"&gt;assert_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;two&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;three&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;
        &lt;span class="n"&gt;assert_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;two&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;three&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;
        &lt;span class="n"&gt;assert_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;two&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;three&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>mvj3</author>
      <pubDate>Sat, 18 Apr 2015 17:53:55 +0800</pubDate>
      <link>https://ruby-china.org/topics/25191</link>
      <guid>https://ruby-china.org/topics/25191</guid>
    </item>
    <item>
      <title>[分享] 在 JavaScript 里解析表单的多层嵌套参数</title>
      <description>&lt;p&gt;项目地址在 &lt;a href="https://github.com/mvj3/normalize_nested_params" rel="nofollow" target="_blank"&gt;https://github.com/mvj3/normalize_nested_params&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;最近在做一个复杂数据结构的内容管理系统，数据格式为多层嵌套。因为后端用的是 Python 的 Flask Web 框架，且在前端也需要进行数据操作，所以只好在前端去模拟 Rails 的 Rack 里支持嵌套参数解析的功能了。&lt;/p&gt;
&lt;h3 id="用例"&gt;用例&lt;/h3&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;normalize_nested_params&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contents[][style]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bold&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contents&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:[{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;style&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bold&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}]}&lt;/span&gt;
&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;normalize_nested_params&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contents[][style]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;         &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bold&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="相关引用"&gt;相关引用&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://codefol.io/posts/How-Does-Rack-Parse-Query-Params-With-parse-nested-query" rel="nofollow" target="_blank"&gt;http://codefol.io/posts/How-Does-Rack-Parse-Query-Params-With-parse-nested-query&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>mvj3</author>
      <pubDate>Sat, 22 Mar 2014 23:21:38 +0800</pubDate>
      <link>https://ruby-china.org/topics/18100</link>
      <guid>https://ruby-china.org/topics/18100</guid>
    </item>
    <item>
      <title>statlysis 统计分析引擎 线下培训策划，欢迎集思广益</title>
      <description>&lt;p&gt;自上周 &lt;a href="http://ruby-china.org/topics/16499" title=""&gt;基于 Mongoid/ActiveRecord 的 statlysis 统计分析引擎&lt;/a&gt; 在 Ruby China 正式发布以来，收到不少同学们的反馈，相关数据整理如下：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;帖子被浏览 500 多次，被 8 人喜欢。&lt;/li&gt;
&lt;li&gt;在 github 收到 18 个 Star 和 3 个 Fork，这个算是起点吧。&lt;/li&gt;
&lt;li&gt;向 Strikingly 的 CTO &lt;a href="/dfguo" class="user-mention" title="@dfguo"&gt;&lt;i&gt;@&lt;/i&gt;dfguo&lt;/a&gt; ，课程格子的 CEO &lt;a href="/tstyle11" class="user-mention" title="@tstyle11"&gt;&lt;i&gt;@&lt;/i&gt;tstyle11&lt;/a&gt; ，和去哪儿网的某招聘负责人 &lt;a href="/numberaugust" class="user-mention" title="@numberaugust"&gt;&lt;i&gt;@&lt;/i&gt;numberaugust&lt;/a&gt; 推荐了一下，均收到了表示要试用的意愿。&lt;/li&gt;
&lt;li&gt;和 Rabel 社区软件作者 &lt;a href="/daqing" class="user-mention" title="@daqing"&gt;&lt;i&gt;@&lt;/i&gt;daqing&lt;/a&gt; 在车库咖啡请教过推广方面事情，他对这类服务还是持保留意见。&lt;/li&gt;
&lt;/ol&gt;

&lt;hr&gt;

&lt;p&gt;个人觉得目前推广和使用还是不太给力，分析原因可能有，&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;受众采用的数据分析工具为两极分化严重的 SQL 和 Hadoop，分别对应一般的小公司和更专业的大公司，在习惯上没有做好接受的准备&lt;/li&gt;
&lt;li&gt;项目在文档支持上还不够完善&lt;/li&gt;
&lt;li&gt;目前没有 UI&lt;/li&gt;
&lt;li&gt;数据本身属于公司内部敏感信息&lt;/li&gt;
&lt;li&gt;再可能就是目前宣传还不够给力：）&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="线下培训"&gt;线下培训&lt;/h4&gt;
&lt;p&gt;因此我想在近段时间作一场 statlysis 的 &lt;strong&gt;线下培训&lt;/strong&gt; ，场地可以是贝塔咖啡，或者近期活动的 Beijing Rails Girl 举办点 ThoughtWorks。&lt;/p&gt;

&lt;p&gt;Beijing Ruby Saturday 主要组织者 &lt;a href="/sundevilyang" class="user-mention" title="@sundevilyang"&gt;&lt;i&gt;@&lt;/i&gt;sundevilyang&lt;/a&gt; 不知是否对此感兴趣，也可以作为 Ruby Saturday 的一部分。&lt;/p&gt;

&lt;p&gt;欢迎数据挖掘方面的专家 &lt;a href="/ouyang" class="user-mention" title="@ouyang"&gt;&lt;i&gt;@&lt;/i&gt;ouyang&lt;/a&gt; 阳志平老师提建议，statlysis 第一次介绍还是在他家客厅，那时 Beijing Ruby 正在商讨如何负责国外讲师的来国内的接机和导游等安排。&lt;/p&gt;

&lt;p&gt;也欢迎其他感兴趣的人来一起集思广益：）&lt;/p&gt;

&lt;p&gt;培训内容就是做出一个满足若干个统计分析需求的后台，类似用户注册量等。&lt;/p&gt;
&lt;h4 id="寻商业公司合作"&gt;寻商业公司合作&lt;/h4&gt;
&lt;p&gt;由于项目的特殊性，需要提供数据来做统计分析（否则就只能写爬虫或 ETL 其他数据了），这方面不知道有无商业公司愿意开放部分无隐私或机密性数据来作为培训 Demo 的数据来源。这也算是赞助吧，欢迎联系我：）&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;项目地址：&lt;a href="http://github.com/mvj3/statlysis" rel="nofollow" target="_blank"&gt;http://github.com/mvj3/statlysis&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="statlysis统计分析引擎支持的功能列表如下:"&gt;statlysis 统计分析引擎支持的功能列表如下：&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;支持 Mongoid 和 ActiveRecord 两种 ORM，其中 Mongoid 以 MapReduce 方式统计，ActiveRecord 基于纯 SQL 操作。&lt;/li&gt;
&lt;li&gt;对统计结果进行 SQL 索引，以支持高效访问。&lt;/li&gt;
&lt;li&gt;支持单行 DSL 配置，链式风格。&lt;/li&gt;
&lt;li&gt;支持跨表统计，需结构相同，表名按日期分割。&lt;/li&gt;
&lt;li&gt;依据统计需求自动配置统计结果的存储表，并支持条件查询，返回 ORM 统计表。&lt;/li&gt;
&lt;li&gt;支持任意维度统计，其中时间维度可选。&lt;/li&gt;
&lt;li&gt;单次统计里支持多个 GroupConcat 字段。&lt;/li&gt;
&lt;li&gt;支持最近统计的时间。&lt;/li&gt;
&lt;li&gt;支持以整数类型存储的时间字段，以兼容 PHP 社区的特别约定。&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="Demo和成功案例"&gt;Demo 和成功案例&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://mvj3.github.io/statlysis/showterm.html" rel="nofollow" target="_blank" title=""&gt;手把手操作示例&lt;/a&gt; ，是用很酷的模拟终端的 showterm 工具录制的。&lt;/li&gt;
&lt;li&gt;eoe.cn 各子网站的页面访问统计，和包含多个条件的数据库表每日数据统计，详情见 &lt;a href="https://github.com/mvj3/statlysis/blob/master/examples/eoecn.rb" rel="nofollow" target="_blank" title=""&gt;示例配置文件&lt;/a&gt; ，按日期维度分。&lt;/li&gt;
&lt;li&gt;阳光书屋的学习提高班的关于做题情况的统计分析，详情见 &lt;a href="https://github.com/mvj3/statlysis/blob/master/examples/sunshinelibrary.rb" rel="nofollow" target="_blank" title=""&gt;示例配置文件&lt;/a&gt; ，按班级维度分。&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;
&lt;h4 id="将来要做的事"&gt;将来要做的事&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;UI 模块。这个感谢 &lt;a href="/blackanger" class="user-mention" title="@blackanger"&gt;&lt;i&gt;@&lt;/i&gt;blackanger&lt;/a&gt; 推荐了简单精美的 &lt;a href="https://github.com/nnnick/Chart.js" rel="nofollow" target="_blank" title=""&gt;Chart.js&lt;/a&gt; ，未来想把它作成类似 &lt;a href="https://github.com/sferik/rails_admin" rel="nofollow" target="_blank" title=""&gt;RailsAdmin&lt;/a&gt; 或 &lt;a href="http://www.activeadmin.info" rel="nofollow" target="_blank" title=""&gt;ActiveAdmin&lt;/a&gt; 的后台系统，因为统计出来的数据也是通过 ORM 访问的。&lt;/li&gt;
&lt;li&gt;功能加强。比如对 ActiveRecord 的分表支持还不是很完善等。&lt;/li&gt;
&lt;li&gt;等你来提 Issue 或直接 Fork 吧！&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;P.S: 我会在 ThoughtWorks 2014.01.11（也就是下周六）举办的 &lt;a href="http://railsgirls.com/beijing" rel="nofollow" target="_blank" title=""&gt;Rails Girls Beijing&lt;/a&gt; 活动上当教练，欢迎一起讨论：）&lt;/p&gt;

&lt;p&gt;本人联系方式 &lt;a href="https://github.com/mvj3" rel="nofollow" target="_blank"&gt;https://github.com/mvj3&lt;/a&gt; ，微博 &lt;a href="/mvj3" class="user-mention" title="@mvj3"&gt;&lt;i&gt;@&lt;/i&gt;mvj3&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="最后做一个求职广告"&gt;最后做一个求职广告&lt;/h4&gt;
&lt;p&gt;本人目前待业，欲寻优秀团队来一起工作，期待一半人是 Geek，另一半人是其他角色，其中一半人的综合水平在我之上，团队之间沟通信息公开，尊重专业人士建议，最后产品靠谱是硬需求。&lt;/p&gt;</description>
      <author>mvj3</author>
      <pubDate>Sun, 05 Jan 2014 20:35:57 +0800</pubDate>
      <link>https://ruby-china.org/topics/16643</link>
      <guid>https://ruby-china.org/topics/16643</guid>
    </item>
    <item>
      <title>同时打开多个页面后，新提示在没有作刷新动作的页面还是存在？</title>
      <description>&lt;p&gt;如题，个人有点洁癖，有个数字在就忍不住要去刷新，或者关掉。&lt;/p&gt;</description>
      <author>mvj3</author>
      <pubDate>Sun, 05 Jan 2014 17:52:39 +0800</pubDate>
      <link>https://ruby-china.org/topics/16639</link>
      <guid>https://ruby-china.org/topics/16639</guid>
    </item>
    <item>
      <title>面试时候如何用 Ruby 写一个最短二分查找代码</title>
      <description>&lt;p&gt;声明：以下描述并非抱怨，而只是针对面试中的算法题，希望给别人提供点借鉴，更多地清醒头脑，理清思路，跳出当时的思维局限，和面试官互动解决掉面试题。&lt;/p&gt;

&lt;p&gt;本人技术背景：全栈式 Ruby on Rails 开发四年多，并在大数据分析方面有些经验，详见个人主页 &lt;a href="http://mvj3.github.io" rel="nofollow" target="_blank"&gt;http://mvj3.github.io&lt;/a&gt; 。&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;今天面试的时候被要求手写二分查找代码。&lt;/p&gt;

&lt;p&gt;这让我不由得想起几年前去 yottaa 面试要求手写二分查找代码时失败的窘迫来。于是我和面试官提了说，有人说过 &lt;a href="http://blog.csdn.net/v_july_v/article/details/7093204" rel="nofollow" target="_blank" title=""&gt;专业程序员里的 90% 都无法正确实现二分查找&lt;/a&gt; ，而且我之前用 &lt;a href="https://github.com/mvj3/logpos" rel="nofollow" target="_blank" title=""&gt;二分查找实现过日志二分查找&lt;/a&gt; ，大概原理就是不断依据范围进行折半查找。面试官还是要求现场写一个，于是我只好硬着头皮开始写了，不断回想和思考里面的边界和技巧，脑子里一团乱，在纸上写实在没感觉（因为要运行程序测试嘛，本人的大脑还不是 CPU。。。），就打开自己带的笔记本开始写了。&lt;/p&gt;

&lt;p&gt;测试代码是：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;binary_search&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;binary_search&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;binary_search&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;binary_search&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个没有疑问。然后先写了代码的轮廓，因为之前项目有好多模块都是通过递归实现的，就构造了一下 &lt;code&gt;binary_search array, value, from, to&lt;/code&gt; 这样的 API，最终代码是：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;binary_search&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt;

  &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="n"&gt;to&lt;/span&gt;   &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;
  &lt;span class="n"&gt;mid_idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;
  &lt;span class="n"&gt;mid_val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid_idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;mid_val&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mid_idx&lt;/span&gt;
  &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mid_val&lt;/span&gt;
    &lt;span class="n"&gt;binary_search&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mid_idx&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;binary_search&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mid_idx&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;测试通过。面试官反应用迭代方式实现，他说有性能问题。这里稍微和他有些讨论，迭代就迭代吧，我和他说那就用这第二种方式实现。&lt;/p&gt;

&lt;p&gt;这次写的时间比较久，估计在二三十分钟，遇到死循环的问题。途中和面试官抱怨了一句，他回说就是考边界。最终调试无果（当时我严重怀疑是边界出了问题，但是我想不起那个准确的解法），就说和面试官一起看看吧。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;binary_search&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
  &lt;span class="vi"&gt;@idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;

  &lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="vi"&gt;@from&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="vi"&gt;@to&lt;/span&gt;   &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="vi"&gt;@from..@to&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt;

    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"+ &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@from&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="vi"&gt;@to&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="vi"&gt;@idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="vi"&gt;@from&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="vi"&gt;@to&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"[&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@from&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@to&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;] &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@idx&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="c1"&gt;#binding.pry&lt;/span&gt;

    &lt;span class="n"&gt;mid_val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="vi"&gt;@idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;mid_val&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mid_val&lt;/span&gt;
      &lt;span class="vi"&gt;@from&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@idx.round&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[((&lt;/span&gt;&lt;span class="vi"&gt;@from&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="vi"&gt;@to&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="vi"&gt;@to&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@idx.round&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[((&lt;/span&gt;&lt;span class="vi"&gt;@from&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="vi"&gt;@to&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="vi"&gt;@idx&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;上面在跑前二个用例是准确的，但是第三个有点异常了，现在回来一看才发现是实例变量在方法多次调用后混淆的问题。而其中出现 round 和 ceil 之类方法的原因是他和我提到了之前远程面试时做的一个题目里我没有用 &lt;code&gt;String#chars&lt;/code&gt; 这样更 Ruby 的写法，而是用了 &lt;code&gt;str.split(//)&lt;/code&gt; ，所以我潜意识里可能顺着他的这个原则走了，当然这里的路走错了。&lt;/p&gt;

&lt;p&gt;下面的是我现在改好的：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;binary_search&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"查找数组 &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, 值 &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"DEBUG"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pred&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
  &lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt;

    &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;mid_val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"起始 &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, 终止 &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, 当前索引 &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"DEBUG"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;mid_val&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mid_val&lt;/span&gt;
      &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在和他讨论这个迭代的死循环代码时，他指明写的太冗余了，好的写法应该可以更短。这个就突然提示了我想起以前其实在 yottaa 面试结束后回家就调查了相关资料，然后写过 &lt;a href="https://gist.github.com/mvj3/843609" rel="nofollow" target="_blank" title=""&gt;这两个版本&lt;/a&gt; 的，里面还包括插入功能，更深的影响就是加入 eoe 后写了上面提到的 logpos 日志二分查找模块。&lt;/p&gt;

&lt;p&gt;然后我打开以前保存的代码，给他看，他反馈说还是可以更短。我说能不能找给我看。他说你回去可以自己找。&lt;/p&gt;

&lt;p&gt;现在回来搜了一个迭代版本的， &lt;a href="http://gistflow.com/posts/199-binary-search-with-ruby-and-tdd" rel="nofollow" target="_blank"&gt;http://gistflow.com/posts/199-binary-search-with-ruby-and-tdd&lt;/a&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;iterative_bindex&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lower&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;upper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;upper&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;lower&lt;/span&gt;
      &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upper&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;
        &lt;span class="n"&gt;lower&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
      &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;
        &lt;span class="n"&gt;upper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;按语义来说，包括关键字和方法， %W[class Array def iterative_bindex element lower = 0 upper = length - 1 while upper &amp;gt;= lower mid = () upper + lower / 2 if self[] mid &amp;lt; element lower = mid + 1 elsif self [] mid &amp;gt; element upper = mid - 1 else return mid end end return nil end end] ，为 55 个词。&lt;/p&gt;

&lt;p&gt;而我回来后实现的版本， %W[def binary_search array value from to idx = 0 array size pred nil loop do return nil if array [] from .. to blank?  idx = () from + to / 2 mid_val = array [] idx if value == mid_val break elsif value &amp;gt; mid_val from = idx + 1 else to = idx - 1 end end return idx end] 为 62 个词。&lt;/p&gt;

&lt;p&gt;我个人觉得两者无甚区别。不知道哪位大牛可以给出更短的 Ruby 版本，标准算 40 个词吧。&lt;/p&gt;

&lt;p&gt;最后面试官总结我应用或 Rails 方面的经验比较多，但是算法不太行，他准备和 CEO 再讨论看看。于是我咨询他公司技术部有哪些算法工作，他提了一个数据排重，然后我说如果准确度不太要求的话，可以用 bloomfilter 进行过滤。但是他坚持这一轮面试结束了，于是只能出门和他道别了。&lt;/p&gt;

&lt;p&gt;额，只能等后续再沟通了，总之有点冤。。。&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;本人之前写过 &lt;a href="http://mvj3.github.io/2013/01/27/interview-frontend-engineer-can-also-be-so-vivid/" rel="nofollow" target="_blank" title=""&gt;前端工程师的面试也可以如此生动&lt;/a&gt; ，过段时间也总结一篇如何面试 Ruby 工程师的文章吧。&lt;/p&gt;</description>
      <author>mvj3</author>
      <pubDate>Fri, 03 Jan 2014 18:12:09 +0800</pubDate>
      <link>https://ruby-china.org/topics/16601</link>
      <guid>https://ruby-china.org/topics/16601</guid>
    </item>
    <item>
      <title>基于 Mongoid/ActiveRecord 的 statlysis 统计分析引擎</title>
      <description>&lt;p&gt;对《statlysis 统计分析引擎 线下培训策划》感兴趣的 请移步 &lt;a href="http://ruby-china.org/topics/16643" rel="nofollow" target="_blank"&gt;http://ruby-china.org/topics/16643&lt;/a&gt;&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;项目地址在 &lt;a href="https://github.com/mvj3/statlysis" rel="nofollow" target="_blank"&gt;https://github.com/mvj3/statlysis&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;统计分析在线演示，拿 showterm 录制的， &lt;a href="http://mvj3.github.io/statlysis/showterm.html" rel="nofollow" target="_blank"&gt;http://mvj3.github.io/statlysis/showterm.html&lt;/a&gt;&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;两个已经部署在生产环境的使用案例：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;eoe.cn 各子网站的页面访问统计，和包含多个条件的数据库表每日数据统计，详情见 &lt;a href="https://github.com/mvj3/statlysis/blob/master/examples/eoecn.rb" rel="nofollow" target="_blank" title=""&gt;示例配置文件&lt;/a&gt; ，按日期维度分。&lt;/li&gt;
&lt;li&gt;阳光书屋的学习提高班的关于做题情况的统计分析，详情见 &lt;a href="https://github.com/mvj3/statlysis/blob/master/examples/sunshinelibrary.rb" rel="nofollow" target="_blank" title=""&gt;示例配置文件&lt;/a&gt; ，按班级维度分。&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>mvj3</author>
      <pubDate>Sun, 29 Dec 2013 22:54:27 +0800</pubDate>
      <link>https://ruby-china.org/topics/16499</link>
      <guid>https://ruby-china.org/topics/16499</guid>
    </item>
    <item>
      <title>《架构腐化之谜》随想</title>
      <description>&lt;p&gt;陈金洲 &lt;a href="/mechiland" class="user-mention" title="@mechiland"&gt;&lt;i&gt;@&lt;/i&gt;mechiland&lt;/a&gt; 很早写的一篇文章，参加过 RubyConf2012 可能都看过，地址在 &lt;a href="http://www.infoq.com/cn/articles/cjz-architecture-corruption" rel="nofollow" target="_blank"&gt;http://www.infoq.com/cn/articles/cjz-architecture-corruption&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;我觉得这是关于系统架构演化的很深刻的一篇总结分析文章，在经验上很足，对 Java 和 Ruby 社区很有启发意义。&lt;/p&gt;

&lt;p&gt;最初提到的 AOP 的概念让我重新去维基百科 &lt;a href="http://zh.wikipedia.org/wiki/%E9%9D%A2%E5%90%91%E4%BE%A7%E9%9D%A2%E7%9A%84%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1" title=""&gt;http://zh.wikipedia.org/wiki/面向侧面的程序设计&lt;/a&gt; 仔细看了一下，AOP 作用的范围其实是可以远超过"日志和权限"的，说白了就是业务之外的依赖技术（或者说实现业务的 DSL）才是难点，也是很多项目最终失败的原因。&lt;/p&gt;

&lt;p&gt;发现我之前写的《人类思维和软件工程学》 &lt;a href="http://mvj3.github.io/2013/12/15/human-mind-and-software-engineering/" rel="nofollow" target="_blank"&gt;http://mvj3.github.io/2013/12/15/human-mind-and-software-engineering/&lt;/a&gt; 里的提到的三间段已经被 这篇两年前的文章在形式上做了类似的说明了，看来后来者走的坑都是一样的。&lt;/p&gt;

&lt;p&gt;我把他对应的最终解决方案重新理解一下，"采用新技术"理解为"针对业务来说更精简的新技术", "重构到物理隔离的组件，将独立的模块放入独立的进程"理解为"开源和 Unix 管道工具化", "形成高度松散耦合的平台 + 应用"理解为"资源调用管理的操作系统式开发"。&lt;/p&gt;

&lt;p&gt;和"关于文档"提到的"想象一下现在的 Rails3/Spring 框架，他们往往有超过 20 个第三方依赖，我们却没有觉得理解困难，最重要的原因是依赖隔离之后，这些模块有了独立的文档可以学习。"一样，开源是把系统架构解耦和模块化的最好手段。&lt;/p&gt;</description>
      <author>mvj3</author>
      <pubDate>Sun, 29 Dec 2013 17:18:57 +0800</pubDate>
      <link>https://ruby-china.org/topics/16492</link>
      <guid>https://ruby-china.org/topics/16492</guid>
    </item>
    <item>
      <title>人类思维和软件工程学</title>
      <description>&lt;h3 id="原文地址在： http://mvj3.github.io/2013/12/15/human-mind-and-software-engineering/ ，并且排版效果更佳。"&gt;原文地址在： &lt;a href="http://mvj3.github.io/2013/12/15/human-mind-and-software-engineering/" rel="nofollow" target="_blank"&gt;http://mvj3.github.io/2013/12/15/human-mind-and-software-engineering/&lt;/a&gt; ，并且排版效果更佳。&lt;/h3&gt;&lt;h2 id="引言"&gt;引言&lt;/h2&gt;
&lt;p&gt;本文试图从直观的角度阐述如何做好常规的软件工程，保持良好的开发进度和可维护性，同时让项目经验对技术社区具有启发意义。Github 源代码托管和社交网站里的 JavaScript 和 Ruby 等开源代码繁多火爆的盛景无疑充分地说明了这一点。&lt;/p&gt;
&lt;h2 id="人类思维特点"&gt;人类思维特点&lt;/h2&gt;
&lt;p&gt;试着把十根左右的火柴散乱地倒在地上，你会发觉你无法一下子看清有多少根。请注意，这里是&lt;strong&gt;看清&lt;/strong&gt;，接着你可以在几秒之内慢慢地&lt;strong&gt;数清&lt;/strong&gt;有多少根火柴。&lt;/p&gt;

&lt;p&gt;这就是一般人类思维的极限和特点，人无法同时在脑子直观地在同一个层面掌握六七个以上不同事物。&lt;/p&gt;

&lt;p&gt;再换个例子就是手机号码比生日难记的多。手机号码首三位是给运营商用的，后面的 8 位被用于地区和用户编码了，对于人脑记忆而言毫无规则。而生日首先已经被人类经验分成了年份和月日这样两层，年份除去世纪就是一个两位数了，而月日是由大小不超过 12 的两个简单数字组成的。&lt;/p&gt;
&lt;h2 id="混沌时代"&gt;混沌时代&lt;/h2&gt;
&lt;p&gt;试想你现在要去写一个猜单词游戏客户端，目标是如何在有限步骤内猜中更多的单词。这个需求可不是你可以用一个 MVC 框架可以套用的，你得自己去组织代码。&lt;/p&gt;

&lt;p&gt;一开始你大概设计了基本的算法框架，先在一个文件里写着，不断的抽取方法，刚开始看着还不错。&lt;/p&gt;

&lt;p&gt;当代码越来越多失去控制的时候，你考虑是否可以把算法独立出去作为一个库存在了。这样你就有了主程序和算法库两个文件。&lt;/p&gt;

&lt;p&gt;接着你发现对方的服务器有时发生超时或内部错误，网络访问速度对于一次要执行几百次的程序也太慢，因此需要搭建本地的 Mock 服务器，这样你又多了 remote 和 local 两套实现机制，加上公用部分就是三个文件了。&lt;/p&gt;

&lt;p&gt;如果再算上 README 等文档，单词数据源文件，测试代码，你就会发现现在这差不多是一个成规模的项目了，它有十来个按目录分组的文件。&lt;/p&gt;

&lt;p&gt;以上的例子并非虚构，它实际来源于我参加 Strikingly 的限时两天远程面试编程项目 &lt;a href="https://github.com/mvj3/hangman/commits/master" rel="nofollow" target="_blank" title=""&gt;Hangman&lt;/a&gt; ，以上代码迭代重构过程完全可以从 commit 信息里得知。&lt;/p&gt;
&lt;h2 id="框架之初"&gt;框架之初&lt;/h2&gt;
&lt;p&gt;经历过 #混沌时代# 的我们，要去写一个涉及到数据库操作，业务逻辑，页面渲染，缓存管理，等等的复杂应用，如果没有一个像 Rails 这样便捷的 Web 框架，而自己一个一个去实现，那是一件多大工作量的事情。&lt;/p&gt;

&lt;p&gt;有了框架，一切都很美满，用 Rails 漂亮的 DSL 配置下代码就可以了。&lt;/p&gt;

&lt;p&gt;我相信没有哪个 Rails 用户不会为 RESTful 架构简洁的风格所体现出来的哲学所折服，GET, POST, PUT, DELETE 四种 HTTP 动词，index, new, create, show, edit, update, destroy 七种 Controller 方法，基本解决了大部分需求。别人来二次维护项目时也能很快地上手。&lt;/p&gt;
&lt;h2 id="框架之中"&gt;框架之中&lt;/h2&gt;
&lt;p&gt;然而实际的世界远远没有这么简单，Rails 框架并不能覆盖到你全部的业务。有些人可能看过一则传授怎样画马的短篇漫画，&lt;/p&gt;

&lt;p&gt;&lt;img src="http://mvj3.github.io/images/how_to_draw_a_horse.jpg" title="" alt="怎样画马"&gt;&lt;/p&gt;

&lt;p&gt;最后一步背后的工作恰恰是最关键的，和耗时最长的，也即是我们常说的 &lt;a href="https://duckduckgo.com/?q=%E4%B8%80%E4%B8%87%E5%B0%8F%E6%97%B6%E5%AE%9A%E5%BE%8B" rel="nofollow" target="_blank" title=""&gt;一万小时定律&lt;/a&gt; ，充分地强调了对技艺的理解力，经验，思考，和风格等。&lt;/p&gt;

&lt;p&gt;当然在开源如此繁华和被倡导的年代，你可以使用插件，比如 exception_notification 去管理你的程序异常。&lt;/p&gt;

&lt;p&gt;再有更大型的，比如 devise 用户认证，kaminari 分页，等等，它们在 Rails 的 MVC 三层都扎根了，甚至还包括了数据库和前端 javascript。&lt;/p&gt;
&lt;h2 id="框架之后"&gt;框架之后&lt;/h2&gt;
&lt;p&gt;慢慢地，有 Rails 开发经验的人，慢慢会发现总有一些不太适合放在 Rails MVC 三层里面的公共代码，于是一般都会把它们放到 config/initializers/或 lib/目录下。&lt;/p&gt;

&lt;p&gt;但是总有一些比较大的东西让你 Hold 不住，举个例子，一个 Model 的业务逻辑是从压缩包里导入多层次的内容，并且得处理格式不规范等各种异常，那样很快就让这个 Model 增加了两百多行，方法数量超过了二十个，即使放到单独的文件里也还嫌多。描述过程的方法和公用的方法混合在一起相互引用，变量共享，中间结果缓存，很快就变得难以维护和扩展。&lt;/p&gt;

&lt;p&gt;其实这个过程和 Ruby 社区的 HTTP 中间件处理库 Rack 做的事情在形式上有点类似，该库把 HTTP 请求的 Header 和 body 封装成 Rack 对象，然后被一个一个封装成模块的业务需求顺序地处理掉，过程类似于剥洋葱，最后把结果返回给客户端。&lt;/p&gt;

&lt;p&gt;所以我们可以把这塞在一个文件的方法重构为以下概念上独立的三个部分。&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;把解压缩和清理临时文件封装成一个 Model 插件。&lt;/li&gt;
&lt;li&gt;把多层次内容的处理过程放到一个类似 Rack 的类中多个实例中，任何异常由调用方捕获。&lt;/li&gt;
&lt;li&gt;处理过程中，数据格式验证可以直接代理到 Model.new(data).validated? 去。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这样就清晰多了，调试也很方便。另外你也可以把它独立出去作为一个模块去处理了，这样 model 就瘦了不少。&lt;/p&gt;
&lt;h2 id="框架之上，来一场范式转移"&gt;框架之上，来一场范式转移&lt;/h2&gt;
&lt;p&gt;让我们再引申一下，对比之前全都放在一个 Model 类里去操作的做法，新的其实是建立了自己的结构，也就是框架。&lt;/p&gt;

&lt;p&gt;这里面最重要的一点就是，一旦你写的代码和 Rails 本身的 MVC 框架无关时，代码组织超出了一定规模，而且它没有对应的开源库可以帮助，那么是有必要去专门为这个问题构造一个模块，框架，或者 DSL 了。&lt;/p&gt;

&lt;p&gt;著名科学哲学家 Thomas S. Kuhn 写过一本《科学革命的结构》，里面提出了"范式转移"这一概念。举个物理学的范式转移例子，关于物质运动的解释，已经历经了从亚里士多德时代的模糊度量，到牛顿定律的理想化计算，再到爱因斯坦相对论的更精细化表述，这样三种体系。精度的变化只是表象中的其中一个度量，最关键的是里面大部分概念已经发生了本质性的变化，或者说那些名字已经不是原来的所指。比如物体的质量在在牛顿力学里不可变的，而在爱因斯坦相对论里因为速度的改变，质量也会发生变化。&lt;/p&gt;

&lt;p&gt;同样，对于构建复杂应用的软件工程师来说，我们所使用的程序语言和软件框架就某个已启动项目来说一般很少发生变化，因为它们通常是业界认可和采用的模式和工具。编程过程中发生的各种技术问题，包括命名不清晰不一致，重复造轮子，破坏单一职责原则，Copy-Paste Style，意大利面条式代码，没有恰当的注释文档，等等，这里不一一列举，它们已经在 Martin Folwer 的著作《重构》一书中被详细论述。&lt;/p&gt;

&lt;p&gt;针对一般的网站开发，我以为 MVC 只相当于三段论这种原则性的方法论而已，而做好一个复杂系统的根本前提是在于你的计算机科学方面的系统知识，数年实际项目编程经验，以及风格化的思考（这通常就是一种品味）。当我们面对的项目越复杂时，不断精细化和抽象化的思考和重构应该贯穿在项目的各个生命周期。于是，Rails, Mongoid, Devise 等从中而出。&lt;/p&gt;
&lt;h2 id="《黑客与画家》"&gt;《黑客与画家》&lt;/h2&gt;
&lt;p&gt;很多人都赞同编程是一种创造性活动，再甚之是一种艺术，大可以和绘画等艺术形式媲美。&lt;/p&gt;

&lt;p&gt;我以为这是对的，很多人都认同旧项目一般都难以维护，特别是糟糕的代码。同样对于一幅画来说，如果乱糟糟一堆，色彩，元素关系，细节刻画都很差劲，稍微修修补补绝对没有画龙点睛的效果，这后来者真的还不如重画。写程序对比其他艺术形式的一个好处就是可以通过采用或抽取开源组件来获得更好的可维护性。&lt;/p&gt;

&lt;p&gt;Paul Graham 在《黑客与画家》一书中写到，"黑客与画家都是在试图创作出优秀的作品。他们本质上都不是在做研究，虽然在创作过程中，他们可能会发现一些新技术。"&lt;/p&gt;

&lt;p&gt;而实际上我以为就艺术这一层面上两者并没有多大关系，唯一的共同点就是都倾向于视觉审美。代码不能拿来听，也不能拿来思考（算法还可以稍微拿来思考一下，但其本质是数学），它只能被拿来看，拿来用计算机去运行，在各个模块或函数中之间调试（那算法来说，这里就包含了具体工程上的很多细节优化实现）。&lt;/p&gt;

&lt;p&gt;这里我想举一个有趣的例子，人们一般提起黑客，就想到那些用 Vim, Emacs 等纯文本界面编辑器的生活在黑底绿字终端下的大牛，IDE 太笨重，而且无助于他们对代码的编写，调试，和思考。我不想比较其中的优劣，或者谁更正统，我认为纯文本目录导航浏览更接近把代码在放在大脑里思考的视觉化模式。&lt;/p&gt;

&lt;p&gt;大家看看 Vim 的操作指南，它的使用模式里居然区分了浏览和编辑等模式，这对用惯了其他电脑程序的人而言无异于初次见到数学的等于符号和编程里的等于符号不等价一样让人惊异。在 Vim 里，我们用的更多的是浏览模式，编辑模式只有输入纯内容而已；而在浏览模式，你可以让光标在字与词，段落之间快速移动，可以把上下行对换，可以批量对齐，甚至可以拷贝某个长方形区块的文本。在此我想说的是，黑客和画家一样，思考的是元素与元素的关系，局部和整体的关系，从远观的良好命名的代码目录结构里可以看出项目架构（这个一般被 Rails 这种框架负责了），也可以从细观的在单个文件的某个类或者函数中把握其局部的独立性（这个就是代码良好的耦合性和单一职责原则）。&lt;/p&gt;

&lt;p&gt;而如果采用 IDE 编写，它会依据行业公认的软件工程经验去组织和自动化代码编写和管理，强壮的 Java 社区的整个工业体系无疑说明了这一点。但是它严重破坏了代码组织的直观，架构和编程完全可以分开，编程从业人员变成其中一颗螺丝钉，编程也失去了创造性的乐趣，导致很多人错误地变成了只会一种软件框架的和吃青春饭的"码农"，很多人觉得三十岁后必然得转向管理或业务。&lt;/p&gt;

&lt;p&gt;同是视觉性的绘画创作（我先声明我不会画画，所以言论可能有失偏颇），它不像诗歌，小说，音乐一样是生活在时间里的艺术，它力求的是直观，从全局和细部都可以欣赏，现代绘画有些已经抛弃细部了，它的画只能在一定距离外才能被有度量尺度限制的人眼看懂和欣赏它的美，比如印象派画家 莫奈的 &lt;img src="http://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/Claude_Monet%2C_Impression%2C_soleil_levant%2C_1872.jpg/780px-Claude_Monet%2C_Impression%2C_soleil_levant%2C_1872.jpg" title="" alt="《印象·日出》"&gt; 。&lt;/p&gt;

&lt;p&gt;拿编程和绘画打个比方就是，好的应用程序应该以 user story 为基本单位去勾勒程序架构，像一幅大型古典油画一样每个细部都可以拿出来欣赏把玩，而不是被扁平地代入一个一个现成的充满棱角的技术框架。其中具体的算法只是采用的材质不同，采用的开源库可能只是某个人物的帽子或者职业特征，技术架构体现了构图。真正优美的软件工程，应该让作为故事的皮肤和血肉恰到好处地覆盖骨架，使人一眼就能明白那是一个美人，而不是畸形得像是失败实验品的科学怪物。&lt;/p&gt;

&lt;p&gt;事实上任何高级的创作必然是纯手工的，或者手工在里面起了必不可少的作用，这个看看奢侈品或咨询行业就知道了。&lt;/p&gt;
&lt;h2 id="回归本质"&gt;回归本质&lt;/h2&gt;
&lt;p&gt;试想一下，规划或者维护项目的时候，一般相关负责人都会画出一个类似思维导图的项目架构图，这个被业界普遍认可和采用。但是有些没亲手架构并实现过大型复杂多系统的人很容易会拿业务架构去套技术架构，搞出一个又一个貌合神离的子系统，而实际做的时候，变成了一个个只能靠 HTTP 通讯的孤立系统，类似于日常见到靠 OAuth 相互认证的互不关联的多个互联网网站一样，当超出一个 MVC 框架可以 hold 住时，他们开始束手无策。&lt;/p&gt;

&lt;p&gt;针对人类思维特点，类似于键盘人体工程学，我们在编写软件时应该注意代码在浏览上对于人类思维的直观，除了比较熟知的一个函数里不要写太多代码外，同样一个作为基本单元的功能也最好不要超出六七个相对不同的函数集。有些人可能不太明白，他们确确实实见到了很多包括有名的开源项目里都有单文件里几百行甚至几千行的代码，但是这些优秀的代码通常都是在一个层次里面把函数集合放在单独抽取的模块里。不要担心做不到这一点，用不同颜色去标记不同国家地区的地图都可以仅用 &lt;a href="http://zh.wikipedia.org/wiki/%E5%9B%9B%E8%89%B2%E5%AE%9A%E7%90%86" title=""&gt;四种颜色来染色&lt;/a&gt; 。&lt;/p&gt;

&lt;p&gt;机械的本质就是齿轮之间的咬合，而相互驱动的齿轮绝对不能像混乱的意大利面条一样到处都是死结。&lt;/p&gt;
&lt;h2 id="Law of Demeter (得墨忒耳定律)"&gt;Law of Demeter (得墨忒耳定律)&lt;/h2&gt;
&lt;p&gt;前段时间同事和我分享了一篇 &lt;a href="http://pragprog.com/articles/tell-dont-ask" rel="nofollow" target="_blank" title=""&gt;Tell, Don't Ask&lt;/a&gt; 的文章，讲述了模块调用之间松耦合的原则，所谓"不在其位，不谋其政"，此观点也可以被归纳为 &lt;a href="http://zh.wikipedia.org/wiki/%E5%BE%97%E5%A2%A8%E5%BF%92%E8%80%B3%E5%AE%9A%E5%BE%8B" title=""&gt;Law of Demeter&lt;/a&gt; 。&lt;/p&gt;

&lt;p&gt;Law of Demeter 处理的是已经划分好模块后如何相互之间通讯和单一职责的事情，而人类同时只能处理有限数量的相似对象的原则指明了什么时候应该适当重构的这条界限。&lt;/p&gt;
&lt;h2 id="别人说的一些话"&gt;别人说的一些话&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://www.wentrue.net/blog/?p=1324" rel="nofollow" target="_blank"&gt;http://www.wentrue.net/blog/?p=1324&lt;/a&gt; 为什么用 R 写代码很爽，是因为它把枯燥的敲键盘的工作变成有趣的大脑思维的工作。马上就被勤奋的 cleverpig 同学逮住了。这几天看《黑客与画家》，看到 Paul Graham 很有创意地把黑客和画家的工作关联起来——正是我要表达的意思！&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>mvj3</author>
      <pubDate>Wed, 18 Dec 2013 16:02:04 +0800</pubDate>
      <link>https://ruby-china.org/topics/16286</link>
      <guid>https://ruby-china.org/topics/16286</guid>
    </item>
    <item>
      <title>红宝石 大战 Hangman</title>
      <description>&lt;h2 id="红宝石 大战 Hangman"&gt;红宝石 大战 Hangman&lt;/h2&gt;
&lt;p&gt;Hangman is a word game played between two people. One person selects a secret word, and the other tries to determine the word by guessing it letter-by-letter.
游戏背景和具体规则可以参考 &lt;a href="http://zh.wikipedia.org/zh-cn/%E7%8C%9C%E5%8D%95%E8%AF%8D%E6%B8%B8%E6%88%8F" title=""&gt;中文 Wiki&lt;/a&gt; 。&lt;/p&gt;

&lt;p&gt;项目地址在 &lt;a href="https://github.com/mvj3/hangman" rel="nofollow" target="_blank"&gt;https://github.com/mvj3/hangman&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;如果单纯想看策略的话，推荐看 &lt;a href="/luikore" class="user-mention" title="@luikore"&gt;&lt;i&gt;@&lt;/i&gt;luikore&lt;/a&gt; 基于决策树写的 &lt;a href="https://gist.github.com/luikore/8011242" rel="nofollow" target="_blank" title=""&gt;a-hangman&lt;/a&gt; 更精妙的实现，他把单词频率和位置信息在决策树里融为一体了，准确率高达 99.3125%。我稍微加了点 &lt;a href="https://gist.github.com/mvj3/8016738" rel="nofollow" target="_blank" title=""&gt;注释&lt;/a&gt; 。&lt;/p&gt;

&lt;p&gt;如果想看一个项目如何在有时间限制下解决开发中各种问题，那就看我这个项目的 &lt;a href="https://github.com/mvj3/hangman/commits/master" rel="nofollow" target="_blank" title=""&gt;commit 信息&lt;/a&gt; 好了。&lt;/p&gt;
&lt;h2 id="目前成绩"&gt;目前成绩&lt;/h2&gt;
&lt;p&gt;我在网上搜了下别人的，在 topcoder 上的最佳成绩在 86% 左右。而现在我这个基于 Ruby 语言开发的 Hangman 项目，在给定 80 个未知单词的情况下，该程序目前猜对率平均在 95% 以上，有时可以达到 100%。&lt;/p&gt;
&lt;h2 id="核心思想"&gt;核心思想&lt;/h2&gt;
&lt;p&gt;贪婪算法，每次排除掉尽可能多的单词，让猜测步骤尽可能少。&lt;/p&gt;
&lt;h2 id="复杂度估计"&gt;复杂度估计&lt;/h2&gt;
&lt;p&gt;a. 最笨的次数是猜 20 次以上，也就是枚举所有字母了。&lt;/p&gt;

&lt;p&gt;b. 最少是该单词唯一字母的个数，所以一般来说底线是单词长度。&lt;/p&gt;
&lt;h2 id="解题步骤"&gt;解题步骤&lt;/h2&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0
返回单词长度这步就不说了
1
第一个猜的字母用统计数据的词频，返回可能部分被*掩盖的单词，
1.1 如果是A或I，判断就终止了;
1.2 如果全是*，继续字母频度的下一个;
1.3 如果不全是*，那么进入第二步
2
在 1 里我们知道了单词的长度，
那么第二个猜的字母根据刚才含有位置信息的字母去找到字典索引找到全部匹配的单词列表，
并统计其中字母频度，并按该结果取出第二个字母（第一个我们刚才用掉了嘛），
并一直直到确认第二个字母匹配。
2.1 如果这个单词只有两个字母，那么到这里就结束了,
2.2
如果是两个以上字母，那么剩余的字母频度就从这个过滤好的单词列表里继续抽取了，
如此反复，直到最终找到那个单词为止。
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="Ruby程序优化原则"&gt;Ruby 程序优化原则&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;使用 Symbol 节省内存&lt;/li&gt;
&lt;li&gt;使用 Hash O(1) 查找&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="问题和参考"&gt;问题和参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;猜词策略，元音和辅音间隔猜。&lt;/li&gt;
&lt;li&gt;采用贝叶斯 bayes? 但是位置信息已经是最大概率。&lt;/li&gt;
&lt;li&gt;写一篇 Hangman 概率论文，猜中牛津词典里全部单词最少需要几步。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;作为一个程序员，我先是选择算法和其他现成做法。以下为其他参考：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/spydez/hangman" rel="nofollow" target="_blank"&gt;https://github.com/spydez/hangman&lt;/a&gt; hanman solver program for job interview&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/258405" rel="nofollow" target="_blank"&gt;http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/258405&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.learnstreet.com/cg/simple/project/hangman-ruby" rel="nofollow" target="_blank"&gt;http://www.learnstreet.com/cg/simple/project/hangman-ruby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://en.wikipedia.org/wiki/Hangman_game)" rel="nofollow" target="_blank"&gt;http://en.wikipedia.org/wiki/Hangman_game)&lt;/a&gt;(&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://zh.wikipedia.org/wiki/" rel="nofollow" target="_blank"&gt;http://zh.wikipedia.org/wiki/&lt;/a&gt;字母频率&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/fredley/pyngman/blob/master/pyngman.py" rel="nofollow" target="_blank"&gt;https://github.com/fredley/pyngman/blob/master/pyngman.py&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.google.com/document/d/18s9i0SKThDasIAb3WgTxxSkz2QEjAT9sVyJFQXMpB1I/edit" rel="nofollow" target="_blank"&gt;https://docs.google.com/document/d/18s9i0SKThDasIAb3WgTxxSkz2QEjAT9sVyJFQXMpB1I/edit&lt;/a&gt; 七种武器：从一个算法的多语言实现看编程语言的横向对比&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/16223305/algorithm-for-classifying-words-for-hangman-difficulty-levels-as-easy-medium" rel="nofollow" target="_blank"&gt;http://stackoverflow.com/questions/16223305/algorithm-for-classifying-words-for-hangman-difficulty-levels-as-easy-medium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/freizl/play-hangman-game/" rel="nofollow" target="_blank"&gt;https://github.com/freizl/play-hangman-game/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="Local测试结果示例"&gt;Local 测试结果示例&lt;/h2&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
➜  hangman git:(master) bundle exec guard
18:26:39 - INFO - Guard uses TerminalTitle to send notifications.
18:26:39 - INFO - Guard::Test 1.0.0 is running, with Test::Unit 2.5.5!
18:26:39 - INFO - Running all tests
单词长度对应的所有单词总数表
    1 : 2
    2 : 96
    3 : 978
    4 : 3919
    5 : 8672
    6 : 15290
    7 : 23208
    8 : 28558
    9 : 25011
   10 : 20404
   11 : 15581
   12 : 11382
   13 : 7835
   14 : 5134
   15 : 3198
   16 : 1938
   17 : 1125
   18 : 594
   19 : 328
   20 : 159
   21 : 62
   22 : 29
   23 : 13
   24 : 9
   25 : 2
   27 : 2
   28 : 1

Started
..


################################################################################
                              开始猜80个单词
################################################################################

 --------------------------------------------------------------------------------
猜测第1个单词，长度为8，可以猜错10次。
10.9.8.-[*****I**]-排除了6196个单词
8.7.-[***A*I**]-排除了608个单词
7.6.-[*O*A*IO*]-排除了9个单词
6.5.-[*O*A*ION]-排除了7个单词
5.4.-[RO*A*ION]-排除了2个单词
4.3.-[ROTATION]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "S", "I", "B", "A", "C", "O", "D", "N", "P", "R", "G", "T"]，共13个
[猜中的单词是]    ROTATION！

 --------------------------------------------------------------------------------
猜测第2个单词，长度为12，可以猜错10次。
10.-[****E******E]-排除了95个单词
10.-[****E**C***E]-排除了2个单词
10.9.-[P***E**C***E]-排除了1个单词
9.-[P***E*AC***E]-排除了1个单词
9.-[PU**E*AC***E]-排除了1个单词
9.-[PU**E*AC*I*E]-排除了1个单词
9.-[PUT*E*ACTI*E]-排除了1个单词
9.-[PUTRE*ACTI*E]-排除了1个单词
9.-[PUTREFACTI*E]-排除了1个单词
9.-[PUTREFACTIVE]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "C", "O", "P", "A", "U", "I", "T", "R", "F", "V"]，共11个
[猜中的单词是]    PUTREFACTIVE！

 --------------------------------------------------------------------------------
猜测第3个单词，长度为17，可以猜错10次。
10.-[I*******I****I***]-排除了13个单词
10.-[IN***N**I*N**I***]-排除了6个单词
10.-[IN*E*N**I*N**I***]-排除了6个单词
10.-[INTE*N*TI*N**I*T*]-排除了1个单词
10.-[INTE*NATI*NA*I*T*]-排除了1个单词
10.-[INTERNATI*NA*I*T*]-排除了1个单词
10.-[INTERNATIONA*I*T*]-排除了1个单词
10.-[INTERNATIONALI*T*]-排除了1个单词
10.-[INTERNATIONALISTS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["I", "N", "E", "T", "A", "R", "O", "L", "S"]，共9个
[猜中的单词是]    INTERNATIONALISTS！

 --------------------------------------------------------------------------------
猜测第4个单词，长度为9，可以猜错10次。
10.9.-[********S]-排除了10318个单词
9.8.-[B*******S]-排除了191个单词
8.-[B****I**S]-排除了34个单词
8.7.6.-[B*LL*I**S]-排除了1个单词
6.-[BULL*I**S]-排除了1个单词
6.-[BULLRI**S]-排除了1个单词
6.-[BULLRIN*S]-排除了1个单词
6.-[BULLRINGS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "S", "A", "B", "I", "D", "O", "L", "U", "R", "N", "G"]，共12个
[猜中的单词是]    BULLRINGS！

 --------------------------------------------------------------------------------
猜测第5个单词，长度为5，可以猜错10次。
10.-[****S]-排除了2707个单词
10.-[*A**S]-排除了456个单词
10.9.-[*A*ES]-排除了112个单词
9.8.7.6.5.4.3.2.1.[状态]            失败
[依次猜过的字母]  ["S", "A", "B", "E", "C", "O", "D", "F", "G", "H", "J", "K", "L"]，共13个
[还没猜完的单词]  [:MANES, :MARES, :MATES, :MAXES, :MAZES, :NAMES, :NAPES, :NARES, :NATES, :NAVES, :PANES, :PARES, :PATES, :PAVES, :PAXES, :RAPES, :RARES, :RATES, :RAVES, :RAXES, :RAZES, :TAMES, :TAPES, :TARES, :TATES, :TAXES, :VANES, :WAMES, :WANES, :WARES, :WAVES, :WAXES, :ZAXES] 这33个单词

 --------------------------------------------------------------------------------
猜测第6个单词，长度为12，可以猜错10次。
10.-[***********E]-排除了896个单词
10.9.8.7.-[*******I*I*E]-排除了4个单词
7.6.-[*O***O*I*I*E]-排除了1个单词
6.-[PO**PO*I*I*E]-排除了1个单词
6.-[POS*POSI*I*E]-排除了1个单词
6.-[POSTPOSITI*E]-排除了1个单词
6.-[POSTPOSITIVE]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "B", "A", "C", "I", "N", "O", "P", "S", "T", "V"]，共11个
[猜中的单词是]    POSTPOSITIVE！

 --------------------------------------------------------------------------------
猜测第7个单词，长度为13，可以猜错10次。
10.-[*****I*******]-排除了669个单词
10.-[***C*I*******]-排除了7个单词
10.-[E*EC*I**EE*E*]-排除了2个单词
10.-[ELEC*I**EE*E*]-排除了2个单词
10.-[ELEC*IO*EE*E*]-排除了2个单词
10.-[ELECTIO*EE*E*]-排除了2个单词
10.-[ELECTIONEE*E*]-排除了2个单词
10.-[ELECTIONEERER]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["I", "C", "E", "L", "O", "T", "N", "R"]，共8个
[猜中的单词是]    ELECTIONEERER！

 --------------------------------------------------------------------------------
猜测第8个单词，长度为10，可以猜错10次。
10.9.-[******I***]-排除了2750个单词
9.8.-[*A**A*I***]-排除了64个单词
8.-[CA**A*I***]-排除了9个单词
8.-[CA**A*IO**]-排除了3个单词
8.7.-[CA*SA*IO*S]-排除了1个单词
7.-[CAUSA*IO*S]-排除了1个单词
7.-[CAUSATIO*S]-排除了1个单词
7.-[CAUSATIONS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "I", "B", "A", "C", "O", "R", "S", "U", "T", "N"]，共11个
[猜中的单词是]    CAUSATIONS！

 --------------------------------------------------------------------------------
猜测第9个单词，长度为11，可以猜错10次。
10.-[******E**E*]-排除了772个单词
10.9.8.7.-[*I**I*E*IE*]-排除了3个单词
7.-[MI**I*E*IE*]-排除了3个单词
7.6.-[MILLI*E*IE*]-排除了1个单词
6.-[MILLINE*IE*]-排除了1个单词
6.-[MILLINERIE*]-排除了1个单词
6.-[MILLINERIES]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "B", "A", "C", "I", "M", "D", "L", "N", "R", "S"]，共11个
[猜中的单词是]    MILLINERIES！

 --------------------------------------------------------------------------------
猜测第10个单词，长度为8，可以猜错10次。
10.9.-[S*******]-排除了3480个单词
9.-[S**A****]-排除了182个单词
9.8.-[S**A*I**]-排除了61个单词
8.7.-[SO*A*IO*]-排除了1个单词
7.-[SOLA*IO*]-排除了1个单词
7.-[SOLATIO*]-排除了1个单词
7.-[SOLATION]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "S", "A", "C", "I", "D", "O", "L", "T", "N"]，共10个
[猜中的单词是]    SOLATION！

 --------------------------------------------------------------------------------
猜测第11个单词，长度为11，可以猜错10次。
10.-[****E*E****]-排除了130个单词
10.-[*N**E*EN***]-排除了2个单词
10.-[IN**E*EN***]-排除了2个单词
10.-[INC*E*EN***]-排除了2个单词
10.9.-[INCLE*EN*L*]-排除了1个单词
9.-[INCLEMEN*L*]-排除了1个单词
9.-[INCLEMENTL*]-排除了1个单词
9.-[INCLEMENTLY]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "N", "I", "C", "A", "L", "M", "T", "Y"]，共9个
[猜中的单词是]    INCLEMENTLY！

 --------------------------------------------------------------------------------
猜测第12个单词，长度为10，可以猜错10次。
10.-[**E*******]-排除了1461个单词
10.9.-[**E*A*****]-排除了44个单词
9.8.-[**E*A*I***]-排除了5个单词
8.7.6.-[T*E*A*I*T*]-排除了1个单词
6.-[THE*A*I*T*]-排除了1个单词
6.-[THERA*I*T*]-排除了1个单词
6.-[THERAPI*T*]-排除了1个单词
6.-[THERAPISTS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "B", "A", "C", "I", "G", "O", "T", "H", "R", "P", "S"]，共12个
[猜中的单词是]    THERAPISTS！

 --------------------------------------------------------------------------------
猜测第13个单词，长度为7，可以猜错10次。
10.9.8.-[****I**]-排除了4852个单词
8.-[B***I**]-排除了304个单词
8.-[BA**I**]-排除了66个单词
8.7.6.5.4.-[BA**I*G]-排除了17个单词
4.3.2.-[BA**ING]-排除了10个单词
2.1.-[BA*HING]-排除了2个单词
1.-[BATHING]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "S", "I", "B", "A", "C", "O", "D", "F", "G", "L", "M", "N", "R", "H", "T"]，共16个
[猜中的单词是]    BATHING！

 --------------------------------------------------------------------------------
猜测第14个单词，长度为14，可以猜错10次。
10.-[*****I*****I**]-排除了176个单词
10.-[*R***I*****I**]-排除了5个单词
10.-[*RE**I*****IE*]-排除了1个单词
10.-[KRE**I*****IE*]-排除了1个单词
10.-[KRE**I*O*O*IE*]-排除了1个单词
10.-[KREM*I*O*O*IE*]-排除了1个单词
10.-[KREMLI*OLO*IE*]-排除了1个单词
10.-[KREMLINOLO*IE*]-排除了1个单词
10.-[KREMLINOLOGIE*]-排除了1个单词
10.-[KREMLINOLOGIES]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["I", "R", "E", "K", "O", "M", "L", "N", "G", "S"]，共10个
[猜中的单词是]    KREMLINOLOGIES！

 --------------------------------------------------------------------------------
猜测第15个单词，长度为12，可以猜错10次。
10.-[*E****E*E***]-排除了19个单词
10.9.-[*E**O*E*E***]-排除了2个单词
9.-[PE**O*E*E***]-排除了2个单词
9.-[PE**O*E*E*I*]-排除了2个单词
9.-[PET*O*E*E*I*]-排除了2个单词
9.-[PETRO*E*E*I*]-排除了1个单词
9.-[PETROGE*E*I*]-排除了1个单词
9.-[PETROGENE*I*]-排除了1个单词
9.-[PETROGENESIS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "B", "O", "P", "I", "T", "R", "G", "N", "S"]，共10个
[猜中的单词是]    PETROGENESIS！

 --------------------------------------------------------------------------------
猜测第16个单词，长度为14，可以猜错10次。
10.-[**********I***]-排除了1018个单词
10.9.-[******A*A*I***]-排除了10个单词
9.8.-[**E***A*A*I*E*]-排除了2个单词
8.-[*VE***A*A*I*E*]-排除了2个单词
8.-[OVE***A*A*I*E*]-排除了2个单词
8.-[OVER*RA*A*I*E*]-排除了2个单词
8.-[OVERDRA*A*I*E*]-排除了2个单词
8.-[OVERDRAMA*I*E*]-排除了1个单词
8.-[OVERDRAMATI*E*]-排除了1个单词
8.-[OVERDRAMATIZE*]-排除了1个单词
8.-[OVERDRAMATIZES]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["I", "C", "A", "H", "E", "V", "O", "R", "D", "M", "T", "Z", "S"]，共13个
[猜中的单词是]    OVERDRAMATIZES！

 --------------------------------------------------------------------------------
猜测第17个单词，长度为10，可以猜错10次。
10.-[***E*E****]-排除了203个单词
10.-[***E*E**C*]-排除了2个单词
10.-[I**E*E**C*]-排除了1个单词
10.-[IN*E*E**C*]-排除了1个单词
10.-[IN*E*E*AC*]-排除了1个单词
10.-[INVE*E*AC*]-排除了1个单词
10.-[INVETE*AC*]-排除了1个单词
10.-[INVETERAC*]-排除了1个单词
10.-[INVETERACY]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "C", "I", "N", "A", "V", "T", "R", "Y"]，共9个
[猜中的单词是]    INVETERACY！

 --------------------------------------------------------------------------------
猜测第18个单词，长度为10，可以猜错10次。
10.-[********E*]-排除了6035个单词
10.-[**R*****E*]-排除了281个单词
10.9.8.-[*ORO****E*]-排除了6个单词
8.-[MORO****E*]-排除了2个单词
8.-[MORO*I*IE*]-排除了2个单词
8.7.-[MOROSI*IES]-排除了1个单词
7.-[MOROSITIES]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "R", "A", "B", "O", "M", "I", "N", "S", "T"]，共10个
[猜中的单词是]    MOROSITIES！

 --------------------------------------------------------------------------------
猜测第19个单词，长度为8，可以猜错10次。
10.-[******E*]-排除了7538个单词
10.-[S*****E*]-排除了663个单词
10.-[SA****E*]-排除了15个单词
10.-[SA****EL]-排除了1个单词
10.-[SA**O*EL]-排除了1个单词
10.-[SAP*OPEL]-排除了1个单词
10.-[SAPROPEL]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "S", "A", "L", "O", "P", "R"]，共7个
[猜中的单词是]    SAPROPEL！

 --------------------------------------------------------------------------------
猜测第20个单词，长度为7，可以猜错10次。
10.-[*E*****]-排除了3442个单词
10.9.8.7.-[*E**O**]-排除了121个单词
7.-[*E**O*D]-排除了12个单词
7.6.5.-[*E**ORD]-排除了1个单词
5.-[TE**ORD]-排除了1个单词
5.-[TEL*ORD]-排除了1个单词
5.-[TELFORD]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "C", "A", "B", "O", "D", "I", "K", "R", "T", "L", "F"]，共12个
[猜中的单词是]    TELFORD！

 --------------------------------------------------------------------------------
猜测第21个单词，长度为5，可以猜错10次。
10.-[***SS]-排除了32个单词
10.-[**ASS]-排除了10个单词
10.9.8.7.6.5.4.-[T*ASS]-排除了1个单词
4.-[TRASS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["S", "A", "B", "C", "F", "G", "K", "Q", "T", "R"]，共10个
[猜中的单词是]    TRASS！

 --------------------------------------------------------------------------------
猜测第22个单词，长度为9，可以猜错10次。
10.-[*E*******]-排除了4005个单词
10.9.8.-[BE**B****]-排除了1个单词
8.-[BE**BI***]-排除了1个单词
8.-[BELLBI***]-排除了1个单词
8.-[BELLBIR**]-排除了1个单词
8.-[BELLBIRD*]-排除了1个单词
8.-[BELLBIRDS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "P", "A", "B", "I", "L", "R", "D", "S"]，共9个
[猜中的单词是]    BELLBIRDS！

 --------------------------------------------------------------------------------
猜测第23个单词，长度为10，可以猜错10次。
10.-[********E*]-排除了6035个单词
10.-[*R******E*]-排除了235个单词
10.-[AR******E*]-排除了10个单词
10.9.-[AR*I**I*E*]-排除了1个单词
9.-[ARGI**I*E*]-排除了1个单词
9.-[ARGILLI*E*]-排除了1个单词
9.-[ARGILLITE*]-排除了1个单词
9.-[ARGILLITES]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "R", "A", "C", "I", "G", "L", "T", "S"]，共9个
[猜中的单词是]    ARGILLITES！

 --------------------------------------------------------------------------------
猜测第24个单词，长度为10，可以猜错10次。
10.-[*********E]-排除了1955个单词
10.9.-[*****A***E]-排除了97个单词
9.8.-[**I*IA*I*E]-排除了4个单词
8.-[T*I*IA*I*E]-排除了2个单词
8.-[TRI*IA*I*E]-排除了2个单词
8.-[TRIVIA*I*E]-排除了2个单词
8.-[TRIVIALI*E]-排除了2个单词
8.-[TRIVIALISE]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "B", "A", "C", "I", "T", "R", "V", "L", "S"]，共10个
[猜中的单词是]    TRIVIALISE！

 --------------------------------------------------------------------------------
猜测第25个单词，长度为4，可以猜错10次。
10.-[**A*]-排除了338个单词
10.9.8.7.-[*EA*]-排除了64个单词
7.-[DEA*]-排除了5个单词
7.6.5.4.-[DEAR]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["A", "B", "O", "C", "E", "D", "F", "L", "N", "R"]，共10个
[猜中的单词是]    DEAR！

 --------------------------------------------------------------------------------
猜测第26个单词，长度为15，可以猜错10次。
10.9.-[*****E*********]-排除了305个单词
9.-[*****E********L]-排除了5个单词
9.-[*O***E***O*O**L]-排除了1个单词
9.-[CO***E***O*O**L]-排除了1个单词
9.-[CO***E***O*O*AL]-排除了1个单词
9.-[COU**E***O*O*AL]-排除了1个单词
9.-[COUN*E***O*O*AL]-排除了1个单词
9.-[COUNTE***O*O*AL]-排除了1个单词
9.-[COUNTER*RO*O*AL]-排除了1个单词
9.-[COUNTERPROPO*AL]-排除了1个单词
9.-[COUNTERPROPOSAL]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["I", "E", "L", "O", "C", "A", "U", "N", "T", "R", "P", "S"]，共12个
[猜中的单词是]    COUNTERPROPOSAL！

 --------------------------------------------------------------------------------
猜测第27个单词，长度为10，可以猜错10次。
10.9.-[*****I****]-排除了2386个单词
9.8.7.6.-[**O**I**O*]-排除了2个单词
6.-[**OP*I**O*]-排除了2个单词
6.-[S*OP*I**O*]-排除了1个单词
6.-[SHOP*I**O*]-排除了1个单词
6.-[SHOPWI**OW]-排除了1个单词
6.-[SHOPWIN*OW]-排除了1个单词
6.-[SHOPWINDOW]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "I", "B", "A", "C", "O", "P", "S", "H", "W", "N", "D"]，共12个
[猜中的单词是]    SHOPWINDOW！

 --------------------------------------------------------------------------------
猜测第28个单词，长度为10，可以猜错10次。
10.-[E**E******]-排除了108个单词
10.9.-[E**E**I***]-排除了8个单词
9.8.7.-[EX*E**I***]-排除了5个单词
7.-[EX*E**IO**]-排除了4个单词
7.-[EXCE**IO**]-排除了2个单词
7.-[EXCEL*IO**]-排除了1个单词
7.-[EXCELSIO*S]-排除了1个单词
7.-[EXCELSIORS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "V", "I", "G", "A", "X", "O", "C", "L", "S", "R"]，共11个
[猜中的单词是]    EXCELSIORS！

 --------------------------------------------------------------------------------
猜测第29个单词，长度为16，可以猜错10次。
10.-[******I*********]-排除了214个单词
10.-[****B*I*********]-排除了2个单词
10.-[****B*IO********]-排除了2个单词
10.-[**L*B*IO********]-排除了1个单词
10.-[*AL*B*IO********]-排除了1个单词
10.-[SAL*B*IO*S**SS*S]-排除了1个单词
10.-[SAL*B*IO*S*ESSES]-排除了1个单词
10.-[SALUB*IOUS*ESSES]-排除了1个单词
10.-[SALUBRIOUS*ESSES]-排除了1个单词
10.-[SALUBRIOUSNESSES]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["I", "B", "O", "L", "A", "S", "E", "U", "R", "N"]，共10个
[猜中的单词是]    SALUBRIOUSNESSES！

 --------------------------------------------------------------------------------
猜测第30个单词，长度为11，可以猜错10次。
10.-[***E*******]-排除了1940个单词
10.9.8.-[***E****C**]-排除了3个单词
8.-[***E***IC**]-排除了1个单词
8.-[U**E***IC**]-排除了1个单词
8.-[UN*E***IC**]-排除了1个单词
8.-[UNDE***IC**]-排除了1个单词
8.-[UNDER*RIC**]-排除了1个单词
8.-[UNDERTRIC**]-排除了1个单词
8.-[UNDERTRICK*]-排除了1个单词
8.-[UNDERTRICKS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "B", "A", "C", "I", "U", "N", "D", "R", "T", "K", "S"]，共12个
[猜中的单词是]    UNDERTRICKS！

 --------------------------------------------------------------------------------
猜测第31个单词，长度为11，可以猜错10次。
10.-[E****E*E***]-排除了10个单词
10.-[EFF**E*E***]-排除了1个单词
10.-[EFFA*E*E***]-排除了1个单词
10.-[EFFACE*E***]-排除了1个单词
10.-[EFFACEME***]-排除了1个单词
10.-[EFFACEMEN**]-排除了1个单词
10.-[EFFACEMENT*]-排除了1个单词
10.-[EFFACEMENTS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "F", "A", "C", "M", "N", "T", "S"]，共8个
[猜中的单词是]    EFFACEMENTS！

 --------------------------------------------------------------------------------
猜测第32个单词，长度为9，可以猜错10次。
10.-[E*****E**]-排除了133个单词
10.9.8.7.-[E*****EA*]-排除了1个单词
7.-[EN****EA*]-排除了1个单词
7.-[EN*O**EA*]-排除了1个单词
7.-[ENDO**EA*]-排除了1个单词
7.-[ENDOS*EA*]-排除了1个单词
7.-[ENDOSTEA*]-排除了1个单词
7.-[ENDOSTEAL]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "R", "I", "F", "A", "N", "O", "D", "S", "T", "L"]，共11个
[猜中的单词是]    ENDOSTEAL！

 --------------------------------------------------------------------------------
猜测第33个单词，长度为10，可以猜错10次。
10.-[*E******E*]-排除了1015个单词
10.-[*ER*****E*]-排除了94个单词
10.-[*ER*A***E*]-排除了15个单词
10.9.-[*ERIA*I*E*]-排除了2个单词
9.-[SERIA*ISES]-排除了1个单词
9.-[SERIALISES]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "R", "A", "D", "I", "S", "L"]，共7个
[猜中的单词是]    SERIALISES！

 --------------------------------------------------------------------------------
猜测第34个单词，长度为11，可以猜错10次。
10.9.-[I*******I**]-排除了231个单词
9.8.-[I**O****I**]-排除了11个单词
8.-[IM*O****I**]-排除了7个单词
8.7.-[IMPO****I**]-排除了2个单词
7.-[IMPOR***I**]-排除了2个单词
7.-[IMPORT**I**]-排除了2个单词
7.-[IMPORTU*I**]-排除了1个单词
7.-[IMPORTUNIN*]-排除了1个单词
7.-[IMPORTUNING]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "I", "C", "O", "M", "B", "P", "R", "T", "U", "N", "G"]，共12个
[猜中的单词是]    IMPORTUNING！

 --------------------------------------------------------------------------------
猜测第35个单词，长度为8，可以猜错10次。
10.9.-[******S*]-排除了2110个单词
9.-[**A***S*]-排除了125个单词
9.-[B*A***S*]-排除了15个单词
9.-[B*A**IS*]-排除了7个单词
9.8.7.-[BRA**IS*]-排除了3个单词
7.6.-[BRAN*IS*]-排除了1个单词
6.-[BRANDIS*]-排除了1个单词
6.-[BRANDISH]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "S", "A", "B", "I", "L", "O", "R", "C", "N", "D", "H"]，共12个
[猜中的单词是]    BRANDISH！

 --------------------------------------------------------------------------------
猜测第36个单词，长度为7，可以猜错10次。
10.-[*E*****]-排除了3442个单词
10.9.-[*EA****]-排除了142个单词
9.8.-[*EA*I**]-排除了60个单词
8.7.6.5.4.-[*EALI**]-排除了3个单词
4.-[REALI**]-排除了3个单词
4.-[REALIS*]-排除了2个单词
4.3.-[REALIST]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "C", "A", "B", "I", "D", "F", "G", "H", "L", "R", "S", "M", "T"]，共14个
[猜中的单词是]    REALIST！

 --------------------------------------------------------------------------------
猜测第37个单词，长度为8，可以猜错10次。
10.-[****E*E*]-排除了751个单词
10.9.8.7.6.-[****E*ED]-排除了73个单词
6.-[**O*E*ED]-排除了11个单词
6.5.4.3.2.-[T*O*E*ED]-排除了1个单词
2.-[TRO*E*ED]-排除了1个单词
2.-[TROWE*ED]-排除了1个单词
2.-[TROWELED]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "C", "A", "B", "I", "D", "O", "F", "G", "P", "S", "T", "R", "W", "L"]，共15个
[猜中的单词是]    TROWELED！

 --------------------------------------------------------------------------------
猜测第38个单词，长度为11，可以猜错10次。
10.9.-[*********I*]-排除了776个单词
9.-[*********IC]-排除了286个单词
9.-[******A**IC]-排除了45个单词
9.8.-[*O*O**A**IC]-排除了12个单词
8.-[*O*O**A*HIC]-排除了7个单词
8.-[LO*O**A*HIC]-排除了1个单词
8.-[LOGOG*A*HIC]-排除了1个单词
8.-[LOGOGRA*HIC]-排除了1个单词
8.-[LOGOGRAPHIC]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "I", "C", "A", "D", "O", "H", "L", "G", "R", "P"]，共11个
[猜中的单词是]    LOGOGRAPHIC！

 --------------------------------------------------------------------------------
猜测第39个单词，长度为8，可以猜错10次。
10.-[******E*]-排除了7538个单词
10.-[S*****ES]-排除了247个单词
10.-[S*A***ES]-排除了45个单词
10.-[S*A*C*ES]-排除了5个单词
10.9.-[SNA*C*ES]-排除了1个单词
9.-[SNATC*ES]-排除了1个单词
9.-[SNATCHES]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "S", "A", "C", "L", "N", "T", "H"]，共8个
[猜中的单词是]    SNATCHES！

 --------------------------------------------------------------------------------
猜测第40个单词，长度为6，可以猜错10次。
10.-[****E*]-排除了4702个单词
10.9.-[*A**E*]-排除了770个单词
9.8.7.-[*AD*E*]-排除了29个单词
7.6.5.4.3.-[*ADLE*]-排除了3个单词
3.-[PADLE*]-排除了1个单词
3.-[PADLES]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "B", "A", "C", "O", "D", "I", "F", "G", "H", "L", "P", "S"]，共13个
[猜中的单词是]    PADLES！

 --------------------------------------------------------------------------------
猜测第41个单词，长度为9，可以猜错10次。
10.-[*******E*]-排除了6851个单词
10.9.8.-[C******E*]-排除了163个单词
8.-[C****I*E*]-排除了41个单词
8.7.-[CO***I*E*]-排除了18个单词
7.-[COM**I*E*]-排除了5个单词
7.-[COMP*I*E*]-排除了5个单词
7.6.-[COMPRI*E*]-排除了4个单词
6.-[COMPRISES]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "B", "A", "C", "I", "H", "O", "M", "P", "L", "R", "S"]，共12个
[猜中的单词是]    COMPRISES！

 --------------------------------------------------------------------------------
猜测第42个单词，长度为7，可以猜错10次。
10.9.-[**S***S]-排除了456个单词
9.-[*AS*A*S]-排除了10个单词
9.-[BAS*A*S]-排除了1个单词
9.-[BASHA*S]-排除了1个单词
9.-[BASHAWS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "S", "A", "B", "H", "W"]，共6个
[猜中的单词是]    BASHAWS！

 --------------------------------------------------------------------------------
猜测第43个单词，长度为8，可以猜错10次。
10.-[******E*]-排除了7538个单词
10.-[S*****E*]-排除了663个单词
10.9.-[S**C**E*]-排除了12个单词
9.-[S*IC**E*]-排除了5个单词
9.-[STIC**E*]-排除了3个单词
9.-[STICK*E*]-排除了3个单词
9.8.-[STICKME*]-排除了1个单词
8.-[STICKMEN]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "S", "A", "C", "I", "T", "K", "L", "M", "N"]，共10个
[猜中的单词是]    STICKMEN！

 --------------------------------------------------------------------------------
猜测第44个单词，长度为13，可以猜错10次。
10.-[******I******]-排除了1125个单词
10.9.-[******I*A****]-排除了16个单词
9.-[******IDA****]-排除了1个单词
9.-[*E****IDA***E]-排除了1个单词
9.-[ME****IDA***E]-排除了1个单词
9.-[ME**O*IDA*O*E]-排除了1个单词
9.-[MET*O*IDA*O*E]-排除了1个单词
9.-[METRO*IDA*O*E]-排除了1个单词
9.-[METRONIDA*O*E]-排除了1个单词
9.-[METRONIDAZO*E]-排除了1个单词
9.-[METRONIDAZOLE]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["I", "C", "A", "D", "E", "M", "O", "T", "R", "N", "Z", "L"]，共12个
[猜中的单词是]    METRONIDAZOLE！

 --------------------------------------------------------------------------------
猜测第45个单词，长度为11，可以猜错10次。
10.-[*E*********]-排除了2641个单词
10.-[RE*********]-排除了220个单词
10.9.8.-[RE**I**I***]-排除了2个单词
8.-[RES*ISSI**S]-排除了1个单词
8.-[RES*ISSIO*S]-排除了1个单词
8.-[RESCISSIO*S]-排除了1个单词
8.-[RESCISSIONS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "R", "A", "B", "I", "S", "O", "C", "N"]，共9个
[猜中的单词是]    RESCISSIONS！

 --------------------------------------------------------------------------------
猜测第46个单词，长度为9，可以猜错10次。
10.9.-[S*****S*S]-排除了89个单词
9.8.-[S***C*S*S]-排除了6个单词
8.-[S**ICIS*S]-排除了1个单词
8.-[ST*ICIS*S]-排除了1个单词
8.-[STOICIS*S]-排除了1个单词
8.-[STOICISMS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "S", "A", "C", "I", "T", "O", "M"]，共8个
[猜中的单词是]    STOICISMS！

 --------------------------------------------------------------------------------
猜测第47个单词，长度为8，可以猜错10次。
10.9.-[*******S]-排除了9757个单词
9.-[*A****AS]-排除了104个单词
9.8.-[*A*I**AS]-排除了9个单词
8.7.6.5.-[MA*I**AS]-排除了3个单词
5.4.-[MATI**AS]-排除了1个单词
4.-[MATIL*AS]-排除了1个单词
4.-[MATILDAS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "S", "A", "B", "I", "C", "O", "F", "M", "N", "T", "L", "D"]，共13个
[猜中的单词是]    MATILDAS！

 --------------------------------------------------------------------------------
猜测第48个单词，长度为13，可以猜错10次。
10.-[*I***********]-排除了645个单词
10.9.8.7.-[*I*E**E****E*]-排除了2个单词
7.-[VI*E**E****E*]-排除了1个单词
7.-[VI*EO*E*O**E*]-排除了1个单词
7.-[VIDEO*E*O*DE*]-排除了1个单词
7.-[VIDEORE*ORDER]-排除了1个单词
7.-[VIDEORECORDER]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["I", "M", "A", "B", "E", "V", "O", "D", "R", "C"]，共10个
[猜中的单词是]    VIDEORECORDER！

 --------------------------------------------------------------------------------
猜测第49个单词，长度为8，可以猜错10次。
10.9.-[*******S]-排除了9757个单词
9.-[***A***S]-排除了493个单词
9.8.7.6.-[I**A*I*S]-排除了3个单词
6.-[IN*A*I*S]-排除了3个单词
6.5.-[INVA*I*S]-排除了1个单词
5.-[INVALI*S]-排除了1个单词
5.-[INVALIDS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "S", "A", "B", "O", "C", "I", "N", "F", "V", "L", "D"]，共12个
[猜中的单词是]    INVALIDS！

 --------------------------------------------------------------------------------
猜测第50个单词，长度为15，可以猜错10次。
10.-[*I******I**I***]-排除了10个单词
10.9.8.7.-[*I**E***I**I***]-排除了2个单词
7.-[MI**E***I**I***]-排除了1个单词
7.-[MI**E***I**IO**]-排除了1个单词
7.-[MIS*ES**I**IO*S]-排除了1个单词
7.-[MISDES**I**IO*S]-排除了1个单词
7.-[MISDESC*I**IO*S]-排除了1个单词
7.-[MISDESCRI**IO*S]-排除了1个单词
7.-[MISDESCRIP*IO*S]-排除了1个单词
7.-[MISDESCRIPTIO*S]-排除了1个单词
7.-[MISDESCRIPTIONS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["I", "B", "A", "F", "E", "M", "O", "S", "D", "C", "R", "P", "T", "N"]，共14个
[猜中的单词是]    MISDESCRIPTIONS！

 --------------------------------------------------------------------------------
猜测第51个单词，长度为13，可以猜错10次。
10.-[*******I*****]-排除了741个单词
10.-[**C****IC****]-排除了4个单词
10.-[A*C****ICA***]-排除了1个单词
10.-[ALC***LICALL*]-排除了1个单词
10.-[ALCO*OLICALL*]-排除了1个单词
10.-[ALCOHOLICALL*]-排除了1个单词
10.-[ALCOHOLICALLY]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["I", "C", "A", "L", "O", "H", "Y"]，共7个
[猜中的单词是]    ALCOHOLICALLY！

 --------------------------------------------------------------------------------
猜测第52个单词，长度为3，可以猜错10次。
10.9.8.7.-[I**]-排除了19个单词
7.6.5.4.3.-[IM*]-排除了1个单词
3.-[IMP]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["A", "E", "O", "I", "C", "D", "F", "L", "M", "P"]，共10个
[猜中的单词是]    IMP！

 --------------------------------------------------------------------------------
猜测第53个单词，长度为12，可以猜错10次。
10.-[E*******E***]-排除了44个单词
10.-[ED******E***]-排除了1个单词
10.-[ED**A***E***]-排除了1个单词
10.-[EDU*A***E***]-排除了1个单词
10.-[EDU*AI**E***]-排除了1个单词
10.-[EDUTAI**E*T*]-排除了1个单词
10.-[EDUTAIN*ENT*]-排除了1个单词
10.-[EDUTAINMENT*]-排除了1个单词
10.-[EDUTAINMENTS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "D", "A", "U", "I", "T", "N", "M", "S"]，共9个
[猜中的单词是]    EDUTAINMENTS！

 --------------------------------------------------------------------------------
猜测第54个单词，长度为14，可以猜错10次。
10.-[*******I******]-排除了764个单词
10.9.-[*******I**A***]-排除了22个单词
9.8.-[**O****IO*A***]-排除了4个单词
8.-[P*O****IO*A***]-排除了1个单词
8.-[P*O*E**IO*A***]-排除了1个单词
8.-[PRO*E**IO*A***]-排除了1个单词
8.-[PROFE**IO*A***]-排除了1个单词
8.-[PROFESSIO*A***]-排除了1个单词
8.-[PROFESSIONA***]-排除了1个单词
8.-[PROFESSIONALL*]-排除了1个单词
8.-[PROFESSIONALLY]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["I", "B", "A", "C", "O", "P", "E", "R", "F", "S", "N", "L", "Y"]，共13个
[猜中的单词是]    PROFESSIONALLY！

 --------------------------------------------------------------------------------
猜测第55个单词，长度为6，可以猜错10次。
10.-[***E**]-排除了1421个单词
10.-[**BE**]-排除了35个单词
10.9.8.-[*IBE**]-排除了8个单词
8.7.6.5.-[LIBE**]-排除了2个单词
5.-[LIBER*]-排除了1个单词
5.-[LIBERS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "B", "A", "C", "I", "F", "G", "J", "L", "R", "S"]，共11个
[猜中的单词是]    LIBERS！

 --------------------------------------------------------------------------------
猜测第56个单词，长度为7，可以猜错10次。
10.-[****E**]-排除了3038个单词
10.9.8.7.6.5.-[**O*E**]-排除了76个单词
5.4.3.2.-[P*O*E**]-排除了13个单词
2.1.-[PLO*E**]-排除了2个单词
1.[状态]            失败
[依次猜过的字母]  ["E", "B", "A", "C", "I", "D", "O", "F", "G", "K", "P", "H", "L", "V"]，共14个
[还没猜完的单词]  [:PLOWERS] 这1个单词

 --------------------------------------------------------------------------------
猜测第57个单词，长度为8，可以猜错10次。
10.-[*EE***E*]-排除了31个单词
10.9.-[*EE*A*E*]-排除了7个单词
9.8.7.6.5.-[TEE*A*E*]-排除了2个单词
5.-[TEENA*E*]-排除了2个单词
5.-[TEENAGE*]-排除了2个单词
5.-[TEENAGED]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "B", "A", "H", "K", "P", "S", "T", "N", "G", "D"]，共11个
[猜中的单词是]    TEENAGED！

 --------------------------------------------------------------------------------
猜测第58个单词，长度为10，可以猜错10次。
10.-[***E*E**E*]-排除了111个单词
10.-[***E*E**ED]-排除了20个单词
10.9.-[*N*E*E**ED]-排除了4个单词
9.8.-[UN*E*E**ED]-排除了3个单词
8.-[UNLE*ELLED]-排除了1个单词
8.-[UNLEVELLED]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "D", "A", "N", "I", "U", "L", "V"]，共8个
[猜中的单词是]    UNLEVELLED！

 --------------------------------------------------------------------------------
猜测第59个单词，长度为5，可以猜错10次。
10.-[****S]-排除了2707个单词
10.-[A***S]-排除了104个单词
10.9.-[A**ES]-排除了17个单词
9.8.-[AI*ES]-排除了1个单词
8.-[AIDES]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["S", "A", "B", "E", "C", "I", "D"]，共7个
[猜中的单词是]    AIDES！

 --------------------------------------------------------------------------------
猜测第60个单词，长度为13，可以猜错10次。
10.9.-[E*****E*E****]-排除了6个单词
9.-[EN****E*E**N*]-排除了1个单词
9.-[EN*O**E*E*ON*]-排除了1个单词
9.-[ENDO**E*E*ON*]-排除了1个单词
9.-[ENDOS*E*E*ONS]-排除了1个单词
9.-[ENDOSKE*E*ONS]-排除了1个单词
9.-[ENDOSKELE*ONS]-排除了1个单词
9.-[ENDOSKELETONS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["I", "E", "N", "O", "D", "S", "K", "L", "T"]，共9个
[猜中的单词是]    ENDOSKELETONS！

 --------------------------------------------------------------------------------
猜测第61个单词，长度为11，可以猜错10次。
10.-[*****E***E*]-排除了323个单词
10.9.-[A****E***E*]-排除了6个单词
9.8.7.6.-[A****E**IE*]-排除了1个单词
6.-[AS***E**IES]-排除了1个单词
6.-[ASY**E**IES]-排除了1个单词
6.-[ASYMME**IES]-排除了1个单词
6.-[ASYMMET*IES]-排除了1个单词
6.-[ASYMMETRIES]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "D", "A", "F", "O", "L", "I", "S", "Y", "M", "T", "R"]，共12个
[猜中的单词是]    ASYMMETRIES！

 --------------------------------------------------------------------------------
猜测第62个单词，长度为14，可以猜错10次。
10.9.-[*******E*E**E*]-排除了96个单词
9.8.7.-[C*C****E*E**E*]-排除了1个单词
7.-[COC****E*E**E*]-排除了1个单词
7.-[COCK***E*E**E*]-排除了1个单词
7.-[COCKS**E*ESSES]-排除了1个单词
7.-[COCKSU*E*ESSES]-排除了1个单词
7.-[COCKSURE*ESSES]-排除了1个单词
7.-[COCKSURENESSES]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["I", "E", "B", "A", "C", "O", "K", "S", "U", "R", "N"]，共11个
[猜中的单词是]    COCKSURENESSES！

 --------------------------------------------------------------------------------
猜测第63个单词，长度为7，可以猜错10次。
10.-[****E**]-排除了3038个单词
10.9.8.7.-[*I**E**]-排除了278个单词
7.6.5.4.3.-[HI**E**]-排除了9个单词
3.2.-[HIN*E**]-排除了1个单词
2.-[HINTE**]-排除了1个单词
2.-[HINTER*]-排除了1个单词
2.-[HINTERS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "B", "A", "C", "I", "D", "O", "F", "G", "H", "L", "N", "T", "R", "S"]，共15个
[猜中的单词是]    HINTERS！

 --------------------------------------------------------------------------------
猜测第64个单词，长度为9，可以猜错10次。
10.-[E********]-排除了1135个单词
10.9.-[EA*******]-排除了9个单词
9.-[EAR****R*]-排除了3个单词
9.-[EAR***OR*]-排除了3个单词
9.-[EART**OR*]-排除了3个单词
9.-[EARTH*OR*]-排除了3个单词
9.8.-[EARTHWOR*]-排除了2个单词
8.7.-[EARTHWORM]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "L", "A", "R", "O", "T", "H", "B", "W", "K", "M"]，共11个
[猜中的单词是]    EARTHWORM！

 --------------------------------------------------------------------------------
猜测第65个单词，长度为9，可以猜错10次。
10.9.-[********S]-排除了10318个单词
9.-[****A***S]-排除了530个单词
9.8.-[****A*I*S]-排除了50个单词
8.7.-[*O**A*I*S]-排除了3个单词
7.-[FO**A*I*S]-排除了1个单词
7.-[FOR*A*I*S]-排除了1个单词
7.-[FORMA*I*S]-排除了1个单词
7.-[FORMALI*S]-排除了1个单词
7.-[FORMALINS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "S", "A", "B", "I", "C", "O", "F", "R", "M", "L", "N"]，共12个
[猜中的单词是]    FORMALINS！

 --------------------------------------------------------------------------------
猜测第66个单词，长度为7，可以猜错10次。
10.9.-[******S]-排除了7543个单词
9.8.7.-[***I**S]-排除了284个单词
7.6.-[*O*I**S]-排除了32个单词
6.5.4.3.2.1.-[*O*IN*S]-排除了3个单词
1.-[RO*IN*S]-排除了2个单词
1.-[ROVIN*S]-排除了1个单词
1.-[ROVINGS]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "S", "A", "B", "I", "C", "O", "D", "L", "F", "H", "M", "N", "R", "V", "G"]，共16个
[猜中的单词是]    ROVINGS！

 --------------------------------------------------------------------------------
猜测第67个单词，长度为10，可以猜错10次。
10.-[****E*****]-排除了2239个单词
10.9.-[****EA****]-排除了38个单词
9.8.-[****EA*I**]-排除了21个单词
8.7.-[S***EA*IS*]-排除了2个单词
7.-[SU**EA*IS*]-排除了2个单词
7.-[SURREA*IS*]-排除了2个单词
7.-[SURREALIS*]-排除了2个单词
7.6.-[SURREALIST]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "B", "A", "C", "I", "N", "S", "U", "R", "L", "M", "T"]，共12个
[猜中的单词是]    SURREALIST！

 --------------------------------------------------------------------------------
猜测第68个单词，长度为6，可以猜错10次。
10.9.-[*****S]-排除了4306个单词
9.8.7.-[*O***S]-排除了320个单词
7.6.5.-[*O**DS]-排除了11个单词
5.4.3.2.-[MO**DS]-排除了3个单词
2.1.-[MOU*DS]-排除了2个单词
1.[状态]            失败
[依次猜过的字母]  ["E", "S", "A", "B", "O", "C", "I", "D", "F", "G", "H", "M", "P", "U", "L"]，共15个
[还没猜完的单词]  [:MOUNDS] 这1个单词

 --------------------------------------------------------------------------------
猜测第69个单词，长度为9，可以猜错10次。
10.-[***E*****]-排除了2788个单词
10.9.8.7.-[***E**I**]-排除了132个单词
7.-[***ED*I**]-排除了2个单词
7.-[*O*EDOI**]-排除了1个单词
7.-[FO*EDOI**]-排除了1个单词
7.-[FOREDOI**]-排除了1个单词
7.-[FOREDOIN*]-排除了1个单词
7.-[FOREDOING]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "B", "A", "C", "I", "D", "O", "F", "R", "N", "G"]，共11个
[猜中的单词是]    FOREDOING！

 --------------------------------------------------------------------------------
猜测第70个单词，长度为10，可以猜错10次。
10.-[******E**E]-排除了134个单词
10.-[**B***E**E]-排除了3个单词
10.-[**B*I*E**E]-排除了2个单词
10.-[S*BSI*E**E]-排除了1个单词
10.-[SUBSI*E**E]-排除了1个单词
10.-[SUBSIDE**E]-排除了1个单词
10.-[SUBSIDEN*E]-排除了1个单词
10.-[SUBSIDENCE]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "B", "I", "S", "U", "D", "N", "C"]，共8个
[猜中的单词是]    SUBSIDENCE！

 --------------------------------------------------------------------------------
猜测第71个单词，长度为8，可以猜错10次。
10.-[E**E**E*]-排除了37个单词
10.9.8.-[E*CE**E*]-排除了3个单词
8.-[EXCE**E*]-排除了3个单词
8.7.-[EXCESSE*]-排除了2个单词
7.-[EXCESSED]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "T", "I", "C", "X", "L", "S", "D"]，共8个
[猜中的单词是]    EXCESSED！

 --------------------------------------------------------------------------------
猜测第72个单词，长度为7，可以猜错10次。
10.-[E***E*E]-排除了10个单词
10.9.-[E*I*E*E]-排除了3个单词
9.-[EPI*E*E]-排除了3个单词
9.8.7.-[EPIME*E]-排除了1个单词
7.-[EPIMERE]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "K", "I", "P", "C", "G", "M", "R"]，共8个
[猜中的单词是]    EPIMERE！

 --------------------------------------------------------------------------------
猜测第73个单词，长度为8，可以猜错10次。
10.-[******E*]-排除了7538个单词
10.-[S*****E*]-排除了663个单词
10.-[S**A**E*]-排除了41个单词
10.-[SC*A**E*]-排除了10个单词
10.-[SC*A*LE*]-排除了2个单词
10.-[SCRA*LE*]-排除了2个单词
10.-[SCRAWLE*]-排除了1个单词
10.-[SCRAWLED]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "S", "A", "C", "L", "R", "W", "D"]，共8个
[猜中的单词是]    SCRAWLED！

 --------------------------------------------------------------------------------
猜测第74个单词，长度为4，可以猜错10次。
10.9.8.7.6.-[*I**]-排除了511个单词
6.-[DI**]-排除了37个单词
6.5.4.3.2.-[DI*G]-排除了1个单词
2.-[DING]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["A", "E", "S", "O", "I", "D", "L", "B", "C", "T", "G", "N"]，共12个
[猜中的单词是]    DING！

 --------------------------------------------------------------------------------
猜测第75个单词，长度为11，可以猜错10次。
10.-[***E*****E*]-排除了586个单词
10.9.-[A**E*****E*]-排除了23个单词
9.-[A**E*****ED]-排除了2个单词
9.-[A**E*O***ED]-排除了2个单词
9.-[ALLE*O***ED]-排除了2个单词
9.-[ALLE*O*I*ED]-排除了2个单词
9.-[ALLEGO*I*ED]-排除了2个单词
9.-[ALLEGORI*ED]-排除了2个单词
9.8.-[ALLEGORIZED]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "C", "A", "D", "O", "L", "I", "G", "R", "S", "Z"]，共11个
[猜中的单词是]    ALLEGORIZED！

 --------------------------------------------------------------------------------
猜测第76个单词，长度为15，可以猜错10次。
10.9.-[*************E*]-排除了959个单词
9.8.-[*****A****A**E*]-排除了3个单词
8.-[C****A****A**E*]-排除了2个单词
8.-[C**O*A*O**A**E*]-排除了2个单词
8.-[CH*O*A*O**A*HE*]-排除了2个单词
8.-[CHRO*A*O*RA*HE*]-排除了2个单词
8.-[CHROMA*O*RA*HE*]-排除了1个单词
8.-[CHROMATO*RA*HE*]-排除了1个单词
8.-[CHROMATOGRA*HE*]-排除了1个单词
8.-[CHROMATOGRAPHE*]-排除了1个单词
8.-[CHROMATOGRAPHED]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["I", "E", "B", "A", "C", "O", "H", "R", "M", "T", "G", "P", "D"]，共13个
[猜中的单词是]    CHROMATOGRAPHED！

 --------------------------------------------------------------------------------
猜测第77个单词，长度为7，可以猜错10次。
10.-[****E**]-排除了3038个单词
10.9.8.7.-[I***E**]-排除了23个单词
7.6.5.-[IM**E**]-排除了3个单词
5.-[IMP*E**]-排除了3个单词
5.-[IMPRE**]-排除了3个单词
5.4.-[IMPRES*]-排除了2个单词
4.-[IMPREST]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "B", "A", "C", "I", "L", "O", "M", "P", "R", "G", "S", "T"]，共13个
[猜中的单词是]    IMPREST！

 --------------------------------------------------------------------------------
猜测第78个单词，长度为7，可以猜错10次。
10.-[****E**]-排除了3038个单词
10.9.8.7.6.5.-[O***E**]-排除了22个单词
5.4.-[O***EP*]-排除了2个单词
4.-[OU**EP*]-排除了2个单词
4.-[OUT*EPT]-排除了2个单词
4.3.-[OUTWEPT]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "B", "A", "C", "I", "D", "O", "F", "P", "U", "T", "K", "W"]，共13个
[猜中的单词是]    OUTWEPT！

 --------------------------------------------------------------------------------
猜测第79个单词，长度为12，可以猜错10次。
10.9.-[***I*****I**]-排除了338个单词
9.8.-[**AI**A**I**]-排除了1个单词
8.-[B*AI**A**I**]-排除了1个单词
8.-[BRAI**A**I**]-排除了1个单词
8.-[BRAIN*A**IN*]-排除了1个单词
8.-[BRAINWA**IN*]-排除了1个单词
8.-[BRAINWAS*IN*]-排除了1个单词
8.-[BRAINWASHIN*]-排除了1个单词
8.-[BRAINWASHING]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "I", "C", "A", "B", "R", "N", "W", "S", "H", "G"]，共11个
[猜中的单词是]    BRAINWASHING！

 --------------------------------------------------------------------------------
猜测第80个单词，长度为8，可以猜错10次。
10.-[*E*E***E]-排除了44个单词
10.9.8.7.-[*E*E*I*E]-排除了5个单词
7.6.5.-[SE*E*I*E]-排除了1个单词
5.-[SELE*I*E]-排除了1个单词
5.-[SELENI*E]-排除了1个单词
5.-[SELENITE]-排除了1个单词
[状态]            成功
[依次猜过的字母]  ["E", "B", "A", "D", "I", "P", "R", "S", "L", "N", "T"]，共11个
[猜中的单词是]    SELENITE！

 --------------------------------------------------------------------------------
猜单词结果是: {"numberOfWordsTried"=&amp;gt;80, "numberOfCorrectWords"=&amp;gt;77, "numberOfWrongGuesses"=&amp;gt;3, "totalScore"=&amp;gt;0}

Finished in 9.71616 seconds.

6 tests, 14 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed

0.62 tests/s, 1.44 assertions/s


18:26:56 - INFO - Guard is now watching at '/Users/mvj3/github/mvj3/hangman'
[1] guard(main)&amp;gt; 

&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="Top scores in other place"&gt;Top scores in other place&lt;/h2&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://community.topcoder.com/tc?module=ProblemDetail&amp;amp;rd=4770&amp;amp;pm=2343
Problems Submitted   57
Problems Correct     49
Submission Accuracy  85.96%
Problems Failed by Challenge     7
Problems Failed by System Test   1
Challenge Attempts Made  12
Challenge Accuracy   58.33%
Best Time   0:04:13.448 0:03:12.509
Fastest Ruberik
Average Correct Time    0:13:05.750
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>mvj3</author>
      <pubDate>Tue, 17 Dec 2013 19:06:39 +0800</pubDate>
      <link>https://ruby-china.org/topics/16256</link>
      <guid>https://ruby-china.org/topics/16256</guid>
    </item>
    <item>
      <title>[北京] 哈佛大牛创业团队诚觅运维工程师！时间灵活 + 项目自决 + 可以参与开发 </title>
      <description>&lt;p&gt;&lt;strong&gt;与哈佛、杜克、北大、清华…等各路大牛一起，用互联网思维改变中国农村教育！阳光书屋等你加入！&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;深度报道请见 36kr：&lt;a href="http://www.36kr.com/p/204747.html" rel="nofollow" target="_blank"&gt;http://www.36kr.com/p/204747.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;极客公园：&lt;a href="http://www.geekpark.net/read/view/182995" rel="nofollow" target="_blank"&gt;http://www.geekpark.net/read/view/182995&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;我们还处在创业初期，正在进行商业化转型，所以未来 3 个月内暂时无法提供很高的薪水（当然足够你舒服地活着）。但是你的每一点工作我们都会记得，公司发展得越好，你的能力提升得越快，薪酬也会越高，并且会在合适的时候以奖金形式弥补之前低薪酬的阶段。如果你看重的是短期回报，感谢你读到现在。如果你更看重长期回报和个人成长，请继续往下看职位描述并和我们打个招呼吧！一个绝不会让你失望的优秀团队在期待着你！&lt;/p&gt;

&lt;p&gt;如果你个人认为不是合适但是认识可能合适的朋友，那么也不妨把我们推荐给他 or 她（大概不可能有吧……）或者把他 or 她推荐给我们：hr@sunshine-library.org&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/60b0412f8a9fa814a7b405be205b33f2.jpg" title="" alt=""&gt;&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/bffa497bf3bd1284ec9b7e541384ab69.jpg" title="" alt=""&gt;&lt;/p&gt;

&lt;hr&gt;
&lt;h2 id="运维开发工程师"&gt;运维开发工程师&lt;/h2&gt;&lt;h3 id="职位描述"&gt;职位描述&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;实现自动化部署阳光书屋开发的各项分布式网络服务&lt;/li&gt;
&lt;li&gt;监控并维护阳光书屋分布在各学校的网络设备与服务器&lt;/li&gt;
&lt;li&gt;参与开发后台网络服务&lt;/li&gt;
&lt;li&gt;作为技术部的对外服务接口，培训其他部门和驻校项目团队并提供技术支持&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="Perks"&gt;Perks&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;时间灵活：没有固定上下班时间（当然咯关键时刻需要你顶上！：）&lt;/li&gt;
&lt;li&gt;项目自决：如果愿意，自己决定工作优先级和自动化脚本内容，做自己认为最重要的事情&lt;/li&gt;
&lt;li&gt;开发运维并重：运维任务不那么重的时候（我们服务器不多），尽可能参与软件功能的开发！&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="职位要求"&gt;职位要求&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;熟悉在 Linux 上编译，安装与部署集群服务&lt;/li&gt;
&lt;li&gt;熟悉 MySQL 服务器维护和优化&lt;/li&gt;
&lt;li&gt;熟练使用脚本语言编写脚本，如 Shell, Ruby 及 Python&lt;/li&gt;
&lt;li&gt;部署过一些常用网络服务，如 Nginx, HAProxy, Redis&lt;/li&gt;
&lt;li&gt;具备优秀的沟通能力和极强的责任心，享受帮助别人解决问题的乐趣&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="优先条件"&gt;优先条件&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;有网络后台开发经验&lt;/li&gt;
&lt;li&gt;有部署维护 IOS 网络设备经验&lt;/li&gt;
&lt;li&gt;使用过 NoSQL 数据库，如 MongoDB, Cassandra&lt;/li&gt;
&lt;li&gt;使用过集群管理工具，如 Puppet, Chef&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="薪酬"&gt;薪酬&lt;/h3&gt;
&lt;p&gt;面议，根据实际工作能力和经验&lt;/p&gt;

&lt;p&gt;申请鼓励点击链接：&lt;a href="http://www.sunshine-library.org/the-team/joinus/" rel="nofollow" target="_blank"&gt;http://www.sunshine-library.org/the-team/joinus/&lt;/a&gt;
或者发送简历到：hr@sunshine-library.org&lt;/p&gt;</description>
      <author>mvj3</author>
      <pubDate>Thu, 26 Sep 2013 18:34:08 +0800</pubDate>
      <link>https://ruby-china.org/topics/14411</link>
      <guid>https://ruby-china.org/topics/14411</guid>
    </item>
    <item>
      <title>一个人的"Github"</title>
      <description>&lt;p&gt;Github 不是一个人做的，三个核心创始人在创业时都是写代码的，其中两个人作为程序员也十分有名，是不少有名开源项目的作者。对比这个星球上其他伟大的 IT 公司，Github 网站的代码是能开源就尽量开源的，包括操作 Git 的 grit，用作消息队列的 resque，等。&lt;/p&gt;

&lt;p&gt;Github 自然不是我做的，但作为一个自诩有好品味的程序员，我在努力向 Github 学习和实践它的精神和有益的工作方式，我要构建一个自己的”github”，在此也感谢我所处的公司 eoe 能给我自己去选择技术架构和工作进度这样相对灵活的工作方式的机 Github 不是一个人做的，三个核心创始人在创业时都是写代码的，其中两个人作为程序员也十分有名，是不少有名开源项目的作者。对比这个星球上其他伟大的 IT 公司，Github 网站的代码是能开源就尽量开源的，包括操作 Git 的 grit，用作消息队列的 resque，等。Github 自然不是我做的，但作为一个自诩有好品味的程序员，我在努力向 Github 学习和实践它的精神和有益的工作方式，我要构建一个自己的"github"，在此也感谢我所处的公司 eoe 能给我自己去选择技术架构和工作进度这样相对灵活的工作方式的机会。&lt;/p&gt;
&lt;h2 id="缘起"&gt;缘起&lt;/h2&gt;
&lt;p&gt;今年上半年我的主要工作内容是负责一个专注在线学习编程的单页面应用网站的技术部分。从缘起来说，eoe 本身主要是做以 Android 为主的移动开发者服务的，应用市场，移动应用 SDK 统计，开发者大会活动等都有涉猎，正式的尝试进入 IT 培训从去年 2012 年中就开始了（当然想法会更早些）。&lt;/p&gt;

&lt;p&gt;当时 CEO @靳岩 让我调研公司进入类似 codecademy.com 在线编程领域方案的可能性，这对于当时刚做完&lt;a href="http://mvj3.github.io/2012/11/01/android_eoemarket_data_collect_and_analysis_system_summary" rel="nofollow" target="_blank" title=""&gt;优亿市场应用海量下载统计分析&lt;/a&gt; 的算法与数据挖掘工程师无疑是一个很刺激的技术点。codecademy, codeschool 等这些国外在线编程网站毫无意外的展示了他们的创新性，codecademy 既支持 JavaScript, HTML, CSS 这些浏览器本身就提供编程环境的技术，也提供相对初级的 Ruby, Python 等后端语言在浏览器的模拟实现，他们用的相关技术包括用 LLVM 把代码编译成 JavaScript 执行的编译器 Emscripten。codeschool 里有个 &lt;a href="http://code.eoe.cn/67" rel="nofollow" target="_blank" title=""&gt;很有意思的地方&lt;/a&gt; 就是，它支持在浏览器里按照他们的规则去用 Objective-C 写 iOS 程序，编译是在服务器进行的，并通过 base64 编码不断传回截图，然后模拟成仿佛浏览器真的成了完美的 IDE 一样，包括编译信息和出错栈。对于我们要实现在浏览器里用 Java 编写 Android 程序，一般方案是采用传送到服务器编译执行，但是这样涉及到复杂的沙盒模型，且对服务器端资源消耗过大。我知道有一家真的实现了，他们前端用的是 flash 技术，但是这个只能针对简单快速编译的项目，而且我觉得这个脱离了要教会对方学习的本质，因为以后的实际演练肯定是在 Eclipse 等 IDE 里进行的，而你的浏览器在现有技术情况下肯定无法全部模拟。后来我也想到了可以以 IDE 插件的形式解决把线下教学搬到线上的基本构思，技术难度降低一半，这是后话。在教学中三环节 &lt;code&gt;教问练&lt;/code&gt; 中，真正把教和练做好的公司大概就这几家了，问的话去是程序员都上的 stackoverflow 等网站就好了。&lt;/p&gt;

&lt;p&gt;去年下半年做了偏前端的 &lt;a href="http://skill.eoe.cn" rel="nofollow" target="_blank" title=""&gt;技能测评&lt;/a&gt;，和偏后端的 &lt;a href="http://code.eoe.cn" rel="nofollow" target="_blank" title=""&gt;gist.github.com 克隆网站&lt;/a&gt; 。前者算基本没用过，后者不温不火，这让我明白了一个道理，如果我仅仅沉迷于技术实现，自己却无法分身去从事数种自己不熟悉或不太愿意实际执行的工作，那么它的命运就完全取决于组织的决定，因为一个真实产品的成长它需要不同职责的人的参与。前段时间听 &lt;a href="/teahour" class="user-mention" title="@teahour"&gt;&lt;i&gt;@&lt;/i&gt;teahour&lt;/a&gt; 的一期 &lt;a href="http://teahour.fm/2013/07/15/lean-startup-with-knewone.html" rel="nofollow" target="_blank" title=""&gt;和 knewone 的李路聊聊技术和精益创业&lt;/a&gt; 也聊到类似的情况，很有共鸣。&lt;/p&gt;

&lt;p&gt;而公司在这半年也陆续做了些小规模的 Android 培训。今年 2013 春节后，正式开启线上教育项目，产品设计由 &lt;a href="/iceskysl" class="user-mention" title="@iceskysl"&gt;&lt;i&gt;@&lt;/i&gt;iceskysl&lt;/a&gt; 主导和驱动，我开始做聊天技术的预演，内容运营部门则调动内外部资源继续制作教程内容。&lt;/p&gt;
&lt;h2 id="研发"&gt;研发&lt;/h2&gt;
&lt;p&gt;单页面学习应用 learn.eoe.cn 和 报名支付宣传 xuexie.eoe.cn 及后台管理的整体开发上线共历时大概三四个月，我负责的是 learn.eoe.cn（一位前端同事负责写 CSS），其他的都是 php 项目组负责实施。&lt;/p&gt;

&lt;p&gt;当 &lt;a href="/iceskysl" class="user-mention" title="@iceskysl"&gt;&lt;i&gt;@&lt;/i&gt;iceskysl&lt;/a&gt; 设计好产品基本原型后，确认学习过程中为单页面应用，因为里面的聊天，问答，考试等的一些操作应该是尽量避免重载页面的。我自告奋勇去设计了学习系统的数据库设计，基本思想上按模块做命名空间切分，课程大纲设计为一个课程包含多个课时，一个课时包含多个小节，小节可以为视频，资料，测评等多种类型，这是内容部分。对应的学生数据则是一个学习数据表绑定一个课程，并关联观看视频监控记录，考试记录，和计时等。这期间，项目组内关于数据结构，或者说课程具体的产品设计需求，经过多次讨论，终于达成思路上的一致。&lt;/p&gt;

&lt;p&gt;以下是现在上线后测试服务器里学习页面的多个模块的截图。
&lt;img src="http://mvj3.github.io/images/one-man-github/learn_video.png" title="" alt="learn_video"&gt;
&lt;img src="http://mvj3.github.io/images/one-man-github/learn_qa.png" title="" alt="learn_qa"&gt;
&lt;img src="http://mvj3.github.io/images/one-man-github/learn_exam.png" title="" alt="learn_exam"&gt;&lt;/p&gt;

&lt;p&gt;我对架构设计的原则是技术模块化，业务流程化，两者互相解耦。&lt;/p&gt;
&lt;h3 id="业务流程化"&gt;业务流程化&lt;/h3&gt;
&lt;p&gt;对于一个学生来说，TA 面对的主体是课程和 TA 的学习数据，其他都是依附于其之上。&lt;/p&gt;

&lt;p&gt;对于内容管理人员来说，课程是标准的层级关联，视频和其他也只是依附于其之上。&lt;/p&gt;

&lt;p&gt;对于我作为学习页面的技术负责人来说，用户是否付款和加入某个班级只是一个是非状态。用户的学习状态依赖于业务需求，可能需要结合多个数据源做操作判断，比如是否可以测评要保证你起码观看过教学视频及教学资料，是否学习完成也依赖于你对该课程所有课时的学习状态。&lt;/p&gt;
&lt;h3 id="技术模块化"&gt;技术模块化&lt;/h3&gt;
&lt;p&gt;想清楚好以上清晰的业务流程骨架后，我开始本人 4 年技术生涯里最彻底的模块拆解，并开源出十多个模块。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;跨子域名用户登陆&lt;/strong&gt;，用的是 PHP 写的单点登陆解决方案 UCenter，我整理了 &lt;a href="/iceskysl" class="user-mention" title="@iceskysl"&gt;&lt;i&gt;@&lt;/i&gt;iceskysl&lt;/a&gt; 从 PHP 改写的 Ruby 代码，并&lt;a href="https://github.com/eoecn/ucenter_authcode" rel="nofollow" target="_blank" title=""&gt;开源&lt;/a&gt;出来。在应用时，有次遇到误把对方一个每次都变的 cookies 作为这边的唯一身份认证，这个在单域名操作体现不出来，而访问多个子域名后这边 session 就失效了。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;视频播放&lt;/strong&gt;用的 &lt;a href="http://www.videojs.com" rel="nofollow" target="_blank" title=""&gt;VIDEO.JS&lt;/a&gt; 框架，不需要太多配置代码。另外我想了个开源的&lt;a href="https://github.com/eoecn/videojs_user_track" rel="nofollow" target="_blank" title=""&gt;视频监控的方案&lt;/a&gt;，就是把用户对不同时间段的观看频次对应的以秒为单位的数组里，播放一次是 1, 最大是 9，以此观察视频具体效果，和单个学生的学习疑点。从最近遇到的一个 BUG 来看，浏览器缓存了视频，但是网络是随时可断的，导致某些网络不太稳定的用户的监控数据可能是部分缺失的。所以监控数据还是得与业务逻辑彻底分开的，前者只应该作为业务判断参考之一。（有人可能会提到放在 cookie 里，但是其最大长度是 4K，那么一个小时的视频 &lt;code&gt;1*2*3600=7200&lt;/code&gt; 就放不下了）。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;参考资料&lt;/strong&gt;用的是 markdown 编辑和渲染，我抽取了 ruby-china 的 markdown 渲染代码，并 &lt;a href="https://github.com/eoecn/markdown-ruby-china" rel="nofollow" target="_blank" title=""&gt;自动识别程序语言，文件名，别名等多种格式&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;问答讨论&lt;/strong&gt;是个太标准的 CRUD 应用，一个论坛无非是主题和回复，里面显示的用户名和头像其实都是可以在前端用 JavaScript 去组装的， &lt;a href="http://mvj3.github.io/2013/05/28/fix-backbones-view-duplicated-events-bind/" rel="nofollow" target="_blank" title=""&gt;用 Backbones 这个 Javascript MVC 框架实现模版和事件绑定&lt;/a&gt;  ，添加完数据表后，直接用一个 Rails Helper 配置下即可，我把它取名为 &lt;a href="https://github.com/eoecn/qa-rails" rel="nofollow" target="_blank" title=""&gt;qa-rails&lt;/a&gt; 。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;测评&lt;/strong&gt;是个相对独立的业务，鉴于去年做过差不多的，这次实现更加精炼了些，JavaScript 239 行，HAML 两个模版 60 行。这块限于业务特殊无法作到开源。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;班级讨论&lt;/strong&gt;是基于 &lt;a href="https://github.com/faye/faye" rel="nofollow" target="_blank" title=""&gt;Faye 消息订阅发布系统&lt;/a&gt; 做的，并实现了 &lt;a href="https://github.com/eoecn/faye-online" rel="nofollow" target="_blank" title=""&gt;在线用户显示和计时&lt;/a&gt;，原理是绑定了 Faye 提供用户登入和登出的事件接口。这里要特别感谢我们的一个女产品 (条理清晰的黑盒测试)，是她用心的测试出了有这个用户的电脑非正常关闭浏览器造成服务器端一直在计时的错误。Faye 检测用户退出有两种方法，一种是服务器端的 EventMachine 定期检测 client 是否失去连接；另一种是客户端在浏览器关闭前发送 disconnect 请求 (对应的配置选项是 autodisconnect)，如果正常关闭那是 ok 的，但是如果用户取消关闭，那么这个 faye client 就死掉了，也就无法聊天，更新在线用户和计时。然后我想到了一种方案是，就是关闭 autodisconnect，把这个事件改为发送让服务器三秒后才去检测这个 client 是否继续存活的请求，这样无论浏览器是否关掉，服务器 都照样主动检测。聊天室的弊端在于它的特点是需要中央服务器，无法支持过大的聊天室，这里暗示的一个信息是系统架构是可以按聊天室拆分做负载均衡的。&lt;/p&gt;

&lt;p&gt;上面说的大部分都是从前端角度分析的，现在来说说后端。&lt;/p&gt;

&lt;p&gt;随着项目不断迭代，我发现几乎大部分操作都直接绑定到用户学习状态表 LearnIssue 了，关联的课时和学习状态，每门课时对应的视频观看数据和考试信息都是代理过去，这样逻辑相对还是很清晰的。&lt;/p&gt;

&lt;p&gt;在写单页面应用时，虽然像问答和聊天都独立出去用 JavaScript 载入了，但是还是需要同时载入几十个变量。&lt;a href="http://ruby-china.org/topics/12477" title=""&gt;一般人都会反应为什么不整合到 Model 里去呢&lt;/a&gt; ，原因是我还把十多个数据合法验证加入到 Controller 里去了，这里包括后台人员录入的数据不规范和用户访问权限等，出错方式是给出带参数说明的 &lt;code&gt;redirect_to&lt;/code&gt; URL，比如 &lt;code&gt;?reason=course_invalid&lt;/code&gt; ，这样后台可以随时调整并在前端验证。在调整业务的时候，我经常要去调整变量位置，所以就写了类似 rake 步骤依赖的 &lt;a href="http://github.com/eoecn/stepstepstep" rel="nofollow" target="_blank" title=""&gt;stepstepstep.gem&lt;/a&gt; 去生成自动排序执行的 14 个 before_filters，里面涉及一个图论算法。&lt;/p&gt;

&lt;p&gt;这个项目一个很大的特色之一是对 JSON 的运用，比如学习状态，课程信息等。大部分是直接用 &lt;a href="https://github.com/bdurand/json_record/" rel="nofollow" target="_blank" title=""&gt;json_record&lt;/a&gt; 配置的，效果等同于 Mongodb 文档存储（当然副作用是不能直接用 SQL 做字段本身的操作了），但是运维只需面对 MySQL 即可。我把项目设计成基本都是单表操作，现在一个学习页面的载入包含着近 50 条 SQL 查询，而响应时间却都还在 300ms 左右。&lt;/p&gt;

&lt;p&gt;最后为了给大家一个相对直观的项目复杂度的理解，我运行 &lt;code&gt;bundle exec rake stats&lt;/code&gt; 对 Ruby 源码情况做了简单统计，并对比由牛人 &lt;a href="/huacnlee" class="user-mention" title="@huacnlee"&gt;&lt;i&gt;@&lt;/i&gt;huacnlee&lt;/a&gt; 主导开发的 Ruby China 专业社区论坛。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;learn.eoe.cn
+----------------------+-------+-------+---------+---------+-----+-------+
| Name                 | Lines |   LOC | Classes | Methods | M/C | LOC/M |
+----------------------+-------+-------+---------+---------+-----+-------+
| Controllers          |   558 |   356 |       9 |      24 |   2 |    12 |
| Helpers              |    26 |    19 |       0 |       4 |   0 |     2 |
| Models               |   690 |   529 |      17 |      54 |   3 |     7 |
| Libraries            |   114 |    86 |       1 |       2 |   2 |    41 |
| Integration tests    |     0 |     0 |       0 |       0 |   0 |     0 |
| Functional tests     |    11 |     6 |       2 |       0 |   0 |     0 |
| Unit tests           |     8 |     6 |       2 |       0 |   0 |     0 |
+----------------------+-------+-------+---------+---------+-----+-------+
| Total                |  1407 |  1002 |      31 |      84 |   2 |     9 |
+----------------------+-------+-------+---------+---------+-----+-------+
  Code LOC: 990     Test LOC: 12     Code to Test Ratio: 1:0.0

ruby-china
+----------------------+-------+-------+---------+---------+-----+-------+
| Name                 | Lines |   LOC | Classes | Methods | M/C | LOC/M |
+----------------------+-------+-------+---------+---------+-----+-------+
| Controllers          |  1587 |  1251 |      32 |     182 |   5 |     4 |
| Helpers              |   365 |   301 |       0 |      41 |   0 |     5 |
| Models               |  1542 |  1166 |      24 |     106 |   4 |     9 |
| Mailers              |    18 |    15 |       2 |       1 |   0 |    13 |
| Javascripts          |  6908 |  5006 |       1 |     546 | 546 |     7 |
| Libraries            |   552 |   411 |       6 |      41 |   6 |     8 |
| Api specs            |   171 |   148 |       0 |       2 |   0 |    72 |
| Cell specs           |   127 |   106 |       0 |       0 |   0 |     0 |
| Controller specs     |   678 |   572 |       0 |       0 |   0 |     0 |
| Helper specs         |   364 |   290 |       0 |       0 |   0 |     0 |
| Lib specs            |   229 |   173 |       0 |       0 |   0 |     0 |
| Model specs          |  1034 |   859 |       3 |       0 |   0 |     0 |
| Request specs        |    40 |    33 |       0 |       0 |   0 |     0 |
| Routing specs        |    58 |    43 |       0 |       0 |   0 |     0 |
| View specs           |    34 |    26 |       0 |       0 |   0 |     0 |
+----------------------+-------+-------+---------+---------+-----+-------+
| Total                | 13707 | 10400 |      68 |     919 |  13 |     9 |
+----------------------+-------+-------+---------+---------+-----+-------+
  Code LOC: 8150     Test LOC: 2250     Code to Test Ratio: 1:0.3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;假设代码质量和风格差不多的话，从代码量来说 learn.eoe.cn 主体 Ruby 部分的复杂度是 ruby-china.org 的三分之一（从 Models 和 Controllers 占比来说也是差不多的），对于一个单页应用来说这差不多了。唯一的区别是 learn.eoe.cn 的控制器方法行数比 ruby-china.org 大三倍，这和业务逻辑更加复杂有关。（Ruby China 得排除基本都是外部静态 js 的这 6908 行统计数据。）&lt;/p&gt;

&lt;p&gt;另外上午我写了一段 Ruby 脚本来统计 &lt;a href="https://gist.github.com/mvj3/6149713" rel="nofollow" target="_blank" title=""&gt;learn.eoe.cn Rails 项目及其开源项目源码行数&lt;/a&gt; ，结果为：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[rails_engine_eoe]  Ruby:884 | JavaScript:15 | HAML:0
[ucenter_authcode]  Ruby:78 | JavaScript:0 | HAML:0
[rack_image_assets_cache_control]  Ruby:28 | JavaScript:0 | HAML:0
[faye-online]  Ruby:678 | JavaScript:52 | HAML:0
[qa-rails]  Ruby:259 | JavaScript:280 | HAML:183
[videojs_user_track]  Ruby:140 | JavaScript:84 | HAML:0
[stepstepstep]  Ruby:271 | JavaScript:0 | HAML:0
[cross_time_calculation]  Ruby:143 | JavaScript:0 | HAML:0
[/Users/mvj3/eoemobile/code/learn]  Ruby:4113 | JavaScript:1108 | HAML:517

[total] Ruby:6721 | JavaScript:1539 | HAML:700
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以看到 Ruby 和 JavaScript 有三分之一左右是开源的，Ruby 更多些。另外一个数据是 git 提交日志， &lt;code&gt;1,347 commits / 21,477 ++ / 12,354 --&lt;/code&gt; 。&lt;/p&gt;

&lt;p&gt;这项目最大的遗憾就是没有测试，和互联网创业产品风格及资源配备等都很有关系，不过抽取的外部库比较重要或重逻辑的地方都写了必要的测试了。&lt;/p&gt;

&lt;p&gt;注明：本文仅代表个人观点，与实际所涉公司无关。&lt;/p&gt;
&lt;h4 id="原始地址在: http://mvj3.github.io/2013/08/04/a-man-github/"&gt;原始地址在：&lt;a href="http://mvj3.github.io/2013/08/04/a-man-github/" rel="nofollow" target="_blank"&gt;http://mvj3.github.io/2013/08/04/a-man-github/&lt;/a&gt;
&lt;/h4&gt;</description>
      <author>mvj3</author>
      <pubDate>Tue, 06 Aug 2013 09:25:26 +0800</pubDate>
      <link>https://ruby-china.org/topics/13084</link>
      <guid>https://ruby-china.org/topics/13084</guid>
    </item>
    <item>
      <title>DSL for defining before_filters's dependencies like rake tasks</title>
      <description>&lt;p&gt;Rails before_filters don't take it far enough. What stepstepstep allows you to do is define before_filters's dependecies in the same way you do with rake tasks.&lt;/p&gt;
&lt;h2 id="Install"&gt;Install&lt;/h2&gt;
&lt;p&gt;Stick this in your Gemfile.&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'stepstepstep'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="Usage"&gt;Usage&lt;/h2&gt;&lt;h4 id="Include the DSL &amp;amp;&amp;amp; Defining steps"&gt;Include the DSL &amp;amp;&amp;amp; Defining steps&lt;/h4&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FooController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Stepstepstep&lt;/span&gt;

  &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="ss"&gt;:two&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:one_point_three&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:one_point_seven&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="vi"&gt;@a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="ss"&gt;:one_point_three&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:one&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="vi"&gt;@a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;1.3&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="ss"&gt;:one&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="vi"&gt;@a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="ss"&gt;:one_point_seven&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:one_point_three&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:only&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:index&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="vi"&gt;@a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;1.7&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
    &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:inline&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="vi"&gt;@a.inspect&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; [1, 1.3, 1.7, 2].inspect&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;another&lt;/span&gt;
    &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:inline&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="vi"&gt;@a.inspect&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; [1, 1.3, 2].inspect&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="Why does stepstepstep.gem exists?"&gt;Why does stepstepstep.gem exists?&lt;/h2&gt;
&lt;p&gt;A few months ago, I was writing a single page application about learning mobile development technology at &lt;a href="http://learn.eoe.cn" rel="nofollow" target="_blank"&gt;http://learn.eoe.cn&lt;/a&gt;. This page contains lessons, a video, classes, teachers, students, reference material, question-to-answers, exams, chat messages, and their current all learning statuses and dependencies. In brief, there are fifteen steps to load this page, including privileges to judge, fourteen illegal &lt;code&gt;redirect_to&lt;/code&gt; , etc. So I need to write a step dependencies management tool, like rake tasks.&lt;/p&gt;

&lt;p&gt;At first, I thought maybe I could define several &lt;code&gt;proc&lt;/code&gt;s in a single before_filter, but the execution context is really complicated. Then one day, I found action_jackson.gem, which was written by &lt;a href="https://github.com/blakefrost/action_jackson" rel="nofollow" target="_blank" title=""&gt;Blake Taylor&lt;/a&gt; two years ago. The core implementation of this gem is to define each action as a method, and at last call a class method &lt;code&gt;register_filters&lt;/code&gt; to register all these methods as &lt;code&gt;before_filter&lt;/code&gt; independently. Of course, they're ordered by the earlier declarations. This implementation is not elegant, but the idea is really awesome, it doesn't break Rails's rules.&lt;/p&gt;

&lt;p&gt;Then I got a deep understanding of the Rails controllers filters's implementation mechanism. Maybe &lt;code&gt;skip_before_filter&lt;/code&gt; helped. In each &lt;code&gt;step&lt;/code&gt;, I insert it first, extract all the inserted steps by &lt;code&gt;skip_before_filter&lt;/code&gt;, then sort them by TSort(a topological sorting algorithm provided by Ruby standard library), and at last append them again to before_filters. It works, and all rspecs are passed.&lt;/p&gt;

&lt;p&gt;I renamed it from action_jackson to stepstepstep, because the DSL is only a &lt;code&gt;step&lt;/code&gt; class method, which handles all the details. Most of the implementations were rewritten, and I added rspecs . Thanks Blake Taylor :)&lt;/p&gt;

&lt;p&gt;项目地址： &lt;a href="https://github.com/eoecn/stepstepstep" rel="nofollow" target="_blank"&gt;https://github.com/eoecn/stepstepstep&lt;/a&gt;&lt;/p&gt;</description>
      <author>mvj3</author>
      <pubDate>Sat, 13 Jul 2013 14:49:02 +0800</pubDate>
      <link>https://ruby-china.org/topics/12477</link>
      <guid>https://ruby-china.org/topics/12477</guid>
    </item>
    <item>
      <title>Faye Online.gem 0.1 发布了， 实时监控各 Channel 的在线用户和时长</title>
      <description>&lt;p&gt;上周六在 北京 2013 年 06 月 22 日 RubySaturday &lt;a href="http://ruby-china.org/topics/11806" rel="nofollow" target="_blank"&gt;http://ruby-china.org/topics/11806&lt;/a&gt; 上分享的十多个 gem 里介绍了一下，这两天整理了发布到 rubygems.org 了。&lt;/p&gt;

&lt;p&gt;地址:
&lt;a href="https://github.com/eoecn/faye-online/tree/eoecn" rel="nofollow" target="_blank"&gt;https://github.com/eoecn/faye-online/tree/eoecn&lt;/a&gt;
&lt;a href="http://rubygems.org/gems/faye-online" rel="nofollow" target="_blank"&gt;http://rubygems.org/gems/faye-online&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;具体使用方法，数据结构存储，原理，技术细节等 请看 README。&lt;/p&gt;

&lt;p&gt;TODO 列表上还有一些要做的，欢迎大家一起来完善吧&lt;/p&gt;</description>
      <author>mvj3</author>
      <pubDate>Wed, 26 Jun 2013 11:57:45 +0800</pubDate>
      <link>https://ruby-china.org/topics/12003</link>
      <guid>https://ruby-china.org/topics/12003</guid>
    </item>
    <item>
      <title>3-15 个字符，可以用 [a-z0-9_\-] 字符，必须用数字或者字母开头，且不能是纯数字</title>
      <description>&lt;pre class="highlight ruby"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# encoding: UTF-8&lt;/span&gt;
&lt;span class="c1"&gt;# 老大提了个用单个正则表达式来匹配个性域名ID的需求，具体是：3-15个字符，可以用[a-z0-9_\-]字符，必须用数字或者字母开头，且不能是纯数字&lt;/span&gt;

&lt;span class="c1"&gt;# 让我们来分步化解&lt;/span&gt;
&lt;span class="c1"&gt;# 对于，3-15个字符，可以用[a-z0-9_\-]字符，稍微了解点正则表达式的同学马上就可以写出如下正则&lt;/span&gt;
&lt;span class="sr"&gt;/^[a-z0-9_\-]{3,15}$/i&lt;/span&gt;

&lt;span class="c1"&gt;# 让我们来再加一个条件，必须用数字或者字母开头&lt;/span&gt;
&lt;span class="sr"&gt;/^[0-9a-z][a-z0-9_\-]{2,14}$/i&lt;/span&gt;

&lt;span class="c1"&gt;# 最后一个条件是，且不能是纯数字。&lt;/span&gt;
&lt;span class="c1"&gt;# 最初我大概的想到是用 或(|) 来做，一个是数字开头，另一个是字母开头，剩余的是否纯数字在后面判断。但这剩余里还是会遇到判断在哪个位置里已经出现了字母的问题。所以这里就需要正则表达式里非匹配获取的功能了。&lt;/span&gt;

&lt;span class="c1"&gt;# 维基百科里给出的是 (?=pattern) ，它表示 匹配pattern但不获取匹配结果，也就是说这是一个非获取匹配，不进行存储供以后使用。这在使用或字符「(|)」来组合一个模式的各个部分是很有用。例如「industr(?:y|ies)」就是一个比「industry|industries」更简略的表达式。具体见 http://zh.wikipedia.org/wiki/正则表达式&lt;/span&gt;

&lt;span class="c1"&gt;# stackoverflow里有更通俗的例子 http://stackoverflow.com/questions/1559751/regex-to-make-sure-that-the-string-contains-at-least-one-lower-case-char-upper&lt;/span&gt;
&lt;span class="c1"&gt;# ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*(_|[^\w])).+$&lt;/span&gt;
&lt;span class="c1"&gt;# A short explanation:&lt;/span&gt;
&lt;span class="c1"&gt;# ^                  // the start of the string&lt;/span&gt;
&lt;span class="c1"&gt;# (?=.*[a-z])        // use positive look ahead to see if at least one lower case letter exists&lt;/span&gt;
&lt;span class="c1"&gt;# (?=.*[A-Z])        // use positive look ahead to see if at least one upper case letter exists&lt;/span&gt;
&lt;span class="c1"&gt;# (?=.*\d)           // use positive look ahead to see if at least one digit exists&lt;/span&gt;
&lt;span class="c1"&gt;# (?=.*[_\W])        // use positive look ahead to see if at least one underscore or non-word character exists&lt;/span&gt;
&lt;span class="c1"&gt;# .+                 // gobble up the entire string&lt;/span&gt;
&lt;span class="c1"&gt;# $                  // the end of the string&lt;/span&gt;

&lt;span class="c1"&gt;# 这样我们就在 /^[0-9a-z][a-z0-9_-]{2,14}$/i 里再加上个 (?=.*[a-z_\-]) 就可以匹配不是纯数字了&lt;/span&gt;
&lt;span class="vi"&gt;@regexp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/^(?=.*[a-z_\-])[0-9a-z][a-z0-9_\-]{2,14}$/i&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"合法测试"&lt;/span&gt;
&lt;span class="sx"&gt;%w[c11213311 mvj3 123mmmmm iceskysl 3_3]&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;   =&amp;gt;   &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@regexp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"非法测试"&lt;/span&gt;
&lt;span class="sx"&gt;%w[123 12345 mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm _ssssss 你好]&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;   =&amp;gt;   &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@regexp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;'没有匹配'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;span class="c1"&gt;# 测试结果如下：&lt;/span&gt;
&lt;span class="cp"&gt;__END__
合法测试
c11213311   =&amp;gt;   c11213311
mvj3   =&amp;gt;   mvj3
123mmmmm   =&amp;gt;   123mmmmm
iceskysl   =&amp;gt;   iceskysl
3_3   =&amp;gt;   3_3

非法测试
123   =&amp;gt;   没有匹配
12345   =&amp;gt;   没有匹配
mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm   =&amp;gt;   没有匹配
_ssssss   =&amp;gt;   没有匹配
你好   =&amp;gt;   没有匹配
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;原发表在 &lt;a href="http://code.eoe.cn/83/title/3-15%E4%B8%AA%E5%AD%97%E7%AC%A6_%E5%8F%AF%E4%BB%A5%E7%94%A8_a-z0-9__-_%E5%AD%97%E7%AC%A6_%E5%BF%85%E9%A1%BB%E7%94%A8%E6%95%B0%E5%AD%97%E6%88%96%E8%80%85%E5%AD%97%E6%AF%8D%E5%BC%80%E5%A4%B4_%E4%B8%94%E4%B8%8D%E8%83%BD%E6%98%AF%E7%BA%AF%E6%95%B0%E5%AD%97" title=""&gt;http://code.eoe.cn/83&lt;/a&gt;&lt;/p&gt;</description>
      <author>mvj3</author>
      <pubDate>Sat, 26 Jan 2013 15:27:08 +0800</pubDate>
      <link>https://ruby-china.org/topics/8383</link>
      <guid>https://ruby-china.org/topics/8383</guid>
    </item>
    <item>
      <title>Codecademy 在线编程教学　发布 ruby 了</title>
      <description>&lt;p&gt;地址在：&lt;a href="http://www.codecademy.com/tracks/ruby-alpha" rel="nofollow" target="_blank"&gt;http://www.codecademy.com/tracks/ruby-alpha&lt;/a&gt;
版本是 1.9.3，通过和服务器端交互实现的。&lt;/p&gt;

&lt;p&gt;Codecademy 团队的 Amjad Masad 以前的作品有 &lt;a href="http://repl.it/" rel="nofollow" target="_blank"&gt;http://repl.it/&lt;/a&gt; ，实现的浏览器里运行 Ruby/Python，当然必须是跑在 Javascript VM 里的。&lt;/p&gt;</description>
      <author>mvj3</author>
      <pubDate>Fri, 28 Sep 2012 14:07:28 +0800</pubDate>
      <link>https://ruby-china.org/topics/5803</link>
      <guid>https://ruby-china.org/topics/5803</guid>
    </item>
    <item>
      <title>为了做大数据量统计分析的开发工作，如何准备本地数据？ </title>
      <description>&lt;p&gt;要对几十 G 的 MongoDB 数据做统计分析，如需跑对周月的 map/reduce 任务，本地开发的磁盘和 CPU 内存需求都是问题。&lt;/p&gt;

&lt;p&gt;最直观的做法是在服务器做一份测试数据，远程连接服务器用 vim/git 做开发。哪位有经验或建议分享？  &lt;/p&gt;</description>
      <author>mvj3</author>
      <pubDate>Thu, 02 Feb 2012 14:00:13 +0800</pubDate>
      <link>https://ruby-china.org/topics/1011</link>
      <guid>https://ruby-china.org/topics/1011</guid>
    </item>
    <item>
      <title>[北京] eoeMobile 招聘算法和数据挖掘工程师 (含实习)</title>
      <description>&lt;p&gt;职位描述：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;从事易联致远统计分析平台的技术开发，优化和维护工作&lt;/li&gt;
&lt;li&gt;参与易联致远旗下产品策划和产品用户行为分析&lt;/li&gt;
&lt;li&gt;提供易联致远旗下产品运营的技术支持&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;职位要求：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;了解常用算法和数据结构，及数据库实现原理&lt;/li&gt;
&lt;li&gt;逻辑分析能力强，富有责任心，善于主动沟通&lt;/li&gt;
&lt;li&gt;使用 OSX/Linux 处理日常事务达半年以上&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;优先条件：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;本科或本科以上计算机、数学、统计、物理或其他相关领域的训练&lt;/li&gt;
&lt;li&gt;有扎实的编程功底，有 Ruby 等动态语言的实际项目经验&lt;/li&gt;
&lt;li&gt;有数据挖掘推荐系统经验者&lt;/li&gt;
&lt;li&gt;对开源软件有特别兴趣，有钻研新技术的热情和能力&lt;/li&gt;
&lt;li&gt;较高的英文阅读能力&lt;/li&gt;
&lt;li&gt;iPhone/Android手机的活跃用户&lt;/li&gt;
&lt;li&gt;有 redis/mongodb 使用经验&lt;/li&gt;
&lt;li&gt;github 活跃用户&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;有意者请将简历发送至：chendawei@eoemobile.com，并提供一个你认为自己符合该职位的最有说服力的创作经历或理由。&lt;/p&gt;

&lt;p&gt;公司简介：&lt;/p&gt;

&lt;p&gt;eoeMobile 团队是一个有远大的梦想，有充沛的激情，有高效执行力的团队。北京易联致远无线技术有限公司于 2009 年 8 月成立。eoeMobile 致力于让移动互联网的软件开发变得容易，发布变得更加方便，传播变得更加迅捷，让用户以最快的速度获取最适合自己的移动互联网应用。eoeMobile 的核心成员有在哈票网、满座、盛拓传媒的工作经历和相关行业丰富经验.
目前 eoeMobile 专注于 Android 平台，运营国内最大的 Android 开发者社区 (eoeandroid.com) 和国内知名第三方 Android 应用商店 (eoeMarket.com)。 eoeMobile 给国内的 Android 开发者提供最专业的 Android 开发服务，给手机和 MID 厂商提供 Android 软件商店的解决方案和桌面主题平台的解决方案，目前已经有多家厂商采用由 eoeMobile 定制的解决方案。
公司福利： 社会保险（五险）； 年假、各类法定节假日、双休；  通讯补助、交通补助、免费工作餐、咖啡； 月度优秀员工奖金、生日礼金；  外出拓展训练；  多姿多彩的企业文化、聚餐等；  &lt;/p&gt;</description>
      <author>mvj3</author>
      <pubDate>Thu, 05 Jan 2012 10:00:33 +0800</pubDate>
      <link>https://ruby-china.org/topics/735</link>
      <guid>https://ruby-china.org/topics/735</guid>
    </item>
    <item>
      <title>错别字纠正</title>
      <description>&lt;p&gt;&lt;a href="http://ruby-china.org/wiki/gems" rel="nofollow" target="_blank"&gt;http://ruby-china.org/wiki/gems&lt;/a&gt;
居于 Shinx 的全文搜索组件。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://ruby-china.org/wiki/contributors" rel="nofollow" target="_blank"&gt;http://ruby-china.org/wiki/contributors&lt;/a&gt;
一下是本社区的贡献者名单，排名部分先后。&lt;/p&gt;

&lt;p&gt;PS: 期待可以收藏帖子：）  &lt;/p&gt;</description>
      <author>mvj3</author>
      <pubDate>Wed, 02 Nov 2011 13:58:09 +0800</pubDate>
      <link>https://ruby-china.org/topics/19</link>
      <guid>https://ruby-china.org/topics/19</guid>
    </item>
  </channel>
</rss>
