• Posts tagged "package"

Blog Archives

发布gridgame游戏包

R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大。

R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,互联网….都在使用R语言。

要成为有理想的极客,我们不能停留在语法上,要掌握牢固的数学,概率,统计知识,同时还要有创新精神,把R语言发挥到各个领域。让我们一起动起来吧,开始R的极客理想。

关于作者:

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/r-game-gridgame/

gridgame

前言

为了能发布自己的游戏包,我们已经储备了很多的基础知识,包括 R语言面向对象编程、R包开发编程、R语言游戏编程 等,最后一步就到综合运用的时候了。按CRAN的R包发布的要求,把所有代码和文档串起来,就是我们要发布的gridgame游戏包。

目录

  1. 知识储备
  2. gridgame包开发
  3. gridgame包发布

1. 知识储备

在综合运用所有知识前,先回顾一下,我们都需要掌握哪些知识,1)R语言编程的基础是必需,2)游戏的算法主要是对矩阵的操作,线性代数最好也要掌握,3)游戏操作需要有界面,虽然不需要太好看,但我们也要有能力用代码画出游戏界面来,4)游戏的框架封装,对于相同类型的游戏,如果第二款游戏能延续第一款游戏的结构,不仅能简化开发节约时间,还能降低游戏技术门槛,就需要用面向对象的思维模式对游戏框架进行封装。

1.1 基础知识

上面列出的4个主要知识点,我都做技术准备,针对不同问题,参考不同文章就可以解决:

1.2 给R包起名

技术准备一切就绪,先给项目起个名字吧!

其实,起名也是有讲究的,不能太随便,虽然CRAN上面没有叫game包,但我们直接用game做为项目名字,也不是很好。如何起名最好先问问Google,找一个没有太多重名的关键字作为名字。

直接用google搜索 game 有 1,100,000,000 条结果,r game 有1,680,000,000条结果。我连0都数不过来了!和这么多搜索结果去竞争关键字,是我们在推广过程中不可逾越的鸿沟。

rgame-google

所以,换个名字让我们从小成长,找一个热度不是那么高的关键字,作为项目名字。gridgame就是一个不错的选择,既能表现游戏的特征,从推广角度又没有特别强大的竞争对手,一下子压力全无,倍感轻松!

gridgame-google

做好了各种准备工作,下面就是把gridgame包搞定了!

2. gridgame包开发

按照 在巨人的肩膀前行 催化R包开发 文章中介绍的标准化的开发流程,进行R包的开发。

本文的系统环境

  • Win7 64bit
  • R version 3.0.3 x86_64-w64-mingw32/x64 (64-bit)
  • Rtools31.exe
  • basic-miktex-2.9.5105.exe

由于有gridgame包开发的游戏都是基于Window平台的,而且我不打算支持Linux平台运行,所以我们的选择的R包开发环境,也应该是Window平台。后文中会介绍,为什么不支持Linux平台运行,R的版本最好也升级到3.0.3。(坑很多的,要一点一点填!)

2.1 构建工程

为了简化工作量,提高开发效率,我将按照devtools包的开发流程进行操作。

首先,打开一个项目目录,然后创建项目骨架。


~ cd /home/conan/R
~ R    

# 加载开发工具包
> library(devtools)
> library(roxygen2)
Loading required package: digest
> library(testthat)

# 创建项目骨架
> create(paste(getwd(),"/gridgame",sep=""))
Creating package gridgame in /home/conan/R
No DESCRIPTION found. Creating default:

Package: gridgame
Title:
Description:
Version: 0.1
Authors@R: # getOptions('devtools.desc.author')
Depends: R (>= 3.0.1)
License: # getOptions('devtools.desc.license')
LazyData: true

# 重置当前目录
> setwd(paste(getwd(),"/gridgame",sep=""))

# 查看项目骨架生成的文件
> dir(full.names=TRUE)
[1] "./DESCRIPTION" "./man"         "./R"

2.2 编写代码和文档

1). 编辑DESCRIPTION文件,增加项目的描述信息。


~ vi /home/conan/R/gridgame/DESCRIPTION

Package: gridgame
Type: Package
Title: A game framework for R
Version: 0.0.1
Date: 2014-07-23
Authors@R: c(person("Dan", "Zhang", email = "bsspirit@gmail.com", role
    =c("aut", "cre")))
Maintainer: Dan Zhang 
Description: This package provides a general-purpose game framework for grid game in R. The package includes 2 games about snake and 2048. You can run the function snake() or g2048() to startup the game. These games are only running on Window platform.
Depends:
    R (>= 3.0.1)
Imports:
    methods
License: GPL-3
URL: http://onbook.me/#/project/gridgame
BugReports: https://github.com/bsspirit/gridgame/issues
OS_type: windows
Collate:
    'game.R'
    '2048.R'
    'package.R'
    'snake.R'

DESCRIPTION文件中,有两个地方需要注意:

  • Imports: methods,由于我们用的是RC类型,系统默认会用methods包中的函数进行解析,必需在这里显示声明。
  • OS_type: windows,由于我们只仅支持Window系统运行,因此在后面上传到CRAN检查时,必需要指明支持的系统。同时,也是由于加了这个属性,再到Linux中执行R CMD check 过程的时候会自动失败,因此要求我们只能在windows系统中进行打包和发布的操作了。

2). 复制我们已经完成的3个R文件到 /home/conan/R/gridgame/R 目录下面。


~ ls -l
-rw-rw-r-- 1 conan conan 5030  7月 23 17:23 2048.R
-rw-rw-r-- 1 conan conan 2151  7月 23 17:18 game.R
-rw-rw-r-- 1 conan conan 5204  7月 23 17:23 snake.R

我们需要对代码进行再整理,都是检查失败错误。

  • 1. 去掉2048.R和snake.R代码中source()函数对game.R文件的引用。
  • 2. 去掉代码中所有中文注释,只能是ASCII码支持的字符。
  • 3. 在代码中增加Window平台检查,非Window则禁止运行,通过 .Platform$OS.type==’windows’ 代码,判断运行时的系统环境。
  • 4. 增加package.R文件,用于加载methods包的配置信息,#’ @import methods。
  • 5. 去掉代码中启动函数,启动交给用户来操作。

2.3 调试程序

在Windows系统开发环境中,通过load_all()函数加载程序包,然后运行一个snake()函数 或者 g2048()函数,一切正常。


# 加载程序包
> load_all(getwd())
Loading gridgame

# 启动snake游戏
> snake()

# 启动2048游戏
> g2048()

我们写的游戏程序,都是在window7下开发的,运行一切正常,那么为什么不支持在Linux系统中运行呢? 主要原因是 Linux和Window7有不同的图形设备输出。windows系统中,输出设备是通过.net框架来支持的;而Linux系统中的输出设备是X11()显示驱动支持,或者通过在Linux系统中加载第三方的tk设备支持,R语言通过tkrplot包来实现调用。


~ sudo apt-get install tk-dev
> install.packages("tkrplot")

Windows系统和Linux系统对于运行GUI程序是有区别的,无法统一用一套代码来完成。有人会说,每个地方都增加系统类型的判断条件,就能可实现了。

当然情况并不是这么简单,除了输出设备的问题以外,Linux上面还会遇到字体的问题,字库不全将导致字符加载失败的错误。下面的问题,Linux系统中没有helvetica的60号字体。


Error in text.default(0.5, 0.7, label = name, cex = 5) : 
  X11 font -adobe-helvetica-%s-%s-*-*-%d-*-*-*-*-*-*-*, face 1 at size 60 could not be loaded

虽然在Linux Ubuntu环境中,我尝试了安装所有字体库,仍然无法解决大号字体的加载问题。所以,我决定最终将不支持Linux平台。


~ sudo apt-get install xfont-100dpi xfont-75dpi xfont-cyrillic xfont-*

2.4 单元测试

在inst/test目录下面,我们分别针对不同的文件,创建单元测试类。

  • test-game.R, 对game.R的函数进行单元测试
  • test-snake.R,对snake.R的函数进行单元测试
  • test-2048.R,对2048.R的函数进行单元测试

以test-game.R为例,打开test-game.R文件


~ vi inst/test/test-game.R

context("game")

test_that("Initial the construct function of Game class", {
  name<-"R"
  width<-height<-10
  
  game<-Game$new()
  game$initFields(name=name,width=width,height=height)
  expect_that(game$name,equals(name))
  expect_that(game$width,equals(width))
  expect_that(game$height,equals(height))
})

执行单元测试代码。


> test(getwd())
Testing gridgame
Loading gridgame
game : ...

2.5 撰写文档

R包开发中最繁琐的一个过程,就是撰写文档,Latex的格式文档。幸好有人发明了roxygen2包,通过简单的注释规则来生成Latex文档。

我们用roxygen2包,来生成man/*.Rd的文档文件,对RC类型的程序,其实就可以偷点懒了,只是在类的定义上,增加注释就行了。RC类中方法的注释,就没强制的检查了。多写少写就看开发者的心情了。如果是S3的编程方式或者纯函数式的包,那么写文档也是一件很辛苦的工程呢。当然,文件不能出现中文字符,不然check过程的时候,还是会有警告发生的。

以snake.R文件中注释为例,我们只写setRefClass的注释 和 snake<-function(){}的注释就行了,Snake类的内部方法就省略了。


~ vi snake.R

#' Snake game class
#' @include game.R
Snake<-setRefClass("Snake",contains="Game",
   ...
)

#' Snake game function
#'
#' @export
snake<-function(){
  game<-Snake$new()
  game$initFields()
  game$run()
}

通过代码中的注释生成Latex文件。


> document(getwd())
Updating gridgame documentation
Loading gridgame
Writing G2048-class.Rd
Writing g2048.Rd
Writing Game-class.Rd
Writing Snake-class.Rd
Writing snake.Rd

打开snake.Rd文件,看看生成的内容。


~ vi man/snake.Rd

% Generated by roxygen2 (4.0.1): do not edit by hand
\name{snake}
\alias{snake}
\title{Snake game function}
\usage{
snake()
}
\description{
Snake game function
}

这一步的操作过程,其实也不是一帆风顺的。在引用roxygen2 包的时候,我同样遇到的问题了。
在Window环境中,roxygen2包 依赖于R 3.0.2以上的版本,R 3.0.1版本的R程序装不上roxygen2包。github有对这个强依赖问题的描述:https://github.com/klutometis/roxygen/issues/163

所以,上文中指定的R 3.0.3的版本环境,是实践检验出来的。

2.6 程序检查

程序检查,这一步其实是所有操作过程最容易出错的,而且还搞不定。R的打包的检查真的很严格啊!!

在Windows平台中开发R包,要装额外装两个软件 Rtools(http://cran.us.r-project.org/bin/windows/Rtools/) 和 MikTeX (http://www.miktex.org/download),不仅版本要和R语言环境对上,还要配置环境变量。MikTeX在调用过程中,还会遇到文件找不到,pdflatex.exe运行的错误 等等。

比如,其中的一个常见错误:


* checking PDF version of manual ... WARNING
LaTeX errors when creating PDF version.
This typically indicates Rd problems.
LaTeX errors found:
!pdfTeX error: pdflatex.EXE (file ts1-zi4r): Font ts1-zi4r at 540 not found
 ==> Fatal error occurred, no output PDF file produced!
* checking PDF version of manual without hyperrefs or index ... ERROR

解决方法,运行下面的命令。


~ updmap 
~ initexmf --update-fndb
~ initexmf --edit-config-file updmap

# 在文件中增加一行
Map zi4.map 

~ initexmf --mkmaps

最后,如果经过9*9=81难,终于修成正果,一路OK的完成了!


> check(getwd())
Updating gridgame documentation
Loading gridgame
Writing NAMESPACE
Writing G2048-class.Rd
Writing g2048.Rd
Writing Game-class.Rd
Writing Snake-class.Rd
Writing snake.Rd
"C:/PROGRA~1/R/R-30~1.3/bin/x64/R" --vanilla CMD build  \
  "D:\workspace\R\app\gridgame" --no-manual --no-resave-data

* checking for file 'D:\workspace\R\app\gridgame/DESCRIPTION' ... OK
* preparing 'gridgame':
* checking DESCRIPTION meta-information ... OK
* checking for LF line-endings in source and make files
* checking for empty or unneeded directories
* building 'gridgame_0.0.1.tar.gz'

"C:/PROGRA~1/R/R-30~1.3/bin/x64/R" --vanilla CMD check  \
  "C:\Users\ADMINI~1\AppData\Local\Temp\RtmponOeAc/gridgame_0.0.1.tar.gz"  \
  --timings

* using log directory 'C:/Users/ADMINI~1/AppData/Local/Temp/RtmponOeAc/gridgame.Rcheck'
* using R version 3.0.3 (2014-03-06)
* using platform: x86_64-w64-mingw32 (64-bit)
* using session charset: ASCII
* checking for file 'gridgame/DESCRIPTION' ... OK
* checking extension type ... Package
* this is package 'gridgame' version '0.0.1'
* checking package namespace information ... OK
* checking package dependencies ... OK
* checking if this is a source package ... OK
* checking if there is a namespace ... OK
* checking for executable files ... OK
* checking for hidden files and directories ... OK
* checking for portable file names ... OK
* checking whether package 'gridgame' can be installed ... OK
* checking installed package size ... OK
* checking package directory ... OK
* checking DESCRIPTION meta-information ... OK
* checking top-level files ... OK
* checking for left-over files ... OK
* checking index information ... OK
* checking package subdirectories ... OK
* checking R files for non-ASCII characters ... OK
* checking R files for syntax errors ... OK
* checking whether the package can be loaded ... OK
* checking whether the package can be loaded with stated dependencies ... OK
* checking whether the package can be unloaded cleanly ... OK
* checking whether the namespace can be loaded with stated dependencies ... OK
* checking whether the namespace can be unloaded cleanly ... OK
* checking loading without being on the library search path ... OK
* checking dependencies in R code ... OK
* checking S3 generic/method consistency ... OK
* checking replacement functions ... OK
* checking foreign function calls ... OK
* checking R code for possible problems ... OK
* checking Rd files ... OK
* checking Rd metadata ... OK
* checking Rd cross-references ... OK
* checking for missing documentation entries ... OK
* checking for code/documentation mismatches ... OK
* checking Rd \usage sections ... OK
* checking Rd contents ... OK
* checking for unstated dependencies in examples ... OK
* checking examples ... OK
* checking PDF version of manual ... OK

在执行check过程中,你的项目里可能会有其他的文件,检查也过不去的。你可新建一个文件.Rbuildignore,通过这个文件配置,可以忽略不希望参与打包的文件。


~ vi .Rbuildignore

.gitignore
dist
^.*\.Rproj$
^\.Rproj\.user$
README*
NEWS*
FAQ*

这样一些帮助文件,就能躲避检查了。

2.7 程序打包

在检查通过以后,我们就可以自由地打包了,用build命令。

我们可以选择2种打包方式,源代码打包和二进打包。

默认是给源代码打包。


> build()
"C:/PROGRA~1/R/R-30~1.3/bin/x64/R" --vanilla CMD build  \
  "D:\workspace\R\app\gridgame" --no-manual --no-resave-data

* checking for file 'D:\workspace\R\app\gridgame/DESCRIPTION' ... OK
* preparing 'gridgame':
* checking DESCRIPTION meta-information ... OK
* checking for LF line-endings in source and make files
* checking for empty or unneeded directories
* building 'gridgame_0.0.2.tar.gz'

[1] "D:/workspace/R/app/gridgame_0.0.2.tar.gz"

二进制打包


> build(binary=TRUE)
"C:/PROGRA~1/R/R-30~1.3/bin/x64/R" --vanilla CMD INSTALL  \
  "D:\workspace\R\app\gridgame" --build

* installing to library 'C:/Users/Administrator/AppData/Local/Temp/RtmpI3hhpp'
* installing *source* package 'gridgame' ...
** R
** inst
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
*** arch - i386
*** arch - x64
* MD5 sums
packaged installation of 'gridgame' as gridgame_0.0.2.zip
* DONE (gridgame)
[1] "D:/workspace/R/app/gridgame_0.0.2.zip"

这两个文件都可以用出来发布项目,用户下载后可以直接进行安装。


# 安装命令
~ R CMD INSTALL gridgame_0.0.2.tar.gz
* installing to library 'C:/Users/Administrator/R/win-library/3.0'
* installing *source* package 'gridgame' ...
** R
** inst
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
*** arch - i386
*** arch - x64
* DONE (gridgame)

3. gridgame包发布

最后一步,就是把我的好不容易开发的包,发布到资源库。有3个地方可以发布。

  • CRAN:R的官方发布平台
  • R-Forge:R-Forge发布平台
  • RForge:RForge发布平台
  • Github:个人开源发布平台

3.1 Github:个人的开源发布平台

在Github上发布是最容易的,只要把项目代码上传到Github就完成了,都不需要做check()检查。基于Github的包管理工具是devtools包,我把gridgame项目已上传到Github, 项目地址是:https://github.com/bsspirit/gridgame,用户可以下面两种方式,直接从Github安装gridgame项目。

方法一:使用devtools包,二进制安装。


library(devtools)
install_github("gridgame","bsspirit")

方法二:通过源代码安装。


git clone https://github.com/bsspirit/gridgame.git
R CMD BUILD gridgame
R CMD INSTALL gridgame_*.tar.gz

3.2 R-Forge:R-Forge发布平台

在R-Forge(https://r-forge.r-project.org/)发布,就比较麻烦了,你需要先注册一个账号,https://r-forge.r-project.org/account/register.php,登陆后,再新建一个项目,需要等72小时审核才能通过。

在R-Forge中,gridgame项目管理界面截图
rfroge1

然后,通过SVN把项目的源代码提交上去。我用习惯了Git进行版本管理,再用回SVN感觉好老土啊!

在RForge提交代码,并运行通过以后,你会有项目介绍页:http://gridgame.r-forge.r-project.org/,别个会看到介绍,下载你的包。

rfroge2

用户可以直接查看项目信息 http://gridgame.r-forge.r-project.org/,也可以在线查看项目源代码,https://r-forge.r-project.org/scm/viewvc.php/?root=gridgame,R-Froge平台会每天自动打包一次。

3.3 RForge:RForge发布平台

此RForge(http://rforge.net/)非R-Froge,竟然两个名字如此之近似,第一次用的人肯定会混的。首先注册RForge账号,同时注册一个要发布的项目。gridgame项目,我已经上传到Github了,这边能直接导入Github项目,就非常方便了。

rfroge

通过RForge源下载gridgame包,可以直接用install.packages()函数。


install.packages('gridgame', repos = 'http://rforge.net')  # 未发布成功,请先用Github的方案

3.4 CRAN发布:R的官方发布平台

这4个发布平台,CRAN是最全威的、是官方的,也不是那么容易发布的,有很严格的审查机制。CRAN发布条款:http://cran.r-project.org/web/packages/policies.html

我们明白政策后,通过 http://cran.r-project.org/submit.html 提交项目,大概要等待48小时审查。可能我这个包的问题比较严重6个小时内有就了回复。

  • 第一次不合格:没有标出只支持Window平台,对应DESCRIPTION文件中OS_type: windows。(当然,他是不会告诉你怎么改的,找自己Google找)
  • 第二次不合格:Linux平台R CMD check出错。(加了OS_type后,Linux执行当然会出错了,老外似乎也晕了。)
  • 第三次不合格:为什么Linux不能用,为什么用.Platform$OS.type的代码检查,getGraphicsEvent在没有GUI的环境中怎么办,文档不全,对game framework的定义不清楚。(费了好大劲的解释,把这几篇文章的设计理念,写了封总结的邮件。)
  • 第四次不合格:这次Uwe Ligges的态度很强硬,必须把Rd写完整,必须支持至少2个平台,必须对getGraphicsEvent进行检查,必须处理OS.type的代码问题,没有商量的余地,不搞定就不发包。(我真是悲剧了,看来发布项目,又要延迟一周了。)

下面是,提交项目到CRAN过程。

第一步:填写用户基本信息,并上传打好的tar.gz包
cran1

第二步:核对DESCRIPTION文件中的描述,与网页自动解析的内容是否一致。
cran2

第三步:等待审核。
cran3

第一次不合格,老外回复的邮件:


On 25/07/2014 04:24, Dan Zhang wrote:
> [This was generated from CRAN.R-project.org/submit.html]
>
> The following package was uploaded to CRAN:
> ===========================================
>
> Package Information:
> Package: gridgame
> Version: 0.0.1
> Title: A game framework for R
> Author(s): Dan Zhang [aut, cre]
> Maintainer: Dan Zhang 
> Depends: R (>= 3.0.1)
> Description: This package provides a general-purpose game framework for
 
'This package provides' is redundant.
 
>    grid game in R. The package includes 2 games about snake and
>    2048. You can run the function snake() or g2048() to startup
>    the game. These games are only running on Window platform.
 
Eh?  The CRAN policies do not allow such a package, and you have not
marked this as Windows-only.
> License: GPL-3
> Imports: methods
>
>
> The maintainer confirms that he or she
> has read and agrees to the CRAN policies.
>
> Submitter's comment: This package provides a general-purpose game
>    framework for grid game in R. The package includes 2
>    games about snake and 2048. You can run the function
>    snake() or g2048() to startup the game. These games
>    are only running on Window platform.
>

--
Brian D. Ripley,                  ripley@stats.ox.ac.uk
Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/
University of Oxford,             Tel:  +44 1865 272861 (self)
1 South Parks Road,                     +44 1865 272866 (PA)
Oxford OX1 3TG, UK                Fax:  +44 1865 272595

经过多次的对决和修改,终于把包成功发布到了CRAN。

同学们可以直接下载使用了。


# 从CRAN下载gridgame包
install.packages('gridgame')  # 未发布成功,请先用Github的方案

# 加载gridgame包
library(gridgame)

# 启动贪食蛇游戏
snake()

# 启动2048游戏
g2048()

到CRAN上发布一个R包,真是不一件轻松的事情啊。坚持,修改,打磨,再坚持,虽然过程很痛苦,但是软件质量最终得到了保证,这就是CRAN严格审查的意义。

转载请注明出处:
http://blog.fens.me/r-game-gridgame/

打赏作者

快速创建基于npm的nodejs库

从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发。Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎。chrome浏览器就基于V8,同时打开20-30个网页都很流畅。Nodejs标准的web开发框架Express,可以帮助我们迅速建立web站点,比起PHP的开发效率更高,而且学习曲线更低。非常适合小型网站,个性化网站,我们自己的Geek网站!!

关于作者

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/nodejs-npm-package

nodejs-npm

前言

用Node实现的功能越来越多,代码越来越复杂,我们就开始考虑如何把代码从项目中抽出来,形成单独的类库(模块)管理。就像我们所依赖其他第三方类库一样。

本文将介绍如何定义开发一个类库,包括命令开发,发布到npm中,让其他人也可以使用。

目录

  1. npm是什么?
  2. 快速创建包
  3. 创建命令行工具
  4. 本地安装lowercase包
  5. 项目上传到github
  6. 通过npm发布包
  7. 通过npm安装包

1. npm是什么?

NPM的全称是,是一个NodeJS包管理和分发工具,已经成为了非官方的发布Node模块的标准。

Nodejs自身提供了基本的模块,但是开发实际应用过程中仅仅依靠这些基本模块则还需要较多的工作。幸运的是,Nodejs库和框架为我们提供了帮助,让我们减少工作量。但是成百上千的库或者框架管理起来又很麻烦,有了NPM,可以很快的找到特定服务要使用的包,进行下载、安装以及管理已经安装的包。

类似于Java中的Maven,Ubuntu中的apt-get, Ruby中的Gem, Python中pypi等…

NPM模块发布页:https://npmjs.org/

2. 快速创建包

项目描述:读取文件,把所有的大写文字转换成小写文字,控制台输出。

系统环境:

  • win7 64bit
  • Nodejs:v0.10.5
  • Npm:1.2.19

创建项目


~ D:\workspace\javascript>mkdir nodejs-package && cd nodejs-package

创建项目结构


~ D:\workspace\javascript\nodejs-package>mkdir bin
~ D:\workspace\javascript\nodejs-package>touch bin/lowercase
~ D:\workspace\javascript\nodejs-package>touch bin/lowercase.bat
~ D:\workspace\javascript\nodejs-package>mkdir test
~ D:\workspace\javascript\nodejs-package>mkdir test/data
~ D:\workspace\javascript\nodejs-package>touch test/data/sample.txt
~ D:\workspace\javascript\nodejs-package>touch lowercase.js
~ D:\workspace\javascript\nodejs-package>touch example.js
~ D:\workspace\javascript\nodejs-package>touch README.md

nodejs-package-folder

项目结构说明

  • bin目录: 用于存放命令的目录
  • bin/lowercase文件: Linux命令行可执行文件
  • bin/lowercase.bat文件: Win命令行可执行文件
  • test目录: 用于存放测试代码的目录
  • test/data目录: 用于存放测试数据的目录
  • test/data/sample.txt: 测试数据文件
  • lowercase.js文件: 核心功能代码文件
  • example.js文件: 例子代码文件
  • package.json文件: 项目描述及依赖文件
  • README.md文件: 项目说明文件

1). 创建文件:package.json


~ D:\workspace\javascript\nodejs-package>npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sane defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install  --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (nodejs-package) lowercase
version: (0.0.0) 0.0.1
description: A demo package
entry point: (index.js)
test command:
git repository:
keywords:
author: Conan Zhang
license: (BSD) MIT
About to write to D:\workspace\javascript\nodejs-package\package.json:

{
  "name": "lowercase",
  "version": "0.0.1",
  "description": "A demo package",
  "main": "index.js",
  "directories": {
    "test": "test"
  },
  "dependencies": {
    "moment": "~2.4.0"
  },
  "devDependencies": {},
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": "",
  "author": "Conan Zhang",
  "license": "MIT",
  "readmeFilename": "README.md"
}

Is this ok? (yes) yes
npm WARN package.json lowercase@0.0.1 No readme data!

修改文件:package.json


~ vi package.json

{
    "name": "lowercase_demo",
    "version": "0.0.1",
    "description": "A demo package of lowercase",
    "keywords":[
        "demo","lowercase"
    ],
    "author": "Conan Zhang  (http://blog.fens.me)",
    "license": "MIT",
    "main": "lowercase.js",
    "repository": {
        "type":"git",
        "url":"https://github.com/bsspirit/lowercase_demo"
    },
    "engines": {
        "node": ">=v0.10.5"
    },
    "readmeFilename": "README.md"
}

2). 编辑文件:lowercase.js


~ vi lowercase.js

"use strict"
var fs = require('fs');

exports.lowerCase = function (myfile) {
    console.log(myfile);

    if (fs.existsSync(myfile)) {
        var content = fs.readFileSync(myfile, 'utf8');
        console.log(content.toLowerCase());
    } else {
        console.log("File does not exist - " + myfile);
    }
}

3). 编辑文件:example.js


~ vi example

"use strict"

var lowercase = require('./lowercase.js');
var myfile="test/data/sample.txt"
lowercase.lowerCase(myfile);

4). 编辑文件:test/data/sample.txt


~ vi sample.txt

JAVA
NODEJS
PYTHON
PHP
.NET
R
RUBY
C
C++
GO

5). 运行:example.js


~ D:\workspace\javascript\nodejs-package>node example.js
test/data/sample.txt
java
nodejs
python
php
.net
r
ruby
c
c++
go

6). 编辑文件:README.md


~ vi README.md

lowercase
========================

A demo package of lowercase

```{bash}
npm install lowercase_demo
```

## author

Conan Zhang, http://blog.fens.me

## License

MIT

3. 创建命令行工具

1). 编辑文件:bin/lowercase


~ vi lowercase

#!/usr/bin/env node

var myfile = process.argv.slice(2);

var path = require('path');
var fs = require('fs');
var dir = path.dirname(fs.realpathSync(__filename))+"/../";
require(dir+'lowercase.js').lowerCase(dir+myfile);

2). 编辑文件:bin/lowercase.bat


~ vi lowercase.bat

node.exe bin/lowercase %1

3). 运行lowercase.bat


~ D:\workspace\javascript\nodejs-package>bin\lowercase.bat test\data\sample.txt

D:\workspace\javascript\nodejs-package>node.exe bin/lowercase test\data\sample.txt
D:\workspace\javascript\nodejs-package\bin/../test\data\sample.txt
java
nodejs
python
php
.net
r
ruby
c
c++
go

4. 本地安装lowercase包

新建项目,并安装lowercase依赖库


~ D:\workspace\javascript>mkdir nodejs-package-project && cd nodejs-package-project
~ D:\workspace\javascript\nodejs-package-project>npm install ..\nodejs-package
lowercase_demo@0.0.1 node_modules\lowercase_demo

nodejs-package-project

新建运行文件:app.js


~ vi app.js

var lowercase = require('lowercase_demo');
var myfile="data.txt"
lowercase.lowerCase(myfile);

数据文件: data.txt


~ vi data.txt

APP
BACCDADDS

运行app.js


~ D:\workspace\javascript\nodejs-package-project>node app.js
data.txt
app
baccdadds

5. 项目上传到github

把lowercase_demo库,上传到github。


~ git init
~ git add .
~ git commit -m 'init'
~ git remote add origin git@github.com:bsspirit/lowercase_demo.git
~ git push origin master

项目github地址:https://github.com/bsspirit/lowercase_demo

注:大家可以基于这个demo项目基础上,继续完成包的开发。

5. 通过npm发布包

在npm上,注册新用户


~ D:\workspace\javascript\nodejs-package>npm adduser
Username: bsspirit
Password:
Email: bsspirit@gmail.com
npm http PUT https://registry.npmjs.org/-/user/org.couchdb.user:bsspirit
npm http 409 https://registry.npmjs.org/-/user/org.couchdb.user:bsspirit
npm http GET https://registry.npmjs.org/-/user/org.couchdb.user:bsspirit
npm http 200 https://registry.npmjs.org/-/user/org.couchdb.user:bsspirit
npm http PUT https://registry.npmjs.org/-/user/org.couchdb.user:bsspirit/-rev/2-25eae797548e61
npm http 201 https://registry.npmjs.org/-/user/org.couchdb.user:bsspirit/-rev/2-25eae797548e61

在npm上,发布项目


~ D:\workspace\javascript\nodejs-package>npm publish
npm http PUT https://registry.npmjs.org/lowercase_demo
npm http 201 https://registry.npmjs.org/lowercase_demo
npm http GET https://registry.npmjs.org/lowercase_demo
npm http 200 https://registry.npmjs.org/lowercase_demo
npm http PUT https://registry.npmjs.org/lowercase_demo/-/lowercase_demo-0.0.1.tgz/-rev/1-162a1
e
npm http 201 https://registry.npmjs.org/lowercase_demo/-/lowercase_demo-0.0.1.tgz/-rev/1-162a1
e
npm http PUT https://registry.npmjs.org/lowercase_demo/0.0.1/-tag/latest
npm http 201 https://registry.npmjs.org/lowercase_demo/0.0.1/-tag/latest
+ lowercase_demo@0.0.1

6. 通过npm安装

通过npm下载安装


~ D:\workspace\javascript>mkdir nodejs-package-project2 && cd nodejs-package-project2
~ D:\workspace\javascript\nodejs-package-project2>npm install lowercase_demo
npm http GET https://registry.npmjs.org/lowercase_demo
npm http 200 https://registry.npmjs.org/lowercase_demo
lowercase_demo@0.0.1 node_modules\lowercase_demo

全局安装lowercase_demo


~ D:\workspace\javascript\nodejs-package-project2>npm install lowercase_demo -g
npm http GET https://registry.npmjs.org/lowercase_demo
npm http 304 https://registry.npmjs.org/lowercase_demo
D:\toolkit\nodejs\lowercase -> D:\toolkit\nodejs\node_modules\lowercase_demo\bin\lowercase
npm ERR! peerinvalid The package generator-karma does not satisfy its siblings' peerDependenci
npm ERR! peerinvalid Peer generator-angular@0.4.0 wants generator-karma@~0.5.0

npm ERR! System Windows_NT 6.1.7601
npm ERR! command "D:\\toolkit\\nodejs\\\\node.exe" "D:\\toolkit\\nodejs\\node_modules\\npm\\bi
lowercase_demo" "-g"
npm ERR! cwd D:\workspace\javascript\nodejs-package-project2
npm ERR! node -v v0.10.5
npm ERR! npm -v 1.2.19
npm ERR! code EPEERINVALID
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR!     D:\workspace\javascript\nodejs-package-project2\npm-debug.log
npm ERR! not ok code 0

错误不是lowercase_demo的,没有关系。

执行全局命令:lowercase


~ D:\workspace\javascript\nodejs-package-project2>lowercase test\data\sample.txt
D:\toolkit\nodejs\node_modules\lowercase_demo\bin/../test\data\sample.txt
java
nodejs
python
php
.net
r
ruby
c
c++
go

注: 关于命令lowercase,因为代码中定义的是相对目录,所以只能访问D:\toolkit\nodejs\node_modules\lowercase_demo\目录的数据文件。

这样,我们自定义的lowercase_demo库,开发完成,发布到npm官方依赖管理,并且安装成功!整体流程走了一遍发现还是挺简单的。

你也来动手试试吧!

转载请注明出处:
http://blog.fens.me/nodejs-npm-package

打赏作者

开发自己的R包sayHello

R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大。

R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,互联网….都在使用R语言。

要成为有理想的极客,我们不能停留在语法上,要掌握牢固的数学,概率,统计知识,同时还要有创新精神,把R语言发挥到各个领域。让我们一起动起来吧,开始R的极客理想。

关于作者:

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/r-build-package/

r-package

前言
R是一个世界范围开发者共同协作的产物,至2013年2月共计近5000个包可在互联网上自由下载。现在作为R的使用者,有朝一日也可以成为R的开发者,把我们自己的知识做成R包分享给世界。

今天我们简单介绍如何开发自己R包。

目录

  1. 系统环境
  2. vi中制作R包
  3. RStudio中制作R包

1. 系统环境

操作系统:Linux Ubuntu 12.04.2 LTS 64bit
R语言版本:R 3.0.1


~ uname -a
Linux conan-deskop 3.5.0-23-generic #35~precise1-Ubuntu SMP Fri Jan 25 17:13:26 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

~ cat /etc/issue
Ubuntu 12.04.2 LTS \n \l

~ R --version
R version 3.0.1 (2013-05-16) -- "Good Sport"
Copyright (C) 2013 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under the terms of the
GNU General Public License versions 2 or 3.
For more information about these matters see
http://www.gnu.org/licenses/.

2. vi中制作R包

创建目录:/home/conan/R/demo


~ mkdir /home/conan/R/demo
~ cd /home/conan/R/demo

新建R脚本sayHello.R


~ vi sayHello.R
sayHello<-function(name){
    print(paste("Hello",name))
}

自定义一个sayHello的函数,将作为自定义包的第一个函数。

启动R程序


~ R

#清空变量设置工作目录
rm(list=ls())
setwd("/home/conan/R/demo")

#通过sayHello的脚本生成开发包的骨架
package.skeleton(name="sayHello",code_files="/home/conan/R/demo/sayHello.R")
Creating directories ...
Creating DESCRIPTION ...
Creating NAMESPACE ...
Creating Read-and-delete-me ...
Copying code files ...
Making help files ...
Done.
Further steps are described in './sayHello/Read-and-delete-me'.

#退出R的客户端
q()

在当前目录生成sayHello目录


~ ls -l
drwxrwxr-x 4 conan conan 4096  8月  1 15:07 sayHello
-rw-rw-r-- 1 conan conan   59  8月  1 15:04 sayHello.R

~ ls -l sayHello
-rw-rw-r-- 1 conan conan  281  8月  1 15:07 DESCRIPTION
drwxrwxr-x 2 conan conan 4096  8月  1 15:07 man
-rw-rw-r-- 1 conan conan   31  8月  1 15:07 NAMESPACE
drwxrwxr-x 2 conan conan 4096  8月  1 15:07 R
-rw-rw-r-- 1 conan conan  420  8月  1 15:07 Read-and-delete-me

~ ls -l sayHello/man
-rw-rw-r-- 1 conan conan 1043  8月  1 15:07 sayHello-package.Rd
-rw-rw-r-- 1 conan conan 1278  8月  1 15:07 sayHello.Rd

~ ls -l sayHello/R
-rw-rw-r-- 1 conan conan 59  8月  1 15:07 sayHello.R

文件及目录解释:

  • DESCRIPTION文件: 包描述文件
  • NAMESPACE文件: 包的命名空间文件
  • Read-and-delete-me文件: 说明文件,可以删除
  • man目录: 存放函数的说明文件的目录
  • R目录:存放源文件的目录
  • man/sayHello.Rd: sayHello函数的说明文件,latex语法,用来生成PDF文档
  • man/sayHello-package.Rd: sayHello包的说明文件,可以删除

编辑DESCRIPTION文件:

~ vi sayHello/DESCRIPTION
Package: sayHello
Type: Package
Title: R package demo for sayHello
LazyLoad: yes
Author: Dan Zhang
Maintainer: Dan Zhang
Description: This package provides a package demo
License: GPL
Version: 1.0
Date: 2013-07-31
Depends: R (>= 3.0.1)

编辑NAMESPACE文件:

~ vi sayHello/NAMESPACE
exportPattern("^[[:alpha:]]+")

编辑sayHello.Rd文件:

~ vi sayHello/man/sayHello.Rd
\name{sayHello}
\alias{sayHello}
\title{a sayHello function demo}
\description{
a sayHello function demo
}
\usage{
sayHello(name)
}
\arguments{
  \item{name}{a word}
}
\details{
nothing
}
\value{
no return
}
\references{
nothing
}
\author{
Dan Zhang
}
\note{
nothing
}
\seealso{
nothing
}
\examples{
sayHello("world")
}
\keyword{ sayHello }

删除文件:


~ rm sayHello/Read-and-delete-me
~ rm sayHello/man/sayHello-package.Rd

打包sayHello


~ R CMD build sayHello
* checking for file ‘sayHello/DESCRIPTION’ ... OK
* preparing ‘sayHello’:
* checking DESCRIPTION meta-information ... OK
* checking for LF line-endings in source and make files
* checking for empty or unneeded directories
* building ‘sayHello_1.0.tar.gz’

~ ls -l
drwxrwxr-x 4 conan conan 4096  8月  1 15:22 sayHello
-rw-r--r-- 1 conan conan  663  8月  1 15:24 sayHello_1.0.tar.gz
-rw-rw-r-- 1 conan conan   59  8月  1 15:04 sayHello.R

本地安装sayHello


~ R CMD INSTALL sayHello_1.0.tar.gz
* installing to library ‘/home/conan/R/x86_64-pc-linux-gnu-library/3.0’
* installing *source* package ‘sayHello’ ...
** R
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
* DONE (sayHello)

~ ls /home/conan/R/x86_64-pc-linux-gnu-library/3.0
bitops  digest  manipulate  rstudio  sayHello  XML

sayHello包,已经在当前账号下进行安装

使用sayHello函数


~ R

library(sayHello)
sayHello("Conan")
[1] "Hello Conan"

#查看sayHello文档
?sayHello

sayHello               package:sayHello                R Documentation

a sayHello function demo

Description:
     a sayHello function demo
Usage:
     sayHello(name)
Arguments:
    name: a word
Details:
     nothing
Value:
     no return
Note:
     nothing
Author(s):
     Dan Zhang
References:
     nothing

我们包已经成功制作完成!并在本地进行安装和使用!!

检查R包
如果要提交R包和CRAN,必须要执行check检查。如果有任何的error和warning都将不被通过。

退出R的客户端,回到命令行

先安装latex的依赖包(500mb+)


~ sudo apt-get install texlive
~ sudo apt-get install texlive-xetex
~ sudo apt-get install texlive-latex-base
~ sudo apt-get install texlive-fonts-extra 
~ sudo apt-get install texlive-latex-recommended
~ sudo apt-get install texlive-fonts-recommended

执行check


~ R CMD check sayHello_1.0.tar.gz

* using log directory ‘/home/conan/R/demo/sayHello.Rcheck’
* using R version 3.0.1 (2013-05-16)
* using platform: x86_64-pc-linux-gnu (64-bit)
* using session charset: UTF-8
* checking for file ‘sayHello/DESCRIPTION’ ... OK
* checking extension type ... Package
* this is package ‘sayHello’ version ‘1.0’
* checking package namespace information ... OK
* checking package dependencies ... OK
* checking if this is a source package ... OK
* checking if there is a namespace ... OK
* checking for executable files ... OK
* checking for hidden files and directories ... OK
* checking for portable file names ... OK
* checking for sufficient/correct file permissions ... OK
* checking whether package ‘sayHello’ can be installed ... OK
* checking installed package size ... OK
* checking package directory ... OK
* checking DESCRIPTION meta-information ... OK
* checking top-level files ... OK
* checking for left-over files ... OK
* checking index information ... OK
* checking package subdirectories ... OK
* checking R files for non-ASCII characters ... OK
* checking R files for syntax errors ... OK
* checking whether the package can be loaded ... OK
* checking whether the package can be loaded with stated dependencies ... OK
* checking whether the package can be unloaded cleanly ... OK
* checking whether the namespace can be loaded with stated dependencies ... OK
* checking whether the namespace can be unloaded cleanly ... OK
* checking loading without being on the library search path ... OK
* checking for unstated dependencies in R code ... OK
* checking S3 generic/method consistency ... OK
* checking replacement functions ... OK
* checking foreign function calls ... OK
* checking R code for possible problems ... OK
* checking Rd files ... OK
* checking Rd metadata ... OK
* checking Rd cross-references ... OK
* checking for missing documentation entries ... OK
* checking for code/documentation mismatches ... OK
* checking Rd \usage sections ... OK
* checking Rd contents ... OK
* checking for unstated dependencies in examples ... OK
* checking examples ... OK
* checking PDF version of manual ... WARNING
LaTeX errors when creating PDF version.
This typically indicates Rd problems.
* checking PDF version of manual without hyperrefs or index ... OK

WARNING: There was 1 warning.
See
  ‘/home/conan/R/demo/sayHello.Rcheck/00check.log’
for details.

发现有一个警告,checking PDF version of manual ... WARNING。是latex生成pdf错误。

查检警告的debug日志


~ R CMD Rd2pdf sayHello_1.0.tar.gz
Converting Rd files to LaTeX ...
  sayHello_1.0.tar.gz
Warning in readLines(f) :
  incomplete final line found on 'sayHello_1.0.tar.gz'
Warning in parse_Rd("sayHello_1.0.tar.gz", encoding = "unknown", fragment = FALSE,  :
  sayHello_1.0.tar.gz:16: unexpected '}'
Warning: sayHello_1.0.tar.gz:1: All text must be in a section
Warning: sayHello_1.0.tar.gz:2: All text must be in a section
Warning: sayHello_1.0.tar.gz:3: All text must be in a section
Warning: sayHello_1.0.tar.gz:4: All text must be in a section
Warning: sayHello_1.0.tar.gz:5: All text must be in a section
Warning: sayHello_1.0.tar.gz:6: All text must be in a section
Warning: sayHello_1.0.tar.gz:7: All text must be in a section
Warning: sayHello_1.0.tar.gz:8: All text must be in a section
Warning: sayHello_1.0.tar.gz:9: All text must be in a section
Warning: sayHello_1.0.tar.gz:10: All text must be in a section
Warning: sayHello_1.0.tar.gz:11: All text must be in a section
Warning: sayHello_1.0.tar.gz:12: All text must be in a section
Warning: sayHello_1.0.tar.gz:15: All text must be in a section
Error : sayHello_1.0.tar.gz: Sections \title, and \name must exist and be unique in Rd files

求助:
Error : sayHello_1.0.tar.gz: Sections \title, and \name must exist and be unique in Rd files
这个问题我检查了好多次始终没有解决。请求帮助!!

问题解决:安装完整包

sudo apt-get install texlive-full

上传R包
当解决了上面的WARN就可以上传了。。。(待续)

卸载R包


remove.packages("sayHello")
Removing package from ‘/home/conan/R/x86_64-pc-linux-gnu-library/3.0’

~ ls /home/conan/R/x86_64-pc-linux-gnu-library/3.0
bitops  digest  manipulate  rstudio  XML

3. RStudio中制作R包

RStudio Server的安装及配置,请参考:多人在线协作R开发RStudio Server

RStudio已经为我们准备了一个有界面的环境,方便我们制作R包。

  1. 创建一个工程sayHello
  2. 编辑DESCRIPTION
  3. 创建sayHello.R的脚本
  4. 编辑sayHello.Rd的文档

1). 创建一个工程sayHello
project1

project2

2). 编辑rstudio/sayHello/DESCRIPTION

Package: sayHello
Type: Package
Title: R package demo for sayHell
LazyLoad: yes
Author: Dan Zhang
Maintainer: Dan Zhang
Description: This package provides a package demo
License: GPL
Version: 1.0
Date: 2013-07-31
Depends: R (>= 3.0.1)

3). 编辑rstudio/sayHello/R/sayHello.R的脚本

sayHello<-function(name){
  print(paste("Hi",name))
}

4). 编辑rstudio/sayHello/man/sayHello.Rd的文档

\name{sayHello}
\alias{sayHello}
\title{a sayHello function demo}
\description{
a sayHello function demo
}
\usage{
sayHello(name)
}
\arguments{
  \item{name}{a word}
}
\details{
nothing
}
\value{
no return
}
\references{
nothing
}
\author{
Dan Zhang
}
\note{
nothing
}
\seealso{
nothing
}
\examples{
sayHello("world")
}
\keyword{ sayHello }

5). 执行build和reload
project3

project4

6). 执行check
project5

在RStudio中可以更方便的进行R的开包,打包,检查等的过程。RStudio就是R的神器!

虽然还没有发布自己的R包,不过很快了!!有此想法已经多时了!!每一天加油!

转载请注明出处:
http://blog.fens.me/r-build-package/

打赏作者