Good good study, day day up

aleung的学习笔记, aleung的idea

去年底跑完广州马拉松半程后,一直都没有怎么认真跑步,经常一停就几个星期。转眼间到了7月中,算一下离今年广州马拉松不够四个月了,是时候开始训练。用miCoach做训练计划,选择了全程马拉松,居然第一次训练就是要2小时long run,太狠了。想着之前已经隔天跑,跑了一个半星期,身体应该能承受,那就按计划来吧。

半小时左右,跑到二沙岛过广州大桥,开始有累感。然后是各种累各种想停下的感觉,但好歹步速还在五分多六分多左右。

经过广州塔,江堤上很多游人,景色不错。五十多分钟时过猎德桥,过完桥就开始回程了。
猎德大桥上竟然铺了橡胶,但太软了跑起来反而不好用力。

下桥后停下来吃了根蕉,这一停不得了,再也跑不动了,真是宁可慢不可停。跑了几百米,虽然很慢,但都还是恢复不了跑步状态,大腿小腿都动不起来。才刚回程这样的状态不是办法,只好再停下来做了一轮腿部拉伸。拉伸完之后跑步的状态恢复了,虽然腿还是累。

然后水袋饮水软管和耳机线又在胸前晃来晃去,每跑一步就拍一下身体,很不舒服。前半程卡在背包带上好好的,后面就总卡不稳了,可能是累了后身体晃动厉害了。又得停下来倒弄一番,还不小心把软件弄停了,后面都没有了记录。

阅读全文 »

周末早餐时读上一段,前后一年时间,终于把这本《与艺术相伴》读完了。

艺术家的作品源于一生的经历、思考和情感;其余任何人都无法精确地复制它们。艺术品拥有多重含义。如果一些艺术品对某个人来说有某种意义,而他自己的经历、思考和情感也在其中找到了合适的位置,那么就可以说他赋予了艺术品生命。

艺术家的任务是实践自己的艺术观,表达自己的观点、见解和感情,以及在内心需要的命令下进行创作。

美脫離功能而存在。欣賞美時無功利性的成分在內。

自然主義:具象,再次呈現可見世界,可被感官感知的外在物質現實;

抽象:被想像力感知的內在精神現實

位于自然主义和抽象之间的是程式化。“程式化”(stslized)形容的是这样一种具象艺术:它遵照某种早已确定的风格或套路来描绘世界。

阅读全文 »

两个小时,演讲太啰嗦,时间压缩一半可能会精炼很多,乔布斯有这么多废话吗?另外就是老罗一贯的自恋。我突然想找小米首次发布会来看看,看雷布斯的表现如何。老罗已经是名嘴,雷布斯更惨不忍睹?

从发布会的信息上看,锤子是一个做了UI / HI (Human Interface) 优化的Android系统:

  1. 更换了System UI(风格基调是iOS的)
  2. 提供以九宫格无背景为特色的Launcher(Android UI优点之一的widget无处容身了)
  3. 替换了所有应用自带的图标
  4. 提供了一些重新设计的系统自带应用,如相机、通讯录、拨号等(里面加入不少体贴用户的细节)
  5. 语音控制功能的整合(还没做好)

这样看来,锤子做的事情跟很多基于Android的定制系统是一个层面的,类似的系统太多太多了:最早但死掉的中国移动OMS,各手机厂商为自己手机定制的系统(HTC SenseUI,联想乐OS,魅族Flyme),已经放弃的点心OS,很火的MIUI……。顺便说一下,MIUI为应用图标硬加的圆角矩形背景极为难看,希望被老罗炮轰一下后能改过来。

从整体设计风格来说,锤子追随的是iOS的UI风格和人机界面设计规范,从各个UI组件的样子可以看得出来,还有交互操作的方式,也包括拟物化的设计、仿真的视觉反馈等。

阅读全文 »

在豆瓣小组里,有人问笔记本充满电后,是否应该拔掉电源用电池。我的回答是“否”,在有电源时应该插着电源,以延长电池寿命。我的回答遭到了某些疑似文科生的质疑(抱歉我对文科生的不敬)。现在很多中文网站、论坛的东西都是东抄西抄,以讹传讹。为此我科普了一把。


看看Apple的网站吧:

A charge cycle means using all of the battery’s power, but that doesn’t necessarily mean a single charge. For instance, you could listen to your iPod for a few hours one day, using half its power, and then recharge it fully. If you did the same thing the next day, it would count as one charge cycle, not two, so you may take several days to complete a cycle.

阅读全文 »

Recently I changed an Artifactory repository configuration from storing non-unique snapshots to unique snapshots (as described here). After that, “Unable to download the artifact” error happened on some artifacts.

When both unique snapshot and non-unique snapshot of the same version of an artifact exists, there will be problem to download it. For example, in a repository if under folder /com/mycompany/test/foo/1.0.0-SNAPSHOT/ there are foo-1.0.0-SNAPSHOT.pom and foo-1.0.0-20130329-231102-1.pom, then downloading com.mycompany.test:foo:1.0.0-SNAPSHOT:pom will get error. You have to delete either the file with SNAPSHOT in name or all the files with time stamp in name.

Before I changed the configuration, there were SNAPSHOT artifacts in the repository. After configuration changed, the continuous integration jobs running on CI server redeployed artifacts to the repository, and those new files have time stamp in file names, and the version is the same. That caused the problem.

To solve the problem, I should delete the *-SNAPSHOT file, if and only if there are both unique snapshot and non-unique snapshot of the same version.

I wrote a Ruby script to do that. It scans all recent deployed artifacts (they have time stamp in file name because of the new configuration) and try to delete the same version non-unique snapshot (-SNAPSHOT) file if any. It uses Artifactory’s REST API. This script need to be run periodically till all artifacts have been rebuilt and deployed to repository.

阅读全文 »

Artifactory has no feature to automatically remove old artifacts from local repository. Once the disk is full, manually remove unused artifacts is painful. Moveover, you’re not sure which artifacts are unused and can be safely deleted.

Artifactory has a set of REST API. One of the API is to search artifacts not downloaded since a specified date. In our projects, there are CI jobs which keep building the software for each branch. If a SNAPSHOT artifact hasn’t been downloaded for a time, we can make sure that this artifact is no use any more, a newer version should be existing.

I made a Ruby script to do the clean up job automatically. It searches artifacts which weren’t downloaded in specific days and deletes them. It can be invoked in a CI job to run periodically.

#!/bin/env ruby
# --- Configuration ---------------------------------
# Remove artifacts which were created before $age_days ago and haven't been downloaded in recent $age_days.
$age_days = 730
# The repository to be cleaned.
$repo = 'repository-key'
$user = 'user'
$password = 'password'
$host = 'mavenrepo.mycompany.com'
$artifactory_root_path = '/repo'
# --- Configuration end ------------------------------
require 'rubygems'
require 'net/http'
require 'json'
def handle_usused_result(result)
JSON.parse(result)["results"].each { |artifact|
delete_artifact(artifact["uri"])
}
end
def delete_artifact(artifact_uri)
puts "Delete artifact #{artifact_uri}"
%r|.*/#{$repo}/(.*)/.*| =~ artifact_uri
url = "#{$artifactory_root_path}/#{$repo}/#{$1}"
http = Net::HTTP.new($host)
request = Net::HTTP::Delete.new(url)
request.basic_auth($user, $password)
response = http.request(request)
puts "#{response.code} #{response.body}\n"
end
def retrieve_unused_artifacts()
since = (Time.now - $age_days * 3600*24).to_i * 1000
url = "#{$artifactory_root_path}/api/search/usage?notUsedSince=#{since}&createdBefore=#{since}&repos=#{$repo}"
puts url
http = Net::HTTP.new($host)
http.read_timeout = 500
request = Net::HTTP::Get.new(url)
request.basic_auth($user, $password)
response = http.request(request)
if response.code != "200"
puts "#{response.code} #{response.body}"
exit!
end
save_file(response.body)
return response.body
end
def save_file(result)
File.open('unused_artifactorys.txt', 'w') { |f| f.puts(result) }
end
def load_file()
File.open('unused_artifactorys.txt') { |f| f.gets }
end
handle_usused_result(retrieve_unused_artifacts())
# handle_usused_result(load_file())

The script can also be used to clean unused release (non-SNAPSHOT) artifacts. However a good practice is to keep releases forever.

阅读全文 »

I need to migrate a Maven repository from Artifactory to Nexus. Nexus’s migration solution uses its migration plugin. But our Nexus service is managed by IT team and I don’t want to bother to ask them to install a plugin.

Artifactory is able to export a whole repository into file system as local repository layout (like .m2/repository folder). So I looked for import feature in Nexus, but failed.

Searched on Google then I found this answer on StackOverflow. Sean provided a pom with embedded Groovy script to upload (deploy) a hierarchy of files to a Maven repository. However Sean’s solution handles groupId, artifactId and version in a way differ to what I want. It requires to specify groupId and version in pom as fixed value.

I modify the Groovy script a bit to handle local repository folder layout. GroupId, artifactId and version are parsed from path of file. Here is my modified version:

Note: This file was created in 2003. It might not work on current version of Maven.

A pom.xml to batch deploy artifacts which are put under local repository folder structure to a repository.

If you upload your local repository, make sure you have removed the non-artifact files like *.sha1, *.lastUpdated. Modify the setting in <deploy.basefolder> and <distributionManagement> before use.

Run mvn install to deploy.

This file is created base on StackOverflow answer: http://stackoverflow.com/a/3304212/94148Referenced by http://aleung.github.io/blog/2013/03/19/maven-batch-deploy-artifacts/

view raw readme.md hosted with ❤ by GitHub
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany</groupId>
<artifactId>localrepodeployer</artifactId>
<packaging>jar</packaging>
<version>1.0.0</version>
<properties>
<!-- This is where your artifacts are -->
<deploy.basefolder>./repository</deploy.basefolder>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>deploy-files</id>
<phase>prepare-package</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
<![CDATA[
// read components from plexus container
def layout = session.lookup(
'org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout');
def repoFactory = session.lookup(
'org.apache.maven.artifact.repository.ArtifactRepositoryFactory');
def repository = repoFactory.createDeploymentArtifactRepository(
pom.distributionManagement.repository.id,
pom.distributionManagement.repository.url,
layout, true );
def localRepository = session.localRepository;
def helper =
session.lookup("org.apache.maven.project.MavenProjectHelper");
def afm = session.lookup(
'org.apache.maven.artifact.handler.manager.ArtifactHandlerManager');
def factory = new org.apache.maven.artifact.factory.DefaultArtifactFactory();
factory.class.getDeclaredField("artifactHandlerManager").accessible = true;
factory.artifactHandlerManager=afm;
def deployer = session.lookup(
'org.apache.maven.artifact.deployer.ArtifactDeployer');
// initialize properties
def baseFolder = new File(pom.properties['deploy.basefolder']);
// iterate over all files recursively
baseFolder.eachFileRecurse{
if(it.isDirectory())return;
System.out.println "Deploying " + it.absolutePath
// packaging = file.extension
def packaging = it.name.replaceAll( /.+\./ , '' );
def relativePath = it.absolutePath.replace(baseFolder.absolutePath, '')
def matcher = (relativePath =~ /\/?(.*)\/(.+)\/(.+)\/(.*)/)
if (!matcher) return;
def groupId = matcher[0][1].replace('/', '.');
def artifactId = matcher[0][2]
def version = matcher[0][3]
def fileName = matcher[0][4]
def fileNameMatcher = (fileName =~ /($artifactId)-($version)-?(.*)\./)
def classifier = fileNameMatcher[0][3]
if (classifier.equals(""))
artifact = factory.createBuildArtifact(groupId, artifactId, version, packaging );
else
artifact = factory.createArtifactWithClassifier(groupId, artifactId, version, packaging, classifier);
def pomFilePath = baseFolder.absolutePath + '/' + matcher[0][1] + '/' + artifactId + '/' + version + '/' + artifactId + '-' + version + '.pom'
System.out.println "POM: " + pomFilePath
File pomFile = new File(pomFilePath)
def metadata =
new org.apache.maven.project.artifact.ProjectArtifactMetadata(artifact, pomFile );
artifact.addMetadata( metadata );
// deploy file
deployer.deploy(it, artifact, repository, localRepository );
}
]]>
</source>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<!-- Modify below to point to your repository -->
<distributionManagement>
<repository>
<id>my-repo</id>
<url>http://myhost.com/nexus/content/repositories/my-repo</url>
<layout>default</layout>
</repository>
</distributionManagement>
</project>
view raw pom.xml hosted with ❤ by GitHub

Before using it, modify the setting in <deploy.basefolder> and <distributionManagement>. Make sure you have removed all non-artifact files e.g. *.sha1, *.lastUpdated from your import directory. Or you may enhance the script to filter those files out.

阅读全文 »

坐姿,特别是不正确的坐姿,对腰椎间盘的压力是站姿的2到3倍,长期在电脑前工作的人很容易得腰椎间盘突出等腰椎疾病。因此现在IT工作者逐渐流行站立工作。但是,长期站立也会带来其他的问题,如下肢静脉曲张等。一个比较理想的方案是使用可升降的办公桌,坐姿站姿交替。

2011年我花了不少时间寻找国内哪里可以买到可升降办公桌,但都没有找到。网上搜索倒是有不少信息,但都是厂家寻求批发订货的,电话问过几个本地厂商,基本都说不做,做的也没有现货不零售。唯一的是淘宝上有个泠泠岛,做个人客户,当时价格很高,外地购买也不方便,而且我对它的质量不是很放心。最终放弃了购买升降桌的念头,改为自行DIY站立工作桌。

2012年初用IKEA的BRODER系统加一个VIKA桌面搭建了一个站立工作桌。BRODER归属在重型储物系列里,本来用途是储物架,钢柱杆和钢网搁板很牢固,最大的搁板深度基本足够做桌面了,在上面垫上一块木桌面刚刚好。用IKEA的东西好处是你有很大发挥的空间,这个IKEA的居家生活部落格里就有不少BRODER各种应用的照片。但刚刚查IKEA中国网站,已经找不到BRODER,不知是否不卖了。

就这样用了一年,但长期站立工作也不好,于是想配一张高脚凳也许就差不多了。桌面高度是按站立工作而定的,按照我的身高桌面高度也偏高,一般市面上卖的高脚凳(酒吧凳)座高都不够。最后在淘宝上找到了一款,高度比较合适。今天到货刚刚装起来了。其实这凳子做工、质量都不算很好,组装也不够方便,如果IKEA有合适的我绝对不会选择它的(虽然说IKEA的东西质量也只算一般,但还是要比这淘宝货强)。

阅读全文 »

Android用户常常会被耗电问题困扰,明明手机没怎么使用,电量却不停的掉,半天就耗光了。有些人会寻求kill应用的方法——而Android系统的设计原则是用户不需要关心进程的启停的。其实大多数情况下,这都跟系统无关,而是安装的某些应用的问题。合理设计的应用,即使有后台进程,也只会在必要的时候唤醒进行短时间工作。但有些应用开发者不懂怎么合理设计应用后台任务,造成耗电问题。

要解决耗电问题,首先得找出是那个应用耗电。Android 4.0以上系统已经能够显示出系统各模块以及各个应用的耗电比例(设置-电量使用情况),不过细节信息还是不够多,往往不足以判定是什么原因耗电严重,这时候就要用到这个应用:GSam Battery Monitor。就像Android系统的电量使用情况,GSam可以列出系统各模块(系统、电话、屏幕、Wifi等)以及各应用的耗电比例,但它可以看到每项更细节的信息,如某一应用使用各传感器的时间、屏幕不同亮度分布使用时间等等,可以帮助判断是什么模块/应用耗电严重,以及耗电的具体原因。GSam还有更多的功能,用起来也不太复杂,自己摸索一下就行。

找到罪魁祸首后,最简单处理手段就是卸载它。但如果这个应用非装不可没有替代品,怎么办?Kill不是办法,若应用因后台服务而耗电,后台服务kill掉也能自动重启的。每次用完都要去kill用起来也不方便。这时 Greenify 就派上用场了,当你将一个应用加入greenify列表中,它能够在你不使用这个应用时将它进入冬眠状态,但又不影响其正常使用。除了用来对付耗电应用,对付耗内存应用也不错,当应用冬眠时,也不会占用内存(RAM)。至于它的工作原理,作者没有透露过,我还没有见到有解释。Greenify只能用于Android 3.1+,需要root。Android手机要玩好,root基本上是不可少的。

阅读全文 »

包管理

从CRAN安装一个包:install.packages("pkg_name")

加载包:library(package)

R的基本数据类型

在R里面一个元素的基本数据类型称为 mode。每个对象都有mode属性。

阅读全文 »