From d0fea954ec3a3a81945b99743bf34f3110be1a33 Mon Sep 17 00:00:00 2001 From: Fengda HUANG Date: Fri, 17 Nov 2017 07:23:56 +0800 Subject: [PATCH] [fix] fix typo && fixed #17 --- chapters/01-start-project.md | 4 +- github-roam.md | 4 +- index.html | 153 ++++++++++++++++++----------------- 3 files changed, 84 insertions(+), 77 deletions(-) diff --git a/chapters/01-start-project.md b/chapters/01-start-project.md index bc54ff5..7360392 100644 --- a/chapters/01-start-project.md +++ b/chapters/01-start-project.md @@ -33,7 +33,9 @@ ![License 使用情况](./img/permissive-vs-copylift-license-2.jpg) -又比如,在我们看到的一些外版书籍上,如果拥有代码。那么作者一般就会在前言或者类似的位置里,指明书中代码的版权所属。如:``也许你需要在自己的程序或文档中用到本书的代码,但除非大篇幅地使用,否则不必与我们联系取得授权。例如,用本书中的几段代码编写程序无需请求许可,blabla``。 +又比如,在我们看到的一些外版书籍上,如果拥有代码。那么作者一般就会在前言或者类似的位置里,指明书中代码的版权所属。如: + +> 也许你需要在自己的程序或文档中用到本书的代码,但除非大篇幅地使用,否则不必与我们联系取得授权。例如,用本书中的几段代码编写程序无需请求许可,blabla。 于是,选择一个合理的 LICENSE,就变成了一个有趣的话题。为此,笔者做了一个如何进行开源协议选型的流程图: diff --git a/github-roam.md b/github-roam.md index 1c39351..fe92c7d 100644 --- a/github-roam.md +++ b/github-roam.md @@ -162,7 +162,9 @@ ![License 使用情况](./img/permissive-vs-copylift-license-2.jpg) -又比如,在我们看到的一些外版书籍上,如果拥有代码。那么作者一般就会在前言或者类似的位置里,指明书中代码的版权所属。如:``也许你需要在自己的程序或文档中用到本书的代码,但除非大篇幅地使用,否则不必与我们联系取得授权。例如,用本书中的几段代码编写程序无需请求许可,blabla``。 +又比如,在我们看到的一些外版书籍上,如果拥有代码。那么作者一般就会在前言或者类似的位置里,指明书中代码的版权所属。如: + +> 也许你需要在自己的程序或文档中用到本书的代码,但除非大篇幅地使用,否则不必与我们联系取得授权。例如,用本书中的几段代码编写程序无需请求许可,blabla。 于是,选择一个合理的 LICENSE,就变成了一个有趣的话题。为此,笔者做了一个如何进行开源协议选型的流程图: diff --git a/index.html b/index.html index 547851b..f01cca4 100644 --- a/index.html +++ b/index.html @@ -368,7 +368,10 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
License 使用情况
License 使用情况
-

又比如,在我们看到的一些外版书籍上,如果拥有代码。那么作者一般就会在前言或者类似的位置里,指明书中代码的版权所属。如:也许你需要在自己的程序或文档中用到本书的代码,但除非大篇幅地使用,否则不必与我们联系取得授权。例如,用本书中的几段代码编写程序无需请求许可,blabla

+

又比如,在我们看到的一些外版书籍上,如果拥有代码。那么作者一般就会在前言或者类似的位置里,指明书中代码的版权所属。如:

+
+

也许你需要在自己的程序或文档中用到本书的代码,但除非大篇幅地使用,否则不必与我们联系取得授权。例如,用本书中的几段代码编写程序无需请求许可,blabla。

+

于是,选择一个合理的 LICENSE,就变成了一个有趣的话题。为此,笔者做了一个如何进行开源协议选型的流程图:

如何选择 License

简单地来说,这些 License 之间是一些权利的区别,如当你把代码放置到公有领域,就意味着任何人可以修改,并且不需要标明出注;可如果你想要别人标明出处及作者,你就需要 MIT 协议;而你希望别人闭源的话,那么你就需要 MPL 协议等等。

@@ -737,16 +740,16 @@ git push -u origin master

本地测试都通过了,于是我们添加了Travis-CI来跑我们的测试

CI

虽然node.js不算是一门语言,但是因为我们用的node,下面的是一个简单的.travis.yml示例:

-
language: node_js
+
language: node_js
 node_js:
     - "0.10"
 
 notifications:
-    email: false
+    email: false
 
-before_install: npm install -g grunt-cli
-install: npm install
-after_success: CODECLIMATE_REPO_TOKEN=321480822fc37deb0de70a11931b4cb6a2a3cc411680e8f4569936ac8ffbb0ab codeclimate < coverage/lcov.info
+before_install: npm install -g grunt-cli +install: npm install +after_success: CODECLIMATE_REPO_TOKEN=321480822fc37deb0de70a11931b4cb6a2a3cc411680e8f4569936ac8ffbb0ab codeclimate < coverage/lcov.info

代码来源: https://github.com/phodal/lettuce

我们把这些集成到README.md之后,就有了之前那张图。

CI对于一个开发者在不同城市开发同一项目上来说是很重要的,这意味着当你添加的部分功能有测试覆盖的时候,项目代码会更加强壮。

@@ -887,12 +890,12 @@ git push -u origin master

当然函数也是一个对象。

自动化测试

一直习惯用Travis CI,于是也继续用Travis Ci,.travis.yml配置如下所示:

-
language: node_js
+
language: node_js
 node_js:
   - "0.10"
 
 notifications:
-  email: false
+  email: false
 
 branches:
   only:
@@ -1409,16 +1412,16 @@ str = tableHandler(str编写测试->功能代码->修改测试->重构

上次在和buddy聊天的时候,才知道测试在功能简单的时候是后行的,在功能复杂不知道怎么下手的时候是先行的。

开始之前请原谅我对于Java语言的一些无知,然后,看一下我写的Main函数:

-
package com.phodal.learing;
+
package com.phodal.learing;
 
 public class Main {
 
-    public static void main(String[] args) {
+    public static void main(String[] args) {
         int c=new Cal().add(1,2);
         int d=new Cal2().sub(2,1);
-        System.out.println("Hello,s");
-        System.out.println(c);
-        System.out.println(d);
+        System.out.println("Hello,s");
+        System.out.println(c);
+        System.out.println(d);
     }
 }

代码写得还好(自我感觉),先不管Cal和Cal2两个类。大部分都能看懂,除了c,d不知道他们表达的是什么意思,于是。

@@ -1430,16 +1433,16 @@ str = tableHandler(str把光标移到int d中的d,按下shift+f6,输入result_sub

于是就有

-
package com.phodal.learing;
+
package com.phodal.learing;
 
 public class Main {
 
-    public static void main(String[] args) {
+    public static void main(String[] args) {
         int result_add=new Cal().add(1,2);
         int result_sub=new Cal2().sub(2,1);
-        System.out.println("Hello,s");
-        System.out.println(result_add);
-        System.out.println(result_sub);
+        System.out.println("Hello,s");
+        System.out.println(result_add);
+        System.out.println(result_sub);
     }
 }

Extract Method

@@ -1451,16 +1454,16 @@ str = tableHandler(str在弹出的窗口中输入mprint

于是有了

-
public static void main(String[] args) {
+
public static void main(String[] args) {
     int result_add=new Cal().add(1,2);
     int result_sub=new Cal2().sub(2,1);
-    System.out.println("Hello,s");
+    System.out.println("Hello,s");
     mprint(result_add);
     mprint(result_sub);
 }
 
 private static void mprint(int result_sub) {
-    System.out.println(result_sub);
+    System.out.println(result_sub);
 }

似乎我们不应该这样对待System.out.println,那么让我们内联回去

Inline Method

@@ -1472,12 +1475,12 @@ str = tableHandler(str选中Inline all invocations and remove the method(2 occurrences) 点确定

然后我们等于什么也没有做了~~:

-
public static void main(String[] args) {
+
public static void main(String[] args) {
     int result_add=new Cal().add(1,2);
     int result_sub=new Cal2().sub(2,1);
-    System.out.println("Hello,s");
-    System.out.println(result_add);
-    System.out.println(result_sub);
+    System.out.println("Hello,s");
+    System.out.println(result_add);
+    System.out.println(result_sub);
 }

似乎这个例子不是很好,但是够用来说明了。

Pull Members Up

@@ -1517,7 +1520,7 @@ str = tableHandler(str重构之前

过多的临时变量会让我们写出更长的函数,函数不应该太多,以便使功能单一。这也是重构的另外的目的所在,只有函数专注于其功能,才会更容易读懂。

以书中的代码为例

-
import java.lang.System;
+
import java.lang.System;
 
 public class replaceTemp {
     public void count() {
@@ -1535,7 +1538,7 @@ str = tableHandler(str
Replace Temp With Query

便会返回

-
import java.lang.System;
+
import java.lang.System;
 
 public class replaceTemp {
     public void count() {
@@ -1562,9 +1565,9 @@ str = tableHandler(str
public class replaceTemp {
 
     public void method() {
-        String str = "str";
-        String aString = returnString().concat(str);
-        System.out.println(aString);
+        String str = "str";
+        String aString = returnString().concat(str);
+        System.out.println(aString);
     }
 
 }
@@ -1599,9 +1602,9 @@ public class replaceTemp { return res.end('Unauthorized'); }

可是除了HTTP协议,还有MQTT和CoAP。对于MQTT协议来说,那还算好,毕竟自带授权,如:

-
mosquitto_pub -u root -P root -h localhost -d -t lettuce -m "Hello, MQTT. This is my first message."
+
mosquitto_pub -u root -P root -h localhost -d -t lettuce -m "Hello, MQTT. This is my first message."

便可以让我们简单地完成这个功能,然而有的协议是没有这样的功能如CoAP协议中是用Option来进行授权的。现在的工具如libcoap只能有如下的简单功能

-
coap-client -m get coap://127.0.0.1:5683/topics/zero -T
+
coap-client -m get coap://127.0.0.1:5683/topics/zero -T

于是,先写了个测试脚本来验证功能。

var coap     = require('coap');
 var request  = coap.request;
@@ -2004,7 +2007,7 @@ Set up your git name and email, this is important so that your commits can be id
 

2014年1月1日零时到一时,用户在github上的操作,这里的用户指的是很多。。一共有4814条数据,从commit、create到issues都有。

数据解析

import json
-for line in open(jsonfile):
+for line in open(jsonfile):
     line = f.readline()

然后再解析json

import dateutil.parser
@@ -2017,23 +2020,23 @@ date = dateutil.parser.parse(lin["
     dataarray = []
     datacount = 0
 
-    for line in open(jsonfile):
+    for line in open(jsonfile):
         line = f.readline()
         lin = json.loads(line)
         date = dateutil.parser.parse(lin["created_at"])
         datacount += 1
         dataarray.append(date.minute)
 
-    minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
+    minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
     f.close()
     return minuteswithcount

下面这句代码就是将上面的解析为

-
minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
+
minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]

这样的数组以便于解析

[(0, 92), (1, 67), (2, 86), (3, 73), (4, 76), (5, 67), (6, 61), (7, 71), (8, 62), (9, 71), (10, 70), (11, 79), (12, 62), (13, 67), (14, 76), (15, 67), (16, 74), (17, 48), (18, 78), (19, 73), (20, 89), (21, 62), (22, 74), (23, 61), (24, 71), (25, 49), (26, 59), (27, 59), (28, 58), (29, 74), (30, 69), (31, 59), (32, 89), (33, 67), (34, 66), (35, 77), (36, 64), (37, 71), (38, 75), (39, 66), (40, 62), (41, 77), (42, 82), (43, 95), (44, 77), (45, 65), (46, 59), (47, 60), (48, 54), (49, 66), (50, 74), (51, 61), (52, 71), (53, 90), (54, 64), (55, 67), (56, 67), (57, 55), (58, 68), (59, 91)]

Matplotlib

开始之前需要安装``matplotlib

-
sudo pip install matplotlib
+
sudo pip install matplotlib

然后引入这个库

  import matplotlib.pyplot as plt

如上面的那个结果,只需要

@@ -2059,14 +2062,14 @@ date = dateutil.parser.parse(lin[" dataarray = [] datacount = 0 - for line in open(jsonfile): + for line in open(jsonfile): line = f.readline() lin = json.loads(line) date = dateutil.parser.parse(lin["created_at"]) datacount += 1 dataarray.append(date.minute) - minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)] + minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)] f.close() return minuteswithcount @@ -2075,7 +2078,7 @@ date = dateutil.parser.parse(lin[" x = [] y = [] mwcs = parse_data(files) - for mwc in mwcs: + for mwc in mwcs: x.append(mwc[0]) y.append(mwc[1]) @@ -2129,7 +2132,7 @@ draw_date("data/2014-01-01-0.json")
重写了一个新的方法用于计算提交数,直至后面才意识到其实我们可以算行数就够了,但是方法上有点hack

def get_minutes_counts_with_id(jsonfile):
     datacount, dataarray = handle_json(jsonfile)
-    minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
+    minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
     return minuteswithcount
 
 
@@ -2138,7 +2141,7 @@ draw_date("data/2014-01-01-0.json")= []
     datacount = 0
 
-    for line in open(jsonfile):
+    for line in open(jsonfile):
         line = f.readline()
         lin = json.loads(line)
         date = dateutil.parser.parse(lin["created_at"])
@@ -2160,7 +2163,7 @@ draw_date("data/2014-01-01-0.json")    :rtype : object
     """
     monthdaycount = []
-    for i in range(1, 20):
+    for i in range(1, 20):
         if i < 10:
             filename = 'data/2014-02-0' + i.__str__() + '-0.json'
         else:
@@ -2195,43 +2198,43 @@ draw_date("data/2014-01-01-0.json")= 0
     userinfo = []
     condition = 'select * from userinfo where owener = \'' + str(username) + '\''
-    for zero in c.execute(condition):
+    for zero in c.execute(condition):
         count += 1
         userinfo.append(zero)
 
     return count, userinfo

当我查询gmszone的时候,也就是我自己就会有如下的结果

-
(u'gmszone', u'ForkEvent', u'RESUME', u'TeX', u'https://github.com/gmszone/RESUME')
-(u'gmszone', u'WatchEvent', u'iot-dashboard', u'JavaScript', u'https://github.com/gmszone/iot-dashboard')
-(u'gmszone', u'PushEvent', u'wechat-wordpress', u'Ruby', u'https://github.com/gmszone/wechat-wordpress')
-(u'gmszone', u'WatchEvent', u'iot', u'JavaScript', u'https://github.com/gmszone/iot')
-(u'gmszone', u'CreateEvent', u'iot-doc', u'None', u'https://github.com/gmszone/iot-doc')
-(u'gmszone', u'CreateEvent', u'iot-doc', u'None', u'https://github.com/gmszone/iot-doc')
-(u'gmszone', u'PushEvent', u'iot-doc', u'TeX', u'https://github.com/gmszone/iot-doc')
-(u'gmszone', u'PushEvent', u'iot-doc', u'TeX', u'https://github.com/gmszone/iot-doc')
-(u'gmszone', u'PushEvent', u'iot-doc', u'TeX', u'https://github.com/gmszone/iot-doc')
-109
+
(u'gmszone', u'ForkEvent', u'RESUME', u'TeX', u'https://github.com/gmszone/RESUME')
+(u'gmszone', u'WatchEvent', u'iot-dashboard', u'JavaScript', u'https://github.com/gmszone/iot-dashboard')
+(u'gmszone', u'PushEvent', u'wechat-wordpress', u'Ruby', u'https://github.com/gmszone/wechat-wordpress')
+(u'gmszone', u'WatchEvent', u'iot', u'JavaScript', u'https://github.com/gmszone/iot')
+(u'gmszone', u'CreateEvent', u'iot-doc', u'None', u'https://github.com/gmszone/iot-doc')
+(u'gmszone', u'CreateEvent', u'iot-doc', u'None', u'https://github.com/gmszone/iot-doc')
+(u'gmszone', u'PushEvent', u'iot-doc', u'TeX', u'https://github.com/gmszone/iot-doc')
+(u'gmszone', u'PushEvent', u'iot-doc', u'TeX', u'https://github.com/gmszone/iot-doc')
+(u'gmszone', u'PushEvent', u'iot-doc', u'TeX', u'https://github.com/gmszone/iot-doc')
+109

一共有109个事件,有Watch,Create,Push,Fork还有其他的, 项目主要有iot,RESUME,iot-dashboard,wechat-wordpress, 接着就是语言了,Tex,Javascript,Ruby,接着就是项目的url了。

值得注意的是。

-
-rw-r--r--   1 fdhuang staff 905M Apr 12 14:59 userdata.db
+
-rw-r--r--   1 fdhuang staff 905M Apr 12 14:59 userdata.db

这个数据库文件有905M,不过查询结果相当让人满意,至少相对于原来的结果来说。

Python自带了对SQLite3的支持,然而我们还需要安装SQLite3

-
brew install sqlite3
+
brew install sqlite3

或者是

-
sudo port install sqlite3
+
sudo port install sqlite3

或者是Ubuntu的

-
sudo apt-get install sqlite3
+
sudo apt-get install sqlite3

openSUSE自然就是

-
sudo zypper install sqlite3
+
sudo zypper install sqlite3

不过,用yast2也很不错,不是么。。

数据导入

需要注意的是这里是需要python2.7,起源于对gzip的上下文管理器的支持问题

def handle_gzip_file(filename):
     userinfo = []
     with gzip.GzipFile(filename) as f:
-        events = [line.decode("utf-8", errors="ignore") for line in f]
+        events = [line.decode("utf-8", errors="ignore") for line in f]
 
-        for n, line in enumerate(events):
+        for n, line in enumerate(events):
             try:
                 event = json.loads(line)
             except:
@@ -2240,7 +2243,7 @@ draw_date("data/2014-01-01-0.json")= event["actor"]
             attrs = event.get("actor_attributes", {})
-            if actor is None or attrs.get("type") != "User":
+            if actor is None or attrs.get("type") != "User":
                 continue
 
             key = actor.lower()
@@ -2260,15 +2263,15 @@ draw_date("data/2014-01-01-0.json")= 2014
     month = 3
 
-    for day in range(1,31):
+    for day in range(1,31):
         date_re = re.compile(r"([0-9]{4})-([0-9]{2})-([0-9]{2})-([0-9]+)\.json.gz")
 
         fn_template = os.path.join("march",
-                                   "{year}-{month:02d}-{day:02d}-{n}.json.gz")
+                                   "{year}-{month:02d}-{day:02d}-{n}.json.gz")
         kwargs = {"year": year, "month": month, "day": day, "n": "*"}
         filenames = glob.glob(fn_template.format(**kwargs))
 
-        for filename in filenames:
+        for filename in filenames:
             c.executemany('INSERT INTO userinfo VALUES (?,?,?,?,?)', handle_gzip_file(filename))
 
     conn.commit()
@@ -2294,11 +2297,11 @@ pipe = pipe = r.pipeline()
 pipe.zscore('osrc:user',"gmszone")
 pipe.execute()

系统返回了227.0,试试别人。

-
>>> pipe.zscore('osrc:user',"dfm")
-<redis.client.StrictPipeline object at 0x104fa7f50>
->>> pipe.execute()
-[425.0]
->>>
+
>>> pipe.zscore('osrc:user',"dfm")
+<redis.client.StrictPipeline object at 0x104fa7f50>
+>>> pipe.execute()
+[425.0]
+>>>

看看主要是在哪一天提交的

>>> pipe.hgetall('osrc:user:gmszone:day')
 <redis.client.StrictPipeline object at 0x104fa7f50>
@@ -2325,7 +2328,7 @@ pipe.execute()
r = redis.StrictRedis(host='localhost', port=6379, db=0) no_pipe = False - if pipe is None: + if pipe is None: pipe = pipe = r.pipeline() no_pipe = True @@ -2381,12 +2384,12 @@ pipe.execute()
points[0] = 1.0 / (total + 1) # Week means. - for k, v in results[1].iteritems(): + for k, v in results[1].iteritems(): points[1 + int(k)] = float(v) / total # Event types. n = 8 - for k, v in results[2]: + for k, v in results[2]: points[n + evttypes.index(k)] = float(v) / total # Number of contributions, connections and languages. @@ -2398,8 +2401,8 @@ pipe.execute()
# Top languages. n += 4 - for k, v in results[7]: - if k in langs: + for k, v in results[7]: + if k in langs: points[n + langs.index(k)] = float(v) / total else: # Unknown language.