<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>Sound/Noise</title>
 <link href="https://blog.pzheng.me//atom.xml" rel="self"/>
 <link href="https://blog.pzheng.me//"/>
 <updated>2022-07-15T12:32:43+00:00</updated>
 <id>https://blog.pzheng.me/</id>
 <author>
   <name>pzheng</name>
   <email></email>
 </author>

 
 <entry>
   <title>Select Box Experience I</title>
   <link href="https://blog.pzheng.me//2016/09/07/select-box-experience-i/"/>
   <updated>2016-09-07T20:25:00+00:00</updated>
   <id>https://blog.pzheng.me//2016/09/07/select-box-experience-i</id>
   <content type="html">&lt;p&gt;前段时间做了个简单的页面应用，其中用到了&lt;a href=&quot;http://vuejs.org/&quot;&gt;Vue.js&lt;/a&gt;去实现几种不同的select box，一些要点记录如下。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Vue.js是一款轻量级的MVVM前端框架，使用Vue，一定程度就是忍受不了jQuery。但作为初学者，在前人用Bootstrap搭的网站上新增页面，本身已依赖大量jQuery的插件/组件，一时也无法全盘推翻。而Vue本身也并不像React，如选择它，就只能从一而终，且彻底抛弃其他框架。Vue可以和jQuery混搭使用，如不想重构，也可以work。后面有些功能，也不知道如何用Vue写，最后采用jQuery也能奏效。&lt;/p&gt;

&lt;p&gt;实现一个简单的单选框，HTML原生的方式如下(&lt;a href=&quot;https://jsfiddle.net/slownoise/dbbzgds9/&quot;&gt;jsfiddle&lt;/a&gt;)：&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;select&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;select2&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;option&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Ongoing&lt;span class=&quot;nt&quot;&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;option&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Released&lt;span class=&quot;nt&quot;&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;option&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;3&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Delay&lt;span class=&quot;nt&quot;&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;option&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;4&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Hold&lt;span class=&quot;nt&quot;&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果用Vue(&lt;a href=&quot;https://jsfiddle.net/slownoise/ajtc1v4w/&quot;&gt;jsfiddle&lt;/a&gt;)：&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;allStatus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Ongoing&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Released&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Delay&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Hold&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;editPlanApp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Vue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;#editPlanApp&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;allStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;allStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;HTML这样写：&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;editPlanApp&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;select&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;v-model=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;form-control&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;option&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;v-for=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;status in allStatus&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;v-bind:value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;status.id&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;你会发现使用Vue之后，代码量还增加了。Don’t worry，接下来我们对比一下如何获取已选项的value。&lt;/p&gt;

&lt;p&gt;使用jQuery的方式:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;.select2&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;select2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;使用Vue的方式：&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;editPlanApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;而通过程序更新所选项的话，jQuery的方式时，找到页面元素，设置选项，接着trigger更新页面：&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.select2&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;select2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,{&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Ongoing&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;change&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Vue的话，直接赋值，即可自动更新页面元素：&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;editPlanApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;是不是更简洁清爽了？一旦页面涉及到交互和计算，用MVVM的优势就展现出来了。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>「译」How We Release So Frequently</title>
   <link href="https://blog.pzheng.me//2016/02/21/translate-how-we-release-so-frequently/"/>
   <updated>2016-02-21T21:00:00+00:00</updated>
   <id>https://blog.pzheng.me//2016/02/21/translate-how-we-release-so-frequently</id>
   <content type="html">&lt;p&gt;这篇文章是&lt;a href=&quot;https://www.skybet.com/&quot;&gt;Sky Betting &amp;amp; Gaming&lt;/a&gt;网站的Principle Engineer Tom Hudson发在他们blog上的&lt;a href=&quot;http://engineering.skybettingandgaming.com/2016/02/02/how-we-release-so-frequently/&quot;&gt;技术文章&lt;/a&gt;，介绍他们是如何做到每天发布多次，以及这样做的好处。Sky Betting &amp;amp; Gaming是一家英国博彩网站，运行过程中涉及到大量的资金流转。对数据迁移以及资金安全等方面，都有较高要求。我们不一定要像他们一样每天发布多次，但其中的思想是值得学习和探讨的，比如数据库迁移和git的feature分支流程等。因此粗译出来分享给大家，欢迎指正。&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;how-we-release-so-frequently&quot;&gt;How We Release So Frequently&lt;/h2&gt;

&lt;p&gt;原文链接：&lt;a href=&quot;http://engineering.skybettingandgaming.com/2016/02/02/how-we-release-so-frequently/&quot;&gt;http://engineering.skybettingandgaming.com/2016/02/02/how-we-release-so-frequently/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;在Sky Betting &amp;amp; Gaming，我们每天会发布数次新版本的代码，同时并不暂停我们的服务。我们的生产环境体量很大，而且种类繁多。但我只想关注在我们那个类似LAMP的技术栈上如何发布（最新的）软件。说它“类似”是因为，虽然很多年前我们使用的是传统的LAMP栈。但随着需求增加，我们相应地，也增加了很多其他技术，比如redis，Node.js，MongoDB等。不过，它的核心部件，仍然是一些跑着Apache和mod_php的服务器，它们会跟各种数据库和API会话。&lt;/p&gt;

&lt;p&gt;我们的发布流程如下:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;构建发布包，并基于它进行测试；&lt;/li&gt;
  &lt;li&gt;拷贝这个发布包到一个NFS的共享服务器上去；&lt;/li&gt;
  &lt;li&gt;进行数据库迁移；&lt;/li&gt;
  &lt;li&gt;自动切换Apache docroot至新的包；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;只需点击Jenkins UI上的一个按钮，就可以在10分钟内完成上述所有动作。而这10分钟里，大部分都用在测试上了。我们有大量测试：unit tests, integration tests和full stack tests。每种测试都有各自的价值，所以每一种我们都有很多（用例）。如果串行执行，需要跑一个多小时。因此，我们将之分成小类，在十多个Jenkins slaves上并行执行。&lt;/p&gt;

&lt;p&gt;这些听起来都没什么新意，确实是因为也没什么新奇的东西。速度方面还有很多提升空间（Jenkins slaves数量会一直够吗？）。当然，更快的构建过程也可以让我们更频繁地发布。但这些，并不是故事的全部。&lt;/p&gt;

&lt;p&gt;我们之所以能如此频繁地发布，主要原因是&lt;strong&gt;约定&lt;/strong&gt;。&lt;/p&gt;

&lt;h3 id=&quot;仅前向迁移&quot;&gt;仅前向迁移&lt;/h3&gt;

&lt;p&gt;我们&lt;strong&gt;绝&lt;/strong&gt;不回滚数据库的迁移。技术上讲，我们可以。但至少四年了，我们都没有这个需求。这是因为我们做的每次数据库迁移，新生成的schema都可以兼容代码的前一个版本和新版本。如果我们不得不回滚我们的代码（有时确实需要这么干），前一个版本的代码也可以完美地使用数据库新的schema.&lt;/p&gt;

&lt;p&gt;实现它的并不是什么黑魔法，纯粹基于约定。以删除一列为例。我们如何发布这个改动？很简单：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;发布一版不使用那列数据的代码；确保它是稳定的，不会被回滚；&lt;/li&gt;
  &lt;li&gt;发布第二版，包含将该列移除的数据库迁移；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;就是这么简单。移除一张表也是相同的方法：先发布一个不使用它的版本，接着在下一个版本里移除这张表。&lt;/p&gt;

&lt;p&gt;也不是所有更新都这么简单。如果我们想重命名一列，我们需要：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;发布第一版。先添加新列，列名为新的名字。相应地更新代码，写数据库的地方需要两列都写，读数据库的地方只用读老的那一列；&lt;/li&gt;
  &lt;li&gt;执行一个批处理job，将老的那一列数据都复制到新的这一列。为了避免过多的locking，每次只复制一行；&lt;/li&gt;
  &lt;li&gt;接着发布第二版，读取和写入都是到新的这一列；&lt;/li&gt;
  &lt;li&gt;最后发布第三版，彻底移除老的那一列；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;三次独立的发布和一个批处理job，对于重命名一列来说，工作貌似有累赘。但我们并不经常重命名列，而且这么做让我们在发布回滚时更有自信（，所以也可以接受）。&lt;/p&gt;

&lt;h3 id=&quot;新代码--新功能&quot;&gt;新代码 != 新功能&lt;/h3&gt;

&lt;p&gt;除非是一次性能上显著的提升，用户不应注意到代码的发布。对用户来说，看到一个新功能出现，开始使用，几分钟后因为发布回滚（可能因为不相关的原因），功能又消失了，这绝对是一次糟糕的体验。&lt;/p&gt;

&lt;p&gt;我们每次新功能的发布，最初都处于隐藏状态，随时可以用一个“功能开关”触发开启。功能开关可以基于每个session来开启，这样就可以在用户看到它之前，在线上环境完整地测试。这种方式有几个流弊的优点：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;我们不需要只是因为某个新功能无法正常工作，就回滚整次发布（可能包含多个改动）；&lt;/li&gt;
  &lt;li&gt;我们可以在拥有完全一致的硬软件以及所需数据的环境里，完整地测试新功能；&lt;/li&gt;
  &lt;li&gt;我们可以逐步向用户发布新功能；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;最后这一点非常重要。如果我们不能保证一个新功能可以承受所有用户同时使用的压力时，可以先向少部分用户发布这个功能，然后监控它的性能。&lt;/p&gt;

&lt;p&gt;我们将每个新的session分配一个1到100之间的随机值，将它存在一个long-lived cookie里。接着用这个值来将所有sessions归到不同的分组里。比如，假设我们有：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;1-10: 有风险的新功能组；&lt;/li&gt;
  &lt;li&gt;11-100: 可控组；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这样，10%左右的sessions就会得到有风险的新功能，剩下的将没有任何变化。如果一切OK，我们就会将范围扩大到50%的session会得到这个新功能。最后，当我们对所有事情都非常有信心时，就可以推广到100%了。&lt;/p&gt;

&lt;p&gt;（这里有个问题，）对一个已存在的session来说，只露出部分新功能不是很和谐。所以我们用了另一个小技巧来消弭这种不和谐。在session开始时，不仅使用long-lived cookie保存随机值，我们也会用一个session cookie来将用户”粘到”定义好的分组里。&lt;/p&gt;

&lt;p&gt;如果session是全新的，那么我们将：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;分配一个随机值，并存在一个long-lived cookie;&lt;/li&gt;
  &lt;li&gt;检查这个随机值归属于哪些分组；&lt;/li&gt;
  &lt;li&gt;将那些分组信息保存在一个session cookie里；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在这个session里，所有后续的request，我们都将持续使用那些分组的规则。即使后来我们改变了新功能生效范围，导致那个随机值已经不属于之前的那些分组。一旦这个用户的session过期了，这个session cookie就会消失；因此所有以后的requests都会基于这个随机值的long-lived cookie来执行。除了不需要再分配新的随机值，这些使用随机值的long-lived cookie的requests，都会遵循前述相同的规则；&lt;/p&gt;

&lt;p&gt;这种方式的好处是，用户在一个session过程中，不会看到部分露出的新功能。而在他们后来新的session里，就会看到完整露出的新功能。&lt;/p&gt;

&lt;h3 id=&quot;小型发布&quot;&gt;小型发布&lt;/h3&gt;

&lt;p&gt;通过快速构建，大量测试，低风险的数据库迁移，以及和代码发布解耦合的功能更新，不仅能帮助我们快速地发布代码，也提供了一个非常有用的反馈环路：发布得越频繁，每次发布就可以越小。更小的发布带来更少的风险，也让我们能更频繁地发布代码。频繁的发布并不一定意味着小的发布–它依然需要一点约定。&lt;/p&gt;

&lt;p&gt;我们的开发通常是在git的feature分支上进行的，技术上讲，没什么能防范我们制造生存周期过长的feature 分支（这样的分支将导致大型，并随之高风险的发布）。这时需要的规范是，&lt;strong&gt;不要等到所有（功能）都完成了再发布，而应该在没有破坏（任何其他功能）时就发布&lt;/strong&gt;。这种做法最初可能会让人觉得不自然，但长期来看确实会减少开发人员的“发布焦虑”问题。&lt;/p&gt;

&lt;p&gt;当你开始更频繁地发布代码，随之而来的另一件事就是，你将更清晰地感受到发布流程里的小痛点。大部分人可能可以忍受一个月才执行一次的手动操作，但没多少人能忍受每天进行数次手动操作。那些之前你想暂且搁置一边的小问题，（在频繁发布过程中）将变成大烦恼，但这也是好事：大问题就会得到更高的优先级并会被修复。&lt;/p&gt;

&lt;p&gt;这看上去很明显，但更频繁地做某些事，确实是更好的改进它的一种方式。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>REST API for Xinyue App</title>
   <link href="https://blog.pzheng.me//2015/09/05/rest-api-for-xinyue-app/"/>
   <updated>2015-09-05T20:32:00+00:00</updated>
   <id>https://blog.pzheng.me//2015/09/05/rest-api-for-xinyue-app</id>
   <content type="html">&lt;p&gt;下面我将按照当初从一个idea到最终开发出一个app的过程，讲述一下其中遇到和解决的一些问题。首先是网站，即server端的，接口问题。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;最初，仅仅只是起意想为“&lt;a href=&quot;http://www.xinyue.in&quot;&gt;新月&lt;/a&gt;”网站做一枚配套的Android App。可心里着实没底，虽然有了&lt;a href=&quot;http://conn.pzheng.me&quot;&gt;Conn&lt;/a&gt;的一点点经验，仍然不知道如何下手。模模糊糊有个概念，是客户端需要去retrieve网站上的信息，然后展现在手机上。&lt;/p&gt;

&lt;p&gt;首先遇到的问题，就是需要一个接口，让客户端能获取网站信息。&lt;a href=&quot;http://www.xinyue.in&quot;&gt;新月&lt;/a&gt;网站是用Wordpress搭建的，是否有合适的插件实现接口的功能呢？如果没有，自己再做一个接口的程序，开发难度无疑将大大增加。本着Just Get It Work的原则，有现成的就不去再造轮子。先做了一些前期调查，了解到现在最流行的是RESTful API和SOAP等。REST相对来说更流行。在此之前，我可是对RESTful一窍不通。没过几个月，在学习Cloud资料的过程中，发现我们的产品中也应用到了REST（这不，你学的任何东西都不会白费，是吧？）。&lt;/p&gt;

&lt;p&gt;快速地选定REST类型的API之后，立即搜索Wordpress的插件库。没让我失望，好几款plugins都可以让Wordpress的网站瞬间拥有REST API。搜了一下网上的评论和各插件的文档，没费多少功夫，就选定了&lt;a href=&quot;http://v2.wp-api.org/&quot;&gt;WP REST API V2&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;安装之后当然是试用了。官方文档里说，要获取网站的posts，直接GET网站的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/wp-json/wp/v2/posts&lt;/code&gt;即可。但是，无论我在Chrome浏览器的Advanced Rest Client中，如何尝试去GET这个路径，都提示出错，返回的message是”No route was found matching the URL and request method”。明显路径不对(一定是我打开的方式有问题…)。后来无意中，用这个路径&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/wp-json/posts&lt;/code&gt;打开，发现竟然可以。啊哈，这感觉就像在黑暗的山洞里前行，终于看到前方貌似有一丝光亮了。&lt;/p&gt;

&lt;p&gt;因此，所有的接口route都基于这个网址来request的：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;http://www.yourwebsite.com/wp-json/posts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;App的前期开发（ContentProvider的实现），都是基于上面这个网址去实现的。到中后期，发现问题了：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;该网址只返回最近的10篇帖子，10篇以前的posts该如何获取？&lt;/li&gt;
  &lt;li&gt;在app的tab中，是以首饰的种类做区分的，如何通过REST API获取特定category的posts?&lt;/li&gt;
  &lt;li&gt;如何实现搜索？有相应的API吗？&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;查看了&lt;a href=&quot;http://wp-api.org/#posts_retrieve-posts&quot;&gt;官方文档&lt;/a&gt;后，发现有filter可以使用。而filter的参数，可以通过Wordpress的&lt;a href=&quot;http://codex.wordpress.org/Class_Reference/WP_Query#Category_Parameters&quot;&gt;开发文档&lt;/a&gt;查看。调试了几遍，摸清了门路，用下面这个网址，即可获取到earrings这个类目下的第一页所有posts。注意，你可以先通过前面的方式，查看每个post的结构，找出你想要过滤的字段对应的是什么参数。比如，新月网站中的类目实际上就是Category中的slug字段，通过Wordpress的&lt;a href=&quot;http://codex.wordpress.org/Class_Reference/WP_Query#Category_Parameters&quot;&gt;开发文档&lt;/a&gt;找到对应的参数，就是category_name.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;http://www.yourwebsite.com/wp-json/posts/?filter[category_name]=earrings&amp;amp;page=1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;而对于搜索，可以使用下面的scheme，来搜索所有包含”rings”字符串的posts。非常方便。（search功能在app中暂未提供）&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;http://www.yourwebsite.com/wp-json/posts/?filter[s]=rings
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Server端的API接口搞定了，接下来是app中最重要的ContentProvider部分了。事实上，这部分也是我花时间最多的地方。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Libraries used in Xinyue App</title>
   <link href="https://blog.pzheng.me//2015/09/04/libraries-used-in-xinyue-app/"/>
   <updated>2015-09-04T22:04:00+00:00</updated>
   <id>https://blog.pzheng.me//2015/09/04/libraries-used-in-xinyue-app</id>
   <content type="html">&lt;p&gt;在制作第一款App Conn时，使用了不少三方库，比如Floating Action Button和Navigation Drawer等。因为那时Google虽已正式提出&lt;a href=&quot;http://www.google.com/design/spec/material-design/introduction.html&quot;&gt;Material Design&lt;/a&gt;，介绍了不少新颖的设计方案。但并未适时推出配套库，因此涌现出大量三方库来支持此类需求。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;题外话，作为developer，你完全可以不遵守Material Design。比如以小米的&lt;a href=&quot;http://www.miui.com&quot;&gt;MIUI&lt;/a&gt;和魅族&lt;a href=&quot;http://www.flyme.cn/&quot;&gt;Flyme&lt;/a&gt;为首的iOS向，还有锤子Smartisan为代表的前iOS向。基本上都是长了颗Android的心，却又向往iOS的长相，因此大刀阔斧地进行了整容。这里就不提其他大量如华为&lt;a href=&quot;http://www.emui.com/&quot;&gt;EMUI&lt;/a&gt;、联想&lt;a href=&quot;http://www.vibeui.com/vibeui/index#!/index&quot;&gt;VIBE UI&lt;/a&gt;、中兴等各家整残的ROM了。&lt;/p&gt;

&lt;p&gt;还有以微信为首，tab放在bottom的那些apps，几乎全未遵守Material Design的设计规范。说的就是你们，支付宝和豆瓣，学谁不好…&lt;/p&gt;

&lt;p&gt;其实对很多无设计经验的developers来说，Material Design的出现，绝对是好事。它保证了设计的底线和统一的用户体验，按它的来起码不会丑到哭。因此在整个开发设计过程中，我也希望能尽量遵守Material Design规范。&lt;/p&gt;

&lt;p&gt;今年Google推出&lt;a href=&quot;http://android-developers.blogspot.jp/2015/05/android-design-support-library.html&quot;&gt;Android Design Support Library&lt;/a&gt;成功解救了我们。FAB等功能或效果都可使用support lib来实现了。因此在Xinyue App中，能使用官方库的，我都会用官方的support-v4和design support库去实现。如下：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.android.com/intl/zh-cn/reference/android/support/v4/widget/DrawerLayout.html&quot;&gt;DrawerLayout&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.android.com/intl/zh-cn/reference/android/support/design/widget/TabLayout.html&quot;&gt;TabLayout&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.android.com/intl/zh-cn/reference/android/widget/Toolbar.html&quot;&gt;Toolbar&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.android.com/intl/zh-cn/reference/android/widget/Toolbar.html&quot;&gt;SwipeRefreshLayout&lt;/a&gt;;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;官方库也不是没有坑，比如在support-v4:22.2.1中，tab可能会无故消失。这个问题在&lt;a href=&quot;https://code.google.com/p/android/issues/detail?id=180462&quot;&gt;论坛&lt;/a&gt;里吵翻了，据说在23版本里仍然未解决。我暂时使用的是&lt;a href=&quot;https://code.google.com/p/android/issues/detail?id=180462#c17&quot;&gt;17楼&lt;/a&gt;提供的work-around，并不完美。&lt;/p&gt;

&lt;p&gt;同时，另一些重要的功能，如在右滑退出等，Google仍未提供官方库支持。因此，还是不可避免的需要使用一些三方库。在Xinyue App中，我主要使用了：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.android.com/intl/zh-cn/training/volley/index.html&quot;&gt;Volley&lt;/a&gt;：Google出品，用于网络请求；&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/nostra13/Android-Universal-Image-Loader&quot;&gt;Universal Image Loader&lt;/a&gt;：用于请求和加载image;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/google/gson&quot;&gt;Gson&lt;/a&gt;：同样来自Google，快捷方便地解析JSON格式;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/yrom/SwipeBackLayout&quot;&gt;SwipeBackLayout&lt;/a&gt;：用于滑动退出；&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Demievil/SwipeRefreshLayout&quot;&gt;SwipeRefreshLayout&lt;/a&gt;：用于上拉加载；&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gist.github.com/cbeyls/7475726&quot;&gt;PreferenceFragment&lt;/a&gt;：官方的PreferenceFragment不支持support-v4中的fragment，这个第三方的可以；&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>First Phase of Xinyue App</title>
   <link href="https://blog.pzheng.me//2015/09/03/first-phase-of-xinyue-app/"/>
   <updated>2015-09-03T22:44:00+00:00</updated>
   <id>https://blog.pzheng.me//2015/09/03/first-phase-of-xinyue-app</id>
   <content type="html">&lt;p&gt;新月App第一期的工作差不多完成了。有几个TODO还没完成，不过暂时不影响基本使用。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;比如：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Product detail页面是用TextView混排文字和图片，导致灵活性不够，图片暂时无法点击放大；&lt;/li&gt;
  &lt;li&gt;Search功能未加入，WP API插件是已经提供了搜索的接口，想想应该不难，在现有的代码上增加点功能就可实现；&lt;/li&gt;
  &lt;li&gt;Design部分稀烂，比如配色，DrawerLayout各元素不完全符合Material Design规范，产品列表和详情页的版式等，是大有可提升的空间；&lt;/li&gt;
  &lt;li&gt;ListView要替换成现在更流行的RecyclerView；&lt;/li&gt;
  &lt;li&gt;分享功能太简陋，比如微信朋友圈的分享功能没实现，不想用腾讯或第三方的SDK去做；&lt;/li&gt;
  &lt;li&gt;某些用户体验部分还有待提升，比如产品列表底部的loadMore最好做成自动载入等；&lt;/li&gt;
  &lt;li&gt;对Android不同版本和不同size屏幕的适配工作；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;现在的app界面暂时如下所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20150903_xinyue_home.png&quot; alt=&quot;home&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20150903_xinyue_drawer.png&quot; alt=&quot;drawer&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20150903_xinyue_detail.png&quot; alt=&quot;detail&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20150903_xinyue_settings.png&quot; alt=&quot;settings&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20150903_xinyue_about.png&quot; alt=&quot;about&quot; /&gt;&lt;/p&gt;

&lt;p&gt;接下来的工作，主要是想写Unit Testing cases，然后做refactoring. 前面提到的TODOS最好也能一并做了。如果时间不允许，就暂缓。重点还是想学学Android的UT，以及实践一下重构。&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>New Android App Xinyue Based on RESTful API</title>
   <link href="https://blog.pzheng.me//2015/08/24/new-android-app-xinyue-based-on-restful-api/"/>
   <updated>2015-08-24T09:26:00+00:00</updated>
   <id>https://blog.pzheng.me//2015/08/24/new-android-app-xinyue-based-on-restful-api</id>
   <content type="html">&lt;p&gt;做完第一个Android小应用&lt;a href=&quot;http://blog.pzheng.me/2015/04/03/my-first-android-app-conn/&quot;&gt;Conn&lt;/a&gt;后，一直跃跃欲试想再做一款应用练练手。毕竟脑子里的idea还挺多的，而用工程驱动的方式去学习，也不失乐趣。&lt;/p&gt;

&lt;!--more--&gt;

&lt;h3 id=&quot;java-self-learning&quot;&gt;Java Self-learning&lt;/h3&gt;

&lt;p&gt;不过在上个项目中，遇到很多关于Java基础知识不清晰的地方，比如抽象类，匿名类等。基本都是靠代码拼贴，还有联想及试错的方式整出来的。所以，想在制作第二款App之前，能稍微巩固一下Java相关的基础。基于此，就学习了University of Helsinki的&lt;a href=&quot;http://mooc.fi/english.html&quot;&gt;在线课程&lt;/a&gt;Object-Oriented programming with Java &lt;a href=&quot;http://mooc.fi/courses/2013/programming-part-1/&quot;&gt;part 1&lt;/a&gt; &amp;amp; &lt;a href=&quot;http://mooc.fi/courses/2013/programming-part-2/&quot;&gt;part II&lt;/a&gt;。不得不说，这套课程设置得很棒，是学习Java入门非常好的材料。具体体现在：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;配套的IDE是开源的Netbeans，学校还制作了课程插件，可上传课后作业的代码和计分。关键是windows/Linux/Mac全平台适用，太用心了（尤其是Linux，很多软件声称适配Linux，但其实只支持某些发行版。而这套Netbeans+插件，在家里的Arch Linux上跑毫无问题，大赞。）；&lt;/li&gt;
  &lt;li&gt;每个课后作业都有一套完整的UT代码，通过UT测试来计算是否pass和算分。同时，你只能在pass之后才能看得到参考答案；&lt;/li&gt;
  &lt;li&gt;内容说起来算是很浅显的，因此仅适用于入门。不过有几题是没有提示，完全靠自己freestyle的构造整个工程，也需要花点时间；&lt;/li&gt;
  &lt;li&gt;如果有什么不懂的地方，可以上IRC chat去咨询，反馈及时也挺热情的。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;server-side-api&quot;&gt;Server side API&lt;/h3&gt;

&lt;p&gt;把课后习题全都做完一遍，语法方面的障碍基本扫清。就开始着手做App了，最先想到的就是，希望为&lt;a href=&quot;http://blog.pzheng.me/2014/06/01/promotion-independent-designer/&quot;&gt;之前搭建&lt;/a&gt;的网站“&lt;a href=&quot;http://www.xinyue.in&quot;&gt;新月&lt;/a&gt;”，制作一枚Android客户端。想要完成客户端对服务器的接入，必定要经过API接口。经过前期调研，决定选广泛采用的RESTful API。WordPress有成熟的&lt;a href=&quot;http://wp-api.org/&quot;&gt;WP REST API插件&lt;/a&gt;使用。安装并激活插件后，就可以通过下面形式的网址来get JSON格式的response了。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;GET http://www.xinyue.in/wp-json/posts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Chrome里有Advanced REST client和Postman等多款插件，可在浏览器里debug RESTful API，很顺手。&lt;/p&gt;

&lt;h3 id=&quot;client-side-architecture&quot;&gt;Client side architecture&lt;/h3&gt;

&lt;p&gt;服务器端的问题解决了。接下来就是客户端如何实现了。Google早在2010年的开发者大会上，就提出了几种推荐的RESTful client的解决方案。视频在&lt;a href=&quot;https://www.youtube.com/watch?v=xHXn3Kg2IQE&quot;&gt;YouTube&lt;/a&gt;上有，slides材料在&lt;a href=&quot;https://dl.google.com/googleio/2010/android-developing-RESTful-android-apps.pdf&quot;&gt;这里&lt;/a&gt;。最终选用的是Option B方案。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20150824_restful_client_use_contentprovider_api.png&quot; alt=&quot;use contentprovider api&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;reference&quot;&gt;Reference&lt;/h3&gt;

&lt;p&gt;期间，主要参考的资料是：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://shop.oreilly.com/product/0636920010364.do&quot;&gt;Programming Android&lt;/a&gt;的Part III. A Skeleton Application for Android。这本书于2011年出版，太老了。Demo里使用的YouTube API早换了不知多少轮了，所以请注意代码下下来，是没法直接运行的。据悉，该书第二个版本将于今年年底发行；&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/stormzhang/9GAG&quot;&gt;9GAG REST Client&lt;/a&gt;. 用了大量第三方库;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.vogella.com/tutorials/AndroidSQLite/article.html&quot;&gt;Android SQLite database and content provider - Tutorial&lt;/a&gt;. 主要是参考学习ContentProvider的；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;就像下面这幅&lt;a href=&quot;http://oktop.tumblr.com/post/15352780846&quot;&gt;漫画&lt;/a&gt;(by Van Oktop)画的一样，看了那么多书和代码，还是不会写啊。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20150824_how_to_draw_a_horse.jpg&quot; alt=&quot;how to draw a horse&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;source-code&quot;&gt;Source code&lt;/h3&gt;

&lt;p&gt;最后还是抽空余时间，慢慢磨，写了个大致的框架出来。核心其实就是实现Google提出的Option B里，用ContentProvider API来异步获取网络信息。这个实现了，后面的基本就都是小修补和User Experience上的改善了。&lt;/p&gt;

&lt;p&gt;代码放在&lt;a href=&quot;https://github.com/happybit/Xinyue&quot;&gt;GitHub&lt;/a&gt;上了，现在还是非常初级的版本，远未达到release的标准。后续我会接着提交改动来完善它。初步在Android 4.1.2和5.0.1两个版本上跑通了，偶有force close的crash问题，正在debug中(时间不够用啊）。&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Protocol Buffers at a Glance II</title>
   <link href="https://blog.pzheng.me//2015/07/19/protocol-buffers-at-a-glance-ii/"/>
   <updated>2015-07-19T21:57:00+00:00</updated>
   <id>https://blog.pzheng.me//2015/07/19/protocol-buffers-at-a-glance-ii</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://blog.pzheng.me/2015/07/11/protocol-buffers-at-a-glance-i/&quot;&gt;上篇&lt;/a&gt;简单介绍了JSON和ASN.1作为Protocol Buffers的背景知识。今天我们来具体讲解一下Protocol Buffers的encoding。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;官方网站上有专门的&lt;a href=&quot;https://developers.google.com/protocol-buffers/docs/encoding&quot;&gt;Encoding&lt;/a&gt;一章详述如何编码。这里就以一个简单的例子来讲解。&lt;/p&gt;

&lt;p&gt;假如我们需要传输一条消息，这条消息里包含一个structure，或者用官方说法是embedded message（嵌入式消息）。里面息只有一个元素叫userId，值为4621.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;removeUser {
    userId = 4621;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;为了更清晰的展示编码过程，我们先来看一下编码完成后的结果，通过解码来看其中的原理。这条消息经过编码后，serialized data为(0x表示十六进制):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(0x) 1A 03 08 8D 24
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;step-1-wire-type&quot;&gt;Step 1 Wire type&lt;/h2&gt;

&lt;p&gt;首先来看0x1A，转化为二进制(0b)为：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(0b) 00011 010
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;请注意，上面估计写成右边LSB的低三位和MSB的高五位分开。原因是，LSB的这三位表示的是这个field的wire type，如下：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Type&lt;/th&gt;
      &lt;th&gt;Meaning&lt;/th&gt;
      &lt;th&gt;Used For&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;Varint&lt;/td&gt;
      &lt;td&gt;int32, int64, uint32, uint64, sint32, sint64, bool, enum&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;64-bit&lt;/td&gt;
      &lt;td&gt;fixed64, sfixed64, double&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;Length-delimited&lt;/td&gt;
      &lt;td&gt;string, bytes, embedded messages, packed repeated fields&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;Start group&lt;/td&gt;
      &lt;td&gt;groups (deprecated)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;End group&lt;/td&gt;
      &lt;td&gt;groups (deprecated)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;32-bit&lt;/td&gt;
      &lt;td&gt;fixed32, sfixed32, float&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;(0b) 010是十进制的2，对应地，表示这个field里的值类型是“string, bytes, embedded messages, packed repeated fields”的其中一种。如前所述，这个例子里表示embedded message.&lt;/p&gt;

&lt;h2 id=&quot;step-2-field-number&quot;&gt;Step 2 Field number&lt;/h2&gt;

&lt;p&gt;再将剩下MSB的高五位，向右移三位，得到(0b) 11，为十进制的3. 表示这个field number。这里就要介绍一下Protocol Buffers的模板机制。&lt;/p&gt;

&lt;p&gt;我们需要提前预设消息模板，一般以.proto为文件扩展名。如下是userconfig.proto:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;message Userconfig {
    ...
    message ActionUserconfig {
        required int32 userId = 1;
    }
    ...
    optional ActionUserconfig addUser = 2;
    optional ActionUserconfig removeUser = 3;
    ...
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这里的field number就是指在这条消息里tag为3的这个optional的structure，也就是说，是removeUser message.&lt;/p&gt;

&lt;h2 id=&quot;step-3-payload-length&quot;&gt;Step 3 Payload length&lt;/h2&gt;

&lt;p&gt;接下来看(0x) 03，十进制也是3。表明后面接着有3个bytes的payload。数一数，(0x) 08 8D 24，确实是三个bytes.&lt;/p&gt;

&lt;h2 id=&quot;step-4-values&quot;&gt;Step 4 Values&lt;/h2&gt;

&lt;p&gt;接着用step 1/2/3里的方法再来解析(0x) 08 8D 24。简单的讲：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(0x) 08&lt;/code&gt;转换为二进制是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(0b) 00001 000&lt;/code&gt;, 得到wire type是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;，表示是Varint；&lt;/li&gt;
  &lt;li&gt;同时得到field number为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;，从消息模板中，找到对应的tag为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;的就是userId；&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(0x) 8d 24&lt;/code&gt;转换为二进制是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(0b) 10001101 00100100&lt;/code&gt;；
    &lt;ul&gt;
      &lt;li&gt;按照每8 bits分成两份，分别为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(0b) 10001101&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(0b) 00100100&lt;/code&gt;；&lt;/li&gt;
      &lt;li&gt;分别去掉MSB的最高一位，得到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(0b) 0001101&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(0b) 0100100&lt;/code&gt;. （最高位是用来表示是否到了number的结尾，如果number多于一个byte，就会将第一个byte的最高位设为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;）;&lt;/li&gt;
      &lt;li&gt;再将右边的数放在左边（高位），左边的数放在右边（低位），拼在一起，得到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(0b) 00100100 10001101&lt;/code&gt;.相当于做了一次大小端的转换。最终可知&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(0b) 00100100 10001101&lt;/code&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(0x) 12 0D&lt;/code&gt;，也就是十进制的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;4621&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;可以看到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.proto&lt;/code&gt;文件在编解码过程中，起了非常关键的作用。这点和ASN.1类似，但和JSON等自解释的截然不同。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Protocol Buffers at a Glance I</title>
   <link href="https://blog.pzheng.me//2015/07/11/protocol-buffers-at-a-glance-i/"/>
   <updated>2015-07-11T21:13:00+00:00</updated>
   <id>https://blog.pzheng.me//2015/07/11/protocol-buffers-at-a-glance-i</id>
   <content type="html">&lt;p&gt;前段时间在研究一个问题时，发现系统中某个组件，发送消息使用的是Google的&lt;a href=&quot;https://developers.google.com/protocol-buffers/&quot;&gt;Protocol Buffers&lt;/a&gt;。这里简单介绍一下，权作记录。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;当我们需要从一端向对端传输数据，需要规定好传输格式(rules)，否则当对端接收到数据后不知道如何将数据解码出来。通常，这种规范需要兼具human-readable和machine-readable的特性。Wikipedia有一个&lt;a href=&quot;https://en.wikipedia.org/wiki/Comparison_of_data_serialization_formats&quot;&gt;专页&lt;/a&gt;对比各种data serialization formats.&lt;/p&gt;

&lt;p&gt;我们熟知的XML, JSON等，在human-readable方面做得都不错，且灵活度高。由于自带属性说明(key-value pair)，所传数据具备“自解释”性。但带来的副作用，是冗余度会提升。比如下例中的”firstName”/”lastName”等，甚至”{“/”}”/”:”这些符号都会占用传输带宽。&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;firstName&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;lastName&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Smith&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;isAlive&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;age&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;address&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;streetAddress&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;21 2nd Street&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;city&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;New York&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;state&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;NY&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;postalCode&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;10021-3100&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;而在通信协议中，由于对时延的敏感和减少信令开销，我们通常使用的是&lt;a href=&quot;http://www.itu.int/en/ITU-T/asn1/Pages/introduction.aspx&quot;&gt;ASN.1&lt;/a&gt; (Abstract Syntax Notation One). 比如我们常用的&lt;a href=&quot;http://www.3gpp.org/DynaReport/25331.htm&quot;&gt;RRC信令传输&lt;/a&gt;中，会在RNC和Node B里都预设信息的模板和格式。这样只用按照格式传输value值，到了对端按照模板还原信息即可。这样大大减少了冗余信息的传输。但同时也造成了传输时，数据是一长串bit stream，可读性非常差。通常在调试时，需要辅助的解码工具才能有相对较好的human-readability.&lt;/p&gt;

&lt;p&gt;手边没有现成的RRC message，下面以一条baseband message的部分信息为例。&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;IE/Group Name&lt;/th&gt;
      &lt;th&gt;Value range&lt;/th&gt;
      &lt;th&gt;IE Type&lt;/th&gt;
      &lt;th&gt;Value (Decimal)&lt;/th&gt;
      &lt;th&gt;Value (Hexadecimal)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;User ID&lt;/td&gt;
      &lt;td&gt;1…4095&lt;/td&gt;
      &lt;td&gt;INTEGER&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0x01&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;User Type&lt;/td&gt;
      &lt;td&gt;0, 1, 2, 3&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0x00&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;# of Radio Link Information&lt;/td&gt;
      &lt;td&gt;1…4&lt;/td&gt;
      &lt;td&gt;INTEGER&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0x01&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Radio Link Information (SRadioLinkSetup.h)&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;STRUCT&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;gt;RL-ID&lt;/td&gt;
      &lt;td&gt;0…31&lt;/td&gt;
      &lt;td&gt;INTEGER&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;0x0A&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;gt;C-ID&lt;/td&gt;
      &lt;td&gt;1…65535&lt;/td&gt;
      &lt;td&gt;INTEGER&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;0x03&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;gt;Frame Offset&lt;/td&gt;
      &lt;td&gt;0…255&lt;/td&gt;
      &lt;td&gt;INTEGER&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0x00&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;gt;Chip Offset&lt;/td&gt;
      &lt;td&gt;0…38399&lt;/td&gt;
      &lt;td&gt;INTEGER&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0x00&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;最终传出去的serialized data是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;01 00 01 0A 03 00 00&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Google提出的Protocol Buffers更接近ASN.1。它也需要双方互知消息模板，用来decode数据。不过它使用的方式于ASN.1又有所不同。&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Testing Less</title>
   <link href="https://blog.pzheng.me//2015/07/04/testing-less/"/>
   <updated>2015-07-04T10:01:00+00:00</updated>
   <id>https://blog.pzheng.me//2015/07/04/testing-less</id>
   <content type="html">&lt;p&gt;前两天看到一篇&lt;a href=&quot;http://blog.acolyer.org/2015/06/25/the-art-of-testing-less-without-sacrificing-quality/&quot;&gt;文章&lt;/a&gt; &lt;em&gt;The Art of Testing Less Without Sacrificing Quality&lt;/em&gt;，挺有意思的，和大家分享一下。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;做软件测试的工程师，常常陷入一种矛盾中。为了保证质量和所谓的“测试覆盖率”，我们需要尽可能&lt;strong&gt;多&lt;/strong&gt;的测试，各种可能在客户现场发生的场景。但同时，由于资源限制和项目压力，我们又只能测试&lt;strong&gt;有限&lt;/strong&gt;的测试集合。现阶段所面临的主要矛盾，是精力日益增长的质量需要同紧迫的项目交割日期还有有限的资源之间的矛盾。于是，各路大神纷纷祭出各种测试方法，各种流程改进（通常还会冠之以牛逼哄哄的名字），希望能缓解这类冲突。&lt;/p&gt;

&lt;p&gt;这篇文章就是微软的Kim Herzig等工程师，提出的一种基于历史数据来优化测试效率的方法。作者称之为THEO（ Test Effectiveness Optimization using Historic data）。并且发表了相关&lt;a href=&quot;http://research.microsoft.com/pubs/238350/The%20Art%20of%20Testing%20Less%20without%20Sacrificing%20Quality.pdf&quot;&gt;paper&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;工作原理说起来并不复杂。首先，测试中发现的bug通常是两类:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Genuine defect，真实有效需要改正的bug；&lt;/li&gt;
  &lt;li&gt;False alarm，由测试环境测试数据等引入的非真实bug；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;因此，可以定义两个相应的参数：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;P&lt;sub&gt;defect&lt;/sub&gt;(test,context) = #detectedDefects(test,context) / #executions(test,context)&lt;/li&gt;
  &lt;li&gt;P&lt;sub&gt;falsePositive&lt;/sub&gt;(test,context) = #falseAlarms(test,context) / #executions(test,context)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;接着来判断，一个case，跑它所需要的cost Cost&lt;sub&gt;exec&lt;/sub&gt; 和不跑它可能导致的cost Cost&lt;sub&gt;skip&lt;/sub&gt;。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Cost&lt;sub&gt;exec&lt;/sub&gt; = Cost&lt;sub&gt;machine&lt;/sub&gt; + (P&lt;sub&gt;falsePositive&lt;/sub&gt; x Cost&lt;sub&gt;inspect&lt;/sub&gt;)&lt;/li&gt;
  &lt;li&gt;Cost&lt;sub&gt;skip&lt;/sub&gt; = P&lt;sub&gt;defect&lt;/sub&gt; x Cost&lt;sub&gt;escaped&lt;/sub&gt; x Time&lt;sub&gt;delay&lt;/sub&gt; x #Engineers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;其中，&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Cost&lt;sub&gt;machine&lt;/sub&gt;为占用机器的时间，硬件损耗和维护等成本；&lt;/li&gt;
  &lt;li&gt;Cost&lt;sub&gt;inspect&lt;/sub&gt;为检视testing团队的时间和人力成本；&lt;/li&gt;
  &lt;li&gt;Cost&lt;sub&gt;escaped&lt;/sub&gt;为bug逃出去之后分析和修正它所需要的成本；&lt;/li&gt;
  &lt;li&gt;Time&lt;sub&gt;delay&lt;/sub&gt;和#Engineers分别为修正一个历史bug所需要的时间和会被影响到的工程师数量；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;最后，通过比较Cost&lt;sub&gt;exec&lt;/sub&gt;和Cost&lt;sub&gt;skip&lt;/sub&gt;来判断是否需要跑这个case:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;if Cost&lt;sub&gt;exec&lt;/sub&gt; &amp;lt; Cost&lt;sub&gt;skip&lt;/sub&gt;, case should be executed;&lt;/li&gt;
  &lt;li&gt;Else, case won’t be executed;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;原理说起来很简单，其实我们在反复优化测试集合，以及为未来release制定test plan时，也反复使用，就是基于某个case，衡量跑与不跑所带来的成本，来决定以后是否还需要继续跑这个case。微软的这个做法就是是基于历史数据，提出了具体量化如何计算成本的算法和过程。如果没有海量的历史统计数据，这里的每一项都将是不确定的变量，导致最终结果不够准确，也无法说服人。&lt;/p&gt;

&lt;p&gt;文中提到，使用这种方法，微软的Windows/Office/Dynamics等部门，在两年时间内，case执行数减少了50%，测试时间降低了47%。在保证软件质量的前提下，每个产品线每个开发年度平均可以降低两百万美元的开发成本。经理们看到这里眼睛都要发直了吧。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Conn Experience I</title>
   <link href="https://blog.pzheng.me//2015/04/12/conn-experience-i/"/>
   <updated>2015-04-12T20:40:00+00:00</updated>
   <id>https://blog.pzheng.me//2015/04/12/conn-experience-i</id>
   <content type="html">&lt;p&gt;Conn的核心操作不过是自动toggle data connection。可以将&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ConnectivityManager&lt;/code&gt;中的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setMobileDataEnabled&lt;/code&gt;方法reflection出来使用。&lt;/p&gt;

&lt;!--more--&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ConnectivityManager&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;conman&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ConnectivityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getSystemService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CONNECTIVITY_SERVICE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Class&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;conmanClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;forName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conman&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getClass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Field&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;connectivityManagerField&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;conmanClass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getDeclaredField&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mService&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;connectivityManagerField&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setAccessible&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;connectivityManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;connectivityManagerField&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conman&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Class&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;connectivityManagerClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;  &lt;span class=&quot;nc&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;forName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;connectivityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getClass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Method&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setMobileDataEnabledMethod&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;connectivityManagerClass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getDeclaredMethod&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;setMobileDataEnabled&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Boolean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;TYPE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;setMobileDataEnabledMethod&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setAccessible&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;setMobileDataEnabledMethod&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;invoke&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;connectivityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;同时，在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AndroidManifest.xml&lt;/code&gt;中添加下列两行，需要获取这两项权限：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;uses-permission android:name=&quot;android.permission.CHANGE_NETWORK_STATE&quot; /&amp;gt;
&amp;lt;uses-permission android:name=&quot;android.permission.ACCESS_NETWORK_STATE&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;年初手机升级5.0后，突然发现应用无法使用，出错信息提示“NoSuchMethodException”。搜了一圈，发现Android Lollipop之后，该方法已从&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ConnectivityManager&lt;/code&gt;中移除了。在AOSP论坛里，开发人员已经&lt;a href=&quot;https://code.google.com/p/android/issues/detail?can=2&amp;amp;start=0&amp;amp;num=100&amp;amp;q=&amp;amp;colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&amp;amp;groupby=&amp;amp;sort=&amp;amp;id=78084&quot;&gt;哀嚎一片&lt;/a&gt;。短期内看来，Google不会有进一步的反应。应该也有考虑第三方apps偷偷打开数据连接偷流量的风险。&lt;/p&gt;

&lt;p&gt;无奈，再寻找work-around。现阶段找到的一个是通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;su&lt;/code&gt; command直接操作，动作是糙了点，而且这种方式下device必需要rooted。不过还好有效。&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;enable&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;disable&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;svc data &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Process&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;su&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Runtime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getRuntime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;exec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;su&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;DataOutputStream&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outputStream&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DataOutputStream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;su&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getOutputStream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;outputStream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;writeBytes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;outputStream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;outputStream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;writeBytes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;exit\n&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;outputStream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;su&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;waitFor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;InterruptedException&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;printStackTrace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;outputStream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;IOException&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;printStackTrace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;详细调用情况请参看&lt;a href=&quot;https://github.com/happybit/Conn/blob/master/app/src/main/java/me/pzheng/conn/DataConn.java&quot;&gt;这里&lt;/a&gt;。&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>My First Android App Conn</title>
   <link href="https://blog.pzheng.me//2015/04/03/my-first-android-app-conn/"/>
   <updated>2015-04-03T20:22:00+00:00</updated>
   <id>https://blog.pzheng.me//2015/04/03/my-first-android-app-conn</id>
   <content type="html">&lt;p&gt;终于我的第一个&lt;a href=&quot;http://conn.pzheng.me&quot;&gt;Android app&lt;/a&gt;出炉了，拖得太久了。本来去年底开始自学Android开发时，就已经把雏形做出来了，基本功能完成，并一直在使用。但是“能用”和“好用”之间，还需填补大量完善的功夫。前几个月因其他事务太多，一度停止。最近又捡起来，熬了几个夜总算弄出一个“可用”的&lt;a href=&quot;https://dl.dropboxusercontent.com/u/6459697/app/Conn/Conn_v1.0.0.apk&quot;&gt;版本&lt;/a&gt;。欢迎尝鲜！&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;最初起意学Android开发，也是基于自己的需求。由于鄙司可怜又可笑的自尊，谨遵”eat your own dog &lt;del&gt;shit&lt;/del&gt;food”原则，不允许友商的基站凌驾于自己头顶。运营商也乐得不用网优和维护，于是我们在一片友商基站的包围下成了孤岛。不仅所辖小区未被加入邻小区的active set，无法进行softer handover，导致进出公司电话必断。而且大楼内数据连接异常不稳定，上网一段时间后自动断线或陷入“僵尸网络”症状–数据显示是连接的，死活就是上不了网。大家给出的tips无外乎频繁关闭/开启“飞行模式”或“数据连接”。&lt;/p&gt;

&lt;p&gt;即使现在Android已可通过status bar的快捷按钮，快速地进行“数据连接”的操作，仍嫌繁琐。且不说每次“下拉状态栏–点击关闭数据连接–下拉状态栏–点击开启数据连接”，一轮未连上，再来一轮，狼狈得狠。就是每次手机制造商看似贴心的小提示(如下图所示)，还要再多耗费一次点击，也着实x疼。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20150403_conn_dialog.jpg&quot; alt=&quot;dialog&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这个app的核心功能很简单，就是点击一次，会尝试自动连接网络，如接入失败，会自动重连，直至成功。其实只用制作一个widget button就可以的事，我还是制作了一个MainActivity，有overdevelopment之嫌。主要也是抱着学习的目的玩一玩各种功能。从核心功能实现，到界面完善，到确定名称为&lt;strong&gt;Conn&lt;/strong&gt;和logo（好啦知道两个都很逊只花半个下午就定稿了），最后签名发布，并利用&lt;a href=&quot;https://pages.github.com/&quot;&gt;GitHub Pages&lt;/a&gt;制作&lt;a href=&quot;http://conn.pzheng.me/&quot;&gt;应用专属页面&lt;/a&gt;。除了没上传Google Play Store，也算硬着头皮走完了一个简单的流程。&lt;/p&gt;

&lt;p&gt;整个app制作过程中，大致使用了(四大组件除了ContentProvider其他都用到了)：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Activity;&lt;/li&gt;
  &lt;li&gt;Fragment;&lt;/li&gt;
  &lt;li&gt;Intent;&lt;/li&gt;
  &lt;li&gt;Service;&lt;/li&gt;
  &lt;li&gt;AsyncTask;&lt;/li&gt;
  &lt;li&gt;AppWidgetProvider/BroadcastReciever;&lt;/li&gt;
  &lt;li&gt;SharedPreference;&lt;/li&gt;
  &lt;li&gt;PreferenceFragment;&lt;/li&gt;
  &lt;li&gt;NavigationDrawer;&lt;/li&gt;
  &lt;li&gt;FloatingActionButton;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;其中，&lt;a href=&quot;https://github.com/kanytu/android-material-drawer-template&quot;&gt;NavigationDrawer&lt;/a&gt;和&lt;a href=&quot;https://github.com/makovkastar/FloatingActionButton&quot;&gt;FloatingActionButton&lt;/a&gt;使用了开源代码，大大加速了开发进程。后续几篇posts，我会将开发中遇到的问题汇总，陆续贴出来，算是入门的经验。&lt;/p&gt;

&lt;p&gt;关于软件的使用，请参看&lt;a href=&quot;http://conn.pzheng.me/&quot;&gt;应用页面&lt;/a&gt;，代码也放在&lt;a href=&quot;https://github.com/happybit/Conn&quot;&gt;GitHub&lt;/a&gt;上了。&lt;/p&gt;

&lt;p&gt;对了，我没学过Java，所有代码都是看&lt;a href=&quot;http://developer.android.com/training/index.html&quot;&gt;官方training&lt;/a&gt;和&lt;a href=&quot;http://developer.android.com/guide/index.html&quot;&gt;API文档&lt;/a&gt;，还有&lt;a href=&quot;http://www.google.com&quot;&gt;Google&lt;/a&gt;/&lt;a href=&quot;http://www.github.com&quot;&gt;GitHub&lt;/a&gt;/&lt;a href=&quot;http://www.stackoverflow.com&quot;&gt;StackOverflow&lt;/a&gt;上搜到，拼凑起来的（all honor belongs to them）。写得不合规范的地方，请多指教，万谢。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Learn Vim The Hard Way IV</title>
   <link href="https://blog.pzheng.me//2015/02/25/learn-vim-the-hard-way-iv/"/>
   <updated>2015-02-25T10:46:00+00:00</updated>
   <id>https://blog.pzheng.me//2015/02/25/learn-vim-the-hard-way-iv</id>
   <content type="html">&lt;p&gt;接下来就是不停的练习，以加强肌肉记忆了。其实，不光可以在Vim中练，在其他很多软件中，也可以练习类Vim的快捷键。&lt;/p&gt;

&lt;!--more--&gt;

&lt;h3 id=&quot;emacs--evil&quot;&gt;Emacs &amp;amp; Evil&lt;/h3&gt;

&lt;p&gt;如果觊觎Vim的各种commands，又离不开Emacs。&lt;a href=&quot;https://gitorious.org/evil/pages/Home&quot;&gt;Evil&lt;/a&gt;插件就是你的不二选择。它不仅支持大部分的Vim命令。更妙的是，在insert mode，原有的Emacs快捷键也可以继续使用。&lt;/p&gt;

&lt;p&gt;唯一有一点不遍的是，Evil在org-mode的Org Agenda界面不起作用，也就是说&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jkhl&lt;/code&gt;在Org Agenda里无法进行方向操作。不过网上已有解决办法，从&lt;a href=&quot;http://www.sanityinc.com/&quot;&gt;Steve Purcell&lt;/a&gt;大神的&lt;a href=&quot;https://github.com/purcell/emacs.d&quot;&gt;配置文件&lt;/a&gt;中抄的。在Emacs配置文件中加入下面这几行，重定义快捷键即可。&lt;/p&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'org-agenda-mode-hook&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-agenda-mode-map&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;\C-n&quot;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'evil-next-buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-agenda-mode-map&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;\C-p&quot;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'evil-prev-buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-agenda-mode-map&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;b&quot;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'evil-backward-word-begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-agenda-mode-map&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;h&quot;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'evil-backward-char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-agenda-mode-map&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;j&quot;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'evil-next-line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-agenda-mode-map&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;k&quot;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'evil-previous-line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-agenda-mode-map&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;l&quot;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'evil-forward-char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-agenda-mode-map&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;n&quot;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'evil-forward-word-begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-agenda-mode-map&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'evil-forward-word-begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-agenda-mode-map&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;w&quot;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'evil-forward-word-begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;total-commander--viatc&quot;&gt;Total Commander &amp;amp; ViATc&lt;/h3&gt;

&lt;p&gt;Total Commander有一个插件&lt;a href=&quot;https://github.com/linxinhong/ViATc&quot;&gt;ViATc&lt;/a&gt;，可以实现，对文件及文件夹的操作，也可以用类Vim的快捷键完成。这个工具是开源的，使用AutoHotKey写的。本来想直接把core部分代码移植到自己的AHK配置文件里，看了一下耦合比较严重。直接移植要花一番功夫，暂时搁置。&lt;/p&gt;

&lt;h3 id=&quot;vimperator--vimium&quot;&gt;Vimperator &amp;amp; Vimium&lt;/h3&gt;

&lt;p&gt;Firefox上的&lt;a href=&quot;http://www.vimperator.org/vimperator&quot;&gt;Vimperator&lt;/a&gt;，和Chrome上的&lt;a href=&quot;https://chrome.google.com/webstore/detail/vimium/dbepggeogbaibhgnhhndojpepiihcmeb?hl=en&quot;&gt;Vimium&lt;/a&gt;，也属必装。总的来说，Vimperator比Vimium强大，可定制性更高。&lt;/p&gt;

&lt;h3 id=&quot;gmail--twitter&quot;&gt;Gmail &amp;amp; Twitter&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://mail.google.com&quot;&gt;Gmail&lt;/a&gt;和&lt;a href=&quot;http://www.twitter.com&quot;&gt;Twitter&lt;/a&gt;原生支持类Vim的快捷键。&lt;/p&gt;

&lt;h3 id=&quot;outlook&quot;&gt;Outlook&lt;/h3&gt;

&lt;p&gt;在Outlook中，可以使用&lt;a href=&quot;http://www.ocellated.com/2009/03/18/pimping-microsoft-outlook/&quot;&gt;这个AHK的脚本&lt;/a&gt;，可实现类似Gmail的快捷键。&lt;/p&gt;

&lt;h3 id=&quot;others&quot;&gt;Others&lt;/h3&gt;

&lt;p&gt;其他有编辑功能的软件，如&lt;a href=&quot;http://developer.android.com/sdk/index.html&quot;&gt;Android Studio IDE&lt;/a&gt;，&lt;a href=&quot;pad.haroopress.com/&quot;&gt;Haroopad&lt;/a&gt;等，都可以绑定Vim快捷键。&lt;/p&gt;

&lt;p&gt;这样，在大部分情况下，就能统一快捷键了。这样不仅减少了context切换的效率损耗，还可以不停演练Vim操作。唯一有一点不便，就是中文输入法的切换，在Vim中经常打乱击键节奏。所以，我尽量只在英文输入环境中使用这套操作。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Learn Vim The Hard Way III</title>
   <link href="https://blog.pzheng.me//2015/02/25/learn-vim-the-hard-way-iii/"/>
   <updated>2015-02-25T08:25:00+00:00</updated>
   <id>https://blog.pzheng.me//2015/02/25/learn-vim-the-hard-way-iii</id>
   <content type="html">&lt;p&gt;光背命令还不够，最好了解一下背景，以及和其他editor的差异，就能更好的理解Vim。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;常将&lt;a href=&quot;http://en.wikipedia.org/wiki/Vi&quot;&gt;Vi&lt;/a&gt;和&lt;a href=&quot;http://www.vim.org/index.php&quot;&gt;Vim&lt;/a&gt;混为一谈，貌似一样。其实有区别，但区别也很简单。Vi是Unix上的一款编辑器，最初是&lt;a href=&quot;http://en.wikipedia.org/wiki/Bill_Joy&quot;&gt;Bill Joy&lt;/a&gt;(Sun公司的联合创始人之一)于1976年写的。Vim是&lt;strong&gt;V&lt;/strong&gt;i &lt;strong&gt;IM&lt;/strong&gt;proved的缩写，顾名思义你可以将它看作Vi的增强版(Vim并没有完全兼容Vi)。由荷兰人&lt;a href=&quot;http://www.moolenaar.net/&quot;&gt;Bram Moolenaar&lt;/a&gt;(现任职Google)于1991年写出来的。你可以在terminal中使用Vim，也可以有单独的GUI application，比如在Windows下常用的&lt;a href=&quot;ftp://ftp.vim.org/pub/vim/pc/gvim74.exe&quot;&gt;gVim&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;和Emacs类似，由于早期的键盘无方向键也没有鼠标，因此操作都需要用快捷键实现。这也让尽可能多的键盘操作，在主键盘范围内，也就是左右手自然放在键盘上，那片区域内。而不需要频繁移动到键盘其他位置，效率自然高了。在Emacs中，为了区分真正的input和快捷键，通常用功能键&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl&lt;/code&gt;来组合各种操作的快捷键，比如前进&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-F&lt;/code&gt;(orward)和后退&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-B&lt;/code&gt;(ack)。而在Vim中，前进后退的快捷键分别是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;j&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k&lt;/code&gt;，右手食指和中指落在键盘上的两个键。宗旨也就是越频繁的键要在越方便的位置。但是由于没有功能键的辅助，编辑器无法区分当前是真的想输入”j/k”还是方向操作。因此Vim最重要的一个概念就是normal mode和insert mode，默认进入文件是normal mode，可以使用各种快捷键移动或操作，通常键入&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt;进入insert mode，按&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Esc&lt;/code&gt;键退出insert mode进入normal mode。据说高手使用Vim时只有normal mode。击键效率上来说，肯定是Vim取胜。不过用惯了Emacs，倒也不觉得常按&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl&lt;/code&gt;键有什么不适。&lt;/p&gt;

&lt;p&gt;和Emacs完全定制成自己喜欢的方式不同，Vim我暂时未加其他插件，除了基本设置了一下ignorecase/autoindent/hlsearch等，也没有太多定制（主要也是不熟vimscript)。其中一个原因是，希望能像原教旨派那样享受纯粹的击键快感。更重要的原因是，很多操作未必是在本地，比如SSH到服务器上，太多定制可能反而导致记不住默认的设置。&lt;/p&gt;

&lt;p&gt;相较于Emacs，Vim的快捷键看起来更强大。这种强大体现在快捷键的组合上。Emacs的快捷键之间相对独立，如果想要实现一个连起来的操作，就需要重新定义一个key binding。而Vim上移动和操作的快捷键可以组合，比如删除是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d&lt;/code&gt;，移动至行末是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$&lt;/code&gt;。可以在normal mode直接键入&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d$&lt;/code&gt;就是删除至行尾。甚至可以加入数字，比如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dw&lt;/code&gt;是删除一个单词，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d3w&lt;/code&gt;就是删除三个单词。如果任性定制自己喜欢的快捷键，反而可能丢失了这些组合功能。因此也没有太多必要去customize和redirect已有的key binding。&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Learn Vim The Hard Way II</title>
   <link href="https://blog.pzheng.me//2015/02/23/learn-vim-the-hard-way-ii/"/>
   <updated>2015-02-23T21:50:00+00:00</updated>
   <id>https://blog.pzheng.me//2015/02/23/learn-vim-the-hard-way-ii</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://blog.pzheng.me/2015/02/22/learn-vim-the-hard-way-i/&quot;&gt;前文&lt;/a&gt;提到个人学Vim的一些背景和动机。本文将介绍一下自己学习Vim的方法。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;一直以来，我学习的方法都是尽量快速入门，并在练习中熟练基本操作，然后在日积月累的日常使用中去精进和进阶学习。这种学习方法是遵循&lt;a href=&quot;http://en.wikipedia.org/wiki/Pareto_principle&quot;&gt;Pareto principle&lt;/a&gt;而来。我的理解是，对于某项技能，只用掌握20%就可以应付生活或工作中80%的需求。因此，快速掌握了这20%后，就能以此为基础去探索剩下的80%，成为真正的专家。这样才不会因为开始就举步维艰而中途放弃。之前学习Vim每每放弃的原因，也就在于未能掌握这最开始的20%。&lt;/p&gt;

&lt;p&gt;然而如网上流传的各种editors的learning curve图来看，Vim和Emacs都是最为诡异的。其中Vim是以学习曲线陡峭著称，也就是说这前20%是最难学的。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20150223_editors_learning_curve.jpg&quot; alt=&quot;Editors Learning Curve&quot; /&gt;
[&lt;a href=&quot;http://www.quora.com/How-accurate-do-you-think-these-text-editor-learning-curves-are&quot;&gt;Source&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;个人在学习Vim时。遇到的最大困难是经常和Emacs的快捷键记混。使用Emacs几年后，一些基本操作的快捷键已形成肌肉记忆，编辑时左手小拇指会不自觉地想去按键盘左下角的Ctrl键。只要抑制住按Ctrl键的冲动，就可以说迈出了成功的第一步。剩下的，就是”背”了。&lt;/p&gt;

&lt;p&gt;这里就要祭出利器了–&lt;a href=&quot;http://ankisrs.net/&quot;&gt;Anki&lt;/a&gt;。这是一个遵循遗忘曲线的卡片式辅助记忆工具（好几年前学习Perl时，也做过一个类似的命令行工具，用来记单词的，当然不能和这个相比啦:blush:）。这个工具强大之处在于全平台支持，支持各种操作系统如Windows，Linux，Mac，&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.ichi2.anki&quot;&gt;Android&lt;/a&gt;，&lt;a href=&quot;https://itunes.apple.com/us/app/ankimobile-flashcards/id373493387?mt=8&amp;amp;ign-mpt=uo%3D4&quot;&gt;iOS&lt;/a&gt;等。如不想使用app，还支持&lt;a href=&quot;https://ankiweb.net/&quot;&gt;web&lt;/a&gt;界面，无比贴心。其中Android版本免费，而iOS版本人民币163元（作者知道Android用户购买力没iOS用户强么？:sunglasses:）。&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;(https://ankiweb.net/)&quot;&gt;AnkiWeb&lt;/a&gt;上有很多共享的decks，可直接下载使用。如有特殊需求，也可自制deck和cards。我选择的shared deck是&lt;a href=&quot;https://ankiweb.net/shared/info/3803780219&quot;&gt;Vim Commands&lt;/a&gt;. 其中共有239张卡片，对应239个Vim命令（有些非常用或暂时用不上的可在学习过程中hide起来）。&lt;/p&gt;

&lt;p&gt;我用的是Android版本&lt;a href=&quot;(https://play.google.com/store/apps/details?id=com.ichi2.anki)&quot;&gt;AnkiDroid Flashcards&lt;/a&gt;，非常直观，上手就能使用。而且有各种统计值辅助了解学习进度。我直接使用默认设置，也就是每天学习20张新卡片。别小看这20张卡片。因为之前学过的卡片，会在遗忘期限到达之前，加入到复习列队里，所以学过一段时间后，每天新增的和复习的卡片加起来会有100多张。&lt;/p&gt;

&lt;p&gt;通常我都是在每天通勤时，掏出手机翻那些卡片学习，到公司之后，把刚才觉得比较难的命令，在电脑上操作一下，加深记忆就ok了。除掉周末，三周时间就可以将整个deck全部过一遍。再加几周反复巩固，大部分常用命令就都不在话下了。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Learn Vim The Hard Way I</title>
   <link href="https://blog.pzheng.me//2015/02/22/learn-vim-the-hard-way-i/"/>
   <updated>2015-02-22T21:08:00+00:00</updated>
   <id>https://blog.pzheng.me//2015/02/22/learn-vim-the-hard-way-i</id>
   <content type="html">&lt;p&gt;使用“神之编辑器”Emacs有几年了，当初学它主要看中了org-mode，用来实现GTD。带着目的去学，倒也没遇到大的问题。有问题就&lt;a href=&quot;https://www.google.com.hk/search?q=emacs&quot;&gt;Google&lt;/a&gt;，99.9%都有现成的解决方案。虽然不怎么懂elisp，照猫画虎也学着写了一些configuration file，来满足自己的定制需求。因此，一直也使用Emacs作为唯一的编辑器，未考虑过移情别恋“编辑器之神”Vim。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; 本文不涉及Emacs和Vim之间的&lt;a href=&quot;http://en.wikipedia.org/wiki/Editor_war&quot;&gt;flame war&lt;/a&gt;。我相信理智之人能包容地看待事物，并能按需选择适合自己的，而不是“非此即彼”地全盘否定另一方。尤其是面对两个历史如此悠久的工具时，更应谨慎。&lt;/p&gt;

&lt;p&gt;知道Vi/Vim是很早之前的事情了，读书的时候偶然看到有同学在命令行里运指如飞。那时还处于“命令行恐惧症”时期，打字可能都比较生硬且强烈依赖鼠标，接触过的编辑器估计还停留在Notepad和MS Word阶段。了解一番后觉得操作太反人类，遂放弃。后来学习期间经常需要在Linux/Unix机器上设计电路图，免不了需要编辑一些文件，仍未学会，只是在需要用的时候查一下基本操作。主要还是不习惯normal mode和insert mode之间的切换，以及无法使用方向键。工作后心血来潮也多次想捡起来再学学，又数次放弃。至后来因长期使用Emacs，更是一去不复返，断了学Vim的念头。&lt;/p&gt;

&lt;p&gt;前两个月下定决心要学一学Vim，原因主要有两点：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;最近工作中，测试的嵌入式系统主要跑在Linux上。虽是我厂定制版本，也遵守&lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/9699919799/utilities/vi.html&quot;&gt;POSIX&lt;/a&gt;规范，自带了vi编辑器(Emacs想都别想)。通常遇到一些需要直接编辑的文件，不熟悉vi很让人着急。这时Emacs用得再熟也白搭；&lt;/li&gt;
  &lt;li&gt;很多工具如Android Studio等都自定义快捷键的preference，通常会提供成套的Vim快捷键设置，很少有工具会再提供Emacs快捷键适配。更不要提Firefox上的&lt;a href=&quot;http://www.vimperator.org/vimperator&quot;&gt;Vimperator&lt;/a&gt;和Chrome上的&lt;a href=&quot;https://chrome.google.com/webstore/detail/vimium/dbepggeogbaibhgnhhndojpepiihcmeb?hl=en&quot;&gt;Vimium&lt;/a&gt;，这些在非编辑器工具上实现类Vim操作的神插件了。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vi/Vim给我的感觉就像Linux上的Notepad之于Windows一样，built-in且轻量(no offense，Vim当然比Notepad强大太多！)。随用随开，用完即关，非常轻便。Emacs由于各种定制的插件载入，在启动速度和体量上都比Vim要慢和重。因此我更倾向于开了Emacs后就一直打开并常驻内存直至关机，而且会想尽办法把所有事情都在Emacs中处理掉，比如org-mode和eshell等。而Vim基本上只用于编辑。从这个意义上说，Vim可能更遵循&lt;a href=&quot;http://en.wikipedia.org/wiki/Unix_philosophy&quot;&gt;Unix philosophy&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Do one thing and do it well.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>2014H2 Retrospective</title>
   <link href="https://blog.pzheng.me//2015/01/24/2014h2-retrospective/"/>
   <updated>2015-01-24T18:48:00+00:00</updated>
   <id>https://blog.pzheng.me//2015/01/24/2014h2-retrospective</id>
   <content type="html">&lt;p&gt;2015年第一个月即将过完，才进行2014年下半年总结。就像去年暗自定了个目标，争取每周发一篇blog post，这样全年总计应有52篇左右。最终实发43篇，落后目标17.3%。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;以前多半会归咎于“忙”或“懒”。现在不这么想。&lt;a href=&quot;http://book.douban.com/subject/10773358/&quot;&gt;《意志力：关于专注、自控与效率的心理学》&lt;/a&gt;指出，人的意志力是有限的，也是可控和可训练的。意思是，人在一天中的精力是有限的，如果在某些方面用掉过多意志力，在其他方面必定会显得意志力薄弱。意识到这一点，我就能更坦然地面对这些delay，集中精力解决问题，而不是无用的内疚与自责。因此，与其说是时间没有安排好，不如说是精力没有合理分配。&lt;/p&gt;

&lt;p&gt;今年后半段体会最深的，就是用头脑最清醒精力最旺盛的时间段，去完成那些设定的目标。如果想在辛苦工作一天后，回到家还要做饭做家务之余，再去写或学点新东西，几乎是不可能的。即使可能，效率也不会太高。而以前更关注工作上的productivity，比如&lt;a href=&quot;http://blog.pzheng.me/2013/07/30/productivity-tools-on-pc-1/&quot;&gt;各种工具的使用&lt;/a&gt;，其实生活中太多方面的productivity都值得研究。新的一年要继续实践。&lt;/p&gt;

&lt;p&gt;由于每周都基于Org-mode的agenda记录，做前一周的review，每个月也会做一次月度总结。所以这种年度retrospective很简单，过一下之前的review记录即可。&lt;/p&gt;

&lt;p&gt;我厂规定每年自评，我都用这种方式总结过往一年完成的任务。工作性质导致平时经常进行多线程任务，并且各项任务较杂，项目size也大小不一。还好有这样的习惯，一年下来看看也完成了不少tasks。细节就不说了，年中内部转岗，幸运的是前后两任老板都给了自己足够多的支持和宽容，让我能相对自由地做自己想做的事情。而自己想做的事情，恰好能和团队发展方向合拍，是非常难得的一件美事。年头和年尾分别接了一件有趣又有些难度的任务，多得同事帮助，都还算顺利地完成了。&lt;/p&gt;

&lt;p&gt;学习方面总的来说有些虎头蛇尾，比如Python的进阶学习和Clean Code等，都未能按时完成。零零散散学了些不成系统的知识，不值一提。生活上起了些变化，直接导致下半年更忙了。&lt;/p&gt;

&lt;p&gt;个人兴趣方面，书看得不多，book of the year毫无疑问是金宇澄的《繁花》。&lt;a href=&quot;http://www.infzm.com/content/102584&quot;&gt;据说&lt;/a&gt;王家卫筹拍该小说改编的电影，期待一下。从播放量上讲，album of the year是Chet Faker的Built on Glass，就像Daft Punk出的RAM之于2013年，没什么好听的时，就会捞出它来听听。Movie of the year从缺，因个人事务增多，全年去影院都没几次。&lt;/p&gt;

&lt;p&gt;如前述，2015年1月就快过完了，现在再说plan有点晚，具体的计划应已开始实施了。一个想做好久的小玩意儿也正在制作中，过一段时间就能面世了。心底里还是期望在2015年有些实质的变化，光想是不会有任何change的，take action.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Trace Of Bug</title>
   <link href="https://blog.pzheng.me//2014/12/30/trace-of-bug/"/>
   <updated>2014-12-30T13:54:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/12/30/trace-of-bug</id>
   <content type="html">&lt;p&gt;这是很早以前遇到的一个关于MIMO HSDPA的问题，其实是在研究其他问题的时候，顺带发现的。后来同事和我深究下去，最后发现还真是一个bug。&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;table-of-contents&quot;&gt;Table Of Contents&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;#intro&quot;&gt;Intro&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#background-knowledge&quot;&gt;Background knowledge&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#deduction&quot;&gt;Deduction&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#summary&quot;&gt;Summary&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;intro&quot;&gt;Intro&lt;/h2&gt;

&lt;p&gt;起初，我们在一个多用户的MIMO HSDPA测试用例里，同一个Node B中identical的两个cells内，分别建立一个QoS完全相同的MIMO HSDPA用户。最终出来的结果与预期一样，两个用户的data rate相同。不过，在研究log时，无意发现两个用户的HS-SCCH power level差别很大。其中一个用户是我们预设的&lt;em&gt;minimum HS-SCCH power&lt;/em&gt;，而另一个用户比前者高接近9dB（也就是差不多8倍）。&lt;strong&gt;为何会出现配置相同的小区和用户，HS-SCCH power差别如此之大呢？&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;background-knowledge&quot;&gt;Background Knowledge&lt;/h2&gt;

&lt;p&gt;我们知道，3GPP协议规范中并未明确指出关于HSDPA相关的两个物理信道—HS-PDSCH和HS-SCCH–的power control的细节，&lt;strong&gt;具体算法完全up to vendors&lt;/strong&gt;. 虽然这不是必须的，但大部分公司还是在这两条信道上做了一定的power control以增进基站性能。&lt;/p&gt;

&lt;p&gt;一般来说，这两个信道的power变化不会太剧烈，因为用于传data的HS-PDSCH优先级较其他R99的信道较低，通常都是在为R99的下行DCH信道以及HSUPA的下行信道分配完power之后，整个小区的剩余power几乎都可供HS-PDSCH使用。因此，基站完全可以基于需传的数据来合理控制power的大小，如果真的是信道质量非常差，power control算法一直需要抬升功率的话，它至多提升到将剩余power用完的程度，不能再多了。而用于传control信息的HS-SCCH，相较而言，就更需要稳定了。因为一来它的spreading factor很大，为128，也就是说速率相对较低，所需power也较低。二来为了保证control信息的稳定接收（因为如果这部分信息接收不稳定，就无法保证数据部分的正确接收了），对这条信道的power调整通常也不会太剧烈和太频繁。&lt;/p&gt;

&lt;p&gt;说到power control，总要有一定的feedback作为算法输入，才能进行相应的调整。对HSDPA来说，上行只有一条信道HS-DPCCH，由用户反馈ACK/NACK信息以及CQI信息。因此通常算法也会围绕这些feedback来做文章。具体算法每个公司不同，此处细节略过。&lt;/p&gt;

&lt;h2 id=&quot;deduction&quot;&gt;Deduction&lt;/h2&gt;

&lt;h3 id=&quot;rough-checking&quot;&gt;Rough Checking&lt;/h3&gt;

&lt;p&gt;实验室环境比真实无线环境简单，从算法推导，HS-SCCH power理应处于&lt;em&gt;minimum HS-SCCH power&lt;/em&gt;的状态。因此，倾向于认为是power较高的那个小区出了问题。&lt;/p&gt;

&lt;p&gt;我们发现，两个UE的BLER都接近零，接收过程一直是连续的，不存在DTX的情况。因此ACK/NACK这条路我们认为是近乎相同的。检查UE和Node B两端的log也证实了我们的想法。&lt;/p&gt;

&lt;p&gt;接着怀疑点自然就放在CQI上了。因为在实验室空口质量非常好，所以CQI照道理应该质量也非常好。在检查了power较高的UE和Node B两侧的log后发现端倪。UE侧显示CQI值是每九个TTI上报CQI 14后，会紧接着的一个TTI上上报CQI 30，以10个TTI为一个周期循环往复。但是Node B侧的log显示CQI值有一定的规律，但值的变化并不是9+1的形式。&lt;/p&gt;

&lt;p&gt;OK. 现在初步定位了问题在哪儿，我们需要仔细研究一下关于MIMO的CQI上报。&lt;/p&gt;

&lt;h3 id=&quot;mimo-cqi-reporting&quot;&gt;MIMO CQI Reporting&lt;/h3&gt;

&lt;p&gt;MIMO HSDPA的CQI上报和普通HSDPA用户不同。&lt;a href=&quot;http://www.3gpp.org/DynaReport/25214.htm&quot;&gt;3GPP TS25.214&lt;/a&gt; sub-clause 6A.1.2.2中指出，MIMO HSDPA用户会依次上报Type A和Type B的CQI values。符合下面公式的TTI就会上报Type A CQI，不符合的就会报Type B CQI.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20141230_MIMI_CQI.jpg&quot; alt=&quot;MIMO CQI&quot; /&gt;&lt;/p&gt;

&lt;p&gt;简单说，CQI是UE对下行pilot的测量，Node B收到CQI后可以大致得到UE推荐的transport block size。因此：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Type A就是UE基于当前的信道质量推荐的CQI value：
    &lt;ul&gt;
      &lt;li&gt;如果信道质量够好速率够高可以用双流，取值为 15*CQI&lt;sub&gt;1&lt;/sub&gt;+CQI&lt;sub&gt;2&lt;/sub&gt;+31。这种情况下，CQI取值范围是4bit, [0, 14];&lt;/li&gt;
      &lt;li&gt;如果信道质量不够好也可以使用单流，取值为CQI&lt;sub&gt;s&lt;/sub&gt;。取值范围是5 bit，[0, 30];&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Type B就是假设当前只能传输primary transport block，也就是单流模式的情况下，基于当前的信道质量，UE给出的CQI值。因此这种CQI值和普通的HSDPA CQI取值范围相同，为[0, 30]。Type B的频率通常较Type A更慢。引入Type B CQI的动机是假设信道条件很好，CQI值也很高，但是Node B暂时没有那么多数据需要传输的时候，就可以参考Type B的CQI只用单流来发送数据即可；&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;k&quot;&gt;k’&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;k' = k/(2ms)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;其中k是CQI feedback cyle. 此处假设为2 ms.&lt;/p&gt;

&lt;h4 id=&quot;cfn&quot;&gt;CFN&lt;/h4&gt;

&lt;p&gt;UE和Node B内部主要基于SFN，所以需要进行SFN和CFN的转换，参见&lt;a href=&quot;http://blog.pzheng.me/2014/10/26/sfn-and-cfn/&quot;&gt;该文&lt;/a&gt;。&lt;/p&gt;

&lt;h4 id=&quot;nm-ratio&quot;&gt;N/M ratio&lt;/h4&gt;

&lt;p&gt;N/M ratio是Node B内部定义的一个参数，取值范围有10个，依次是1/2, 2/3, 3/4,…, 9/10, 1/1. 在我们的测试用例中，这个值为9/10，所以&lt;em&gt;M_cqi&lt;/em&gt;为10，同时&lt;em&gt;N_cqi_typeA&lt;/em&gt;为9.&lt;/p&gt;

&lt;h4 id=&quot;m&quot;&gt;m&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;m&lt;/em&gt;值是基于&lt;a href=&quot;http://www.3gpp.org/DynaReport/25214.htm&quot;&gt;3GPP TS25.211&lt;/a&gt; sub-clause 7.7算出来的:&lt;/p&gt;

&lt;p&gt;m = (T&lt;sub&gt;TX_diff&lt;/sub&gt;/256 ) + 101&lt;/p&gt;

&lt;p&gt;其中T&lt;sub&gt;TX_diff&lt;/sub&gt;是下面两个timing的时间差，单位是chips（T&lt;sub&gt;TX_diff&lt;/sub&gt; =0, 256, ….., 38144）：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;该HS-PDSCH子帧的起始传输时间(参看sub-clauses 7.8 and 7.1)；&lt;/li&gt;
  &lt;li&gt;下行DPCH或F-DPCH的起始时间(参看sub-clause 7.1)；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;一个frame有5个sub-frames，也就是5个HSDPA TTI。所以对某个特定的radio link来说，随着SFN的变化，&lt;em&gt;m&lt;/em&gt;会有5个值。&lt;/p&gt;

&lt;p&gt;同样，基于TS25.211 sub-clause 7.1，所有下行的时序都是基于P-CCPCH的:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;DPCH/F-DPCH: t&lt;sub&gt;DPCH,n&lt;/sub&gt;或t&lt;sub&gt;F-DPCH,n&lt;/sub&gt;，即RL frame offset * 38400 + chip offset;&lt;/li&gt;
  &lt;li&gt;HS-PDSCH: 第一个HS-SCCH帧的时序是和P-CCPCH对齐的。所以一个DPCH frame里对应的5个HS-SCCH子帧取值就是{0, 2560&lt;em&gt;3, 2560&lt;/em&gt;6, 2560&lt;em&gt;9, 2560&lt;/em&gt;12}. HS-PDSCH晚于HS-SCCH两个sub-frames，也就是5120 chips;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;所以，&lt;em&gt;T&lt;sub&gt;TX_diff&lt;/sub&gt;&lt;/em&gt;的取值范围就是{5120 - t&lt;sub&gt;DPCH,n&lt;/sub&gt;, 12800 - t&lt;sub&gt;DPCH,n&lt;/sub&gt;, 20480 - t&lt;sub&gt;DPCH,n&lt;/sub&gt;, 28160 - t&lt;sub&gt;DPCH,n&lt;/sub&gt;, 35840 - t&lt;sub&gt;DPCH,n&lt;/sub&gt;}。由此也可以算出&lt;em&gt;m&lt;/em&gt;对应5个子帧的取值范围。&lt;/p&gt;

&lt;h4 id=&quot;instance&quot;&gt;Instance&lt;/h4&gt;

&lt;p&gt;假设frame offset和chip offset都为0，则T&lt;sub&gt;TX_diff&lt;/sub&gt; ∈ {5120, 12800, 20480, 28160, 35840}. 而 &lt;em&gt;m&lt;/em&gt; ∈ {121, 151, 181, 211, 241}.&lt;/p&gt;

&lt;p&gt;我们以SFN 1972 sub-frame 4(sub-frame是0/1/2/3/4)为例，CFN = 1972 mod 256 = 180, &lt;em&gt;m&lt;/em&gt;为241。所以公式中:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Left hand = Rounddown((5*180 + roundup(241 * 256/7680))/1) mod 10 = 9
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;因为&lt;em&gt;N_cqi_typeA&lt;/em&gt;也为9，公式左右相等，因此符合传输Type B CQI的上报时刻。&lt;/p&gt;

&lt;p&gt;但是我们发现这个时候在UE侧上报的是一个Type A的CQI value。最终确认问题出在UE端的CQI上报时序出错。而此时Node B还是以正确的时序尝试去解HS-DPCCH时，解出来的CQI值就全是乱的，因此导致Node B认为CQI变化过大，一直在尝试升HS-SCCH的power，最终导致我们看到一个cell的HS-SCCH power比另一个高很多的情况。&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;这是一次从下行方向细微处发现的小问题，研究至上行方向反馈，最后追溯到UE处为止，探索bug的踪迹。在此之前，我对MIMO的两种type CQI没有太深入的研究，借这次bug的契机，学习和巩固了MIMO以及时序方面的知识，实在是一次有意义又有趣的explore之旅。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>You Are So Mean</title>
   <link href="https://blog.pzheng.me//2014/12/14/you-are-so-mean/"/>
   <updated>2014-12-14T21:31:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/12/14/you-are-so-mean</id>
   <content type="html">&lt;p&gt;最近&lt;a href=&quot;http://paulgraham.com&quot;&gt;&lt;em&gt;Paul Graham&lt;/em&gt;&lt;/a&gt;的这篇文章&lt;a href=&quot;http://paulgraham.com/mean.html&quot;&gt;Mean People Fail&lt;/a&gt;在网上疯传。&lt;em&gt;Paul Graham&lt;/em&gt;是创业公司孵化器&lt;a href=&quot;http://www.ycombinator.com/&quot;&gt;Y Combinator&lt;/a&gt;的联合创始人之一，曾成功孵化过&lt;a href=&quot;http://dropbox.com&quot;&gt;Dropbox&lt;/a&gt;和&lt;a href=&quot;https://www.airbnb.com/&quot;&gt;Airnbn&lt;/a&gt;等新晋企业。其本人还是有名的Lisp程序员。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;em&gt;Paul Graham&lt;/em&gt;会在其&lt;a href=&quot;http://paulgraham.com&quot;&gt;个人网站&lt;/a&gt;上发布关于创业和技术相关的文章。他的文章，文法漂亮逻辑严谨，是非常好的英语学习材料。&lt;/p&gt;

&lt;p&gt;说回到这篇Mean People Fail的文章，其实对他的论点，我不太同意。远的不说，Steve Job不能再mean了吧，把女友肚子搞大又踹了别人最后还怀疑小孩不是他的，工作中动不动就骂手下做的东西是shit等恶劣行径，无论如何算不上“仁爱”吧。而电影&lt;a href=&quot;www.imdb.com/title/tt1285016/&quot;&gt;The Social Network&lt;/a&gt;中评价Mark Zuckerberg的那句&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;You’re not an asshole, Mark. You’re just trying so hard to be.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;言犹在耳。而国内各大公司各种没节操的行径就更不用多说了。&lt;/p&gt;

&lt;p&gt;不过文章里提到两点，我个人觉得有道理：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;斗争让人无法专注，也无益于真正问题的解决；&lt;/li&gt;
  &lt;li&gt;现代企业不再是靠攫取稀有资源形成垄断来玩的零和游戏，而应靠不断创新才能进步；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;下面是对该文的草译，有错漏的地方还请多多指教。&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;刻薄的人不会成功&quot;&gt;刻薄的人不会成功&lt;/h2&gt;

&lt;p&gt;原文链接： &lt;a href=&quot;http://paulgraham.com/mean.html&quot;&gt;http://paulgraham.com/mean.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;最近我突然意识到，在我认识的最成功的那群人里，刻薄之人极少。可能有例外，但非常少。&lt;/p&gt;

&lt;p&gt;刻薄，一点都不稀奇。事实上，网络带来的众多启示之一，就是发现人到底可以有多刻薄和恶毒。十几年前，只有名人和专业作家有机会发表他们的意见。而现在，（在网上）任何人都可以。因此我们可以发现之前未显示出来的满满恶意及其长尾效应。&lt;/p&gt;

&lt;p&gt;但即使存在如此多刻薄的人，在我认识的那些最成功的人里，几乎没有类似的情况。怎么回事？难道刻薄和成功是负相关的？&lt;/p&gt;

&lt;p&gt;当然，部分原因可能是选择偏倚&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;。我只认识在某些领域工作的人，如初创公司创始人，程序员，教授等。我相信，在某些其他领域，肯定是有刻薄的成功人士。比如，成功的对冲基金经理就有可能很刻薄。无奈我了解得太少，不能随意发表意见。另外，最成功的毒枭也极有可能很刻薄。但是，至少世界还有很大一部分未被刻薄的人统治，而且这片领域看起来还在不断增长。&lt;/p&gt;

&lt;p&gt;我妻子Jessica，也是Y Combinator的联合创始人，是少数拥有对人品有如X射线般准确判断能力的人之一。和她结为夫妇就像站在一台机场行李扫描仪旁似的。她是从投资银行领域进入创业领域的。她也经常发现，那些成功的创业者常常都是人品很好，而那些人品不怎么样的，则常常会失败。&lt;/p&gt;

&lt;p&gt;为什么？我想这里有很多原因。其中之一就是，刻薄让人变得愚蠢。这也是为什么我痛恨斗争。在斗争的过程中，你永远不可能将工作做到最好。因为斗争不具备普适性，每次斗争的情况和相关的人都不同。想要在斗争中赢得胜利，就得在那件特定的事情上想着如何玩些小花招，而不是去思考些真正大的问题。争斗和解决真正问题相比，事实上花费的精力也差不多。这就让那些在意如何使用自己脑子的人感到很痛苦：你的思维转得很快，但是不知道去往何处，就像一辆车的车轮一直空转打滑中。&lt;/p&gt;

&lt;p&gt;初创公司不是通过攻击别人来取得胜利的。而应通过超越对方的方式来赢取胜利。当然也有一些例外。但通常，赢取胜利在于比谁跑得快，而不是停下来忙着斗争。&lt;/p&gt;

&lt;p&gt;刻薄的创始人会失败的另一个原因是，他们找不到最好的人为他们工作。他们可以招到一些人，但那些人仅仅只是需要一份工作（糊口）而已。而真正最强的人往往都有其他选择。一个刻薄的人无法说服那些最优秀的人才为他工作，除非他真的非常有说服力。拥有最优秀的人对任何组织都有好处，但这一点对初创公司来说又显得更为关键。&lt;/p&gt;

&lt;p&gt;而且在工作中还有其他因素：如果想成大事，最好是由仁爱的精神驱动。那些最后变得很富有的初创公司创始人，都不是为钱所驱动的。而那些为钱驱动的创始人，常常会接受–几乎所有成功初创公司都会经历的–高价收购。而那些选择继续（而不是被高价收购）的人，常常是被其他事情所驱动。可能不会说得这么直白，但通常他们想的是如何去改进这个世界。也就是说，那些想要改进世界（有仁爱之心）的人，常常有先天优势。&lt;/p&gt;

&lt;p&gt;令人兴奋的是，初创公司不是刻薄和成功负相关唯一的例子。类似的事情，在未来将会越来越多。&lt;/p&gt;

&lt;p&gt;历史上大多数成功就意味着控制稀有资源。而这只能通过斗争来获取，不管是真的如游牧民族将狩猎采集者&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;们赶到贫瘠的地方，还是像镀金时代金融家们相互竞争来企图垄断铁路资源。对多数历史事件而言，胜利就意味着零和游戏&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;。在这种情况下，刻薄大多不是劣势，反而是优势。&lt;/p&gt;

&lt;p&gt;但事情正在改变。慢慢的，游戏不再是零和的了。现在要想取得胜利，不再是试图控制稀有资源，而是通过发现新创意和创造新事物。&lt;/p&gt;

&lt;p&gt;通过创新赢取胜利已经有些历史了。公元前三世纪，阿基米德就是用这种方式不断取得胜利&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;的，至少在入侵希腊的罗马士兵杀死他之前是这样的。这也说明为什么会发生改变：想要创新有用，必须有一定稳固程度的社会秩序（做前提）。避免战争还不够，还需要预防十九世纪那种大鳄之间的经济暴力，以及社会主义国家对待他们公民那种做法。人们只有觉得自己创造的东西不会被人随意盗取（才会去积极创新）。&lt;/p&gt;

&lt;p&gt;思想者的情况亦常如此（通过创新取胜），这也是为什么他们常是时代弄潮儿的原因。你想想历史上有修养的那些成功人士，也许想到的会是数学家、作家和艺术家。高兴的是，他们的精神现在广为流传了。智者们玩的游戏也开始在凡人世界传播开来，因而逆转了历史上刻薄和成功的相关性。&lt;/p&gt;

&lt;p&gt;很高兴我能停下来想想这件事。Jessica和我经常教育我们的小孩不要太刻薄。我们可以忍受噪音，混乱和垃圾食品，但不能忍受刻薄。而现在我又有了新的理由和论点去反对它，那就是：刻薄会让你失败。&lt;/p&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;&lt;a href=&quot;http://startupclass.samaltman.com/courses/lec05&quot;&gt;Peter Thiel&lt;/a&gt;指出，成功的创始人仍在通过控制垄断来敛财，但这仅限于他们自己创造出来（的新业务新领域而导致）的垄断，而不是攫取（稀有资源来垄断）。即使他说的都是对的，那也说明获得胜利的这类人（和以往相比也）有了很大的变化。&lt;/li&gt;
  &lt;li&gt;实际上，罗马人并没有想杀阿基米德。罗马长官特别强调不要杀他。但他还是在混乱中被杀了。在混乱的非常时期，即使是“思考”都需要控制稀有资源，因为“活着”已然是一种稀有资源了。&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Selection_bias&quot;&gt;http://en.wikipedia.org/wiki/Selection_bias&lt;/a&gt; &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Hunter-gatherer&quot;&gt;http://en.wikipedia.org/wiki/Hunter-gatherer&lt;/a&gt; &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Zero-sum_game&quot;&gt;http://en.wikipedia.org/wiki/Zero-sum_game&lt;/a&gt; &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Archimedes&quot;&gt;http://en.wikipedia.org/wiki/Archimedes&lt;/a&gt; &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>How Many Bugs Should Be Captured In CI</title>
   <link href="https://blog.pzheng.me//2014/12/07/how-many-bugs-should-be-captured-in-ci/"/>
   <updated>2014-12-07T22:55:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/12/07/how-many-bugs-should-be-captured-in-ci</id>
   <content type="html">&lt;p&gt;&lt;em&gt;一个Continuous Integration系统发现多少bugs才合适？&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;我知道脱离context，这个问题没意义。产品、测试方式/工具、编程语言、测试范围/粒度等都不尽相同，每人答案肯定不一样。But seriously, have you ever thought about it? How many bugs should be captured in &lt;strong&gt;YOUR CI system&lt;/strong&gt;?&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;自打Continuous Integration这个概念出现后，自动化测试（注意，自动化测试不等于CI。）变得前所未有的重要起来。团队在测试过程中会花费大量时间搭建CI框架/环境以及想方设法将测试用例加入CI，以期通过自动触发跑用例的方式找到新代码提交是否break了之前已验证过的功能。有过CI经历的团队，想必知道这个过程中，搭建和维护整个CI环境/用例的effort还是挺大的。&lt;/p&gt;

&lt;p&gt;那么当别人问起我们在CI里发现了多少bugs，如果说出来的数字很少，甚或一个星期也发现不了一个bug时，他一定会质疑这样的投入产出比是否值得。&lt;/p&gt;

&lt;p&gt;有意思的是，如果数字大得惊人的话，他同样会质疑，不过质疑的是软件质量–真的这么差？&lt;/p&gt;

&lt;p&gt;因此，这个问题就变得特别微妙，太多太少看起来都不好。要么测试没做好，要么开发不行，总之就是在打自己R&amp;amp;D团队的脸。&lt;/p&gt;

&lt;p&gt;这里涉及到另一个长期有争议的话题：&lt;em&gt;用发现bug的数量来衡量一个人或一个系统，是否合适？&lt;/em&gt; 个人意见是，&lt;strong&gt;如果只拿它当作唯一或者最重要的指标，肯定不合适。&lt;/strong&gt;我们应该基于全方位了解的前提下，去评估一个人或一个系统，而不是简单笼统的评价他/她/它的好坏。&lt;/p&gt;

&lt;p&gt;不必说不同的产品或feature间的差异，就算是同一个产品和feature，随着时间的推移，情况都不一样。一个产品周期里，前期测试发现的问题一定是最多的。同理，break CI的机会也是最大的，CI上发现的问题数肯定很多。而当feature开发进入尾声，CI上发现问题的频率和可能性都会降到极低，因为这时代码的改动都非常少了。用简单的数量比较，没有太多意义。&lt;/p&gt;

&lt;p&gt;因此，我更倾向于认为，&lt;strong&gt;持续集成(Continuous Integration)虽好，更应该持续优化(Continuous Improvement)&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;当你发现CI上bugs数量过少时，应先看项目开发进度。如已进入尾声，少点也无妨。若处于项目开初，看看是否由于CI框架还不够完善。如果产品各features都已火热的启动，每天commit数量巨大，而CI上bugs数仍少得可怜，需检查CI上case的设计和选取是否合适，以及自动化的check points是否合理等(这需要case by case的分析)。&lt;/p&gt;

&lt;p&gt;当CI上bugs数量惊人时，也不必惊慌。先检查valid的bugs数量，搞不好是CI环境的不稳定引入了大量非软件问题。如果valid CI bugs数量持续增多，一定要和开发人员以及当前测试环节之前的测试人员（比如系统测试就要找前面的UT/MT等）沟通，提高自测和前期测试的质量。&lt;/p&gt;

&lt;p&gt;而我们的CI也一定不是一成不变的。一个产品的成长过程，就如同人的成长一样，每个时期的问题都是不一样的。因此我们需要对不同的时期设定不一样的CI规则。比如每个case的CI频率，有per commit/day/week等。每种频率，有对人员和设备需求的考虑。这里有个误区，我们倾向于越简单的case越频繁，越难跑的case频率越低。而忽略了一点，应该是越容易出问题的case越频繁，而不是用case的难以程度去区分。一般而言，项目早期，我们应选择最基础的用例去验证启动等过程是否正常；基于不同的feature开发进度，选择代码改动最频繁的feature相关case，去做最频繁的验证；项目尾声，大部分代码改动是对bug的修正，因此更应该验证改动对legacy basic functionalities的影响。&lt;/p&gt;

&lt;p&gt;同样，CI上的cases和check points等，也不应是一成不变的。这里就涉及到CI框架/工具是否足够灵活，今天暂且不提。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Linux Driver for RTL8188CE</title>
   <link href="https://blog.pzheng.me//2014/11/28/linux-driver-for-rtl8188ce/"/>
   <updated>2014-11-28T21:25:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/11/28/linux-driver-for-rtl8188ce</id>
   <content type="html">&lt;p&gt;Arch Linux on ThinkPad T420i sucks due to the stock wireless network card – RealTek RTL8188CE. The wireless connection keeps dropping and most of the ping packages are lost even to the router(Netgear WNDR4300) in home LAN.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;I have tried several ways mentioned on the internet. For instance, disable IPv6 or replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;netctl&lt;/code&gt; by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NetworkManager&lt;/code&gt;, etc. The situation becomes even worse. The wireless would disconnect completely after a short while and cannot bring back to live again.&lt;/p&gt;

&lt;p&gt;Till recently, I found &lt;a href=&quot;https://github.com/FreedomBen/rtl8188ce-linux-driver&quot;&gt;this modified driver&lt;/a&gt; for RTL8188CE. It’s not the official driver but fixes some issue on official driver.&lt;/p&gt;

&lt;p&gt;If you have the similar problem, please try this driver. Don’t forget to explore #Troubleshooting section if the problem still exists. The fixed rate commands finally help to solve my problem.&lt;/p&gt;

&lt;p&gt;Really appreciate the author’s sharing. :smile:&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Frame Offset and Chip Offset</title>
   <link href="https://blog.pzheng.me//2014/11/23/frame-offset-and-chip-offset/"/>
   <updated>2014-11-23T22:17:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/11/23/frame-offset-and-chip-offset</id>
   <content type="html">&lt;p&gt;Frame Offset and Chip Offset are timing offset for one radio link in terms of frames and chips.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;More speficically, it defines the timing offset between downlink DPCH relative to P-CPICH (Look familiar? Yes. It’s also the delay for SFN and CFN. Please refer to &lt;a href=&quot;http://blog.pzheng.me/2014/10/26/sfn-and-cfn/&quot;&gt;SFN and CFN&lt;/a&gt;).&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Toffset = FrameOffset * 38400 + ChipOffset
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Figure 29: Radio frame timing and access slot timing of downlink physical channels&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20141123_radio_frame_timing.png&quot; alt=&quot;radio frame timing&quot; /&gt;&lt;/p&gt;

&lt;p&gt;t&lt;sub&gt;DPCH,n&lt;/sub&gt; is the same as T&lt;sub&gt;offset&lt;/sub&gt; in the above equation.&lt;/p&gt;

&lt;p&gt;Generally, Frame Offset and Chip Offset are picked by RNC randomly to distribute different radio links’ data evenly. Even the chanelisation codes could be used to distinguish different channels, it’s still not a good idea to initiate all the radio links at the same time or very closely since it may cause data burst in a short period.&lt;/p&gt;

&lt;p&gt;According to 3GPP &lt;a href=&quot;http://www.3gpp.org/DynaReport/25433.htm&quot;&gt;TS25.433&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The Frame Offset is the required offset between the dedicated channel downlink transmission frames (CFN, Connection Frame Number) and the broadcast channel frame offset (Cell Frame Number). The Frame Offset is used in the translation between Connection Frame Number (CFN) on Iub/Iur and the least significant 8 bits of SFN (System Frame Number) on Uu. The Frame Offset is UE and cell specific.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Chip Offset definition as well:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The Chip Offset is defined as the radio timing offset inside a radio frame. The Chip offset is used as offset relative to the Primary CPICH timing for the DL DPCH or for the F-DPCH.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And the technical speficiation also defines the value range of Frame Offset is [0, 255] while that of Chip Offset is [0, 38399].&lt;/p&gt;

&lt;p&gt;However, &lt;a href=&quot;http://www.wiley.com/WileyCDA/WileyTitle/productCd-0470724056.html&quot;&gt;&lt;em&gt;Radio Access Networks for UMTS&lt;/em&gt;&lt;/a&gt; mentions that, usually, RNC will only select Frame Offset from [0, 7] randomly for a new set-up radio link:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;When a UE makes the transition to CELL_DCH and the first DPCH radio link is established the range is limited to between 0 and 7. In this scenario, a range of eight radio frames is sufficient and corresponds to the maximum Transmission Time Interval (TTI) of 80 ms. This range of 8 radio frames is mirrored by the maximum range defined for the corresponding RRC signalling used to inform the UE of the equivalent information… the full range of frame offset values become applicable when a UE enters soft handover and the NBAP Radio Link Setup Request message is used to specify the timing of a new radio link.&lt;/p&gt;
&lt;/blockquote&gt;

</content>
 </entry>
 
 <entry>
   <title>Quick Open File by AutoHotKey</title>
   <link href="https://blog.pzheng.me//2014/11/12/quick-open-file-by-autohotkey/"/>
   <updated>2014-11-12T12:31:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/11/12/quick-open-file-by-autohotkey</id>
   <content type="html">&lt;p&gt;以前我们的测试工作大部分是基于脚本的，所用语言是公司自创的一套简单语法逻辑。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;通常每个case都会有一个主脚本，所有测试步骤就在这个脚本里实现。这个主脚本会引用许多公共库里的子脚本，让测试人员快速方便地实现一些子模块功能。在引用这些子脚本时，使用的既不算绝对路径，也不能完全算相对路径。而是如下所示这种参数引用式的路径，文件路径的部分或全部可以用str代替。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;run [CommonLibraryPath]\subdir\common_script.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;而CommonLibraryPath这个str参数的定义，存在与case主脚本同目录下一个名为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;paramus.txt&lt;/code&gt;的文件里。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;PARAM str,$CommonLibraryPath,&quot;C:\Common_Library\&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这样做的好处是公共库的location可以随意变换，而不用动case本身。这在一个case应用于多个branch的release下是非常有用的，比如现在trunk的库是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C:\Common_Library\\&lt;/code&gt;,还有另一个branch的库是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C:\Common_Library_branch\\&lt;/code&gt;。case会同时在这两个库里运行，只需对&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;params.txt&lt;/code&gt;进行集中替换即可，毋需改动主脚本，减少因此可能出错的机率。&lt;/p&gt;

&lt;p&gt;但这样随之带来的一个坏处，就是在我们平时编辑脚本的编辑器UltraEdit中，无法快速的打开相应的公共脚本。UltraEdit有一个方便的功能，如果是绝对路径，它可以方便的识别出来，然后在相应行右键即可直接打开该文件。可如果是我们这种引用式的路径，UltraEdit就无能为力了。因为它无法识别参数对应的绝对路径。&lt;/p&gt;

&lt;p&gt;几年前我用AutoHotKey实现了可以快速打开这种路径文件的方法。去年重构了一下，简单做了个界面&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;，只用填&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;params.txt&lt;/code&gt;和编辑器的路径，就可以方便的操作。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20141112_quick_open.png&quot; alt=&quot;Quick Open&quot; /&gt;&lt;/p&gt;

&lt;p&gt;具体操作方法是：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;在QuickOpen中设置好params.txt和编辑器的路径&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;；&lt;/li&gt;
  &lt;li&gt;将鼠标置于想打开的文件那一行；&lt;/li&gt;
  &lt;li&gt;同时按下”Alt”+”O”键，相应的文件就会在编辑器中自动打开；&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;AHK脚本已上传&lt;a href=&quot;https://github.com/happybit/playground/blob/master/20141112_QuickOpen.ahk&quot;&gt;GitHub&lt;/a&gt;。&lt;/p&gt;

&lt;hr /&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;借助了&lt;a href=&quot;http://www.autohotkey.com/board/topic/738-smartgui-creator/&quot;&gt;SmartGUI Creator&lt;/a&gt;，实话实说，AHK不是一个好的语言，生成界面更不友好。执行点简单的操作还行，稍大点的任务所需的effort，和其他如Python等脚本语言相比，就相当不划算了。这只能算是前几年刚接触AHK时自己感兴趣做的小实验而已； &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;具体params.txt可以是任何文件名，但参数定义的格式需如上例所示相同。Uedit32.exe也可是任意编辑器。 &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Probability Problem</title>
   <link href="https://blog.pzheng.me//2014/11/08/probability-problem/"/>
   <updated>2014-11-08T20:57:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/11/08/probability-problem</id>
   <content type="html">&lt;p&gt;上周因故需电话抢票，叫了几个朋友一起帮忙打电话抢。遇到一个问题，主办方有三部座机接受预订，我们是应该分散随机打三个电话，还是强攻其中一个呢？下面是我的分析。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;先做一些必要的assumption和simplification。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;假定&lt;/strong&gt;：&lt;/p&gt;

&lt;p&gt;共计有900人(N&lt;sub&gt;total_people&lt;/sub&gt;)抢票，3只(N&lt;sub&gt;groups&lt;/sub&gt;)电话接受预订，每个人接通的机率相同，只取前60个(N&lt;sub&gt;selected&lt;/sub&gt;)接通电话的人(平均每部电话有300人抢票，取前20人)。我方共有九人(N&lt;sub&gt;team_members&lt;/sub&gt;)，其中任一人打通电话即算抽中。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;方案&lt;/strong&gt;：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;方案1，九人均分为三组，各自拨打各自对应的电话；&lt;/li&gt;
  &lt;li&gt;方案2，九人全都打一个电话；&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：&lt;/p&gt;

&lt;p&gt;是第一种情况还是第二种情况被抽中的机率大？&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;解析&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;假设方案1中单组人抽中的概率为a。单组都抽不中的概率即为1-a。那么所有组都抽不中的概率为(1-a)&lt;sup&gt;3&lt;/sup&gt;。所以三组人抽中的概率为1-(1-a)&lt;sup&gt;3&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;假设方案2中抽中的概率为b，可知，a和b的计算方式类似，只是参与抽奖的我方人员个数不同。现在需算出a和b分别是多少。&lt;/p&gt;

&lt;p&gt;先计算b，在300人里，任意选20个人，不计顺序。抽中我方9人中任意一个的机率多大？换个思路，300人中，任意抽20个，我方9人全不在里面的机率多大？&lt;/p&gt;

&lt;p&gt;任选20个不计顺序，总共有C(300, 20)种可能。去掉我方9人后，剩余291个人中任选20个的可能为C(291,20)，所以这9个人都不被选中的可能是 C(291,20)/C(300,20)。9人被选中的机率b就是1- C(291,20)/C(300,20)=46.72%。&lt;/p&gt;

&lt;p&gt;同理，方案1中的a就是1-C(297,20)/C(300,20)。所以方案1的最终概率为1-(1-a)&lt;sup&gt;3&lt;/sup&gt;=46.37%&lt;/p&gt;

&lt;p&gt;看起来差别不大，可是如将电话数改为9部，方案1的机率骤降为16.94%，而方案2的机率下降不多，为44.08%。可知将鸡蛋放在一个篮子里的中奖机率还是高于放在多个篮子里的机率，尤其是篮子较多的时候。当然这个里面我忽略了很多因素，比如一旦一个人抽中，和他同team的一批人都将撤出等，这里就不考虑这些了。&lt;/p&gt;

&lt;p&gt;我将上面的计算过程用Python写了个小程序，放在&lt;a href=&quot;https://github.com/happybit/playground/blob/master/20141108_possibility_problem.py&quot;&gt;GitHub&lt;/a&gt;上了。如思路或计算过程有问题，请指正！&lt;/p&gt;

&lt;p&gt;对了，我最终选用了第二种方案抢票，而最后我们也非常幸运地抢到了。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Two Tips For This Week</title>
   <link href="https://blog.pzheng.me//2014/11/02/two-tips-for-this-week/"/>
   <updated>2014-11-02T20:27:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/11/02/two-tips-for-this-week</id>
   <content type="html">&lt;p&gt;I was annoyed by two issues for a long time when using Total Commander. This week I spent half an hour to tweak my settings and solved them quickly.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;open-text-file-in-existing-emacs-process&quot;&gt;Open text file in existing Emacs process&lt;/h2&gt;

&lt;p&gt;GNU Emacs is always openning on my computer. So I am trying to open and edit text files in the existed Emacs window instead of a new Emacs window.&lt;/p&gt;

&lt;p&gt;Firstly, you need to add below line in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.emacs&lt;/code&gt; file.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(and window-system (server-start))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then add below AutoHotKey snippet to your AHK configuration file.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;^!e::
    ClipTemp := ClipboardAll
    Clipboard :=
    Send, ^c
    ClipWait, 200
    S := Clipboard
    SplitPath, S, SName
    Clipboard := ClipTemp
    If (S != &quot;&quot;)
        Run, D:\Backup\Software\Develop\emacs-24.3\bin\emacsclientw.exe -n %S%
    return
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Please replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;D:\Backup\Software\Develop\emacs-24.3\bin\emacsclientw.exe&lt;/code&gt; to the correct Emacs client path on your PC.&lt;/p&gt;

&lt;p&gt;At last, select a text file and press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e&lt;/code&gt; simultaneously. This file would be opened in Emacs client immediately.&lt;/p&gt;

&lt;h2 id=&quot;unpack-archive-file-to-the-same-folder&quot;&gt;Unpack archive file to the same folder&lt;/h2&gt;

&lt;p&gt;There is a built-in shortcut key in Total Commander to unpack archive file: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F9&lt;/code&gt;. However, the unpacked files would be allocated to the folder in the other column of Total Commander. Is it possible to unpack them in the same folder as the original archive?&lt;/p&gt;

&lt;p&gt;Of course. We still need a little help from AutoHotKey. Below codes are coming from &lt;a href=&quot;http://www.ghisler.ch/wiki/index.php/AutoHotkey:_Unpack_each_archive_to_a_separate_subdir&quot;&gt;internet&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;^!u::
IfWinActive ahk_class TTOTAL_CMD
{
	PostMessage, 1075, 509
	WinWaitActive, ahk_class TDLGUNZIPALL
	Send, {Del}
	Control, Check, , TCheckBox1
	Send, {Enter}
}
else
	Send ^!+{F9}
return
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Select the zip file in Total Commander and press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;u&lt;/code&gt;. It would work like a charm. It’s time to replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F9&lt;/code&gt; to this shotcut key.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Chinese Input on Arch Linux</title>
   <link href="https://blog.pzheng.me//2014/10/29/chinese-input-on-arch-linux/"/>
   <updated>2014-10-29T07:00:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/10/29/chinese-input-on-arch-linux</id>
   <content type="html">&lt;p&gt;Linux下的输入法，有几种主流的frameworks，&lt;a href=&quot;https://code.google.com/p/ibus/&quot;&gt;IBus&lt;/a&gt;，&lt;a href=&quot;https://fcitx-im.org/wiki/Fcitx&quot;&gt;fcitx&lt;/a&gt;和&lt;a href=&quot;http://sourceforge.net/projects/scim/&quot;&gt;SCIM&lt;/a&gt;等。基于这几种框架，又有数种输入法可供选择。看起来种类繁多，但实际试用后能满意的却寥寥。以下是我在Arch Linux上切换各种中文输入法的一点经历。&lt;/p&gt;

&lt;p&gt;注，本人习惯使用简体中文全拼输入法，Arch Linux桌面环境为LXDE。在Windows上大部分时间使用搜狗输入法。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;最初安装Arch Linux时，循着安装手册安装了ibus-pinyin。丑是丑了点，好歹能用。头两年某天常规地&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo pacman -Syu&lt;/code&gt;，升级了系统和IBus后，ibus-pinyin忽然就不能工作。据Arch Linux wiki的&lt;a href=&quot;https://wiki.archlinux.org/index.php/IBus#Input_method_engines&quot;&gt;IBus词条&lt;/a&gt;说，是ibus-pinyin不再维护了：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Package currently not maintained and partly broken with latest ibus base.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;转而使用页面上推荐的ibus-libpinyin，倒是能启动并使用。问题是响应速度太慢了，常常一句话打得稍快点就漏字，很不爽。将就使用一段时间，实在忍不了，继续寻找适合的输入法。过程中也试用过ibus-sunpinyin和ibus-cloud-pinyin，都因各种原因放弃。&lt;/p&gt;

&lt;p&gt;正好这个时候，&lt;a href=&quot;http://blog.felixc.at/2014/04/sogou-pinyin-for-linux-new-release/&quot;&gt;发现&lt;/a&gt;Windows上常用的搜狗拼音出&lt;a href=&quot;http://pinyin.sogou.com/linux/&quot;&gt;Linux版本&lt;/a&gt;了。觊觎搜狗的词库，就顺便从IBus阵营切换到fcitx阵营。词库是丰富了，无奈搜狗继承了大公司Linux产品都是后妈养的这个优良传统（参见&lt;a href=&quot;http://im.qq.com/qq/linux/&quot;&gt;Linux QQ&lt;/a&gt;的境遇），活脱脱一个半成品。自启动除了fcitx本身的自启，将&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/xdg/autostart/fcitx-autostart.desktop&lt;/code&gt;拷贝至&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/autostart/&lt;/code&gt;，还需要启动面板程序&lt;em&gt;qimpanel&lt;/em&gt;。在自启文件里（我的机器上是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/lxsession/LXDE/autostart&lt;/code&gt;），加上:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@sogou-qimpanel
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这样还有问题，左下角经常有个小黑框挡着，不影响使用，但影响心情啊。放狗&lt;a href=&quot;http://askubuntu.com/questions/451095/lubuntu-14-04-and-fcitx-qimpanel-how-to-remove-this-black-square&quot;&gt;搜出来&lt;/a&gt;，可以通过安装&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compton&lt;/code&gt;解决：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Install compton from AUR;&lt;/li&gt;
  &lt;li&gt;create &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.compton.conf&lt;/code&gt; according to &lt;a href=&quot;http://ubuntuforums.org/showthread.php?t=2144468&quot;&gt;this post&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;modify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shadow = false&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/lxsession/LXDE/autostart&lt;/code&gt;, add ”@compton”&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;可即使是这样，还是经常出问题，面板经常无法正常自启，动不动就提示“搜狗输入法面板无法启动”，需要手工启动&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sougou-qimpanel&lt;/code&gt;。而且词汇记忆能力极弱，我平时输入中使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;在&lt;/code&gt;多于&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;再&lt;/code&gt;，可无论我重选多少次。每次当我键入&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zai&lt;/code&gt;时，出现在首词的永远是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;再&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;愤而转向“&lt;a href=&quot;https://code.google.com/p/rimeime/&quot;&gt;中州韵输入法&lt;/a&gt;”，也就是Mac上有名的“鼠须管输入法”，Windows上称作“小狼毫输入法”。安装非常简单，配置是纯文本形式，非常好。使用了几天，暂时还在慢慢摸索中，未出现各种奇怪的问题。而且基于用户习惯积累词汇功能很强大，基本上输入过一两次的词组，后面就会优先跳出来。慢慢积累，就会越用越顺手。现在Windows上的搜狗输入法也被我卸载，换成“小狼毫”了 :smile:&lt;/p&gt;

&lt;p&gt;以上通过中州韵输入法“明月拼音”输入。&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>SFN and CFN</title>
   <link href="https://blog.pzheng.me//2014/10/26/sfn-and-cfn/"/>
   <updated>2014-10-26T17:00:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/10/26/sfn-and-cfn</id>
   <content type="html">&lt;p&gt;在UMTS中，同步是很重要的一项工作。如果同步出现问题，轻则某些用户无法建立通话连接，重则整个小区网络瘫痪。而同步中，有两个重要的概念，经常会碰到。那就是SFN和CFN，所有的物理信道都将基于SFN对齐或做一定的偏置。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;要谈SFN和CFN，还有一个BFN不得不提：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;BFN: Node &lt;strong&gt;B&lt;/strong&gt; &lt;strong&gt;F&lt;/strong&gt;rame &lt;strong&gt;N&lt;/strong&gt;umber. 一个Node B内所有小区的参考时钟，是Node B-specific的；&lt;/li&gt;
  &lt;li&gt;SFN: &lt;strong&gt;S&lt;/strong&gt;ystem &lt;strong&gt;F&lt;/strong&gt;rame &lt;strong&gt;N&lt;/strong&gt;umber. 每个小区独立的时间，是cell-specific的；&lt;/li&gt;
  &lt;li&gt;CFN: &lt;strong&gt;C&lt;/strong&gt;onnection &lt;strong&gt;F&lt;/strong&gt;rame &lt;strong&gt;N&lt;/strong&gt;umber. 表征UE和UTRAN之间的时间关系，是user-specific的；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SFN是在BFN的基础上，加上T&lt;sub&gt;cell&lt;/sub&gt;值区分同一个Node B下各个小区的。T&lt;sub&gt;cell&lt;/sub&gt;取值0~9，代表的实际偏置值是T&lt;sub&gt;cell&lt;/sub&gt;*256 chips。同频小区不可使用相同的T&lt;sub&gt;cell&lt;/sub&gt;，否则UE将不能同步上小区。&lt;/p&gt;

&lt;p&gt;每个小区的SFN是在BCH上发送的，UE收到并解出BCH后，将基于SFN推算出CFN。&lt;a href=&quot;http://www.3gpp.org/DynaReport/25211.htm&quot;&gt;TS25.211&lt;/a&gt; subclause 7中提到的转换关系如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;CFN = (SFN + (frame_offset*38400 + chip_offset) Mod 38400) Mod 256
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;几条基于小区时间(而不是RL-specific或UE-specific)的物理信道，其他信道具体时序关系请参看TS25.211 subclause 7.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;小区的P-CCPCH和SFN是对齐的；&lt;/li&gt;
  &lt;li&gt;HS-SCCH和小区的P-CCPCH的SFN是对齐的，HS-PDSCH落后HS-SCCH两个slots;&lt;/li&gt;
  &lt;li&gt;E-AGCH是在小区的P-CCPCH基础上，延迟5120个chips对齐的；&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>BER and BLER</title>
   <link href="https://blog.pzheng.me//2014/10/20/ber-and-bler/"/>
   <updated>2014-10-20T07:00:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/10/20/ber-and-bler</id>
   <content type="html">&lt;p&gt;BLER and BER are two of the most important key performance indicators(KPI) in any of those wireless products. Let’s get a quick review about what they mean and what performance they indicate exactly.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;BLER stands for &lt;strong&gt;B&lt;/strong&gt;lock &lt;strong&gt;E&lt;/strong&gt;rror &lt;strong&gt;R&lt;/strong&gt;ate while BER is &lt;strong&gt;B&lt;/strong&gt;it &lt;strong&gt;E&lt;/strong&gt;rror &lt;strong&gt;R&lt;/strong&gt;ate. Here &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block&lt;/code&gt; means transport blocks and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bit&lt;/code&gt; is information bits. Both BER and BLER are statistic results over a certain period.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The Bit Error Ratio is defined as the ratio of the bits wrongly received to all data bits sent. The bits are the information bits &lt;strong&gt;above the convolutional/turbo decoder&lt;/strong&gt;. A Block Error Ratio is defined as the ratio of the number of erroneous blocks received to the total number of blocks sent. An erroneous block is defined as a Transport Block, the cyclic redundancy check (CRC) of which is wrong.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here comes a simple flow chart of decoding downlink DPDCH on UE side. As you can see, BLER measurement takes place at “CRC detection” phase within BTS physical layer. And BER is measured after CRC detection (most often in RNC) when information bits are received and then compared with an &lt;strong&gt;already-known data pattern&lt;/strong&gt;. The pattern could be either fixed data or PN9/PN15. Of course pseudo noise patter is preferred.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20141020_ber_bler_blocks.jpg&quot; alt=&quot;BER and BLER&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In above figure, there is also a “DPDCH BER measurement” which is mainly used in internal R&amp;amp;D. This BER is measured by physical layer. Once the data is decoded, physical layer would encode the data and compare it with the original received data from RAKE receiver to calculate DPDCH BER.&lt;/p&gt;

&lt;p&gt;BLER indicates the quality of the whole network which is more critical. Because even there is data loss/error during transmission, the original data could be restored to perfect due to coding gain of turbo/convolutional algorithm. Thus BER just reflects the estimation of coding gain.&lt;/p&gt;

&lt;p&gt;Usually, in laboratory, we expect zero BER for each channel during low/medium-load testing. And pass criterion for BLER depends on different services and their QoS(Quality of Service). Outer Loop Power Control could help to maintain the BLER target.&lt;/p&gt;

&lt;p&gt;If BER/BLER doesn’t meet the criteria, we need firstly to fine-tune the test environment. If the test environment could be excluded from suspicion, for BER issue, we can compare the sending and receiving data to check whether they follow the same pattern. For BLER issue, we can start from debugging CRC functionality and then check from top to bottom to find the root cause step by step. In such way, we have found an undermining bug which caused the CRC data was different during retransmission.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Modulation difference between UL and DL</title>
   <link href="https://blog.pzheng.me//2014/10/12/ul-dl-difference/"/>
   <updated>2014-10-12T20:00:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/10/12/ul-dl-difference</id>
   <content type="html">&lt;p&gt;Last time, one of my colleagues asked me an interesting question regarding the difference of modulation between uplink and downlink. And I’d like to share with you here today.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;As you know, IQ(In-phase &amp;amp; Quadrature) modulation is widely used in various wireless technologies. And QPSK is adopted for downlink DCH while BPSK for uplink in UMTS. The difference is, one copy of downlink data from one physical channel will split into two and each one will be mapped to each IQ phase. However uplink data from one physical channel would be only mapped to one phase, either in-phase part or quadrature part. Please refer to below figure for illustration.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20141012_iq_modulation.png&quot; alt=&quot;IQ modulation&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I didn’t figure out the reason why they are different from official materials. Here are some personal thoughts on it.&lt;/p&gt;

&lt;p&gt;Firstly and most importantly, BPSK is less complicated than QPSK, which means it needs less power to modulate the signals. And as you know, UE battery power is the key and critical factor for all design considerations.&lt;/p&gt;

&lt;p&gt;Secondly, if downlink chooses the same modulation as uplink, it would consume more code resource which is limited and quite precious. At the beginning, the data rate for R99 is not that high. According to below table, you can see that for the same data rate, spreading factor for downlink is twice as minimum SF for uplink. And for the downlink, the bottleneck is code resource instead of power consuming.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Service/data rate&lt;/th&gt;
      &lt;th&gt;UL min SF&lt;/th&gt;
      &lt;th&gt;DL SF&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;4.75AMR&lt;/td&gt;
      &lt;td&gt;SF128&lt;/td&gt;
      &lt;td&gt;SF256&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;12.2AMR&lt;/td&gt;
      &lt;td&gt;SF64&lt;/td&gt;
      &lt;td&gt;SF128&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;32kbps&lt;/td&gt;
      &lt;td&gt;SF32&lt;/td&gt;
      &lt;td&gt;SF64&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;57.6kbps&lt;/td&gt;
      &lt;td&gt;SF16&lt;/td&gt;
      &lt;td&gt;SF32&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;64kbps&lt;/td&gt;
      &lt;td&gt;SF16&lt;/td&gt;
      &lt;td&gt;SF32&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;128kbps&lt;/td&gt;
      &lt;td&gt;SF8&lt;/td&gt;
      &lt;td&gt;SF16&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Last, multiple physical channels with big SF will cause larger PAR(peak to average power ratio) than single physical channel with small SF. For instance, one DPDCH channel with SF4 carries the same rate of data as two DPDCH channel with SF8. However, according to TFC selection mechanism in 3GPP(as well as E-TFCI selection for E-DCH), UE inclines to choose single SF4 channel other than two SF8 channels. This is also considered from UE power consumption perspective.&lt;/p&gt;

&lt;p&gt;Since I didn’t search around for the technical discussion/meeting minutes during the initial design. This is just my own assumption. Please let me know if you have second opinion.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>E-DCH serving cell</title>
   <link href="https://blog.pzheng.me//2014/10/12/edch-serving-cell/"/>
   <updated>2014-10-12T17:00:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/10/12/edch-serving-cell</id>
   <content type="html">&lt;p&gt;Kind of busy these days. I will simply share some basic knowledge from my personal wiki. The first one is about the definition of E-DCH serving cell.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Once you read about all kinds of technical materials, like 3GPP technical specification or those feature documentations within your company. You might probably have met several specific terms related to E-DCH serving cell, which are not explicitly explained. Therefore you would confuse about them. Let me get it straight.&lt;/p&gt;

&lt;p&gt;Actually, most of them come from &lt;a href=&quot;http://www.3gpp.org/DynaReport/25321.htm&quot;&gt;3GPP TS25.321&lt;/a&gt; subclause 3.1.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Serving E-DCH cell&lt;/strong&gt;: Cell from which the UE receives Absolute Grants from the Node-B scheduler. A UE has one Serving E-DCH cell.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;E-DCH active set&lt;/strong&gt;: The set of cells which carry the E-DCH for one UE. For FDD, in CELL_FACH state and Idle mode, the E-DCH active set consists of the Serving E-DCH cell only. There are &lt;strong&gt;at most 4 cells&lt;/strong&gt; within one E-DCH active set for a certain UE.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Non-serving E-DCH RL or Non-serving RL&lt;/strong&gt;: Cell which belongs to the E-DCH active set but does not belong to the Serving E-DCH RLS and from which the UE can receive one Relative Grant. The UE can have zero, one or several Non-serving E-DCH RL(s).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Serving E-DCH RLS or Serving RLS&lt;/strong&gt;: Set of cells which contains at least the Serving E-DCH cell and from which the UE can receive and combine one Relative Grant. The UE has only one Serving E-DCH RLS. For FDD, in CELL_FACH state and Idle mode, the Serving E-DCH RLS or Serving RLS contains the Serving E-DCH cell only, from which the UE can receive one Relative Grant.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For better understanding, I draw a picture to illustrate.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20141012_edch_serving_cell.png&quot; alt=&quot;E-DCH serving cell&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As you can see from above picture, cell 2 of Node B 1 is the Serving E-DCH cell for this UE. Cell 2 and cell 3 from Node B 1 and cell 1 from Node B2 consist of E-DCH active set. While Serving E-DCH RLS includes cell 2 and cell 3 of Node B 1. And Cell 1 of Node B 2 is Non-serving E-DCH RL.&lt;/p&gt;

&lt;p&gt;Please note, the presumption for Serving E-DCH RLS in above picture is cell 2 and cell 3 are controlled and scheduled by the same scheduler. Or they share the same source for E-RGCH decision. Otherwise they cannot be called as a Serving E-DCH cell.&lt;/p&gt;

&lt;p&gt;And you can find that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Serving E-DCH cell could send E-AGCH and all three kinds of E-RGCH, i.e. UP, Hold, and DOWN;&lt;/li&gt;
  &lt;li&gt;The cells in Serving E-DCH RLS other than Serving E-DCH cell could only send E-RGCH with all three possible decisions: UP/HOLD/DOWN;&lt;/li&gt;
  &lt;li&gt;Non-serving E-DCH RL could only send E-RGCH with two kinds of E-RGCH: HOLD/DOWN;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Why there is no UP for Non-serving E-DCH RL? Think about it. Basically E-RGCH from non-serving E-DCH RL is major for power overload control and not in charge of UE scheduling, which means non-serving E-DCH RL only send E-RGCH once the total cell power is exceeded certain threshold. Then it would send E-RGCH DOWN to those non-serving UEs in order to decrease the interference from other cells.&lt;/p&gt;

&lt;p&gt;All above definition are from UE point of view. However there is also a term from cell perspective. That is &lt;strong&gt;Non-serving UE&lt;/strong&gt;. Generally non-serving UE is the user equipment whose serving cell is not this cell. Talk to above picture, we can say this UE is non-serving UE for cell 3 of Node B 1 as well as cell 1 of Node B 2.&lt;/p&gt;

&lt;p&gt;This is just my personal understanding. Please correct me if I am wrong. I’d be really appreciated.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Nine Algorithms</title>
   <link href="https://blog.pzheng.me//2014/09/21/nine-algorithms/"/>
   <updated>2014-09-21T17:00:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/09/21/nine-algorithms</id>
   <content type="html">&lt;p&gt;最近看了&lt;em&gt;John MacCormick&lt;/em&gt;写的&lt;a href=&quot;http://www.amazon.com/Nine-Algorithms-That-Changed-Future/dp/0691158193&quot;&gt;Nine Algorithms That Changed the Future: The Ingenious Ideas That Drive Today’s Computers&lt;/a&gt;。此书为科普读物，适合对计算机不太熟悉但感兴趣的人阅读。国内中信出版社已发行&lt;a href=&quot;http://book.douban.com/subject/24529132/&quot;&gt;中译版&lt;/a&gt;。&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;intro&quot;&gt;Intro&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;http://img3.douban.com/lpic/s7118015.jpg&quot; alt=&quot;Nine algorithms that changed future&quot; /&gt;&lt;/p&gt;

&lt;p&gt;书中提到的九大算法：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;搜索引擎索引：如何在海量网页中进行关键字搜索；&lt;/li&gt;
  &lt;li&gt;Page Rank：如何决定网页搜索中的排名高低；&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;可计算性：通过反证法推论能发现所有软件crash bug的程序是不存在的；&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;my-interests&quot;&gt;My interests&lt;/h2&gt;

&lt;h3 id=&quot;encoding&quot;&gt;Encoding&lt;/h3&gt;

&lt;p&gt;这几大算法中，和我工作直接相关的，就是“纠错码”，如UMTS中常用的Turbo编码和convolutional编码。而各种编码机制的原理，简而言之，就是用冗余换取信息传递时的损耗。好的编码算法，可以传递尽量少的冗余信息，但仍能最大程度的还原传递过程中，被破坏过的原始信息。实际使用中，并不是冗余度越低越好。因为不是所有产品对纠错要求都这么高，而这种算法相对复杂，对计算能力和功耗要求较高，因此未必适合所有产品。应基于产品应用场景和实际硬件，选择最合适的编码算法。&lt;/p&gt;

&lt;h3 id=&quot;encryption&quot;&gt;Encryption&lt;/h3&gt;

&lt;p&gt;其他算法中，个人感兴趣的有“公钥加密”，“数据压缩”，“数字签名”和“可计算性”。其中“公钥加密”和“数字签名”都涉及到&lt;a href=&quot;http://en.wikipedia.org/wiki/RSA_(cryptosystem)&quot;&gt;RSA加密算法&lt;/a&gt;，该算法核心是欧拉定理。而至今它都未被破解的原因，在于现今仍无法找到有效的方式分解一个大的整数的因子，只能暴力破解。如大家一眼可以看出，14的两个因子是2和7。而如果是9709549，你可能要花上一番功夫才能知道，它的两个质数因子分别是2719和3571。如长度更大，想分析出它的因子难度将更大，甚至用最强劲的计算机也无法暴力破解。&lt;/p&gt;

&lt;h3 id=&quot;compression&quot;&gt;Compression&lt;/h3&gt;

&lt;p&gt;“数据压缩”的基本原理是找到数据中重复的pattern，然后用更精简的方式(shorter symbol)替代那些重复的信息比特。和编码相反，它的原理是尽可能的消除冗余。也就是说，如果信息是完全随机杂乱，无任何规律可循，那么它的可压缩度就为0。最初的压缩算法是香农(Claude Shannon)1948年在贝尔实验室提出的。（又见香农！）&lt;/p&gt;

&lt;h3 id=&quot;computable&quot;&gt;Computable&lt;/h3&gt;

&lt;p&gt;“可计算性”涉及到图灵机(Turing machine)，作者通过简单的反证法，先验证了无法找到一种程序，可以在“输入的程序在输入自己时，若crash就输出yes；若不crash输出就直接crash”。反推出“能找到所有软件crash bug的程序”是不存在的。这里之所以我会感兴趣，说明希望一劳永逸能用机器寻找出&lt;strong&gt;所有&lt;/strong&gt;程序bug是不存在的，起码在一段时间内，测试人员还是有口饭吃的。但以后机器变得更加智能，就不好说了。&lt;/p&gt;

&lt;h3 id=&quot;database-consistency&quot;&gt;Database consistency&lt;/h3&gt;

&lt;p&gt;对Database不是很熟悉，此书介绍的主要集中在如何保证数据库的一致性上，因为一旦出现不一致，就可能发生数据死锁(dead-lock)的情况。为了保证一致性，这里提到了一种方法，竟然在我工作中也经常使用，就是prepare-then-commit。因为数据库可能分散在多个备份中，一旦其中一份(primary)发生了更新，其他几份也要相应更新。使用prepare-then-commit方式，可以最大限度的将准备工作在各个备份处先做好，然后commit时同时生效即可。如果在prepare过程中，某个备份出了问题，可以很轻易对已经prepare好的其他备份执行cancel即可。&lt;/p&gt;

&lt;p&gt;这个原理使用在UMTS中，就是NBAP协议中存在prepare/commit/cancel message，保证了各网元以及Node B各子模块系统在重配过程中能协同生效。&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;看这本书主要为了消遣，最大的收获是作者讲解技术问题时的方式，有些算法的原理不算复杂。但一旦涉及到如何实现和应用，就会有非常多的技术名词和细节。不过作者通过一些精巧设计的例子，如通过“染色”讲解“公钥加密”，“锁和钥匙”解释“数字签名”等，将复杂的理论化解为普通人也能看懂的道理，相当了不起。上半年做过一次某feature的workshop，为了让大家能更深入地了解其中的原理，也做过类似的尝试。想用更生动活泼的例子来解释，但效果并不算好。发现要找到合适的例子，最好是基本原理互通但浅显还不生硬，还真是不容易！&lt;/p&gt;

&lt;p&gt;另外一点启发就是，有些算法，起初都不复杂，如“搜索引擎”、“图像识别”和“压缩”最初的原理非常简单直观。但能将生活中的发现提炼成算法，却不容易。而能将算法实现和演进，并真正应用到实际中，又是一次大的飞跃。&lt;/p&gt;

&lt;p&gt;而算法的普适性也让我非常吃惊，不用说现在计算机领域广泛应用的加密，压缩，编码等算法，就是上文提到的“prepare-then-commit”这种方法，既应用于database操作，又适用于通信领域的信令面流程。应用的广泛程度，着实让人震惊。学习的深度是一方面，广度也可以让人接触到其他领域优秀的方式方法，反过来优化自己工作的领域。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Low-hanging Fruit</title>
   <link href="https://blog.pzheng.me//2014/09/14/low-hanging-fruit/"/>
   <updated>2014-09-14T22:58:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/09/14/low-hanging-fruit</id>
   <content type="html">&lt;p&gt;业界，尤其是测试界，最近几年反复被提及的，除了Agile/Scrum/TDD，可能就是Exploratory Testing（ET）了。个人觉得，不过是新瓶装旧酒，强调的无非还是“学习-积累-应用”这一套行之四海的方法。有心人一定或多或少都用ET的方法进行过测试。不过事实就是这样，任何事一旦套上名头，唬起人来似乎也格外有自信。&lt;/p&gt;

&lt;p&gt;不过我今天想说的可不是ET，而是一种不需要花费大量心力和时间，但也能收获一些bug的方法。也就是人们常说的&lt;em&gt;Low-hanging Fruit&lt;/em&gt;，我个人简称为LHF :smile:.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140914_low-hanging_fruit.png&quot; alt=&quot;low-hanging fruit&quot; /&gt;&lt;/p&gt;

&lt;p&gt;ET确实是谁都可以做，不过想做得好，学习积累的过程必不可少。而经验丰富的工程师，也更易于找到软件有风险的地方，并且有针对地创建不同的场景来做ET。进而快速地搭建环境并验证，这样才能发挥ET最大的功效。而这一点，对我们现在的团队，受限于测试工具/框架/软件复杂度/外部依赖等各种原因，如果想创建一套稳定的测试环境来快速验证各种场景，还是需要花费不少功夫的。这样就极大限制了ET在团队中的推广，大家也更倾向于在已有稳定的环境中工作。&lt;/p&gt;

&lt;p&gt;当然，环境和场景如果一成不变，也就意味着有大量的bugs，可能因为场景缺失而泄露。但如果我们能在有限的空间内，用很少的effort找到更多的bugs，是否也是一件有必要且极划算的买卖呢？事实上，过去两三年，我一直在跟踪统计我们组测试过程中泄露出去的defects。发现有1/3强的问题都是和“check points缺失”有关，排在所有原因中的首位。&lt;/p&gt;

&lt;p&gt;这就意味着，其实我们的场景和环境都已经搭建好了，甚至case都有的，只是因为各种原因，未对某些结果检查，导致问题漏过去了。光想想就让人沮丧：如果能先期对case和pass criteria进行一番refactor，我们就能减少1/3的bug泄露。&lt;/p&gt;

&lt;p&gt;亡羊补牢犹未晚也。那就来总结一下，那些容易被我们忽视的low-hanging fruit. 请注意，low-hanging fruit绝不等于low value fruit.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;软件打印log的检查。系统打印出的任何error和warning都可能是潜在的问题，尤其是老版本上没有，新版本上出现的这种打印尤其要注意。而log打印也会占用CPU load，因此如果发现massive log printing，一定也是某个component出现了异常导致的；&lt;/li&gt;
  &lt;li&gt;CPU load检查。在容量测试和功能测试中都应该注意，尤其是软件开发初期，可能压力并不大的情况下，就出现了高到异常的CPU load（可通过经验或简单的比例来推算满负荷时的CPU load）。这样就不用等到软件开发后期，容量测试进行中发现问题再进行refactor。问题发现得越早，refactor或优化的成本越低；&lt;/li&gt;
  &lt;li&gt;增加loop数来测试简单的stability。比如让软件在晚上或者周末自动跑成千上万个loop。软件中某些bug，可能通过简单的几次循环，未必能发现得到。尤其是一些内存泄露的问题，往往要积累到一定程度，才能彻底爆发出来。而这种问题，一旦发现一个，也是价值非常高的bug了。&lt;/li&gt;
  &lt;li&gt;尝试不同的参数值和参数组合。虽然场景不一定好轻易改变，但参数改变还是很容易的。作为系统测试人员，我们不用遍历所有参数值（事实上不可能也没必要），但我们可以基于经验来选择一些关键参数来验证它们的边界或者组合条件。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;个人而言，ET带给我最大的感受，是先学习后印证想法的快乐，以及目标是A功能结果斜刺里杀出个B功能的bug这种意外之喜。而LHF，就是躺在地上捡钱的快乐–大量的bugs被人视而不见–稍微动动手就可以摘到那些挂得很低的果子。而这，对一些新人而言，是可以积攒大量bug经验的绝好机会。量变引发质变，才有机会摘到那些high-hanging fruit.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Dogfight: Apple vs. Google</title>
   <link href="https://blog.pzheng.me//2014/09/07/dogfight-apple-vs-google/"/>
   <updated>2014-09-07T23:30:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/09/07/dogfight-apple-vs-google</id>
   <content type="html">&lt;p&gt;换了新住处后，上下班都得坐公交。本以为时间会更紧张，不想等车坐车的时间倒多了出来。把几本一直断断续续看的书看完了。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;上个月翻译过一篇关于Apple发布初代iPhone的&lt;a href=&quot;http://blog.pzheng.me/2014/08/04/and_then_steve_said/&quot;&gt;文章&lt;/a&gt;。后循着页面找到作者写的书&lt;a href=&quot;http://www.amazon.com/Battle-Titans-Transforming-Previously-Published-ebook/dp/B00BIV1R98&quot;&gt;Dogfight: How Apple and Google Went to War and Started a Revolution&lt;/a&gt;，前面提到的那篇文章就是这本书第一章的略微改写。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140907_dogfight_cover.jpg&quot; alt=&quot;cover of dogfight&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这本书前面几章讲述了iPhone/iPad和Android分别在Apple和Google诞生的故事，也就是书名中”Went to War”的部分。两家超级大公司的营销能力，加上科技媒体时不时地爆料和八卦，以及两大阵营粉丝在网络上卖力地宣传和时不时的火拼，普通人对这些故事多少都有些耳闻。而这本书在此基础上，讲了更多幕后的故事。得益于作者讲故事的手法，读起来饶有兴致。&lt;/p&gt;

&lt;p&gt;最后几章集中在“Started a Revolution”，即smartphone和tablet（主要是iPad）是如何改变传统媒体，娱乐和有线电视网络的。对美国这方面不熟悉，所以感触不深。&lt;/p&gt;

&lt;p&gt;作者在介绍跨时代新产品是如何艰难地诞生的同时（这一点，在前面翻译的那篇文章里已有所提及，作者喻之为Moon Mission登月计划），对点题的&lt;strong&gt;dogfight&lt;/strong&gt;也着墨颇多。而这里的fight，不光是Apple和Google之间，还有部门与部门之间，部门内部团队之间，个人与个人之间的各种fight，让我印象最深的当属Scott Forstall和Tony Fadell之间的竞争。&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Tony Fadell&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://upload.wikimedia.org/wikipedia/commons/thumb/6/67/Tony_Fadell.jpg/570px-Tony_Fadell.jpg&quot; alt=&quot;Tony Fadell&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Scott Forstall&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Scott_Forstall.jpg/400px-Scott_Forstall.jpg&quot; alt=&quot;Scott Forstall&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;background&quot;&gt;Background&lt;/h3&gt;

&lt;p&gt;Tony Fadell和Scott Forstall同岁(1969年出生)。Scott Forstall于1992年从Stanford毕业后加入NeXT就跟着Jobs干了。Fadell直到2001年才加入Apple，为制造初代iPod服务。但Fadell升得比Forstall快多了，iPod在2006年贡献了Apple 40%的利润，市场份额大于70%。很快他就成了iPod部门的老大并晋升Jobs核心圈。&lt;/p&gt;

&lt;p&gt;虽然Forstall跟Jobs的时间更长，但一直不是核心圈的人物。他主要负责MAC上的应用软件，如Address Book, Mail, Safari和Photo Booth。&lt;/p&gt;

&lt;p&gt;同事认为是在2003-4年间，Jobs才和Forstall变得熟起来的。那时Forstall患了严重的胃病，刚好Jobs也第一次确诊胰腺癌。Jobs最初希望用食疗治自己的癌症，结果为Forstall设计的一套养生法治好了他的胃病。之后，Forstall就越来越多的出现在Jobs的周一高层会议上了。照理说，Forstall不应知道iPhone项目的，因为他还不够高级。但当他从这些核心圈的讨论中发现Jobs想生产一款手机时，他就开始想方设法挤进来了。&lt;/p&gt;

&lt;p&gt;2011年Bloomberg报道，说Forstall从很多方面讲，就是迷你版的Jobs。他是那种为每个细节抓狂的经理。和Jobs相同，能用通俗易懂的语言描述技术问题。他喜欢银色款的奔驰SL55 AMG，和Jobs同款。甚至相同的台上行头：黑鞋，牛仔裤，黑色拉链毛衣。”（瞧瞧，不光国内这么多雷布斯，罗布斯，国外也不少啊。）&lt;/p&gt;

&lt;h3 id=&quot;fight-before-iphone&quot;&gt;Fight before iPhone&lt;/h3&gt;

&lt;p&gt;在iPhone之前,Andy Grignon就发现他俩不和的苗头。2004年Forstall阻止Andy去Fadell的部门。Grigon已经为Forstall工作了三年，产品是Dashboard和iChat。他认为他们在工作上还算是不错的朋友，他们在周末还会一起去攀岩。但是当Fadell给Grignon提供了一份更好的工作机会时，Forstall阻止了。他先告诉Grignon，支持他要走的想法。接着背着Grignon，他跑去告诉Jobs让他阻止这件事。Jobs下令禁止任何人从SW team (Forstall掌管)迁移到iPod team(Fadell掌管)。 敌意就是从那时开始的。&lt;/p&gt;

&lt;h3 id=&quot;fight-for-iphone&quot;&gt;Fight for iPhone&lt;/h3&gt;

&lt;p&gt;制造iPhone过程中，Jobs让Forstall和Fadell对打。Jobs非常善于玩弄这一套。一会是Tony，一会是Forstall，接着又是Tony，然后还是Forstall，不断循环。&lt;/p&gt;

&lt;p&gt;Apple的很多人认为，这场战争不平等。Fadell专长HW。Forstall专长SW。Forstall更占优，因为Jobs对SW和工业设计更感兴趣。当iPhone开始时，Forstall组织了一个秘密团队工作在这个项目上。Fadell有一段时间都不知道这个事情。&lt;/p&gt;

&lt;p&gt;官方上来说，iPhone最初是由Fadell来管理的。因为Fadell管理iPod部门，很自然的，iPhone就是iPod的升级。但Forstall和Jobs想让OS X运行在iPhone上。Jobs不确定是否可行。所以最终当Forstall的团队成功实现了，Forstall就赢得了对整个iPhone项目的控制。iPhone在2007年中开始发售时，Forstall掌控了大量软件工程师。几个月后，Apple发布了iPod touch。同样，Forstall也控制了那个产品线上的大量软件工程师。&lt;/p&gt;

&lt;h3 id=&quot;after-iphone-ship&quot;&gt;After iPhone Ship&lt;/h3&gt;

&lt;p&gt;iPhone出货后，高官们都去到各大Apple直营店造势宣传。Jobs去的是Palo Alto那一家。Jobs直接走到Fadell跟前，在商店的一个角落和他交谈了一个小时，故意冷落Forstall。&lt;/p&gt;

&lt;p&gt;因为直到那天，从发布到销售的那六个月，所有事都是Fadell的错。任何硬件，出货时间delay，制造问题，都是Fadell的问题。Forstall作为软件的头不会错。但是当各大媒体测评报告出街后，发现iPhone的email软件不能使用，相反人人都爱死了iPhone的硬件。瞬间Forstall变成了坏孩子，Fadell成了天之骄子。&lt;/p&gt;

&lt;p&gt;同事说：“好笑的是，Jobs故意背对着Forstall，Fadell全程都可以看到Forstall。Forstall脸上的表情相当好笑。好似他爸告诉他再也不会爱他一样。”&lt;/p&gt;

&lt;h3 id=&quot;latest-news&quot;&gt;Latest News&lt;/h3&gt;

&lt;p&gt;2008年Fadell辞职，他拒绝承认是和Forstall关系不和导致的。辞职后创立了著名的Nest，生产智能家居设备。后被Google收购。&lt;/p&gt;

&lt;p&gt;Forstall后来变成了一个只会“抢别人的功劳，但让别人承担自己的罪责”的经理，并将自己视为Apple的CEO。2011年Bloomberg报道，首席设计师Jony Ive和技术部老大Bod Mansfield非常讨厌Fostall，据称他们拒绝和Forstall开会，除非Tim Cook也在场。Tim Cook最后在2012年将Forstall赶出了Apple。&lt;/p&gt;

&lt;p&gt;Fadell在Forstall被赶出Apple之后，对BBC称”活该”。Forstall离开Apple后没再公开露面过。&lt;/p&gt;

&lt;h3 id=&quot;funny-stories&quot;&gt;Funny Stories&lt;/h3&gt;

&lt;p&gt;另外几个好笑的故事。虽然一定程度的竞争可以让组织保持更积极的状态，从结果导向来说，Jobs玩的这一局也相当漂亮。但仍避免不了一些负面影响。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;那两年，Forstall和Fadell打得正欢，导致Jobs不得不为了一些很小的事情介入进来仲裁。比如需要Jobs决定在iPhone上使用哪个组的boot loader。。。&lt;strong&gt;[政治斗争不幸把设局的人也卷进去了]&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;这种狗咬狗的战争，也影响了下面干活的人。Fadell下面一个工程师抱怨“两年了一直在各种节日加班，还要为了政治上的这些屁事烦心，真是受够了。”&lt;strong&gt;[政治斗争另一个影响是底层工程师无所适从]&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;初代iPhone只能用2G，不能用3G，没有GPS，不可更换电池，不支持扩展存储卡，不支持Flash。而简单的一些如通讯录搜索，剪贴文字，录制视频都不行。主要问题是Apple没时间做。Grignon说，“很遗憾，但我们不得不说，我们要出货了。即使那些都是很蠢的，很容易解决的小问题，（我们也不能保证解决，因为）我们要排优先级，然后解决那些最恶劣的问题。” &lt;strong&gt;[当项目紧张时，是砍content/feature，保住关键的feature。而不是试图什么都做，结果什么都做不好。]&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;

&lt;p&gt;不光Apple内部，看了书后发现Google内部存在同样的问题，负责Android的Andy Rubin和负责iPhone上Google Apps的Vic Gundotra也有类似的竞争关系。（Andy Rubin也是一枚有意思的人物，以后再写。）看了这本书后，也就对现在团队里一些吵吵闹闹的场景有所理解了。每个人看问题的角度不同，想要的结果也不同，因此方式也不尽相同。这多少也算是点读书的收获吧。&lt;/p&gt;

&lt;p&gt;“阳光底下无新事”，硅谷的故事总在不停的重复，Apple和Google的战争，就有如20多年前Apple和Microsoft的战争。甚至连结局都有类似的倾向–Android在市场份额上大幅领先于iPhone。（唯一的疑惑是，为什么相同的策略，iPod在音乐播放器这个领域可以取得绝对优势？）&lt;/p&gt;

&lt;p&gt;自Steve Jobs去世后，Apple就再无让人眼前一亮的全新硬件产品面世。吴军在《浪潮之巅》里说Apple是创新驱动型的硬件公司，靠硬件赚钱，因此一旦硬件创新速度跟不上来，利润会大幅下滑。而Google是他所谓的“印钞机”模式，通过”网络入口–搜索–广告“这种模式，即使创新上偶尔跟不上也不会有大碍。不论这种论述正确与否，倒是点明了两个公司的差别。Google祭出Android也正是忌惮iPhone全面流行，会控制移动互联网的入口。而Apple现在全面倚重于iPhone，作为一个在手机领域成长不到10年，却要一直处于领跑位置，压力可想而知。（如果哪天Apple倒了，真替后面的跟跑者着急–哪里再去找抄袭的点子啊。不过也不必担心，如果Apple倒了，一定是被另一家更创新的公司干掉的，行业永远不缺领跑者和搅局者。）&lt;/p&gt;

&lt;p&gt;过两天，iPhone 6就要上市了，iWatch据说也要发布了。Apple是否能守住阵脚，甚至反守为攻，我们拭目以待！&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Do We Still Need Test Spec</title>
   <link href="https://blog.pzheng.me//2014/08/22/do-we-still-need-spec/"/>
   <updated>2014-08-22T20:30:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/08/22/do-we-still-need-spec</id>
   <content type="html">&lt;p&gt;做weekly retrospective时，赫然发现本周大大小小拢共做了16个test case的review(包括test specification和test report)，且大部分都集中在后半周。直接后果就是，每天的日程表都被会议占得满满的，只有晚上到家才有时间提前看材料和提comments。没办法，每个sprint快结束时，都是各个团队最忙碌的时候–要抓紧时间把backlog上的任务都消灭掉。这么多的specification(abbr. spec)，着实花了不少author和reviewer的时间。不禁想起人们常提的那个问题：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;软件测试还需要测试用例规范吗？&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;p&gt;软件测试流程无外乎以下几点。略微有些出入的，也左不过是某些步骤交叉结合在一起。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;需求分析 requirements analysisl;&lt;/li&gt;
  &lt;li&gt;测试规划 test plan;&lt;/li&gt;
  &lt;li&gt;测试用例编写 test case spec;&lt;/li&gt;
  &lt;li&gt;测试用例执行 test case execution;&lt;/li&gt;
  &lt;li&gt;测试报告提交 test report;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;通常“用例执行”最受重视也耗时最久，因为只有这一步是在真正的被测对象上进行操作，而大部分的软件bug也是在这一步被发现的。“需求分析”和“测试规划”重视程度次之，这可以理解，因为这两步可以说是重要的学习过程，不做好这两步后面的步骤将困难重重。而“用例编写”和“测试报告”，作为常规意义上的“文档类工作”，通常是优先级最低的tasks，预留的时间往往也最短。有的同事说写得那么好干嘛，我们是coder不是writer，我把case测好，能发现问题就够了。更有甚者宣称“test spec完全是可有可无的东西”。&lt;/p&gt;

&lt;p&gt;不知道这些同事是否跟了业界的潮流，受了&lt;a href=&quot;http://en.wikipedia.org/wiki/Test-driven_development&quot;&gt;TDD(Test-Driven Development)&lt;/a&gt;和&lt;a href=&quot;http://agilemodeling.com/essays/executableSpecifications.htm&quot;&gt;executable specification&lt;/a&gt;等蛊惑，觉得文档可有可无，spec也完全可以被脚本script代替。&lt;/p&gt;

&lt;p&gt;至于是否真的可以不写test spec，我的答案很简单：&lt;strong&gt;it depends&lt;/strong&gt;（又一句政治正确的废话）。任何事情，脱离了语境(context)直接下结论，都是耍流氓。就我所在的团队而言，个人觉得现阶段test spec还是不可或缺的。原因如下：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;通过spec消解测试复杂度&lt;/strong&gt;。现阶段我们进行的是软件系统组件测试，需同时兼顾信令面和用户面的需求。对于信令面而言，消息繁多，而每条消息内部又有着成百上千个参数。不同消息之间的耦合，以及消息内或消息间参数的耦合，都导致直接阅读脚本会陷入“只缘身在此山中”的茫然感，而无法提纲挈地理解case用意；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;测试框架和测试工具决定了脚本是否轻易可读&lt;/strong&gt;。我们现在使用的测试工具基于&lt;a href=&quot;https://www.eclipse.org/&quot;&gt;Eclipse&lt;/a&gt;二次开发，GUI界面让手动测试(manual testing)非常容易上手。而带来的问题就是语法臃肿，调用库变得复杂，因此无法醒目地通过阅读“脚本(scripts)”，去了解该case的目的和重点；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;保证信息交流低误码率&lt;/strong&gt;。我们的test case往往不是测完就丢弃的，在手动测试后需要加到Continous Integration上进行自动化测试。而往往一个case在整个生命周期内，会经手好几位同事。因此同事之间就不能只是通过简单的口头交流进行任务交接。一份清晰的文档可以省却许多口舌之争；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;通过spec的撰写更进一步地理解需求&lt;/strong&gt;。对一件事情的看法，人们脑子里想的，嘴上说的，和最后写出来的可能都不一样。而以前也常听人说“某人很厉害，可惜了，肚子里有货倒不出来”，暗示某人不善表达。克服这一点最好的办法，就是写出来：如果自己都无法说服自己，那就说明理解得不够透彻，或者根本就是理解有误。我现在每周固定一篇blog，也是强迫自己在有限的时间和文字内，表述清楚一件事情；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;搭建需求和测试间的桥梁&lt;/strong&gt;。如能在这一步就分析清楚可测性以及合理搭配测试步骤，到“测试执行”时就不会无目的的乱试，大大提高测试效率。这也是大家常说的“磨刀不误砍柴工”；&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;说这么多，那一份好的test spec要具备哪些特征呢。个人觉得：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;简洁&lt;/strong&gt;。该有的都有，不该有的一个字也不要提。尽量减少文档工作的时间，重点放在测试方案的制定上；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;清晰&lt;/strong&gt;。不要出现模棱两可的词句，这样会增加tester的理解成本。更不应出现诸如“该步骤测试结果请参考需求文档”这样的描述。否则大家就可以不用test spec，直接看需求文档好了；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;目的明确&lt;/strong&gt;。spec是测试用例的guideline，要把握好细节和提纲之间的trade off；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;尽量减少错别字和语法错误&lt;/strong&gt;。有些typo可以理解，但如果满篇都是错别字文法混乱的话，那就不可原谅了；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;总的来说，我不赞成在文档上花费太多时间，宁愿花时间在思考测试方式和步骤上，但同时，最后输出的spec一定要有可读性。至于spec的后期更新和管理，也是一个纠结的话题，以后再聊。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Inner Loop Power Control II</title>
   <link href="https://blog.pzheng.me//2014/08/16/inner-loop-power-control-2/"/>
   <updated>2014-08-16T19:25:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/08/16/inner-loop-power-control-2</id>
   <content type="html">&lt;p&gt;Inner Loop Power Control exists on both uplink and downlink. For the uplink, Node B will send TPC(Transmit Power Control) command to UE which would adjust its own transmission power accordingly. Vice versa for the downlink.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h3 id=&quot;tpc-command-for-ul-ilpc&quot;&gt;TPC command for UL ILPC&lt;/h3&gt;

&lt;p&gt;TPC command is carried on downlink DPCCH for R99 users. Figure 2 in 3GPP &lt;a href=&quot;http://www.3gpp.org/DynaReport/25211.htm&quot;&gt;TS25.211&lt;/a&gt; shows the TPC command in DPCCH fields.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140816_dl_dpcch_frame_structure.png&quot; alt=&quot;dl DPCH structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;After HSDPA was announced in 3GPP Release 5, the data and TFCI could be carried on HS-PDSCH and HS-SCCH. If each user is configured with downlink DPCH(including DPDCH/DPCCH), RNC needs to reserve one channelization code for each user. The impact, that the DPCH occupy considerable portion of the downlink channelization codes, may emerge as the user amount increases. Fortunately, F-DPCH was introduced in 3GPP Release 6 to relieve such burden.&lt;/p&gt;

&lt;p&gt;The spreading factor is fixed as 128 which is fairly large. Therefore, it’s not a big problem for RNC to allocate several F-DPCH codes on the downlink code tree with limited channelization code resource. As illustrated in Figure 12B in 3GPP TS25.211, each slot of F-DPCH consists of N&lt;sub&gt;OFF1&lt;/sub&gt; bits, N&lt;sub&gt;TPC&lt;/sub&gt; bits and N&lt;sub&gt;OFF2&lt;/sub&gt; bits.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140816_fdpch_structure.png&quot; alt=&quot;F-DPCH structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The exact bits number of N&lt;sub&gt;OFF1&lt;/sub&gt;, N&lt;sub&gt;TPC&lt;/sub&gt; and N&lt;sub&gt;OFF2&lt;/sub&gt; depends on F-DPCH slot format as Table 16C in 3GPP TS25.211. N&lt;sub&gt;OFF1&lt;/sub&gt; and N&lt;sub&gt;OFF2&lt;/sub&gt; are actually DTX with nothing transmitted.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140816_f-dpch_slot_format.png&quot; alt=&quot;F-DPCH slot format&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Basically users sharing the same F-DPCH code would have different F-DPCH slot formats to distribute TPC commands for all users evenly on F-DPCH channel without overlapping. One F-DPCH code could carry TPC commands for at most &lt;strong&gt;TEN&lt;/strong&gt; users.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140816_f-dpch_ten_users.png&quot; alt=&quot;F-DPCH slot format&quot; /&gt;&lt;/p&gt;

&lt;p&gt;However, the above figure is not accurate enough. Since it doesn’t take the user specific delay(compared to P-CPICH), i.e. chip offset, into account for the timing alignment. If the chip offset of user 1-10 are 0/256/512/…/2304 respectively which happens to be just 1/10 slot in between. It will lead to the overlapping of TPC commands transmission between User 1 and User 6 (as well as User 2 and User 7, etc.) as below figure.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140816_f-dpch_ten_users_chipoffset_overlapping.png&quot; alt=&quot;F-DPCH overlapping&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Then you could just adjust either the chip offset or the F-DPCH slot format for each user. But usually RNC will take care of all the stuff for you. Here is one example as all users share the same F-DPCH code and the same F-DPCH slot format at the same time.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140816_f-dpch_ten_users_chipoffset_non_overlapping.png&quot; alt=&quot;F-DPCH non-overlapping&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You may ask, if there is no downlink DPCH, where are the pilot bits after all data/TFCI/TPC bits could be carried on other channels? I will explain it later.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Inner Loop Power Control I</title>
   <link href="https://blog.pzheng.me//2014/08/08/inner-loop-power-control_1/"/>
   <updated>2014-08-08T22:37:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/08/08/inner-loop-power-control_1</id>
   <content type="html">&lt;p&gt;Power Control(PC) is one of the most important features in UMTS technology. Here I’d like to introduce the Inner Loop Power Control(ILPC).&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;intro-of-power-control&quot;&gt;Intro of power control&lt;/h2&gt;

&lt;p&gt;Power control, just as the name implies, is the mechanism to adjust the transmission power of physical channels for certain purpose. Generally, the purpose is to achieve the specific quality for the signals with the adequate transmission power. No more, no less.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140808_intro_power_control.png&quot; alt=&quot;Power control intro&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Please note, in this context, “power” means the signal strength rather than the battery power or the power consumed by the devices. Though a better power control would eventually make devices consume less battery power.&lt;/p&gt;

&lt;h3 id=&quot;categories&quot;&gt;Categories&lt;/h3&gt;

&lt;p&gt;From “feedback” perspective, there are two kinds of power control:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Open loop power control&lt;/p&gt;

    &lt;p&gt;Open loop power control is operated without any direct adjustment indicator from reciever as in below figure.&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140808_open_loop_power_control.png&quot; alt=&quot;Power control intro&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;Before I was using “feedback” but later I found “direct adjustment indicator” was more accurate. For instance, the power control for PRACH preamble is open loop during random access procedure. If no AICH(acknowledge for PRACH preamble) was received by UE, the preamble power shall increase step by step(power ramp step) till:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;Maximum preamble retransmission number is reached; or&lt;/li&gt;
      &lt;li&gt;Maximum preamble power is reached; or&lt;/li&gt;
      &lt;li&gt;AICH, either ACK or NACK, is finially received by UE;&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;So actually there is feedback, i.e. AICH, from Node B to UE. However there is no way for Node B to directly inform UE to increase or decrease the power of PRACH preamble. In fact, sort of like one way street, UE could only increase the power or even stop but is forbidden to decrease it during random access procedure.&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140808_rach_preamble.png&quot; alt=&quot;Power control intro&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Closed loop power control&lt;/p&gt;

    &lt;p&gt;In contrast to open loop power control, there is straightforward direct indicator from the receiver to inform the transmitter how to adjust the channel power. And then the transmitter would increase/decrease/remain the power level accordingly.&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140808_closed_loop_power_control.png&quot; alt=&quot;Power control intro&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;Both uplink and downlink DPCH power control are closed loop while the indicator is called Transmit Power Control(TPC) command.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Meanwhile, from Node B point of view, there are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Outer loop power control&lt;/p&gt;

    &lt;p&gt;Outer loop power control, a.k.a. OLPC, is mainly proceeded in RNC to derive the SIR target for UL physical channels based on the calculated BLER as well as BLER target. And then RNC will send this SIR target via FP Control Frame to Node B for inner loop power control.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Inner loop power control&lt;/p&gt;

    &lt;p&gt;As mentioned before, both Node B and UE could sent TPC command carried on DPCCH to each other to tell them to calibrate the power of the corresponding physical channels.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I think both OLPC and ILPC are closed loop power control. In my company, we usually use CLPC which actually refers to ILPC in our daily work .&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140808_inner_outer_loop_power_control.png&quot; alt=&quot;Power control intro&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>And Then Steve Said</title>
   <link href="https://blog.pzheng.me//2014/08/04/and_then_steve_said/"/>
   <updated>2014-08-04T12:15:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/08/04/and_then_steve_said</id>
   <content type="html">&lt;p&gt;周末花了点时间把&lt;a href=&quot;http://www.nytimes.com/2013/10/06/magazine/and-then-steve-said-let-there-be-an-iphone.html?_r=1&amp;amp;&amp;amp;pagewanted=all&quot;&gt;这篇文章&lt;/a&gt;翻译出来。以前没有翻译长文的经验，时间也有限，难免有错漏，见谅。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;该文刊载于去年10月的The New York Times上，报道了关于Steve Jobs和第一代iPhone设计及发布时一些事情。个人非常喜欢！我觉得一定程度上，比Walter Isaacson为Jobs写的传记还要精彩。读完回头再看看&lt;a href=&quot;https://www.youtube.com/watch?v=9hUIxyE2Ns8&quot;&gt;2007年首代iPhone发布会Jobs的演讲视频&lt;/a&gt;，完全是另外一种感受。在感受Jobs人格魅力的同时，也意识到，在台上舌灿莲花的genius，背后有着这样一群战战兢兢的工程师们在等待大考。有意思的是，在大考前他们能做的都做完了，帮他们参加大考，决定最终成绩的是台上的Jobs。&lt;/p&gt;

&lt;p&gt;Genius都有自己的个性，最近听说&lt;a href=&quot;http://www.yinwang.org/blog-cn/2014/07/30/help/&quot;&gt;王垠&lt;/a&gt;和&lt;a href=&quot;http://ergoemacs.org/misc/xah_as_good_as_dead.html&quot;&gt;李杀&lt;/a&gt;的事情，也让人颇生感慨。&lt;/p&gt;

&lt;h2 id=&quot;steve说要有iphone&quot;&gt;Steve说，要有iPhone&lt;/h2&gt;

&lt;p&gt;原文标题：&lt;a href=&quot;http://www.nytimes.com/2013/10/06/magazine/and-then-steve-said-let-there-be-an-iphone.html?_r=1&amp;amp;&amp;amp;pagewanted=all&quot;&gt;And Then Steve Said, ‘Let There Be an iPhone’&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;原作者：&lt;em&gt;Fred Vogelstein&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Campbell通往San Francisco的55英里是世上最好的一段通勤路程。大部分时间是在Santa Cruz Mountains（圣克鲁斯山脉）东面那条宏伟空旷的Junipero Serra Freeway（280号州际公路）上驰骋。这里是在硅谷观看初创公司巨头为他的法拉第测速的最佳地点。也是硅谷手机信号最差的地方。因此，对2007年1月8日的Andy Grignon来说，这是他能静下来独自思考一下的绝佳地点。&lt;/p&gt;

&lt;p&gt;这本不是Grignon通常上班的路线。Grignon是位于Cupertino（Campbell西边的一个镇）的Apple公司的高级工程师。通常，他早上会花刚好15分钟时间，开车到七公里外的公司。但今天有所不同，他要去见证他老板Steve Jobs在San Francisco的Macworld大会上创造历史。Apple粉丝已经央求了Jobs好几年，希望他能将手机放到他们的iPod里，这样他们就不用随身携带两台设备。Jobs即将实现这个愿望。Grignon和一些同事将在附近的宾馆住一晚，然后在第二天早上10点左右，和全世界所有人一起，观看Jobs发布第一代iPhone。&lt;/p&gt;

&lt;p&gt;但是，当Grignon往北驶时，他并未感到兴奋，反而只有恐惧。硅谷大部分的台上产品发布通常都是预先录制好的demo&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;。他想着为什么要让糟糕的网络质量或手机信号毁了一个绝好的发布会？但是，Jobs坚持现场展示。这是让发布会如此迷人的原因之一。Jobs传奇里的一部分，是那些引人注目的产品发布会上几乎不会出现任何的小故障。但是，对于如Grignon这样的幕后人员来说，这些部分引起了更大的压力。&lt;/p&gt;

&lt;p&gt;Grignon是负责iPhone所有无线射频部分的高级经理。这是个大任务。今天，手机可以为我们做很多事情，但说到本质，它不过是个花哨的双工射频通信设备而已。Grignon就是负责将iPhone变成一台真正（可通信）的电话。如果设备无法打电话，或者不能连接到蓝牙耳机或Wi-Fi，Grignon需要解决这些问题。作为iPhone最早的一批工程师之一，他为这个项目奉献了两年半时间–经常一周工作七天。&lt;/p&gt;

&lt;p&gt;Grignon之前是Apple的iPhone排练组成员之一，后来来到了位于San Francisco的Moscone Center展示厅。他很少看到Jobs在90分钟的展示中一个小故障也不出。Jobs已经演练了五天。即使是排练的最后一天，iPhone依然会随机的掉话，或无法连接网络，或死机，或直接关机。&lt;/p&gt;

&lt;p&gt;Grignon说：“一开始还觉得能参与排练里挺酷的，有点像信誉勋章的意味。”只选择了很少人参与此次排练。“但很快就变得非常不舒服了。我很少看到他变得如此烦躁。出现问题后，通常他只是看着你，然后非常严厉大声地咆哮‘你XX的毁了我的公司。’或是‘都怪你让我们失败了。’。”他非常紧张。而你永远感觉自己只有一英寸那么点高。和参于彩排的其他人一样，Grignon知道，如果在正式发布会上发生了小故障，Jobs绝对不会为归罪于他自己。“我们像过了100多遍demo，但每次都还有些小问题。”，Grignon说，“那真不好过。”&lt;/p&gt;

&lt;p&gt;这次发布会是顶级机密。从星期四开始，直到接下来的一周结束，Apple都征用了整个Moscone。他们在后台搭建了一个近6平方米的电子实验室，来摆放和测试iPhone。在它旁边还建了一个休息室，里面有张Jobs的沙发。在那些房间和大楼的门口，都部署了10多个每天24小时值班的门卫。如果没有通过电子身份检查，或者和Jobs亲自审核的人员名单比对失败，谁都将无法进入其内。Jobs排练的会场只对少部分高管开放。Jobs执念于保密，以致于他想让Apple雇佣的承包商人员（从驻守展位和布置展台到到负责灯光音响系统的人），在他的发布会演讲之前，晚上全都睡在这栋楼里。他的助手劝阻了他。&lt;/p&gt;

&lt;p&gt;Grignon知道，iPhone的发布不是一次普通的产品发布会。但是没人能预料到，那到底将是一个影响多深远的时刻。在随后的七年时间里，iPhone和它的衍生品iPad一起，跻身硅谷历史上最重要的创新。它们改变了平庸的手机产业。它们为一个全新的且利润丰厚的软件产业–移动应用–提供了一个平台。这个产业从2008年开始已经产生了超过100亿美金的利润。而且，它颠覆了数十亿美元的个人电脑产业。如果台式机和笔记本电脑销量中包含iPad，Apple就是世界上最大的个人电脑制造商。去年Apple总计销售了将近两亿台iPhone和iPad，比全球汽车总销量的两倍还多。&lt;/p&gt;

&lt;p&gt;影响不仅是经济上的，还有文化上的。Apple的创新让人们彻底地重新思考人机互动机制。这不止是用手指取代鼠标操作这么简单。尤其是，智能机已然变成了我们大脑的延伸。它们已经完全颠覆了人们接收和处理信息的方式。想想它们对书籍，报刊，电话，广播，录音机，相机，录像机，指南针，电视，VCR和DVD，个人电脑，手机，电子游戏以及iPod的影响。智能机可以做以上所有事情，而你还能将它放入你的口袋。它的技术改变了我们在校学习的方式，改变了医生治疗病人的方式，也改变了我们旅行和探索的方式。通过智能机，我们用一种全新的方式接触和体验娱乐及媒体。&lt;/p&gt;

&lt;p&gt;然而今天，Apple却身处围攻之中。2007年底，Google发布了Android，那是Google统治全球手机和其他移动设备的计划。从那一刻起，Google就不只是尝试追赶iPhone，事实上，它已经追上并成功打败了iPhone。从2010年开始Android爆炸式普及。Android占据几近80%的全球手机市场份额，而Apple已经下降到少于20%。iPad有类似的趋势：2010年iPad占据了平板市场的90%份额，而现在，60%以上的已售平板上运行的是Android。&lt;/p&gt;

&lt;p&gt;最让Apple粉丝担心的是，不知道公司将驶向何方。2011年Jobs去世后，盛行的问题不是Tim Cook能否成功接任，而是这世上到底有没有人能够接任。Jobs任职时，Apple就像一台创新机器，每三至五年就会推出大量革命性产品。他告诉他的传记作家Walter Isaacson，他的另一个突破即将到来–电视界的革命。但在Cook治下，什么都没实现，而且投资者对其明显缺乏信心。今年九月，Cook发布最新款智能机iPhone 5c和iPhone 5s后，Apple的股价下跌了10%。一年前，Apple每股股价702美金，使Apple成为全球市值最高的公司。而今，它已从最高点下滑了超过25%。&lt;/p&gt;

&lt;p&gt;将任何人和Jobs相比，都是不公平的。在Cook任职Apple CEO的两年时间里，他不厌其烦的指出，Jobs已明确告诉过他，他不希望Cook用他认为Jobs想要的方式去运行公司，而应该用Cook自己认为必要的方式去管理。这是毋庸置疑的。当你回看iPhone是怎么产生的，可以明显发现，它和这个常有”无理需求“，以及具有不同寻常的能量的独特男人息息相关。&lt;/p&gt;

&lt;p&gt;将时钟拨回到2007年一月，当Jobs决定发布iPhone时，很难说那不是一场赌博。不仅仅是因为他介绍了一款Apple之前从未生产过的新式手机，而是因为在他发布时，使用的还是一款几乎无法正常工作的原型机。即使iPhone要到六个月后才正式发售，他仍希望全世界的人们能有立即就要拥有一台的想法。老实说，需要做的事情还有很多。一条生产线都还没搭建好。总共只生产了100来台iPhone，而且手机质量各异。有些机器的屏幕和塑料边框之间有明显的缝隙；还有些在屏幕上有磨损。而且手机上运行的软件满是bug.&lt;/p&gt;

&lt;p&gt;那时的iPhone可以播放一首歌或一个视频的其中一部分，但无法完整播放完一整段，因为软件会崩溃。如果你先发送电子邮件再上网，手机可以正常运行。而如果你先上网再发邮件，手机可能就会罢工。iPhone团队通过不断的试错找到一条工程师所谓的”黄金路径”。通过一个特定的方式和顺序完成一组特定的任务，可以让手机看起来在正常工作。&lt;/p&gt;

&lt;p&gt;但即使Jobs走的是“黄金路径”，仍不停的需要一些最后一分钟的应急方案&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;来让iPhone能正常工作。在发布日那天，运行Grignon负责的无线射频软件仍有问题。管理iPhone内存的软件同样有问题。没人知道Jobs为演示手机而加的那些额外的电子器材，会不会让问题变得更严重。&lt;/p&gt;

&lt;p&gt;Jobs希望他在台上演示的手机屏幕能投射到他背后的大屏幕。大部分的公司在大屏幕上展示产品时，通常是用摄像头指向它然后直接拍摄。但对Jobs来说，这是不可接受的。观众会看到他的手指在iPhone的屏幕上滑动，这将影响他整场发布会的观感。因此他要求Apple工程师，花几周时间在他台上会用到的那台iPhone背面，搭了些额外的电路板和视频线。视频线连接到投影仪，这样当Jobs触摸iPhone上比如日历应用图标时，他的手指就不会显示在大屏幕上，但大屏幕上的图像会根据他手指的命令做出相应的响应。效果非常神奇。观众会感觉就像他们自己手中拿着一台iPhone似的。但让这套系统准确运行起来，又给iPhone带来其他一些重大的问题，在当时看来都一时难以解决。&lt;/p&gt;

&lt;p&gt;iPhone上运行Wi-Fi射频组件的软件非常不稳定，以至于Grignon和他的团队不得不将手机的天线延长，连接到台下的有线上，这样无线信号就不需要传输太远。并且，还需要防止观众使用这段无线频率。“即使是基站的ID被隐藏了”–就是当笔记本扫描Wi-Fi信号时，不会显示这个Wi-Fi的ID–“(但是)观众席有5000个技术呆子（nerd）。” Grigon说，“他们可能会想办法入侵这些信号。”。他说，最后的解决方案是，调整了一下AirPort的软件，让它看起来是工作在日本而不是美国，因为在日本，Wi-Fi使用的一些频率在美国是被禁止使用的。&lt;/p&gt;

&lt;p&gt;在保障Jobs预备在台上能畅通打电话这件事上，他们能做的很少。Grignon和他的团队唯一能做的就是保证无线信号足够好，然后祈祷。他们让AT&amp;amp;T（iPhone的无线运营商）在会场内安装了一个便携式的小区基站发射塔，这样就能确保手机接收的信号足够强。接着，在得到Jobs的同意后，他们修改了程序，不管手机接收的真实信号是多少，都会显示五格信号。在Jobs打电话的那几分钟时间内，无线射频组件不太可能崩溃，但不敢保证在整个90分钟的演讲内都不发生崩溃。“如果像我们预测的那样，无线射频组件可能崩溃然后重启，我们也不想让观众席的人们看到这一点。”Grignon说，”所以我们强制写死软件，将无线信号指示栏固定为五格（表示信号最强）。”&lt;/p&gt;

&lt;p&gt;但这些应急方案都没能解决iPhone最大的问题：如果一段时间处理了过多任务，它就会耗尽内存而不得不重启。Jobs带了很多demo设备上台来解决这个问题。如果一台的内存快耗尽了，他会切换到另外一台，然后让第一台重启。但是得知Jobs准备进行多少个demo展示后，Grigon担心可能存在太多的潜在失败点。如果在前数十个demo都没有发生灾难，那么它一定出现在最后阶段，就是Jobs计划同时在同一台iPhone上展示它所有顶级特性。他将会播放一段音乐，打一个电话，暂停电话，接听另一个电话，查找并通过电子邮件发送一张照片给第二个通话者，在互联网上查找点东西给第一个通话者，然后再回到他的音乐。“我和同事们对这个阶段都非常紧张。”Grignon说，“那些手机都只有128M的内存”就只有20来张大点的数码照片那么大，“因为软件应用还没有正式完成，所以所有那些应用体积都很庞大。”&lt;/p&gt;

&lt;p&gt;Jobs很少像这样把自己逼到墙角。广为人知的是，他是一个任务管理专家，他好像知道如何用力的推动他的员工来完成那些不可能的任务。但他总会有一个备用方案Plan B，这样当时间到了任务还未完成时，他还可以选择备用方案。&lt;/p&gt;

&lt;p&gt;但是iPhone是Apple当时正在进行中的唯一一个称得上酷的新产品。那段时间里，Apple的所有资源都倾斜到iPhone这个项目上，以至于没有其他任何后备方案。“当时只有Apple TV或者iPhone，”Grignon说，“如果当时在Macworld大会上，他只推出Apple TV，”就是一个将iTunes连接到电视上的产品，“全世界的人都会说‘这是啥破X玩意儿？’”&lt;/p&gt;

&lt;p&gt;一想到一生中最重要的时刻可能毁于一旦，Grignon的胃就很疼。直到2007年，他几乎所有的职业生涯都是在Apple或附属公司度过的。1993年当他还在Iowa大学时，他和朋友Jeremy Wyld重新编译了Newton上的 MessagePad应用，使它能以无线的方式连接互联网。Newton作为一款产品，即使最终未能成功，很多人仍认为它是第一款主流的手持电脑。而在当时，他们的这个程序可是很火过一阵。而且帮他俩都在Apple找到了工作。Wyld最后去了Newton部门，Grignon则去了Apple著名的的R&amp;amp;D实验室– Advanced Technology Group（先进技术组） – 专攻视频会议技术。&lt;/p&gt;

&lt;p&gt;2000年，Grignon去了Pixo，一家由前Apple软件工程师创办的公司，这家公司主要为手机和其他小型设备制作操作系统。当Pixo的软件最后在2001年运行在第一款iPod上时，Grignon发现他又回到了Apple了。&lt;/p&gt;

&lt;p&gt;得益于在Pixo的工作经历，当时他不仅是视频会议技术方面的专家，在另两个领域也很杰出：电脑无线传输(Wi-Fi和蓝牙)，和为小型手持设备（如手机）编写软件。Grignon进入另一个世界，这个世界和硅谷传统工程师所处的世界全然不同。那些工程师大多不用考虑，他们的代码是否太占硬盘空间，或者是否超过了芯片的能力。桌面电脑和笔记本电脑的硬件非常强大，可更改而且便宜；内存，硬盘甚至处理器都可较低廉地升级；电脑不是连在外接电源上就是外带巨大的电池。而在Grignon工作的嵌入式软件领域，硬件是固定的。太大的代码将无法运行。同时，也需要调校小小的电池来维持一整天的使用，而那个小电池也许只能给一台笔记本电脑维持数分钟使用时间。当Grignon在2004年底开始为iPhone工作时，他就拥有了一系列完美的技能，也就成为了这个项目早期的工程师之一。&lt;/p&gt;

&lt;p&gt;现在，2007年，他却感觉身心疲惫。他的体重增加了50磅，婚姻关系紧张。iPhone团队很早就发现，做一款手机，根本不像电脑或者iPod那样，简单组装就了事。“非常戏剧性，”Grignon说，“每个人头脑里都被灌输了这种思想，这将是Apple下一个大事件。所以你将这所有超级自大超级聪明的人，放入一个空间紧张的地方，给予一定的压力，然后疯狂的事情就开始了。”&lt;/p&gt;

&lt;p&gt;值得注意的是，Jobs“不得不”让Apple生产手机。自2001年发布iPod起，在他的核心圈子里就不停的讨论着这个话题。理由很明显：如果消费者只用携带一台设备来发电子邮件/打电话或者播放音乐，他们绝不会携带两到三台设备来干这些事。但是每次Jobs和高层们详细研究这个想法时，看起来都这想是个自杀式任务。对希望用手机浏览网页和下载音乐或视频的人来说，手机芯片和带宽速度都太慢了。电子邮件这个功能加到手机上倒是不错，但RIM公司的BlackBerry手机已迅速锁定了这个市场。&lt;/p&gt;

&lt;p&gt;而且，Jobs不想和任何无线运营商合作。当时，运营商都想主导和手机制造商的合作关系，因为他们控制着网络，他们有他们的方式。Jobs，著名的控制狂，不能想象自己受他们摆布。Apple于2003年考虑收购Motorola，但是高官们迅速给出结论，对当时的Apple来说，那还是一次过大的收购行动（两个公司在几年后有过一次不成功的合作）。&lt;/p&gt;

&lt;p&gt;但到2004年秋，和运营商合作开始变得不那么费力了。Sprint开始批发出售它的无线带宽。这意味着，如果Apple从Sprint买下带宽然后重售，Apple就将拥有自己的无线运营商，也就是所谓的“移动虚拟网络运营商”。Apple有能力制造一款手机，但还从未和运营商打过交道。迪斯尼（Jobs是董事局成员之一）已经在和Sprint讨论这样一笔交易，用以提供自己的无线服务。Jobs问了大量的问题，考虑Apple是否也应该购买一个此类业务。2006年，在经过一年多的商讨后最终敲定，Apple和Cingular(后被AT&amp;amp;T收购)签订合作协议。听起来很难，但和Apple制造一款iPhone比起来，还是容易很多。&lt;/p&gt;

&lt;p&gt;很多高管和工程师，因iPod的成功而春风得意，他们都以为手机就是缩小版的Macintosh。但是，Apple在2005年和2006年不是设计了一款，而是三款早期的iPhone版本。曾为该项目工作过的某人认为，当时Apple制造了六台能正常工作的原型机，每一台都有自己的一套硬件，软件和设计。有些团队成员精疲力竭，在第一款iPhone上市后就很快离职了。“它就像首次登月一样”，项目的关键高管Tony Fadell（他于2010年创办了自己的公司Nest）说，“我已经习惯了在一个项目中有一定程度的未知因素，但在这个项目里，由于它还在蹒跚前行，实在是存在太多未知的新事物了。”&lt;/p&gt;

&lt;p&gt;OS X是每台Mac上运行的软件操作系统，Jobs想让iPhone运行OS X的更新版本。但是从未有人将类似OS X那样巨大的程序放在一个手机芯片上运行。软件将只有它正常大小的十分之一。成千上万行代码将被删除或者重写。工程师也只能模拟芯片速度和电池耗电，因为直到2006年才有真正的手机芯片。&lt;/p&gt;

&lt;p&gt;以前主流消费类电子产品上也没有使用过多点触屏。电容触摸技术，就是通过手指或其他导体就可以实现“触摸”的电路，上世纪60年代就出现了。但是电容式多点触屏，就是使用两个或多个手指操作，并能独立识别的技术，就大大增加了复杂度。对这项技术的研究是上世纪80年代中就开始了。众所周知，即便如此艰难，Apple最终还是在iPhone上使用了这种触摸屏，并且量产了。没有多少公司有这个财力和胆量去完成这个挑战。而下一步更为艰难，以至生产一个可用的原型机都将非常昂贵：将这项多点触控技术镶嵌在一块透明的玻璃中，让它足够智能到可显示一个具有自动校正功能的虚拟键盘，并足够成熟到能在这块屏幕上稳定地处理照片及网页。没几条生产线有制造这种多点触屏的经验。消费类电子产品的触摸屏以前通常是压力敏感触控屏，用户需要用手指或者触摸笔去按压它（这项技术在PalmPilot和它的继任者如Palm Treo颇为流行）。即便假定iPhone的多点触屏很容易制造，Apple的高管团队也不能完全确定知道他们开发的这些特性，如屏幕上的键盘，和“双击缩放”，确实是消费者真正需要的那些增强型功能。&lt;/p&gt;

&lt;p&gt;早在2003年，一些Apple工程师就研究出了如何在平板电脑上使用多点触控技术。“问题是，Jobs想要一款可以在上厕所时读邮件的设备–这是产品需求文档的某种延伸，”项目早期工程师Joshua Strickon说，“但是假如你制造的设备，电池不足以足够支撑到能带到室外，芯片也不足以强到支持那些图像处理能力，那也无法使用。我们花了很长时间去研究该如何应对。”Strickon在2003年加入Apple前，曾在M.I.T为他的硕士论文制作了一台多点触控的设备。他说，由于在Apple对处理他和同事开发的这些原型缺乏共识，他认为公司不会将这项技术用于任何产品，他于2004年离开了Apple。&lt;/p&gt;

&lt;p&gt;作为那时Apple的高管，Tim Bucher是公司里多点触控的坚定支持者。他说那些原型机的其中一部分问题在于，他们是基于OS X操作系统搭建的，而OS X当初设计出来就是用于鼠标操作，而不是手指移动操作的。“我们用的是一个10寸或12寸屏幕，运行的系统就像微缩版的MAC…你可以用不同的多点触控和手势动作来启动那些demo。其中一个demo是键盘应用会从底部浮上来–和两年后在iPhone正式版本上搭载的非常相似。但是原型机还不够漂亮。有很多的电线，机器也只是临时组装在一起的而已。”&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;直到Jobs从2005年中开始真正的推动这个想法前，也没多少人真的认为触摸屏可以成为一种新式手机的核心。“他说，‘Tony，过来一下。这儿有些我们正在做的玩意儿。你觉得怎么样？我们可以用这个做一个手机吗？’”Fadell说，这个东西指的是Jobs当时正在玩的demo，“它非常大，几乎占满了房间。天花板上有个投影仪，可以将Mac的屏幕投影到上面，大小差不多一平方米。然后你可以触摸Mac屏幕，将东西移来移去，或是在上面画画。”Fadell知道有这么个触摸屏的原型，但不知道太多细节，因为那属于Mac产品部门，而他负责的是iPod部门。“最后我们都坐下来，严肃地讨论了我们能做些什么。”&lt;/p&gt;

&lt;p&gt;Fadell非常怀疑是否能将如此巨大的原型缩小到能生产制造的范围。但他知道最好不要对Jobs说不。Fadell是Apple的超级明星之一。他于2001年以咨询师的身份加入Apple，协助打造第一款iPod。如果只是因为一些棘手的技术问题而畏首畏尾，他绝不可能走到今天的地位。2005年，iPod销量暴涨。那一年他只有36岁，争议性地成为公司最重要的那条产线的高管。&lt;/p&gt;

&lt;p&gt;“我知道我们可以做到”，Fadell说，“但知道是一回事，将满屋子的特殊材料和器件，用成本可控且可靠的方式，生产成亿万个手机大小的版本又是另一回事。”光是想想还有多少事情要做就让人感到绝望。“你得去找知道怎么将这些技术放到玻璃里去的LCD制造商；你还得去找他们生产线的空余时间；为了不让触摸屏的像素电子元件产生各种噪声，你还得实现各种补偿和校准算法。”–这只是LCD上的事情。”光是制造触摸屏设备就是个大项目。我们尝试了两到三种方式去制造触摸屏，直到我们发现其中一种足以量产。”&lt;/p&gt;

&lt;p&gt;缩小OS X和设计多点触屏这些任务，需要很多创意，做起来也非常困难。但至少还在Apple公司已掌握的技术范畴内。没人比他们更适合去重新思考OS X的设计。Apple和LCD制造商也很熟悉，因为每台笔记本电脑和iPod上都需要安装一个LCD屏。但手机完全是个全新的领域。当他们在2006年投入iPhone的设计时，才意识到他们对手机的了解真的很少。Apple建造了测试实验室和测试仪器来测试iPhone的天线。还制作了一些人类头颅模型，模型里填充了一些粘性物质来模拟人脑密度，用以测量用户在使用手机时可能接触到的辐射量。一位高管称，打造第一款iPhone至少花费了1.5亿美金。&lt;/p&gt;

&lt;p&gt;从项目一开始，Jobs就希望他可以生产一种运行着OS X带触屏的iPhone，和他最后发布时的那款类似。但在2005年时，他还不知道研发会花费多长时间。所以Apple的第一台iPhone，看起来就像Jobs在发布会上介绍真正iPhone时展示的那张笑话胶片，一台中间有着老式拨盘的iPod。而原型机最初确实是一台具有手机射频模块的iPod，中间有个类似iPod操作转盘的拨号器。Grignon说，“向市场推出将那样的产品，设计制造起来很简单。但是，比起今天我们做的这些设备，就显得一点都不酷了。”&lt;/p&gt;

&lt;p&gt;2006年初设计的第二款iPhone原型机，就非常接近Jobs最后发布的那一款了。它有一块触屏，运行着OS X，但手机全部由拉丝铝制造而成。Jobs和Apple的首席设计师Jonathan Ive为这个设计感到非常骄傲。但是由于他俩都不是无线微波技术的专家，他们未能意识到制作出来的东西只是一块漂亮的板砖。因为无线电波无法穿透金属。“我和Rubén Caballero（Apple的天线专家），不得不到会议室去给Steve和Ive解释，为什么不能无线电波不能穿透金属。”2008年离职的前Apple工程师Phil Kearney说，“这可没那么容易解释。大多数设计师都是艺术家。他们上的最后一节科学课还是八年级的时候。但他们在Apple又有很大的权利。所以他们问，‘为什么我们不能弄一些小缝隙让无线电波传出来呢？’你还得给他们解释为什么不行。”&lt;/p&gt;

&lt;p&gt;前Apple的高级硬件执行官Jon Rubinstein称，关于手机尺寸大小，有过很一段长时间的讨论。“实际上，我主张有两种大小，一种是普通的iPhone那么大，另一种是像iPod那么大的iPhone mini。我认为前一种可以是智能机，而后一种可以是傻瓜机。但我们压根从没有去做小的那种。要完成这么多大项目中的一个，你真的需要全力以赴往一个方向使劲儿。”&lt;/p&gt;

&lt;p&gt;iPhone项目如此复杂，以至它偶尔会威胁到整个公司，可能使其整个出轨。很多顶尖的工程师都被吸收进这个项目，导致其他项目进展缓慢。要是iPhone最后没成功&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;，那么Apple将在很长一段时间内都没有其他大的产品可以发布。据项目高管称，更为糟糕的是，顶级工程师会对失败很灰心，很可能将就此离开Apple。&lt;/p&gt;

&lt;p&gt;不仅仅是这些技术上的挑战，Jobs对保密也极为偏执。百来号为iPhone工作的工程师和设计师，即使他们已经被每周80小时的工作弄得精疲力竭，也不能和其他任何人谈论此事。如果Apple发现你在酒吧将这个项目告诉了一个朋友，或者甚至是你的配偶，你都会被炒鱿鱼。最开始，经理会询问你是否愿意加入一个项目，你必须在他的办公室签署一份保密协议后，他才会告诉你这个项目是什么，你得再签一份文件确保你签署了保密协议（NDA），而且你不会向其他任何人透露此事。“我们在iPhone楼（purple dorm）的前门贴了一个写着’搏击俱乐部（fight club）’标记，因为搏击俱乐部里第一条规则就是你可以和其他人谈论搏击俱乐部”，负责iOS软件的前Apple高级副总裁（去年10月离职）Scott Forstall，在2012年Apple和三星的官司庭审中作证，“Steve绝不会从Apple以外的公司雇人来制作用户界面，不过他告诉我可以调公司里的任何人来做这件事。”Forstall说，“因此我将想要的工程师们带到我的办公室，和他们坐下来，然后告诉他们’你们在现在的工作角色里都是超级明星。我这儿有一个项目，值得你考虑一下。我不能告诉你这是什么项目。我只能说，如果加入这个项目，你将不得不放弃所有晚上和周末时间，这将是你一生工作中最努力的工作的一段时间。’”&lt;/p&gt;

&lt;p&gt;一个iPhone早期的工程师称，“我最中意那些供应商在发布后一天说的话”，有些大公司，像生产Wi-Fi射频芯片的Marvell公司，还有提供蓝牙射频芯片的CSR公司，根本不知道他们的芯片将用于一款新手机上。他们原以为会是一款新的iPod。这位工程师称，“实际上我们做了些假的电路图和工业设计”。Grignon说，甚至在出差时，尤其是去Cingular出差，Apple会假扮其他公司的员工，“总之，你不想让接待员或者其他人碰巧发现你的工牌（上面有Apple的名字）”。&lt;/p&gt;

&lt;p&gt;Jobs对于保密的偏执，最显著的证明就是，封锁了公司的iPhone工作区域，不为iPhone工作的人禁止进入。“Steve就爱这种事，”Grignon说，“他喜欢划分工作区域。但是，对于那些没有权限进入那些地方的人来说，就柑橘自己个‘大傻X’。每个人都知道公司的明星们是哪些人，当你开始看到他们都慢慢的从你的身边溜走，然后进入那些你没有权限进去的玻璃门后，那感觉真的很不好。”&lt;/p&gt;

&lt;p&gt;即使是项目组内的人也禁止相互交流。设计电路的工程师不允许看软件。当他们需要测试硬件上的软件，他们拿到手的将是伪代码，而不是真实的代码。如果你软件工程师，你也只能是用模拟器来测试硬件性能。&lt;/p&gt;

&lt;p&gt;除了Jobs核心圈子里的人，其他人都不允许进入Jonathan Ive位于二幢一楼的办公室。Ive的原型机保密非常严格。有的员工称，如果你没有权限就试图强行进入Ive的房间的话，刷卡器会报警。“那感觉非常奇怪，因为不是你故意绕开它就可以避开。它就在前台旁边的一个大铁门后面。时不时看到门被打开，就会想朝里瞄一瞄，但你永远不会那样做。”一位出了校门第一份工作就是为iPhone工作的工程师说。Forstall在他的证词里称，进入某些实验室，可能需要你进行多达四次身份验证。&lt;/p&gt;

&lt;p&gt;在Jobs定的最后期限前完成任务的压力非常大，以至于普通的讨论都会迅速升级为大吵大叫。工程师如果感到精疲力竭，会退出工作一小会。当他们补充一段时间睡眠后，过几天再回来继续工作。Forstall的首席经理，Kim Vorrath，曾经重重地摔她的办公室门，导致门卡住了，然后把她自己给锁在里面了。同事们花了一个多小时才把她给弄出来。“我们都站那儿看着，”Grignon说，“部分原因是很好笑。但也让你跳脱出来意识到这有多么XX。”&lt;/p&gt;

&lt;p&gt;2007年1月9日，当Jobs开始谈论iPhone时，他说，“我期盼这一天已经期盼2年半了”。接着他对观众讲了很多消费者痛恨他们手机的故事。然后，毫无疑问地，他一一解决了他们所有的问题。&lt;/p&gt;

&lt;p&gt;当时，Grigon和其他同事紧张地坐在观众席里。Jobs在台上用iPhone播放了一些音乐，还有一小段电影来展示手机漂亮的屏幕。他打了个电话来展示重新设计过的地址薄和语音留言。接着发了一条短信和一封电子邮件，展示在iPhone的触屏键盘上打字是多么的轻松的一件事。他再翻了翻照片，展示如何通过两只手指简单地按压和缩放，就可以让图片缩小或放大。他又用手机登陆到纽约时报和亚马逊网站，展示了一下在iPhone上浏览网页和电脑上效果一样好。最后他在Google Maps上找到一家Starbucks——还在台上打了这家店的电话——表示有一台iPhone在手，就永远不可能走失。&lt;/p&gt;

&lt;p&gt;最后发布会结束，Grignon不仅仅只是放松了，他还喝醉了。事先他买了一瓶苏格兰威士忌来镇定情绪。“我们当时在观众席第五排左右，工程师、经理、我们所有人，在每一段demo后都喝一小杯威士忌。差不多有5、6个人，每段demo结束后，负责那段demo的同事就猛干一杯。最终结束时，所有功能都（奇迹般地）正常工作了，我们也刚好把那瓶酒喝干了。那是我们看过最好的一次发布会。那天剩下的时间，整个iPhone团队都XX的爽翻了。我们整日都在市区花天酒地。挺乱的，但真的很爽。”&lt;/p&gt;

&lt;hr /&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Canned demonstration&lt;/code&gt; 罐头演示，表示事先准备好的胶片或视频，不是真正的现场演示； &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Last-minute workarounds&lt;/code&gt; 最后一分钟的应急方案，表示到最后还仍然有问题，需要一些应急方案解决； &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chewing gum and baling wire&lt;/code&gt; 口香糖和捆扎线，表示临时解决方案，并不是最终产品； &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a dud or not gotten off the ground at all&lt;/code&gt; 哑弹或根本没升空，表示产品没有成功； &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Scheduling Information Reporting</title>
   <link href="https://blog.pzheng.me//2014/07/27/scheduling-infomation-report/"/>
   <updated>2014-07-27T21:31:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/07/27/scheduling-infomation-report</id>
   <content type="html">&lt;p&gt;About half an year ago, we met a problem which resulted in data rate with dramastically ups and downs during load testing. Finally we found it was caused by Scheduling Information(SI) reporting. Here are some learning notes about SI.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;prerequisite&quot;&gt;Prerequisite&lt;/h2&gt;

&lt;p&gt;Some definitions you’d better to be familiar with in advance:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;SG = “Zero_Grant”: it means AG = 1.&lt;/li&gt;
  &lt;li&gt;SG &amp;lt;&amp;gt; “Zero_Grant”: it means AG is any value between [0, 31] other than 1.&lt;/li&gt;
  &lt;li&gt;All processes are deactivated: it means AG = 0 while AG scope = 0 (which means all HARQs).&lt;/li&gt;
  &lt;li&gt;At least one process is activated: it means AG &amp;gt; 2 while AG scope = either 1 (single HARQ) or 0.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;what-is-si&quot;&gt;What is SI&lt;/h2&gt;

&lt;p&gt;Scheduling Information(SI) is carried on E-DPDCH along with data. Well, it could be sent as stand-alone SI(18 bits) without any data.&lt;/p&gt;

&lt;p&gt;In 3GPP &lt;a href=&quot;http://www.3gpp.org/DynaReport/25321.htm&quot;&gt;TS25.321&lt;/a&gt; sub-clause 9.2.5.3.2, SI consists of below elements:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Highest priority Logical channel ID (HLID) (4 bits);&lt;/li&gt;
  &lt;li&gt;Total E-DCH Buffer Status (TEBS) (5 bits);&lt;/li&gt;
  &lt;li&gt;Highest priority Logical channel Buffer Status (HLBS) (4 bits);&lt;/li&gt;
  &lt;li&gt;UE Power Headroom (UPH) (5 bits);&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;E-DCH scheduler in Node B will use SI as one of the inputs for scheduling algorithm.&lt;/p&gt;

&lt;h2 id=&quot;trigger-conditions&quot;&gt;Trigger conditions&lt;/h2&gt;

&lt;p&gt;There are several trigger conditions to send SI in 3GPP TS25.321.&lt;/p&gt;

&lt;h3 id=&quot;si-reporting-triggered-by-sg&quot;&gt;SI reporting triggered by SG&lt;/h3&gt;

&lt;p&gt;According to 3GPP TS25.321 sub-clause 11.8.1.6, there are two major conditions to report SI which depends on SG value.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;SG = “Zero_Grant” or all processes are deactivated&lt;/li&gt;
  &lt;li&gt;SG &amp;lt;&amp;gt; “Zero_Grant” and at least one process is activated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the precondition is “TEBS &amp;gt; 0” because it mentions:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In CELL_DCH state, when MAC-e or MAC-i is configured, the Scheduling Information shall not be transmitted if the TEBS is zero, even if it was triggered by one of the configured triggering mechanisms.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The brief mechanism is showed in below figure:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140727_SI_reporting.jpg&quot; alt=&quot;SI reporting&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;si-reporting-along-with-scheduled-data&quot;&gt;SI reporting along with scheduled data&lt;/h3&gt;

&lt;p&gt;Besides above trigger condition, there is another scenario which could trigger SI reporting in 3GPP TS25.321 sub-clause 9.2.4.2.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;When, due to the quantization in the transport block sizes that can be supported or triggering of the Scheduling Information, the size of the data plus header is less than or equal to the TB size of the E-TFC selected by the UE minus 24 bits, the DDI value [111111] shall be appended at the end of the MAC-e header and a Scheduling Information shall be concatenated into this MAC-e PDU, where DDI value [111111] indicates that there is a Scheduling Information concatenated in this MAC-e PDU. Otherwise, if the size of the data plus header is less than or equal to the TB size of the E-TFC selected by the UE minus 18 bits, a Scheduling Information shall be concatenated into this MAC-e PDU. In any other case it is understood that another MAC-es PDU or Scheduling Information does not fit and it is therefore not necessary to reserve room in the transport block for an additional DDI field.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The basic principle is, whenever there is enough space for SI in that transport block excluding (data + header), SI will be added along with data in that TTI.&lt;/p&gt;

&lt;h2 id=&quot;misunderstanding&quot;&gt;Misunderstanding&lt;/h2&gt;

&lt;p&gt;Regarding “SI reporting triggered by SG”, at first we were not clear about 3GPP statement, especially about the meaning of “becomes”:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;If SG &lt;strong&gt;becomes&lt;/strong&gt; too small to allow transmission of a single PDU from any scheduled MAC-d flow or if the SG is too small to allow transmission of a single PDU from any scheduled MAC-d flow on that frequency and TEBS &lt;strong&gt;becomes&lt;/strong&gt; larger than zero, the transmission of Scheduling Information should be triggered on that frequency.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Later I found this change request was raised by Qualcomm as &lt;a href=&quot;http://www.3gpp.org/ftp/tsg_ran/tsg_ran/TSGR_37/Docs/RP-070636.zip&quot;&gt;RP-070636 CR0362 (Rel-7) R2-073822&lt;/a&gt;. So I turned to Qualcomm enginneers and fortunately they kindly replied soon. They confirmed with below interpretation:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The UE sends SI when SG becomes too small and TEBS &amp;gt; 0; or&lt;/li&gt;
  &lt;li&gt;The UE sends SI when TEBS becomes &amp;gt; 0 and SG is too small.&lt;/li&gt;
  &lt;li&gt;The UE only sends once when the above condition is met.&lt;/li&gt;
  &lt;li&gt;For the restricted HARQ, our UE follow the spec. accurately such that SI can be on any HARQ.&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Model-Based Testing</title>
   <link href="https://blog.pzheng.me//2014/07/20/model-based-testing/"/>
   <updated>2014-07-20T09:58:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/07/20/model-based-testing</id>
   <content type="html">&lt;p&gt;前段时间听同事提到”Model-based Testing”（基于模型的测试），挺有趣的，就找来相关资料研究了一下。下面是一些学习心得。&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;table-of-contents&quot;&gt;Table Of Contents&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;#reference&quot;&gt;Reference&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#process&quot;&gt;Process&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#create-state-model&quot;&gt;Create State Model&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#generate-sequence-of-actions&quot;&gt;Generate Sequence of Actions&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#practice&quot;&gt;Practice&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#advantages&quot;&gt;Advantages&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#disadvantages&quot;&gt;Disadvantages&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#summary&quot;&gt;Summary&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;reference&quot;&gt;Reference&lt;/h2&gt;

&lt;p&gt;参考资料主要是Microsoft的Principal SDET &lt;em&gt;Harry Robinson&lt;/em&gt;的&lt;a href=&quot;http://www.harryrobinson.net/&quot;&gt;个人网站&lt;/a&gt;和&lt;a href=&quot;http://model-based-testing.info/&quot;&gt;Model-based Testing community&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;process&quot;&gt;Process&lt;/h2&gt;

&lt;p&gt;简短来讲，MBT是一种黑盒(Black Box)测试方法，将软件的行为抽象为模型，然后基于模型，选择合适的方式/算法，设计测试用例覆盖相应的模型，以测试各种模型代表的软件行为。&lt;/p&gt;

&lt;h3 id=&quot;create-state-model&quot;&gt;Create State Model&lt;/h3&gt;

&lt;p&gt;首先需要对软件行为进行抽象，转化为模型。抽象模型需基于测试scope，选择合适的抽象粒度，否则可能抽象出无数种大小不一层次各异的模型。&lt;/p&gt;

&lt;p&gt;在&lt;em&gt;Harry Robinson&lt;/em&gt;的文章中，他是用以下三个属性来定义State Model的：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Starting State&lt;/li&gt;
  &lt;li&gt;Action&lt;/li&gt;
  &lt;li&gt;Ending State&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;软件在运行过程中，可能会经过多种不同的状态State，触发切换状态的是不同的动作Action。某种状态，可能其中一个Model中的Ending State，又是另一个Model的Startging State。甚至可能通过相同或不同的Actions触发，在两个State之间相互切换，这也是2种不同的Models。&lt;/p&gt;

&lt;h3 id=&quot;generate-sequence-of-actions&quot;&gt;Generate Sequence of Actions&lt;/h3&gt;

&lt;p&gt;在上步中得到一系列models后，首先将所有状态states画成不同的节点nodes，接着用表征方向的箭头线，连接不同model下的Starting State和Ending States，不同的线即表示不同的动作Actions。这样就可以得到一张有数个节点，其间有不同连线连接各个节点的拓扑图（也就是一张软件测试人眼中的状态机State Machine）。&lt;/p&gt;

&lt;p&gt;接下来就要考虑如何设计测试场景，能完全覆盖所有models。其实就涉及到寻找一条尽可能短的路径，经过各个节点和连线，同时尽量不重复走过的路径。&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Harry Robinson&lt;/em&gt;选择使用著名的图论Graph Theory中“中国邮递员问题”(&lt;a href=&quot;http://en.wikipedia.org/wiki/Chinese_postman_problem&quot;&gt;Chinese postman problem&lt;/a&gt;)的算法来解决。“中国邮递员问题”由中国数学家&lt;a href=&quot;http://baike.baidu.com/view/318032.htm&quot;&gt;管梅谷&lt;/a&gt;Kwan Mei-Ko于1962年研究并给出算法的。使用该算法，可以从上文提到的状态机快速地寻找出，能覆盖所有models的最短路径。&lt;/p&gt;

&lt;p&gt;如果某些model更为关键，也可以加上一定的权重weight，通过算法中可实现多次穿越权重更高的节点和路径。&lt;/p&gt;

&lt;p&gt;基于最短路径，即可设计出相应的测试用例并进行测试。&lt;/p&gt;

&lt;h2 id=&quot;practice&quot;&gt;Practice&lt;/h2&gt;

&lt;p&gt;在前不久的一次&lt;a href=&quot;http://blog.pzheng.me/2014/07/04/a-practice-for-new-feature-grooming/&quot;&gt;new feature测试规划&lt;/a&gt;中，我们使用了该方法设计了其中部分测试用例。&lt;/p&gt;

&lt;p&gt;在该新特性中，我们的产品需支持setup/addition/reconfiguration/deletion这四种Actions，状态是在最多4条links之间相互切换。下图即为整个状态图，不需要在该feature中测试的部分，在图中未予显示。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140720_MBT_practice.png&quot; alt=&quot;MBT practice&quot; /&gt;&lt;/p&gt;

&lt;p&gt;最终我们从这么多条路径中，选择了一些我们认为更重要的路径，组成了一系列的test cases。基于上图，我们对路径的覆盖率，也有了相对清晰的把握。&lt;/p&gt;

&lt;h2 id=&quot;advantages&quot;&gt;Advantages&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;快速方便的找出整体待测点；&lt;/li&gt;
  &lt;li&gt;用尽可能少的步骤覆盖尽可能多的路径；&lt;/li&gt;
  &lt;li&gt;清晰的把握整体覆盖率；&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;disadvantages&quot;&gt;Disadvantages&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;一旦需求更新，有新的节点加入，整体测试plan都要重新全盘更新；&lt;/li&gt;
  &lt;li&gt;复杂的通信设备上，各种feature之间的interworking也非常多，因此要精确的定义出各种可能的states，可能用时较长，并且数量庞大。有时甚至连状态都很难清晰界定。可能做出来也不具备可测性；&lt;/li&gt;
  &lt;li&gt;在MBT中假定的是每个state保持一定的独立性，所以测试中可能经过1次也就可以达到测试目的。但实际产品中，状态之间的影响是隐性的，因此有些问题是需要经过多次操作积累到一定量后才会暴露。对这种问题，MBT貌似还没有很好的办法解决；&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Model-based Testing非常有创意的将图论的算法，融合进测试当中，使测试人员可以快速又方便地制定测试计划，并对整体的路径覆盖率有一定的把控。因此，在测试一些有明确的动作以及状态界定的feature时，能很好的指导测试规划。但一旦系统庞大复杂起来，这种方法的可行性会大大降低。而对于一些需要随机测试，或者stability验证的场景，MBT能做也相对有限。&lt;/p&gt;

&lt;p&gt;There is no silver bullet for testing. 一种测试方法不可能打遍天下。不过我们可以在了解学习之后，归入武器库。一旦有适用的场景，就可以立马派上用场。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Clean Desktop</title>
   <link href="https://blog.pzheng.me//2014/07/13/clean-desktop/"/>
   <updated>2014-07-13T21:49:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/07/13/clean-desktop</id>
   <content type="html">&lt;p&gt;今天来谈谈桌面。关于桌面，爱因斯坦有名言：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;If a cluttered desk is a sign of a cluttered mind, of what, then, is an empty desk a sign?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;p&gt;大师言出必行，让我们看看他老人家的办公室及桌面。下面&lt;a href=&quot;http://life.time.com/?attachment_id=13800&quot;&gt;这张照片&lt;/a&gt;是Princeton他的办公室，摄于1955年4月爱因斯坦去世几小时后。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140713_albert_einstein_desk.png&quot; alt=&quot;Albert Einstein’s office&quot; /&gt;&lt;/p&gt;

&lt;p&gt;OK. 再来看另一位大师Mark Twain的桌面。瞧，是否和他的文章一样，充满了喜感？&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140713_mark_twain_desk.png&quot; alt=&quot;Mark Twain desk&quot; /&gt;&lt;/p&gt;

&lt;p&gt;对了，当然不会漏了我们敬爱的乔帮主的办公室和桌面&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;。天啦，这还是&lt;a href=&quot;http://www.amazon.com/Steve-Jobs-Walter-Isaacson-ebook/dp/B004W2UBYW&quot;&gt;传记&lt;/a&gt;里提到的，那个找不到合适的家具宁愿一连几年坐在没家具光地板上的minimalist么？&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140713_steve_jobs_desk.png&quot; alt=&quot;Steve Jobs desk&quot; /&gt;&lt;/p&gt;

&lt;p&gt;关于“桌面是否应该整洁”的讨论，最终会变成“一屋不扫何以扫天下”这类中学议论文。那就直接上我的观点好了：&lt;strong&gt;我支持应时刻保持办公桌面的整洁&lt;/strong&gt;。除非你能达到上文提到那几位大牛的水平，到那个level，做什么都是合理的了。&lt;/p&gt;

&lt;p&gt;意识到桌面对productivity的影响，是我从接触GTD开始慢慢有感悟的。在GTD中，有个重要的的理念是&lt;strong&gt;Zero Inbox&lt;/strong&gt;。Inbox是所有idea，task等可能存储的地方，可以是实体，比如办工桌面，某个记录to do list的notebook等；也可以是虚拟的，比如电脑桌面，邮件收件箱，还有大脑等（今天主要关注办公桌面，其他可能会另开新帖详述）。GTD希望能尽量将inbox统一，并且inbox里的items都顺利安排进task list，从而保持inbox时刻为空。&lt;/p&gt;

&lt;p&gt;生活中，我们时常有这种经验，一份复印资料，一张快递回执，一张待报销的发票等，貌似有用而又杂碎零散的小东西，专门放在某处显得太郑重其事。于是&lt;strong&gt;为了方便&lt;/strong&gt;，随手扔在桌上。经过一段时间，这种东西越积越多，桌面就会变得凌乱不堪。真正需要用的东西，淹没在一大堆冗余的物件中，一时找起来也颇费功夫，实际变得&lt;strong&gt;非常不方便&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;保持桌面整洁最重要的一点，就是&lt;strong&gt;减少distraction&lt;/strong&gt;。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;不需要的东西，绝不要放在桌上，应统统归类放进抽屉或箱子里。&lt;strong&gt;任何出现在桌面的多余物件，都可能分散工作时的注意力&lt;/strong&gt;；&lt;/li&gt;
  &lt;li&gt;需要的东西都在触手可及的范围内，并根据自己的情况分别放在不同的方位。具体到我个人：
    &lt;ul&gt;
      &lt;li&gt;中间身体正对方位主要放置生产工具，如笔记本，分屏显示器，外接键盘鼠标；&lt;/li&gt;
      &lt;li&gt;本人右撇子，右手是主要用手，因此生活用品大多放在身体右侧，如水杯，便签本，少量文具，绿色植物等；&lt;/li&gt;
      &lt;li&gt;身体左侧放置少量经常查阅的书和资料；&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;电源线，网线，外设接口线等，能通过一定的方式隐藏起来的就藏起来，不要裸露在外面。可适当使用扎线带和USB hub；&lt;/li&gt;
  &lt;li&gt;遵循GTD原则，凡是&lt;strong&gt;可于三分钟内处理掉的资料，不论重要紧急与否，当即处理&lt;/strong&gt;。一时无法处理的，收入抽屉，将该项事务计入task list，延后处理；&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;并且，整洁的桌面让人找起东西来也异常方便，当同事或老板站在旁边问你要一份资料，而你急得满头大汗也找不到的那种尴尬，我想大家都不想遇到。因此，&lt;strong&gt;整洁的办公桌面，可让人工作起来显得更加professional&lt;/strong&gt;。尤其对程序员来说，如果都无法保证自己个人生活的clean，实在无法让人相信他写出来的会是clean code（有些武断，事实上我注意到，大部分优秀的程序员都不怎么关注个人生活:scream:）。&lt;/p&gt;

&lt;p&gt;于我个人，还有一个重要的原因，就是&lt;strong&gt;每个早上来到办公室，看到整洁的办公桌，一天的心情也会很好&lt;/strong&gt;。简单清理一下，便可以很快进入工作状态。&lt;/p&gt;

&lt;p&gt;由于公司规定，我的workspace无法分享给大家。奉上GTD创始人David Allen的办公环境，给大家感受下:+1:。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140713_david_allen_desk.png&quot; alt=&quot;David Allen desk&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://lifehacker.com/5367129/nine-workspaces-where-famous-folks-get-stuff-done&quot;&gt;LifeHacker&lt;/a&gt;上关于名人workspace的文章； &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>一次新特性测试规划的实践</title>
   <link href="https://blog.pzheng.me//2014/07/04/a-practice-for-new-feature-grooming/"/>
   <updated>2014-07-04T21:45:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/07/04/a-practice-for-new-feature-grooming</id>
   <content type="html">&lt;p&gt;三年前一次面试过程中，对方面试官问的一系列问题，至今难忘。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;“如何保证测试覆盖率？”&lt;/p&gt;

&lt;p&gt;“对requirements的覆盖率尽量达到100%。”&lt;/p&gt;

&lt;p&gt;“如何保证requirements的覆盖率到100%？”&lt;/p&gt;

&lt;p&gt;“保证每条requirement都有对应的test case。”&lt;/p&gt;

&lt;p&gt;“如何保证单条requirement是被全覆盖的？”&lt;/p&gt;

&lt;p&gt;“…”&lt;/p&gt;

&lt;h2 id=&quot;table-of-contents&quot;&gt;Table Of Contents&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;#origin&quot;&gt;Origin&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ideas&quot;&gt;Ideas&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#implementation&quot;&gt;Implementation&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#background&quot;&gt;Background&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#split-requirements&quot;&gt;Split requirements&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#add-more-check-points&quot;&gt;Add more check points&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#prioritize&quot;&gt;Prioritize&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#design-test-cases&quot;&gt;Design test cases&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#analyze-uncovered-points&quot;&gt;Analyze uncovered points&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#known-issues&quot;&gt;Known issues&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#summary&quot;&gt;Summary&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;origin&quot;&gt;Origin&lt;/h2&gt;

&lt;p&gt;特性需求的覆盖率，算是测试界经久不衰的话题。不同产品不同层级的测试，对需求的覆盖要求和测试粒度都不尽相同。但无论如何，即使测试资源充足，100%需求覆盖率也是不可能的。更何况现实中，测试资源和交付日期永远是紧张的。盲目追求所谓100%覆盖率，只会使边际效应愈发明显，性价比颇低。&lt;/p&gt;

&lt;p&gt;那么，需求覆盖率多少才算达标呢？&lt;/p&gt;

&lt;p&gt;其实，覆盖率本身就是一个伪命题。若软件质量没有保证，覆盖率就无从谈起。但质量如此虚无缥缈难以量化，导致现实中，往往只能将覆盖率设定为质量的一项重要指标，甚至等同于质量本身。有经验的测试工程师，也很难避免在平时工作中，掉入这种本末倒置的陷阱。&lt;/p&gt;

&lt;p&gt;因此，问题应是，如何规划测试来保证软件质量？&lt;/p&gt;

&lt;h2 id=&quot;ideas&quot;&gt;Ideas&lt;/h2&gt;

&lt;p&gt;一切还是得从客户需求谈起。&lt;/p&gt;

&lt;p&gt;通常客户需求相对简略，我厂系统架构师会分析客户需求，丰满为特性需求文档Feature Requirements和用户故事User Stories。有时一条requirement中可能存在多条分支，并包含大量异常处场景。&lt;/p&gt;

&lt;p&gt;这样的需求，对开发和测试人员来说，还是太粗放。我们需要更进一步的需求分析。以往，在需求分析的同时，我们会基于预设场景将需求映射到测试用例中，这样的问题是对需求覆盖率（看，还是覆盖率）无法整体把握。&lt;/p&gt;

&lt;p&gt;参加和组织过数次新特性测试规划，对规划过程有些新的想法，大致如下。总想着总结为一套可复用的流程。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;先拆分需求为粒度可接受的，包括场景和check points；&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;h2 id=&quot;implementation&quot;&gt;Implementation&lt;/h2&gt;

&lt;p&gt;最近我厂基于全新硬件平台，在为某国顶尖运营商定制一款WCDMA/LTE基站。我负责其中几个新特性的测试规划和技术支持，正好可以实践一把。&lt;/p&gt;

&lt;h3 id=&quot;background&quot;&gt;Background&lt;/h3&gt;

&lt;p&gt;本次规划的测试层级是系统组建测试，高于UT/MT。产品规模较大，涉及的大软件模块主要有4个。为了保证开会讨论的效率，每个模块组我只邀请了一人参与讨论。四人中有测试背景也有开发背景的，因此某些技术问题的深入讨论，可邀请一到两名直接相关工程师参与当期会议。&lt;/p&gt;

&lt;h3 id=&quot;split-requirements&quot;&gt;Split requirements&lt;/h3&gt;

&lt;p&gt;首先我们对需求进行了深入的拆解，将每条requirement里提及的正常以及异常分支，都按场景列出来。此阶段不考虑是否值得测或者资源是否允许。比如如果该需求适用与多种用户类型，就列出相应的场景。如果该需求还适用于不同信令操作流程，也相应的列出那些场景。至于用户类型和信令操作之间的交叉，由于组合可能性过多，除非是相互间的差别和风险都非常大，我们暂时未进一步划分。不同场景之间的组合，将在“设计测试用例”的过程中进行。&lt;/p&gt;

&lt;p&gt;由于有成员在会前未深入学习相关材料，导致会议进程较慢。不过好在过程中发现了不少问题，比如不同组件对接口的定义，或需求的理解不一致等等。&lt;/p&gt;

&lt;p&gt;作为主持者，我做得更多的是引导讨论的主题不要跑偏，并保证会议效率。一旦发现有话题讨论僵持不下的情况，就立即建议中止该话题的讨论。这种情况往往是争论一方或双方，在细节上不够清楚，需要会后找更熟悉的同事讨论确认。因此在会议记录上记一个action point，下次会议再回顾这个话题即可。&lt;strong&gt;Action point的owner最好只设置为特定的一人，并设置相应deadline。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;这一步我主要使用XMind思维脑图进行会议记录，快速直观。大节点如下所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140705_feature_grooming_xmind.png&quot; alt=&quot;XMind&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;add-more-check-points&quot;&gt;Add more check points&lt;/h3&gt;

&lt;p&gt;在拆分需求时，可同时进行，基于以往的开发和测试经验，列举出所有在需求文档中&lt;strong&gt;未提及&lt;/strong&gt;但&lt;strong&gt;可能出现&lt;/strong&gt;的场景（更多的是不同场景的组合或异常场景）。需求中已明确规定的异常处理，一般开发人员会相对注意，所以出问题的几率相对较小。反而是需求中未提到的异常，一旦在客户现场发生，程序处理极有可能出问题。这一步相对tricky，一方面，取决于与会人员的经验，要求我们不停的问what if并think wildly；另一方面，正常的分支可能只有有限的几种，但异常可能有无数种，因此要做一定的筛选。&lt;/p&gt;

&lt;p&gt;建议此步以测试人员为主导，但凡遇到诸如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;绝对&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;肯定&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;100%&lt;/code&gt;等此类词语，需仔细分析。以前发生过开发人员说“绝对没有问题”的场景，后来客户真就出了问题的惨剧。这时测试人员一定要“打破沙锅问到底”，如开发不能明确说出所以然，也需要把相应场景列上去。&lt;/p&gt;

&lt;h3 id=&quot;prioritize&quot;&gt;Prioritize&lt;/h3&gt;

&lt;p&gt;我将每个可测点从XMind上导入到Excel中，做了一些基础的分类，比如验证functionality的，验证exceptional的，验证feature inter-working的等等。&lt;/p&gt;

&lt;p&gt;接下来需要做的就是制定可测点相应的优先级。但如果只是凭经验简单排序，恐怕无法保证优先级制定的合理性。因此，我为每一点都新增了属性&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Importance&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Risk&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Difficulty&lt;/code&gt;。每个属性取值为范围为1/2/3。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Importance: 从功能角度评估可测点的重要性。
    &lt;ul&gt;
      &lt;li&gt;3: 非常重要。如果缺失该特性基本功能都无法运行；&lt;/li&gt;
      &lt;li&gt;2: 中度重要。如果缺失一些高级功能或者扩展功能可能无法运行；&lt;/li&gt;
      &lt;li&gt;1: 不太重要。一些锦上添花的功能，如对testability的增强等，实际客户无法感知；&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Risk: 从代码改动复杂度以及场景复杂度来评估可测点的风险。
    &lt;ul&gt;
      &lt;li&gt;3: 代码改动量很大，或相关场景以前出过大量问题等，风险很高；&lt;/li&gt;
      &lt;li&gt;2: 代码改动量不太大，风险一般；&lt;/li&gt;
      &lt;li&gt;1: 代码改动量很小，风险很小；&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Difficulty: 由于通信设备测试环境非常复杂，如果场景特别复杂，测试难度很大，所需effort也可能非常高。因此我将这一项也设为其中一个属性。
    &lt;ul&gt;
      &lt;li&gt;3: 场景简单，在已有测试环境/用例上简单更新即可测试，测试难度很小；&lt;/li&gt;
      &lt;li&gt;2: 场景有一定的难度，但仍可参考/复用已有的测试环境/用例，测试难度适中；&lt;/li&gt;
      &lt;li&gt;1: 场景复杂，没有可参考/复用的已有测试用例，构造环境需很长时间，测试难度很大；&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;我们将每个可测点的这三个属性值在会议上都评估出来。基于这三项属性的评估值，加上一定的权重，得到最后的优先级。权重是经验值，这里我们选择&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Importance&lt;/code&gt;权重40%，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Risk&lt;/code&gt;权重40%，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Difficulty&lt;/code&gt;权重20%。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Priority = Importance * 40% + Risk * 40% + Difficulty * 20%
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;最终的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Priority&lt;/code&gt;取值范围为[1, 3]，可带小数点。虽然这三项也是凭经验估计出来的，但细化后再排序总比直接排序更有说服力。基本上，&lt;strong&gt;越重要，风险越高，难度越小的可测点&lt;/strong&gt;，值会相应越大，表示&lt;strong&gt;优先级也越高&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140705_feature_grooming_check_points.png&quot; alt=&quot;checkpoints&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;design-test-cases&quot;&gt;Design test cases&lt;/h3&gt;

&lt;p&gt;这一步非常关键，因为期望输出就是每个测试用例的步骤和每一步的pass criteria，之后具体测试用例的设计会以此为guidance。这一步的主要原则是，&lt;strong&gt;在尽可能少的测试步骤中验证尽可能多的可测点，避免测试用例之间的重复或冗余&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;测试人员根据经验，结合User Stories的schedule，定制相应的测试用例。需要考虑几点：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;高优先级的可测点必须全覆盖，低优先级的采样测试，比如多种低优先级的组合，可选测其中一种或几种；&lt;/li&gt;
  &lt;li&gt;测试用例的排布遵循先简单后困难的顺序。开发的US(User Story)通常也是先交付较简单的功能，接着交付高级功能，最后交付容量和性能相关的功能；&lt;/li&gt;
  &lt;li&gt;尽量保证可测点均匀分布，避免出现某些测试用例需要检查数十个可测点，另一些测试用例又只测了一两个点的情况；&lt;/li&gt;
  &lt;li&gt;在设计用例步骤时，需要考虑用最精简的路径串联起尽可能多的状态，并且最好不要出现重复的状态。这里可能需要一些图论的知识。&lt;/li&gt;
  &lt;li&gt;需要明确测试用例每一步的check points，确保可测性；&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;analyze-uncovered-points&quot;&gt;Analyze uncovered points&lt;/h3&gt;

&lt;p&gt;最后需要分析所有未被覆盖的场景，通常这些可测点都是优先级相对较低的。我们需要：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;再过一遍那些可测点，确认是否在前期测试阶段如UT/MT中覆盖；&lt;/li&gt;
  &lt;li&gt;检查是否有必要在UT/MT中没有覆盖的可测点中，挑选部分补充调整到测试用例中；&lt;/li&gt;
  &lt;li&gt;对于决定彻底drop的可测点，可以列到risks中（当然是low risk了），以备后期回顾查阅；&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;known-issues&quot;&gt;Known issues&lt;/h2&gt;

&lt;p&gt;这次新特性的测试规划做下来，觉得还存在一些问题：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;部分与会人员对需求和specification没有前期准备，讨论过程中浪费太多时间在解释需求上；&lt;/li&gt;
  &lt;li&gt;整个过程下来，至少需要4~5次讨论，非常细致，花费effort较多，似乎有违scrum敏捷的原则；&lt;/li&gt;
  &lt;li&gt;如果有系统构架师参与，应该效果会更好，争端更容易当场确认和解决；&lt;/li&gt;
  &lt;li&gt;从头到尾我作为组织者，不仅主持了讨论，而且将材料及rough plan在每次讨论前都准备妥当。造成其他与会人员有一定的依赖性，而自己也累得够呛；&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;这次做下来收获还是颇丰的，对特性有了更深入的理解，消除了组件之间一些误解，并且在开发之前就发现并解决了部分潜在的问题。而对照最终的test plan，也可以很清楚的看到可测点的覆盖率，即使最终覆盖率没有达到100%，我们对风险一目了然，而且对输出的测试用例也能相对自信。在这个特性测试结束后，我会做一次retrospective，回顾这次实践的结果。&lt;/p&gt;

&lt;p&gt;当然流程是人制定的，也是人去实施的。因此要想保证高质量的输出，每个讨论者都要keep quality in mind，积极参与其中，贡献自己的力量。&lt;/p&gt;

&lt;p&gt;如果以后还有人问我“如何保证测试覆盖率”，我将用这篇文章来回答他。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Jekyll Notes</title>
   <link href="https://blog.pzheng.me//2014/07/03/Jekyll-Notes/"/>
   <updated>2014-07-03T11:17:08+00:00</updated>
   <id>https://blog.pzheng.me//2014/07/03/Jekyll-Notes</id>
   <content type="html">&lt;p&gt;As I mentioned in &lt;a href=&quot;http://blog.pzheng.me/2014/05/25/migrating-from-octopress-to-jekyll/&quot;&gt;previous post&lt;/a&gt;, Jekyll on GitHub is lack of some basic features such as category and archive pages since it doesn’t support plugins. Here is how to add those features without plugin support. Of course, all tips were found from the open internet :smile:.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h2&gt;

&lt;p&gt;Sometimes we want to add some footnotes for reference as in &lt;a href=&quot;http://blog.pzheng.me/2014/07/02/2014H1-summary/&quot;&gt;this post&lt;/a&gt;. The original markdown parser “redcarpet” cannot support it, at least for Jekyll on Github. We just need to change below line in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;markdown:         redcarpet
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;markdown:         kramdown
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At the place you want to insert the subscript, just add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[^1]&lt;/code&gt;. You can choose whatever number you like. Then at the end of post, add footnote as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[^1]: here is an example of footnote.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Please don’t forget the colon mark next to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[^1]&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;disqus-comments&quot;&gt;Disqus Comments&lt;/h2&gt;

&lt;p&gt;Insert below codes at the end of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_layouts/post.html&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;disqus_thread&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/javascript&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;disqus_shortname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;YOURNAME&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// required: replace example with your forum shortname
&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/* * * DON'T EDIT BELOW THIS LINE * * */&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dsq&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dsq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;text/javascript&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dsq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;dsq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;src&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;disqus_shortname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;.disqus.com/embed.js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dsq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})();&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;noscript&amp;gt;&lt;/span&gt;Please enable JavaScript to view the &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://disqus.com/?ref_noscript&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;comments powered by Disqus.&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/noscript&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;nextprevious-post-navigator&quot;&gt;Next/Previous Post Navigator&lt;/h2&gt;

&lt;p&gt;Insert below codes between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;post&lt;/code&gt; div and Disqus part in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_layouts/post.html&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;navigator&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  {% if page.previous %}
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;float:left&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ page.previous.url }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;« {{ page.previous.title }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  {% endif %}
  {% if page.next %}
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;float:right&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ page.next.url }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{{ page.next.title }} »&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  {% endif %}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;archive-page&quot;&gt;Archive Page&lt;/h2&gt;

&lt;p&gt;Create new file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;archive.html&lt;/code&gt; in root directory as &lt;a href=&quot;https://raw.githubusercontent.com/happybit/happybit.github.io/master/archive.html&quot;&gt;this file&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;category-page&quot;&gt;Category Page&lt;/h2&gt;

&lt;p&gt;Create new file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;categories.html&lt;/code&gt; in root directory as &lt;a href=&quot;https://raw.githubusercontent.com/happybit/happybit.github.io/master/categories.html&quot;&gt;this file&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can display category for each post. Just need to add below line in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_layouts/post.html&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;post-date&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{{ page.date | date_to_string }}&lt;span class=&quot;ni&quot;&gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;/span&gt;Category: {% for category in page.categories %}&lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ site.url }}/categories.html#{{ category }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;title=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Pages categorized {{ category }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;category&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{{ category }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;{% unless forloop.last %} &lt;span class=&quot;ni&quot;&gt;&amp;amp;bull;&lt;/span&gt; {% endunless %}{% endfor %}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;search--feed&quot;&gt;Search &amp;amp; Feed&lt;/h2&gt;

&lt;p&gt;You can customize &lt;a href=&quot;https://www.google.com/cse/all&quot;&gt;Google&lt;/a&gt; search for your personal website. After get your specific URL, just paste into the appropriate place in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_includes/sidebar.html&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;a class=&quot;sidebar-nav-item&quot; href=&quot;https://www.google.com:443/cse/publicurl?cx=xxxxxxxxxxxxx&quot;&amp;gt;Search&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Similarly, you can get the feed URL via &lt;a href=&quot;www.feedburner.com&quot;&gt;FeedBurner&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;a class=&quot;sidebar-nav-item&quot; href=&quot;http://feeds.feedburner.com/knoise&quot;&amp;gt;RSS&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;google-analytics&quot;&gt;Google Analytics&lt;/h2&gt;

&lt;p&gt;Create new file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_includes/google_analytics.html&lt;/code&gt; and paste your Google Analytics scripts. Then insert below line before &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;body&amp;gt;&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_layouts/default.html&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{%  include google_analytics.html %}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</content>
 </entry>
 
 <entry>
   <title>2014H1 Summary</title>
   <link href="https://blog.pzheng.me//2014/07/02/2014H1-summary/"/>
   <updated>2014-07-02T13:11:08+00:00</updated>
   <id>https://blog.pzheng.me//2014/07/02/2014H1-summary</id>
   <content type="html">&lt;p&gt;Every weekend, I would spend less than half an hour to summarize my personal and work issues during the past week according to my Emacs Org-mode records. And every month, I will collect all the weekly summaries to check monthly status as well as look forward to the future. Yes. I admit that I am kind of boring with regular habits. So here comes my 2014 first half year book.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;learning&quot;&gt;Learning&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Only learned a bit of LTE which was interrupted later by heavy workload;&lt;/li&gt;
  &lt;li&gt;Tried to self learn Android development and Java. Suspended right now;&lt;/li&gt;
  &lt;li&gt;Finished below six books while several unlisted are still ongoing:
    &lt;ul&gt;
      &lt;li&gt;&lt;em&gt;Joel on Software&lt;/em&gt; by &lt;em&gt;Joel Spolsky&lt;/em&gt;;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://blog.pzheng.me/2014/04/06/on-top-of-tides/&quot;&gt;&lt;em&gt;On top of tides&lt;/em&gt;&lt;/a&gt; 《浪潮之巅》 by &lt;em&gt;Wu Jun&lt;/em&gt; 吴军 ;&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;The Seven Habits of Highly Effective People&lt;/em&gt; by &lt;em&gt;Stephen R.Covey&lt;/em&gt;;&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;Blossoms&lt;/em&gt;《繁花》 by &lt;em&gt;Jin Yucheng&lt;/em&gt; 金宇澄;&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;Lo Shu Square &amp;amp; Ho Tu&lt;/em&gt;《洛书河图》 by &lt;em&gt;A Cheng&lt;/em&gt; 阿城;&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;The Monk&lt;/em&gt; 《道士下山》 by &lt;em&gt;Xu Haofen&lt;/em&gt; 徐皓峰 &lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;work&quot;&gt;Work&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;From January to Mid May, major effort was spend on new feature Enhanced CELL_FACH, including:
    &lt;ul&gt;
      &lt;li&gt;Enhanced CELL_FACH feature learning;&lt;/li&gt;
      &lt;li&gt;Enhanced CELL_FACH feature basic testing;&lt;/li&gt;
      &lt;li&gt;Enhanced CELL_FACH feature workshop;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;From Mid May to present, mainly focus on:
    &lt;ul&gt;
      &lt;li&gt;Testing efficiency investigation and improvement in new team;&lt;/li&gt;
      &lt;li&gt;New features testing plan for a brand new product in our company;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;personal&quot;&gt;Personal&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Major change is job rotation. Internally transferred to another team for a new product;&lt;/li&gt;
  &lt;li&gt;In March, caught some ailment and fortunately not serious;&lt;/li&gt;
  &lt;li&gt;Helped my sister to build her personal website &lt;a href=&quot;www.xinyue.in&quot;&gt;Xinyue&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;Two domestic trips:
    &lt;ul&gt;
      &lt;li&gt;Xi’an in April;&lt;/li&gt;
      &lt;li&gt;Beijing business trip in May;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Formed two habits:
    &lt;ul&gt;
      &lt;li&gt;Get up early in the morning(6:00-6:30 AM);&lt;/li&gt;
      &lt;li&gt;Write blog post weekly no matter how busy I am (hasn’t formed yet :sob:);&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Learning: neither learned much new knowledge nor read enough books;&lt;/li&gt;
  &lt;li&gt;Work: Enhanced CELL_FACH is a complicated feature. I was really glad to take this challenge. From learning, to testing, then training, I have learned a lot;&lt;/li&gt;
  &lt;li&gt;Work: After transferred to new team, the tasks and workload were suddenly increased. Super busy;&lt;/li&gt;
  &lt;li&gt;Personal: tried to step out of the comfort zone and got some outside opportunities. But finally decided to stay (many thanks to my former and current managers);&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;next&quot;&gt;Next&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Need to focus on limited things for self-learning;&lt;/li&gt;
  &lt;li&gt;Work efficiency needs to be improved further because too many things have to learn for this new product. Need more focus and concentration;&lt;/li&gt;
  &lt;li&gt;Excersice should be on my list next half year;&lt;/li&gt;
  &lt;li&gt;Make better use of fragmentary time;&lt;/li&gt;
  &lt;li&gt;Plan my life according to the long term and short term target;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Chen_Kaige&quot;&gt;Chen Kaige&lt;/a&gt; is directing a new film based on this novel. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>RACH Part 4: AICH transmission timing</title>
   <link href="https://blog.pzheng.me//2014/06/21/rach-part-4-aich-transmission-timing/"/>
   <updated>2014-06-21T03:15:08+00:00</updated>
   <id>https://blog.pzheng.me//2014/06/21/rach-part-4-aich-transmission-timing</id>
   <content type="html">&lt;p&gt;&lt;em&gt;AICH transmission timing&lt;/em&gt;, either &lt;em&gt;0&lt;/em&gt; or &lt;em&gt;1&lt;/em&gt;, is informed to UE by RNC in SIB5/5bis via BCH.&lt;/p&gt;

&lt;!--more--&gt;

&lt;ul&gt;
  &lt;li&gt;If &lt;em&gt;AICH transmission timing&lt;/em&gt; is 0, the next PRACH preamble will be initiated at earliest 3 access slots later after previous failed(no acknowledggement or acknowledggement is NACK) PRACH preamble. And AICH is expected to arrive at UE after 1.5 access slots;&lt;/li&gt;
  &lt;li&gt;If &lt;em&gt;AICH transmission timing&lt;/em&gt; is 1, the next PRACH preamble will be initiated at earliest 4 access slots later after previous failed(no acknowledggement or acknowledggement is NACK) PRACH preamble. And AICH is expected to arrive at UE after 2.5 access slots;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below figures show the timing of the whole PRACH process when &lt;em&gt;AICH transmission timing&lt;/em&gt; is 0. &lt;em&gt;t&lt;sub&gt;AIF&lt;/sub&gt;&lt;/em&gt; stands for the transmission time on the air interface. Whereas &lt;em&gt;t&lt;sub&gt;proc&lt;/sub&gt;&lt;/em&gt; is the processing time within Node B, including receiving/transmission time in RF and baseband processing time, etc.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140621_rach_part4_aich_transmission_timing.png&quot; alt=&quot;Mapping&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As you can see, since the duration between PRACH preamble and AICH is fixed as 1.5 access slots, &lt;em&gt;t&lt;sub&gt;AIF&lt;/sub&gt;&lt;/em&gt; impacts &lt;em&gt;t&lt;sub&gt;proc&lt;/sub&gt;&lt;/em&gt; a lot:&lt;/p&gt;

&lt;p&gt;2 * &lt;em&gt;t&lt;sub&gt;AIF&lt;/sub&gt;&lt;/em&gt; + &lt;em&gt;t&lt;sub&gt;proc&lt;/sub&gt;&lt;/em&gt; + 4096 chips &amp;lt;= 1.5 access slots&lt;/p&gt;

&lt;p&gt;For simplicity, let’s assume:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;t&lt;sub&gt;AIF&lt;/sub&gt;&lt;/em&gt; = &lt;em&gt;d&lt;sub&gt;UE&lt;/sub&gt;&lt;/em&gt; / &lt;em&gt;C&lt;sub&gt;light&lt;/sub&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;in above formula, &lt;em&gt;d&lt;sub&gt;UE&lt;/sub&gt;&lt;/em&gt; is the distance between Node B and UE while &lt;em&gt;C&lt;sub&gt;light&lt;/sub&gt;&lt;/em&gt; is the light speed, i.e. 3e8 meters per second.&lt;/p&gt;

&lt;p&gt;In case the cell radius is 20 kilometers, &lt;em&gt;t&lt;sub&gt;AIF&lt;/sub&gt;&lt;/em&gt; is 0.0667 millisecond. Therefore we can calculate the maximum allowed &lt;em&gt;t&lt;sub&gt;proc&lt;/sub&gt;&lt;/em&gt; is 0.8 millisecond. And the more cell radius, the less &lt;em&gt;t&lt;sub&gt;proc&lt;/sub&gt;&lt;/em&gt; is allowed. So generally, the vendors will limit the maximum cell radius(for instance 60 km) when &lt;em&gt;AICH transmission timing&lt;/em&gt; 0 is used by the operators.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>RACH Part 3: RACH info in SIB5</title>
   <link href="https://blog.pzheng.me//2014/06/13/rach-part-3-rach-info-in-sib5/"/>
   <updated>2014-06-13T23:06:08+00:00</updated>
   <id>https://blog.pzheng.me//2014/06/13/rach-part-3-rach-info-in-sib5</id>
   <content type="html">&lt;p&gt;All of the RACH related information is broadcasted on SIB5/5bis via BCH. &lt;a href=&quot;http://blog.pzheng.me/2014/06/07/rach-part-2-ac-and-asc/&quot;&gt;Last time&lt;/a&gt;, the &lt;em&gt;PRACH partitioning&lt;/em&gt;, which contained the available PRACH preamble signatures and sub-channels, was elaborated in details. But as I mentioned, we need more info to check the exact available signatures and sub-channels.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Once I was confused about SIB5 and SIB5bis and later found they were almost identical. On &lt;a href=&quot;http://wireless.agilent.com/rfcomms/refdocs/wcdma/wcdma_gen_bse_freqbandind.html&quot;&gt;Agilent website&lt;/a&gt; it says:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;SIB5bis was introduced by 3GPP as a way to allow new frequency bands to be created that overlap existing frequency bands. For example, when Band IV was introduced it overlapped Band I. To prevent older Band I UEs from camping on Band IV cells (and then transmitting their PRACH messages on the wrong uplink frequency due to a different Tx/Rx frequency separation), Band IV networks transmit SIB5bis instead of SIB5. Band IV UEs expect SIB5bis and can camp to the cell, but older Band I mobiles simply see that SIB5 is missing and thus do not camp to the Band IV cell. SIB5bis is identical to SIB5 except for the SIB type.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In &lt;em&gt;PRACH System Information List&lt;/em&gt; of SIB5/5bis, there is one Information Elements block called &lt;em&gt;PRACH RACH Info&lt;/em&gt;. Basically, it specifies the available signatures and sub-channels for this PRACH as well as other necessary info like available SF, preamble scrambling code word number and puncturing limit, etc.&lt;/p&gt;

&lt;p&gt;With this part of information and &lt;em&gt;PRACH partitioning&lt;/em&gt;, we can finnally get the exact available signatures and sub-channels rather than just index or bit number.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140614_rach_part3_sib5_sib5bis.png&quot; alt=&quot;SIB 5/5bis&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The mapping for available sub-channels is kind of tricky between &lt;em&gt;PRACH Partitioning&lt;/em&gt; and &lt;em&gt;PRACH System Information List&lt;/em&gt;. Because &lt;em&gt;AICH Transmission Timing&lt;/em&gt; should be also taken into account. And you can find the specific mechanism in &lt;a href=&quot;www.3gpp.org/ftp/tsg_ran/wg1_rl1/TSGR1_05/.../r1-99650.pdf&quot;&gt;TSG WG1#5 (99) 650&lt;/a&gt;. (I will introduce &lt;em&gt;AICH Transmission Timing&lt;/em&gt; in next post and how it impacts Node B process.)&lt;/p&gt;

&lt;p&gt;So now we can see the whole mapping is presented as below.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140614_rach_part3_mapping.png&quot; alt=&quot;Mapping&quot; /&gt;&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>RACH Part 2: Access Class and Access Service Class</title>
   <link href="https://blog.pzheng.me//2014/06/08/rach-part-2-ac-and-asc/"/>
   <updated>2014-06-08T03:06:08+00:00</updated>
   <id>https://blog.pzheng.me//2014/06/08/rach-part-2-ac-and-asc</id>
   <content type="html">&lt;p&gt;In &lt;a href=&quot;http://blog.pzheng.me/2014/05/25/rach-part-1-access-slot-sub-channels/&quot;&gt;previous post&lt;/a&gt;, I have illustrated the access slot and sub-channel is the basic time unit for PRACH. As we know, RACH is &lt;strong&gt;R&lt;/strong&gt;andom &lt;strong&gt;A&lt;/strong&gt;ccess &lt;strong&gt;Ch&lt;/strong&gt;annel which means UE shall initiate PRACH preamble &lt;em&gt;somehow&lt;/em&gt; randomly. However, it doesn’t mean UE could access to network at any access slot. The Access Service Class(ASC) defines the available sub-channels as well as PRACH preamble signatures.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;define-asc&quot;&gt;Define ASC&lt;/h2&gt;

&lt;h3 id=&quot;ue-in-idle-mode&quot;&gt;UE in Idle mode&lt;/h3&gt;

&lt;p&gt;Access Class(AC) is ranged from 0 to 15, while normal UE is randomly allocated AC between 0~9(stored in USIM). AC 10 is not used in field. And AC 11-15 are usded for special or emergency services.&lt;/p&gt;

&lt;p&gt;When UE in RRC Idle mode tries to access to the network via PRACH preamble, it will firstly read system information(SIB) from BCH(physical channel P-CCPCH), to get the “AC to ASC mapping table”. The value range of ASC is [0, 7] which is totally eight values.&lt;/p&gt;

&lt;p&gt;Here is a snippet of SIB5.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140608_rach_part2_sib5.png&quot; alt=&quot;snippet of SIB 5&quot; /&gt;&lt;/p&gt;

&lt;p&gt;There are seven IEs in the block of “ac-To-ASC-MappingTable”. And each IE corresponds to certain ACs and their ASC respectively as below table. Please note to not mix these seven IEs with eight possible ASC values.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140608_rach_part2_ac_asc_mapping.png&quot; alt=&quot;snippet of SIB 5&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Hence we can find that all ACs’ ASC is &lt;strong&gt;0&lt;/strong&gt;, i.e. there is only one Access Service Class for this PRACH. Thus there is only one PRACH partitioning as shown in the snippet of SIB5. If there are two ASC (0 and 1), there will be two PRACH partitioning. And the first one for ASC 0 whereas the other one for ASC 1.&lt;/p&gt;

&lt;h3 id=&quot;ue-in-connected-mode&quot;&gt;UE in connected mode&lt;/h3&gt;

&lt;p&gt;When UE is in connected mode, i.e. CELL_FACH mode, ASC is decided by:
    ASC = Min(MLP, NumASC)&lt;/p&gt;

&lt;p&gt;In which, &lt;em&gt;MLP&lt;/em&gt; stands for MAC Logical Channel Priority signalled to UE for each logical channel. And &lt;em&gt;NumASC&lt;/em&gt; is the configured maximum ASC number.&lt;/p&gt;

&lt;h2 id=&quot;next-step&quot;&gt;Next step&lt;/h2&gt;

&lt;p&gt;In PRACH partitioning block, we can find the available PRACH preamble signatures and sub-channels. But it’s still implicit. We need to combine these infomations with PRACH RACH Info in SIB5 to get the exact available signatures and sub-channels. I will explain it later.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>[Promotion] A New Website for An Independent Designer</title>
   <link href="https://blog.pzheng.me//2014/06/01/promotion-independent-designer/"/>
   <updated>2014-06-01T11:48:08+00:00</updated>
   <id>https://blog.pzheng.me//2014/06/01/promotion-independent-designer</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;Alert&lt;/strong&gt;: this post includes contents for promotion and advertisement. Please skip this one if you are not interested.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;I just deployed a new website &lt;a href=&quot;http://www.xinyue.in&quot;&gt;Xinyue(新月)&lt;/a&gt;, which is powered by &lt;a href=&quot;http://wordpress.org/&quot;&gt;Wordpress&lt;/a&gt;, for my sister &lt;em&gt;Zehui&lt;/em&gt;, an independent jewellery designer. After graduated from &lt;a href=&quot;http://www.gzarts.edu.cn&quot;&gt;Guangzhou Academy of Fine Arts&lt;/a&gt;, she worked as a designer in fashion and garment industry for several years. Later she followed her heart, resigned from company and entered a new field: jewellery design mainly based on jade. As we know, nowadays it’s not easy to make a living from designing independently in China. Finally she made it and created a batch of amazing products by herself.&lt;/p&gt;

&lt;p&gt;Wordpress is so handy that I only spent half an day to build the site and customize the &lt;a href=&quot;http://www.dessign.net/simplephototheme/&quot;&gt;theme&lt;/a&gt;. Now the rough framework was finished but most of the contents are still under construction. And the price and offer details will be added soon. Sorry for any inconvenience.&lt;/p&gt;

&lt;p&gt;I put two pictures of the beautiful products on the bottom of this post. If you feel interested, please go to her website &lt;a href=&quot;http://www.xinyue.in&quot;&gt;Xinyue&lt;/a&gt; for further check. If you want to buy it, you can contact me or her directly.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140601_independent_designer_1.jpg&quot; alt=&quot;xilu&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140601_independent_designer_2.jpg&quot; alt=&quot;zhibai&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>TOAWS, TOAWE and TOA</title>
   <link href="https://blog.pzheng.me//2014/05/31/toaws-toawe-and-toa/"/>
   <updated>2014-05-31T14:12:08+00:00</updated>
   <id>https://blog.pzheng.me//2014/05/31/toaws-toawe-and-toa</id>
   <content type="html">&lt;p&gt;Last time one of my colleagues asked me what was &lt;em&gt;TOAWS&lt;/em&gt;, &lt;em&gt;TOAWE&lt;/em&gt; and &lt;em&gt;TOA&lt;/em&gt;. I knew it related to Frame Protocol and &lt;em&gt;TOA&lt;/em&gt; was time of arrival. But I cannot remember any more. So I did some investigation and here are some notes.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;These definitions were initiated by Nokia in &lt;a href=&quot;http://www.3gpp.org/ftp/tsg_ran/WG3_Iu/TSGR3_05/docs/Zips/R3-99663.zip&quot;&gt;Tdoc R3-99663&lt;/a&gt; and refined by Ericsson in &lt;a href=&quot;http://www.3gpp.org/ftp/tsg_ran/WG3_Iu/TSGR3_06/docs/Pdfs/r3-99875.pdf&quot;&gt;Tdoc R3-99875&lt;/a&gt; in 1999. Please note, in R3-99875, it mentioned 3GPP &lt;a href=&quot;http://www.3gpp.org/DynaReport/25401.htm&quot;&gt;TS25.401&lt;/a&gt;(V1.2.1) would be updated accordingly. But later “the synchronisation in UTRAN” chapter was seperated as an individual 3GPP &lt;a href=&quot;http://www.3gpp.org/DynaReport/25402.htm&quot;&gt;TS25.402&lt;/a&gt;. So now the official definitions are presented in sub-clause 5 of TS25.402(V11.0.0) while the mechanism is introduced in sub-clause 7 of the same 3GPP technical specification.&lt;/p&gt;

&lt;p&gt;These three timers are used for transport channel synchronisation, more specifically, for timing adjustment on Iub/Iur. Figure 10 in TS25.402 illustrates how it works.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140531_toaws_toawe_toa.png&quot; alt=&quot;toaws toawe toa&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;TOAWS&lt;/em&gt;(Time of Arrival Window Startpoint) and &lt;em&gt;TOAWE&lt;/em&gt;(Time of Arrival Window Endpoint) are defined in NBAP messages for Transport bearer Setup/Addition/Reconfiguration.&lt;/p&gt;

&lt;p&gt;In the above figure, it’s assumed that the target CFN on air interface is 152 for certain tranport block. Since Layer 1 in Node B needs some processing time(t&lt;sub&gt;proc&lt;/sub&gt;) to encode &amp;amp; transmit etc. Therefore, this tranport block should arrive in Node B before CFN 152. Node B will send control frame to RNC for timing adjustment with &lt;em&gt;TOA&lt;/em&gt; which is the time difference between the &lt;em&gt;TOAWE&lt;/em&gt; and when a data frame is received.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If TBS arrives too early before &lt;em&gt;TOAWS&lt;/em&gt;, it will increase the burden of buffer in Node B. Node B will send Timing Adjustment Control frame with positive &lt;em&gt;TOA&lt;/em&gt; to RNC;&lt;/li&gt;
  &lt;li&gt;If TBS arrives right between &lt;em&gt;TOAWS&lt;/em&gt; and &lt;em&gt;TOAWE&lt;/em&gt;, timing is perfect. Thus no Timing Adjustment Control frame needed;&lt;/li&gt;
  &lt;li&gt;If TBS arrives between &lt;em&gt;TOAWE&lt;/em&gt; and &lt;em&gt;LTOA&lt;/em&gt;, Node B is still able to process such TBS. But it’s a bit late and dangerous that Node B might not be so quick to process it. So Node B will send Timing Adjustment Control frame with negative &lt;em&gt;TOA&lt;/em&gt; to RNC;&lt;/li&gt;
  &lt;li&gt;If TBS arrives too late even after &lt;em&gt;LTOA&lt;/em&gt;, Node B is unable to process this TBS and it will send Timing Adjustment Control frame with negative &lt;em&gt;TOA&lt;/em&gt; to RNC;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After RNC receives Timing Adjustment Control frame with &lt;em&gt;TOA&lt;/em&gt;, it will adjust the DL data sending timing accordingly, to synchronize with Node B in this way.&lt;/p&gt;

&lt;p&gt;The situation for soft handover is more complicated. Please check Figure 14 in TS25.402 for more details.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Migrating from Octopress to Jekyll</title>
   <link href="https://blog.pzheng.me//2014/05/25/migrating-from-octopress-to-jekyll/"/>
   <updated>2014-05-25T11:17:08+00:00</updated>
   <id>https://blog.pzheng.me//2014/05/25/migrating-from-octopress-to-jekyll</id>
   <content type="html">&lt;p&gt;Just remind you, this site has been migrated from &lt;a href=&quot;http://octopress.org&quot;&gt;Octopress&lt;/a&gt; to &lt;a href=&quot;http://jekyllrb.com&quot;&gt;Jekyll&lt;/a&gt;. The theme was cloned from &lt;a href=&quot;http://lanyon.getpoole.com/&quot;&gt;Lanyon&lt;/a&gt; and I tweaked it a bit.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Honestly, Octopress is so far so good as a blog framework. It’s simple and static. And it supports markdown syntax naturally without needing any dedicated webhost, since it could be hosted on &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;. However, the biggest problem to me is, the whole site needs to be deloyed &lt;strong&gt;locally&lt;/strong&gt; whenever I am going to post new article, which means I can hardly publish posts conveniently on the other computer except my home PC.&lt;/p&gt;

&lt;p&gt;After searching around, I found Jekyll, as the basic framework of Octopress, could be easily depoyed on GitHub as well(so it’s extremely easy for migration). Thus it’s also simple and static. Even better than Octopress in terms of simplicity.&lt;/p&gt;

&lt;p&gt;For instance, there is only one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; branch for Jekyll and the structure of folders is simple as below:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;├── 404.html
├── about.md
├── archive.html
├── atom.xml
├── CNAME
├── _config.yml
├── _includes
├── index.html
├── _layouts
├── LICENSE.md
├── _posts
├── public
└── README.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Though Jekyll on GitHub is unable to support plugins due to security risks. Fortunately, I just need a very simple blog site and am not eager for those fancy features introduced by various plugins.&lt;/p&gt;

&lt;p&gt;Besides, I could write and publish posts almost anywhere via:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://prose.io&quot;&gt;Prose.io&lt;/a&gt; on web;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.github.mobile&quot;&gt;GitHub&lt;/a&gt; or &lt;a href=&quot;https://play.google.com/store/apps/details?id=gr.tsagi.jekyllforandroid&quot;&gt;Jekyll&lt;/a&gt; apps on Android;&lt;/li&gt;
  &lt;li&gt;Just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clone&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;push&lt;/code&gt; new post on another PC;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And then GitHub will take care of the rest:smile:.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>RACH Part 1: Access Slot and Sub-channel</title>
   <link href="https://blog.pzheng.me//2014/05/25/rach-part-1-access-slot-sub-channels/"/>
   <updated>2014-05-25T10:55:08+00:00</updated>
   <id>https://blog.pzheng.me//2014/05/25/rach-part-1-access-slot-sub-channels</id>
   <content type="html">&lt;p&gt;I studied and worked on Enhanced CELL_FACH(3GPP Rel8 feature) during past a few months. This feature was evolved based on R99 RACH and Rel6 E-DCH. Here are some learning notes about R99 RACH.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Let’s get clear about some critial definitions firstly.&lt;/p&gt;

&lt;h2 id=&quot;access-slot&quot;&gt;Access slot&lt;/h2&gt;

&lt;p&gt;As we know, slot is one of the important timing unit in UMTS, just like frame, chip, etc. And one slot consists of 2560 chips whereas one frame(10ms) has 15 slots. However, in R99 RACH, one &lt;strong&gt;Access slot&lt;/strong&gt; is 5120 chips instead, i.e. two normal slots. Accordingly, two frames(20ms) have 15 access slots. The reason why one access slot occupies 5120 chips is, one PRACH preamble and AICH is as long as 4096 slots, which is more than one slot but less than two slots.&lt;/p&gt;

&lt;h2 id=&quot;sub-channel&quot;&gt;Sub-channel&lt;/h2&gt;

&lt;p&gt;Sub-channel defines a sub-set of the total set of uplink access slots. There are a total of 12 RACH sub-channels. Since two frames have 15 Access slots, and the least common multiple for 12 and 15 is 60 access slots, i.e. eight frames(80 ms). Thus the mapping of access slot and sub-channel remains the same every 80ms.&lt;/p&gt;

&lt;p&gt;Here is the table for available uplink access slots for different RACH sub-channels in &lt;em&gt;3GPP TS25.214 Table 7&lt;/em&gt;. As you can see, for sub-channel #3, it could be:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;#3 access slot in frames with SFN modulo 8 = 0;&lt;/li&gt;
  &lt;li&gt;#0 access slot in frames with SFN module 8 = 2;&lt;/li&gt;
  &lt;li&gt;#12 access slot in frames with SFN module 8 = 3;&lt;/li&gt;
  &lt;li&gt;#9 access slot in frames with SFN module 8 = 5;&lt;/li&gt;
  &lt;li&gt;#6 access slot in frames with SFN module 8 = 6;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140525_rach_part1_1.png&quot; alt=&quot;RACH part 1_1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Some guys might be confused by above table. So I drew another figure by taking SFN 96~103 as example. SFN 104 is the same as SFN 96 due to the cycle period of 80ms.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140525_rach_part1_2.png&quot; alt=&quot;RACH part 1_2&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Access slot is basic timing unit for R99 RACH for aligning PRACH preamble and AICH channel. Sub-channel is the available set of access slots for certain UE. In my view, sub-channel is the possibility for UE to initiate PRACH preamble. The more available sub-channels, the more possibility to establish a call successfully, especially when there are large quantity of UEs with BHCA (busy hour call attempt).&lt;/p&gt;

&lt;p&gt;Regarding how to map sub-channels to certain UE, I will illustrate it in &lt;a href=&quot;http://blog.pzheng.me/2014/06/07/rach-part-2-ac-and-asc/&quot;&gt;next posts&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Aria2 on Archlinux</title>
   <link href="https://blog.pzheng.me//2014/05/18/aria2-on-archlinux/"/>
   <updated>2014-05-18T13:56:08+00:00</updated>
   <id>https://blog.pzheng.me//2014/05/18/aria2-on-archlinux</id>
   <content type="html">&lt;p&gt;Days ago, I configured my netbook for &lt;a href=&quot;http://blog.pzheng.me/2014/02/24/build-home-backup-system/&quot;&gt;BitTorrent Sync&lt;/a&gt;. This week, I proceeded further to install &lt;a href=&quot;http://aria2.sourceforge.net/&quot;&gt;Aria2&lt;/a&gt; on it for the purpose of remote downloading.&lt;/p&gt;

&lt;!--more--&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Install Aria2 via Pacman and then create file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.aria2/aria2.conf&lt;/code&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; $ sudo pacman -S aria2
 $ mkdir ~/.aria2
 $ touch ~/.aria2/aria2.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Configure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.aria2/aria2.conf&lt;/code&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; #configuration file for aria2c
 continue=true
 daemon=true
 dir=/home/YOURNAME/Pic/Download
 file-allocation=none
 input-file=/home/YOURNAME/.aria2/input.conf
 log-level=warn
 log=/home/YOURNAME/.aria2/aria2.log
 max-connection-per-server=3
 max-concurrent-downloads=3
 max-overall-download-limit=0
 max-upload-limit=128K
 #split=3
 check-integrity=true
 max-tries=5
 retry-wait=3
 min-split-size=5M
 #enable-http-pipelining=true
 enable-rpc=true
 rpc-listen-all=true
 rpc-allow-origin-all=true
 disc-cache=32M
 save-session=/home/YOURNAME/.aria2/input.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Please notice to create &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;input.conf&lt;/code&gt; &amp;amp; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aria2.log&lt;/code&gt; in the same folder as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aria2.conf&lt;/code&gt;. Otherwise Aria2 doesn’t work properly and YAAW would report “internal server error”.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Aria2 autostart on boot:&lt;/p&gt;

    &lt;p&gt;Save this file as /etc/systemd/system/aria2c.service, adjust username and config path according to your setup. Ensure your config is set to deamonize (daemon=true).&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; [Unit]
 Description=Aria2c download manager
 After=network.target
    
 [Service]
 Type=forking
 User=root
 RemainAfterExit=yes
 ExecStart=/usr/bin/aria2c --conf-path=/home/YOURNAME/.aria2/aria2.conf
    
 [Install]
 WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If fault reported as “code=exited, status=217/USER”, please modify “User=***” to proper user, e.g. “root”.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Install Apache:&lt;/p&gt;

    &lt;p&gt;Apache configuration file: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/httpd/conf/httpd.conf&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;DocumentRoot: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv/http&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Install &lt;a href=&quot;https://github.com/binux/yaaw&quot;&gt;YAAW&lt;/a&gt; for Aria2 webfront UI. You can choose any other alternatives as you like.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; $ cd /srv/http
 $ git clone https://github.com/binux/yaaw
 $  sudo systemctl start aria2c
 $ sudo systemctl start httpd.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Configure for &lt;a href=&quot;lixian.xunlei.com&quot;&gt;Thunder offline&lt;/a&gt; or &lt;a href=&quot;yun.baidu.com&quot;&gt;Baidu Yun&lt;/a&gt; download:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;Install Tampermonkey or Greasemonkey extension for js in Chrome/Firefox;&lt;/li&gt;
      &lt;li&gt;Install JS script from &lt;a href=&quot;https://github.com/binux/ThunderLixianExporter&quot;&gt;here&lt;/a&gt;;&lt;/li&gt;
      &lt;li&gt;On Xunlei offline download/Baidu Yun webpage, configure Aria2 JSON-RPC Path to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://192.168.2.103:6800/jsonrpc&lt;/code&gt;;&lt;/li&gt;
      &lt;li&gt;Install &lt;a href=&quot;https://chrome.google.com/webstore/detail/mblmc%E8%BF%85%E9%9B%B7%E7%A6%BB%E7%BA%BFqq%E6%97%8B%E9%A3%8E%E7%99%BE%E5%BA%A6%E7%BD%91%E7%9B%98360%E4%BA%91%E7%9B%98%E7%AD%89ar/iamaphkapjbdhhpdapkalhanifedeged&quot;&gt;MBL&amp;amp;MC extension&lt;/a&gt; in chrome;&lt;/li&gt;
      &lt;li&gt;There will be “YAAW” or “Aria2c for RPC” option on Xunlei offline download/Baidu Yun webpage;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now you can download files on PC or even &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.paranoia.remotearia2&quot;&gt;cellphone&lt;/a&gt; remotely in the same LAN. I tried it on both &lt;a href=&quot;www.xunlei.com&quot;&gt;Xunlei&lt;/a&gt; and &lt;a href=&quot;yun.baidu.com&quot;&gt;Baidu Yun&lt;/a&gt;. It works like a charm! Or you can even configure Dynamic DNS to remotely monitor and download files. Cool.&lt;/p&gt;

&lt;p&gt;Tips for “internal server error”:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Aria2 doesn’t run as daemon. Check the process firstly;&lt;/li&gt;
  &lt;li&gt;JSON-RPC path is incorrect on client(PC/cellphone);&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rpc-secret&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rpc-user/password&lt;/code&gt; is in use but it isn’t configured in JSON-RPC path;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If Aria2 stops automatically within several seconds after downloading without completion, you might need to tweak your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.aria2.conf&lt;/code&gt; file. Some websites limit the maximum simultaneous connections. So I set “max-connection-per-server=3” and it works.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>This Week Reading - wk16 2014</title>
   <link href="https://blog.pzheng.me//2014/04/20/this-week-reading-wk16-2014/"/>
   <updated>2014-04-20T11:02:53+00:00</updated>
   <id>https://blog.pzheng.me//2014/04/20/this-week-reading-wk16-2014</id>
   <content type="html">&lt;p&gt;It’s a sad news that &lt;a href=&quot;http://en.wikipedia.org/wiki/Gabriel_Garc%C3%ADa_M%C3%A1rquez&quot;&gt;Gabriel García Márquez&lt;/a&gt; passed away this week. Although many of us haven’t read of his most famous novel &lt;em&gt;One Hundred Years of Solitude&lt;/em&gt;, we should have heard about it once in a while.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;I read &lt;a href=&quot;http://book.douban.com/subject/1786670/&quot;&gt;One Hundred Years of Solitude&lt;/a&gt; on Kindle last year when I studied in the driving school to get the driver’s license. Our school was located in the near suburbs, and surrounded by a green hill full of graves and a waste incineration power plant which kept pumping white smoke through a large chimney. It was a cloudy day in late spring and early summer when I finished it. A few cars were crawling randomly in the vast training field before my bare eyes. But my twisted brain was still shocked and spinning in the world of crazy Macondo. Like I said on &lt;a href=&quot;https://twitter.com/Knoise&quot;&gt;twitter&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Though it’s a bit awkward, I always thought it was such a great honor to live with those great men/women, like Gabriel Márquez, &lt;a href=&quot;http://en.wikipedia.org/wiki/Claude_Shannon&quot;&gt;Claude Shannon&lt;/a&gt;, Steve Jobs and &lt;a href=&quot;http://en.wikipedia.org/wiki/Eileen_Chang&quot;&gt;Eileen Chang&lt;/a&gt; etc. on the same earth for a while.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Rest in peace, Gabo!&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I finished &lt;a href=&quot;http://www.amazon.com/More-Joel-Software-Occasionally-Developers-ebook/dp/B001VNCF30/&quot;&gt;More Joel on Software&lt;/a&gt; by &lt;a href=&quot;http://www.joelonsoftware.com/&quot;&gt;Joel Spolsky&lt;/a&gt; this week. Yeah I know it was published almost 6 years ago. But good knowledge is never out of date. Right?&lt;/p&gt;

&lt;p&gt;Joel is an experienced software engineer once worked in Microsoft for MS Excel and now in his own company &lt;a href=&quot;http://www.fogcreek.com/&quot;&gt;Fog Creek Software&lt;/a&gt;. Also he is an excellent writer with most articles were posted on his &lt;a href=&quot;http://www.joelonsoftware.com&quot;&gt;weblog&lt;/a&gt;. Indeed, there are lots of good programmers and good writers all over the world. But it’s not easy to find out the talents with both charecters. Moreover he co-founded the prevailing Q&amp;amp;A website &lt;a href=&quot;http://www.joelonsoftware.com/&quot;&gt;Stack Overflow&lt;/a&gt; which in my humble opinion is much better than &lt;a href=&quot;http://www.quora.com/&quot;&gt;Quora&lt;/a&gt; at computer-specific questions.&lt;/p&gt;

&lt;p&gt;A bunch of people over the internet doubted this book, as well as his website, was a way to promote and advertise &lt;em&gt;Fog Creek Software&lt;/em&gt; and their products. But I think there is nothing to againt earning money by your own words and speech. Especially those words are somehow useful for the readers.&lt;/p&gt;

&lt;p&gt;In my view, a good writer should firstly be an independent thinker without talking big to impress people. Actually I have the same feeling on certain subjects. Unfortunately, I didn’t go further to investigate deeply about the root cause and then get the final solvement. But Joel did. And he sorted it out by words in an interesting way. For instance, how to estimate effort for software development and testing, how to set task priorities, how to hire people, how to set price tag for software products, and so on.&lt;/p&gt;

&lt;p&gt;Though a few posts cover technical issues regarding programming. This book, in which most of the articles are about management in software company, mainly aims to managers instead of software engineers. However, I still suggest all software engineers to read it in your spare time.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Another article I’ve read in &lt;a href=&quot;http://getpocket.com/&quot;&gt;Pocket&lt;/a&gt; this week was &lt;a href=&quot;http://www.newyorker.com/reporting/2014/02/17/140217fa_fact_packer?currentPage=all&quot;&gt;Cheap Words&lt;/a&gt; from New Yorker , which analyzed the good and bad of &lt;a href=&quot;http://www.amazon.com&quot;&gt;Amazon&lt;/a&gt; from book industry perspective.&lt;/p&gt;

&lt;p&gt;After reading this article, I finally found out why those journalists always refered &lt;em&gt;Jeff Bezos&lt;/em&gt; as a Wall Street guy when they talked about &lt;em&gt;Amazon&lt;/em&gt;. He is rather a bussiness man than an artist like Steve Jobs or a geek like Bill Gates or Mark Zuckerberg. It’s also hilarious to read the part about “Amazon filed a complaint with the Federal Trade Commission” to accuse &lt;em&gt;Apple&lt;/em&gt; for manipulating ebook prices with big publishers. You should check it out by yourself. It is really worth your while to read.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Productivity Tools on PC (6)</title>
   <link href="https://blog.pzheng.me//2014/04/13/productivity-tools-on-pc-6/"/>
   <updated>2014-04-13T12:20:04+00:00</updated>
   <id>https://blog.pzheng.me//2014/04/13/productivity-tools-on-pc-6</id>
   <content type="html">&lt;p&gt;I have used &lt;a href=&quot;https://www.dropbox.com&quot;&gt;Dropbox&lt;/a&gt; for a few years and cannot live without it now. Dropbox is simple as it (and free on all platforms) and you could just use it directly after installation without any tweak. Here I will introduce how I use it and integrate it with other productivity tools.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Here is the overall structure of my Dropbox directory.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;├── ConfigFiles
├── DokuWikiStick
├── MobileOrg
├── org
├── Personal
├── Photos
├── Public
└── Workspace
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ConfigFiles&lt;/code&gt;: All dotfiles are stored here like AHK, Emacs as well as &lt;a href=&quot;http://blog.pzheng.me/2013/08/19/productivity-tools-on-pc-3/&quot;&gt;TotalCommander(wincmd.ini)&lt;/a&gt; configuration files, etc.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DokuWikiStick&lt;/code&gt;: The biggest motive for me to use Dropbox is trying to store DokuWikiStick on cloud. Thus I could simply sync all my wiki entries on windows PC in company, at home and even on my mobile phone and tablet. Since DokuWiki stores posts as text files without real database. So even Apache cannot be running on mobile phone or tablet, I could still check my personal wiki on mobile devices which is really amazing!&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MobileOrg&lt;/code&gt; &amp;amp; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;org&lt;/code&gt;: The latter is used to store all my org-mode files which will be introduced later in Emacs chapter. While the former is the folder for &lt;a href=&quot;http://orgmode.org/manual/MobileOrg.html&quot;&gt;Mobile Org&lt;/a&gt;. But due to the poor quality of Mobile Org apps on Android, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MobileOrg&lt;/code&gt; is not in use and almost dumped for now.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Personal&lt;/code&gt; &amp;amp; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Public&lt;/code&gt; &amp;amp; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Photos&lt;/code&gt;: As their names indicate, all my personal stuffs are stored here. By the way, it’s quite interesting to explore the collaborative features of Dropbox. For instance, my family share the same spreadsheet to manage our personal finance. Yes we are not using those fancy financial management apps on mobile devices. Because we want to customize various statistics by our own (yes control freak :-)) and secure the data in relatively safe mode.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Workspace&lt;/code&gt;: This folder is mainly used for work and my self-learning materials. I totally dropped my desktop as &lt;strong&gt;inbox&lt;/strong&gt; (aha, critical definition in GTD) but instead initiated a sub-folder in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Workspace&lt;/code&gt; (this sub-folder is fixed and defaultly opened in TotalCommander). With this folder, all my documentations could be synchronized between home and office. Thus I could continue to read the unfinished docs at home seamlessly without bringing the heavy laptop back and forth.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thanks to the speedy internet and wireless network, modern mobile devices, cloud tech, and all of those wonderful software and apps etc, our life becomes easier and more convenient. I am so glad to be one of participants as well as one of contributors as a wireless engineer.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>On Top of Tides</title>
   <link href="https://blog.pzheng.me//2014/04/06/on-top-of-tides/"/>
   <updated>2014-04-06T12:48:09+00:00</updated>
   <id>https://blog.pzheng.me//2014/04/06/on-top-of-tides</id>
   <content type="html">&lt;p&gt;Many guys on the internet highly recommended &lt;a href=&quot;http://www.amazon.com/Top-Tides-Chinese-wu-jun/dp/7121139510/ref=sr_1_1?s=books&amp;amp;ie=UTF8&amp;amp;qid=1396230827&amp;amp;sr=1-1&amp;amp;keywords=9787121139512&quot;&gt;On Top of Tides&lt;/a&gt;(浪潮之巅). But untill recently, I got the chance to read the first edition which was  published three years ago.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;http://img3.douban.com/lpic/s6584764.jpg&quot; alt=&quot;On top of tides&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In this book, the author &lt;a href=&quot;https://sites.google.com/site/junwu02/home&quot;&gt;Wu Jun&lt;/a&gt; who is the research scientist in Google, introduced the ups and downs of several world-wide known enterprises, most of which are IT companies in US, e.g. AT&amp;amp;T, IBM, Apple, Cisco, Motorola, Microsoft, Yahoo and Google, etc. Those firms are so famous that many of us may, more or less, have been aware of their history and current status. Even you are not so familiar with them, you could find the introduction on &lt;a href=&quot;http://www.wikipedia.org&quot;&gt;Wikipedia&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But it’s not only a collection of wiki entries for those famous companies. Due to author’s rich working experience in AT&amp;amp;T and Google as well as Silicon Vally, he also provided his personal thoughts on how those companies operated and why they failed or successed. For example, he blamed the greedy board of directors and Wall Street banks to divide AT&amp;amp;T into three firms in 90s last century, one of which was Lucent as telecom vendor (later acquisited and merged as &lt;a href=&quot;http://www.alcatel-lucent.com/&quot;&gt;Alcatel-Lucent&lt;/a&gt;). And for several times, he looked down upon Nokia and Samsung who were better at mobile phone appearance than Motorola. At the same time, he felt sad for Motorola’s falling as a former technical giant. Since this book was published in 2011. Motorola hasn’t been sold to Google and later Lenovo while Nokia device department hasn’t be acquisited by Microsoft either at that time. I am looking forward to what the author thinks on these latest news.&lt;/p&gt;

&lt;h2 id=&quot;two-interesting-laws&quot;&gt;Two interesting laws&lt;/h2&gt;

&lt;p&gt;There are two interesting laws in this book, one is &lt;a href=&quot;http://norvig.com/norvigs-law.html&quot;&gt;Norvig’s Law&lt;/a&gt; by &lt;a href=&quot;http://en.wikipedia.org/wiki/Peter_Norvig&quot;&gt;Peter Norvig&lt;/a&gt;, the other is the opposite of &lt;a href=&quot;http://en.wikipedia.org/wiki/Moore's_law&quot;&gt;Moore’s Law&lt;/a&gt; .&lt;/p&gt;

&lt;h3 id=&quot;norvigs-law&quot;&gt;Norvig’s Law&lt;/h3&gt;

&lt;p&gt;This law declares that any technology that surpasses 50% penetration will never double again (in any number of months). This is easy and straightforward. It means when a company gets over 50% of market share in certain area, it needs to discover a new field to get high penetration.&lt;/p&gt;

&lt;h3 id=&quot;the-opposite-of-moores-law&quot;&gt;The opposite of Moore’s Law&lt;/h3&gt;

&lt;p&gt;Actually I cannot find any formal source for this one. Generally the opposite of Moore’s Law, which is self-explaining, means “all technology gets half the size, or half the price, or twice the speed every 18 months”. If the technology is not evolved, the money you will earn half and a year later would be only half of what you are earning now. It also keeps pushing the technolog to evolve as fast as possible. You see, even you double the evolvement of technology every 18 months, you just maintain the price and earning without any more.&lt;/p&gt;

&lt;h2 id=&quot;my-thoughts&quot;&gt;My thoughts&lt;/h2&gt;

&lt;p&gt;Firstly, I think consumer market is the most competetive field which needs continuous innovations and ideas all the time. Sometimes, improvements are even not enough for multi-national enterprises.&lt;/p&gt;

&lt;p&gt;Secondly, how insignificant an engineer is in a big company. In AT&amp;amp;T, Motorola and Hewlett-Packard, there are best engineers of US or even over the world. But they still could not stop the falling of those giants, no matter how hard-working they were.&lt;/p&gt;

&lt;p&gt;Last, how can we survive as a telecom vendor? We are so far away from consumers market that current prevailing so-called “internet thinking mode” is not applicable. Though all the vendors and mobile phone manufacturers are following the same protocols like 3GPP etc. Each vendor is making its own hardware and software. What if we try to build a platform for hardware and basic software? Then all the other vendors could add features based on it. Thus they could focus on feature implementations other than all HW and SW stuff. Still, it’s better not try to earn money from HW according to the lessons learned from SUN in this book.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Power Drifting</title>
   <link href="https://blog.pzheng.me//2014/03/30/power-drifting/"/>
   <updated>2014-03-30T09:08:45+00:00</updated>
   <id>https://blog.pzheng.me//2014/03/30/power-drifting</id>
   <content type="html">&lt;p&gt;Closed loop power control (CLPC), a.k.a. fast power control, is an important feature in UMTS to adjust both uplink and downlink power level between Node B and UE via Transmit Power Control (TPC) commands. However the other side of CLPC is power drifting during soft handover (&lt;a href=&quot;http://blog.pzheng.me/2013/04/02/soft-and-softer-handover/&quot;&gt;1&lt;/a&gt; &amp;amp; &lt;a href=&quot;http://blog.pzheng.me/2013/05/12/soft-and-softer-handover-ii/&quot;&gt;2&lt;/a&gt;). In subclause 9.2.1.3 of &lt;em&gt;WCDMA for UMTS: HSPA Evolution and LTE (5th Edition)&lt;/em&gt;, the authors have presented the cause and possible solvement for this issue. So I don’t bother to repeat it again. Just some personal thoughts to help me deeply understand.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Please think about below questions before proceeding further. Let’s assume there are two cells in active set, which means two Node B are involved during soft handover.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;How many ul-DPCCH/DPDCH are there during SHO?&lt;/li&gt;
  &lt;li&gt;How many TPC commands on the uplink from UE to Node B?&lt;/li&gt;
  &lt;li&gt;Why does downlink tranmission power need to be consistent from two Node B?&lt;/li&gt;
  &lt;li&gt;What is the impact of power drifting?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;question-12&quot;&gt;Question #1&amp;amp;#2&lt;/h2&gt;

&lt;p&gt;Actually Q#1 and Q#2 are the same. UE needs to add anothe radio link (RL) to another cell (Node B) for SHO. Scrambling code is used on UL to distinguish UEs, which means two Node B will receive one copy of UL data from UE during SHO. Therefore, there is only one pair of ul-DPCCH/DPDCH as well as only one UL TPC commands.&lt;/p&gt;

&lt;p&gt;If you still cannot understand, please think about how it could be possible to allocate uplink I/Q code tree if one more ul-DPCCH/DPDCH is added for 2ms TTI E-DCH user with 2SF2+2SF4 of E-DPDCH set.&lt;/p&gt;

&lt;h2 id=&quot;question-3&quot;&gt;Question #3&lt;/h2&gt;

&lt;p&gt;Please note, here I use “consistent” instead of “equal”. Because CPICH power might be different in two involved cells (Node B). To be more specific, we need to equalize the &lt;strong&gt;power windows&lt;/strong&gt; of these two cells.&lt;/p&gt;

&lt;p&gt;Why do we need to keep them consistent? UE will softly combine the downlink signals from two different cells. Thus in order to stabilize power control, the combined signal power is expected to be the same when UE moves from one cell to anther without considering other factors like interference except the distance. While the respective received power could reflect the distance between UE and Node B to some extend.&lt;/p&gt;

&lt;h2 id=&quot;question-4&quot;&gt;Question #4&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;If the real TPC command is &lt;strong&gt;UP&lt;/strong&gt;, and any one of the Node B mis-decodes it as &lt;strong&gt;DOWN&lt;/strong&gt;. It will result in smaller Eb/N0 than expected on UE side, which would lower the gain of soft combining.&lt;/li&gt;
  &lt;li&gt;If the real TPC command is &lt;strong&gt;DOWN&lt;/strong&gt;, and any one of the Node B mis-decodes it as &lt;strong&gt;UP&lt;/strong&gt;. Though it will not impact UE receiving. It is a waste of power and impacts the power level of other UEs, i.e. impacts the capacity of whole cell.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;To summarize, it’s definitely necessary to prevent power drifting. Especially the frequency of CLPC is as quick as 1500 per second while there is only one bit for TPC command. Moreover, SHO usually happens on the edge of cells, which means the channel condition is not good enough. It’s very likely that Node B would misinterpret TPC commands during SHO.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Conky Issue on Archlinux</title>
   <link href="https://blog.pzheng.me//2014/03/21/conky-issue-on-archlinux/"/>
   <updated>2014-03-21T23:09:30+00:00</updated>
   <id>https://blog.pzheng.me//2014/03/21/conky-issue-on-archlinux</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://conky.sourceforge.net/index.html&quot;&gt;Conky&lt;/a&gt; is a light-weight and handy system monitor for X on Linux. However, wheneven I click other area on the destkop, it would disappear immediately. Here is how I sovle it after googling around.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Openbox, LXDE and PCManFM are used on my Archlinux. Later I found out the disappearing was caused by PCManFM which was also used for desktop management besides file manager. Please enter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;# killall pcmanfm&lt;/code&gt; and if there is no Conky disappearing afterwards, you could try my following method to replace PCManFM with Feh to manage wallpaper.&lt;/p&gt;

&lt;p&gt;Please notice the autostart file might be different on different Linux distro.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Disable pcmanfm from autostarting. Edit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/xdg/lxsession/LXDE/autostart&lt;/code&gt; to remove or comment out below line:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; @pcmanfm --desktop-off --profile LXDE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Install Feh from official repository:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; # pacman -S feh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Edit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/lxsession/LXDE/autostart&lt;/code&gt; to add:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; @feh --bg-fill /path/to/wallpaper.jpg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Attach my screenshot and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.conky&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140322_conky.png&quot; alt=&quot;conky&quot; /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;alignment top_right

own_window yes
own_window_transparent yes
own_window_type destop
own_window_hints undecorated,below,sticky,skip_taskbar,skip_pager

double_buffer yes
background yes
text_buffer_size 512
#maximum_width 

border_width 1
cpu_avg_samples 10
default_color white
#default_outline_color white${scroll 16 $nodename - $sysname $kernel on $machine | }
default_shade_color white
draw_borders no
draw_graph_borders yes
draw_outline no
draw_shades no
use_xft yes
xftfont DejaVu Sans Mono:size=8
gap_x 5
gap_y 60
#minimum_size 5 5
net_avg_samples 2
no_buffers yes
out_to_console no
out_to_stderr no
extra_newline no
own_window yes
own_window_class Conky
own_window_type desktop
stippled_borders 0
update_interval 1.0
uppercase no
use_spacer none
show_graph_scale no
show_graph_range no

TEXT
${color grey}Archlinux $color ${alignr}${exec whoami}@$nodename
${color grey}$sysname $kernel on $machine 

Date &amp;amp; Time ${hr 2}
${color grey}${execpi 60 DJS=`date +%_d`; cal | sed s/&quot;\(^\|[^0-9]\)$DJS&quot;'\b'/'\1${color}'&quot;$DJS&quot;'${color grey}'/}
${color}${font : size=16}${offset 150}${voffset -65}${time %l:%M:%S}${color grey}${offset 1}${voffset -24}${font : size=8}${time %p}






Info ${hr 2}
${color grey}Uptime:$color $uptime
${color grey}Frequency (in GHz):$color $freq_g
${color grey}RAM Usage:$color $mem/$memmax - $memperc% ${membar 4}
${color grey}Swap Usage:$color $swap/$swapmax - $swapperc% ${swapbar 4}
${color grey}CPU Usage:$color $cpu% ${cpubar 4}
${color grey}CPU Temp: $color ${acpitemp} C
${color grey}Processes:$color $processes  ${color grey}Running:$color $running_processes
${color grey}Battery: ${color}${battery} ${battery_bar}

HDD ${hr 2}
${color grey}root $color${fs_used /}/${fs_size /} ${fs_used_perc /}% ${fs_bar 6 /}
${color grey}boot $color${fs_used /boot}/${fs_size /boot} ${fs_used_perc /boot}% ${fs_bar 6 /boot}
${color grey}home $color${fs_used /home}/${fs_size /home} ${fs_used_perc /home}% ${fs_bar 6 /home}

Network ${hr 2}
${color grey}SSID: $color${wireless_essid wlp3s0}
${color grey}Signal: $color${wireless_link_qual_perc wlp3s0}% ${alignr}${wireless_link_bar 8,60 wlp3s0}
${color grey}Address: ${color}${addr wlp3s0}
Up:$color ${upspeed wlp3s0} ${color grey} - Down:$color ${downspeed wlp3s0}

Processes ${hr 2}
${color grey}Name              PID   CPU%   MEM%
${color lightgrey} ${top name 1} ${top pid 1} ${top cpu 1} ${top mem 1}
${color lightgrey} ${top name 2} ${top pid 2} ${top cpu 2} ${top mem 2}
${color lightgrey} ${top name 3} ${top pid 3} ${top cpu 3} ${top mem 3}
${color lightgrey} ${top name 4} ${top pid 4} ${top cpu 4} ${top mem 4}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>OVSF Codes</title>
   <link href="https://blog.pzheng.me//2014/03/12/ovsf-codes/"/>
   <updated>2014-03-12T13:34:32+00:00</updated>
   <id>https://blog.pzheng.me//2014/03/12/ovsf-codes</id>
   <content type="html">&lt;p&gt;As we know, the channelization codes for physical channels in UMTS should be orthogonal. Otherwise the reciever would not be able to decode the data correctly.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;spreading-factor&quot;&gt;Spreading Factor&lt;/h2&gt;

&lt;p&gt;3GPP adopts &lt;a href=&quot;http://en.wikipedia.org/wiki/Hadamard_code&quot;&gt;Hamamard Codes&lt;/a&gt;, a.k.a. Walsh Codes, to generate channelisation codes as below figure(from &lt;a href=&quot;http://www.amazon.com/Harri-Holma-Antti-Toskala-Evolution/dp/B00AOTQMC2&quot;&gt;WCDMA for UMTS HSPA Evolution and LTE 5th Edition&lt;/a&gt;). In UMTS, we usally call them OVSF(&lt;strong&gt;O&lt;/strong&gt;rthogonal &lt;strong&gt;V&lt;/strong&gt;ariable &lt;strong&gt;S&lt;/strong&gt;preading &lt;strong&gt;F&lt;/strong&gt;actor) codes.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140312_channelizationcodes.png&quot; alt=&quot;channelizationcodes&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;orthogonal&quot;&gt;Orthogonal&lt;/h2&gt;

&lt;p&gt;It’s easy to understand why the codes with the same Spreading Factor(SF) are orthogonal.&lt;/p&gt;

&lt;p&gt;For instance, C&lt;sub&gt;4,3&lt;/sub&gt; and C&lt;sub&gt;4,4&lt;/sub&gt; are orthogonal since the product(bit by bit) is 0.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;C&lt;sub&gt;4,3&lt;/sub&gt;(1) * C&lt;sub&gt;4,4&lt;/sub&gt;(1) + C&lt;sub&gt;4,3&lt;/sub&gt;(2) * C&lt;sub&gt;4,4&lt;/sub&gt;(2) + C&lt;sub&gt;4,3&lt;/sub&gt;(3) * C&lt;sub&gt;4,4&lt;/sub&gt;(3) + C&lt;sub&gt;4,3&lt;/sub&gt;(4) * C&lt;sub&gt;4,4&lt;/sub&gt;(4) 
= 1 * 1 + (-1) * (-1) + 1 * (-1) + (-1) * 1 
= 0&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Assume there are two channels to transmit data. Let’s say signal on one channel is &lt;em&gt;x&lt;/em&gt; while signal on the other channel is &lt;em&gt;y&lt;/em&gt;. And &lt;em&gt;x&lt;/em&gt; is spread by channelization code C&lt;sub&gt;4,3&lt;/sub&gt; and &lt;em&gt;y&lt;/em&gt; is spread by code C&lt;sub&gt;4,4&lt;/sub&gt;. So the final data to receiver is:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;x&lt;em&gt;C&lt;sub&gt;4,3&lt;/sub&gt; +  y&lt;/em&gt;C&lt;sub&gt;4,4&lt;/sub&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Receiver should be aware of these two channelization codes in advance, from for example control channels etc. Thus it could respectively decode the original data by multipying received data by each channelization code. That is:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;(xC&lt;sub&gt;4,3&lt;/sub&gt; +  yC&lt;sub&gt;4,4&lt;/sub&gt;) * C&lt;sub&gt;4,3&lt;/sub&gt; = x&lt;em&gt;C&lt;sub&gt;4,3&lt;/sub&gt;&lt;/em&gt;C&lt;sub&gt;4,3&lt;/sub&gt; +  y&lt;em&gt;C&lt;sub&gt;4,4&lt;/sub&gt;&lt;/em&gt;C&lt;sub&gt;4,3&lt;/sub&gt; = x*C&lt;sub&gt;4,3&lt;/sub&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s why we say ideally there is no inter-channel intereference once they are spread by channelization codes.&lt;/p&gt;

&lt;h2 id=&quot;non-orthogonal&quot;&gt;Non-orthogonal&lt;/h2&gt;

&lt;p&gt;In &lt;em&gt;WCDMA for UMTS HSPA Evolution and LTE 5th Edition&lt;/em&gt;, it says below words without detailed explanation.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;There are certain restrictions as to which of the channelization codes can be used for a transmission from a single source. Another physical channel may use a certain code in the tree if no other physical channel to be transmitted using the same code tree is using a code that is on an underlying branch, i.e. using a higher spreading factor code generated from the intended spreading code to be used. Neither can a smaller spreading factor code on the path to the root of the tree be used.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Still, take C&lt;sub&gt;2,2&lt;/sub&gt; and C&lt;sub&gt;4,4&lt;/sub&gt; as example. But here is the problem, C&lt;sub&gt;4,4&lt;/sub&gt; is a four-dimensional vector meanwhile C&lt;sub&gt;2,2&lt;/sub&gt; is only two dimensional. How to linealy multiply these two vectors?&lt;/p&gt;

&lt;p&gt;One of my colleagues told me, in Linear Algebra, the missing bits would be filled with “0” in case two different dimensional vectors multiply. Thus the product of C&lt;sub&gt;2,2&lt;/sub&gt; and C&lt;sub&gt;4,4&lt;/sub&gt; should be “2” instead of “0”.&lt;/p&gt;

&lt;p&gt;It’s more clear to draw an illustrator when the signal is one bit as “1”. Because the chip duration T&lt;sub&gt;chip&lt;/sub&gt; is fixed as 1/3840000 second. The spreading data with C&lt;sub&gt;4,4&lt;/sub&gt; is longer than C&lt;sub&gt;2,2&lt;/sub&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140312_non_orthogonal_1.png&quot; alt=&quot;Non-orthogonal 1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If the input data is (1, -1) and spread by C&lt;sub&gt;2,2&lt;/sub&gt;. Then the output will be exactly the same as “1” spread by C&lt;sub&gt;4,4&lt;/sub&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140312_non_orthogonal_2.png&quot; alt=&quot;Non-orthogonal 2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;That’s why certain code and its children codes are not orthogonal. And it is impossible for receiver to decode the original channel data respectively.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>2SF2+2SF4 E-DPDCH without ul-DPDCH</title>
   <link href="https://blog.pzheng.me//2014/03/09/2sf2-plus-2sf4-e-dpdch-without-ul-dpdch/"/>
   <updated>2014-03-09T12:38:10+00:00</updated>
   <id>https://blog.pzheng.me//2014/03/09/2sf2-plus-2sf4-e-dpdch-without-ul-dpdch</id>
   <content type="html">&lt;p&gt;The reason why ul-DPDCH is not supported for E-DPDCH with 2SF2+2SF4, is presented in 3GPP &lt;a href=&quot;http://www.3gpp.org/DynaReport/25213.htm&quot;&gt;TS25.213&lt;/a&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;According to Table 0: Maximum number of simultaneously-configured uplink dedicated channels in TS25.213 as below, in case of 4 E-DPDCH channels, there should be no ul-DPDCH configured.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140309_3gpp_ts25213_table0.png&quot; alt=&quot;3gpp_ts25213_table0&quot; /&gt;&lt;/p&gt;

&lt;p&gt;More specifically, you could refer to &lt;a href=&quot;http://www.amazon.com/3G-Evolution-Second-Edition-Broadband/dp/0123745381&quot;&gt;3G Evolution: HSPA and LTE for Mobile Broadband&lt;/a&gt;. As you can see, when there are 2SF2+2SF4 E-DPDCH configured, there is no extra space for ul-DPDCH in terms of code tree.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20140309_edpdch_with_and_without_dch.jpg&quot; alt=&quot;edpdch_with_and_without_dch&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Thoughts On Asking Questions</title>
   <link href="https://blog.pzheng.me//2014/03/05/thoughts-on-asking-questions/"/>
   <updated>2014-03-05T20:10:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/03/05/thoughts-on-asking-questions</id>
   <content type="html">&lt;p&gt;As a software tester, I need to coorperate with many guys in my daily work, internally like software/simulator developers, architects etc. While externally, with application engineers(AE) for test equipments. Recently, I meet some problems with a certain test equipment and communicate with its AEs frequently. And here are some thoughts on an interesting thing happened during this period.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;The problem I met was a bit complex and it’s hard to decribe in only words. And at first, I was not sure whether my configuration and settings were correct or not. So I asked AE why some abnormal results were encountered during testing via Email(he works and lives in UK). Actually, I asked for the possible reasons because I was trying to debug it by myself.&lt;/p&gt;

&lt;p&gt;Later with several rounds of back and forth replying, both of us were agitated and tired by endless mails without actual progress. I blamed him for not looking into my queries carefully and he might think I am unreasonble and make trouble out of nowhere.&lt;/p&gt;

&lt;p&gt;At last when he visited China, we had a face to face discussion. And about half an hour later, we were both clear about the problem. Even now the problem is still under investigation, we are satisfied with current situation because finally we can understand what each other means.&lt;/p&gt;

&lt;p&gt;Well. It’s all my fault and shame on myself… When I looked back the whole procedure, I found I made several mistakes. Actually I have to answer many questions from colleagues and help them to solve problems during work. I noticed a few guys were terrible at asking questions(some of the answers could be simply found on &lt;a href=&quot;www.google.com&quot;&gt;Google&lt;/a&gt;). However I made almost all of those stupid mistakes this time…&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Didn’t state my questions and needs as clear as possible at very beginning&lt;/strong&gt; And the statement should be concise but not simple. At first I thought I was familiar with this AE because we have worked together many times. He should know what I meant. Wrong! Totally wrong!!! Never assume others could understand you without enough information. I should have decribe the testing background, exact testing procedure, testing purpose, expected results and the actual results, etc. On the opposite, I just briefly introduced my problem and directly asked for reasons why it happened.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Didn’t stop those non-sense emails on time.&lt;/strong&gt; As I mentioned, the problem could hardly be described in words. I should have initiated a tele-conference instead of endless and useless emails. Then I could show him my test environment and results directly.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Show respect.&lt;/strong&gt; Though I took care of my writings, I might have used some heavy words and might be slightly offensive which I feel terribly sorry. We had good cooperations previously. After all it’s me to request help from him.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Anyway it’s a good experience and makes me think about how I behave as a question-asker. Hope it won’t harm our furture cooperation :-) Maybe I need to read &lt;a href=&quot;http://www.amazon.com/The-Art-Asking-Questions-Payne/dp/0691093040&quot;&gt;The Art of Asking Questions&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Build home backup system</title>
   <link href="https://blog.pzheng.me//2014/02/24/build-home-backup-system/"/>
   <updated>2014-02-24T20:28:00+00:00</updated>
   <id>https://blog.pzheng.me//2014/02/24/build-home-backup-system</id>
   <content type="html">&lt;p&gt;I never seriously consider photoes as precious wealth till one day I drowned into my album collections. Those silly and embarrassed moments instantly became vivid. In order to backup and organize all my family’s pictures at one place, I decide to build up a system on my out-of-date netbook since I don’t want to spare money on an expensive NAS machine.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;backup-folders-from-androidios-automatically&quot;&gt;Backup folders from Android/iOS automatically&lt;/h2&gt;

&lt;p&gt;First of all, I need sync the pictures from all of my family phones and tablet. &lt;a href=&quot;http://www.bittorrent.com/sync&quot;&gt;BitTorrent Sync&lt;/a&gt; is good choice because it covers almost all platforms, Windows/Linux/Android/iOS, etc. And it’s FREE.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Follow &lt;a href=&quot;https://wiki.archlinux.org/index.php/BitTorrent_Sync&quot;&gt;this wiki entry&lt;/a&gt;, I can easily set up BT Sync on my netbook running Archlinux. And run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemctl status btsync@user&lt;/code&gt; to check the status;&lt;/li&gt;
  &lt;li&gt;Install &lt;em&gt;BT Sync&lt;/em&gt; on all phones and iPad;&lt;/li&gt;
  &lt;li&gt;Choose camera folders and set them as backup folders;&lt;/li&gt;
  &lt;li&gt;Add backup folders on PC with secret codes;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now all the pictures will be uploaded to the specific folders on PC and new photoes will be synchronized later as well. And If &lt;em&gt;BT Sync&lt;/em&gt; drains the phones’ battery, you could try to enable “Auto Sleep”.&lt;/p&gt;

&lt;p&gt;The only constraint is, I have to keep &lt;em&gt;BT Sync&lt;/em&gt; opening on iPad during synchronization. But I can bear it since I seldom take pictures on iPad.&lt;/p&gt;

&lt;h2 id=&quot;set-sharing-folders-on-archlinux&quot;&gt;Set sharing folders on Archlinux&lt;/h2&gt;

&lt;p&gt;NFS (&lt;a href=&quot;https://wiki.archlinux.org/index.php/Nfs&quot;&gt;Network File System&lt;/a&gt;) is the my first choice to share folders on Archlinux because it’s UNIX/Linux oriented and highly efficient. However I dropped it later due to the lack of decent client apps on Android/iOS.&lt;/p&gt;

&lt;p&gt;Samba, as an alternative, was set up instead. Always following &lt;a href=&quot;https://wiki.archlinux.org/index.php/SMB&quot;&gt;the official wiki&lt;/a&gt; will make you waste less time on configuration or debugging.&lt;/p&gt;

&lt;h2 id=&quot;view-pictures-on-androidiostv-box&quot;&gt;View Pictures on Android/iOS/TV box&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.estrongs.android.pop&amp;amp;hl=en&quot;&gt;ES File Explorer&lt;/a&gt; on Andorid and &lt;a href=&quot;https://itunes.apple.com/us/app/fileexplorer-free/id510282524?mt=8&quot;&gt;FileExplorer&lt;/a&gt; on iPad are able to mount SMB folders as well as browse remote pictures freely.&lt;/p&gt;

&lt;p&gt;On TV box, &lt;a href=&quot;http://xbmc.org/&quot;&gt;XBMC&lt;/a&gt; is always the best choice. It could even support NFS!&lt;/p&gt;

&lt;h2 id=&quot;existed-problem&quot;&gt;Existed problem&lt;/h2&gt;

&lt;p&gt;The only problem I meet now is the speed. The wireless ethernet card on netbook is only 150Mbps while my TP Link router at home is also 150Mbps. I can approximately get 6Mbps transmission from another Windows PC in the same LAN. But only 2Mbps data rate could be reached on an android phone. SMB client might be the bottleneck I guess.&lt;/p&gt;

&lt;p&gt;I’d like to put it aside. Because I only use it to browse family photographs. Fine is just enouge. Don’t let the pefectionism ruin your life!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Productivity Tools on PC (5)</title>
   <link href="https://blog.pzheng.me//2013/11/18/productivity-tools-on-pc-5/"/>
   <updated>2013-11-18T22:11:00+00:00</updated>
   <id>https://blog.pzheng.me//2013/11/18/productivity-tools-on-pc-5</id>
   <content type="html">&lt;p&gt;Outlook is the only choice in my company to handle with E-mails. Normally, I would receive 40~50 mails everyday and reply around 20 out of them. How to deal with so many mails was a big problem to me until I found &lt;a href=&quot;http://blogs.msdn.com/b/ianpal/archive/2008/06/03/email-task-and-time-management-with-pifem.aspx&quot;&gt;PIFEM(Pay It Forward Email Management)&lt;/a&gt; created by &lt;a href=&quot;http://blogs.msdn.com/ianpal&quot;&gt;Ian Palangio&lt;/a&gt;. I immediately fell in love with this method and tweaked it according to my situation. After two years using, I am so pleased to introduce it here.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;environment&quot;&gt;Environment&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Windows 7 Professinal 64-bit&lt;/li&gt;
  &lt;li&gt;Outlook 2007&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;pre-rules&quot;&gt;Pre-rules&lt;/h2&gt;

&lt;h3 id=&quot;rule-1-cancel-alerts&quot;&gt;Rule #1: Cancel Alerts&lt;/h3&gt;

&lt;p&gt;Before you do anything, please firstly cancel Outlook alerts. Yes alerts will keep you following the updates in time. But most of the time it distracts me quite a bit. I’d check the outlook randomly after cancelling the alerts. Fortunately I haven’t missed any urgent e-mails.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20131118_cancelalerts.jpg&quot; alt=&quot;Cancel alerts&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;rule-2-regular-pst&quot;&gt;Rule #2: Regular PST&lt;/h3&gt;

&lt;p&gt;I would archive my PST file regularly, which means to create new PST file per six months. Since there might be unexpected problems when PST file is larger than 2Gb. And the naming rule is listed as below:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20131118_PSThalfyear.jpg&quot; alt=&quot;PST half year&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;rule-3-organized-folders&quot;&gt;Rule #3: Organized Folders&lt;/h3&gt;

&lt;p&gt;And in each PST, there are several organized folders based on different priorities. I would press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v&lt;/code&gt; to move some useful items to corresponding folder via &lt;a href=&quot;&quot;&gt;AHK&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20131118_organizedfolder.jpg&quot; alt=&quot;Organized folder&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I will adjust the order and folder structure based on my needs at that time when initiate a new PST data file.&lt;/p&gt;

&lt;h3 id=&quot;rule-4-apply-rules&quot;&gt;Rule #4: Apply rules&lt;/h3&gt;

&lt;p&gt;There would be certain mails sent by Robots. And it’s unnecessary to check them one by one. You just need to archive them to specific folders. And you could check it when you need them.&lt;/p&gt;

&lt;p&gt;Another most important thing is, don’t forget to “mark them as read” when applying such rules. I hate those unread numbers!&lt;/p&gt;

&lt;h2 id=&quot;pifem&quot;&gt;PIFEM&lt;/h2&gt;

&lt;p&gt;In GTD, the No. 1 rule is to keep inbox clean. However, with PIFEM, this inbox is not the one displayed in each PST. We are gonna set up a new “inbox” from nowhere.&lt;/p&gt;

&lt;p&gt;Actually the essential of PIFEM is to use “Search Folders”/”Follow up”/”Category” flexibly. Here is my list of favorite folders.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20131118_favoritefolders.jpg&quot; alt=&quot;Favorite folder&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;set-up-search-folders&quot;&gt;Set up Search Folders&lt;/h3&gt;

&lt;p&gt;You could follow below steps to set up new Search Folders.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20131118_searchfolders.jpg&quot; alt=&quot;Search folder&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;inbox-to-be-vetted&quot;&gt;Inbox (To Be Vetted)&lt;/h4&gt;

&lt;p&gt;Here is the virtual “inbox” you have to cope with every now and then.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20131118_vettedinbox.jpg&quot; alt=&quot;Vetted inbox&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;follow-up-today&quot;&gt;Follow up (Today)&lt;/h4&gt;

&lt;p&gt;All the mails you need to read/reply/finish will be found in this very folder. You just need to focus on this folder everyday and try your best to finish all of them by the end of day. That’s it.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20131118_followuptoday.jpg&quot; alt=&quot;followup today&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;follow-up-later&quot;&gt;Follow up (Later)&lt;/h4&gt;

&lt;p&gt;All the mails you need to deal with on tomorrow or even later.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20131118_followuplater.jpg&quot; alt=&quot;followup later&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;follow-up-maybe&quot;&gt;Follow up (Maybe)&lt;/h4&gt;

&lt;p&gt;All the mails you might read but with low priorities.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20131118_followupmaybe.jpg&quot; alt=&quot;followup maybe&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;tasks---delegate&quot;&gt;Tasks - Delegate&lt;/h4&gt;

&lt;p&gt;You might want to check those mails you sent out. For example, assign some tasks to somebody else. Or ask help from others. But you would forget if they miss that mail.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20131118_delegatetask.jpg&quot; alt=&quot;delegate task&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;inbox-completed-today&quot;&gt;Inbox (Completed Today)&lt;/h4&gt;

&lt;p&gt;This is just a folder to display those mails you have finished today.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20131118_completedtoday.jpg&quot; alt=&quot;completed today&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;add-search-folders-to-favorite-folders&quot;&gt;Add Search Folders to Favorite Folders&lt;/h4&gt;

&lt;p&gt;Finally you just need to add those new search folders to “Favorite Folders”.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20131118_addfavoritefolders.jpg&quot; alt=&quot;addfavorite folders&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;workflow&quot;&gt;Workflow&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;When you get a new mail, you just need to choose next action from below accordingly:
    &lt;ul&gt;
      &lt;li&gt;delete it;&lt;/li&gt;
      &lt;li&gt;or move it to proper folders for future reference;&lt;/li&gt;
      &lt;li&gt;or flag it as “Today”;&lt;/li&gt;
      &lt;li&gt;or flag it as “Tomorrow” or someday in the future;&lt;/li&gt;
      &lt;li&gt;or flag it as “No date”;&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20131118_newmail.jpg&quot; alt=&quot;newmail&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;Just remember to proceed mails appropriately and keep “Inbox (To Be Vetted)” empty.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Focus on “Follow up (Today)” everyday and work. When you finish that mail (mostly end by replying it), you just need to click flag again and mark it as “Completed”. It will disappear from this folder.&lt;/p&gt;

    &lt;p&gt;The mails in “Follow up (Later)” will be showed in this folder on start date.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;After you reply one mail and you feel like it’s better to follow up it. You could assign the task into “Tasks - Delegate” category and proper follow-up date.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Actually all the mails are still in the real inbox. And it’s kind of messy at first glance. So it’s better to sort your real inbox weekly and only keep those unfinished items.&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20131118_realinbox.jpg&quot; alt=&quot;real inbox&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;That’s all. I promise you are gonna love PIFEM once you try it. It definitely makes my life much easier.&lt;/p&gt;

&lt;p&gt;Later, I will write a new post to introduce how I integrate Outlook (PIFEM) with Emacs Org-mode.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Productivity Tools on PC (4)</title>
   <link href="https://blog.pzheng.me//2013/11/10/productivity-tools-on-pc-4/"/>
   <updated>2013-11-10T23:17:00+00:00</updated>
   <id>https://blog.pzheng.me//2013/11/10/productivity-tools-on-pc-4</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://www.dokuwiki.org/dokuwiki&quot;&gt;DokuWiki&lt;/a&gt;, more specific, &lt;a href=&quot;https://www.dokuwiki.org/install:dokuwiki_on_a_stick&quot;&gt;DokuWikiStick&lt;/a&gt; is the final choice of me for wiki software.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;why-i-need-a-wiki&quot;&gt;Why I need a wiki?&lt;/h2&gt;

&lt;p&gt;To avoid &lt;a href=&quot;http://en.wikipedia.org/wiki/Infobesity&quot;&gt;infobesity&lt;/a&gt; and manage personal knowledgement.&lt;/p&gt;

&lt;h2 id=&quot;why-i-chose-dokuwiki&quot;&gt;Why I chose DokuWiki?&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Opensource and &lt;a href=&quot;http://en.wikipedia.org/wiki/GNU_General_Public_License&quot;&gt;free&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;Simple, clean, easy to maintain and backup;&lt;/li&gt;
  &lt;li&gt;Works on plain text file. No need for database;&lt;/li&gt;
  &lt;li&gt;Continuous &lt;a href=&quot;http://download.dokuwiki.org/&quot;&gt;release/update&lt;/a&gt; and active &lt;a href=&quot;https://forum.dokuwiki.org/&quot;&gt;community&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;Lots of available &lt;a href=&quot;https://www.dokuwiki.org/plugins&quot;&gt;plugins&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;Normal wiki functionalities like version control, search etc;&lt;/li&gt;
  &lt;li&gt;Cross different platforms (Windows/Linux).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;why-dokuwikistick&quot;&gt;Why DokuWikiStick?&lt;/h2&gt;

&lt;p&gt;Easy to integrate with Dropbox. I could view my personal wiki pages on any computers. Because it is running on plain text files, I could even read it on my phone.&lt;/p&gt;

&lt;h2 id=&quot;plugins-in-use&quot;&gt;Plugins in use&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.dokuwiki.org/plugin:fontcolor&quot;&gt;fontcolor&lt;/a&gt; for different font colors;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.dokuwiki.org/plugin:markdownextra&quot;&gt;markdownextra&lt;/a&gt; for markdown syntax;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.dokuwiki.org/plugin:mathjax&quot;&gt;mathjax&lt;/a&gt; for math formula.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After installing &lt;a href=&quot;https://www.dokuwiki.org/template:vector&quot;&gt;vector&lt;/a&gt; template, it really looks like &lt;a href=&quot;http://en.wikipedia.org/&quot;&gt;Wikipedia&lt;/a&gt;/&lt;a href=&quot;http://www.mediawiki.org/wiki/MediaWiki&quot;&gt;MediaWiki&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;how-i-use-it&quot;&gt;How I use it?&lt;/h2&gt;

&lt;p&gt;I install it in my Dropbox folder and sync it between Windows 7 laptop in my office and Archlinux netbook at home (my cell phone is able to access to it as well). Localhost running gets rid of the access control problem and security issues.&lt;/p&gt;

&lt;p&gt;Overall structure of my personal wiki lists as below:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Work
    &lt;ul&gt;
      &lt;li&gt;Company 1 [tips and summary during working]&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Learning
    &lt;ul&gt;
      &lt;li&gt;English&lt;/li&gt;
      &lt;li&gt;Wireless&lt;/li&gt;
      &lt;li&gt;Computer&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Life
    &lt;ul&gt;
      &lt;li&gt;GTD [weekly and monthly retrospective]&lt;/li&gt;
      &lt;li&gt;Account [not in use anymore]&lt;/li&gt;
      &lt;li&gt;Websites [not in use anymore]&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Reading [reading notes]
    &lt;ul&gt;
      &lt;li&gt;Chinese&lt;/li&gt;
      &lt;li&gt;English&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;cons&quot;&gt;Cons&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Not support Markdown syntax natively. Though there is markdown plugin, it’s not convinient;&lt;/li&gt;
  &lt;li&gt;No rich editor to WYSIWYG. Actually it’s not a disadvantage for me;&lt;/li&gt;
  &lt;li&gt;Apache is a must to running it. But it’s inevitable. Isn’t it?&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Productivity Tools on PC (3)</title>
   <link href="https://blog.pzheng.me//2013/08/19/productivity-tools-on-pc-3/"/>
   <updated>2013-08-19T06:13:00+00:00</updated>
   <id>https://blog.pzheng.me//2013/08/19/productivity-tools-on-pc-3</id>
   <content type="html">&lt;p&gt;I found &lt;a href=&quot;http://www.ghisler.com/&quot;&gt;&lt;em&gt;Total Commander&lt;/em&gt;&lt;/a&gt; was used by almost everyone in our company when I got on board. Because we have to work among several different scripts with different directories in our daily work. I fell in love with &lt;em&gt;Total Commander&lt;/em&gt; soon after I tried it. And thanks to my firm, I can use an authorized one.&lt;/p&gt;

&lt;p&gt;All the configurations are stored in a file names as “wincmd.ini” under directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Application Data&lt;/code&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;a href=&quot;http://www.ghisler.com/download.htm&quot;&gt;++Download++&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;f2-to-rename&quot;&gt;F2 to rename&lt;/h1&gt;

&lt;p&gt;There has already been lots of defaul shortcusts in &lt;em&gt;Total Commander&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Some work in &lt;em&gt;Firefox&lt;/em&gt; way, e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl + T&lt;/code&gt; to open new tab, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl + W&lt;/code&gt; to close current tab, etc.&lt;/li&gt;
  &lt;li&gt;Some are quite convenient, e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F5&lt;/code&gt; to copy, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F6&lt;/code&gt; to move, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F7&lt;/code&gt; to create new folder, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But I still cannot get used to a few of them.&lt;/p&gt;

&lt;p&gt;For example, by default, we cannot press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F2&lt;/code&gt; to rename file or folder. You just need to add below lines in “wincmd.ini”.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Shortcuts]
F2=cm_RenameOnly
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;enable-right-button-of-mouse&quot;&gt;Enable right button of mouse&lt;/h1&gt;

&lt;p&gt;You might be pissed of by some of the default configurations of &lt;em&gt;Total Commander&lt;/em&gt;. For instance, right button of mouse is disable by default. You cannot use it to select file/check properties like the way in &lt;em&gt;Windows Explorer&lt;/em&gt;, etc. I don’t know the intension of author for disabling right button (maybe he wishes all operations should be executed by keyboard shortcuts :-)). But sometimes I really need it, especially when I want to compare some files via &lt;em&gt;Beyond Compare&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So just copy this line in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[Configuration]&lt;/code&gt; part of “wincmd.ini”.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;UseRightButton=0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;drives-list&quot;&gt;Drives list&lt;/h1&gt;

&lt;p&gt;Drives are listed as drop-down list by default which is not convenient when I try to select different hard drives. Instead, I like all of them being displayed in the upper part of &lt;em&gt;Total Commander&lt;/em&gt;. Then I could choose any drive with only one click.&lt;/p&gt;

&lt;p&gt;Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[Layout]&lt;/code&gt; in “wincmd.ini” as followings:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[layout]
DriveBar1=1
DriveBar2=1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You will see the change as below picture:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20130819_totalcmd_driverlist.png&quot; alt=&quot;TotalCMD driverlist&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;using-specific-configuration-file&quot;&gt;Using Specific Configuration File&lt;/h1&gt;

&lt;p&gt;As mentioned, all the settings are stored in “wincmd.ini” file. So you could over-write this file in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Application Data&lt;/code&gt; by your own configuration file.&lt;/p&gt;

&lt;p&gt;Just in case you want to keep the default file still, you could open &lt;em&gt;Total Commander&lt;/em&gt; in &lt;em&gt;Command&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; C:\Program Files\TOTALCMD.EXE i=&quot;d:\Dropbox\wincmd.ini&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then you could store your &lt;em&gt;Total Commander&lt;/em&gt; configuration file in &lt;em&gt;Dropbox&lt;/em&gt; and bring it anywhere.&lt;/p&gt;

&lt;p&gt;But you may be tired of open &lt;em&gt;Command&lt;/em&gt; and type so many letters. You could turn to &lt;em&gt;AutoHotKey&lt;/em&gt; for quick opening.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;^!q::
Run, &quot;C:\Program Files\TOTALCMD.EXE&quot; &quot;/i=&quot;d:\Dropbox\wincmd.ini&quot;&quot;
return
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl + Alt + q&lt;/code&gt;. And you could launch &lt;em&gt;Total Commander&lt;/em&gt; with your own “wincmd.ini” like a charm.&lt;/p&gt;

&lt;p&gt;See, this is the second time I integrated my tools together: &lt;em&gt;Total Commander&lt;/em&gt;, &lt;em&gt;Dropbox&lt;/em&gt; and &lt;em&gt;AutoHotKey&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&quot;others-configurations&quot;&gt;Others Configurations&lt;/h1&gt;

&lt;p&gt;You might want to change the colore for selected files from red to others. Or some other configurations.&lt;/p&gt;

&lt;p&gt;Please refer to my configuration file as below for details.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Configuration]
StartupScreen=0
firstmnu=1591
PanelsVertical=0
test=33
SoundDelay=-10
FirstTimeUnpack=0
ShowCentury=1
Aligned extension=0
SizeStyle=1
SizeFooter=1
DirTabOptions=824
DirTabLimit=32
onlyonce=1
TrayIcon=0
UseRightButton=0
Savepath=1
Savepanels=1
MarkDirectories=1
AltSearch=2
SaveCommands=1
CountSpace=1
CountMarked=1
1hourdif=0
CopyComments=6
ShowHiddenSystem=0
UseLongNames=1
Small83Names=0
OldStyleTree=0
autotreechange=0
ShowParentDirInRoot=0
IconOverlays=0
Showicons=2
ShowEXEandLNKicons=2
SortDirsByName=0
Tips=3
IconsOnNet=1
FileTipWindows=1
Win32TipWindows=0
ThumbsLocation=%$LOCAL_APPDATA%\GHISLER
ThumbsCopyDel=1
ThumbsCustomFieldsEnabled=1
ThumbOptions=15
ThumbExplTypes=*.* | *.htm *.html
ThumbPlgTypes=*.*
ThumbIrfXnTypes=*.*
ThumbTxtTypes=*.txt *.ini
FirstTimeZIP=0
ExplorerForCopy=0
Win95Delete=0
UseTrash=1
InstallDir=D:\Software\Utilities\totalcmd
AlwaysToRoot=0
SingleClickStart=0
RenameSelOnlyName=0
SaveHistory=1
SeparateTree=0
DirBrackets=1
SortUpper=0
QuickSearchAutoFilter=1
[left]
path=D:\
ShowAllDetails=1
SpecialView=0
show=1
sortorder=0
negative Sortorder=0
[right]
path=D:\
ShowAllDetails=1
SpecialView=0
show=1
sortorder=0
negative Sortorder=1
[Command line history]
[1280x800 (8x16)]
TreeDlgX=434
TreeDlgY=201
TreeDlgDX=411
TreeDlgDY=397
TreeDlgMax=0
Tabstops=278,281,339,-1,736,93
MenuChangeX=160
MenuChangeY=120
MenuChangeDX=960
MenuChangeDY=560
MenuChangeMax=1
ConnectX=397
ConnectY=215
ConnectDX=485
ConnectDY=370
ConnectMax=0
[Confirmation]
deleteDirs=1
OverwriteFiles=1
OverwriteReadonly=1
OverwriteHidSys=1
MouseActions=1
[Shortcuts]
F2=cm_RenameOnly
C+A+e=em_everything
[Layout]
ButtonBar=1
DriveBar1=1
DriveBar2=1
DriveBarFlat=1
InterfaceFlat=1
DriveCombo=1
DirectoryTabs=1
CurDir=1
TabHeader=1
StatusBar=1
CmdLine=1
KeyButtons=1
HistoryHotlistButtons=1
XPthemeBg=1
BreadCrumbBar=1
[Lister]
Startup=17
textwidth=81
binwidth=75
SearchGoBack=3
BmpStartup=1
Multimedia=1
RTF=1
IView=0
IViewPath=i_view32.exe
HTMLasText=1
LinkBraces=1
[Colors]
InverseCursor=0
InverseSelection=1
BackColor=-1
ForeColor=-1
MarkColor=8388608
CursorColor=255
CursorText=-1
[Packer]
InternalZip=1
InternalUnzip=1
zipnt=0
ZIP=pkzip.exe
UnZIP=pkunzip.exe
InternalZipRate=6
Zip83Name=0
ZipSetDateToNewest=0
nodelete=0
OpenPartial=0
ZIPlikeDirectory=1
InternalUnarj=1
ARJlongnames=0
InternalUnlzh=1
InternalUnrar=1
InternalUnace=1
LinuxCompatible=1
ARJ=arj.exe
LHA=lha.exe
RAR=rar.exe
UC2=uc.exe
ACE=ace32.exe
[Tabstops]
0=278
1=281
3=339
4=-1
6=736
5=93
AdjustWidth=1
[MkDirHistory]
[1440x900 (8x16)]
CmdSelX=394
CmdSelY=220
CmdSelDX=637
CmdSelDY=371
CmdSelMax=0
ConnectX=477
ConnectY=265
ConnectDX=485
ConnectDY=370
ConnectMax=0
[1440x900 (10x20)]
ConnectX=472
ConnectY=263
ConnectDX=485
ConnectDY=451
ConnectMax=0
MenuChangeX=150
MenuChangeY=150
MenuChangeDX=864
MenuChangeDY=496
MenuChangeMax=0
[1280x800 (10x20)]
MenuChangeX=145
MenuChangeY=25
MenuChangeDX=768
MenuChangeDY=436
MenuChangeMax=0
[DirMenu]
[lefttabs]
[righttabs]
[RightHistory]
[LeftHistory]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</content>
 </entry>
 
 <entry>
   <title>Productivity Tools on PC (2)</title>
   <link href="https://blog.pzheng.me//2013/08/08/productivity-tools-on-pc-2/"/>
   <updated>2013-08-08T05:59:00+00:00</updated>
   <id>https://blog.pzheng.me//2013/08/08/productivity-tools-on-pc-2</id>
   <content type="html">&lt;p&gt;Eight frequently-used tools were listed in &lt;a href=&quot;http://blog.pzheng.me/2013/07/30/productivity-tools-on-pc-1/&quot;&gt;preview post&lt;/a&gt;. Some of them are so handy that you could use them directly  without any customization. I will introduce first two tools in this single post.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h1 id=&quot;everyting&quot;&gt;Everyting&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Everything&lt;/em&gt; is the most convenient search tool on PC.  I configured the following two points according to my own habits and started using it. Honestly, you don’t need to follow but just try it. I bet you’re gonna love it!&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.voidtools.com/download.php&quot;&gt;++Download++&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;hot-key-setting&quot;&gt;Hot Key Setting&lt;/h2&gt;

&lt;p&gt;I’d like to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt + F1&lt;/code&gt; to call out &lt;em&gt;Everything&lt;/em&gt; from system tray. So I change these two values in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tools --&amp;gt; Options --&amp;gt; General&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;New window Hotkey Modifier: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;New window Hotkey Modifier: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VK_F1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20130808_everything_hotkey.png&quot; alt=&quot;Everything Hotkey&quot; /&gt;&lt;/p&gt;

&lt;p&gt;What? You need hot key to minimize it back to system tray? I bet you could try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt + F4&lt;/code&gt; :-P&lt;/p&gt;

&lt;h2 id=&quot;hide-empty&quot;&gt;Hide Empty&lt;/h2&gt;

&lt;p&gt;As a fake minimalist, I’d like empty appearance when there is nothing in search bar, rather than bunch of non-sense files showing up. I just need to pick &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hide results when the search is empty&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tools --&amp;gt; Options --&amp;gt; View&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20130808_everything_hide_empty.png&quot; alt=&quot;Everything hide empty&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;launchy&quot;&gt;Launchy&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Launchy&lt;/em&gt;, a quick launcher, is another small tool which will improve your quality of experience on PC. I can get rid of the quick launch bar and all nasty shortcuts on my destop.&lt;/p&gt;

&lt;p&gt;Actually &lt;em&gt;Launchy&lt;/em&gt; could be replaced by &lt;em&gt;Everything&lt;/em&gt; to some extent. But I still keep both of them. Why not let them do their own jobs?&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.launchy.net/download.php&quot;&gt;++Download++&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first thing when I use &lt;em&gt;Launchy&lt;/em&gt; is changing default skin to &lt;em&gt;Spotlight Wide&lt;/em&gt; :-)&lt;/p&gt;

&lt;h2 id=&quot;scan-catalog&quot;&gt;Scan Catalog&lt;/h2&gt;

&lt;p&gt;Firstly you need to rescan your program files folders, especially if you are more interested in portable programs. Since the default catalog only contains &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;start menu&lt;/code&gt; directory and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Program Files&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Go to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options --&amp;gt; Catalog&lt;/code&gt;, add certain directories. Don’t forget to add file type, e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.exe&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.lnk&lt;/code&gt;, as well as option for sub-directories. Then click &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rescan Catalog&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20130808_launchy_settings.png&quot; alt=&quot;Launchy settings&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;plugins&quot;&gt;Plugins&lt;/h2&gt;

&lt;p&gt;As you may know, &lt;em&gt;Launchy&lt;/em&gt; is able to calculate, search web etc, which I don’t use frequently.&lt;/p&gt;

&lt;p&gt;But one plugin I use almost every day is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Runner&lt;/code&gt;. Because portable &lt;em&gt;DokuWiki&lt;/em&gt; (&lt;em&gt;DokuWikiStick&lt;/em&gt;), one of my indispensible tools I’d like to introduce later, needs to run mini &lt;em&gt;Apache&lt;/em&gt; engine locally (Please note, this is the first time two tools connect. There will be more in later posts.). I have to click &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mapache.exe&lt;/code&gt; whenever PC rebooting to start &lt;em&gt;Apache&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So I just go to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options --&amp;gt; Plugins&lt;/code&gt; and add those executable files into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Runner&lt;/code&gt; as the following screenshot. You could run other similar programs as well.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20130808_launchy_plugin.png&quot; alt=&quot;Launchy plugin&quot; /&gt;&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Productivity Tools on PC (1)</title>
   <link href="https://blog.pzheng.me//2013/07/30/productivity-tools-on-pc-1/"/>
   <updated>2013-07-30T07:13:00+00:00</updated>
   <id>https://blog.pzheng.me//2013/07/30/productivity-tools-on-pc-1</id>
   <content type="html">&lt;p&gt;Until graduated from school, I didn’t consiously realise that software tool could help to improve my productivity. And after woke up, I kept absorbing related information from internet and colleagues. Though I have spent quite a lot time on configuring and customizing various tools, even dropped some of them after deep investigation and study, I still think what I learned and was benefited is much more than what I lost.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Therefore it’s time to summarize and share my experience on this topic.&lt;/p&gt;

&lt;p&gt;In the following days, I’d like to introduce below tools (yeah, I know you might be disappointed since they are all so popular and well-known):&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.pzheng.me/2013/08/08/productivity-tools-on-pc-2/&quot;&gt;Everything&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.pzheng.me/2013/08/08/productivity-tools-on-pc-2/&quot;&gt;Launchy&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.pzheng.me/2013/08/19/productivity-tools-on-pc-3/&quot;&gt;TotalCommand&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.pzheng.me/2013/11/10/productivity-tools-on-pc-4/&quot;&gt;DokuWiki&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.pzheng.me/2013/11/18/productivity-tools-on-pc-5/&quot;&gt;Outlook&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.pzheng.me/2014/04/13/productivity-tools-on-pc-6/&quot;&gt;Dropbox&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;AutoHotKey&lt;/li&gt;
  &lt;li&gt;Emacs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I will try not to write it in a “manual” or “how-to” way which you could easily find all over the internet, but major focus on why and how I use and integrate them as my own software eco-system. Every tool has its pros and cons. You need to choose your most suitable tools by yourself.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>UMTS Layers Mapping for 12.2kbps AMR Call</title>
   <link href="https://blog.pzheng.me//2013/07/15/umts-layers-mapping-for-12-dot-2kbps-amr-call/"/>
   <updated>2013-07-15T03:27:00+00:00</updated>
   <id>https://blog.pzheng.me//2013/07/15/umts-layers-mapping-for-12-dot-2kbps-amr-call</id>
   <content type="html">&lt;p&gt;Every freshman needs to learn the channel mapping of different layers when comming into UMTS fields. I don’t want to repeat those mapping relationships which could be found in almost every wireless book.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Here is an abstract figure showing the mapping of Logical Channels and Transport Channels, taking 12.2kbps AMR call as an example. Wheneven my mind is messed up about it, I will glance below picture and recall quickly.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20130715_122kbpsamrcall.png&quot; alt=&quot;12.2kbps AMR call&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The biggest pipe stands for a radio link. And there are four Transport Channels for this radio link: DCH1, DCH2, DCH3 and DCH24.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;DCH24 carries four SRBs, which map to four Logical Channels through RLC.&lt;/li&gt;
  &lt;li&gt;DCH1/2/3 map to three Logical Channels respectively. These three DCHs correspond to three classes of voice quality: Class A, Class B and Class C. They share the same AAL2 channels with the same Binding ID.&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>HS-SCCH Number Configuration</title>
   <link href="https://blog.pzheng.me//2013/07/01/hs-scch-number-configuration/"/>
   <updated>2013-07-01T06:49:00+00:00</updated>
   <id>https://blog.pzheng.me//2013/07/01/hs-scch-number-configuration</id>
   <content type="html">&lt;p&gt;I have met a nasty bug regarding HS-SCCH number during testing Dual Cell HSDPA (DC-HSDPA), which took weeks to debug on both Node B and testing equipment side.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;With DC-HSDPA enabled, one UE could only monitor up to 6 HS-SCCH channels in both cells (one dual cell pair), e.g. 3+3, 2+4, 4+2, etc. Usually we’d like to use 3+3 configuration. But really it’s up to the vendors. No specific limitation in 3GPP specification regarding this point.&lt;/p&gt;

&lt;p&gt;However, there are still 8 HS-SCCH codes available from Node B perspective for these two cells. Then if Node B doesn’t inform UE which three out of four HS-SCCH codes will be scheduled in one cell, UE might miss some data due to this mismatch.&lt;/p&gt;

&lt;p&gt;The whole process is like this:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Node B gets available HS-SCCH codes for each cell via NBAP: Physical Shared Channel Reconfiguration (PSCR) message.&lt;/li&gt;
  &lt;li&gt;RNC sends NBAP: radio link set up message to Node B.&lt;/li&gt;
  &lt;li&gt;Node B sends back radio link set up response message to RNC with specific HS-SCCH codes (in certain sequence).&lt;/li&gt;
  &lt;li&gt;RNC sends RRC: radio link set up message to UE with those HS-SCCH codes (the same sequence).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;According to &lt;a href=&quot;http://www.3gpp.org/ftp/Specs/html-info/25212.htm&quot;&gt;TS25.212&lt;/a&gt; section 4.6.2.3, P and O should fulfil the following formula:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Round(O - 1 - downward round(P/8) * 15) = (HS-SCCH number) mod 2&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;P&lt;/em&gt; stands for the total HS-PDSCH code number, while &lt;em&gt;O&lt;/em&gt; the start HS-PDSCH code number.&lt;/p&gt;

&lt;p&gt;Generally, HS-SCCH number is the index of HS-SCCH codes in radio link set up response message (step #3). For example, in one cell, there are 4 HS-SCCH codes, 4, 8, 9 and 10 in a row. UE 0 is assigned as 4/8/9, and UE 1 as 8/9/10, UE 2 as 8/10/4, etc. For UE 0, the HS-SCCH number for code 4 is 1, code 8 is 2, code 9 is 3. The same is applicable for UE 1, 2, and so forth.&lt;/p&gt;

&lt;p&gt;But if you misunderstand HS-SCCH number as the index of HS-SCCH number in PSCR message for the whole cell as below. For instance, in PSCR code 4/8/9/10 is allocated to this cell as this sequence. Please don’t make mistake that code 4 as HS-SCCH number 1 for all users. That would result in so unexpected problems since it leads to misbehaviour in above formula.&lt;/p&gt;

&lt;p&gt;As you may know, HS-SCCH amount is updated with Multi-Carrier HSDPA arising. But the same formula should be followed no matter how the amount changes.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Fix Archlinux</title>
   <link href="https://blog.pzheng.me//2013/06/22/fix-archlinux/"/>
   <updated>2013-06-22T04:20:00+00:00</updated>
   <id>https://blog.pzheng.me//2013/06/22/fix-archlinux</id>
   <content type="html">&lt;p&gt;If you are an Archlinux user, you might have noticed the latest news - &lt;a href=&quot;https://www.archlinux.org/news/binaries-move-to-usrbin-requiring-update-intervention/&quot;&gt;Binaries move to /usr/bin requiring update intervention&lt;/a&gt;. The same problem was encountered on my laptop during update:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;error: failed to commit transaction (conflicting files)
filesystem: /bin exists in filesystem
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Following the instruction, I just uninstalled Grub and some other programs. But accidentally hit POWER OFF button right after. No surprise I cannot login to Archlinux after reboot. Here is the procedure how I fixed it.&lt;/p&gt;

&lt;!--more--&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Download &lt;a href=&quot;https://www.archlinux.org/download/&quot;&gt;latest Linux ISO&lt;/a&gt; and creat Live USB via &lt;a href=&quot;http://www.linuxliveusb.com/&quot;&gt;LinuxLive USB Creator&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Get into Live CD mode and set up internet connect according to &lt;a href=&quot;https://wiki.archlinux.org/index.php/Beginners%27_Guide&quot;&gt;Beginners’ Guide&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;Here is an example of wireless connection.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; # iw dev
 # ip link set wlp3s0 up
 # wifi-menu wlp3s0 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Check disk partitioning.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; # lsblk /dev/sda 
 # fdisk -l  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;On my laptop, sda 7/8/9/10 are Linux partitions.&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;sda 7: 200M boot directory&lt;/li&gt;
      &lt;li&gt;sda 8: 2G SWAP&lt;/li&gt;
      &lt;li&gt;sda 9: 4.7G root directory&lt;/li&gt;
      &lt;li&gt;sda 10: 28.6G home directory&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Mount the directories respectively.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; # mkdir /mnt/arch
 # mount /dev/sda9 /mnt/arch
 # mount /dev/sda7 /mnt/arch/boot/
 # mount /dev/sdb10 /mnt/arch/home/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Chroot according to wikipage &lt;a href=&quot;https://wiki.archlinux.org/index.php/Chroot&quot;&gt;Change Root&lt;/a&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; # arch-chroot /mnt/arch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Use the same internet connection.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; # cp -L /etc/resolv.conf etc/resolv.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Assign the shell.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; # chroot . /bin/bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Install syslinux.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; # pacman -S syslinux
 # syslinux-install_update -i -a -m
 # nano /boot/syslinux/syslinux.cfg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Change sda9 to the root directory.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ...
 LABEL arch
     ...
     APPEND root=/dev/sda9 ro
 	...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;To prevent below error. You still need the following steps.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; /sbin/init does not exist 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Install systemd-sysvcompat.&lt;/p&gt;

    &lt;p&gt;Find below line in ‘/boot/syslinux/syslinux.cfg’.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; LINUX ../vmlinuz-linux
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Add init as:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; LINUX ../vmlinuz-linux init=/usr/lib/systemd/systemd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Exit chroot.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# exit
# umount /mnt/arch/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Reboot and now you will get into the nice bootload interface.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Scrum Practice II</title>
   <link href="https://blog.pzheng.me//2013/06/03/scrum-practice-ii/"/>
   <updated>2013-06-03T03:32:00+00:00</updated>
   <id>https://blog.pzheng.me//2013/06/03/scrum-practice-ii</id>
   <content type="html">&lt;p&gt;Backlog should be sorted out and orgnaized after sprint planning. And the testers could start taking the tasks afterwards.&lt;/p&gt;

&lt;p&gt;Stand-up meeting will be held daily to check the progress and obstacles. Still, if we don’t pay close attention, it will become a mere formality without any useful output. More dangerously, scrum master would assume it’s all under control by hosting such daily meeting. But actually it’s not.&lt;/p&gt;

&lt;p&gt;We take the following actions to monitor the project more actively.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h3 id=&quot;milestone-setting&quot;&gt;Milestone Setting&lt;/h3&gt;

&lt;p&gt;Though human beings are able to process multiple tasks simultaneously. We still don’t suggest to hold more than three tasks in hands at the same time. Therefore, all the tasks should be spanned reasonably along with the time.&lt;/p&gt;

&lt;p&gt;What we have done is to set milestone for each task based on the estimated effort. Well you could call it other name, such as “deadline” which I dislike.&lt;/p&gt;

&lt;p&gt;As I have presented in &lt;a href=&quot;http://blog.pzheng.me/2013/06/02/scrum-practice-i/&quot;&gt;Scrum Practice I&lt;/a&gt;, there are several weekly targets in this sprint. So it’s quite easy to set milestone respectively.&lt;/p&gt;

&lt;p&gt;We highlight the milestone days in a different colour in backlog which makes it colourful. Thus with a quick glance, you will find maybe too many tasks are gathered in one week which are obviously impossible to finish on time.&lt;/p&gt;

&lt;p&gt;Since there are sorts of dependencies among all the tasks from time perspective. One task delay may cause the delay of all the subsequent tasks. Therefore, every time we meet postponement, besides current task, we should re-estimate the consequence and risks for all the following tasks. There are two options:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Work overtime to catch up the schedule.&lt;/li&gt;
  &lt;li&gt;Ask Product Owner’s approval for the delay of certain tasks.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We don’t need to wait till the end of sprint to find out, OMG, too many tasks haven’t been done yet. Instead, almost every change is under our control.&lt;/p&gt;

&lt;h3 id=&quot;actual-effortlatest-estimation&quot;&gt;Actual Effort/Latest Estimation&lt;/h3&gt;

&lt;p&gt;In the official guide of Agile, it’s told to record the remaining effort in the backlog in stand-up meeting. But we found it was somehow useless to record only remaining effort since estimation was not accurate enough to indicate the progress.&lt;/p&gt;

&lt;p&gt;Thus we record not only lastest estimation effort (RE), but also actual effort (AE) which has paid on this task, as the format of “AE/RE”. For example, today I have spent four hours on an item and I suppose two hours are still needed to completely finish it. Then I will write “4/2” in that field for the specific task on that day.&lt;/p&gt;

&lt;p&gt;In that way, we are able to calculate the actual effort you have put on certain task in the sprint retrospective meeting. And use the historical data as reference to estimate effort for the next sprint during planning, which is much useful and reasonable.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Scrum Practice I</title>
   <link href="https://blog.pzheng.me//2013/06/02/scrum-practice-i/"/>
   <updated>2013-06-02T06:08:00+00:00</updated>
   <id>https://blog.pzheng.me//2013/06/02/scrum-practice-i</id>
   <content type="html">&lt;p&gt;Scrum master in our team took annual leaves these days. As her backup, I hosted the sprint retrospective &amp;amp; planning meeting, which was a rare and exciting experience to manage a scrum team and practice scrum.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;In my humble opinion, Agile aims to develop and test software in a more lightweight and quick-response way, which is why it’s chosen by many software companies. But for the testing work in our team, more specifically, for testing large scale of telecom software, it’s a bit difficult to do it lightly, due to the complexity of testing frame/tool/objectives.&lt;/p&gt;

&lt;p&gt;Well it’s another topic for the improvement of our testing frame (Honestly it hasn’t been improved quite much. So it is still being far away from “idealy”). Today I’d like to summarize some tips we are using in sprint retrospective and planning.&lt;/p&gt;

&lt;h3 id=&quot;sprint-planning&quot;&gt;Sprint Planning&lt;/h3&gt;
&lt;p&gt;We will get the task list from Product Owner before sprint planning. And during planning, we need to break down those tasks which are expected to be finished in this sprint, estimate the effort for each task and check whether we could finish them on time.&lt;/p&gt;

&lt;h4 id=&quot;problems--possible-reasons&quot;&gt;Problems &amp;amp; Possible Reasons&lt;/h4&gt;

&lt;p&gt;Previously, we would simply sum up all the tasks’ effort and compare it with the available time(total working hours - possible leave hours) in hour bank. But we found it was so inaccurate that we could hardly finish all the tasks we had promised in beginning.&lt;/p&gt;

&lt;p&gt;In my view, there are two reasons for this inaccuracy:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Estimation is not precise.&lt;/li&gt;
  &lt;li&gt;Estimation is pure effort, instead of duration on timeline.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Group dicussion and breaking down tasks as small as possible would help for #1, as Agile coach suggests.&lt;/p&gt;

&lt;h4 id=&quot;effort-vs-duration&quot;&gt;Effort vs. Duration&lt;/h4&gt;

&lt;p&gt;As for #2, you might be suprised. Frankly, now it’s the biggest challenge in our team. Aforementioned complixity and dependency by other sites/components are definitely the cause.&lt;/p&gt;

&lt;p&gt;For instance, we may estimate a certain task is expected to complete within four hours. And the actual effort is four hours. But it lasts for, let’s say, four days in the end. The scenario might be:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Tester spends two hours creating test scripts and running case. And he/she finds a problem in software.&lt;/li&gt;
  &lt;li&gt;After two days investigation, software guys would provide correction.&lt;/li&gt;
  &lt;li&gt;Tester verifies the correction and another bug is encountered in one hour.&lt;/li&gt;
  &lt;li&gt;Feedback to software guys and discussion is still ongoing. Finally root cause is found two days later.&lt;/li&gt;
  &lt;li&gt;Tester verifies it again and report the test results in one hour.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is a very common scenario in our daily work. The reality is much more complicated and time-consuming. Please don’t ask why so much time is needed for software guys investigation. That’s the current status which we cannot change in a multinational corporation.&lt;/p&gt;

&lt;p&gt;As you can see, it only costs four hours for this task. But the duration is four days totally. So if we just sum the efforts up for all tasks, there might be huge gap between calculation and reality.&lt;/p&gt;

&lt;h4 id=&quot;what-actions-weve-taken&quot;&gt;What Actions We’ve Taken&lt;/h4&gt;

&lt;p&gt;We use two simple tools in sprint planning to try to prevent such gap:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Mindmap tool (either &lt;a href=&quot;http://sourceforge.net/projects/freemind/&quot;&gt;Freemind&lt;/a&gt; or &lt;a href=&quot;http://www.xmind.net/&quot;&gt;Xmind&lt;/a&gt;. Both are free.).&lt;/li&gt;
  &lt;li&gt;Calendar&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Suppose we have a list of tasks and the effort has already been estimated. Now we need to fill those tasks into the calendar.&lt;/p&gt;

&lt;p&gt;Firstly, add four nodes in Mindmap tool.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Monthly target&lt;/li&gt;
  &lt;li&gt;Weekly target&lt;/li&gt;
  &lt;li&gt;Risks&lt;/li&gt;
  &lt;li&gt;Leave plan&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Secondly, add all the tasks with effort into “Monthly target” node.&lt;/p&gt;

&lt;p&gt;Thirdly, list the leave plan for the forthcoming sprint. And line through those days in calendar.&lt;/p&gt;

&lt;p&gt;Fourthly, add several nodes under “Weekly target”. Node number accords to the week number in one sprint. Generally there are four weeks (one month) in our team. Please highlight the actual working days(without weekends and public holidays) for each node.&lt;/p&gt;

&lt;p&gt;Finally, fill those tasks into each week node accordingly. Leave plan should be taken into account during filling. And don’t forget to list the risks under “Risks” node during planning.&lt;/p&gt;

&lt;p&gt;Of course you may have daily target but it’s to aggressive and pushing. We’d rather recommend weekly target.&lt;/p&gt;

&lt;p&gt;After practice with several testers, we suprisely found we were too optimistic previously. Many tasks cannot be added into this map aligned with timeline.&lt;/p&gt;

&lt;p&gt;With weekly target, we could control the progress of project more carefully. Please also pay attention to “risks” which might cause delay for your project.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Performance Testing</title>
   <link href="https://blog.pzheng.me//2013/05/19/performance-testing/"/>
   <updated>2013-05-19T19:57:00+00:00</updated>
   <id>https://blog.pzheng.me//2013/05/19/performance-testing</id>
   <content type="html">&lt;p&gt;Performance testing is kind of advanced testing when basic functionalities have already been verified in software. And there are several terms regarding performance testing, such as capacity testing, load testing, etc. Once I heard about them from bunch of guys and was confused by different meanings of them from different people’s perspective.&lt;/p&gt;

&lt;p&gt;There is a dedicated page on Wikipedia for &lt;a href=&quot;http://en.wikipedia.org/wiki/Software_performance_testing&quot;&gt;performance testing&lt;/a&gt;. But here I’d like to share my view about it.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h3 id=&quot;stability-testing&quot;&gt;Stability testing&lt;/h3&gt;

&lt;p&gt;The main objective of stability testing is to verify that SW functions correctly with at least such traffic intensity that it is normally designed to handle (i.e. nominal traffic) and that SW is stable &lt;strong&gt;when loaded for a long time&lt;/strong&gt;. The used traffic mix is designed in co-operation with product management. Traffic should correspond real traffic as much as possible. Other objectives of stability testing are to find faults and to verify capacity requirements defined in product documentation.&lt;/p&gt;

&lt;p&gt;The keyword of stability testing is lasting for amount of time, one hours, six hours, one day, two days, one week, etc. It depends on the usage of software in customer field.&lt;/p&gt;

&lt;p&gt;Generally, there are three phases for stability testing:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;low load&lt;/li&gt;
  &lt;li&gt;moderate load&lt;/li&gt;
  &lt;li&gt;high load&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;capacity-testing&quot;&gt;Capacity testing&lt;/h3&gt;

&lt;p&gt;These tests consist of detailed measurements of the capacity influence of different events. It focuses on different kinds of traffic/services, and how much load SW could afford for each profile. Usually, the real capacity of software is more than what product managers promise to customers for margin purpose.&lt;/p&gt;

&lt;p&gt;Major target of capacity testing is to verify different capacities for different profiles which are defined in requirements.&lt;/p&gt;

&lt;h3 id=&quot;overload-testing&quot;&gt;Overload testing&lt;/h3&gt;

&lt;p&gt;In the overload tests, traffic are obviously overloaded. There are two situations:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Load is more than requirement but less than the real capacity of software.&lt;/li&gt;
  &lt;li&gt;Load is even more than the real capacity of software.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;General rule for overload testing is, software could reject those extra traffic. But it should at least obtain the nominal capacity in requirements and shouldn’t crash for any reason! Sometimes requirements would define the performance of software with different level of overload traffice.&lt;/p&gt;

&lt;p&gt;Overload control is a MUST considered functionality in software design.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Soft and Softer Handover II</title>
   <link href="https://blog.pzheng.me//2013/05/12/soft-and-softer-handover-ii/"/>
   <updated>2013-05-12T20:28:00+00:00</updated>
   <id>https://blog.pzheng.me//2013/05/12/soft-and-softer-handover-ii</id>
   <content type="html">&lt;h3 id=&quot;power-control-during-sho&quot;&gt;Power control during SHO&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Misunderstanding #2:&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;No SHO for HSDPA. There is always only one active RL for HS-PDSCH. Thus there is also only one F-DPCH in downlink during ul SHO.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;p&gt;Since HSDPA was introduced in 3GPP Rel 5, HSDPA scheduling is handled by MAC-hs in Node B instead of RNC. The major reason why there is no SHO for HSDPA is, shared channel aka HS-DSCH is involved in HSDPA.&lt;/p&gt;

&lt;p&gt;As we know, downlink TPC command is carried on either DPCCH or F-DPCH.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;In case of DPCCH, the service would be like DL: HSDPA + DCH / UL: HSUPA (+ DCH). Downlink DCH could perform softer/soft handover without any doubt. So there will be two/three TPC commands in downlink.&lt;/li&gt;
  &lt;li&gt;In case of F-DPCH, the serice is more like DL: HSDPA / UL: HSUPA.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As for ul SHO with #2, HSDPA is still active in former serving cell. But on the uplink, there are already two RLs from UE to two/three different cell in Node B.&lt;/p&gt;

&lt;p&gt;Each cell needs to send dl TPC to UE for power control purpose. Thus F-DPCH is definitely active for all cells.&lt;/p&gt;

&lt;p&gt;The only difference for softer and soft handover is TPC:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Softer handover: one Node B will receive all the uplink channels from the same UE and bring in diversity gain. Thus TPC might be the same for all cells.&lt;/li&gt;
  &lt;li&gt;Soft handover: two or more different Node Bs receive the uplink channels and generate downlink TPC respectively. So that might be possible that TPCs are different at the same time. From UE perspective, the general rule is firstly to follow “DOWN” command in any case. Because, closed loop power control is as quick as 1500Hz to balance the power. And subsequent cell overload is not a good idea in such case.&lt;/li&gt;
&lt;/ol&gt;

</content>
 </entry>
 
 <entry>
   <title>Soft and Softer Handover I</title>
   <link href="https://blog.pzheng.me//2013/04/02/soft-and-softer-handover/"/>
   <updated>2013-04-02T20:38:00+00:00</updated>
   <id>https://blog.pzheng.me//2013/04/02/soft-and-softer-handover</id>
   <content type="html">&lt;p&gt;A few days ago, I found myself wasn’t so clear about soft and softer handover and misunderstood the whole procedure. So I just read some material and also asked help from some experts who were good at this topic. Here is the summary part I for my learning.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: SHO stands for soft/softer HO in the following paragraphs.&lt;/p&gt;

&lt;p&gt;Firstly, let’s take a look at the overall picture of different handovers.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20130402_handover.png&quot; alt=&quot;handover&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;ul-sho&quot;&gt;UL SHO&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Misunderstanding #1:&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;There are multiple RLs in both uplink and downlink during SHO.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In downlink, there are two/three RLs(radio links) during SHO. Please notice, radio link is just a logic concept which isn’t existed but just describes the connection between Node B and UE. But unlike downlink, there is only one RL in uplink. The reason is, in the downlink, scrambling code is used to distinguish the cells, whereas it’s used to identify UE in the uplink.&lt;/p&gt;

&lt;p&gt;Therefore, Node B should send two/three copies of the same data via two/three different cells with different scrambling codes (2 way/3 way softer handover). At the same time, there is only one copy of data transmitting from UE to Node B. But all cells in active set will recieve it respectively and finally soft-combine it in RAKE.&lt;/p&gt;

&lt;p&gt;That is also the reason why “addleg” command could only apply in downlink without uplink in TM500(test equipment from &lt;a href=&quot;http://aeroflex.com/&quot;&gt;Aeroflex&lt;/a&gt;) command reference.&lt;/p&gt;

&lt;p&gt;The same mechanism is also applicable for E-DPDCH/E-DPCCH, as well as associated ul DPCCH and HS-DPCCH. As a result, all uplink channels have got diversity receiving gain.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Some Thoughts on DFMEA</title>
   <link href="https://blog.pzheng.me//2013/03/26/some-thoughts-on-dfmea/"/>
   <updated>2013-03-26T21:45:00+00:00</updated>
   <id>https://blog.pzheng.me//2013/03/26/some-thoughts-on-dfmea</id>
   <content type="html">&lt;p&gt;Yesterday I took part in a whole day training by my colleague &lt;em&gt;Zack Taylor&lt;/em&gt; on &lt;strong&gt;DFMEA&lt;/strong&gt;, which was really interesting. &lt;strong&gt;DFMEA&lt;/strong&gt; stands for &lt;strong&gt;D&lt;/strong&gt;esign &lt;strong&gt;F&lt;/strong&gt;ailure &lt;strong&gt;M&lt;/strong&gt;ode and &lt;strong&gt;E&lt;/strong&gt;ffects &lt;strong&gt;A&lt;/strong&gt;nalysis. It’s a method (or process) for design product, either hardware or software, to predict and prevent defects before delivering.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Zack&lt;/em&gt; told me &lt;strong&gt;DFMEA&lt;/strong&gt; was a part of &lt;strong&gt;FMEA&lt;/strong&gt;, which was created by (maybe) &lt;em&gt;Motorola&lt;/em&gt; and once used in aviation design in 1960s. Well, it’s a little bit different from &lt;a href=&quot;http://en.wikipedia.org/wiki/Failure_mode_and_effects_analysis#History&quot;&gt;the history of FMEA&lt;/a&gt; on Wikipedia. But one thing for sure, it was invented decades ago. And it was used in military/NASA firstly which extremely concerned about safety and security, and was introduced into software industry later.&lt;/p&gt;

&lt;h1 id=&quot;critical-factors-in-dfmea&quot;&gt;Critical factors in DFMEA&lt;/h1&gt;

&lt;p&gt;Firstly team members should identify below critical issues along with &lt;strong&gt;functionalities&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Failure mode&lt;/li&gt;
  &lt;li&gt;Failure effect&lt;/li&gt;
  &lt;li&gt;Failure cause&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then calculate the &lt;strong&gt;Risk Priority Number&lt;/strong&gt; (&lt;strong&gt;RPN&lt;/strong&gt;) based on the following values (also need input/discussion from team members):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Probability/occurrence&lt;/li&gt;
  &lt;li&gt;Severity&lt;/li&gt;
  &lt;li&gt;Detection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At last, take actions according to &lt;strong&gt;RPN&lt;/strong&gt; list!&lt;/p&gt;

&lt;h1 id=&quot;my-thoughts&quot;&gt;My thoughts&lt;/h1&gt;

&lt;p&gt;It’s a great idea to abstract a manual procedure to a general concept or methodology. The inventors tried to quantify and visualize the risks before implementation. Human beings are unmeasurable. But more and more modern methodologies are focusing on inspring the employees and measuring the productivity at the same time, e.g. &lt;strong&gt;Agile&lt;/strong&gt;, as well as &lt;strong&gt;DFMEA&lt;/strong&gt;.&lt;/p&gt;

&lt;h1 id=&quot;my-concerns&quot;&gt;My concerns&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Team members might feel confused about the definition of “failure mode” and “failure cause”. &lt;em&gt;Zack&lt;/em&gt; said “failure mode” should not be sensed by customer. And with different &lt;strong&gt;scope&lt;/strong&gt; of DFMEA, the same issue could be either “failure mode” or “failure cause”. To be honest, now I am still perplexed about it… No wonder there will be lots of discussion of it on DFMEA meeting.&lt;/li&gt;
  &lt;li&gt;I am also confused about “detection”. &lt;em&gt;Zack&lt;/em&gt; told me it should be derived from customers’ perspective instead of testers. But still, if our SW detects one certain fault, there will be only two possibilities, “raise alarm” or not. Thus no 1~10 levels of ratings. And why the weight of “detection” is the same as “occurrence” and “severity”?&lt;/li&gt;
  &lt;li&gt;All of these items and values are provided by humans. In other words, they are subjective to some extend, i.e. inaccuracy and uncertainty. How to avoid it?&lt;/li&gt;
  &lt;li&gt;Managers more like firefightors rather than wizards or witches. Those defects eliminating during DFMEA are non-existed and avoidable in their opinion. At the same time, it’s very difficult to measure the quality of DFMEA.&lt;/li&gt;
  &lt;li&gt;It’s a mindset about failure. And without doubt, successful DFMEA needs competency and experienced team member. How to implement it in an ordinary team?&lt;/li&gt;
  &lt;li&gt;It’s living document requiring constantly updating. In my view, process is very easy to be implemented as just a “process”, instead of a mindset. Any ideas?&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;enlightening&quot;&gt;Enlightening&lt;/h1&gt;

&lt;p&gt;Brainstorming during DFMEA is keeping asking “what if…” questions. So DFMEA is also a very good chance to discuss &lt;strong&gt;exploratory testing&lt;/strong&gt; among architects/developers/testers. Also, we could just use the output of DFMEA as the input of our testing. See, all things have connections!&lt;/p&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;

&lt;p&gt;If you are not familiar with this topic, please check the brief introduction on Wikipedia.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Failure_mode_and_effects_analysis&quot;&gt;FMEA&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/DFMEA&quot;&gt;DFMEA&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You could also check other alternatives:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Design_Review_Based_on_Failure_Mode&quot;&gt;Design Review Based on Failure Mode (DRBFM)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Fault_Tree_Analysis&quot;&gt;Fault tree analysis (FTA)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Taguchi_methods&quot;&gt;Taguchi methods&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Confluence Learning Notes</title>
   <link href="https://blog.pzheng.me//2013/03/23/confluence-learning-notes/"/>
   <updated>2013-03-23T21:00:00+00:00</updated>
   <id>https://blog.pzheng.me//2013/03/23/confluence-learning-notes</id>
   <content type="html">&lt;p&gt;Days ago I was asked to help building a knowledge sharing wiki for our team. Yes, I’m interested in different kinds of wiki. And most of my previous wiki experiences were coming from my own wiki which is based on open-sourced &lt;a href=&quot;https://www.dokuwiki.org/dokuwiki&quot;&gt;DokuWiki&lt;/a&gt;. It’s a good chance to learn the best enterprise wiki software – &lt;a href=&quot;http://www.atlassian.com/software/confluence/overview/team-collaboration-software&quot;&gt;Confluence&lt;/a&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;The &lt;a href=&quot;https://confluence.atlassian.com/display/DOC/Confluence+Documentation+Home&quot;&gt;syntax of Confluence&lt;/a&gt; is totally different from &lt;a href=&quot;https://www.dokuwiki.org/wiki:syntax&quot;&gt;DokuWiki&lt;/a&gt; or &lt;a href=&quot;http://daringfireball.net/projects/markdown/syntax&quot;&gt;Markdown&lt;/a&gt; or &lt;a href=&quot;http://orgmode.org/&quot;&gt;Org mode&lt;/a&gt;, which is the most annoyed issue during learning. Except this, everything is almost perfect in Confluence. Especially, various of macros are quite inspiring to create beautiful pages.&lt;/p&gt;

&lt;p&gt;Here I just want to show you how to insert a Table of Contents on the upper right corner, and create a multi-tab page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: Below instructions are based on Confluence 3.5 (may not be compatible with the latest Confluence).&lt;/p&gt;

&lt;h2 id=&quot;toc-on-upper-right-corner&quot;&gt;TOC on upper right corner&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;First section this page;&lt;/li&gt;
  &lt;li&gt;Split this section into two columns;&lt;/li&gt;
  &lt;li&gt;Contents are placed in the left(first) column;&lt;/li&gt;
  &lt;li&gt;TOC is displayed in the right(second) column within a panel.&lt;/li&gt;
  &lt;li&gt;Title/colore of the panel could be formatted by yourself.&lt;/li&gt;
&lt;/ol&gt;

&lt;pre&gt;&lt;code&gt;
{section}
{column}
{numberedheadings}

body of contents

{numberedheadings}
{column}
{column:width=30%}
{panel:title=Contents| borderColor=#ccc| titleBGColor=#FFAF00| bgColor=#FFFFCE}
{toc}
{panel}
{column}
{section}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;multi-tab-page&quot;&gt;Multi-tab page&lt;/h2&gt;

&lt;p&gt;The following macros are required when designing multi-tab page:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;composition-setup&lt;/li&gt;
  &lt;li&gt;card&lt;/li&gt;
  &lt;li&gt;deck&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code&gt;
{composition-setup}
deck.startHidder=true
deck.tab.inactive.border = 1px #ccc solid
deck.tab.inactive.background = #ccc
deck.tab.active.border = 1px #ccc solid
deck.tab.active.background = #FFFFFF
deck.card.border = #FFFFFF
deck.width = 100%
deck.tab.spacer = 5px
{composition-setup}

{deck:id=FAQsCard}

{card:label=General Questions}

card 1 content

{card}

{card:label=Case &amp;amp; PR Questions}

card 2 content

{card}

{card:label=Other Questions}

card 3 content

{card}

{deck}
&lt;/code&gt;&lt;/pre&gt;
</content>
 </entry>
 
 <entry>
   <title>My Android Home Screen II</title>
   <link href="https://blog.pzheng.me//2013/03/23/my-android-home-screen-ii/"/>
   <updated>2013-03-23T19:54:00+00:00</updated>
   <id>https://blog.pzheng.me//2013/03/23/my-android-home-screen-ii</id>
   <content type="html">&lt;p&gt;Right after posted &lt;a href=&quot;http://blog.pzheng.me/2013/03/12/my-android-home-screen/&quot;&gt;“My Android Home Screen”&lt;/a&gt;, I found another powerful launcher to customize my home screen.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;It is &lt;a href=&quot;https://play.google.com/store/apps/details?id=net.pierrox.lightning_launcher&quot;&gt;“Lightning Launcher”&lt;/a&gt; which is really great on both conciseness and customization. Frankly, it’s more powerful than &lt;a href=&quot;https://play.google.com/store/apps/details?id=org.zeam&quot;&gt;“Zeam Launcher”&lt;/a&gt; &lt;strong&gt;from my own perspective&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;My new screen home is presented below:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20130323_androidhomescreen2.jpg&quot; alt=&quot;android home screen 2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The most attactive feature than Zeam Launcher is, no fixed dock on the bottom. Almost every inch of the screen could be customized, which is amazing :-)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>My android home screen</title>
   <link href="https://blog.pzheng.me//2013/03/12/my-android-home-screen/"/>
   <updated>2013-03-12T07:59:00+00:00</updated>
   <id>https://blog.pzheng.me//2013/03/12/my-android-home-screen</id>
   <content type="html">&lt;p&gt;To be honest, I am not a WP fan, though I am working in Nokia right now. iPhone is dream phone and perfect from all aspects. But it’s too expensive. That’s why I choose Android.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;I customized the home screen of every android phone I have owned, for the same reasons:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;plain text&lt;/li&gt;
  &lt;li&gt;battery saving&lt;/li&gt;
  &lt;li&gt;I see is what I want in only one screen&lt;/li&gt;
  &lt;li&gt;handy (maybe only for myself)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://dl.dropboxusercontent.com/u/6459697/blogimage/20130312_androidhomescreen.png&quot; alt=&quot;Android home screen&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Attention&lt;/strong&gt;: I am not a minimalist, nor perfectionst. I know many details need to improve. (Clock time is incorrect, space, font, etc…)&lt;/p&gt;

&lt;p&gt;Here are the apps in use:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.google.code.appsorganizer&quot;&gt;Apps Organizer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.th.android.widget.gTabsimiClock&quot;&gt;SiMi Clock Widget&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=de.j4velin.calendarWidget&quot;&gt;Simple Calendar Widget&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.redphx.simpletext&quot;&gt;Simple Text-Text Icon Creator&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=org.zeam&quot;&gt;Zeam Launcher&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>Simple math problem</title>
   <link href="https://blog.pzheng.me//2013/03/08/simple-math-problem/"/>
   <updated>2013-03-08T21:01:00+00:00</updated>
   <id>https://blog.pzheng.me//2013/03/08/simple-math-problem</id>
   <content type="html">&lt;p&gt;Here is a problem I met during designing test case:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Module &lt;strong&gt;A&lt;/strong&gt; is claimed to be able to process &lt;em&gt;MaxPrcMsg&lt;/em&gt; messages per second. The buffer could store each message for at most 2 seconds. Once the message hasn’t been proceeded within 2 seconds, it will be expired. Input messages are rushed into Module &lt;strong&gt;A&lt;/strong&gt; every 100ms. In case the testing duration is (&lt;em&gt;n&lt;/em&gt; * 100ms). How to set the maximum number &lt;em&gt;MaxInMsg&lt;/em&gt; of input messages to verify the performance of Module &lt;strong&gt;A&lt;/strong&gt; with high load?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The author of this requirement has presented the result and brief calculation. I read about it and found it was interesting. We could solve it by primary school skills.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Firstly, please take a look at this simple math problem (water in and out):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Water is drained with stable velocity &lt;em&gt;x&lt;/em&gt; L per second from tub, whose capacity is &lt;em&gt;y&lt;/em&gt; L. At the same time, &lt;em&gt;z&lt;/em&gt; L fresh water is poured in the tub every second. Give a duration &lt;em&gt;t&lt;/em&gt;. How to set &lt;em&gt;z&lt;/em&gt; as big as possible without breaking the maximum capacity of the tub.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;See, so simple. Isn’t it?&lt;/p&gt;

&lt;p&gt;The final result is&lt;/p&gt;

&lt;p&gt;&lt;em&gt;MaxInMsg&lt;/em&gt; =  [2 + (&lt;em&gt;n&lt;/em&gt;-1) * 0.1] * &lt;em&gt;MaxPrcMsg&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Assume the buffer is empty at the beginning, and &lt;em&gt;MaxPrcMsg&lt;/em&gt; is 40.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;In case &lt;em&gt;n&lt;/em&gt; is 1 (the duration is 100ms), &lt;em&gt;MaxInMsg&lt;/em&gt; equals 80 as shown in above formula. It means at most 80 messages could be sent to module &lt;strong&gt;A&lt;/strong&gt; within 100ms. But in the next 1.9 second, &lt;strong&gt;A&lt;/strong&gt; cannot afford any more message at all.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;In case &lt;em&gt;n&lt;/em&gt; is 3 (the duration is 300ms), &lt;em&gt;MaxInMsg&lt;/em&gt; equals 88 as shown in above formula. It doesn’t mean we could send 88 messages at the first 100ms, or even (80+8) at the first and second messages. Since when &lt;em&gt;n&lt;/em&gt; equals to 2, &lt;em&gt;MaxInMsg&lt;/em&gt; should be 84. So the proper setting should be 80+4+4.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Would you please give a reasonable input for &lt;em&gt;n&lt;/em&gt; = 100, to keep the buffer in always full state and module &lt;strong&gt;A&lt;/strong&gt; always busy in the mean time?&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>ACK/NACK/DTX in HSDPA</title>
   <link href="https://blog.pzheng.me//2013/03/07/ack-slash-nack-slash-dtx-in-hsdpa/"/>
   <updated>2013-03-07T21:08:00+00:00</updated>
   <id>https://blog.pzheng.me//2013/03/07/ack-slash-nack-slash-dtx-in-hsdpa</id>
   <content type="html">&lt;p&gt;I own a localhost wiki based on &lt;a href=&quot;https://www.dokuwiki.org/&quot;&gt;DokuWiki&lt;/a&gt; as my personal knowledge management tool. After more than two years collecting day by day, I am pleased to see more and more tips/experience in different areas appearing on it. I don’t think I will publish the whole wiki on the internet in the near future. But I’d like to orgnize and share some of the topics on this site.&lt;/p&gt;

&lt;p&gt;The first post is about HSDPA’s acknowledge.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;As we know, ACK/NACK which is carried on uplink HS-DPCCH is sending from UE to inform Node B whether it has received/decoded certain transport block successfully.&lt;/p&gt;

&lt;p&gt;The meanings of ACK/NACK/DTX are as obvious as their names express:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ACK: Transport block is decoded correctly by UE;&lt;/li&gt;
  &lt;li&gt;NACK: Transport block is decoded incorrectly;&lt;/li&gt;
  &lt;li&gt;DTX: discontinuous transmission.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Actually, it’s not that simple. We could tell more from these different states.&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;According to [chapter 6.2.6 ACK/NACK Transmit Power Reduction for HS-DPCCH](http://books.google.com/books?id=pl6U09IkLHwC&amp;amp;pg=PA174&amp;amp;lpg=PA174&amp;amp;dq=hs-scch+fail+nack+ack+dtx&amp;amp;source=bl&amp;amp;ots=r-SporHp0o&amp;amp;sig=zW_–9jdV5J6QmAimxPNjRTHwY8&amp;amp;hl=en&amp;amp;ei=GlSyTvbZBq3V4QT73PHLAw&amp;amp;sa=X&amp;amp;oi=book_result&amp;amp;ct=result&amp;amp;resnum=10&amp;amp;ved=0CFoQ6AEwCQ#v=onepage&amp;amp;q&amp;amp;f=false&lt;/td&gt;
      &lt;td&gt;Mobile communication systems and security]]) in &lt;em&gt;Mobile Communication Systems and Security&lt;/em&gt; by &lt;em&gt;Man Young Rhee&lt;/em&gt;.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;blockquote&gt;
  &lt;p&gt;In Release 5, the UE always uses DTX in the ACK/NACK field of the HS-DPCCH except when an ACK or NACK is being transmitted in response to an HS-DSCH rtansmission. This means that if the UE fails to detect typical probability 0.01 of the HS-SCCH, the UE will use DTX in the corresponding ACK/NACK field. The Node B must avoid decoding this DTX as ACK if it is to avoid loss of the HS-DSCH TTI at the physical layer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In summary:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;If HS-SCCH is not decoded successfully(no matter which part is wrong, part 1 or part 2), UE will not send any ACK/NACK info on HS-DPCCH, which is &lt;strong&gt;DTX&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;If HS-SCCH is successful but HS-PDSCH CRC is failed, &lt;strong&gt;NACK&lt;/strong&gt; will be sent.&lt;/li&gt;
  &lt;li&gt;Only if both HS-SCCH and HS-PDSCH are decoded correctly, UE will send &lt;strong&gt;ACK&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>New Year New Site</title>
   <link href="https://blog.pzheng.me//2012/01/05/new-year-new-site/"/>
   <updated>2012-01-05T17:30:00+00:00</updated>
   <id>https://blog.pzheng.me//2012/01/05/new-year-new-site</id>
   <content type="html">&lt;p&gt;Finally, 2012 is coming. And one more blog site was born for me.&lt;/p&gt;

&lt;p&gt;I will try to focus on two fields in this weblog:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Radio access&lt;/li&gt;
  &lt;li&gt;Productivity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But I am not 100% sure whether I will follow this rule in the future. Who knows. After all there are so many topics I am interested in.&lt;/p&gt;

&lt;p&gt;So let’s just go. And keep going…&lt;/p&gt;

&lt;p&gt;Oh, almost forgot, happy new year :-)&lt;/p&gt;
</content>
 </entry>
 

</feed>
